ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTim.cpp
Revision: 611
Committed: Tue Jul 15 17:10:50 2003 UTC (20 years, 11 months ago) by gezelter
File size: 6780 byte(s)
Log Message:
Fixing  pressure tensor

File Contents

# User Rev Content
1 gezelter 596 #include <cmath>
2     #include "Atom.hpp"
3 gezelter 604 #include "Molecule.hpp"
4 gezelter 596 #include "SRI.hpp"
5     #include "AbstractClasses.hpp"
6     #include "SimInfo.hpp"
7     #include "ForceFields.hpp"
8     #include "Thermo.hpp"
9     #include "ReadWrite.hpp"
10     #include "Integrator.hpp"
11     #include "simError.h"
12    
13    
14     // Basic isotropic thermostating and barostating via the Melchionna
15     // modification of the Hoover algorithm:
16     //
17     // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
18     // Molec. Phys., 78, 533.
19     //
20     // and
21     //
22     // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
23    
24     // The NPTim variant scales the molecular center-of-mass coordinates
25     // instead of the atomic coordinates
26    
27     NPTim::NPTim ( SimInfo *theInfo, ForceFields* the_ff):
28     Integrator( theInfo, the_ff )
29     {
30     chi = 0.0;
31     eta = 0.0;
32     have_tau_thermostat = 0;
33     have_tau_barostat = 0;
34     have_target_temp = 0;
35     have_target_pressure = 0;
36     }
37    
38     void NPTim::moveA() {
39    
40 gezelter 605 int i, j, k;
41 gezelter 596 DirectionalAtom* dAtom;
42 gezelter 604 double Tb[3], ji[3];
43     double A[3][3], I[3][3];
44     double angle, mass;
45     double vel[3], pos[3], frc[3];
46    
47     double rj[3];
48 gezelter 596 double instaTemp, instaPress, instaVol;
49 gezelter 611 double tt2, tb2, scaleFactor;
50 gezelter 596
51 gezelter 604 int nInMol;
52     double rc[3];
53    
54 gezelter 596 nMols = info->n_mol;
55 gezelter 604 myMolecules = info->molecules;
56 gezelter 596
57     tt2 = tauThermostat * tauThermostat;
58     tb2 = tauBarostat * tauBarostat;
59    
60     instaTemp = tStats->getTemperature();
61     instaPress = tStats->getPressure();
62     instaVol = tStats->getVolume();
63    
64     // first evolve chi a half step
65    
66     chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
67     eta += dt2 * ( instaVol * (instaPress - targetPressure) /
68     (p_convert*NkBT*tb2));
69    
70     for( i = 0; i < nMols; i++) {
71    
72 gezelter 604 myMolecules[i].getCOM(rc);
73 gezelter 596
74 gezelter 604 nInMol = myMolecules[i].getNAtoms();
75     myAtoms = myMolecules[i].getMyAtoms();
76 gezelter 596
77     // find the minimum image coordinates of the molecular centers of mass:
78    
79     info->wrapVector(rc);
80    
81     for (j = 0; j < nInMol; j++) {
82    
83 gezelter 604 if(myAtoms[j] != NULL) {
84 gezelter 596
85 gezelter 605 myAtoms[j]->getVel( vel );
86     myAtoms[j]->getPos( pos );
87     myAtoms[j]->getFrc( frc );
88 gezelter 596
89 gezelter 605 mass = myAtoms[j]->getMass();
90 gezelter 596
91 gezelter 605 for (k=0; k < 3; k++)
92     vel[k] += dt2 * ((frc[k] / mass ) * eConvert - vel[k]*(chi+eta));
93 gezelter 596
94 gezelter 605 myAtoms[j]->setVel( vel );
95 gezelter 596
96 gezelter 605 for (k = 0; k < 3; k++)
97     pos[k] += dt * (vel[k] + eta*rc[k]);
98 gezelter 596
99 gezelter 605 myAtoms[j]->setPos( pos );
100 gezelter 596
101 gezelter 604 if( myAtoms[j]->isDirectional() ){
102 gezelter 596
103 gezelter 604 dAtom = (DirectionalAtom *)myAtoms[j];
104 gezelter 596
105     // get and convert the torque to body frame
106 gezelter 604
107     dAtom->getTrq( Tb );
108 gezelter 596 dAtom->lab2Body( Tb );
109 gezelter 604
110 gezelter 596 // get the angular momentum, and propagate a half step
111    
112 gezelter 604 dAtom->getJ( ji );
113    
114 gezelter 605 for (k=0; k < 3; k++)
115     ji[k] += dt2 * (Tb[k] * eConvert - ji[k]*chi);
116 gezelter 596
117     // use the angular velocities to propagate the rotation matrix a
118     // full time step
119    
120 gezelter 604 dAtom->getA(A);
121     dAtom->getI(I);
122    
123 gezelter 596 // rotate about the x-axis
124 gezelter 604 angle = dt2 * ji[0] / I[0][0];
125     this->rotate( 1, 2, angle, ji, A );
126 gezelter 596
127     // rotate about the y-axis
128 gezelter 604 angle = dt2 * ji[1] / I[1][1];
129     this->rotate( 2, 0, angle, ji, A );
130 gezelter 596
131     // rotate about the z-axis
132 gezelter 604 angle = dt * ji[2] / I[2][2];
133     this->rotate( 0, 1, angle, ji, A);
134 gezelter 596
135     // rotate about the y-axis
136 gezelter 604 angle = dt2 * ji[1] / I[1][1];
137     this->rotate( 2, 0, angle, ji, A );
138 gezelter 596
139     // rotate about the x-axis
140 gezelter 604 angle = dt2 * ji[0] / I[0][0];
141     this->rotate( 1, 2, angle, ji, A );
142 gezelter 596
143 gezelter 604 dAtom->setJ( ji );
144     dAtom->setA( A );
145     }
146 gezelter 596 }
147     }
148     }
149 gezelter 611
150 gezelter 596 // Scale the box after all the positions have been moved:
151    
152 gezelter 611 scaleFactor = exp(dt*eta);
153    
154     if (scaleFactor > 1.1 || scaleFactor < 0.9) {
155     sprintf( painCave.errMsg,
156     "NPTi error: Attempting a Box scaling of more than 10 percent"
157     " check your tauBarostat, as it is probably too small!\n"
158     " eta = %lf, scaleFactor = %lf\n", eta, scaleFactor
159     );
160     painCave.isFatal = 1;
161     simError();
162     } else {
163     info->scaleBox(exp(dt*eta));
164     }
165 gezelter 596 }
166    
167 gezelter 604 void NPTim::moveB( void ){
168     int i, j;
169 gezelter 596 DirectionalAtom* dAtom;
170 gezelter 604 double Tb[3], ji[3];
171     double vel[3], frc[3];
172     double mass;
173    
174 gezelter 596 double instaTemp, instaPress, instaVol;
175     double tt2, tb2;
176 gezelter 604
177 gezelter 596 tt2 = tauThermostat * tauThermostat;
178     tb2 = tauBarostat * tauBarostat;
179    
180     instaTemp = tStats->getTemperature();
181     instaPress = tStats->getPressure();
182     instaVol = tStats->getVolume();
183    
184     chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
185     eta += dt2 * ( instaVol * (instaPress - targetPressure) /
186     (p_convert*NkBT*tb2));
187    
188     for( i=0; i<nAtoms; i++ ){
189    
190 gezelter 604 atoms[i]->getVel( vel );
191     atoms[i]->getFrc( frc );
192    
193     mass = atoms[i]->getMass();
194    
195 gezelter 596 // velocity half step
196 gezelter 604 for (j=0; j < 3; j++)
197     vel[j] += dt2 * ((frc[j] / mass ) * eConvert - vel[j]*(chi+eta));
198 gezelter 596
199 gezelter 604 atoms[i]->setVel( vel );
200    
201 gezelter 596 if( atoms[i]->isDirectional() ){
202    
203     dAtom = (DirectionalAtom *)atoms[i];
204    
205 gezelter 604 // get and convert the torque to body frame
206 gezelter 596
207 gezelter 604 dAtom->getTrq( Tb );
208 gezelter 596 dAtom->lab2Body( Tb );
209    
210 gezelter 604 // get the angular momentum, and propagate a half step
211 gezelter 596
212 gezelter 604 dAtom->getJ( ji );
213 gezelter 596
214 gezelter 604 for (j=0; j < 3; j++)
215     ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
216 gezelter 596
217 gezelter 604 dAtom->setJ( ji );
218 gezelter 596 }
219     }
220     }
221    
222 gezelter 604 int NPTim::readyCheck() {
223 gezelter 596
224     // First check to see if we have a target temperature.
225     // Not having one is fatal.
226    
227     if (!have_target_temp) {
228     sprintf( painCave.errMsg,
229 gezelter 604 "NPTim error: You can't use the NPTim integrator\n"
230 gezelter 596 " without a targetTemp!\n"
231     );
232     painCave.isFatal = 1;
233     simError();
234     return -1;
235     }
236    
237     if (!have_target_pressure) {
238     sprintf( painCave.errMsg,
239 gezelter 604 "NPTim error: You can't use the NPTim integrator\n"
240 gezelter 596 " without a targetPressure!\n"
241     );
242     painCave.isFatal = 1;
243     simError();
244     return -1;
245     }
246    
247     // We must set tauThermostat.
248    
249     if (!have_tau_thermostat) {
250     sprintf( painCave.errMsg,
251 gezelter 604 "NPTim error: If you use the NPTim\n"
252 gezelter 596 " integrator, you must set tauThermostat.\n");
253     painCave.isFatal = 1;
254     simError();
255     return -1;
256     }
257    
258     // We must set tauBarostat.
259    
260     if (!have_tau_barostat) {
261     sprintf( painCave.errMsg,
262 gezelter 604 "NPTim error: If you use the NPTim\n"
263 gezelter 596 " integrator, you must set tauBarostat.\n");
264     painCave.isFatal = 1;
265     simError();
266     return -1;
267     }
268    
269     // We need NkBT a lot, so just set it here:
270    
271     NkBT = (double)info->ndf * kB * targetTemp;
272    
273     return 1;
274     }