ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPT.cpp
Revision: 1129
Committed: Thu Apr 22 03:29:30 2004 UTC (20 years, 2 months ago) by tim
File size: 8415 byte(s)
Log Message:
fixed two bugs in MPI version of InitfromFile and one unmatch MPI command in DumpWriter

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 gezelter 1097 oldPos = new double[3*integrableObjects.size()];
66     oldVel = new double[3*integrableObjects.size()];
67     oldJi = new double[3*integrableObjects.size()];
68 mmeineke 778
69     }
70    
71     template<typename T> NPT<T>::~NPT() {
72     delete[] oldPos;
73     delete[] oldVel;
74     delete[] oldJi;
75     }
76    
77     template<typename T> void NPT<T>::moveA() {
78 tim 837
79 mmeineke 778 //new version of NPT
80     int i, j, k;
81     double Tb[3], ji[3];
82     double mass;
83     double vel[3], pos[3], frc[3];
84     double sc[3];
85     double COM[3];
86    
87     instaTemp = tStats->getTemperature();
88 mmeineke 780 tStats->getPressureTensor( press );
89     instaPress = p_convert * (press[0][0] + press[1][1] + press[2][2]) / 3.0;
90 mmeineke 778 instaVol = tStats->getVolume();
91 tim 837
92 mmeineke 778 tStats->getCOM(COM);
93 tim 837
94 mmeineke 778 //evolve velocity half step
95 mmeineke 857
96     calcVelScale();
97    
98 gezelter 1097 for( i=0; i<integrableObjects.size(); i++ ){
99 mmeineke 778
100 gezelter 1097 integrableObjects[i]->getVel( vel );
101     integrableObjects[i]->getFrc( frc );
102 mmeineke 778
103 gezelter 1097 mass = integrableObjects[i]->getMass();
104 mmeineke 778
105     getVelScaleA( sc, vel );
106    
107     for (j=0; j < 3; j++) {
108 tim 837
109 mmeineke 778 // velocity half step (use chi from previous step here):
110     vel[j] += dt2 * ((frc[j] / mass ) * eConvert - sc[j]);
111 tim 837
112 mmeineke 778 }
113    
114 gezelter 1097 integrableObjects[i]->setVel( vel );
115 tim 837
116 gezelter 1097 if( integrableObjects[i]->isDirectional() ){
117 mmeineke 778
118     // get and convert the torque to body frame
119 tim 837
120 gezelter 1097 integrableObjects[i]->getTrq( Tb );
121     integrableObjects[i]->lab2Body( Tb );
122 tim 837
123 mmeineke 778 // get the angular momentum, and propagate a half step
124    
125 gezelter 1097 integrableObjects[i]->getJ( ji );
126 mmeineke 778
127 tim 837 for (j=0; j < 3; j++)
128 mmeineke 778 ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
129 tim 837
130 gezelter 1097 this->rotationPropagation( integrableObjects[i], ji );
131 tim 837
132 gezelter 1097 integrableObjects[i]->setJ( ji );
133 tim 837 }
134 mmeineke 778 }
135    
136     // evolve chi and eta half step
137 tim 837
138 mmeineke 778 evolveChiA();
139     evolveEtaA();
140    
141     //calculate the integral of chidt
142     integralOfChidt += dt2*chi;
143    
144     //save the old positions
145 gezelter 1097 for(i = 0; i < integrableObjects.size(); i++){
146     integrableObjects[i]->getPos(pos);
147 mmeineke 778 for(j = 0; j < 3; j++)
148     oldPos[i*3 + j] = pos[j];
149     }
150 tim 837
151     //the first estimation of r(t+dt) is equal to r(t)
152    
153 mmeineke 778 for(k = 0; k < 5; k ++){
154    
155 gezelter 1097 for(i =0 ; i < integrableObjects.size(); i++){
156 mmeineke 778
157 gezelter 1097 integrableObjects[i]->getVel(vel);
158     integrableObjects[i]->getPos(pos);
159 mmeineke 778
160     this->getPosScale( pos, COM, i, sc );
161 tim 837
162 mmeineke 778 for(j = 0; j < 3; j++)
163     pos[j] = oldPos[i*3 + j] + dt*(vel[j] + sc[j]);
164    
165 gezelter 1097 integrableObjects[i]->setPos( pos );
166 mmeineke 778 }
167 tim 837
168 mmeineke 778 if (nConstrained){
169     constrainA();
170     }
171     }
172    
173 tim 837
174 mmeineke 778 // Scale the box after all the positions have been moved:
175 tim 837
176 mmeineke 778 this->scaleSimBox();
177     }
178    
179     template<typename T> void NPT<T>::moveB( void ){
180 tim 837
181 mmeineke 778 //new version of NPT
182     int i, j, k;
183     double Tb[3], ji[3], sc[3];
184     double vel[3], frc[3];
185     double mass;
186 tim 837
187 mmeineke 778 // Set things up for the iteration:
188    
189 gezelter 1097 for( i=0; i<integrableObjects.size(); i++ ){
190 mmeineke 778
191 gezelter 1097 integrableObjects[i]->getVel( vel );
192 mmeineke 778
193     for (j=0; j < 3; j++)
194     oldVel[3*i + j] = vel[j];
195    
196 gezelter 1097 if( integrableObjects[i]->isDirectional() ){
197 mmeineke 778
198 gezelter 1097 integrableObjects[i]->getJ( ji );
199 mmeineke 778
200     for (j=0; j < 3; j++)
201     oldJi[3*i + j] = ji[j];
202    
203     }
204     }
205    
206     // do the iteration:
207    
208     instaVol = tStats->getVolume();
209 tim 837
210 mmeineke 778 for (k=0; k < 4; k++) {
211 tim 837
212 mmeineke 778 instaTemp = tStats->getTemperature();
213     instaPress = tStats->getPressure();
214    
215     // evolve chi another half step using the temperature at t + dt/2
216    
217     this->evolveChiB();
218     this->evolveEtaB();
219 mmeineke 857 this->calcVelScale();
220 tim 837
221 gezelter 1097 for( i=0; i<integrableObjects.size(); i++ ){
222 mmeineke 778
223 gezelter 1097 integrableObjects[i]->getFrc( frc );
224     integrableObjects[i]->getVel(vel);
225 tim 837
226 gezelter 1097 mass = integrableObjects[i]->getMass();
227 tim 837
228 mmeineke 778 getVelScaleB( sc, i );
229    
230     // velocity half step
231 tim 837 for (j=0; j < 3; j++)
232 mmeineke 778 vel[j] = oldVel[3*i+j] + dt2 * ((frc[j] / mass ) * eConvert - sc[j]);
233 tim 837
234 gezelter 1097 integrableObjects[i]->setVel( vel );
235 tim 837
236 gezelter 1097 if( integrableObjects[i]->isDirectional() ){
237 mmeineke 778
238 tim 837 // get and convert the torque to body frame
239    
240 gezelter 1097 integrableObjects[i]->getTrq( Tb );
241     integrableObjects[i]->lab2Body( Tb );
242 tim 837
243     for (j=0; j < 3; j++)
244 mmeineke 778 ji[j] = oldJi[3*i + j] + dt2 * (Tb[j] * eConvert - oldJi[3*i+j]*chi);
245 tim 837
246 gezelter 1097 integrableObjects[i]->setJ( ji );
247 mmeineke 778 }
248     }
249 tim 837
250 mmeineke 778 if (nConstrained){
251     constrainB();
252 tim 837 }
253    
254 mmeineke 778 if ( this->chiConverged() && this->etaConverged() ) break;
255     }
256    
257     //calculate integral of chida
258     integralOfChidt += dt2*chi;
259    
260    
261     }
262    
263     template<typename T> void NPT<T>::resetIntegrator() {
264     chi = 0.0;
265     T::resetIntegrator();
266     }
267    
268     template<typename T> void NPT<T>::evolveChiA() {
269     chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
270     oldChi = chi;
271     }
272    
273     template<typename T> void NPT<T>::evolveChiB() {
274 tim 837
275 mmeineke 778 prevChi = chi;
276     chi = oldChi + dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
277     }
278    
279     template<typename T> bool NPT<T>::chiConverged() {
280 tim 837
281     return ( fabs( prevChi - chi ) <= chiTolerance );
282 mmeineke 778 }
283    
284     template<typename T> int NPT<T>::readyCheck() {
285    
286     //check parent's readyCheck() first
287     if (T::readyCheck() == -1)
288     return -1;
289 tim 837
290     // First check to see if we have a target temperature.
291     // Not having one is fatal.
292    
293 mmeineke 778 if (!have_target_temp) {
294     sprintf( painCave.errMsg,
295     "NPT error: You can't use the NPT integrator\n"
296     " without a targetTemp!\n"
297     );
298     painCave.isFatal = 1;
299     simError();
300     return -1;
301     }
302    
303     if (!have_target_pressure) {
304     sprintf( painCave.errMsg,
305     "NPT error: You can't use the NPT integrator\n"
306     " without a targetPressure!\n"
307     );
308     painCave.isFatal = 1;
309     simError();
310     return -1;
311     }
312 tim 837
313 mmeineke 778 // We must set tauThermostat.
314 tim 837
315 mmeineke 778 if (!have_tau_thermostat) {
316     sprintf( painCave.errMsg,
317     "NPT error: If you use the NPT\n"
318     " integrator, you must set tauThermostat.\n");
319     painCave.isFatal = 1;
320     simError();
321     return -1;
322 tim 837 }
323 mmeineke 778
324     // We must set tauBarostat.
325 tim 837
326 mmeineke 778 if (!have_tau_barostat) {
327     sprintf( painCave.errMsg,
328     "NPT error: If you use the NPT\n"
329     " integrator, you must set tauBarostat.\n");
330     painCave.isFatal = 1;
331     simError();
332     return -1;
333 tim 837 }
334 mmeineke 778
335     if (!have_chi_tolerance) {
336     sprintf( painCave.errMsg,
337     "NPT warning: setting chi tolerance to 1e-6\n");
338     chiTolerance = 1e-6;
339     have_chi_tolerance = 1;
340     painCave.isFatal = 0;
341     simError();
342 tim 837 }
343 mmeineke 778
344     if (!have_eta_tolerance) {
345     sprintf( painCave.errMsg,
346     "NPT warning: setting eta tolerance to 1e-6\n");
347     etaTolerance = 1e-6;
348     have_eta_tolerance = 1;
349     painCave.isFatal = 0;
350     simError();
351 tim 837 }
352    
353 mmeineke 778 // We need NkBT a lot, so just set it here: This is the RAW number
354 tim 1129 // of integrableObjects, so no subtraction or addition of constraints or
355 mmeineke 778 // orientational degrees of freedom:
356 tim 837
357 tim 1129 NkBT = (double)(info->getTotIntegrableObjects()) * kB * targetTemp;
358 tim 837
359 mmeineke 778 // fkBT is used because the thermostat operates on more degrees of freedom
360     // than the barostat (when there are particles with orientational degrees
361 tim 1129 // of freedom).
362 tim 837
363 tim 1129 fkBT = (double)(info->getNDF()) * kB * targetTemp;
364 mmeineke 778
365     tt2 = tauThermostat * tauThermostat;
366     tb2 = tauBarostat * tauBarostat;
367    
368     return 1;
369     }