ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Thermo.cpp
Revision: 428
Committed: Thu Mar 27 21:07:14 2003 UTC (21 years, 3 months ago) by mmeineke
File size: 7035 byte(s)
Log Message:
fixed the compile time bugs, Source builds and links

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