ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Thermo.cpp
Revision: 708
Committed: Wed Aug 20 22:23:34 2003 UTC (20 years, 10 months ago) by tim
File size: 7589 byte(s)
Log Message:
user can setup seed in bass file now, if he does not specify any value for
seed, oopse will take the value of seconds of system time as seed

File Contents

# Content
1 #include <cmath>
2 #include <iostream>
3 using namespace std;
4
5 #ifdef IS_MPI
6 #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
16 #include "mpiSimulation.hpp"
17 #endif // is_mpi
18
19 Thermo::Thermo( SimInfo* the_info ) {
20 info = the_info;
21 int baseSeed = the_info->getSeed();
22
23 gaussStream = new gaussianSPRNG( baseSeed );
24 }
25
26 Thermo::~Thermo(){
27 delete gaussStream;
28 }
29
30 double Thermo::getKinetic(){
31
32 const double e_convert = 4.184E-4; // convert kcal/mol -> (amu A^2)/fs^2
33 double kinetic;
34 double amass;
35 double aVel[3], aJ[3], I[3][3];
36 int j, kl;
37
38 DirectionalAtom *dAtom;
39
40 int n_atoms;
41 double kinetic_global;
42 Atom** atoms;
43
44
45 n_atoms = info->n_atoms;
46 atoms = info->atoms;
47
48 kinetic = 0.0;
49 kinetic_global = 0.0;
50 for( kl=0; kl < n_atoms; kl++ ){
51
52 atoms[kl]->getVel(aVel);
53 amass = atoms[kl]->getMass();
54
55 for (j=0; j < 3; j++)
56 kinetic += amass * aVel[j] * aVel[j];
57
58 if( atoms[kl]->isDirectional() ){
59
60 dAtom = (DirectionalAtom *)atoms[kl];
61
62 dAtom->getJ( aJ );
63 dAtom->getI( I );
64
65 for (j=0; j<3; j++)
66 kinetic += aJ[j]*aJ[j] / I[j][j];
67
68 }
69 }
70 #ifdef IS_MPI
71 MPI_Allreduce(&kinetic,&kinetic_global,1,MPI_DOUBLE,
72 MPI_SUM, MPI_COMM_WORLD);
73 kinetic = kinetic_global;
74 #endif //is_mpi
75
76 kinetic = kinetic * 0.5 / e_convert;
77
78 return kinetic;
79 }
80
81 double Thermo::getPotential(){
82
83 double potential_local;
84 double potential;
85 int el, nSRI;
86 Molecule* molecules;
87
88 molecules = info->molecules;
89 nSRI = info->n_SRI;
90
91 potential_local = 0.0;
92 potential = 0.0;
93 potential_local += info->lrPot;
94
95 for( el=0; el<info->n_mol; el++ ){
96 potential_local += molecules[el].getPotential();
97 }
98
99 // Get total potential for entire system from MPI.
100 #ifdef IS_MPI
101 MPI_Allreduce(&potential_local,&potential,1,MPI_DOUBLE,
102 MPI_SUM, MPI_COMM_WORLD);
103 #else
104 potential = potential_local;
105 #endif // is_mpi
106
107 #ifdef IS_MPI
108 /*
109 std::cerr << "node " << worldRank << ": after pot = " << potential << "\n";
110 */
111 #endif
112
113 return potential;
114 }
115
116 double Thermo::getTotalE(){
117
118 double total;
119
120 total = this->getKinetic() + this->getPotential();
121 return total;
122 }
123
124 double Thermo::getTemperature(){
125
126 const double kb = 1.9872179E-3; // boltzman's constant in kcal/(mol K)
127 double temperature;
128
129 temperature = ( 2.0 * this->getKinetic() ) / ((double)info->ndf * kb );
130 return temperature;
131 }
132
133 double Thermo::getEnthalpy() {
134
135 const double e_convert = 4.184E-4; // convert kcal/mol -> (amu A^2)/fs^2
136 double u, p, v;
137 double press[3][3];
138
139 u = this->getTotalE();
140
141 this->getPressureTensor(press);
142 p = (press[0][0] + press[1][1] + press[2][2]) / 3.0;
143
144 v = this->getVolume();
145
146 return (u + (p*v)/e_convert);
147 }
148
149 double Thermo::getVolume() {
150
151 return info->boxVol;
152 }
153
154 double Thermo::getPressure() {
155
156 // Relies on the calculation of the full molecular pressure tensor
157
158 const double p_convert = 1.63882576e8;
159 double press[3][3];
160 double pressure;
161
162 this->getPressureTensor(press);
163
164 pressure = p_convert * (press[0][0] + press[1][1] + press[2][2]) / 3.0;
165
166 return pressure;
167 }
168
169
170 void Thermo::getPressureTensor(double press[3][3]){
171 // returns pressure tensor in units amu*fs^-2*Ang^-1
172 // routine derived via viral theorem description in:
173 // Paci, E. and Marchi, M. J.Phys.Chem. 1996, 100, 4314-4322
174
175 const double e_convert = 4.184e-4;
176
177 double molmass, volume;
178 double vcom[3];
179 double p_local[9], p_global[9];
180 int i, j, k, nMols;
181 Molecule* molecules;
182
183 nMols = info->n_mol;
184 molecules = info->molecules;
185 //tau = info->tau;
186
187 // use velocities of molecular centers of mass and molecular masses:
188 for (i=0; i < 9; i++) {
189 p_local[i] = 0.0;
190 p_global[i] = 0.0;
191 }
192
193 for (i=0; i < nMols; i++) {
194 molmass = molecules[i].getCOMvel(vcom);
195
196 p_local[0] += molmass * (vcom[0] * vcom[0]);
197 p_local[1] += molmass * (vcom[0] * vcom[1]);
198 p_local[2] += molmass * (vcom[0] * vcom[2]);
199 p_local[3] += molmass * (vcom[1] * vcom[0]);
200 p_local[4] += molmass * (vcom[1] * vcom[1]);
201 p_local[5] += molmass * (vcom[1] * vcom[2]);
202 p_local[6] += molmass * (vcom[2] * vcom[0]);
203 p_local[7] += molmass * (vcom[2] * vcom[1]);
204 p_local[8] += molmass * (vcom[2] * vcom[2]);
205 }
206
207 // Get total for entire system from MPI.
208
209 #ifdef IS_MPI
210 MPI_Allreduce(p_local,p_global,9,MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
211 #else
212 for (i=0; i<9; i++) {
213 p_global[i] = p_local[i];
214 }
215 #endif // is_mpi
216
217 volume = this->getVolume();
218
219 for(i = 0; i < 3; i++) {
220 for (j = 0; j < 3; j++) {
221 k = 3*i + j;
222 press[i][j] = (p_global[k] + info->tau[k]*e_convert) / volume;
223
224 }
225 }
226 }
227
228 void Thermo::velocitize() {
229
230 double x,y;
231 double aVel[3], aJ[3], I[3][3];
232 int i, j, vr, vd; // velocity randomizer loop counters
233 double vdrift[3];
234 double vbar;
235 const double kb = 8.31451e-7; // kb in amu, angstroms, fs, etc.
236 double av2;
237 double kebar;
238 int n_atoms;
239 Atom** atoms;
240 DirectionalAtom* dAtom;
241 double temperature;
242 int n_oriented;
243 int n_constraints;
244
245 atoms = info->atoms;
246 n_atoms = info->n_atoms;
247 temperature = info->target_temp;
248 n_oriented = info->n_oriented;
249 n_constraints = info->n_constraints;
250
251 kebar = kb * temperature * (double)info->ndf /
252 ( 2.0 * (double)info->ndfRaw );
253
254 for(vr = 0; vr < n_atoms; vr++){
255
256 // uses equipartition theory to solve for vbar in angstrom/fs
257
258 av2 = 2.0 * kebar / atoms[vr]->getMass();
259 vbar = sqrt( av2 );
260
261 // vbar = sqrt( 8.31451e-7 * temperature / atoms[vr]->getMass() );
262
263 // picks random velocities from a gaussian distribution
264 // centered on vbar
265
266 for (j=0; j<3; j++)
267 aVel[j] = vbar * gaussStream->getGaussian();
268
269 atoms[vr]->setVel( aVel );
270
271 }
272
273 // Get the Center of Mass drift velocity.
274
275 getCOMVel(vdrift);
276
277 // Corrects for the center of mass drift.
278 // sums all the momentum and divides by total mass.
279
280 for(vd = 0; vd < n_atoms; vd++){
281
282 atoms[vd]->getVel(aVel);
283
284 for (j=0; j < 3; j++)
285 aVel[j] -= vdrift[j];
286
287 atoms[vd]->setVel( aVel );
288 }
289 if( n_oriented ){
290
291 for( i=0; i<n_atoms; i++ ){
292
293 if( atoms[i]->isDirectional() ){
294
295 dAtom = (DirectionalAtom *)atoms[i];
296 dAtom->getI( I );
297
298 for (j = 0 ; j < 3; j++) {
299
300 vbar = sqrt( 2.0 * kebar * I[j][j] );
301 aJ[j] = vbar * gaussStream->getGaussian();
302
303 }
304
305 dAtom->setJ( aJ );
306
307 }
308 }
309 }
310 }
311
312 void Thermo::getCOMVel(double vdrift[3]){
313
314 double mtot, mtot_local;
315 double aVel[3], amass;
316 double vdrift_local[3];
317 int vd, n_atoms, j;
318 Atom** atoms;
319
320 // We are very careless here with the distinction between n_atoms and n_local
321 // We should really fix this before someone pokes an eye out.
322
323 n_atoms = info->n_atoms;
324 atoms = info->atoms;
325
326 mtot_local = 0.0;
327 vdrift_local[0] = 0.0;
328 vdrift_local[1] = 0.0;
329 vdrift_local[2] = 0.0;
330
331 for(vd = 0; vd < n_atoms; vd++){
332
333 amass = atoms[vd]->getMass();
334 atoms[vd]->getVel( aVel );
335
336 for(j = 0; j < 3; j++)
337 vdrift_local[j] += aVel[j] * amass;
338
339 mtot_local += amass;
340 }
341
342 #ifdef IS_MPI
343 MPI_Allreduce(&mtot_local,&mtot,1,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
344 MPI_Allreduce(vdrift_local,vdrift,3,MPI_DOUBLE,MPI_SUM, MPI_COMM_WORLD);
345 #else
346 mtot = mtot_local;
347 for(vd = 0; vd < 3; vd++) {
348 vdrift[vd] = vdrift_local[vd];
349 }
350 #endif
351
352 for (vd = 0; vd < 3; vd++) {
353 vdrift[vd] = vdrift[vd] / mtot;
354 }
355
356 }
357