# | Line 4 | Line 4 | using namespace std; | |
---|---|---|
4 | ||
5 | #ifdef IS_MPI | |
6 | #include <mpi.h> | |
7 | – | #include <mpi++.h> |
7 | #endif //is_mpi | |
8 | ||
9 | #include "Thermo.hpp" | |
10 | #include "SRI.hpp" | |
11 | #include "Integrator.hpp" | |
12 | + | #include "simError.h" |
13 | ||
14 | #ifdef IS_MPI | |
15 | #define __C | |
# | Line 33 | Line 33 | double Thermo::getKinetic(){ | |
33 | double Thermo::getKinetic(){ | |
34 | ||
35 | const double e_convert = 4.184E-4; // convert kcal/mol -> (amu A^2)/fs^2 | |
36 | < | double vx2, vy2, vz2; |
37 | < | double kinetic, v_sqr; |
38 | < | int kl; |
39 | < | double jx2, jy2, jz2; // the square of the angular momentums |
36 | > | double kinetic; |
37 | > | double amass; |
38 | > | double aVel[3], aJ[3], I[3][3]; |
39 | > | int j, kl; |
40 | ||
41 | DirectionalAtom *dAtom; | |
42 | ||
# | Line 51 | Line 51 | double Thermo::getKinetic(){ | |
51 | kinetic = 0.0; | |
52 | kinetic_global = 0.0; | |
53 | for( kl=0; kl < n_atoms; kl++ ){ | |
54 | + | |
55 | + | atoms[kl]->getVel(aVel); |
56 | + | amass = atoms[kl]->getMass(); |
57 | + | |
58 | + | for (j=0; j < 3; j++) |
59 | + | kinetic += amass * aVel[j] * aVel[j]; |
60 | ||
55 | – | vx2 = atoms[kl]->get_vx() * atoms[kl]->get_vx(); |
56 | – | vy2 = atoms[kl]->get_vy() * atoms[kl]->get_vy(); |
57 | – | vz2 = atoms[kl]->get_vz() * atoms[kl]->get_vz(); |
58 | – | |
59 | – | v_sqr = vx2 + vy2 + vz2; |
60 | – | kinetic += atoms[kl]->getMass() * v_sqr; |
61 | – | |
61 | if( atoms[kl]->isDirectional() ){ | |
62 | ||
63 | dAtom = (DirectionalAtom *)atoms[kl]; | |
64 | + | |
65 | + | dAtom->getJ( aJ ); |
66 | + | dAtom->getI( I ); |
67 | ||
68 | < | jx2 = dAtom->getJx() * dAtom->getJx(); |
69 | < | jy2 = dAtom->getJy() * dAtom->getJy(); |
68 | < | jz2 = dAtom->getJz() * dAtom->getJz(); |
68 | > | for (j=0; j<3; j++) |
69 | > | kinetic += aJ[j]*aJ[j] / I[j][j]; |
70 | ||
70 | – | kinetic += (jx2 / dAtom->getIxx()) + (jy2 / dAtom->getIyy()) |
71 | – | + (jz2 / dAtom->getIzz()); |
71 | } | |
72 | } | |
73 | #ifdef IS_MPI | |
74 | < | MPI::COMM_WORLD.Allreduce(&kinetic,&kinetic_global,1,MPI_DOUBLE,MPI_SUM); |
74 | > | MPI_Allreduce(&kinetic,&kinetic_global,1,MPI_DOUBLE, |
75 | > | MPI_SUM, MPI_COMM_WORLD); |
76 | kinetic = kinetic_global; | |
77 | #endif //is_mpi | |
78 | ||
# | Line 86 | Line 86 | double Thermo::getPotential(){ | |
86 | double potential_local; | |
87 | double potential; | |
88 | int el, nSRI; | |
89 | < | SRI** sris; |
89 | > | Molecule* molecules; |
90 | ||
91 | < | sris = entry_plug->sr_interactions; |
91 | > | molecules = entry_plug->molecules; |
92 | nSRI = entry_plug->n_SRI; | |
93 | ||
94 | potential_local = 0.0; | |
95 | + | potential = 0.0; |
96 | potential_local += entry_plug->lrPot; | |
97 | ||
98 | for( el=0; el<entry_plug->n_mol; el++ ){ | |
99 | < | potential_local += entry_plug->molecules[el]->get_potential(); |
99 | > | potential_local += molecules[el].getPotential(); |
100 | } | |
101 | ||
102 | // Get total potential for entire system from MPI. | |
103 | #ifdef IS_MPI | |
104 | < | MPI::COMM_WORLD.Allreduce(&potential_local,&potential,1,MPI_DOUBLE,MPI_SUM); |
104 | > | MPI_Allreduce(&potential_local,&potential,1,MPI_DOUBLE, |
105 | > | MPI_SUM, MPI_COMM_WORLD); |
106 | #else | |
107 | potential = potential_local; | |
108 | #endif // is_mpi | |
109 | ||
110 | + | #ifdef IS_MPI |
111 | + | /* |
112 | + | std::cerr << "node " << worldRank << ": after pot = " << potential << "\n"; |
113 | + | */ |
114 | + | #endif |
115 | + | |
116 | return potential; | |
117 | } | |
118 | ||
# | Line 120 | Line 128 | double Thermo::getTemperature(){ | |
128 | ||
129 | const double kb = 1.9872179E-3; // boltzman's constant in kcal/(mol K) | |
130 | double temperature; | |
123 | – | int ndf_local, ndf; |
131 | ||
132 | < | ndf_local = 3 * entry_plug->n_atoms + 3 * entry_plug->n_oriented |
133 | < | - entry_plug->n_constraints; |
132 | > | temperature = ( 2.0 * this->getKinetic() ) / ((double)entry_plug->ndf * kb ); |
133 | > | return temperature; |
134 | > | } |
135 | ||
136 | < | #ifdef IS_MPI |
129 | < | MPI::COMM_WORLD.Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM); |
130 | < | #else |
131 | < | ndf = ndf_local; |
132 | < | #endif |
136 | > | double Thermo::getEnthalpy() { |
137 | ||
138 | < | ndf = ndf - 3; |
138 | > | const double e_convert = 4.184E-4; // convert kcal/mol -> (amu A^2)/fs^2 |
139 | > | double u, p, v; |
140 | > | double press[3][3]; |
141 | > | |
142 | > | u = this->getTotalE(); |
143 | > | |
144 | > | this->getPressureTensor(press); |
145 | > | p = (press[0][0] + press[1][1] + press[2][2]) / 3.0; |
146 | > | |
147 | > | v = this->getVolume(); |
148 | > | |
149 | > | return (u + (p*v)/e_convert); |
150 | > | } |
151 | > | |
152 | > | double Thermo::getVolume() { |
153 | > | |
154 | > | return entry_plug->boxVol; |
155 | > | } |
156 | > | |
157 | > | double Thermo::getPressure() { |
158 | > | |
159 | > | // Relies on the calculation of the full molecular pressure tensor |
160 | ||
161 | < | temperature = ( 2.0 * this->getKinetic() ) / ( ndf * kb ); |
162 | < | return temperature; |
161 | > | const double p_convert = 1.63882576e8; |
162 | > | double press[3][3]; |
163 | > | double pressure; |
164 | > | |
165 | > | this->getPressureTensor(press); |
166 | > | |
167 | > | pressure = p_convert * (press[0][0] + press[1][1] + press[2][2]) / 3.0; |
168 | > | |
169 | > | return pressure; |
170 | } | |
171 | ||
140 | – | double Thermo::getPressure(){ |
172 | ||
173 | < | // const double conv_Pa_atm = 9.901E-6; // convert Pa -> atm |
174 | < | // const double conv_internal_Pa = 1.661E-7; //convert amu/(fs^2 A) -> Pa |
175 | < | // const double conv_A_m = 1.0E-10; //convert A -> m |
173 | > | void Thermo::getPressureTensor(double press[3][3]){ |
174 | > | // returns pressure tensor in units amu*fs^-2*Ang^-1 |
175 | > | // routine derived via viral theorem description in: |
176 | > | // Paci, E. and Marchi, M. J.Phys.Chem. 1996, 100, 4314-4322 |
177 | ||
178 | < | return 0.0; |
178 | > | const double e_convert = 4.184e-4; |
179 | > | |
180 | > | double molmass, volume; |
181 | > | double vcom[3]; |
182 | > | double p_local[9], p_global[9]; |
183 | > | int i, j, k, l, nMols; |
184 | > | Molecule* molecules; |
185 | > | |
186 | > | nMols = entry_plug->n_mol; |
187 | > | molecules = entry_plug->molecules; |
188 | > | //tau = entry_plug->tau; |
189 | > | |
190 | > | // use velocities of molecular centers of mass and molecular masses: |
191 | > | for (i=0; i < 9; i++) { |
192 | > | p_local[i] = 0.0; |
193 | > | p_global[i] = 0.0; |
194 | > | } |
195 | > | |
196 | > | for (i=0; i < nMols; i++) { |
197 | > | molmass = molecules[i].getCOMvel(vcom); |
198 | > | |
199 | > | p_local[0] += molmass * (vcom[0] * vcom[0]); |
200 | > | p_local[1] += molmass * (vcom[0] * vcom[1]); |
201 | > | p_local[2] += molmass * (vcom[0] * vcom[2]); |
202 | > | p_local[3] += molmass * (vcom[1] * vcom[0]); |
203 | > | p_local[4] += molmass * (vcom[1] * vcom[1]); |
204 | > | p_local[5] += molmass * (vcom[1] * vcom[2]); |
205 | > | p_local[6] += molmass * (vcom[2] * vcom[0]); |
206 | > | p_local[7] += molmass * (vcom[2] * vcom[1]); |
207 | > | p_local[8] += molmass * (vcom[2] * vcom[2]); |
208 | > | } |
209 | > | |
210 | > | // Get total for entire system from MPI. |
211 | > | |
212 | > | #ifdef IS_MPI |
213 | > | MPI_Allreduce(p_local,p_global,9,MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); |
214 | > | #else |
215 | > | for (i=0; i<9; i++) { |
216 | > | p_global[i] = p_local[i]; |
217 | > | } |
218 | > | #endif // is_mpi |
219 | > | |
220 | > | volume = entry_plug->boxVol; |
221 | > | |
222 | > | for(i = 0; i < 3; i++) { |
223 | > | for (j = 0; j < 3; j++) { |
224 | > | k = 3*i + j; |
225 | > | l = 3*j + i; |
226 | > | press[i][j] = (p_global[k] - entry_plug->tau[l]*e_convert) / volume; |
227 | > | } |
228 | > | } |
229 | } | |
230 | ||
231 | void Thermo::velocitize() { | |
232 | ||
233 | double x,y; | |
234 | < | double vx, vy, vz; |
235 | < | double jx, jy, jz; |
154 | < | int i, vr, vd; // velocity randomizer loop counters |
234 | > | double aVel[3], aJ[3], I[3][3]; |
235 | > | int i, j, vr, vd; // velocity randomizer loop counters |
236 | double vdrift[3]; | |
237 | double vbar; | |
238 | const double kb = 8.31451e-7; // kb in amu, angstroms, fs, etc. | |
239 | double av2; | |
240 | double kebar; | |
160 | – | int ndf, ndf_local; // number of degrees of freedom |
161 | – | int ndfRaw, ndfRaw_local; // the raw number of degrees of freedom |
241 | int n_atoms; | |
242 | Atom** atoms; | |
243 | DirectionalAtom* dAtom; | |
# | Line 172 | Line 251 | void Thermo::velocitize() { | |
251 | n_oriented = entry_plug->n_oriented; | |
252 | n_constraints = entry_plug->n_constraints; | |
253 | ||
254 | < | // Raw degrees of freedom that we have to set |
255 | < | ndfRaw_local = 3 * entry_plug->n_atoms + 3 * entry_plug->n_oriented; |
177 | < | |
178 | < | // Degrees of freedom that can contain kinetic energy |
179 | < | ndf_local = 3 * entry_plug->n_atoms + 3 * entry_plug->n_oriented |
180 | < | - entry_plug->n_constraints; |
254 | > | kebar = kb * temperature * (double)entry_plug->ndf / |
255 | > | ( 2.0 * (double)entry_plug->ndfRaw ); |
256 | ||
182 | – | #ifdef IS_MPI |
183 | – | MPI::COMM_WORLD.Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM); |
184 | – | MPI::COMM_WORLD.Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM); |
185 | – | #else |
186 | – | ndfRaw = ndfRaw_local; |
187 | – | ndf = ndf_local; |
188 | – | #endif |
189 | – | ndf = ndf - 3; |
190 | – | |
191 | – | kebar = kb * temperature * (double)ndf / ( 2.0 * (double)ndfRaw ); |
192 | – | |
257 | for(vr = 0; vr < n_atoms; vr++){ | |
258 | ||
259 | // uses equipartition theory to solve for vbar in angstrom/fs | |
260 | ||
261 | av2 = 2.0 * kebar / atoms[vr]->getMass(); | |
262 | vbar = sqrt( av2 ); | |
263 | < | |
263 | > | |
264 | // vbar = sqrt( 8.31451e-7 * temperature / atoms[vr]->getMass() ); | |
265 | ||
266 | // picks random velocities from a gaussian distribution | |
267 | // centered on vbar | |
268 | ||
269 | < | vx = vbar * gaussStream->getGaussian(); |
270 | < | vy = vbar * gaussStream->getGaussian(); |
271 | < | vz = vbar * gaussStream->getGaussian(); |
269 | > | for (j=0; j<3; j++) |
270 | > | aVel[j] = vbar * gaussStream->getGaussian(); |
271 | > | |
272 | > | atoms[vr]->setVel( aVel ); |
273 | ||
209 | – | atoms[vr]->set_vx( vx ); |
210 | – | atoms[vr]->set_vy( vy ); |
211 | – | atoms[vr]->set_vz( vz ); |
274 | } | |
275 | ||
276 | // Get the Center of Mass drift velocity. | |
# | Line 220 | Line 282 | void Thermo::velocitize() { | |
282 | ||
283 | for(vd = 0; vd < n_atoms; vd++){ | |
284 | ||
285 | < | vx = atoms[vd]->get_vx(); |
224 | < | vy = atoms[vd]->get_vy(); |
225 | < | vz = atoms[vd]->get_vz(); |
226 | < | |
227 | < | vx -= vdrift[0]; |
228 | < | vy -= vdrift[1]; |
229 | < | vz -= vdrift[2]; |
285 | > | atoms[vd]->getVel(aVel); |
286 | ||
287 | < | atoms[vd]->set_vx(vx); |
288 | < | atoms[vd]->set_vy(vy); |
289 | < | atoms[vd]->set_vz(vz); |
287 | > | for (j=0; j < 3; j++) |
288 | > | aVel[j] -= vdrift[j]; |
289 | > | |
290 | > | atoms[vd]->setVel( aVel ); |
291 | } | |
292 | if( n_oriented ){ | |
293 | ||
# | Line 239 | Line 296 | void Thermo::velocitize() { | |
296 | if( atoms[i]->isDirectional() ){ | |
297 | ||
298 | dAtom = (DirectionalAtom *)atoms[i]; | |
299 | + | dAtom->getI( I ); |
300 | + | |
301 | + | for (j = 0 ; j < 3; j++) { |
302 | ||
303 | < | vbar = sqrt( 2.0 * kebar * dAtom->getIxx() ); |
304 | < | jx = vbar * gaussStream->getGaussian(); |
303 | > | vbar = sqrt( 2.0 * kebar * I[j][j] ); |
304 | > | aJ[j] = vbar * gaussStream->getGaussian(); |
305 | ||
306 | < | vbar = sqrt( 2.0 * kebar * dAtom->getIyy() ); |
247 | < | jy = vbar * gaussStream->getGaussian(); |
306 | > | } |
307 | ||
308 | < | vbar = sqrt( 2.0 * kebar * dAtom->getIzz() ); |
309 | < | jz = vbar * gaussStream->getGaussian(); |
251 | < | |
252 | < | dAtom->setJx( jx ); |
253 | < | dAtom->setJy( jy ); |
254 | < | dAtom->setJz( jz ); |
308 | > | dAtom->setJ( aJ ); |
309 | > | |
310 | } | |
311 | } | |
312 | } | |
# | Line 260 | Line 315 | void Thermo::getCOMVel(double vdrift[3]){ | |
315 | void Thermo::getCOMVel(double vdrift[3]){ | |
316 | ||
317 | double mtot, mtot_local; | |
318 | + | double aVel[3], amass; |
319 | double vdrift_local[3]; | |
320 | < | int vd, n_atoms; |
320 | > | int vd, n_atoms, j; |
321 | Atom** atoms; | |
322 | ||
323 | // We are very careless here with the distinction between n_atoms and n_local | |
# | Line 277 | Line 333 | void Thermo::getCOMVel(double vdrift[3]){ | |
333 | ||
334 | for(vd = 0; vd < n_atoms; vd++){ | |
335 | ||
336 | < | vdrift_local[0] += atoms[vd]->get_vx() * atoms[vd]->getMass(); |
337 | < | vdrift_local[1] += atoms[vd]->get_vy() * atoms[vd]->getMass(); |
338 | < | vdrift_local[2] += atoms[vd]->get_vz() * atoms[vd]->getMass(); |
336 | > | amass = atoms[vd]->getMass(); |
337 | > | atoms[vd]->getVel( aVel ); |
338 | > | |
339 | > | for(j = 0; j < 3; j++) |
340 | > | vdrift_local[j] += aVel[j] * amass; |
341 | ||
342 | < | mtot_local += atoms[vd]->getMass(); |
342 | > | mtot_local += amass; |
343 | } | |
344 | ||
345 | #ifdef IS_MPI | |
346 | < | MPI::COMM_WORLD.Allreduce(&mtot_local,&mtot,1,MPI_DOUBLE,MPI_SUM); |
347 | < | MPI::COMM_WORLD.Allreduce(vdrift_local,vdrift,3,MPI_DOUBLE,MPI_SUM); |
346 | > | MPI_Allreduce(&mtot_local,&mtot,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); |
347 | > | MPI_Allreduce(vdrift_local,vdrift,3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); |
348 | #else | |
349 | mtot = mtot_local; | |
350 | for(vd = 0; vd < 3; vd++) { |
– | Removed lines |
+ | Added lines |
< | Changed lines |
> | Changed lines |