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 454 by gezelter, Fri Apr 4 01:57:11 2003 UTC vs.
Revision 481 by gezelter, Tue Apr 8 21:35:49 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 &info ) {
9 > ExtendedSystem::ExtendedSystem( SimInfo* the_entry_plug ) {
10  
11    // get what information we need from the SimInfo object
12    
13 <  entry_plug = &info;
14 <  nAtoms = info.n_atoms;
15 <  atoms = info.atoms;
16 <  nMols = info.n_mol;
17 <  molecules = info.molecules;
18 <  zeta = 0;
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 < ExtendedSystem::~ExtendedSystem() {  
22 < }
24 > void ExtendedSystem::NoseHooverNVT( double dt, double ke ){
25  
24
25 void ExtendedSystem::NoseHooverNVT( double dt ){
26
26    // Basic thermostating via Hoover, Phys.Rev.A, 1985, Vol. 31 (5) 1695-1697
27    
28    int i;
29 <  double kB, keconverter, NkBT, zetaScale, ke_temp;
29 >  double NkBT, zetaScale, ke_temp;
30    double vx, vy, vz, jx, jy, jz;
31 <  
32 <  kB = 8.31451e-7; // boltzmann constant in amu*Ang^2*fs^-2/K
33 <  keconverter = 4.184e-4; // to convert ke from kcal/mol to amu*Ang^2*fs^-2 / K
34 <  
36 <  ke_temp = getKinetic() * keconverter;
37 <  NkBT = (double)getNDF() * kB * targetTemp;
31 >  const double kB = 8.31451e-7;     // boltzmann constant in amu*Ang^2*fs^-2/K
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;    
35  
36 <  // advance the zeta term to zeta(t + dt) - zeta is 0.0d0 on config. readin &
40 <  // qmass is set in the parameter file
41 <  zeta += dt*((ke_temp*2 - NkBT)/qmass);
42 <  zetaScale = zeta * dt;
36 >  if (this->NVTready()) {
37  
38 <  // perform thermostat scaling on linear velocities and angular momentum
45 <  
46 <  for(i = 0; i < n_atoms; i++){
38 >    atoms = entry_plug->atoms;
39      
40 <    vx = atoms[i]->get_vx();
41 <    vy = atoms[i]->get_vy();
50 <    vz = atoms[i]->get_vz();
40 >    ke_temp = ke * e_convert;
41 >    NkBT = (double)entry_plug->ndf * kB * targetTemp;
42      
43 <    atoms[i]->set_vx(vx - zetaScale * vx);
44 <    atoms[i]->set_vy(vy - zetaScale * vy);
54 <    atoms[i]->set_vz(vz - zetaScale * vz);
55 <  }
56 <  if( n_oriented ){
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 <    for( i=0; i < n_atoms; i++ ){
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 - zetaScale * jx);
72 <        dAtom->setJy( jy - zetaScale * jy);
73 <        dAtom->setJz( jz - zetaScale * jz);
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 pressure, double ke,
86 <                                           double dt, double temp ) {
85 > void ExtendedSystem::NoseHooverAndersonNPT( double dt,
86 >                                            double ke,
87 >                                            double p_int ) {
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
91  
92 <  int i, j, degrees_freedom;
93 <  double pressure, dt, temp, pressure_units, epsilonScale;
94 <  double ke, kB, vxi, vyi, vzi, pressure_ext;
95 <  double boxx_old, boxy_old, boxz_old;
96 <  double keconverter, NkBT, zetaScale, ke_temp;
97 <  double jxi, jyi, jzi, scale;
92 >  double oldBox[3];
93 >  double newBox[3];
94 >  const double kB = 8.31451e-7;     // boltzmann constant in amu*Ang^2*fs^-2/K
95 >  const double p_units = 6.10192996e-9; // converts atm to amu*fs^-2*Ang^-1
96 >  const double e_convert = 4.184e-4;    // to convert ke from kcal/mol to
97 >                                        // amu*Ang^2*fs^-2/K
98  
99 <  kB = 8.31451e-7; // boltzmann constant in amu*Ang^2*fs^-2/K
100 <  pressure_units = 6.10192996e-9; // converts atm to amu*fs^-2*Ang^-1
101 <  degrees_freedom = 6*nmol; // number of degrees of freedom for the system
102 <  keconverter = 4.184e-4; // to convert ke from kcal/mol to amu*Ang^2*fs^-2/K
99 >  int i;
100 >  double p_ext, zetaScale, epsilonScale, scale, NkBT, ke_temp;
101 >  double volume, p_mol;
102 >  double vx, vy, vz, jx, jy, jz;
103 >  DirectionalAtom* dAtom;
104  
105 <  pressure_ext = pressure * pressure_units;
106 <  volume = boxx*boxy*boxz;
97 <  ke_temp = ke * keconverter;
98 <  NkBT = degrees_freedom*kB*temp;
99 <
100 <  // propogate the strain rate
101 <
102 <  epsilon_dot +=  dt * ( (p_mol - pressure_ext)*volume
103 <                         / (tau_relax*tau_relax * kB * targetTemp) );
104 <
105 <  // determine the change in cell volume
106 <  scale = pow( (1.0 + dt * 3.0 * epsilon_dot), (1.0 / 3.0));
107 <
108 <  volume = volume * pow(scale, 3.0);
109 <
110 <  // perform affine transform to update positions with volume fluctuations
111 <  affine_transform( scale );
112 <
113 <  // save old lengths and update box size
114 <  boxx_old = boxx;
115 <  boxy_old = boxy;
116 <  boxz_old = boxz;
117 <
118 <  boxx = boxx_old*scale;
119 <  boxy = boxy_old*scale;
120 <  boxz = boxz_old*scale;
121 <
122 <  epsilonScale = epsilonDot * dt;
123 <
124 <  // advance the zeta term to zeta(t + dt) - zeta is 0.0d0 on config. readin
125 <  // qmass is set in the parameter file
126 <  zeta += dt * ( (ke_temp*2 - NkBT) / qmass );
127 <  zetaScale = zeta * dt;
128 <  
129 <  // apply barostating and thermostating to velocities and angular momenta
130 <  for(i = 0; i < 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();
134 <    vz = atoms[i]->get_vz();
108 >    p_ext = targetPressure * p_units;
109 >    p_mol = p_int * p_units;
110      
111 <    atoms[i]->set_vx(vx * (1.0 - zetaScale * epsilonScale));
112 <    atoms[i]->set_vy(vy * (1.0 - zetaScale * epsilonScale));
138 <    atoms[i]->set_vz(vz * (1.0 - zetaScale * epsilonScale));
139 <  }
140 <  if( n_oriented ){
111 >    entry_plug->getBox(oldBox);
112 >    volume = oldBox[0]*oldBox[1]*oldBox[2];
113      
114 <    for( i=0; i < n_atoms; i++ ){
114 >    ke_temp = ke * e_convert;
115 >    NkBT = (double)entry_plug->ndf * kB * targetTemp;
116 >    
117 >    // propogate 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 >    
125 >    newBox[0] = oldBox[0] * scale;
126 >    newBox[1] = oldBox[1] * scale;
127 >    newBox[2] = oldBox[2] * scale;
128 >    volume = newBox[0]*newBox[1]*newBox[2];
129 >    
130 >    entry_plug->setBox(newBox);
131 >    
132 >    // perform affine transform to update positions with volume fluctuations
133 >    this->AffineTransform( oldBox, newBox );
134 >    
135 >    epsilonScale = epsilonDot * dt;
136 >    
137 >    // advance the zeta term to zeta(t + dt) - zeta is 0.0d0 on config. readin
138 >    // qmass is set in the parameter file
139 >    
140 >    zeta += dt * ( (ke_temp*2.0 - NkBT) / qmass );
141 >    zetaScale = zeta * dt;
142 >    
143 >    std::cerr << "zetaScale = " << zetaScale << " epsilonScale = " << epsilonScale <<  "\n";
144 >    
145 >  // apply barostating and thermostating to velocities and angular momenta
146 >    for(i = 0; i < entry_plug->n_atoms; i++){
147        
148 <      if( atoms[i]->isDirectional() ){
149 <        
150 <        dAtom = (DirectionalAtom *)atoms[i];
148 >      vx = atoms[i]->get_vx();
149 >      vy = atoms[i]->get_vy();
150 >      vz = atoms[i]->get_vz();
151 >      
152 >      atoms[i]->set_vx(vx * (1.0 - zetaScale - epsilonScale));
153 >      atoms[i]->set_vy(vy * (1.0 - zetaScale - epsilonScale));
154 >      atoms[i]->set_vz(vz * (1.0 - zetaScale - epsilonScale));
155 >    }
156 >    if( entry_plug->n_oriented ){
157 >      
158 >      for( i=0; i < entry_plug->n_atoms; i++ ){
159          
160 <        jx = dAtom->getJx();
161 <        jy = dAtom->getJy();
162 <        jz = dAtom->getJz();
163 <        
164 <        dAtom->setJx( jx * (1.0 - zetaScale));
165 <        dAtom->setJy( jy * (1.0 - zetaScale));
166 <        dAtom->setJz( jz * (1.0 - zetaScale));
167 <      }
168 <    }  
160 >        if( atoms[i]->isDirectional() ){
161 >          
162 >          dAtom = (DirectionalAtom *)atoms[i];
163 >          
164 >          jx = dAtom->getJx();
165 >          jy = dAtom->getJy();
166 >          jz = dAtom->getJz();
167 >          
168 >          dAtom->setJx( jx * (1.0 - zetaScale));
169 >          dAtom->setJy( jy * (1.0 - zetaScale));
170 >          dAtom->setJz( jz * (1.0 - zetaScale));
171 >        }
172 >      }
173 >    }
174    }
175   }
176  
177 < void ExtendedSystem::AffineTransform( double scale ){
177 > void ExtendedSystem::AffineTransform( double oldBox[3], double newBox[3] ){
178  
179    int i;
180 <  double boxx_old, boxy_old, boxz_old, percentScale;
181 <  double boxx_num, boxy_num, boxz_num, rxi, ryi, rzi;
182 <  double[3] r;
180 >  double r[3];
181 >  double boxNum[3];
182 >  double percentScale[3];
183 >  double delta[3];
184 >  double rxi, ryi, rzi;
185 >
186 >  molecules = entry_plug->molecules;
187      
188    // first determine the scaling factor from the box size change
189 <  percentScale = (boxx - boxx_old)/boxx_old;
189 >  percentScale[0] = (newBox[0] - oldBox[0]) / oldBox[0];
190 >  percentScale[1] = (newBox[1] - oldBox[1]) / oldBox[1];
191 >  percentScale[2] = (newBox[2] - oldBox[2]) / oldBox[2];
192    
193 +  for (i=0; i < entry_plug->n_mol; i++) {
194 +    
195 +    molecules[i].getCOM(r);
196  
197 <  for (i=0; i < nMols; i++) {
197 >    // find the minimum image coordinates of the molecular centers of mass:    
198      
199 <    molecules[i]->getCOM(r);
200 <    
175 <    // find the minimum image coordinates of the molecular centers of mass:
176 <    
177 <    
178 <    boxx_num = boxx_old*copysign(1.0,r[0])*(double)(int)(fabs(r[0]/boxx_old)+0.5);
199 >    boxNum[0] = oldBox[0] * copysign(1.0,r[0]) *
200 >      (double)(int)(fabs(r[0]/oldBox[0]) + 0.5);
201  
202 <    boxx_num = boxx_old*dsign(1.0d0,rx(i))*int(abs(rx(i)/boxx_old)+0.5d0);
203 <    boxy_num = boxy_old*dsign(1.0d0,ry(i))*int(abs(ry(i)/boxy_old)+0.5d0);
182 <    boxz_num = boxz_old*dsign(1.0d0,rz(i))*int(abs(rz(i)/boxz_old)+0.5d0);
202 >    boxNum[1] = oldBox[1] * copysign(1.0,r[1]) *
203 >      (double)(int)(fabs(r[1]/oldBox[1]) + 0.5);
204  
205 <    rxi = rx(i) - boxx_num;
206 <    ryi = ry(i) - boxy_num;
186 <    rzi = rz(i) - boxz_num;
205 >    boxNum[2] = oldBox[2] * copysign(1.0,r[2]) *
206 >      (double)(int)(fabs(r[2]/oldBox[2]) + 0.5);
207  
208 +    rxi = r[0] - boxNum[0];
209 +    ryi = r[1] - boxNum[1];
210 +    rzi = r[2] - boxNum[2];
211 +
212      // update the minimum image coordinates using the scaling factor
213 <    rxi = rxi + rxi*percentScale;
214 <    ryi = ryi + ryi*percentScale;
215 <    rzi = rzi + rzi*percentScale;
213 >    rxi += rxi*percentScale[0];
214 >    ryi += ryi*percentScale[1];
215 >    rzi += rzi*percentScale[2];
216  
217 <    rx(i) = rxi + boxx_num;
218 <    ry(i) = ryi + boxy_num;
219 <    rz(i) = rzi + boxz_num;
217 >    delta[0] = r[0] - (rxi + boxNum[0]);
218 >    delta[1] = r[1] - (ryi + boxNum[1]);
219 >    delta[2] = r[2] - (rzi + boxNum[2]);
220 >
221 >    molecules[i].moveCOM(delta);
222    }
223   }
224 +
225 + short int ExtendedSystem::NVTready() {
226 +  const double kB = 8.31451e-7;     // boltzmann constant in amu*Ang^2*fs^-2/K
227 +  double NkBT;
228 +
229 +  if (!have_target_temp) {
230 +    sprintf( painCave.errMsg,
231 +             "ExtendedSystem error: You can't use NVT without a targetTemp!\n"
232 +             );
233 +    painCave.isFatal = 1;
234 +    simError();
235 +    return -1;
236 +  }
237 +    
238 +  if (!have_qmass) {
239 +    if (have_tau_thermostat) {
240 +
241 +      NkBT = (double)entry_plug->ndf * kB * targetTemp;
242 +      std::cerr << "Setting qMass = " << tauThermostat * NkBT << "\n";
243 +      this->setQmass(tauThermostat * NkBT);
244 +
245 +    } else {
246 +      sprintf( painCave.errMsg,
247 +               "ExtendedSystem error: If you use the constant temperature\n"
248 +               "    ensemble, you must set either tauThermostat or qMass.\n");
249 +      painCave.isFatal = 1;
250 +      simError();
251 +    }
252 +  }
253 +
254 +  return 0;
255 + }
256 +
257 + short int ExtendedSystem::NPTready() {
258 +  const double kB = 8.31451e-7;     // boltzmann constant in amu*Ang^2*fs^-2/K
259 +  double NkBT;
260 +
261 +  if (!have_target_temp) {
262 +    sprintf( painCave.errMsg,
263 +             "ExtendedSystem error: You can't use NPT without a targetTemp!\n"
264 +             );
265 +    painCave.isFatal = 1;
266 +    simError();
267 +    return -1;
268 +  }
269 +
270 +  if (!have_target_pressure) {
271 +    sprintf( painCave.errMsg,
272 +             "ExtendedSystem error: You can't use NPT without a targetPressure!\n"
273 +             );
274 +    painCave.isFatal = 1;
275 +    simError();
276 +    return -1;
277 +  }
278 +    
279 +  if (!have_tau_barostat) {
280 +    sprintf( painCave.errMsg,
281 +             "ExtendedSystem error: If you use the NPT\n"
282 +             "    ensemble, you must set tauBarostat.\n");
283 +    painCave.isFatal = 1;
284 +    simError();
285 +  }
286 +
287 +  if (!have_qmass) {
288 +    if (have_tau_thermostat) {
289 +
290 +      NkBT = (double)entry_plug->ndf * kB * targetTemp;
291 +      std::cerr << "Setting qMass = " << tauThermostat * NkBT << "\n";
292 +      this->setQmass(tauThermostat * NkBT);
293 +
294 +    } else {
295 +      sprintf( painCave.errMsg,
296 +               "ExtendedSystem error: If you use the NPT\n"
297 +               "    ensemble, you must set either tauThermostat or qMass.\n");
298 +      painCave.isFatal = 1;
299 +      simError();
300 +    }  
301 +  }
302 +  return 0;
303 + }
304 +  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines