ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTi.cpp
Revision: 574
Committed: Tue Jul 8 20:56:10 2003 UTC (21 years ago) by gezelter
File size: 6274 byte(s)
Log Message:
NPTi

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 for( j=atomIndex; j<(atomIndex+3); j=j+3 ) {
69 rj[0] = pos[j];
70 rj[1] = pos[j+1];
71 rj[2] = pos[j+2];
72
73 info->wrapVector(rj);
74
75 pos[j] += dt * (vel[j] + eta*rj[0]);
76 pos[j+1] += dt * (vel[j+1] + eta*rj[1]);
77 pos[j+2] += dt * (vel[j+2] + eta*rj[2]);
78 }
79
80 // Scale the box after all the positions have been moved:
81
82 info->scaleBox(dt*eta);
83
84 if( atoms[i]->isDirectional() ){
85
86 dAtom = (DirectionalAtom *)atoms[i];
87
88 // get and convert the torque to body frame
89
90 Tb[0] = dAtom->getTx();
91 Tb[1] = dAtom->getTy();
92 Tb[2] = dAtom->getTz();
93
94 dAtom->lab2Body( Tb );
95
96 // get the angular momentum, and propagate a half step
97
98 ji[0] = dAtom->getJx();
99 ji[1] = dAtom->getJy();
100 ji[2] = dAtom->getJz();
101
102 ji[0] += dt2 * (Tb[0] * eConvert - ji[0]*chi);
103 ji[1] += dt2 * (Tb[1] * eConvert - ji[1]*chi);
104 ji[2] += dt2 * (Tb[2] * eConvert - ji[2]*chi);
105
106 // use the angular velocities to propagate the rotation matrix a
107 // full time step
108
109 // rotate about the x-axis
110 angle = dt2 * ji[0] / dAtom->getIxx();
111 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
112
113 // rotate about the y-axis
114 angle = dt2 * ji[1] / dAtom->getIyy();
115 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
116
117 // rotate about the z-axis
118 angle = dt * ji[2] / dAtom->getIzz();
119 this->rotate( 0, 1, angle, ji, &Amat[aMatIndex] );
120
121 // rotate about the y-axis
122 angle = dt2 * ji[1] / dAtom->getIyy();
123 this->rotate( 2, 0, angle, ji, &Amat[aMatIndex] );
124
125 // rotate about the x-axis
126 angle = dt2 * ji[0] / dAtom->getIxx();
127 this->rotate( 1, 2, angle, ji, &Amat[aMatIndex] );
128
129 dAtom->setJx( ji[0] );
130 dAtom->setJy( ji[1] );
131 dAtom->setJz( ji[2] );
132 }
133
134 }
135 }
136
137 void NPTi::moveB( void ){
138 int i,j,k;
139 int atomIndex;
140 DirectionalAtom* dAtom;
141 double Tb[3];
142 double ji[3];
143 double instaTemp, instaPress, instaVol;
144 double tt2, tb2;
145
146 tt2 = tauThermostat * tauThermostat;
147 tb2 = tauBarostat * tauBarostat;
148
149 instaTemp = tStats->getTemperature();
150 instaPress = tStats->getPressure();
151 instaVol = tStats->getVolume();
152
153 chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
154 eta += dt2 * ( instaVol * (instaPress - targetPressure) / (NkBT*tb2));
155
156 for( i=0; i<nAtoms; i++ ){
157 atomIndex = i * 3;
158
159 // velocity half step
160 for( j=atomIndex; j<(atomIndex+3); j++ )
161 for( j=atomIndex; j<(atomIndex+3); j++ )
162 vel[j] += dt2 * ((frc[j]/atoms[i]->getMass())*eConvert
163 - vel[j]*(chi+eta));
164
165 if( atoms[i]->isDirectional() ){
166
167 dAtom = (DirectionalAtom *)atoms[i];
168
169 // get and convert the torque to body frame
170
171 Tb[0] = dAtom->getTx();
172 Tb[1] = dAtom->getTy();
173 Tb[2] = dAtom->getTz();
174
175 dAtom->lab2Body( Tb );
176
177 // get the angular momentum, and complete the angular momentum
178 // half step
179
180 ji[0] = dAtom->getJx();
181 ji[1] = dAtom->getJy();
182 ji[2] = dAtom->getJz();
183
184 ji[0] += dt2 * (Tb[0] * eConvert - ji[0]*chi);
185 ji[1] += dt2 * (Tb[1] * eConvert - ji[1]*chi);
186 ji[2] += dt2 * (Tb[2] * eConvert - ji[2]*chi);
187
188 dAtom->setJx( ji[0] );
189 dAtom->setJy( ji[1] );
190 dAtom->setJz( ji[2] );
191 }
192 }
193 }
194
195 int NPTi::readyCheck() {
196
197 // First check to see if we have a target temperature.
198 // Not having one is fatal.
199
200 if (!have_target_temp) {
201 sprintf( painCave.errMsg,
202 "NPTi error: You can't use the NPTi integrator\n"
203 " without a targetTemp!\n"
204 );
205 painCave.isFatal = 1;
206 simError();
207 return -1;
208 }
209
210 if (!have_target_pressure) {
211 sprintf( painCave.errMsg,
212 "NPTi error: You can't use the NPTi integrator\n"
213 " without a targetPressure!\n"
214 );
215 painCave.isFatal = 1;
216 simError();
217 return -1;
218 }
219
220 // We must set tauThermostat.
221
222 if (!have_tau_thermostat) {
223 sprintf( painCave.errMsg,
224 "NPTi error: If you use the NPTi\n"
225 " integrator, you must set tauThermostat.\n");
226 painCave.isFatal = 1;
227 simError();
228 return -1;
229 }
230
231 // We must set tauBarostat.
232
233 if (!have_tau_barostat) {
234 sprintf( painCave.errMsg,
235 "NPTi error: If you use the NPTi\n"
236 " integrator, you must set tauBarostat.\n");
237 painCave.isFatal = 1;
238 simError();
239 return -1;
240 }
241
242 // We need NkBT a lot, so just set it here:
243
244 NkBT = (double)info->ndf * kB * targetTemp;
245
246 return 1;
247 }