# | 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" | |
# | Line 34 | 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 52 | 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 | ||
56 | – | vx2 = atoms[kl]->get_vx() * atoms[kl]->get_vx(); |
57 | – | vy2 = atoms[kl]->get_vy() * atoms[kl]->get_vy(); |
58 | – | vz2 = atoms[kl]->get_vz() * atoms[kl]->get_vz(); |
59 | – | |
60 | – | v_sqr = vx2 + vy2 + vz2; |
61 | – | kinetic += atoms[kl]->getMass() * v_sqr; |
62 | – | |
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(); |
69 | < | jz2 = dAtom->getJz() * dAtom->getJz(); |
68 | > | for (j=0; j<3; j++) |
69 | > | kinetic += aJ[j]*aJ[j] / I[j][j]; |
70 | ||
71 | – | kinetic += (jx2 / dAtom->getIxx()) + (jy2 / dAtom->getIyy()) |
72 | – | + (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 100 | Line 99 | double Thermo::getPotential(){ | |
99 | potential_local += molecules[el].getPotential(); | |
100 | } | |
101 | ||
103 | – | #ifdef IS_MPI |
104 | – | /* |
105 | – | std::cerr << "node " << worldRank << ": before LONG RANGE pot = " << entry_plug->lrPot |
106 | – | << "; pot_local = " << potential_local |
107 | – | << "; pot = " << potential << "\n"; |
108 | – | */ |
109 | – | #endif |
110 | – | |
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 | |
# | Line 136 | Line 128 | double Thermo::getTemperature(){ | |
128 | ||
129 | const double kb = 1.9872179E-3; // boltzman's constant in kcal/(mol K) | |
130 | double temperature; | |
139 | – | 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 |
145 | < | MPI::COMM_WORLD.Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM); |
146 | < | #else |
147 | < | ndf = ndf_local; |
148 | < | #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 | ||
156 | – | 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 = this->getVolume(); |
221 | > | |
222 | > | for(i = 0; i < 3; i++) { |
223 | > | for (j = 0; j < 3; j++) { |
224 | > | k = 3*i + j; |
225 | > | press[i][j] = (p_global[k] + entry_plug->tau[k]*e_convert) / volume; |
226 | > | } |
227 | > | } |
228 | } | |
229 | ||
230 | void Thermo::velocitize() { | |
231 | ||
232 | double x,y; | |
233 | < | double vx, vy, vz; |
234 | < | double jx, jy, jz; |
170 | < | int i, vr, vd; // velocity randomizer loop counters |
233 | > | double aVel[3], aJ[3], I[3][3]; |
234 | > | int i, j, vr, vd; // velocity randomizer loop counters |
235 | double vdrift[3]; | |
236 | double vbar; | |
237 | const double kb = 8.31451e-7; // kb in amu, angstroms, fs, etc. | |
238 | double av2; | |
239 | double kebar; | |
176 | – | int ndf, ndf_local; // number of degrees of freedom |
177 | – | int ndfRaw, ndfRaw_local; // the raw number of degrees of freedom |
240 | int n_atoms; | |
241 | Atom** atoms; | |
242 | DirectionalAtom* dAtom; | |
# | Line 188 | Line 250 | void Thermo::velocitize() { | |
250 | n_oriented = entry_plug->n_oriented; | |
251 | n_constraints = entry_plug->n_constraints; | |
252 | ||
253 | < | // Raw degrees of freedom that we have to set |
254 | < | ndfRaw_local = 3 * entry_plug->n_atoms + 3 * entry_plug->n_oriented; |
193 | < | |
194 | < | // Degrees of freedom that can contain kinetic energy |
195 | < | ndf_local = 3 * entry_plug->n_atoms + 3 * entry_plug->n_oriented |
196 | < | - entry_plug->n_constraints; |
253 | > | kebar = kb * temperature * (double)entry_plug->ndf / |
254 | > | ( 2.0 * (double)entry_plug->ndfRaw ); |
255 | ||
198 | – | #ifdef IS_MPI |
199 | – | MPI::COMM_WORLD.Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM); |
200 | – | MPI::COMM_WORLD.Allreduce(&ndfRaw_local,&ndfRaw,1,MPI_INT,MPI_SUM); |
201 | – | #else |
202 | – | ndfRaw = ndfRaw_local; |
203 | – | ndf = ndf_local; |
204 | – | #endif |
205 | – | ndf = ndf - 3; |
206 | – | |
207 | – | kebar = kb * temperature * (double)ndf / ( 2.0 * (double)ndfRaw ); |
208 | – | |
256 | for(vr = 0; vr < n_atoms; vr++){ | |
257 | ||
258 | // uses equipartition theory to solve for vbar in angstrom/fs | |
# | Line 218 | Line 265 | void Thermo::velocitize() { | |
265 | // picks random velocities from a gaussian distribution | |
266 | // centered on vbar | |
267 | ||
268 | < | vx = vbar * gaussStream->getGaussian(); |
269 | < | vy = vbar * gaussStream->getGaussian(); |
270 | < | vz = vbar * gaussStream->getGaussian(); |
268 | > | for (j=0; j<3; j++) |
269 | > | aVel[j] = vbar * gaussStream->getGaussian(); |
270 | > | |
271 | > | atoms[vr]->setVel( aVel ); |
272 | ||
225 | – | atoms[vr]->set_vx( vx ); |
226 | – | atoms[vr]->set_vy( vy ); |
227 | – | atoms[vr]->set_vz( vz ); |
273 | } | |
274 | ||
275 | // Get the Center of Mass drift velocity. | |
# | Line 236 | Line 281 | void Thermo::velocitize() { | |
281 | ||
282 | for(vd = 0; vd < n_atoms; vd++){ | |
283 | ||
284 | < | vx = atoms[vd]->get_vx(); |
240 | < | vy = atoms[vd]->get_vy(); |
241 | < | vz = atoms[vd]->get_vz(); |
242 | < | |
243 | < | vx -= vdrift[0]; |
244 | < | vy -= vdrift[1]; |
245 | < | vz -= vdrift[2]; |
284 | > | atoms[vd]->getVel(aVel); |
285 | ||
286 | < | atoms[vd]->set_vx(vx); |
287 | < | atoms[vd]->set_vy(vy); |
288 | < | atoms[vd]->set_vz(vz); |
286 | > | for (j=0; j < 3; j++) |
287 | > | aVel[j] -= vdrift[j]; |
288 | > | |
289 | > | atoms[vd]->setVel( aVel ); |
290 | } | |
291 | if( n_oriented ){ | |
292 | ||
# | Line 255 | Line 295 | void Thermo::velocitize() { | |
295 | if( atoms[i]->isDirectional() ){ | |
296 | ||
297 | dAtom = (DirectionalAtom *)atoms[i]; | |
298 | + | dAtom->getI( I ); |
299 | + | |
300 | + | for (j = 0 ; j < 3; j++) { |
301 | ||
302 | < | vbar = sqrt( 2.0 * kebar * dAtom->getIxx() ); |
303 | < | jx = vbar * gaussStream->getGaussian(); |
302 | > | vbar = sqrt( 2.0 * kebar * I[j][j] ); |
303 | > | aJ[j] = vbar * gaussStream->getGaussian(); |
304 | ||
305 | < | vbar = sqrt( 2.0 * kebar * dAtom->getIyy() ); |
263 | < | jy = vbar * gaussStream->getGaussian(); |
305 | > | } |
306 | ||
307 | < | vbar = sqrt( 2.0 * kebar * dAtom->getIzz() ); |
308 | < | jz = vbar * gaussStream->getGaussian(); |
267 | < | |
268 | < | dAtom->setJx( jx ); |
269 | < | dAtom->setJy( jy ); |
270 | < | dAtom->setJz( jz ); |
307 | > | dAtom->setJ( aJ ); |
308 | > | |
309 | } | |
310 | } | |
311 | } | |
# | Line 276 | Line 314 | void Thermo::getCOMVel(double vdrift[3]){ | |
314 | void Thermo::getCOMVel(double vdrift[3]){ | |
315 | ||
316 | double mtot, mtot_local; | |
317 | + | double aVel[3], amass; |
318 | double vdrift_local[3]; | |
319 | < | int vd, n_atoms; |
319 | > | int vd, n_atoms, j; |
320 | Atom** atoms; | |
321 | ||
322 | // We are very careless here with the distinction between n_atoms and n_local | |
# | Line 293 | Line 332 | void Thermo::getCOMVel(double vdrift[3]){ | |
332 | ||
333 | for(vd = 0; vd < n_atoms; vd++){ | |
334 | ||
335 | < | vdrift_local[0] += atoms[vd]->get_vx() * atoms[vd]->getMass(); |
336 | < | vdrift_local[1] += atoms[vd]->get_vy() * atoms[vd]->getMass(); |
337 | < | vdrift_local[2] += atoms[vd]->get_vz() * atoms[vd]->getMass(); |
335 | > | amass = atoms[vd]->getMass(); |
336 | > | atoms[vd]->getVel( aVel ); |
337 | > | |
338 | > | for(j = 0; j < 3; j++) |
339 | > | vdrift_local[j] += aVel[j] * amass; |
340 | ||
341 | < | mtot_local += atoms[vd]->getMass(); |
341 | > | mtot_local += amass; |
342 | } | |
343 | ||
344 | #ifdef IS_MPI | |
345 | < | MPI::COMM_WORLD.Allreduce(&mtot_local,&mtot,1,MPI_DOUBLE,MPI_SUM); |
346 | < | MPI::COMM_WORLD.Allreduce(vdrift_local,vdrift,3,MPI_DOUBLE,MPI_SUM); |
345 | > | MPI_Allreduce(&mtot_local,&mtot,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); |
346 | > | MPI_Allreduce(vdrift_local,vdrift,3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD); |
347 | #else | |
348 | mtot = mtot_local; | |
349 | for(vd = 0; vd < 3; vd++) { |
– | Removed lines |
+ | Added lines |
< | Changed lines |
> | Changed lines |