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

# Content
1 #include <cmath>
2 #include "Atom.hpp"
3 #include "Molecule.hpp"
4 #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 int i, j, k;
41 DirectionalAtom* dAtom;
42 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 double instaTemp, instaPress, instaVol;
49 double tt2, tb2, scaleFactor;
50
51 int nInMol;
52 double rc[3];
53
54 nMols = info->n_mol;
55 myMolecules = info->molecules;
56
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 myMolecules[i].getCOM(rc);
73
74 nInMol = myMolecules[i].getNAtoms();
75 myAtoms = myMolecules[i].getMyAtoms();
76
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 if(myAtoms[j] != NULL) {
84
85 myAtoms[j]->getVel( vel );
86 myAtoms[j]->getPos( pos );
87 myAtoms[j]->getFrc( frc );
88
89 mass = myAtoms[j]->getMass();
90
91 for (k=0; k < 3; k++)
92 vel[k] += dt2 * ((frc[k] / mass ) * eConvert - vel[k]*(chi+eta));
93
94 myAtoms[j]->setVel( vel );
95
96 for (k = 0; k < 3; k++)
97 pos[k] += dt * (vel[k] + eta*rc[k]);
98
99 myAtoms[j]->setPos( pos );
100
101 if( myAtoms[j]->isDirectional() ){
102
103 dAtom = (DirectionalAtom *)myAtoms[j];
104
105 // get and convert the torque to body frame
106
107 dAtom->getTrq( Tb );
108 dAtom->lab2Body( Tb );
109
110 // get the angular momentum, and propagate a half step
111
112 dAtom->getJ( ji );
113
114 for (k=0; k < 3; k++)
115 ji[k] += dt2 * (Tb[k] * eConvert - ji[k]*chi);
116
117 // use the angular velocities to propagate the rotation matrix a
118 // full time step
119
120 dAtom->getA(A);
121 dAtom->getI(I);
122
123 // rotate about the x-axis
124 angle = dt2 * ji[0] / I[0][0];
125 this->rotate( 1, 2, angle, ji, A );
126
127 // rotate about the y-axis
128 angle = dt2 * ji[1] / I[1][1];
129 this->rotate( 2, 0, angle, ji, A );
130
131 // rotate about the z-axis
132 angle = dt * ji[2] / I[2][2];
133 this->rotate( 0, 1, angle, ji, A);
134
135 // rotate about the y-axis
136 angle = dt2 * ji[1] / I[1][1];
137 this->rotate( 2, 0, angle, ji, A );
138
139 // rotate about the x-axis
140 angle = dt2 * ji[0] / I[0][0];
141 this->rotate( 1, 2, angle, ji, A );
142
143 dAtom->setJ( ji );
144 dAtom->setA( A );
145 }
146 }
147 }
148 }
149
150 // Scale the box after all the positions have been moved:
151
152 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 }
166
167 void NPTim::moveB( void ){
168 int i, j;
169 DirectionalAtom* dAtom;
170 double Tb[3], ji[3];
171 double vel[3], frc[3];
172 double mass;
173
174 double instaTemp, instaPress, instaVol;
175 double tt2, tb2;
176
177 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 atoms[i]->getVel( vel );
191 atoms[i]->getFrc( frc );
192
193 mass = atoms[i]->getMass();
194
195 // velocity half step
196 for (j=0; j < 3; j++)
197 vel[j] += dt2 * ((frc[j] / mass ) * eConvert - vel[j]*(chi+eta));
198
199 atoms[i]->setVel( vel );
200
201 if( atoms[i]->isDirectional() ){
202
203 dAtom = (DirectionalAtom *)atoms[i];
204
205 // get and convert the torque to body frame
206
207 dAtom->getTrq( Tb );
208 dAtom->lab2Body( Tb );
209
210 // get the angular momentum, and propagate a half step
211
212 dAtom->getJ( ji );
213
214 for (j=0; j < 3; j++)
215 ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
216
217 dAtom->setJ( ji );
218 }
219 }
220 }
221
222 int NPTim::readyCheck() {
223
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 "NPTim error: You can't use the NPTim integrator\n"
230 " 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 "NPTim error: You can't use the NPTim integrator\n"
240 " 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 "NPTim error: If you use the NPTim\n"
252 " 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 "NPTim error: If you use the NPTim\n"
263 " 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 }