ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPT.cpp
(Generate patch)

Comparing trunk/OOPSE/libmdtools/NPT.cpp (file contents):
Revision 829 by gezelter, Tue Oct 28 16:03:37 2003 UTC vs.
Revision 837 by tim, Wed Oct 29 00:19:10 2003 UTC

# Line 7 | Line 7
7   #include "Thermo.hpp"
8   #include "ReadWrite.hpp"
9   #include "Integrator.hpp"
10 < #include "simError.h"
10 > #include "simError.h"
11  
12   #ifdef IS_MPI
13   #include "mpiSimulation.hpp"
# Line 18 | Line 18
18   // modification of the Hoover algorithm:
19   //
20   //    Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
21 < //       Molec. Phys., 78, 533.
21 > //       Molec. Phys., 78, 533.
22   //
23   //           and
24 < //
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 +  GenericData* data;
31 +  DoubleData * chiValue;
32 +  DoubleData * integralOfChidtValue;
33 +
34 +  chiValue = NULL;
35 +  integralOfChidtValue = NULL;
36 +
37    chi = 0.0;
38    integralOfChidt = 0.0;
39    have_tau_thermostat = 0;
# Line 37 | Line 44 | template<typename T> NPT<T>::NPT ( SimInfo *theInfo, F
44    have_eta_tolerance = 0;
45    have_pos_iter_tolerance = 0;
46  
47 +  // retrieve chi and integralOfChidt from simInfo
48 +  data = info->getProperty(CHIVALUE_ID);
49 +  if(data){
50 +    chiValue = dynamic_cast<DoubleData*>(data);
51 +  }
52 +
53 +  data = info->getProperty(INTEGRALOFCHIDT_ID);
54 +  if(data){
55 +    integralOfChidtValue = dynamic_cast<DoubleData*>(data);
56 +  }
57 +
58 +  // chi and integralOfChidt should appear by pair
59 +  if(chiValue && integralOfChidtValue){
60 +    chi = chiValue->getData();
61 +    integralOfChidt = integralOfChidtValue->getData();
62 +  }
63 +
64    oldPos = new double[3*nAtoms];
65    oldVel = new double[3*nAtoms];
66    oldJi = new double[3*nAtoms];
# Line 55 | Line 79 | template<typename T> void NPT<T>::moveA() {
79   }
80  
81   template<typename T> void NPT<T>::moveA() {
82 <
82 >
83    //new version of NPT
84    int i, j, k;
85    DirectionalAtom* dAtom;
# Line 69 | Line 93 | template<typename T> void NPT<T>::moveA() {
93    tStats->getPressureTensor( press );
94    instaPress = p_convert * (press[0][0] + press[1][1] + press[2][2]) / 3.0;
95    instaVol = tStats->getVolume();
96 <  
96 >
97    tStats->getCOM(COM);
98 <  
98 >
99    //evolve velocity half step
100    for( i=0; i<nAtoms; i++ ){
101  
# Line 83 | Line 107 | template<typename T> void NPT<T>::moveA() {
107      getVelScaleA( sc, vel );
108  
109      for (j=0; j < 3; j++) {
110 <      
110 >
111        // velocity half step  (use chi from previous step here):
112        vel[j] += dt2 * ((frc[j] / mass ) * eConvert - sc[j]);
113 <  
113 >
114      }
115  
116      atoms[i]->setVel( vel );
117 <  
117 >
118      if( atoms[i]->isDirectional() ){
119  
120        dAtom = (DirectionalAtom *)atoms[i];
121  
122        // get and convert the torque to body frame
123 <      
123 >
124        dAtom->getTrq( Tb );
125        dAtom->lab2Body( Tb );
126 <      
126 >
127        // get the angular momentum, and propagate a half step
128  
129        dAtom->getJ( ji );
130  
131 <      for (j=0; j < 3; j++)
131 >      for (j=0; j < 3; j++)
132          ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
133 <      
133 >
134        this->rotationPropagation( dAtom, ji );
135 <      
135 >
136        dAtom->setJ( ji );
137 <    }    
137 >    }
138    }
139  
140    // evolve chi and eta  half step
141 <  
141 >
142    evolveChiA();
143    evolveEtaA();
144  
# Line 127 | Line 151 | template<typename T> void NPT<T>::moveA() {
151      for(j = 0; j < 3; j++)
152        oldPos[i*3 + j] = pos[j];
153    }
154 <  
155 <  //the first estimation of r(t+dt) is equal to  r(t)
156 <    
154 >
155 >  //the first estimation of r(t+dt) is equal to  r(t)
156 >
157    for(k = 0; k < 5; k ++){
158  
159      for(i =0 ; i < nAtoms; i++){
# Line 138 | Line 162 | template<typename T> void NPT<T>::moveA() {
162        atoms[i]->getPos(pos);
163  
164        this->getPosScale( pos, COM, i, sc );
165 <  
165 >
166        for(j = 0; j < 3; j++)
167          pos[j] = oldPos[i*3 + j] + dt*(vel[j] + sc[j]);
168  
169        atoms[i]->setPos( pos );
170      }
171 <    
171 >
172      if (nConstrained){
173        constrainA();
174      }
175    }
152    
176  
177 +
178    // Scale the box after all the positions have been moved:
179 <  
179 >
180    this->scaleSimBox();
181   }
182  
183   template<typename T> void NPT<T>::moveB( void ){
184 <  
184 >
185    //new version of NPT
186    int i, j, k;
187    DirectionalAtom* dAtom;
188    double Tb[3], ji[3], sc[3];
189    double vel[3], frc[3];
190    double mass;
191 <  
191 >
192    // Set things up for the iteration:
193  
194    for( i=0; i<nAtoms; i++ ){
# Line 189 | Line 213 | template<typename T> void NPT<T>::moveB( void ){
213    // do the iteration:
214  
215    instaVol = tStats->getVolume();
216 <  
216 >
217    for (k=0; k < 4; k++) {
218 <    
218 >
219      instaTemp = tStats->getTemperature();
220      instaPress = tStats->getPressure();
221  
# Line 199 | Line 223 | template<typename T> void NPT<T>::moveB( void ){
223  
224      this->evolveChiB();
225      this->evolveEtaB();
226 <    
226 >
227      for( i=0; i<nAtoms; i++ ){
228  
229        atoms[i]->getFrc( frc );
230        atoms[i]->getVel(vel);
231 <      
231 >
232        mass = atoms[i]->getMass();
233 <      
233 >
234        getVelScaleB( sc, i );
235  
236        // velocity half step
237 <      for (j=0; j < 3; j++)
237 >      for (j=0; j < 3; j++)
238          vel[j] = oldVel[3*i+j] + dt2 * ((frc[j] / mass ) * eConvert - sc[j]);
239 <      
239 >
240        atoms[i]->setVel( vel );
241 <      
241 >
242        if( atoms[i]->isDirectional() ){
243  
244          dAtom = (DirectionalAtom *)atoms[i];
245 <  
246 <        // get and convert the torque to body frame      
247 <  
245 >
246 >        // get and convert the torque to body frame
247 >
248          dAtom->getTrq( Tb );
249 <        dAtom->lab2Body( Tb );      
250 <            
251 <        for (j=0; j < 3; j++)
249 >        dAtom->lab2Body( Tb );
250 >
251 >        for (j=0; j < 3; j++)
252            ji[j] = oldJi[3*i + j] + dt2 * (Tb[j] * eConvert - oldJi[3*i+j]*chi);
253 <      
253 >
254            dAtom->setJ( ji );
255        }
256      }
257 <    
257 >
258      if (nConstrained){
259        constrainB();
260 <    }    
261 <    
260 >    }
261 >
262      if ( this->chiConverged() && this->etaConverged() ) break;
263    }
264  
# Line 255 | Line 279 | template<typename T> void NPT<T>::evolveChiB() {
279   }
280  
281   template<typename T> void NPT<T>::evolveChiB() {
282 <  
282 >
283    prevChi = chi;
284    chi = oldChi + dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
285   }
286  
287   template<typename T> bool NPT<T>::chiConverged() {
288 <  
289 <  return ( fabs( prevChi - chi ) <= chiTolerance );  
288 >
289 >  return ( fabs( prevChi - chi ) <= chiTolerance );
290   }
291  
292   template<typename T> int NPT<T>::readyCheck() {
# Line 270 | Line 294 | template<typename T> int NPT<T>::readyCheck() {
294    //check parent's readyCheck() first
295    if (T::readyCheck() == -1)
296      return -1;
297 <
298 <  // First check to see if we have a target temperature.
299 <  // Not having one is fatal.
300 <  
297 >
298 >  // First check to see if we have a target temperature.
299 >  // Not having one is fatal.
300 >
301    if (!have_target_temp) {
302      sprintf( painCave.errMsg,
303               "NPT error: You can't use the NPT integrator\n"
# Line 293 | Line 317 | template<typename T> int NPT<T>::readyCheck() {
317      simError();
318      return -1;
319    }
320 <  
320 >
321    // We must set tauThermostat.
322 <  
322 >
323    if (!have_tau_thermostat) {
324      sprintf( painCave.errMsg,
325               "NPT error: If you use the NPT\n"
# Line 303 | Line 327 | template<typename T> int NPT<T>::readyCheck() {
327      painCave.isFatal = 1;
328      simError();
329      return -1;
330 <  }    
330 >  }
331  
332    // We must set tauBarostat.
333 <  
333 >
334    if (!have_tau_barostat) {
335      sprintf( painCave.errMsg,
336               "NPT error: If you use the NPT\n"
# Line 314 | Line 338 | template<typename T> int NPT<T>::readyCheck() {
338      painCave.isFatal = 1;
339      simError();
340      return -1;
341 <  }    
341 >  }
342  
343    if (!have_chi_tolerance) {
344      sprintf( painCave.errMsg,
# Line 323 | Line 347 | template<typename T> int NPT<T>::readyCheck() {
347      have_chi_tolerance = 1;
348      painCave.isFatal = 0;
349      simError();
350 <  }
350 >  }
351  
352    if (!have_eta_tolerance) {
353      sprintf( painCave.errMsg,
# Line 332 | Line 356 | template<typename T> int NPT<T>::readyCheck() {
356      have_eta_tolerance = 1;
357      painCave.isFatal = 0;
358      simError();
359 <  }
360 <  
359 >  }
360 >
361    // We need NkBT a lot, so just set it here: This is the RAW number
362    // of particles, so no subtraction or addition of constraints or
363    // orientational degrees of freedom:
364 <  
364 >
365    NkBT = (double)Nparticles * kB * targetTemp;
366 <  
366 >
367    // fkBT is used because the thermostat operates on more degrees of freedom
368    // than the barostat (when there are particles with orientational degrees
369    // of freedom).  ndf = 3 * (n_atoms + n_oriented -1) - n_constraint - nZcons
370 <  
370 >
371    fkBT = (double)info->ndf * kB * targetTemp;
372  
373    tt2 = tauThermostat * tauThermostat;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines