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

File Contents

# User Rev Content
1 tim 1774 #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     }