ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/integrators/NPT.cpp
Revision: 1930
Committed: Wed Jan 12 22:41:40 2005 UTC (19 years, 5 months ago) by gezelter
File size: 11168 byte(s)
Log Message:
merging new_design branch into OOPSE-2.0

File Contents

# Content
1 /*
2 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 *
4 * The University of Notre Dame grants you ("Licensee") a
5 * non-exclusive, royalty free, license to use, modify and
6 * redistribute this software in source and binary code form, provided
7 * that the following conditions are met:
8 *
9 * 1. Acknowledgement of the program authors must be made in any
10 * publication of scientific results based in part on use of the
11 * program. An acceptable form of acknowledgement is citation of
12 * the article in which the program was described (Matthew
13 * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14 * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15 * Parallel Simulation Engine for Molecular Dynamics,"
16 * J. Comput. Chem. 26, pp. 252-271 (2005))
17 *
18 * 2. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 3. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * This software is provided "AS IS," without a warranty of any
27 * kind. All express or implied conditions, representations and
28 * warranties, including any implied warranty of merchantability,
29 * fitness for a particular purpose or non-infringement, are hereby
30 * excluded. The University of Notre Dame and its licensors shall not
31 * be liable for any damages suffered by licensee as a result of
32 * using, modifying or distributing the software or its
33 * derivatives. In no event will the University of Notre Dame or its
34 * licensors be liable for any lost revenue, profit or data, or for
35 * direct, indirect, special, consequential, incidental or punitive
36 * damages, however caused and regardless of the theory of liability,
37 * arising out of the use of or inability to use software, even if the
38 * University of Notre Dame has been advised of the possibility of
39 * such damages.
40 */
41
42 #include <math.h>
43
44 #include "brains/SimInfo.hpp"
45 #include "brains/Thermo.hpp"
46 #include "integrators/NPT.hpp"
47 #include "math/SquareMatrix3.hpp"
48 #include "primitives/Molecule.hpp"
49 #include "utils/OOPSEConstant.hpp"
50 #include "utils/simError.h"
51
52 // Basic isotropic thermostating and barostating via the Melchionna
53 // modification of the Hoover algorithm:
54 //
55 // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
56 // Molec. Phys., 78, 533.
57 //
58 // and
59 //
60 // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
61
62 namespace oopse {
63
64 NPT::NPT(SimInfo* info) :
65 VelocityVerletIntegrator(info), chiTolerance(1e-6), etaTolerance(1e-6), maxIterNum_(4) {
66
67 Globals* simParams = info_->getSimParams();
68
69 if (!simParams->getUseInitXSstate()) {
70 Snapshot* currSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
71 currSnapshot->setChi(0.0);
72 currSnapshot->setIntegralOfChiDt(0.0);
73 currSnapshot->setEta(Mat3x3d(0.0));
74 }
75
76 if (!simParams->haveTargetTemp()) {
77 sprintf(painCave.errMsg, "You can't use the NVT integrator without a targetTemp!\n");
78 painCave.isFatal = 1;
79 painCave.severity = OOPSE_ERROR;
80 simError();
81 } else {
82 targetTemp = simParams->getTargetTemp();
83 }
84
85 // We must set tauThermostat
86 if (!simParams->haveTauThermostat()) {
87 sprintf(painCave.errMsg, "If you use the constant temperature\n"
88 "\tintegrator, you must set tauThermostat_.\n");
89
90 painCave.severity = OOPSE_ERROR;
91 painCave.isFatal = 1;
92 simError();
93 } else {
94 tauThermostat = simParams->getTauThermostat();
95 }
96
97 if (!simParams->haveTargetPressure()) {
98 sprintf(painCave.errMsg, "NPT error: You can't use the NPT integrator\n"
99 " without a targetPressure!\n");
100
101 painCave.isFatal = 1;
102 simError();
103 } else {
104 targetPressure = simParams->getTargetPressure();
105 }
106
107 if (!simParams->haveTauBarostat()) {
108 sprintf(painCave.errMsg,
109 "If you use the NPT integrator, you must set tauBarostat.\n");
110 painCave.severity = OOPSE_ERROR;
111 painCave.isFatal = 1;
112 simError();
113 } else {
114 tauBarostat = simParams->getTauBarostat();
115 }
116
117 tt2 = tauThermostat * tauThermostat;
118 tb2 = tauBarostat * tauBarostat;
119
120 update();
121 }
122
123 NPT::~NPT() {
124 }
125
126 void NPT::doUpdate() {
127
128 oldPos.resize(info_->getNIntegrableObjects());
129 oldVel.resize(info_->getNIntegrableObjects());
130 oldJi.resize(info_->getNIntegrableObjects());
131
132 }
133
134 void NPT::moveA() {
135 SimInfo::MoleculeIterator i;
136 Molecule::IntegrableObjectIterator j;
137 Molecule* mol;
138 StuntDouble* integrableObject;
139 Vector3d Tb, ji;
140 double mass;
141 Vector3d vel;
142 Vector3d pos;
143 Vector3d frc;
144 Vector3d sc;
145 int index;
146
147 chi= currentSnapshot_->getChi();
148 integralOfChidt = currentSnapshot_->getIntegralOfChiDt();
149 loadEta();
150
151 instaTemp =thermo.getTemperature();
152 press = thermo.getPressureTensor();
153 instaPress = OOPSEConstant::pressureConvert* (press(0, 0) + press(1, 1) + press(2, 2)) / 3.0;
154 instaVol =thermo.getVolume();
155
156 Vector3d COM = info_->getCom();
157
158 //evolve velocity half step
159
160 calcVelScale();
161
162 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
163 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
164 integrableObject = mol->nextIntegrableObject(j)) {
165
166 vel = integrableObject->getVel();
167 frc = integrableObject->getFrc();
168
169 mass = integrableObject->getMass();
170
171 getVelScaleA(sc, vel);
172
173 // velocity half step (use chi from previous step here):
174 //vel[j] += dt2 * ((frc[j] / mass) * OOPSEConstant::energyConvert - sc[j]);
175 vel += dt2*OOPSEConstant::energyConvert/mass* frc - dt2*sc;
176 integrableObject->setVel(vel);
177
178 if (integrableObject->isDirectional()) {
179
180 // get and convert the torque to body frame
181
182 Tb = integrableObject->lab2Body(integrableObject->getTrq());
183
184 // get the angular momentum, and propagate a half step
185
186 ji = integrableObject->getJ();
187
188 //ji[j] += dt2 * (Tb[j] * OOPSEConstant::energyConvert - ji[j]*chi);
189 ji += dt2*OOPSEConstant::energyConvert * Tb - dt2*chi* ji;
190
191 rotAlgo->rotate(integrableObject, ji, dt);
192
193 integrableObject->setJ(ji);
194 }
195
196 }
197 }
198 // evolve chi and eta half step
199
200 chi += dt2 * (instaTemp / targetTemp - 1.0) / tt2;
201
202 evolveEtaA();
203
204 //calculate the integral of chidt
205 integralOfChidt += dt2 * chi;
206
207 index = 0;
208 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
209 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
210 integrableObject = mol->nextIntegrableObject(j)) {
211 oldPos[index++] = integrableObject->getPos();
212 }
213 }
214
215 //the first estimation of r(t+dt) is equal to r(t)
216
217 for(int k = 0; k < maxIterNum_; k++) {
218 index = 0;
219 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
220 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
221 integrableObject = mol->nextIntegrableObject(j)) {
222
223 vel = integrableObject->getVel();
224 pos = integrableObject->getPos();
225
226 this->getPosScale(pos, COM, index, sc);
227
228 pos = oldPos[index] + dt * (vel + sc);
229 integrableObject->setPos(pos);
230
231 ++index;
232 }
233 }
234
235 rattle->constraintA();
236 }
237
238 // Scale the box after all the positions have been moved:
239
240 this->scaleSimBox();
241
242 currentSnapshot_->setChi(chi);
243 currentSnapshot_->setIntegralOfChiDt(integralOfChidt);
244
245 saveEta();
246 }
247
248 void NPT::moveB(void) {
249 SimInfo::MoleculeIterator i;
250 Molecule::IntegrableObjectIterator j;
251 Molecule* mol;
252 StuntDouble* integrableObject;
253 int index;
254 Vector3d Tb;
255 Vector3d ji;
256 Vector3d sc;
257 Vector3d vel;
258 Vector3d frc;
259 double mass;
260
261
262 chi= currentSnapshot_->getChi();
263 integralOfChidt = currentSnapshot_->getIntegralOfChiDt();
264 double oldChi = chi;
265 double prevChi;
266
267 loadEta();
268
269 //save velocity and angular momentum
270 index = 0;
271 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
272 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
273 integrableObject = mol->nextIntegrableObject(j)) {
274
275 oldVel[index] = integrableObject->getVel();
276 oldJi[index] = integrableObject->getJ();
277 ++index;
278 }
279 }
280
281 // do the iteration:
282 instaVol =thermo.getVolume();
283
284 for(int k = 0; k < maxIterNum_; k++) {
285 instaTemp =thermo.getTemperature();
286 instaPress =thermo.getPressure();
287
288 // evolve chi another half step using the temperature at t + dt/2
289 prevChi = chi;
290 chi = oldChi + dt2 * (instaTemp / targetTemp - 1.0) / tt2;
291
292 //evolve eta
293 this->evolveEtaB();
294 this->calcVelScale();
295
296 index = 0;
297 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
298 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
299 integrableObject = mol->nextIntegrableObject(j)) {
300
301 frc = integrableObject->getFrc();
302 vel = integrableObject->getVel();
303
304 mass = integrableObject->getMass();
305
306 getVelScaleB(sc, index);
307
308 // velocity half step
309 //vel[j] = oldVel[3 * i + j] + dt2 *((frc[j] / mass) * OOPSEConstant::energyConvert - sc[j]);
310 vel = oldVel[index] + dt2*OOPSEConstant::energyConvert/mass* frc - dt2*sc;
311 integrableObject->setVel(vel);
312
313 if (integrableObject->isDirectional()) {
314 // get and convert the torque to body frame
315 Tb = integrableObject->lab2Body(integrableObject->getTrq());
316
317 //ji[j] = oldJi[3*i + j] + dt2 * (Tb[j] * OOPSEConstant::energyConvert - oldJi[3*i+j]*chi);
318 ji = oldJi[index] + dt2*OOPSEConstant::energyConvert*Tb - dt2*chi*oldJi[index];
319 integrableObject->setJ(ji);
320 }
321
322 ++index;
323 }
324 }
325
326 rattle->constraintB();
327
328 if ((fabs(prevChi - chi) <= chiTolerance) && this->etaConverged())
329 break;
330 }
331
332 //calculate integral of chidt
333 integralOfChidt += dt2 * chi;
334
335 currentSnapshot_->setChi(chi);
336 currentSnapshot_->setIntegralOfChiDt(integralOfChidt);
337
338 saveEta();
339 }
340
341 }