ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTi.cpp
Revision: 577
Committed: Wed Jul 9 01:41:11 2003 UTC (21 years ago) by gezelter
File size: 6282 byte(s)
Log Message:
Fixes in NPTi migrated into NPTf

File Contents

# Content
1 #include "Atom.hpp"
2 #include "SRI.hpp"
3 #include "AbstractClasses.hpp"
4 #include "SimInfo.hpp"
5 #include "ForceFields.hpp"
6 #include "Thermo.hpp"
7 #include "ReadWrite.hpp"
8 #include "Integrator.hpp"
9 #include "simError.h"
10
11
12 // Basic isotropic thermostating and barostating via the Melchionna
13 // modification of the Hoover algorithm:
14 //
15 // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
16 // Molec. Phys., 78, 533.
17 //
18 // and
19 //
20 // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
21
22 NPTi::NPTi ( SimInfo *theInfo, ForceFields* the_ff):
23 Integrator( theInfo, the_ff )
24 {
25 chi = 0.0;
26 eta = 0.0;
27 have_tau_thermostat = 0;
28 have_tau_barostat = 0;
29 have_target_temp = 0;
30 have_target_pressure = 0;
31 }
32
33 void NPTi::moveA() {
34
35 int i,j,k;
36 int atomIndex, aMatIndex;
37 DirectionalAtom* dAtom;
38 double Tb[3];
39 double ji[3];
40 double rj[3];
41 double instaTemp, instaPress, instaVol;
42 double tt2, tb2;
43 double angle;
44
45 tt2 = tauThermostat * tauThermostat;
46 tb2 = tauBarostat * tauBarostat;
47
48 instaTemp = tStats->getTemperature();
49 instaPress = tStats->getPressure();
50 instaVol = tStats->getVolume();
51
52 // first evolve chi a half step
53
54 chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
55 eta += dt2 * ( instaVol * (instaPress - targetPressure) / (NkBT*tb2));
56
57 for( i=0; i<nAtoms; i++ ){
58 atomIndex = i * 3;
59 aMatIndex = i * 9;
60
61 // velocity half step
62 for( j=atomIndex; j<(atomIndex+3); j++ )
63 vel[j] += dt2 * ((frc[j]/atoms[i]->getMass())*eConvert
64 - vel[j]*(chi+eta));
65
66 // position whole step
67
68 rj[0] = pos[atomIndex];
69 rj[1] = pos[atomIndex+1];
70 rj[2] = pos[atomIndex+2];
71
72 info->wrapVector(rj);
73
74 pos[atomIndex] += dt * (vel[atomIndex] + eta*rj[0]);
75 pos[atomIndex+1] += dt * (vel[atomIndex+1] + eta*rj[1]);
76 pos[atomIndex+2] += dt * (vel[atomIndex+2] + eta*rj[2]);
77
78 if( atoms[i]->isDirectional() ){
79
80 dAtom = (DirectionalAtom *)atoms[i];
81
82 // get and convert the torque to body frame
83
84 Tb[0] = dAtom->getTx();
85 Tb[1] = dAtom->getTy();
86 Tb[2] = dAtom->getTz();
87
88 dAtom->lab2Body( Tb );
89
90 // get the angular momentum, and propagate a half step
91
92 ji[0] = dAtom->getJx();
93 ji[1] = dAtom->getJy();
94 ji[2] = dAtom->getJz();
95
96 ji[0] += dt2 * (Tb[0] * eConvert - ji[0]*chi);
97 ji[1] += dt2 * (Tb[1] * eConvert - ji[1]*chi);
98 ji[2] += dt2 * (Tb[2] * eConvert - ji[2]*chi);
99
100 // use the angular velocities to propagate the rotation matrix a
101 // full time step
102
103 // rotate about the x-axis
104 angle = dt2 * ji[0] / dAtom->getIxx();
105 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
106
107 // rotate about the y-axis
108 angle = dt2 * ji[1] / dAtom->getIyy();
109 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
110
111 // rotate about the z-axis
112 angle = dt * ji[2] / dAtom->getIzz();
113 this->rotate( 0, 1, angle, ji, &Amat[aMatIndex] );
114
115 // rotate about the y-axis
116 angle = dt2 * ji[1] / dAtom->getIyy();
117 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
118
119 // rotate about the x-axis
120 angle = dt2 * ji[0] / dAtom->getIxx();
121 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
122
123 dAtom->setJx( ji[0] );
124 dAtom->setJy( ji[1] );
125 dAtom->setJz( ji[2] );
126 }
127
128 }
129 // Scale the box after all the positions have been moved:
130
131 info->scaleBox(exp(dt*eta));
132
133 }
134
135 void NPTi::moveB( void ){
136 int i,j,k;
137 int atomIndex;
138 DirectionalAtom* dAtom;
139 double Tb[3];
140 double ji[3];
141 double instaTemp, instaPress, instaVol;
142 double tt2, tb2;
143
144 tt2 = tauThermostat * tauThermostat;
145 tb2 = tauBarostat * tauBarostat;
146
147 instaTemp = tStats->getTemperature();
148 instaPress = tStats->getPressure();
149 instaVol = tStats->getVolume();
150
151 chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
152 eta += dt2 * ( instaVol * (instaPress - targetPressure) / (NkBT*tb2));
153
154 for( i=0; i<nAtoms; i++ ){
155 atomIndex = i * 3;
156
157 // velocity half step
158 for( j=atomIndex; j<(atomIndex+3); j++ )
159 for( j=atomIndex; j<(atomIndex+3); j++ )
160 vel[j] += dt2 * ((frc[j]/atoms[i]->getMass())*eConvert
161 - vel[j]*(chi+eta));
162
163 if( atoms[i]->isDirectional() ){
164
165 dAtom = (DirectionalAtom *)atoms[i];
166
167 // get and convert the torque to body frame
168
169 Tb[0] = dAtom->getTx();
170 Tb[1] = dAtom->getTy();
171 Tb[2] = dAtom->getTz();
172
173 dAtom->lab2Body( Tb );
174
175 // get the angular momentum, and complete the angular momentum
176 // half step
177
178 ji[0] = dAtom->getJx();
179 ji[1] = dAtom->getJy();
180 ji[2] = dAtom->getJz();
181
182 ji[0] += dt2 * (Tb[0] * eConvert - ji[0]*chi);
183 ji[1] += dt2 * (Tb[1] * eConvert - ji[1]*chi);
184 ji[2] += dt2 * (Tb[2] * eConvert - ji[2]*chi);
185
186 dAtom->setJx( ji[0] );
187 dAtom->setJy( ji[1] );
188 dAtom->setJz( ji[2] );
189 }
190 }
191 }
192
193 int NPTi::readyCheck() {
194
195 // First check to see if we have a target temperature.
196 // Not having one is fatal.
197
198 if (!have_target_temp) {
199 sprintf( painCave.errMsg,
200 "NPTi error: You can't use the NPTi integrator\n"
201 " without a targetTemp!\n"
202 );
203 painCave.isFatal = 1;
204 simError();
205 return -1;
206 }
207
208 if (!have_target_pressure) {
209 sprintf( painCave.errMsg,
210 "NPTi error: You can't use the NPTi integrator\n"
211 " without a targetPressure!\n"
212 );
213 painCave.isFatal = 1;
214 simError();
215 return -1;
216 }
217
218 // We must set tauThermostat.
219
220 if (!have_tau_thermostat) {
221 sprintf( painCave.errMsg,
222 "NPTi error: If you use the NPTi\n"
223 " integrator, you must set tauThermostat.\n");
224 painCave.isFatal = 1;
225 simError();
226 return -1;
227 }
228
229 // We must set tauBarostat.
230
231 if (!have_tau_barostat) {
232 sprintf( painCave.errMsg,
233 "NPTi error: If you use the NPTi\n"
234 " integrator, you must set tauBarostat.\n");
235 painCave.isFatal = 1;
236 simError();
237 return -1;
238 }
239
240 // We need NkBT a lot, so just set it here:
241
242 NkBT = (double)info->ndf * kB * targetTemp;
243
244 return 1;
245 }