ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-4/src/integrators/NPT.cpp
Revision: 1774
Committed: Tue Nov 23 23:12:23 2004 UTC (19 years, 7 months ago) by tim
File size: 8969 byte(s)
Log Message:
refactory NPT integrator

File Contents

# Content
1 #include <math.h>
2
3 #include "brains/SimInfo.hpp"
4 #include "brains/Thermo.hpp"
5 #include "integrators/NPT.hpp"
6 #include "utils/simError.h"
7
8
9 // Basic isotropic thermostating and barostating via the Melchionna
10 // modification of the Hoover algorithm:
11 //
12 // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
13 // Molec. Phys., 78, 533.
14 //
15 // and
16 //
17 // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
18
19 namespace oopse {
20
21 NPT::NPT(SimInfo* info) :
22 VelocityVerletIntegrator(info), chiTolerance(1e-6), etaTolerance(1e-6) {
23
24 Globals* globals = info_->getGlobals();
25
26 if (globals->getUseInitXSstate()) {
27 Snapshot* currSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
28 currSnapshot->setChi(0.0);
29 currSnapshot->setIntegralOfChiDt(0.0);
30 }
31
32 if (!globals->haveTargetTemp()) {
33 sprintf(painCave.errMsg, "You can't use the NVT integrator without a targetTemp!\n");
34 painCave.isFatal = 1;
35 painCave.severity = OOPSE_ERROR;
36 simError();
37 } else {
38 targetTemp = globals->getTargetTemp();
39 }
40
41 // We must set tauThermostat
42 if (!globals->haveTauThermostat()) {
43 sprintf(painCave.errMsg, "If you use the constant temperature\n"
44 "\tintegrator, you must set tauThermostat_.\n");
45
46 painCave.severity = OOPSE_ERROR;
47 painCave.isFatal = 1;
48 simError();
49 } else {
50 tauThermostat = globals->getTauThermostat();
51 }
52
53 if (!globals->haveTargetPressure()) {
54 sprintf(painCave.errMsg, "NPT error: You can't use the NPT integrator\n"
55 " without a targetPressure!\n");
56
57 painCave.isFatal = 1;
58 simError();
59 } else {
60 targetPressure = globals->getTargetPressure();
61 }
62
63 if (!globals->haveTauBarostat()) {
64 sprintf(painCave.errMsg,
65 "If you use the NPT integrator, you must set tauBarostat.\n");
66 painCave.severity = OOPSE_ERROR;
67 painCave.isFatal = 1;
68 simError();
69 } else {
70 tauBarostat = globals->getTauBarostat();
71 }
72
73 tt2 = tauThermostat * tauThermostat;
74 tb2 = tauBarostat * tauBarostat;
75
76 update();
77 }
78
79 NPT::~NPT() {
80 }
81
82 void NPT::update() {
83 oldPos.resize(info_->getNIntegrableObjects());
84 oldVel.resize(info_->getNIntegrableObjects());
85 oldJi.resize(info_->getNIntegrableObjects());
86 // We need NkBT a lot, so just set it here: This is the RAW number
87 // of integrableObjects, so no subtraction or addition of constraints or
88 // orientational degrees of freedom:
89 NkBT = info_->getNGlobalIntegrableObjects()*kB *targetTemp;
90
91 // fkBT is used because the thermostat operates on more degrees of freedom
92 // than the barostat (when there are particles with orientational degrees
93 // of freedom).
94 fkBT = info_->getNdf()*kB *targetTemp;
95 }
96
97 void NPT::moveA() {
98 typename SimInfo::MoleculeIterator i;
99 typename Molecule::IntegrableObjectIterator j;
100 Molecule* mol;
101 StuntDouble* integrableObject;
102 Vector3d Tb, ji;
103 double mass;
104 Vector3d vel;
105 Vector3d pos;
106 Vector3d frc;
107 Vector3d sc;
108 Vector3d COM;
109 int index;
110
111 instaTemp = tStats->getTemperature();
112 tStats->getPressureTensor(press);
113 instaPress = p_convert * (press(0, 0) + press(1, 1) + press(2, 2)) / 3.0;
114 instaVol = tStats->getVolume();
115
116 tStats->getCOM(COM);
117
118 //evolve velocity half step
119
120 calcVelScale();
121
122 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
123 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
124 integrableObject = mol->nextIntegrableObject(j)) {
125
126 vel = integrableObject->getVel();
127 frc = integrableObject->getFrc();
128
129 mass = integrableObject->getMass();
130
131 getVelScaleA(sc, vel);
132
133 // velocity half step (use chi from previous step here):
134 //vel[j] += dt2 * ((frc[j] / mass) * eConvert - sc[j]);
135 vel += dt2*eConvert/mass* frc - dt2*sc;
136 integrableObject->setVel(vel);
137
138 if (integrableObject->isDirectional()) {
139
140 // get and convert the torque to body frame
141
142 Tb = integrableObject->getTrq();
143 integrableObject->lab2Body(Tb);
144
145 // get the angular momentum, and propagate a half step
146
147 ji = integrableObject->getJ();
148
149 //ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
150 ji += dt2*eConvert * Tb - dt2*chi* ji;
151
152 this->rotationPropagation(integrableObject, ji);
153
154 integrableObject->setJ(ji);
155 }
156
157 }
158 }
159 // evolve chi and eta half step
160
161 evolveChiA();
162 evolveEtaA();
163
164 //calculate the integral of chidt
165 integralOfChidt += dt2 * chi;
166
167 index = 0;
168 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
169 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
170 integrableObject = mol->nextIntegrableObject(j)) {
171 oldPos[index++] = integrableObject->getPos();
172 }
173 }
174
175 //the first estimation of r(t+dt) is equal to r(t)
176
177 for(int k = 0; k < maxIterNum_; k++) {
178 index = 0;
179 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
180 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
181 integrableObject = mol->nextIntegrableObject(j)) {
182
183 vel = integrableObject->getVel();
184 pos = integrableObject->getPos();
185
186 this->getPosScale(pos, COM, index, sc);
187
188 pos = oldPos[index] + dt * (vel + sc);
189 integrableObject->setPos(pos);
190
191 ++index;
192 }
193 }
194
195 //constraintAlgorithm->doConstrainA();
196 }
197
198 // Scale the box after all the positions have been moved:
199
200 this->scaleSimBox();
201 }
202
203 void NPT::moveB(void) {
204 typename SimInfo::MoleculeIterator i;
205 typename Molecule::IntegrableObjectIterator j;
206 Molecule* mol;
207 StuntDouble* integrableObject;
208 int index;
209 Vector3d Tb;
210 Vector3d ji;
211 Vector3d sc;
212 Vector3d vel;
213 Vector3d frc;
214 double mass;
215
216 //save velocity and angular momentum
217 index = 0;
218 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
219 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
220 integrableObject = mol->nextIntegrableObject(j)) {
221
222 oldVel[index] = integrableObject->getVel();
223 oldJi[3 * i + j] = integrableObject->getJ();
224 ++index;
225 }
226 }
227
228 // do the iteration:
229 instaVol = tStats->getVolume();
230
231 for(int k = 0; k < maxIterNum_; k++) {
232 instaTemp = tStats->getTemperature();
233 instaPress = tStats->getPressure();
234
235 // evolve chi another half step using the temperature at t + dt/2
236 this->evolveChiB();
237 this->evolveEtaB();
238 this->calcVelScale();
239
240 index = 0;
241 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
242 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
243 integrableObject = mol->nextIntegrableObject(j)) {
244 integrableObject->getFrc(frc);
245 vel = integrableObject->getVel();
246
247 mass = integrableObject->getMass();
248
249 getVelScaleB(sc, i);
250
251 // velocity half step
252 //vel[j] = oldVel[3 * i + j] + dt2 *((frc[j] / mass) * eConvert - sc[j]);
253 vel = oldVel[index] + dt2*eConvert/mass* frc - dt2*sc;
254 integrableObject->setVel(vel);
255
256 if (integrableObject->isDirectional()) {
257 // get and convert the torque to body frame
258 Tb = integrableObject->getTrq();
259 integrableObject->lab2Body(Tb);
260
261 //ji[j] = oldJi[3*i + j] + dt2 * (Tb[j] * eConvert - oldJi[3*i+j]*chi);
262 ji = oldJi[index] + dt2*eConvert*Tb - dt2*chi*oldJi[index];
263 integrableObject->setJ(ji);
264 }
265
266 ++index;
267 }
268 }
269
270 //constraintAlgorithm->doConstrainB();
271
272 if (this->chiConverged() && this->etaConverged())
273 break;
274 }
275
276 //calculate integral of chidt
277 integralOfChidt += dt2 * chi;
278 }
279
280 void NPT::evolveChiA() {
281 chi += dt2 * (instaTemp / targetTemp - 1.0) / tt2;
282 oldChi = chi;
283 }
284
285 void NPT::evolveChiB() {
286 prevChi = chi;
287 chi = oldChi + dt2 * (instaTemp / targetTemp - 1.0) / tt2;
288 }
289
290 bool NPT::chiConverged() {
291 return (fabs(prevChi - chi) <= chiTolerance);
292 }
293
294 }