ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-1.0/libmdtools/NPT.cpp
Revision: 1334
Committed: Fri Jul 16 18:58:03 2004 UTC (19 years, 11 months ago) by gezelter
File size: 8489 byte(s)
Log Message:
Initial import of OOPSE-1.0 source tree

File Contents

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