ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPT.cpp
Revision: 1097
Committed: Mon Apr 12 20:32:20 2004 UTC (20 years, 2 months ago) by gezelter
File size: 8534 byte(s)
Log Message:
Changes for RigidBody dynamics (Somewhat extensive)

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