ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPT.cpp
Revision: 857
Committed: Fri Nov 7 17:09:48 2003 UTC (20 years, 8 months ago) by mmeineke
File size: 8249 byte(s)
Log Message:
moved the velocity scale matrix calculation outside of the atom loop in the NPT family of integrators.

File Contents

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