ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPT.cpp
Revision: 780
Committed: Mon Sep 22 21:23:25 2003 UTC (20 years, 9 months ago) by mmeineke
File size: 7795 byte(s)
Log Message:
Converted NPTf to work with the NPT base class.

Removed NPTfm and NPTim from cvs

File Contents

# Content
1 #include <cmath>
2 #include "Atom.hpp"
3 #include "SRI.hpp"
4 #include "AbstractClasses.hpp"
5 #include "SimInfo.hpp"
6 #include "ForceFields.hpp"
7 #include "Thermo.hpp"
8 #include "ReadWrite.hpp"
9 #include "Integrator.hpp"
10 #include "simError.h"
11
12 #ifdef IS_MPI
13 #include "mpiSimulation.hpp"
14 #endif
15
16
17 // Basic isotropic thermostating and barostating via the Melchionna
18 // modification of the Hoover algorithm:
19 //
20 // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
21 // Molec. Phys., 78, 533.
22 //
23 // and
24 //
25 // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
26
27 template<typename T> NPT<T>::NPT ( SimInfo *theInfo, ForceFields* the_ff):
28 T( theInfo, the_ff )
29 {
30 chi = 0.0;
31 integralOfChidt = 0.0;
32 have_tau_thermostat = 0;
33 have_tau_barostat = 0;
34 have_target_temp = 0;
35 have_target_pressure = 0;
36 have_chi_tolerance = 0;
37 have_eta_tolerance = 0;
38 have_pos_iter_tolerance = 0;
39
40 oldPos = new double[3*nAtoms];
41 oldVel = new double[3*nAtoms];
42 oldJi = new double[3*nAtoms];
43 #ifdef IS_MPI
44 Nparticles = mpiSim->getTotAtoms();
45 #else
46 Nparticles = theInfo->n_atoms;
47 #endif
48
49 }
50
51 template<typename T> NPT<T>::~NPT() {
52 delete[] oldPos;
53 delete[] oldVel;
54 delete[] oldJi;
55 }
56
57 template<typename T> void NPT<T>::moveA() {
58
59 //new version of NPT
60 int i, j, k;
61 DirectionalAtom* dAtom;
62 double Tb[3], ji[3];
63 double mass;
64 double vel[3], pos[3], frc[3];
65 double sc[3];
66 double COM[3];
67
68 instaTemp = tStats->getTemperature();
69 tStats->getPressureTensor( press );
70 instaPress = p_convert * (press[0][0] + press[1][1] + press[2][2]) / 3.0;
71 instaVol = tStats->getVolume();
72
73 tStats->getCOM(COM);
74
75 //evolve velocity half step
76 for( i=0; i<nAtoms; i++ ){
77
78 atoms[i]->getVel( vel );
79 atoms[i]->getFrc( frc );
80
81 mass = atoms[i]->getMass();
82
83 getVelScaleA( sc, vel );
84
85 for (j=0; j < 3; j++) {
86
87 // velocity half step (use chi from previous step here):
88 vel[j] += dt2 * ((frc[j] / mass ) * eConvert - sc[j]);
89
90 }
91
92 atoms[i]->setVel( vel );
93
94 if( atoms[i]->isDirectional() ){
95
96 dAtom = (DirectionalAtom *)atoms[i];
97
98 // get and convert the torque to body frame
99
100 dAtom->getTrq( Tb );
101 dAtom->lab2Body( Tb );
102
103 // get the angular momentum, and propagate a half step
104
105 dAtom->getJ( ji );
106
107 for (j=0; j < 3; j++)
108 ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
109
110 this->rotationPropagation( dAtom, ji );
111
112 dAtom->setJ( ji );
113 }
114 }
115
116 // evolve chi and eta half step
117
118 evolveChiA();
119 evolveEtaA();
120
121 //calculate the integral of chidt
122 integralOfChidt += dt2*chi;
123
124 //save the old positions
125 for(i = 0; i < nAtoms; i++){
126 atoms[i]->getPos(pos);
127 for(j = 0; j < 3; j++)
128 oldPos[i*3 + j] = pos[j];
129 }
130
131 //the first estimation of r(t+dt) is equal to r(t)
132
133 for(k = 0; k < 5; k ++){
134
135 for(i =0 ; i < nAtoms; i++){
136
137 atoms[i]->getVel(vel);
138 atoms[i]->getPos(pos);
139
140 this->getPosScale( pos, COM, i, sc );
141
142 for(j = 0; j < 3; j++)
143 pos[j] = oldPos[i*3 + j] + dt*(vel[j] + sc[j]);
144
145 atoms[i]->setPos( pos );
146 }
147
148 if (nConstrained){
149 constrainA();
150 }
151 }
152
153
154 // Scale the box after all the positions have been moved:
155
156 this->scaleSimBox();
157 }
158
159 template<typename T> void NPT<T>::moveB( void ){
160
161 //new version of NPT
162 int i, j, k;
163 DirectionalAtom* dAtom;
164 double Tb[3], ji[3], sc[3];
165 double vel[3], frc[3];
166 double mass;
167
168 // Set things up for the iteration:
169
170 for( i=0; i<nAtoms; i++ ){
171
172 atoms[i]->getVel( vel );
173
174 for (j=0; j < 3; j++)
175 oldVel[3*i + j] = vel[j];
176
177 if( atoms[i]->isDirectional() ){
178
179 dAtom = (DirectionalAtom *)atoms[i];
180
181 dAtom->getJ( ji );
182
183 for (j=0; j < 3; j++)
184 oldJi[3*i + j] = ji[j];
185
186 }
187 }
188
189 // do the iteration:
190
191 instaVol = tStats->getVolume();
192
193 for (k=0; k < 4; k++) {
194
195 instaTemp = tStats->getTemperature();
196 instaPress = tStats->getPressure();
197
198 // evolve chi another half step using the temperature at t + dt/2
199
200 this->evolveChiB();
201 this->evolveEtaB();
202
203 for( i=0; i<nAtoms; i++ ){
204
205 atoms[i]->getFrc( frc );
206 atoms[i]->getVel(vel);
207
208 mass = atoms[i]->getMass();
209
210 getVelScaleB( sc, i );
211
212 // velocity half step
213 for (j=0; j < 3; j++)
214 vel[j] = oldVel[3*i+j] + dt2 * ((frc[j] / mass ) * eConvert - sc[j]);
215
216 atoms[i]->setVel( vel );
217
218 if( atoms[i]->isDirectional() ){
219
220 dAtom = (DirectionalAtom *)atoms[i];
221
222 // get and convert the torque to body frame
223
224 dAtom->getTrq( Tb );
225 dAtom->lab2Body( Tb );
226
227 for (j=0; j < 3; j++)
228 ji[j] = oldJi[3*i + j] + dt2 * (Tb[j] * eConvert - oldJi[3*i+j]*chi);
229
230 dAtom->setJ( ji );
231 }
232 }
233
234 if (nConstrained){
235 constrainB();
236 }
237
238 if ( this->chiConverged() && this->etaConverged() ) break;
239 }
240
241 //calculate integral of chida
242 integralOfChidt += dt2*chi;
243
244
245 }
246
247 template<typename T> void NPT<T>::resetIntegrator() {
248 chi = 0.0;
249 T::resetIntegrator();
250 }
251
252 template<typename T> void NPT<T>::evolveChiA() {
253 chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
254 oldChi = chi;
255 }
256
257 template<typename T> void NPT<T>::evolveChiB() {
258
259 prevChi = chi;
260 chi = oldChi + dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
261 }
262
263 template<typename T> bool NPT<T>::chiConverged() {
264
265 return ( fabs( prevChi - chi ) <= chiTolerance );
266 }
267
268 template<typename T> int NPT<T>::readyCheck() {
269
270 //check parent's readyCheck() first
271 if (T::readyCheck() == -1)
272 return -1;
273
274 // First check to see if we have a target temperature.
275 // Not having one is fatal.
276
277 if (!have_target_temp) {
278 sprintf( painCave.errMsg,
279 "NPT error: You can't use the NPT integrator\n"
280 " without a targetTemp!\n"
281 );
282 painCave.isFatal = 1;
283 simError();
284 return -1;
285 }
286
287 if (!have_target_pressure) {
288 sprintf( painCave.errMsg,
289 "NPT error: You can't use the NPT integrator\n"
290 " without a targetPressure!\n"
291 );
292 painCave.isFatal = 1;
293 simError();
294 return -1;
295 }
296
297 // We must set tauThermostat.
298
299 if (!have_tau_thermostat) {
300 sprintf( painCave.errMsg,
301 "NPT error: If you use the NPT\n"
302 " integrator, you must set tauThermostat.\n");
303 painCave.isFatal = 1;
304 simError();
305 return -1;
306 }
307
308 // We must set tauBarostat.
309
310 if (!have_tau_barostat) {
311 sprintf( painCave.errMsg,
312 "NPT error: If you use the NPT\n"
313 " integrator, you must set tauBarostat.\n");
314 painCave.isFatal = 1;
315 simError();
316 return -1;
317 }
318
319 if (!have_chi_tolerance) {
320 sprintf( painCave.errMsg,
321 "NPT warning: setting chi tolerance to 1e-6\n");
322 chiTolerance = 1e-6;
323 have_chi_tolerance = 1;
324 painCave.isFatal = 0;
325 simError();
326 }
327
328 if (!have_eta_tolerance) {
329 sprintf( painCave.errMsg,
330 "NPT warning: setting eta tolerance to 1e-6\n");
331 etaTolerance = 1e-6;
332 have_eta_tolerance = 1;
333 painCave.isFatal = 0;
334 simError();
335 }
336
337 // We need NkBT a lot, so just set it here: This is the RAW number
338 // of particles, so no subtraction or addition of constraints or
339 // orientational degrees of freedom:
340
341 NkBT = (double)Nparticles * kB * targetTemp;
342
343 // fkBT is used because the thermostat operates on more degrees of freedom
344 // than the barostat (when there are particles with orientational degrees
345 // of freedom). ndf = 3 * (n_atoms + n_oriented -1) - n_constraint - nZcons
346
347 fkBT = (double)info->ndf * kB * targetTemp;
348
349 tt2 = tauThermostat * tauThermostat;
350 tb2 = tauBarostat * tauBarostat;
351
352 return 1;
353 }