ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/oopse-1.0/libmdtools/NPT.cpp
Revision: 1447
Committed: Fri Jul 30 21:01:35 2004 UTC (19 years, 11 months ago) by gezelter
File size: 8489 byte(s)
Log Message:
Initial import of OOPSE sources into cvs tree

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 #ifdef IS_MPI
14 #include "mpiSimulation.hpp"
15 #endif
16
17
18 // Basic isotropic thermostating and barostating via the Melchionna
19 // modification of the Hoover algorithm:
20 //
21 // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
22 // Molec. Phys., 78, 533.
23 //
24 // and
25 //
26 // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
27
28 template<typename T> NPT<T>::NPT ( SimInfo *theInfo, ForceFields* the_ff):
29 T( theInfo, the_ff )
30 {
31 GenericData* data;
32 DoubleData * chiValue;
33 DoubleData * integralOfChidtValue;
34
35 chiValue = NULL;
36 integralOfChidtValue = NULL;
37
38 chi = 0.0;
39 integralOfChidt = 0.0;
40 have_tau_thermostat = 0;
41 have_tau_barostat = 0;
42 have_target_temp = 0;
43 have_target_pressure = 0;
44 have_chi_tolerance = 0;
45 have_eta_tolerance = 0;
46 have_pos_iter_tolerance = 0;
47
48 // retrieve chi and integralOfChidt from simInfo
49 data = info->getProperty(CHIVALUE_ID);
50 if(data){
51 chiValue = dynamic_cast<DoubleData*>(data);
52 }
53
54 data = info->getProperty(INTEGRALOFCHIDT_ID);
55 if(data){
56 integralOfChidtValue = dynamic_cast<DoubleData*>(data);
57 }
58
59 // chi and integralOfChidt should appear by pair
60 if(chiValue && integralOfChidtValue){
61 chi = chiValue->getData();
62 integralOfChidt = integralOfChidtValue->getData();
63 }
64
65 oldPos = new double[3*integrableObjects.size()];
66 oldVel = new double[3*integrableObjects.size()];
67 oldJi = new double[3*integrableObjects.size()];
68
69 }
70
71 template<typename T> NPT<T>::~NPT() {
72 delete[] oldPos;
73 delete[] oldVel;
74 delete[] oldJi;
75 }
76
77 template<typename T> void NPT<T>::moveA() {
78
79 //new version of NPT
80 int i, j, k;
81 double Tb[3], ji[3];
82 double mass;
83 double vel[3], pos[3], frc[3];
84 double sc[3];
85 double COM[3];
86
87 instaTemp = tStats->getTemperature();
88 tStats->getPressureTensor( press );
89 instaPress = p_convert * (press[0][0] + press[1][1] + press[2][2]) / 3.0;
90 instaVol = tStats->getVolume();
91
92 tStats->getCOM(COM);
93
94 //evolve velocity half step
95
96 calcVelScale();
97
98 for( i=0; i<integrableObjects.size(); i++ ){
99
100 integrableObjects[i]->getVel( vel );
101 integrableObjects[i]->getFrc( frc );
102
103 mass = integrableObjects[i]->getMass();
104
105 getVelScaleA( sc, vel );
106
107 for (j=0; j < 3; j++) {
108
109 // velocity half step (use chi from previous step here):
110 vel[j] += dt2 * ((frc[j] / mass ) * eConvert - sc[j]);
111
112 }
113
114 integrableObjects[i]->setVel( vel );
115
116 if( integrableObjects[i]->isDirectional() ){
117
118 // get and convert the torque to body frame
119
120 integrableObjects[i]->getTrq( Tb );
121 integrableObjects[i]->lab2Body( Tb );
122
123 // get the angular momentum, and propagate a half step
124
125 integrableObjects[i]->getJ( ji );
126
127 for (j=0; j < 3; j++)
128 ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
129
130 this->rotationPropagation( integrableObjects[i], ji );
131
132 integrableObjects[i]->setJ( ji );
133 }
134 }
135
136 // evolve chi and eta half step
137
138 evolveChiA();
139 evolveEtaA();
140
141 //calculate the integral of chidt
142 integralOfChidt += dt2*chi;
143
144 //save the old positions
145 for(i = 0; i < integrableObjects.size(); i++){
146 integrableObjects[i]->getPos(pos);
147 for(j = 0; j < 3; j++)
148 oldPos[i*3 + j] = pos[j];
149 }
150
151 //the first estimation of r(t+dt) is equal to r(t)
152
153 for(k = 0; k < 5; k ++){
154
155 for(i =0 ; i < integrableObjects.size(); i++){
156
157 integrableObjects[i]->getVel(vel);
158 integrableObjects[i]->getPos(pos);
159
160 this->getPosScale( pos, COM, i, sc );
161
162 for(j = 0; j < 3; j++)
163 pos[j] = oldPos[i*3 + j] + dt*(vel[j] + sc[j]);
164
165 integrableObjects[i]->setPos( pos );
166 }
167
168 if(nConstrained)
169 constrainA();
170 }
171
172
173 // Scale the box after all the positions have been moved:
174
175 this->scaleSimBox();
176 }
177
178 template<typename T> void NPT<T>::moveB( void ){
179
180 //new version of NPT
181 int i, j, k;
182 double Tb[3], ji[3], sc[3];
183 double vel[3], frc[3];
184 double mass;
185
186 // Set things up for the iteration:
187
188 for( i=0; i<integrableObjects.size(); i++ ){
189
190 integrableObjects[i]->getVel( vel );
191
192 for (j=0; j < 3; j++)
193 oldVel[3*i + j] = vel[j];
194
195 if( integrableObjects[i]->isDirectional() ){
196
197 integrableObjects[i]->getJ( ji );
198
199 for (j=0; j < 3; j++)
200 oldJi[3*i + j] = ji[j];
201
202 }
203 }
204
205 // do the iteration:
206
207 instaVol = tStats->getVolume();
208
209 for (k=0; k < 4; k++) {
210
211 instaTemp = tStats->getTemperature();
212 instaPress = tStats->getPressure();
213
214 // evolve chi another half step using the temperature at t + dt/2
215
216 this->evolveChiB();
217 this->evolveEtaB();
218 this->calcVelScale();
219
220 for( i=0; i<integrableObjects.size(); i++ ){
221
222 integrableObjects[i]->getFrc( frc );
223 integrableObjects[i]->getVel(vel);
224
225 mass = integrableObjects[i]->getMass();
226
227 getVelScaleB( sc, i );
228
229 // velocity half step
230 for (j=0; j < 3; j++)
231 vel[j] = oldVel[3*i+j] + dt2 * ((frc[j] / mass ) * eConvert - sc[j]);
232
233 integrableObjects[i]->setVel( vel );
234
235 if( integrableObjects[i]->isDirectional() ){
236
237 // get and convert the torque to body frame
238
239 integrableObjects[i]->getTrq( Tb );
240 integrableObjects[i]->lab2Body( Tb );
241
242 for (j=0; j < 3; j++)
243 ji[j] = oldJi[3*i + j] + dt2 * (Tb[j] * eConvert - oldJi[3*i+j]*chi);
244
245 integrableObjects[i]->setJ( ji );
246 }
247 }
248
249 if(nConstrained)
250 constrainB();
251
252 if ( this->chiConverged() && this->etaConverged() ) break;
253 }
254
255 //calculate integral of chida
256 integralOfChidt += dt2*chi;
257
258
259 }
260
261 template<typename T> void NPT<T>::resetIntegrator() {
262 chi = 0.0;
263 T::resetIntegrator();
264 }
265
266 template<typename T> void NPT<T>::evolveChiA() {
267 chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
268 oldChi = chi;
269 }
270
271 template<typename T> void NPT<T>::evolveChiB() {
272
273 prevChi = chi;
274 chi = oldChi + dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
275 }
276
277 template<typename T> bool NPT<T>::chiConverged() {
278
279 return ( fabs( prevChi - chi ) <= chiTolerance );
280 }
281
282 template<typename T> int NPT<T>::readyCheck() {
283
284 //check parent's readyCheck() first
285 if (T::readyCheck() == -1)
286 return -1;
287
288 // First check to see if we have a target temperature.
289 // Not having one is fatal.
290
291 if (!have_target_temp) {
292 sprintf( painCave.errMsg,
293 "NPT error: You can't use the NPT integrator\n"
294 " without a targetTemp!\n"
295 );
296 painCave.isFatal = 1;
297 simError();
298 return -1;
299 }
300
301 if (!have_target_pressure) {
302 sprintf( painCave.errMsg,
303 "NPT error: You can't use the NPT integrator\n"
304 " without a targetPressure!\n"
305 );
306 painCave.isFatal = 1;
307 simError();
308 return -1;
309 }
310
311 // We must set tauThermostat.
312
313 if (!have_tau_thermostat) {
314 sprintf( painCave.errMsg,
315 "NPT error: If you use the NPT\n"
316 " integrator, you must set tauThermostat.\n");
317 painCave.isFatal = 1;
318 simError();
319 return -1;
320 }
321
322 // We must set tauBarostat.
323
324 if (!have_tau_barostat) {
325 sprintf( painCave.errMsg,
326 "If you use the NPT integrator, you must set tauBarostat.\n");
327 painCave.severity = OOPSE_ERROR;
328 painCave.isFatal = 1;
329 simError();
330 return -1;
331 }
332
333 if (!have_chi_tolerance) {
334 sprintf( painCave.errMsg,
335 "Setting chi tolerance to 1e-6 in NPT integrator\n");
336 chiTolerance = 1e-6;
337 have_chi_tolerance = 1;
338 painCave.severity = OOPSE_INFO;
339 painCave.isFatal = 0;
340 simError();
341 }
342
343 if (!have_eta_tolerance) {
344 sprintf( painCave.errMsg,
345 "Setting eta tolerance to 1e-6 in NPT integrator");
346 etaTolerance = 1e-6;
347 have_eta_tolerance = 1;
348 painCave.severity = OOPSE_INFO;
349 painCave.isFatal = 0;
350 simError();
351 }
352
353 // We need NkBT a lot, so just set it here: This is the RAW number
354 // of integrableObjects, so no subtraction or addition of constraints or
355 // orientational degrees of freedom:
356
357 NkBT = (double)(info->getTotIntegrableObjects()) * kB * targetTemp;
358
359 // fkBT is used because the thermostat operates on more degrees of freedom
360 // than the barostat (when there are particles with orientational degrees
361 // of freedom).
362
363 fkBT = (double)(info->getNDF()) * kB * targetTemp;
364
365 tt2 = tauThermostat * tauThermostat;
366 tb2 = tauBarostat * tauBarostat;
367
368 return 1;
369 }