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

Comparing trunk/OOPSE/libmdtools/ExtendedSystem.cpp (file contents):
Revision 474 by gezelter, Mon Apr 7 21:42:19 2003 UTC vs.
Revision 483 by gezelter, Wed Apr 9 04:06:43 2003 UTC

# Line 4 | Line 4
4   #include "SimInfo.hpp"
5   #include "Thermo.hpp"
6   #include "ExtendedSystem.hpp"
7 + #include "simError.h"
8  
9   ExtendedSystem::ExtendedSystem( SimInfo* the_entry_plug ) {
10  
# Line 12 | Line 13 | ExtendedSystem::ExtendedSystem( SimInfo* the_entry_plu
13    entry_plug = the_entry_plug;
14    zeta = 0.0;
15    epsilonDot = 0.0;
16 +  have_tau_thermostat = 0;
17 +  have_tau_barostat = 0;
18 +  have_target_temp = 0;
19 +  have_target_pressure = 0;
20 +  have_qmass = 0;
21 +
22   }
23  
24   void ExtendedSystem::NoseHooverNVT( double dt, double ke ){
# Line 25 | Line 32 | void ExtendedSystem::NoseHooverNVT( double dt, double
32    const double e_convert = 4.184e-4;    // to convert ke from kcal/mol to
33                                          // amu*Ang^2*fs^-2/K
34    DirectionalAtom* dAtom;    
28  atoms = entry_plug->atoms;
35  
36 <  ke_temp = ke * e_convert;
31 <  NkBT = (double)entry_plug->ndf * kB * targetTemp;
36 >  if (this->NVTready()) {
37  
38 <  // advance the zeta term to zeta(t + dt) - zeta is 0.0d0 on config. readin
34 <  // qmass is set in the parameter file
35 <
36 <  zeta += dt * ( (ke_temp*2.0 - NkBT) / qmass );
37 <
38 <  zetaScale = zeta * dt;
39 <  
40 <  std::cerr << "zetaScale = " << zetaScale << "\n";
41 <
42 <  // perform thermostat scaling on linear velocities and angular momentum
43 <  for(i = 0; i < entry_plug->n_atoms; i++){
38 >    atoms = entry_plug->atoms;
39      
40 <    vx = atoms[i]->get_vx();
41 <    vy = atoms[i]->get_vy();
47 <    vz = atoms[i]->get_vz();
48 <
49 <    atoms[i]->set_vx(vx * (1.0 - zetaScale));
50 <    atoms[i]->set_vy(vy * (1.0 - zetaScale));
51 <    atoms[i]->set_vz(vz * (1.0 - zetaScale));
52 <  }
53 <  if( entry_plug->n_oriented ){
40 >    ke_temp = ke * e_convert;
41 >    NkBT = (double)entry_plug->ndf * kB * targetTemp;
42      
43 <    for( i=0; i < entry_plug->n_atoms; i++ ){
43 >    // advance the zeta term to zeta(t + dt) - zeta is 0.0d0 on config. readin
44 >    // qmass is set in the parameter file
45 >    
46 >    zeta += dt * ( (ke_temp*2.0 - NkBT) / qmass );
47 >    
48 >    zetaScale = zeta * dt;
49 >    
50 >    std::cerr << "zetaScale = " << zetaScale << "\n";
51 >    
52 >    // perform thermostat scaling on linear velocities and angular momentum
53 >    for(i = 0; i < entry_plug->n_atoms; i++){
54        
55 <      if( atoms[i]->isDirectional() ){
56 <        
57 <        dAtom = (DirectionalAtom *)atoms[i];
55 >      vx = atoms[i]->get_vx();
56 >      vy = atoms[i]->get_vy();
57 >      vz = atoms[i]->get_vz();
58 >      
59 >      atoms[i]->set_vx(vx * (1.0 - zetaScale));
60 >      atoms[i]->set_vy(vy * (1.0 - zetaScale));
61 >      atoms[i]->set_vz(vz * (1.0 - zetaScale));
62 >    }
63 >    if( entry_plug->n_oriented ){
64 >      
65 >      for( i=0; i < entry_plug->n_atoms; i++ ){
66          
67 <        jx = dAtom->getJx();
68 <        jy = dAtom->getJy();
69 <        jz = dAtom->getJz();
70 <        
71 <        dAtom->setJx(jx * (1.0 - zetaScale));
72 <        dAtom->setJy(jy * (1.0 - zetaScale));
73 <        dAtom->setJz(jz * (1.0 - zetaScale));
74 <      }
75 <    }  
67 >        if( atoms[i]->isDirectional() ){
68 >          
69 >          dAtom = (DirectionalAtom *)atoms[i];
70 >          
71 >          jx = dAtom->getJx();
72 >          jy = dAtom->getJy();
73 >          jz = dAtom->getJz();
74 >          
75 >          dAtom->setJx(jx * (1.0 - zetaScale));
76 >          dAtom->setJy(jy * (1.0 - zetaScale));
77 >          dAtom->setJz(jz * (1.0 - zetaScale));
78 >        }
79 >      }
80 >    }
81    }
82   }
83  
84  
85   void ExtendedSystem::NoseHooverAndersonNPT( double dt,
86                                              double ke,
87 <                                            double p_int ) {
87 >                                            double p_tensor[9] ) {
88  
89    // Basic barostating via Hoover, Phys.Rev.A, 1985, Vol. 31 (5) 1695-1697
90    // Hoover, Phys.Rev.A, 1986, Vol.34 (3) 2499-2500
# Line 90 | Line 101 | void ExtendedSystem::NoseHooverAndersonNPT( double dt,
101    double volume, p_mol;
102    double vx, vy, vz, jx, jy, jz;
103    DirectionalAtom* dAtom;
93  atoms = entry_plug->atoms;
104  
105 <  p_ext = targetPressure * p_units;
106 <  p_mol = p_int;
97 <
98 <  entry_plug->getBox(oldBox);
99 <
100 <  volume = oldBox[0]*oldBox[1]*oldBox[2];
101 <
102 <  ke_temp = ke * e_convert;
103 <  NkBT = (double)entry_plug->ndf * kB * targetTemp;
104 <
105 <  // propogate the strain rate
106 <
107 <  epsilonDot +=  dt * ((p_mol - p_ext) * volume /
108 <                       (tauRelax*tauRelax * kB * targetTemp) );
109 <
110 <
111 <  std::cerr << "p_mol = " << p_mol << " p_ext = " << p_ext << " volume = " << volume << " tauRelax = " << tauRelax << "\n";
112 <
113 <
114 <  // determine the change in cell volume
115 <  scale = pow( (1.0 + dt * 3.0 * epsilonDot), (1.0 / 3.0));
116 <
117 <  newBox[0] = oldBox[0] * scale;
118 <  newBox[1] = oldBox[1] * scale;
119 <  newBox[2] = oldBox[2] * scale;
120 <  volume = newBox[0]*newBox[1]*newBox[2];
121 <
122 <  entry_plug->setBox(newBox);
123 <
124 <  // perform affine transform to update positions with volume fluctuations
125 <  this->AffineTransform( oldBox, newBox );
126 <
127 <  epsilonScale = epsilonDot * dt;
128 <
129 <  // advance the zeta term to zeta(t + dt) - zeta is 0.0d0 on config. readin
130 <  // qmass is set in the parameter file
131 <
132 <  zeta += dt * ( (ke_temp*2.0 - NkBT) / qmass );
133 <  zetaScale = zeta * dt;
134 <
135 <  std::cerr << "zetaScale = " << zetaScale << "epsilonScale = " << epsilonScale <<  "\n";
136 <  
137 <  // apply barostating and thermostating to velocities and angular momenta
138 <  for(i = 0; i < entry_plug->n_atoms; i++){
105 >  if (this->NPTready()) {
106 >    atoms = entry_plug->atoms;
107      
108 <    vx = atoms[i]->get_vx();
109 <    vy = atoms[i]->get_vy();
110 <    vz = atoms[i]->get_vz();
108 >    p_ext = targetPressure * p_units;
109 >    p_mol = (p_tensor[0] + p_tensor[4] + p_tensor[8])/3.0;
110 >  
111 >    entry_plug->getBox(oldBox);
112 >    volume = oldBox[0]*oldBox[1]*oldBox[2];
113      
114 <    atoms[i]->set_vx(vx * (1.0 - zetaScale - epsilonScale));
115 <    atoms[i]->set_vy(vy * (1.0 - zetaScale - epsilonScale));
146 <    atoms[i]->set_vz(vz * (1.0 - zetaScale - epsilonScale));
147 <  }
148 <  if( entry_plug->n_oriented ){
114 >    ke_temp = ke * e_convert;
115 >    NkBT = (double)entry_plug->ndf * kB * targetTemp;
116      
117 <    for( i=0; i < entry_plug->n_atoms; i++ ){
118 <      
119 <      if( atoms[i]->isDirectional() ){
120 <        
121 <        dAtom = (DirectionalAtom *)atoms[i];
117 >    // propagate the strain rate
118 >    
119 >    epsilonDot +=  dt * ((p_mol - p_ext) * volume /
120 >                         (tauBarostat*tauBarostat * kB * targetTemp) );
121 >    
122 >    // determine the change in cell volume
123 >    scale = pow( (1.0 + dt * 3.0 * epsilonDot), (1.0 / 3.0));
124 >    std::cerr << "pmol = " << p_mol << " p_ext = " << p_ext << " scale = " << scale << "\n";
125 >    
126 >    newBox[0] = oldBox[0] * scale;
127 >    newBox[1] = oldBox[1] * scale;
128 >    newBox[2] = oldBox[2] * scale;
129 >    volume = newBox[0]*newBox[1]*newBox[2];
130 >    
131 >    entry_plug->setBox(newBox);
132 >    
133 >    // perform affine transform to update positions with volume fluctuations
134 >    this->AffineTransform( oldBox, newBox );
135 >    
136 >    epsilonScale = epsilonDot * dt;
137 >    
138 >    // advance the zeta term to zeta(t + dt) - zeta is 0.0d0 on config. readin
139 >    // qmass is set in the parameter file
140 >    
141 >    zeta += dt * ( (ke_temp*2.0 - NkBT) / qmass );
142 >    zetaScale = zeta * dt;
143 >    
144 >    std::cerr << "zetaScale = " << zetaScale << " epsilonScale = " << epsilonScale <<  "\n";
145 >    
146 >  // apply barostating and thermostating to velocities and angular momenta
147 >    for(i = 0; i < entry_plug->n_atoms; i++){
148 >      
149 >      vx = atoms[i]->get_vx();
150 >      vy = atoms[i]->get_vy();
151 >      vz = atoms[i]->get_vz();
152 >      
153 >      atoms[i]->set_vx(vx * (1.0 - zetaScale - epsilonScale));
154 >      atoms[i]->set_vy(vy * (1.0 - zetaScale - epsilonScale));
155 >      atoms[i]->set_vz(vz * (1.0 - zetaScale - epsilonScale));
156 >    }
157 >    if( entry_plug->n_oriented ){
158 >      
159 >      for( i=0; i < entry_plug->n_atoms; i++ ){
160          
161 <        jx = dAtom->getJx();
162 <        jy = dAtom->getJy();
163 <        jz = dAtom->getJz();
164 <        
165 <        dAtom->setJx( jx * (1.0 - zetaScale));
166 <        dAtom->setJy( jy * (1.0 - zetaScale));
167 <        dAtom->setJz( jz * (1.0 - zetaScale));
168 <      }
169 <    }  
161 >        if( atoms[i]->isDirectional() ){
162 >          
163 >          dAtom = (DirectionalAtom *)atoms[i];
164 >          
165 >          jx = dAtom->getJx();
166 >          jy = dAtom->getJy();
167 >          jz = dAtom->getJz();
168 >          
169 >          dAtom->setJx( jx * (1.0 - zetaScale));
170 >          dAtom->setJy( jy * (1.0 - zetaScale));
171 >          dAtom->setJz( jz * (1.0 - zetaScale));
172 >        }
173 >      }
174 >    }
175    }
176   }
177  
# Line 171 | Line 181 | void ExtendedSystem::AffineTransform( double oldBox[3]
181    double r[3];
182    double boxNum[3];
183    double percentScale[3];
184 +  double delta[3];
185    double rxi, ryi, rzi;
186  
187    molecules = entry_plug->molecules;
# Line 183 | Line 194 | void ExtendedSystem::AffineTransform( double oldBox[3]
194    for (i=0; i < entry_plug->n_mol; i++) {
195      
196      molecules[i].getCOM(r);
197 <    
197 >
198      // find the minimum image coordinates of the molecular centers of mass:    
199      
200      boxNum[0] = oldBox[0] * copysign(1.0,r[0]) *
# Line 204 | Line 215 | void ExtendedSystem::AffineTransform( double oldBox[3]
215      ryi += ryi*percentScale[1];
216      rzi += rzi*percentScale[2];
217  
218 <    r[0] = rxi + boxNum[0];
219 <    r[1] = ryi + boxNum[1];
220 <    r[2] = rzi + boxNum[2];
218 >    delta[0] = r[0] - (rxi + boxNum[0]);
219 >    delta[1] = r[1] - (ryi + boxNum[1]);
220 >    delta[2] = r[2] - (rzi + boxNum[2]);
221  
222 <    molecules[i].moveCOM(r);
222 >    molecules[i].moveCOM(delta);
223    }
224   }
225 +
226 + short int ExtendedSystem::NVTready() {
227 +  const double kB = 8.31451e-7;     // boltzmann constant in amu*Ang^2*fs^-2/K
228 +  double NkBT;
229 +
230 +  if (!have_target_temp) {
231 +    sprintf( painCave.errMsg,
232 +             "ExtendedSystem error: You can't use NVT without a targetTemp!\n"
233 +             );
234 +    painCave.isFatal = 1;
235 +    simError();
236 +    return -1;
237 +  }
238 +    
239 +  if (!have_qmass) {
240 +    if (have_tau_thermostat) {
241 +
242 +      NkBT = (double)entry_plug->ndf * kB * targetTemp;
243 +      std::cerr << "Setting qMass = " << tauThermostat * NkBT << "\n";
244 +      this->setQmass(tauThermostat * NkBT);
245 +
246 +    } else {
247 +      sprintf( painCave.errMsg,
248 +               "ExtendedSystem error: If you use the constant temperature\n"
249 +               "    ensemble, you must set either tauThermostat or qMass.\n");
250 +      painCave.isFatal = 1;
251 +      simError();
252 +    }
253 +  }
254 +
255 +  return 1;
256 + }
257 +
258 + short int ExtendedSystem::NPTready() {
259 +  const double kB = 8.31451e-7;     // boltzmann constant in amu*Ang^2*fs^-2/K
260 +  double NkBT;
261 +
262 +  if (!have_target_temp) {
263 +    sprintf( painCave.errMsg,
264 +             "ExtendedSystem error: You can't use NPT without a targetTemp!\n"
265 +             );
266 +    painCave.isFatal = 1;
267 +    simError();
268 +    return -1;
269 +  }
270 +
271 +  if (!have_target_pressure) {
272 +    sprintf( painCave.errMsg,
273 +             "ExtendedSystem error: You can't use NPT without a targetPressure!\n"
274 +             );
275 +    painCave.isFatal = 1;
276 +    simError();
277 +    return -1;
278 +  }
279 +    
280 +  if (!have_tau_barostat) {
281 +    sprintf( painCave.errMsg,
282 +             "ExtendedSystem error: If you use the NPT\n"
283 +             "    ensemble, you must set tauBarostat.\n");
284 +    painCave.isFatal = 1;
285 +    simError();
286 +  }
287 +
288 +  if (!have_qmass) {
289 +    if (have_tau_thermostat) {
290 +
291 +      NkBT = (double)entry_plug->ndf * kB * targetTemp;
292 +      std::cerr << "Setting qMass = " << tauThermostat * NkBT << "\n";
293 +      this->setQmass(tauThermostat * NkBT);
294 +
295 +    } else {
296 +      sprintf( painCave.errMsg,
297 +               "ExtendedSystem error: If you use the NPT\n"
298 +               "    ensemble, you must set either tauThermostat or qMass.\n");
299 +      painCave.isFatal = 1;
300 +      simError();
301 +    }  
302 +  }
303 +  return 1;
304 + }
305 +  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines