4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_coupling_c
= "$Id$";
43 * This file implements temperature and pressure coupling algorithms:
44 * For now only the Weak coupling and the modified weak coupling.
46 * Furthermore computation of pressure and temperature is done here
50 void calc_pres(int eBox
,matrix box
,tensor ekin
,tensor vir
,tensor pres
,real Elr
)
58 /* Uitzoeken welke ekin hier van toepassing is, zie Evans & Morris - E.
59 * Wrs. moet de druktensor gecorrigeerd worden voor de netto stroom in
63 /* Long range correction for periodic systems, see
65 * divide by 6 because it is multiplied by fac later on.
66 * If Elr = 0, no correction is made.
69 /* This formula should not be used with Ewald or PME,
70 * where the full long-range virial is calculated. EL 990823
74 fac
=PRESFAC
*2.0/det(box
);
75 for(n
=0; (n
<DIM
); n
++)
76 for(m
=0; (m
<DIM
); m
++)
77 pres
[n
][m
]=(ekin
[n
][m
]-vir
[n
][m
]+Plr
)*fac
;
80 pr_rvecs(debug
,0,"PC: pres",pres
,DIM
);
81 pr_rvecs(debug
,0,"PC: ekin",ekin
,DIM
);
82 pr_rvecs(debug
,0,"PC: vir ",vir
, DIM
);
83 pr_rvecs(debug
,0,"PC: box ",box
, DIM
);
88 real
calc_temp(real ekin
,int nrdf
)
90 return (2.0*ekin
)/(nrdf
*BOLTZ
);
93 real
run_aver(real old
,real cur
,int step
,int nmem
)
97 return ((nmem
-1)*old
+cur
)/nmem
;
101 void do_pcoupl(t_inputrec
*ir
,int step
,tensor pres
,
102 matrix box
,int start
,int nr_atoms
,
103 rvec x
[],unsigned short cFREEZE
[],
104 t_nrnb
*nrnb
,ivec nFreeze
[])
106 static bool bFirst
=TRUE
;
108 int n
,d
,m
,g
,ncoupl
=0;
109 real scalar_pressure
, xy_pressure
, p_corr_z
;
113 real muxx
,muxy
,muxz
,muyx
,muyy
,muyz
,muzx
,muzy
,muzz
;
121 /* Initiate the pressure to the reference one */
123 PPP
[m
] = ir
->ref_p
[m
];
128 for(m
=0; m
<DIM
; m
++) {
129 PPP
[m
] = run_aver(PPP
[m
],pres
[m
][m
],step
,ir
->npcmemory
);
130 scalar_pressure
+= PPP
[m
]/DIM
;
132 xy_pressure
+= PPP
[m
]/(DIM
-1);
135 /* Pressure is now in bar, everywhere. */
136 if ((ir
->epc
!= epcNO
) && (scalar_pressure
!= 0.0)) {
138 factor
[m
] = ir
->compress
[m
]*ir
->delta_t
/ir
->tau_p
;
143 mu
[m
][m
] = pow(1.0-factor
[m
]*(ir
->ref_p
[m
]-scalar_pressure
),1.0/DIM
);
145 case epcSEMIISOTROPIC
:
147 mu
[m
][m
] = pow(1.0-factor
[m
]*(ir
->ref_p
[m
]-xy_pressure
),1.0/DIM
);
148 mu
[ZZ
][ZZ
] = pow(1.0-factor
[ZZ
]*(ir
->ref_p
[ZZ
] - PPP
[ZZ
]),1.0/DIM
);
151 for (m
=0; m
<DIM
; m
++)
152 mu
[m
][m
] = pow(1.0-factor
[m
]*(ir
->ref_p
[m
] - PPP
[m
]),1.0/DIM
);
154 case epcSURFACETENSION
:
155 /* ir->ref_p[0/1] is the reference surface-tension times *
156 * the number of surfaces */
157 if (ir
->compress
[ZZ
])
158 p_corr_z
= ir
->delta_t
/ir
->tau_p
*(ir
->ref_p
[ZZ
] - PPP
[ZZ
]);
160 /* when the compressibity is zero, set the pressure correction *
161 * in the z-direction to zero to get the correct surface tension */
163 mu
[ZZ
][ZZ
] = 1.0 - ir
->compress
[ZZ
]*p_corr_z
;
165 mu
[m
][m
] = sqrt(1.0+factor
[m
]*(ir
->ref_p
[m
]/(mu
[ZZ
][ZZ
]*box
[ZZ
][ZZ
]) -
166 (PPP
[ZZ
]+p_corr_z
- xy_pressure
)));
170 fatal_error(0,"Pressure coupling type %s not supported yet\n",
171 EPCOUPLTYPE(ir
->epc
));
174 pr_rvecs(debug
,0,"PC: PPP ",&PPP
,1);
175 pr_rvecs(debug
,0,"PC: fac ",&factor
,1);
176 pr_rvecs(debug
,0,"PC: mu ",mu
,DIM
);
178 /* Scale the positions using matrix operation */
180 muxx
=mu
[XX
][XX
],muxy
=mu
[XX
][YY
],muxz
=mu
[XX
][ZZ
];
181 muyx
=mu
[YY
][XX
],muyy
=mu
[YY
][YY
],muyz
=mu
[YY
][ZZ
];
182 muzx
=mu
[ZZ
][XX
],muzy
=mu
[ZZ
][YY
],muzz
=mu
[ZZ
][ZZ
];
183 for (n
=start
; n
<nr_atoms
; n
++) {
191 x
[n
][XX
] = muxx
*X
+muxy
*Y
+muxz
*Z
;
193 x
[n
][YY
] = muyx
*X
+muyy
*Y
+muyz
*Z
;
195 x
[n
][ZZ
] = muzx
*X
+muzy
*Y
+muzz
*Z
;
199 /* compute final boxlengths */
200 for (d
=0; d
<DIM
; d
++)
201 for (m
=0; m
<DIM
; m
++)
202 box
[d
][m
] *= mu
[d
][m
];
204 inc_nrnb(nrnb
,eNR_PCOUPL
,ncoupl
);
207 void tcoupl(bool bTC
,t_grpopts
*opts
,t_groups
*grps
,
208 real dt
,real SAfactor
,int step
,int nmem
)
210 static real
*Told
=NULL
;
215 snew(Told
,opts
->ngtc
);
216 for(i
=0; (i
<opts
->ngtc
); i
++)
217 Told
[i
]=opts
->ref_t
[i
]*SAfactor
;
220 for(i
=0; (i
<opts
->ngtc
); i
++) {
221 reft
=opts
->ref_t
[i
]*SAfactor
;
225 Told
[i
] = run_aver(Told
[i
],grps
->tcstat
[i
].T
,step
,nmem
);
228 if ((bTC
) && (T
!= 0.0)) {
229 lll
=sqrt(1.0 + (dt
/opts
->tau_t
[i
])*(reft
/T
-1.0));
230 grps
->tcstat
[i
].lambda
=max(min(lll
,1.25),0.8);
233 grps
->tcstat
[i
].lambda
=1.0;
235 fprintf(stdlog
,"group %d: T: %g, Lambda: %g\n",
236 i
,T
,grps
->tcstat
[i
].lambda
);