ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTi.cpp
Revision: 600
Committed: Mon Jul 14 22:38:13 2003 UTC (20 years, 11 months ago) by gezelter
File size: 5658 byte(s)
Log Message:
Fixes for get and set routines in Atom and DirectionalAtom

File Contents

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