ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTi.cpp
Revision: 578
Committed: Wed Jul 9 02:15:29 2003 UTC (21 years ago) by gezelter
File size: 6299 byte(s)
Log Message:
Fixes for both NPTf and NPTi

File Contents

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