ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/integrators/myNVT.cpp
Revision: 1997
Committed: Thu May 29 21:03:19 2014 UTC (10 years, 11 months ago) by jmichalk
File size: 9652 byte(s)
Log Message:
myNVT.hpp and myNVT.cpp are my (Joe) attempts at separating out the chi evolution into evolveChiA and evolveChiB functions as a precursor to implementing a langevin thermostat

File Contents

# User Rev Content
1 jmichalk 1997 /*
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. Redistributions of source code must retain the above copyright
10     * notice, this list of conditions and the following disclaimer.
11     *
12     * 2. Redistributions in binary form must reproduce the above copyright
13     * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the
15     * distribution.
16     *
17     * This software is provided "AS IS," without a warranty of any
18     * kind. All express or implied conditions, representations and
19     * warranties, including any implied warranty of merchantability,
20     * fitness for a particular purpose or non-infringement, are hereby
21     * excluded. The University of Notre Dame and its licensors shall not
22     * be liable for any damages suffered by licensee as a result of
23     * using, modifying or distributing the software or its
24     * derivatives. In no event will the University of Notre Dame or its
25     * licensors be liable for any lost revenue, profit or data, or for
26     * direct, indirect, special, consequential, incidental or punitive
27     * damages, however caused and regardless of the theory of liability,
28     * arising out of the use of or inability to use software, even if the
29     * University of Notre Dame has been advised of the possibility of
30     * such damages.
31     *
32     * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     * research, please cite the appropriate papers when you publish your
34     * work. Good starting points are:
35     *
36     * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37     * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38     * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39     * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41     */
42    
43     #include "integrators/NVT.hpp"
44     #include "primitives/Molecule.hpp"
45     #include "utils/simError.h"
46     #include "utils/PhysicalConstants.hpp"
47    
48     namespace OpenMD {
49    
50     NVT::NVT(SimInfo* info) : VelocityVerletIntegrator(info), chiTolerance_ (1e-6), maxIterNum_(4) {
51    
52     Globals* simParams = info_->getSimParams();
53    
54     if (!simParams->getUseIntialExtendedSystemState()) {
55     Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
56     snap->setThermostat(make_pair(0.0, 0.0));
57     }
58    
59     if (!simParams->haveTargetTemp()) {
60     sprintf(painCave.errMsg, "You can't use the NVT integrator without a targetTemp_!\n");
61     painCave.isFatal = 1;
62     painCave.severity = OPENMD_ERROR;
63     simError();
64     } else {
65     targetTemp_ = simParams->getTargetTemp();
66     }
67    
68     // We must set tauThermostat.
69    
70     if (!simParams->haveTauThermostat()) {
71     sprintf(painCave.errMsg, "If you use the constant temperature\n"
72     "\tintegrator, you must set tauThermostat.\n");
73    
74     painCave.severity = OPENMD_ERROR;
75     painCave.isFatal = 1;
76     simError();
77     } else {
78     tauThermostat_ = simParams->getTauThermostat();
79     }
80    
81     updateSizes();
82     }
83    
84     void NVT::doUpdateSizes() {
85     oldVel_.resize(info_->getNIntegrableObjects());
86     oldJi_.resize(info_->getNIntegrableObjects());
87     }
88    
89     void NVT:evolveChiA(){
90     pair<RealType, RealType> thermostat = snap->getThermostat();
91     RealType instTemp = thermo.getTemperature();
92     thermostat.first += dt2 * (instTemp / targetTemp_ - 1.0) / (tauThermostat_ * tauThermostat_);
93     thermostat.second += thermostat.first * dt2;
94     snap->setThermostat(thermostat);
95     oldChi_ = thermostat.first;
96     oldChiInt_ = thermostat.second;
97     }
98    
99     void NVT::evolveChiB(){
100     pair<RealType, RealType> thermostat = snap->getThermostat();
101     RealType instTemp = thermo.getTemperature();
102     prevChi_ = thermostat.first;
103     thermostat.first = oldChi_ + dt2 * (instTemp / targetTemp_ - 1.0) / (tauThermostat_ * tauThermostat_);
104     thermostat.second = oldChiInt_ + dt2 * thermostat.first;
105     snap->setThermostat(thermostat);
106     }
107    
108     void NVT::moveA() {
109     SimInfo::MoleculeIterator i;
110     Molecule::IntegrableObjectIterator j;
111     Molecule* mol;
112     StuntDouble* sd;
113     Vector3d Tb;
114     Vector3d ji;
115     RealType mass;
116     Vector3d vel;
117     Vector3d pos;
118     Vector3d frc;
119    
120     pair<RealType, RealType> thermostat = snap->getThermostat();
121    
122     // We need the temperature at time = t for the chi update below:
123    
124     RealType instTemp = thermo.getTemperature();
125    
126     for (mol = info_->beginMolecule(i); mol != NULL;
127     mol = info_->nextMolecule(i)) {
128    
129     for (sd = mol->beginIntegrableObject(j); sd != NULL;
130     sd = mol->nextIntegrableObject(j)) {
131    
132     vel = sd->getVel();
133     pos = sd->getPos();
134     frc = sd->getFrc();
135    
136     mass = sd->getMass();
137    
138     // velocity half step (use chi from previous step here):
139     vel += dt2 *PhysicalConstants::energyConvert/mass*frc
140     - dt2*thermostat.first*vel;
141    
142     // position whole step
143     pos += dt * vel;
144    
145     sd->setVel(vel);
146     sd->setPos(pos);
147    
148     if (sd->isDirectional()) {
149    
150     //convert the torque to body frame
151     Tb = sd->lab2Body(sd->getTrq());
152    
153     // get the angular momentum, and propagate a half step
154    
155     ji = sd->getJ();
156    
157     ji += dt2*PhysicalConstants::energyConvert*Tb
158     - dt2*thermostat.first *ji;
159    
160     rotAlgo_->rotate(sd, ji, dt);
161    
162     sd->setJ(ji);
163     }
164     }
165    
166     }
167    
168     flucQ_->moveA();
169     rattle_->constraintA();
170    
171     // Finally, evolve chi a half step (just like a velocity) using
172     // temperature at time t, not time t+dt/2
173     this->evolveChiA();
174     //thermostat.first += dt2 * (instTemp / targetTemp_ - 1.0)
175     // / (tauThermostat_ * tauThermostat_);
176     //thermostat.second += thermostat.first * dt2;
177    
178     //snap->setThermostat(thermostat);
179     }
180    
181     void NVT::moveB() {
182     SimInfo::MoleculeIterator i;
183     Molecule::IntegrableObjectIterator j;
184     Molecule* mol;
185     StuntDouble* sd;
186    
187     Vector3d Tb;
188     Vector3d ji;
189     Vector3d vel;
190     Vector3d frc;
191     RealType mass;
192     RealType instTemp;
193     int index;
194     // Set things up for the iteration:
195    
196     /*
197     * oldChi and prevChi are now oldChi_ and prevChi_ and are set in evolveChiB
198     */
199     //RealType oldChi = thermostat.first;
200     //RealType prevChi;
201    
202     index = 0;
203     for (mol = info_->beginMolecule(i); mol != NULL;
204     mol = info_->nextMolecule(i)) {
205    
206     for (sd = mol->beginIntegrableObject(j); sd != NULL;
207     sd = mol->nextIntegrableObject(j)) {
208    
209     oldVel_[index] = sd->getVel();
210    
211     if (sd->isDirectional())
212     oldJi_[index] = sd->getJ();
213    
214     ++index;
215     }
216     }
217    
218     // do the iteration:
219    
220     for(int k = 0; k < maxIterNum_; k++) {
221     index = 0;
222     instTemp = thermo.getTemperature();
223    
224     // evolve chi another half step using the temperature at t + dt/2
225    
226     /*
227     * calls this files modified version of evolveChiB();
228     */
229     this->evolveChiB();
230    
231     /*
232     * prevChi_ and thermostat.first are set in evolveChiB()
233     */
234     //prevChi = thermostat.first;
235     //thermostat.first = oldChi + dt2 * (instTemp / targetTemp_ - 1.0)
236     // / (tauThermostat_ * tauThermostat_);
237    
238     /*
239     * Since it is changed in a different method, need to get the updated version here
240     */
241     pair<RealType, RealType> thermostat = snap->getThermostat();
242    
243     for (mol = info_->beginMolecule(i); mol != NULL;
244     mol = info_->nextMolecule(i)) {
245    
246     for (sd = mol->beginIntegrableObject(j); sd != NULL;
247     sd = mol->nextIntegrableObject(j)) {
248    
249     frc = sd->getFrc();
250     mass = sd->getMass();
251    
252     // velocity half step
253    
254     vel = oldVel_[index]
255     + dt2/mass*PhysicalConstants::energyConvert * frc
256     - dt2*thermostat.first*oldVel_[index];
257    
258     sd->setVel(vel);
259    
260     if (sd->isDirectional()) {
261    
262     // get and convert the torque to body frame
263    
264     Tb = sd->lab2Body(sd->getTrq());
265    
266     ji = oldJi_[index] + dt2*PhysicalConstants::energyConvert*Tb
267     - dt2*thermostat.first *oldJi_[index];
268    
269     sd->setJ(ji);
270     }
271    
272    
273     ++index;
274     }
275     }
276    
277     rattle_->constraintB();
278    
279     /*
280     * prevChi_ is defined in evolveChiB now
281     */
282     //if (fabs(prevChi - thermostat.first) <= chiTolerance_)
283     if (fabs(prevChi_ - thermostat.first) <= chiTolerance_)
284     break;
285    
286     }
287    
288     flucQ_->moveB();
289    
290     /*
291     * This has already happened in evolveChiB
292     */
293     //thermostat.second += dt2 * thermostat.first;
294     //snap->setThermostat(thermostat);
295     }
296    
297     void NVT::resetIntegrator() {
298     snap->setThermostat(make_pair(0.0, 0.0));
299     }
300    
301     RealType NVT::calcConservedQuantity() {
302    
303     pair<RealType, RealType> thermostat = snap->getThermostat();
304     RealType conservedQuantity;
305     RealType fkBT;
306     RealType Energy;
307     RealType thermostat_kinetic;
308     RealType thermostat_potential;
309    
310     fkBT = info_->getNdf() *PhysicalConstants::kB *targetTemp_;
311    
312     Energy = thermo.getTotalEnergy();
313    
314     thermostat_kinetic = fkBT * tauThermostat_ * tauThermostat_ * thermostat.first * thermostat.first / (2.0 * PhysicalConstants::energyConvert);
315    
316     thermostat_potential = fkBT * thermostat.second / PhysicalConstants::energyConvert;
317    
318     conservedQuantity = Energy + thermostat_kinetic + thermostat_potential;
319    
320     return conservedQuantity;
321     }
322    
323    
324     }//end namespace OpenMD