# | 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 | < | volume = oldBox[0]*oldBox[1]*oldBox[2]; |
100 | < | |
101 | < | ke_temp = ke * e_convert; |
102 | < | NkBT = (double)entry_plug->ndf * kB * targetTemp; |
103 | < | |
104 | < | // propogate the strain rate |
105 | < | |
106 | < | epsilonDot += dt * ((p_mol - p_ext) * volume / |
107 | < | (tauRelax*tauRelax * kB * targetTemp) ); |
108 | < | |
109 | < | |
110 | < | std::cerr << "dt = " << dt << " tauRelax = " << tauRelax << " kB = " << kB << "targetTemp = " << targetTemp << "\n"; |
111 | < | |
112 | < | // determine the change in cell volume |
113 | < | scale = pow( (1.0 + dt * 3.0 * epsilonDot), (1.0 / 3.0)); |
114 | < | |
115 | < | std::cerr << "p_mol = " << p_mol << " p_ext = " << p_ext << " scale = " << scale << "\n"; |
116 | < | |
117 | < | |
118 | < | newBox[0] = oldBox[0] * scale; |
119 | < | newBox[1] = oldBox[1] * scale; |
120 | < | newBox[2] = oldBox[2] * scale; |
121 | < | volume = newBox[0]*newBox[1]*newBox[2]; |
122 | < | |
123 | < | entry_plug->setBox(newBox); |
124 | < | |
125 | < | // perform affine transform to update positions with volume fluctuations |
126 | < | this->AffineTransform( oldBox, newBox ); |
127 | < | |
128 | < | epsilonScale = epsilonDot * dt; |
129 | < | |
130 | < | // advance the zeta term to zeta(t + dt) - zeta is 0.0d0 on config. readin |
131 | < | // qmass is set in the parameter file |
132 | < | |
133 | < | zeta += dt * ( (ke_temp*2.0 - NkBT) / qmass ); |
134 | < | zetaScale = zeta * dt; |
135 | < | |
136 | < | std::cerr << "zetaScale = " << zetaScale << "epsilonScale = " << epsilonScale << "\n"; |
137 | < | |
138 | < | // apply barostating and thermostating to velocities and angular momenta |
139 | < | 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)); |
147 | < | atoms[i]->set_vz(vz * (1.0 - zetaScale - epsilonScale)); |
148 | < | } |
149 | < | 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++ ){ |
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 | < | if( atoms[i]->isDirectional() ){ |
150 | < | |
151 | < | dAtom = (DirectionalAtom *)atoms[i]; |
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 213 | Line 222 | void ExtendedSystem::AffineTransform( double oldBox[3] | |
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 | + |
– | Removed lines |
+ | Added lines |
< | Changed lines |
> | Changed lines |