ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Thermo.cpp
Revision: 401
Committed: Tue Mar 25 22:54:16 2003 UTC (21 years, 3 months ago) by chuckv
File size: 6582 byte(s)
Log Message:
Fixed bugs with calculation of potential energy and temperature.

File Contents

# Content
1 #include <cmath>
2 #include <iostream>
3 using namespace std;
4
5 #ifdef IS_MPI
6 #include <mpi.h>
7 #include <mpi++.h>
8 #endif //is_mpi
9
10 #include "Thermo.hpp"
11 #include "SRI.hpp"
12 #include "Integrator.hpp"
13 #define __C
14 //#include "mpiSimulation.hpp"
15
16 #define BASE_SEED 123456789
17
18 Thermo::Thermo( SimInfo* the_entry_plug ) {
19 entry_plug = the_entry_plug;
20 int baseSeed = BASE_SEED;
21
22 gaussStream = new gaussianSPRNG( baseSeed );
23 }
24
25 Thermo::~Thermo(){
26 delete gaussStream;
27 }
28
29 double Thermo::getKinetic(){
30
31 const double e_convert = 4.184E-4; // convert kcal/mol -> (amu A^2)/fs^2
32 double vx2, vy2, vz2;
33 double kinetic, v_sqr;
34 int kl;
35 double jx2, jy2, jz2; // the square of the angular momentums
36
37 DirectionalAtom *dAtom;
38
39 int n_atoms;
40 double kinetic_global;
41 Atom** atoms;
42
43
44 n_atoms = entry_plug->n_atoms;
45 atoms = entry_plug->atoms;
46
47 kinetic = 0.0;
48 kinetic_global = 0.0;
49 for( kl=0; kl < n_atoms; kl++ ){
50
51 vx2 = atoms[kl]->get_vx() * atoms[kl]->get_vx();
52 vy2 = atoms[kl]->get_vy() * atoms[kl]->get_vy();
53 vz2 = atoms[kl]->get_vz() * atoms[kl]->get_vz();
54
55 v_sqr = vx2 + vy2 + vz2;
56 kinetic += atoms[kl]->getMass() * v_sqr;
57
58 if( atoms[kl]->isDirectional() ){
59
60 dAtom = (DirectionalAtom *)atoms[kl];
61
62 jx2 = dAtom->getJx() * dAtom->getJx();
63 jy2 = dAtom->getJy() * dAtom->getJy();
64 jz2 = dAtom->getJz() * dAtom->getJz();
65
66 kinetic += (jx2 / dAtom->getIxx()) + (jy2 / dAtom->getIyy())
67 + (jz2 / dAtom->getIzz());
68 }
69 }
70 #ifdef IS_MPI
71 MPI::COMM_WORLD.Allreduce(&kinetic,&kinetic_global,1,MPI_DOUBLE,MPI_SUM);
72 kinetic = kinetic_global;
73 #endif //is_mpi
74
75 kinetic = kinetic * 0.5 / e_convert;
76
77 return kinetic;
78 }
79
80 double Thermo::getPotential(){
81
82 double potential_local;
83 double potential;
84 int el, nSRI;
85 SRI** sris;
86
87 sris = entry_plug->sr_interactions;
88 nSRI = entry_plug->n_SRI;
89
90 potential_local = 0.0;
91 potential_local += entry_plug->lrPot;
92
93 for( el=0; el<nSRI; el++ ){
94 potential_local += sris[el]->get_potential();
95 }
96
97 // Get total potential for entire system from MPI.
98 #ifdef IS_MPI
99 MPI::COMM_WORLD.Allreduce(&potential_local,&potential,1,MPI_DOUBLE,MPI_SUM);
100 #else
101 potential = potential_local;
102 #endif // is_mpi
103
104 return potential;
105 }
106
107 double Thermo::getTotalE(){
108
109 double total;
110
111 total = this->getKinetic() + this->getPotential();
112 return total;
113 }
114
115 double Thermo::getTemperature(){
116
117 const double kb = 1.9872179E-3; // boltzman's constant in kcal/(mol K)
118 double temperature;
119 int ndf_local, ndf;
120
121 ndf_local = 3 * entry_plug->n_atoms + 3 * entry_plug->n_oriented
122 - entry_plug->n_constraints;
123
124 #ifdef IS_MPI
125 MPI::COMM_WORLD.Allreduce(&ndf_local,&ndf,1,MPI_INT,MPI_SUM);
126 #else
127 ndf = ndf_local;
128 #endif
129
130 ndf = ndf - 3;
131
132 temperature = ( 2.0 * this->getKinetic() ) / ( ndf * kb );
133 return temperature;
134 }
135
136 double Thermo::getPressure(){
137
138 // const double conv_Pa_atm = 9.901E-6; // convert Pa -> atm
139 // const double conv_internal_Pa = 1.661E-7; //convert amu/(fs^2 A) -> Pa
140 // const double conv_A_m = 1.0E-10; //convert A -> m
141
142 return 0.0;
143 }
144
145 void Thermo::velocitize() {
146
147 double x,y;
148 double vx, vy, vz;
149 double jx, jy, jz;
150 int i, vr, vd; // velocity randomizer loop counters
151 double *vdrift;
152 double vbar;
153 const double kb = 8.31451e-7; // kb in amu, angstroms, fs, etc.
154 double av2;
155 double kebar;
156 int ndf; // number of degrees of freedom
157 int ndfRaw; // the raw number of degrees of freedom
158 int n_atoms;
159 Atom** atoms;
160 DirectionalAtom* dAtom;
161 double temperature;
162 int n_oriented;
163 int n_constraints;
164
165 atoms = entry_plug->atoms;
166 n_atoms = entry_plug->n_atoms;
167 temperature = entry_plug->target_temp;
168 n_oriented = entry_plug->n_oriented;
169 n_constraints = entry_plug->n_constraints;
170
171
172 ndfRaw = 3 * n_atoms + 3 * n_oriented;
173 ndf = ndfRaw - n_constraints - 3;
174 kebar = kb * temperature * (double)ndf / ( 2.0 * (double)ndfRaw );
175
176 for(vr = 0; vr < n_atoms; vr++){
177
178 // uses equipartition theory to solve for vbar in angstrom/fs
179
180 av2 = 2.0 * kebar / atoms[vr]->getMass();
181 vbar = sqrt( av2 );
182
183 // vbar = sqrt( 8.31451e-7 * temperature / atoms[vr]->getMass() );
184
185 // picks random velocities from a gaussian distribution
186 // centered on vbar
187
188 vx = vbar * gaussStream->getGaussian();
189 vy = vbar * gaussStream->getGaussian();
190 vz = vbar * gaussStream->getGaussian();
191
192 atoms[vr]->set_vx( vx );
193 atoms[vr]->set_vy( vy );
194 atoms[vr]->set_vz( vz );
195 }
196
197 // Get the Center of Mass drift velocity.
198
199 vdrift = getCOMVel();
200
201 // Corrects for the center of mass drift.
202 // sums all the momentum and divides by total mass.
203
204 for(vd = 0; vd < n_atoms; vd++){
205
206 vx = atoms[vd]->get_vx();
207 vy = atoms[vd]->get_vy();
208 vz = atoms[vd]->get_vz();
209
210 vx -= vdrift[0];
211 vy -= vdrift[1];
212 vz -= vdrift[2];
213
214 atoms[vd]->set_vx(vx);
215 atoms[vd]->set_vy(vy);
216 atoms[vd]->set_vz(vz);
217 }
218 if( n_oriented ){
219
220 for( i=0; i<n_atoms; i++ ){
221
222 if( atoms[i]->isDirectional() ){
223
224 dAtom = (DirectionalAtom *)atoms[i];
225
226 vbar = sqrt( 2.0 * kebar * dAtom->getIxx() );
227 jx = vbar * gaussStream->getGaussian();
228
229 vbar = sqrt( 2.0 * kebar * dAtom->getIyy() );
230 jy = vbar * gaussStream->getGaussian();
231
232 vbar = sqrt( 2.0 * kebar * dAtom->getIzz() );
233 jz = vbar * gaussStream->getGaussian();
234
235 dAtom->setJx( jx );
236 dAtom->setJy( jy );
237 dAtom->setJz( jz );
238 }
239 }
240 }
241 }
242
243 double* Thermo::getCOMVel(){
244
245 double mtot, mtot_local;
246 double* vdrift;
247 double vdrift_local[3];
248 int vd, n_atoms;
249 Atom** atoms;
250
251 vdrift = new double[3];
252 // We are very careless here with the distinction between n_atoms and n_local
253 // We should really fix this before someone pokes an eye out.
254
255 n_atoms = entry_plug->n_atoms;
256 atoms = entry_plug->atoms;
257
258 mtot_local = 0.0;
259 vdrift_local[0] = 0.0;
260 vdrift_local[1] = 0.0;
261 vdrift_local[2] = 0.0;
262
263 for(vd = 0; vd < n_atoms; vd++){
264
265 vdrift_local[0] += atoms[vd]->get_vx() * atoms[vd]->getMass();
266 vdrift_local[1] += atoms[vd]->get_vy() * atoms[vd]->getMass();
267 vdrift_local[2] += atoms[vd]->get_vz() * atoms[vd]->getMass();
268
269 mtot_local += atoms[vd]->getMass();
270 }
271
272 #ifdef IS_MPI
273 MPI::COMM_WORLD.Allreduce(&mtot_local,&mtot,1,MPI_DOUBLE,MPI_SUM);
274 MPI::COMM_WORLD.Allreduce(&vdrift_local,&vdrift,3,MPI_DOUBLE,MPI_SUM);
275 #else
276 mtot = mtot_local;
277 for(vd = 0; vd < 3; vd++) {
278 vdrift[vd] = vdrift_local[vd];
279 }
280 #endif
281
282 for (vd = 0; vd < 3; vd++) {
283 vdrift[vd] = vdrift[vd] / mtot;
284 }
285
286 return vdrift;
287 }
288