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

# User Rev Content
1 mmeineke 377 #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 chuckv 401 #define __C
14     //#include "mpiSimulation.hpp"
15 mmeineke 377
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 chuckv 401 double potential_local;
83 mmeineke 377 double potential;
84     int el, nSRI;
85     SRI** sris;
86    
87     sris = entry_plug->sr_interactions;
88     nSRI = entry_plug->n_SRI;
89    
90 chuckv 401 potential_local = 0.0;
91     potential_local += entry_plug->lrPot;
92 mmeineke 377
93 chuckv 401 for( el=0; el<nSRI; el++ ){
94     potential_local += sris[el]->get_potential();
95 mmeineke 377 }
96    
97     // Get total potential for entire system from MPI.
98     #ifdef IS_MPI
99 chuckv 401 MPI::COMM_WORLD.Allreduce(&potential_local,&potential,1,MPI_DOUBLE,MPI_SUM);
100     #else
101     potential = potential_local;
102 mmeineke 377 #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 chuckv 401 int ndf_local, ndf;
120 mmeineke 377
121 chuckv 401 ndf_local = 3 * entry_plug->n_atoms + 3 * entry_plug->n_oriented
122     - entry_plug->n_constraints;
123 mmeineke 377
124 chuckv 401 #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 mmeineke 377 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 chuckv 401 double *vdrift;
152 mmeineke 377 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 chuckv 401
197     // Get the Center of Mass drift velocity.
198    
199     vdrift = getCOMVel();
200 mmeineke 377
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 chuckv 401
210 mmeineke 377 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 chuckv 401
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