ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTi.cpp
Revision: 611
Committed: Tue Jul 15 17:10:50 2003 UTC (20 years, 11 months ago) by gezelter
File size: 5997 byte(s)
Log Message:
Fixing  pressure tensor

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 gezelter 611 double tt2, tb2, scaleFactor;
46 gezelter 574
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 611
131 gezelter 577 // Scale the box after all the positions have been moved:
132 gezelter 600
133 gezelter 611 scaleFactor = exp(dt*eta);
134    
135     if (scaleFactor > 1.1 || scaleFactor < 0.9) {
136     sprintf( painCave.errMsg,
137     "NPTi error: Attempting a Box scaling of more than 10 percent"
138     " check your tauBarostat, as it is probably too small!\n"
139     " eta = %lf, scaleFactor = %lf\n", eta, scaleFactor
140     );
141     painCave.isFatal = 1;
142     simError();
143     } else {
144     info->scaleBox(exp(dt*eta));
145     }
146 gezelter 574 }
147    
148     void NPTi::moveB( void ){
149 gezelter 600
150     int i, j;
151 gezelter 574 DirectionalAtom* dAtom;
152 gezelter 600 double Tb[3], ji[3];
153     double vel[3], frc[3];
154     double mass;
155    
156 gezelter 574 double instaTemp, instaPress, instaVol;
157     double tt2, tb2;
158    
159     tt2 = tauThermostat * tauThermostat;
160     tb2 = tauBarostat * tauBarostat;
161    
162     instaTemp = tStats->getTemperature();
163     instaPress = tStats->getPressure();
164     instaVol = tStats->getVolume();
165    
166     chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
167 mmeineke 586 eta += dt2 * ( instaVol * (instaPress - targetPressure) /
168     (p_convert*NkBT*tb2));
169 gezelter 574
170     for( i=0; i<nAtoms; i++ ){
171 gezelter 600
172     atoms[i]->getVel( vel );
173     atoms[i]->getFrc( frc );
174    
175     mass = atoms[i]->getMass();
176    
177 gezelter 574 // velocity half step
178 gezelter 600 for (j=0; j < 3; j++)
179     vel[j] += dt2 * ((frc[j] / mass ) * eConvert - vel[j]*(chi+eta));
180 gezelter 574
181 gezelter 600 atoms[i]->setVel( vel );
182    
183 gezelter 574 if( atoms[i]->isDirectional() ){
184 gezelter 600
185 gezelter 574 dAtom = (DirectionalAtom *)atoms[i];
186 gezelter 600
187     // get and convert the torque to body frame
188    
189     dAtom->getTrq( Tb );
190 gezelter 574 dAtom->lab2Body( Tb );
191 gezelter 600
192     // get the angular momentum, and propagate a half step
193    
194     dAtom->getJ( ji );
195    
196     for (j=0; j < 3; j++)
197     ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
198    
199     dAtom->setJ( ji );
200 gezelter 574 }
201     }
202     }
203    
204     int NPTi::readyCheck() {
205    
206     // First check to see if we have a target temperature.
207     // Not having one is fatal.
208    
209     if (!have_target_temp) {
210     sprintf( painCave.errMsg,
211     "NPTi error: You can't use the NPTi integrator\n"
212     " without a targetTemp!\n"
213     );
214     painCave.isFatal = 1;
215     simError();
216     return -1;
217     }
218    
219     if (!have_target_pressure) {
220     sprintf( painCave.errMsg,
221     "NPTi error: You can't use the NPTi integrator\n"
222     " without a targetPressure!\n"
223     );
224     painCave.isFatal = 1;
225     simError();
226     return -1;
227     }
228    
229     // We must set tauThermostat.
230    
231     if (!have_tau_thermostat) {
232     sprintf( painCave.errMsg,
233     "NPTi error: If you use the NPTi\n"
234     " integrator, you must set tauThermostat.\n");
235     painCave.isFatal = 1;
236     simError();
237     return -1;
238     }
239    
240     // We must set tauBarostat.
241    
242     if (!have_tau_barostat) {
243     sprintf( painCave.errMsg,
244     "NPTi error: If you use the NPTi\n"
245     " integrator, you must set tauBarostat.\n");
246     painCave.isFatal = 1;
247     simError();
248     return -1;
249     }
250    
251     // We need NkBT a lot, so just set it here:
252    
253     NkBT = (double)info->ndf * kB * targetTemp;
254    
255     return 1;
256     }