ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/integrators/NVT.cpp
Revision: 2204
Committed: Fri Apr 15 22:04:00 2005 UTC (19 years, 2 months ago) by gezelter
File size: 8803 byte(s)
Log Message:
xemacs has been drafted to perform our indentation services

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 "integrators/NVT.hpp"
43 #include "primitives/Molecule.hpp"
44 #include "utils/simError.h"
45 #include "utils/OOPSEConstant.hpp"
46
47 namespace oopse {
48
49 NVT::NVT(SimInfo* info) : VelocityVerletIntegrator(info), chiTolerance_ (1e-6), maxIterNum_(4) {
50
51 Globals* simParams = info_->getSimParams();
52
53 if (!simParams->getUseInitXSstate()) {
54 Snapshot* currSnapshot = info_->getSnapshotManager()->getCurrentSnapshot();
55 currSnapshot->setChi(0.0);
56 currSnapshot->setIntegralOfChiDt(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 = OOPSE_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 = OOPSE_ERROR;
75 painCave.isFatal = 1;
76 simError();
77 } else {
78 tauThermostat_ = simParams->getTauThermostat();
79 }
80
81 update();
82 }
83
84 void NVT::doUpdate() {
85 oldVel_.resize(info_->getNIntegrableObjects());
86 oldJi_.resize(info_->getNIntegrableObjects());
87 }
88 void NVT::moveA() {
89 SimInfo::MoleculeIterator i;
90 Molecule::IntegrableObjectIterator j;
91 Molecule* mol;
92 StuntDouble* integrableObject;
93 Vector3d Tb;
94 Vector3d ji;
95 double mass;
96 Vector3d vel;
97 Vector3d pos;
98 Vector3d frc;
99
100 double chi = currentSnapshot_->getChi();
101 double integralOfChidt = currentSnapshot_->getIntegralOfChiDt();
102
103 // We need the temperature at time = t for the chi update below:
104
105 double instTemp = thermo.getTemperature();
106
107 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
108 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
109 integrableObject = mol->nextIntegrableObject(j)) {
110
111 vel = integrableObject->getVel();
112 pos = integrableObject->getPos();
113 frc = integrableObject->getFrc();
114
115 mass = integrableObject->getMass();
116
117 // velocity half step (use chi from previous step here):
118 //vel[j] += dt2 * ((frc[j] / mass ) * OOPSEConstant::energyConvert - vel[j]*chi);
119 vel += dt2 *OOPSEConstant::energyConvert/mass*frc - dt2*chi*vel;
120
121 // position whole step
122 //pos[j] += dt * vel[j];
123 pos += dt * vel;
124
125 integrableObject->setVel(vel);
126 integrableObject->setPos(pos);
127
128 if (integrableObject->isDirectional()) {
129
130 //convert the torque to body frame
131 Tb = integrableObject->lab2Body(integrableObject->getTrq());
132
133 // get the angular momentum, and propagate a half step
134
135 ji = integrableObject->getJ();
136
137 //ji[j] += dt2 * (Tb[j] * OOPSEConstant::energyConvert - ji[j]*chi);
138 ji += dt2*OOPSEConstant::energyConvert*Tb - dt2*chi *ji;
139 rotAlgo->rotate(integrableObject, ji, dt);
140
141 integrableObject->setJ(ji);
142 }
143 }
144
145 }
146
147 rattle->constraintA();
148
149 // Finally, evolve chi a half step (just like a velocity) using
150 // temperature at time t, not time t+dt/2
151
152
153 chi += dt2 * (instTemp / targetTemp_ - 1.0) / (tauThermostat_ * tauThermostat_);
154 integralOfChidt += chi * dt2;
155
156 currentSnapshot_->setChi(chi);
157 currentSnapshot_->setIntegralOfChiDt(integralOfChidt);
158 }
159
160 void NVT::moveB() {
161 SimInfo::MoleculeIterator i;
162 Molecule::IntegrableObjectIterator j;
163 Molecule* mol;
164 StuntDouble* integrableObject;
165
166 Vector3d Tb;
167 Vector3d ji;
168 Vector3d vel;
169 Vector3d frc;
170 double mass;
171 double instTemp;
172 int index;
173 // Set things up for the iteration:
174
175 double chi = currentSnapshot_->getChi();
176 double oldChi = chi;
177 double prevChi;
178 double integralOfChidt = currentSnapshot_->getIntegralOfChiDt();
179
180 index = 0;
181 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
182 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
183 integrableObject = mol->nextIntegrableObject(j)) {
184 oldVel_[index] = integrableObject->getVel();
185 oldJi_[index] = integrableObject->getJ();
186
187 ++index;
188 }
189
190 }
191
192 // do the iteration:
193
194 for(int k = 0; k < maxIterNum_; k++) {
195 index = 0;
196 instTemp = thermo.getTemperature();
197
198 // evolve chi another half step using the temperature at t + dt/2
199
200 prevChi = chi;
201 chi = oldChi + dt2 * (instTemp / targetTemp_ - 1.0) / (tauThermostat_ * tauThermostat_);
202
203 for (mol = info_->beginMolecule(i); mol != NULL; mol = info_->nextMolecule(i)) {
204 for (integrableObject = mol->beginIntegrableObject(j); integrableObject != NULL;
205 integrableObject = mol->nextIntegrableObject(j)) {
206
207 frc = integrableObject->getFrc();
208 vel = integrableObject->getVel();
209
210 mass = integrableObject->getMass();
211
212 // velocity half step
213 //for(j = 0; j < 3; j++)
214 // vel[j] = oldVel_[3*i+j] + dt2 * ((frc[j] / mass ) * OOPSEConstant::energyConvert - oldVel_[3*i + j]*chi);
215 vel = oldVel_[index] + dt2/mass*OOPSEConstant::energyConvert * frc - dt2*chi*oldVel_[index];
216
217 integrableObject->setVel(vel);
218
219 if (integrableObject->isDirectional()) {
220
221 // get and convert the torque to body frame
222
223 Tb = integrableObject->lab2Body(integrableObject->getTrq());
224
225 //for(j = 0; j < 3; j++)
226 // ji[j] = oldJi_[3*i + j] + dt2 * (Tb[j] * OOPSEConstant::energyConvert - oldJi_[3*i+j]*chi);
227 ji = oldJi_[index] + dt2*OOPSEConstant::energyConvert*Tb - dt2*chi *oldJi_[index];
228
229 integrableObject->setJ(ji);
230 }
231
232
233 ++index;
234 }
235 }
236
237
238 rattle->constraintB();
239
240 if (fabs(prevChi - chi) <= chiTolerance_)
241 break;
242
243 }
244
245 integralOfChidt += dt2 * chi;
246
247 currentSnapshot_->setChi(chi);
248 currentSnapshot_->setIntegralOfChiDt(integralOfChidt);
249 }
250
251
252 double NVT::calcConservedQuantity() {
253
254 double chi = currentSnapshot_->getChi();
255 double integralOfChidt = currentSnapshot_->getIntegralOfChiDt();
256 double conservedQuantity;
257 double fkBT;
258 double Energy;
259 double thermostat_kinetic;
260 double thermostat_potential;
261
262 fkBT = info_->getNdf() *OOPSEConstant::kB *targetTemp_;
263
264 Energy = thermo.getTotalE();
265
266 thermostat_kinetic = fkBT * tauThermostat_ * tauThermostat_ * chi * chi / (2.0 * OOPSEConstant::energyConvert);
267
268 thermostat_potential = fkBT * integralOfChidt / OOPSEConstant::energyConvert;
269
270 conservedQuantity = Energy + thermostat_kinetic + thermostat_potential;
271
272 return conservedQuantity;
273 }
274
275
276 }//end namespace oopse