ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTim.cpp
Revision: 605
Committed: Tue Jul 15 03:27:24 2003 UTC (20 years, 11 months ago) by gezelter
File size: 6440 byte(s)
Log Message:
Bugfix in NPTim, fixes for NPTfm

File Contents

# User Rev Content
1 gezelter 596 #include <cmath>
2     #include "Atom.hpp"
3 gezelter 604 #include "Molecule.hpp"
4 gezelter 596 #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 isotropic thermostating and barostating via the Melchionna
15     // modification of the Hoover algorithm:
16     //
17     // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
18     // Molec. Phys., 78, 533.
19     //
20     // and
21     //
22     // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
23    
24     // The NPTim variant scales the molecular center-of-mass coordinates
25     // instead of the atomic coordinates
26    
27     NPTim::NPTim ( SimInfo *theInfo, ForceFields* the_ff):
28     Integrator( theInfo, the_ff )
29     {
30     chi = 0.0;
31     eta = 0.0;
32     have_tau_thermostat = 0;
33     have_tau_barostat = 0;
34     have_target_temp = 0;
35     have_target_pressure = 0;
36     }
37    
38     void NPTim::moveA() {
39    
40 gezelter 605 int i, j, k;
41 gezelter 596 DirectionalAtom* dAtom;
42 gezelter 604 double Tb[3], ji[3];
43     double A[3][3], I[3][3];
44     double angle, mass;
45     double vel[3], pos[3], frc[3];
46    
47     double rj[3];
48 gezelter 596 double instaTemp, instaPress, instaVol;
49     double tt2, tb2;
50    
51 gezelter 604 int nInMol;
52     double rc[3];
53    
54 gezelter 596 nMols = info->n_mol;
55 gezelter 604 myMolecules = info->molecules;
56 gezelter 596
57     tt2 = tauThermostat * tauThermostat;
58     tb2 = tauBarostat * tauBarostat;
59    
60     instaTemp = tStats->getTemperature();
61     instaPress = tStats->getPressure();
62     instaVol = tStats->getVolume();
63    
64     // first evolve chi a half step
65    
66     chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
67     eta += dt2 * ( instaVol * (instaPress - targetPressure) /
68     (p_convert*NkBT*tb2));
69    
70     for( i = 0; i < nMols; i++) {
71    
72 gezelter 604 myMolecules[i].getCOM(rc);
73 gezelter 596
74 gezelter 604 nInMol = myMolecules[i].getNAtoms();
75     myAtoms = myMolecules[i].getMyAtoms();
76 gezelter 596
77     // find the minimum image coordinates of the molecular centers of mass:
78    
79     info->wrapVector(rc);
80    
81     for (j = 0; j < nInMol; j++) {
82    
83 gezelter 604 if(myAtoms[j] != NULL) {
84 gezelter 596
85 gezelter 605 myAtoms[j]->getVel( vel );
86     myAtoms[j]->getPos( pos );
87     myAtoms[j]->getFrc( frc );
88 gezelter 596
89 gezelter 605 mass = myAtoms[j]->getMass();
90 gezelter 596
91 gezelter 605 for (k=0; k < 3; k++)
92     vel[k] += dt2 * ((frc[k] / mass ) * eConvert - vel[k]*(chi+eta));
93 gezelter 596
94 gezelter 605 myAtoms[j]->setVel( vel );
95 gezelter 596
96 gezelter 605 for (k = 0; k < 3; k++)
97     pos[k] += dt * (vel[k] + eta*rc[k]);
98 gezelter 596
99 gezelter 605 myAtoms[j]->setPos( pos );
100 gezelter 596
101 gezelter 604 if( myAtoms[j]->isDirectional() ){
102 gezelter 596
103 gezelter 604 dAtom = (DirectionalAtom *)myAtoms[j];
104 gezelter 596
105     // get and convert the torque to body frame
106 gezelter 604
107     dAtom->getTrq( Tb );
108 gezelter 596 dAtom->lab2Body( Tb );
109 gezelter 604
110 gezelter 596 // get the angular momentum, and propagate a half step
111    
112 gezelter 604 dAtom->getJ( ji );
113    
114 gezelter 605 for (k=0; k < 3; k++)
115     ji[k] += dt2 * (Tb[k] * eConvert - ji[k]*chi);
116 gezelter 596
117     // use the angular velocities to propagate the rotation matrix a
118     // full time step
119    
120 gezelter 604 dAtom->getA(A);
121     dAtom->getI(I);
122    
123 gezelter 596 // rotate about the x-axis
124 gezelter 604 angle = dt2 * ji[0] / I[0][0];
125     this->rotate( 1, 2, angle, ji, A );
126 gezelter 596
127     // rotate about the y-axis
128 gezelter 604 angle = dt2 * ji[1] / I[1][1];
129     this->rotate( 2, 0, angle, ji, A );
130 gezelter 596
131     // rotate about the z-axis
132 gezelter 604 angle = dt * ji[2] / I[2][2];
133     this->rotate( 0, 1, angle, ji, A);
134 gezelter 596
135     // rotate about the y-axis
136 gezelter 604 angle = dt2 * ji[1] / I[1][1];
137     this->rotate( 2, 0, angle, ji, A );
138 gezelter 596
139     // rotate about the x-axis
140 gezelter 604 angle = dt2 * ji[0] / I[0][0];
141     this->rotate( 1, 2, angle, ji, A );
142 gezelter 596
143 gezelter 604 dAtom->setJ( ji );
144     dAtom->setA( A );
145     }
146 gezelter 596 }
147     }
148     }
149     // Scale the box after all the positions have been moved:
150    
151     cerr << "eta = " << eta
152     << "; exp(dt*eta) = " << exp(eta*dt) << "\n";
153    
154     info->scaleBox(exp(dt*eta));
155     }
156    
157 gezelter 604 void NPTim::moveB( void ){
158     int i, j;
159 gezelter 596 DirectionalAtom* dAtom;
160 gezelter 604 double Tb[3], ji[3];
161     double vel[3], frc[3];
162     double mass;
163    
164 gezelter 596 double instaTemp, instaPress, instaVol;
165     double tt2, tb2;
166 gezelter 604
167 gezelter 596 tt2 = tauThermostat * tauThermostat;
168     tb2 = tauBarostat * tauBarostat;
169    
170     instaTemp = tStats->getTemperature();
171     instaPress = tStats->getPressure();
172     instaVol = tStats->getVolume();
173    
174     chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
175     eta += dt2 * ( instaVol * (instaPress - targetPressure) /
176     (p_convert*NkBT*tb2));
177    
178     for( i=0; i<nAtoms; i++ ){
179    
180 gezelter 604 atoms[i]->getVel( vel );
181     atoms[i]->getFrc( frc );
182    
183     mass = atoms[i]->getMass();
184    
185 gezelter 596 // velocity half step
186 gezelter 604 for (j=0; j < 3; j++)
187     vel[j] += dt2 * ((frc[j] / mass ) * eConvert - vel[j]*(chi+eta));
188 gezelter 596
189 gezelter 604 atoms[i]->setVel( vel );
190    
191 gezelter 596 if( atoms[i]->isDirectional() ){
192    
193     dAtom = (DirectionalAtom *)atoms[i];
194    
195 gezelter 604 // get and convert the torque to body frame
196 gezelter 596
197 gezelter 604 dAtom->getTrq( Tb );
198 gezelter 596 dAtom->lab2Body( Tb );
199    
200 gezelter 604 // get the angular momentum, and propagate a half step
201 gezelter 596
202 gezelter 604 dAtom->getJ( ji );
203 gezelter 596
204 gezelter 604 for (j=0; j < 3; j++)
205     ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
206 gezelter 596
207 gezelter 604 dAtom->setJ( ji );
208 gezelter 596 }
209     }
210     }
211    
212 gezelter 604 int NPTim::readyCheck() {
213 gezelter 596
214     // First check to see if we have a target temperature.
215     // Not having one is fatal.
216    
217     if (!have_target_temp) {
218     sprintf( painCave.errMsg,
219 gezelter 604 "NPTim error: You can't use the NPTim integrator\n"
220 gezelter 596 " without a targetTemp!\n"
221     );
222     painCave.isFatal = 1;
223     simError();
224     return -1;
225     }
226    
227     if (!have_target_pressure) {
228     sprintf( painCave.errMsg,
229 gezelter 604 "NPTim error: You can't use the NPTim integrator\n"
230 gezelter 596 " without a targetPressure!\n"
231     );
232     painCave.isFatal = 1;
233     simError();
234     return -1;
235     }
236    
237     // We must set tauThermostat.
238    
239     if (!have_tau_thermostat) {
240     sprintf( painCave.errMsg,
241 gezelter 604 "NPTim error: If you use the NPTim\n"
242 gezelter 596 " integrator, you must set tauThermostat.\n");
243     painCave.isFatal = 1;
244     simError();
245     return -1;
246     }
247    
248     // We must set tauBarostat.
249    
250     if (!have_tau_barostat) {
251     sprintf( painCave.errMsg,
252 gezelter 604 "NPTim error: If you use the NPTim\n"
253 gezelter 596 " integrator, you must set tauBarostat.\n");
254     painCave.isFatal = 1;
255     simError();
256     return -1;
257     }
258    
259     // We need NkBT a lot, so just set it here:
260    
261     NkBT = (double)info->ndf * kB * targetTemp;
262    
263     return 1;
264     }