ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new-templateless/OOPSE/libmdtools/NVT.cpp
Revision: 850
Committed: Mon Nov 3 22:07:17 2003 UTC (20 years, 8 months ago) by mmeineke
File size: 5812 byte(s)
Log Message:
begun work on removing templates and most of standard template library from OOPSE.

File Contents

# Content
1 #include <math.h>
2
3 #include "Atom.hpp"
4 #include "SRI.hpp"
5 #include "AbstractClasses.hpp"
6 #include "SimInfo.hpp"
7 #include "ForceFields.hpp"
8 #include "Thermo.hpp"
9 #include "ReadWrite.hpp"
10 #include "Integrator.hpp"
11 #include "simError.h"
12
13
14 // Basic thermostating via Hoover, Phys.Rev.A, 1985, Vol. 31 (5) 1695-1697
15
16 NVT::NVT ( SimInfo *theInfo, ForceFields* the_ff):
17 Integrator( theInfo, the_ff )
18 {
19 GenericData* data;
20
21 chi = 0.0;
22 have_tau_thermostat = 0;
23 have_target_temp = 0;
24 have_chi_tolerance = 0;
25 integralOfChidt = 0.0;
26
27 // retrieve chi and integralOfChidt from simInfo
28 data = info->getProperty(CHIVALUE_ID);
29 if(data != NULL ){
30 chi = data->getDval();
31 }
32
33 data = info->getProperty(INTEGRALOFCHIDT_ID);
34 if(data != NULL ){
35 integralOfChidt = data->getDval();
36 }
37
38 oldVel = new double[3*nAtoms];
39 oldJi = new double[3*nAtoms];
40 }
41
42 NVT::~NVT() {
43 delete[] oldVel;
44 delete[] oldJi;
45 }
46
47 void NVT::moveA() {
48
49 int i, j;
50 DirectionalAtom* dAtom;
51 double Tb[3], ji[3];
52 double mass;
53 double vel[3], pos[3], frc[3];
54
55 double instTemp;
56
57 // We need the temperature at time = t for the chi update below:
58
59 instTemp = tStats->getTemperature();
60
61 for( i=0; i<nAtoms; i++ ){
62
63 atoms[i]->getVel( vel );
64 atoms[i]->getPos( pos );
65 atoms[i]->getFrc( frc );
66
67 mass = atoms[i]->getMass();
68
69 for (j=0; j < 3; j++) {
70 // velocity half step (use chi from previous step here):
71 vel[j] += dt2 * ((frc[j] / mass ) * eConvert - vel[j]*chi);
72 // position whole step
73 pos[j] += dt * vel[j];
74 }
75
76 atoms[i]->setVel( vel );
77 atoms[i]->setPos( pos );
78
79 if( atoms[i]->isDirectional() ){
80
81 dAtom = (DirectionalAtom *)atoms[i];
82
83 // get and convert the torque to body frame
84
85 dAtom->getTrq( Tb );
86 dAtom->lab2Body( Tb );
87
88 // get the angular momentum, and propagate a half step
89
90 dAtom->getJ( ji );
91
92 for (j=0; j < 3; j++)
93 ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
94
95 this->rotationPropagation( dAtom, ji );
96
97 dAtom->setJ( ji );
98 }
99 }
100
101 if (nConstrained){
102 constrainA();
103 }
104
105 // Finally, evolve chi a half step (just like a velocity) using
106 // temperature at time t, not time t+dt/2
107
108 chi += dt2 * ( instTemp / targetTemp - 1.0) / (tauThermostat*tauThermostat);
109 integralOfChidt += chi*dt2;
110
111 }
112
113 void NVT::moveB( void ){
114 int i, j, k;
115 DirectionalAtom* dAtom;
116 double Tb[3], ji[3];
117 double vel[3], frc[3];
118 double mass;
119 double instTemp;
120 double oldChi, prevChi;
121
122 // Set things up for the iteration:
123
124 oldChi = chi;
125
126 for( i=0; i<nAtoms; i++ ){
127
128 atoms[i]->getVel( vel );
129
130 for (j=0; j < 3; j++)
131 oldVel[3*i + j] = vel[j];
132
133 if( atoms[i]->isDirectional() ){
134
135 dAtom = (DirectionalAtom *)atoms[i];
136
137 dAtom->getJ( ji );
138
139 for (j=0; j < 3; j++)
140 oldJi[3*i + j] = ji[j];
141
142 }
143 }
144
145 // do the iteration:
146
147 for (k=0; k < 4; k++) {
148
149 instTemp = tStats->getTemperature();
150
151 // evolve chi another half step using the temperature at t + dt/2
152
153 prevChi = chi;
154 chi = oldChi + dt2 * ( instTemp / targetTemp - 1.0) /
155 (tauThermostat*tauThermostat);
156
157 for( i=0; i<nAtoms; i++ ){
158
159 atoms[i]->getFrc( frc );
160 atoms[i]->getVel(vel);
161
162 mass = atoms[i]->getMass();
163
164 // velocity half step
165 for (j=0; j < 3; j++)
166 vel[j] = oldVel[3*i+j] + dt2 * ((frc[j] / mass ) * eConvert - oldVel[3*i + j]*chi);
167
168 atoms[i]->setVel( vel );
169
170 if( atoms[i]->isDirectional() ){
171
172 dAtom = (DirectionalAtom *)atoms[i];
173
174 // get and convert the torque to body frame
175
176 dAtom->getTrq( Tb );
177 dAtom->lab2Body( Tb );
178
179 for (j=0; j < 3; j++)
180 ji[j] = oldJi[3*i + j] + dt2 * (Tb[j] * eConvert - oldJi[3*i+j]*chi);
181
182 dAtom->setJ( ji );
183 }
184 }
185
186 if (nConstrained){
187 constrainB();
188 }
189
190 if (fabs(prevChi - chi) <= chiTolerance) break;
191 }
192
193 integralOfChidt += dt2*chi;
194 }
195
196 void NVT::resetIntegrator( void ){
197
198 chi = 0.0;
199 integralOfChidt = 0.0;
200 }
201
202 int NVT::readyCheck() {
203
204 //check parent's readyCheck() first
205 if (Integrator::readyCheck() == -1)
206 return -1;
207
208 // First check to see if we have a target temperature.
209 // Not having one is fatal.
210
211 if (!have_target_temp) {
212 sprintf( painCave.errMsg,
213 "NVT error: You can't use the NVT integrator without a targetTemp!\n"
214 );
215 painCave.isFatal = 1;
216 simError();
217 return -1;
218 }
219
220 // We must set tauThermostat.
221
222 if (!have_tau_thermostat) {
223 sprintf( painCave.errMsg,
224 "NVT error: If you use the constant temperature\n"
225 " integrator, you must set tauThermostat.\n");
226 painCave.isFatal = 1;
227 simError();
228 return -1;
229 }
230
231 if (!have_chi_tolerance) {
232 sprintf( painCave.errMsg,
233 "NVT warning: setting chi tolerance to 1e-6\n");
234 chiTolerance = 1e-6;
235 have_chi_tolerance = 1;
236 painCave.isFatal = 0;
237 simError();
238 }
239
240 return 1;
241
242 }
243
244 double NVT::getConservedQuantity(void){
245
246 double conservedQuantity;
247 double fkBT;
248 double Energy;
249 double thermostat_kinetic;
250 double thermostat_potential;
251
252 fkBT = (double)(info->getNDF() ) * kB * targetTemp;
253
254 Energy = tStats->getTotalE();
255
256 thermostat_kinetic = fkBT* tauThermostat * tauThermostat * chi * chi /
257 (2.0 * eConvert);
258
259 thermostat_potential = fkBT * integralOfChidt / eConvert;
260
261 conservedQuantity = Energy + thermostat_kinetic + thermostat_potential;
262
263 cerr << info->getTime() << "\t" << Energy << "\t" << thermostat_kinetic <<
264 "\t" << thermostat_potential << "\t" << conservedQuantity << endl;
265
266 return conservedQuantity;
267 }
268
269 string NVT::getAdditionalParameters(void){
270 string parameters;
271 const int BUFFERSIZE = 2000; // size of the read buffer
272 char buffer[BUFFERSIZE];
273
274 sprintf(buffer,"\t%g\t%g;", chi, integralOfChidt);
275 parameters += buffer;
276
277 return parameters;
278 }