4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * GROwing Monsters And Cloning Shrimps
52 * This file implements temperature and pressure coupling algorithms:
53 * For now only the Weak coupling and the modified weak coupling.
55 * Furthermore computation of pressure and temperature is done here
59 void calc_pres(int ePBC
,matrix box
,tensor ekin
,tensor vir
,tensor pres
,real Elr
)
67 /* Uitzoeken welke ekin hier van toepassing is, zie Evans & Morris - E.
68 * Wrs. moet de druktensor gecorrigeerd worden voor de netto stroom in
72 /* Long range correction for periodic systems, see
74 * divide by 6 because it is multiplied by fac later on.
75 * If Elr = 0, no correction is made.
78 /* This formula should not be used with Ewald or PME,
79 * where the full long-range virial is calculated. EL 990823
83 fac
=PRESFAC
*2.0/det(box
);
84 for(n
=0; (n
<DIM
); n
++)
85 for(m
=0; (m
<DIM
); m
++)
86 pres
[n
][m
]=(ekin
[n
][m
]-vir
[n
][m
]+Plr
)*fac
;
89 pr_rvecs(debug
,0,"PC: pres",pres
,DIM
);
90 pr_rvecs(debug
,0,"PC: ekin",ekin
,DIM
);
91 pr_rvecs(debug
,0,"PC: vir ",vir
, DIM
);
92 pr_rvecs(debug
,0,"PC: box ",box
, DIM
);
97 real
calc_temp(real ekin
,real nrdf
)
100 return (2.0*ekin
)/(nrdf
*BOLTZ
);
105 void parrinellorahman_pcoupl(t_inputrec
*ir
,int step
,tensor pres
,
106 tensor box
,tensor boxv
,tensor M
,
109 /* This doesn't do any coordinate updating. It just
110 * integrates the box vector equations from the calculated
111 * acceleration due to pressure difference. We also compute
112 * the tensor M which is used in update to couple the particle
113 * coordinates to the box vectors.
115 * In Nose and Klein (Mol.Phys 50 (1983) no 5., p 1055) this is
118 * M_nk = (h') * (h' * h + h' h) * h
120 * with the dots denoting time derivatives and h is the transformation from
121 * the scaled frame to the real frame, i.e. the TRANSPOSE of the box.
122 * This also goes for the pressure and M tensors - they are transposed relative
123 * to ours. Our equation thus becomes:
126 * M_gmx = M_nk' = b * (b * b' + b * b') * b'
128 * where b is the gromacs box matrix.
129 * Our box accelerations are given by
131 * b = vol/W inv(box') * (P-ref_P) (=h')
136 real vol
=box
[XX
][XX
]*box
[YY
][YY
]*box
[ZZ
][ZZ
];
137 real fac
=vol
/PRESFAC
;
138 real atot
,arel
,change
,maxchange
,xy_pressure
;
139 tensor invbox
,pdiff
,t1
,t2
;
146 maxl
=max(box
[XX
][XX
],box
[YY
][YY
]);
147 maxl
=max(maxl
,box
[ZZ
][ZZ
]);
151 (4*M_PI
*M_PI
*ir
->compress
[d
][n
])/(3*ir
->tau_p
*ir
->tau_p
*maxl
);
153 m_sub(pres
,ir
->ref_p
,pdiff
);
155 if(ir
->epct
==epctSURFACETENSION
) {
156 /* Unlike Berendsen coupling it might not be trivial to include a z
157 * pressure correction here? On the other hand we don't scale the
158 * box momentarily, but change accelerations, so it might not be crucial.
160 xy_pressure
=0.5*(pres
[XX
][XX
]+pres
[YY
][YY
]);
162 pdiff
[d
][d
]=(xy_pressure
-(pres
[ZZ
][ZZ
]-ir
->ref_p
[d
][d
]/box
[d
][d
]));
165 tmmul(invbox
,pdiff
,t1
);
168 case epctANISOTROPIC
:
171 t1
[d
][n
]*=winv
[d
][n
]*fac
;
174 /* calculate total volume acceleration */
175 atot
=box
[XX
][XX
]*box
[YY
][YY
]*t1
[ZZ
][ZZ
]+
176 box
[XX
][XX
]*t1
[YY
][YY
]*box
[ZZ
][ZZ
]+
177 t1
[XX
][XX
]*box
[YY
][YY
]*box
[ZZ
][ZZ
];
179 /* set all RELATIVE box accelerations equal, and maintain total V
183 t1
[d
][n
]=winv
[0][0]*fac
*arel
*box
[d
][n
];
185 case epctSEMIISOTROPIC
:
186 case epctSURFACETENSION
:
187 /* Note the correction to pdiff above for surftens. coupling */
189 /* calculate total XY volume acceleration */
190 atot
=box
[XX
][XX
]*t1
[YY
][YY
]+t1
[XX
][XX
]*box
[YY
][YY
];
191 arel
=atot
/(2*box
[XX
][XX
]*box
[YY
][YY
]);
192 /* set RELATIVE XY box accelerations equal, and maintain total V
193 * change speed. Dont change the third box vector accelerations */
196 t1
[d
][n
]=winv
[d
][n
]*fac
*arel
*box
[d
][n
];
198 t1
[ZZ
][n
]*=winv
[d
][n
]*fac
;
201 fatal_error(0,"Parrinello-Rahman pressure coupling type %s "
202 "not supported yet\n",EPCOUPLTYPETYPE(ir
->epct
));
209 boxv
[d
][n
] += ir
->delta_t
*t1
[d
][n
];
210 /* We do NOT update the box vectors themselves here, since
211 * we need them for shifting later. It is instead done last
212 * in the update() routine.
215 /* Calculate the change relative to diagonal elements -
216 * since it's perfectly ok for the off-diagonal ones to
217 * be zero it doesn't make sense to check the change relative
218 * to its current size.
220 change
=fabs(ir
->delta_t
*boxv
[d
][n
]/box
[d
][d
]);
226 fprintf(stdlog
,"\nStep %d Warning: Pressure scaling more than 1%%.\n",
230 mtmul(boxv
,box
,t1
); /* t1=boxv * b' */
233 t1
[d
][n
] += t1
[n
][d
]; /* t1=t1+t1' */
238 void berendsen_pcoupl(t_inputrec
*ir
,int step
,tensor pres
,matrix box
,
242 real scalar_pressure
, xy_pressure
, p_corr_z
;
243 char *ptr
,buf
[STRLEN
];
246 * Calculate the scaling matrix mu
250 for(d
=0; d
<DIM
; d
++) {
251 scalar_pressure
+= pres
[d
][d
]/DIM
;
253 xy_pressure
+= pres
[d
][d
]/(DIM
-1);
255 /* Pressure is now in bar, everywhere. */
256 #define factor(d,m) (ir->compress[d][m]*ir->delta_t/ir->tau_p)
258 /* mu has been changed from pow(1+...,1/3) to 1+.../3, since this is
259 * necessary for triclinic scaling
265 mu
[d
][d
] = 1.0 - factor(d
,d
)*(ir
->ref_p
[d
][d
] - scalar_pressure
)/DIM
;
267 case epctSEMIISOTROPIC
:
269 mu
[d
][d
] = 1.0 - factor(d
,d
)*(ir
->ref_p
[d
][d
]-xy_pressure
)/DIM
;
271 1.0 - factor(ZZ
,ZZ
)*(ir
->ref_p
[ZZ
][ZZ
] - pres
[ZZ
][ZZ
])/DIM
;
273 case epctANISOTROPIC
:
276 mu
[d
][n
] = (d
==n
? 1.0 : 0.0)
277 -factor(d
,n
)*(ir
->ref_p
[d
][n
] - pres
[d
][n
])/DIM
;
279 case epctSURFACETENSION
:
280 /* ir->ref_p[0/1] is the reference surface-tension times *
281 * the number of surfaces */
282 if (ir
->compress
[ZZ
][ZZ
])
283 p_corr_z
= ir
->delta_t
/ir
->tau_p
*(ir
->ref_p
[ZZ
][ZZ
] - pres
[ZZ
][ZZ
]);
285 /* when the compressibity is zero, set the pressure correction *
286 * in the z-direction to zero to get the correct surface tension */
288 mu
[ZZ
][ZZ
] = 1.0 - ir
->compress
[ZZ
][ZZ
]*p_corr_z
;
289 for(d
=0; d
<DIM
-1; d
++)
290 mu
[d
][d
] = 1.0 + factor(d
,d
)*(ir
->ref_p
[d
][d
]/(mu
[ZZ
][ZZ
]*box
[ZZ
][ZZ
])
291 - (pres
[ZZ
][ZZ
]+p_corr_z
- xy_pressure
))/(DIM
-1);
294 fatal_error(0,"Berendsen pressure coupling type %s not supported yet\n",
295 EPCOUPLTYPETYPE(ir
->epct
));
298 /* To fullfill the orientation restrictions on triclinic boxes
299 * we will set mu_yx, mu_zx and mu_zy to 0 and correct
300 * the other elements of mu to first order.
302 mu
[YY
][XX
] += mu
[XX
][YY
];
303 mu
[ZZ
][XX
] += mu
[XX
][ZZ
];
304 mu
[ZZ
][YY
] += mu
[YY
][ZZ
];
310 pr_rvecs(debug
,0,"PC: pres ",pres
,3);
311 pr_rvecs(debug
,0,"PC: mu ",mu
,3);
314 if (mu
[XX
][XX
]<0.99 || mu
[XX
][XX
]>1.01 ||
315 mu
[YY
][YY
]<0.99 || mu
[YY
][YY
]>1.01 ||
316 mu
[ZZ
][ZZ
]<0.99 || mu
[ZZ
][ZZ
]>1.01) {
317 sprintf(buf
,"\nStep %d Warning: pressure scaling more than 1%%, "
318 "mu: %g %g %g\n",step
,mu
[XX
][XX
],mu
[YY
][YY
],mu
[ZZ
][ZZ
]);
319 fprintf(stdlog
,"%s",buf
);
320 fprintf(stderr
,"%s",buf
);
324 void berendsen_pscale(matrix mu
,
325 matrix box
,int start
,int nr_atoms
,
326 rvec x
[],unsigned short cFREEZE
[],
327 t_nrnb
*nrnb
,ivec nFreeze
[])
331 /* Scale the positions */
332 for (n
=start
; n
<start
+nr_atoms
; n
++) {
336 x
[n
][XX
] = mu
[XX
][XX
]*x
[n
][XX
]+mu
[YY
][XX
]*x
[n
][YY
]+mu
[ZZ
][XX
]*x
[n
][ZZ
];
338 x
[n
][YY
] = mu
[YY
][YY
]*x
[n
][YY
]+mu
[ZZ
][YY
]*x
[n
][ZZ
];
340 x
[n
][ZZ
] = mu
[ZZ
][ZZ
]*x
[n
][ZZ
];
342 /* compute final boxlengths */
343 for (d
=0; d
<DIM
; d
++) {
344 box
[d
][XX
] = mu
[XX
][XX
]*box
[d
][XX
]+mu
[YY
][XX
]*box
[d
][YY
]+mu
[ZZ
][XX
]*box
[d
][ZZ
];
345 box
[d
][YY
] = mu
[YY
][YY
]*box
[d
][YY
]+mu
[ZZ
][YY
]*box
[d
][ZZ
];
346 box
[d
][ZZ
] = mu
[ZZ
][ZZ
]*box
[d
][ZZ
];
349 /* (un)shifting should NOT be done after this,
350 * since the box vectors might have changed
352 inc_nrnb(nrnb
,eNR_PCOUPL
,nr_atoms
);
355 void berendsen_tcoupl(t_grpopts
*opts
,t_groups
*grps
,real dt
,real lambda
[])
361 for(i
=0; (i
<opts
->ngtc
); i
++) {
362 T
= grps
->tcstat
[i
].T
;
364 if ((opts
->tau_t
[i
] > 0) && (T
> 0.0)) {
366 reft
= max(0.0,opts
->ref_t
[i
]);
367 lll
= sqrt(1.0 + (dt
/opts
->tau_t
[i
])*(reft
/T
-1.0));
368 lambda
[i
] = max(min(lll
,1.25),0.8);
374 fprintf(debug
,"TC: group %d: T: %g, Lambda: %g\n",
379 void nosehoover_tcoupl(t_grpopts
*opts
,t_groups
*grps
,real dt
,real xi
[])
383 real reft
=0,xit
,oldxi
;
385 for(i
=0; (i
<opts
->ngtc
); i
++) {
386 if ((opts
->tau_t
[i
] > 0) && (opts
->ref_t
[i
] > 0))
387 Qinv
=1.0/(opts
->tau_t
[i
]*opts
->tau_t
[i
]*opts
->ref_t
[i
]/(4*M_PI
*M_PI
));
390 reft
= max(0.0,opts
->ref_t
[i
]);
391 xi
[i
] += dt
*Qinv
*(grps
->tcstat
[i
].T
-reft
);
395 /* set target temperatures if we are annealing */
396 void update_annealing_target_temp(t_grpopts
*opts
,real t
)
401 for(i
=0;i
<opts
->ngtc
;i
++) {
402 npoints
= opts
->anneal_npoints
[i
];
403 switch (opts
->annealing
[i
]) {
407 /* calculate time modulo the period */
408 pert
= opts
->anneal_time
[i
][npoints
-1];
410 thist
= t
- n
*pert
; /* modulo time */
411 /* Make sure rounding didn't get us outside the interval */
412 if (fabs(thist
-pert
) < GMX_REAL_EPS
*100)
419 fatal_error(0,"Death horror in update_annealing_target_temp (i=%d/%d npoints=%d)",i
,opts
->ngtc
,npoints
);
421 /* We are doing annealing for this group if we got here,
422 * and we have the (relative) time as thist.
423 * calculate target temp */
425 while ((j
< npoints
-1) && (thist
>(opts
->anneal_time
[i
][j
+1])))
428 /* Found our position between points j and j+1.
429 * Interpolate: x is the amount from j+1, (1-x) from point j
430 * First treat possible jumps in temperature as a special case.
432 if ((opts
->anneal_time
[i
][j
+1]-opts
->anneal_time
[i
][j
]) < GMX_REAL_EPS
*100)
433 opts
->ref_t
[i
]=opts
->anneal_temp
[i
][j
+1];
435 x
= ((thist
-opts
->anneal_time
[i
][j
])/
436 (opts
->anneal_time
[i
][j
+1]-opts
->anneal_time
[i
][j
]));
437 opts
->ref_t
[i
] = x
*opts
->anneal_temp
[i
][j
+1]+(1-x
)*opts
->anneal_temp
[i
][j
];
441 opts
->ref_t
[i
] = opts
->anneal_temp
[i
][npoints
-1];