ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTf.cpp
Revision: 576
Committed: Tue Jul 8 21:10:16 2003 UTC (21 years ago) by gezelter
File size: 6370 byte(s)
Log Message:
*** empty log message ***

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