ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTxym.cpp
Revision: 755
Committed: Tue Sep 9 20:35:25 2003 UTC (20 years, 10 months ago) by mmeineke
File size: 8536 byte(s)
Log Message:
updated the ChangeLog

added two new NPT integrators, they still need work.

File Contents

# User Rev Content
1 mmeineke 755 #include <cmath>
2     #include "Atom.hpp"
3     #include "Molecule.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 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 NPTxym variant scales the molecular center-of-mass coordinates
25     // instead of the atomic coordinates
26    
27     template<typename T> NPTxym<T>::NPTxym ( SimInfo *theInfo, ForceFields* the_ff):
28     T( theInfo, the_ff )
29     {
30     chi = 0.0;
31     eta = 0.0;
32     etaX = 0.0;
33     etaY = 0.0;
34     have_tau_thermostat = 0;
35     have_tau_barostat = 0;
36     have_target_temp = 0;
37     have_target_pressure = 0;
38     }
39    
40     template<typename T> void NPTxym<T>::moveA() {
41    
42     int i, j, k;
43     DirectionalAtom* dAtom;
44     double Tb[3], ji[3];
45     double A[3][3], I[3][3];
46     double angle, mass;
47     double vel[3], pos[3], frc[3];
48    
49     double rj[3];
50     double instaTemp, instaPress, instaPressZ, instaVol;
51     double tt2, tb2;
52     double scaleFactor, scaleFactorZ, scaleFactorX, scaleFactorY, bigFactor;
53     double hm[3][3], hmnew[3][3], scaleMat[3][3];
54     double scF3;
55    
56    
57     int nInMol;
58     double rc[3];
59    
60     nMols = info->n_mol;
61     myMolecules = info->molecules;
62    
63     tt2 = tauThermostat * tauThermostat;
64     tb2 = tauBarostat * tauBarostat;
65    
66     instaTemp = tStats->getTemperature();
67     instaPress = tStats->getPressure();
68     instaPressX = tStats->getPressureX();
69     instaPressY = tstats->getPressureY();
70     instaVol = tStats->getVolume();
71    
72     // first evolve chi a half step
73    
74     chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
75     eta += dt2 * ( instaVol * (instaPress - targetPressure) /
76     (p_convert*NkBT*tb2));
77     etaX += dt2 * ( instaVol * (instaPressX - targetPressure) /
78     (p_convert*NkBT*tb2));
79     etaY += dt2 * ( instaVol * (instaPressY - targetPressure) /
80     (p_convert*NkBT*tb2));
81    
82     for( i = 0; i < nMols; i++) {
83    
84     myMolecules[i].getCOM(rc);
85    
86     nInMol = myMolecules[i].getNAtoms();
87     myAtoms = myMolecules[i].getMyAtoms();
88    
89     // find the minimum image coordinates of the molecular centers of mass:
90    
91     info->wrapVector(rc);
92    
93     for (j = 0; j < nInMol; j++) {
94    
95     if(myAtoms[j] != NULL) {
96    
97     myAtoms[j]->getVel( vel );
98     myAtoms[j]->getPos( pos );
99     myAtoms[j]->getFrc( frc );
100    
101     mass = myAtoms[j]->getMass();
102    
103     for (k=0; k < 3; k++)
104     vel[k] += dt2 * ((frc[k] / mass ) * eConvert - vel[k]*(chi+eta));
105    
106     myAtoms[j]->setVel( vel );
107    
108     for (k = 0; k < 3; k++)
109     pos[k] += dt * (vel[k] + eta*rc[k]);
110    
111     myAtoms[j]->setPos( pos );
112    
113     if( myAtoms[j]->isDirectional() ){
114    
115     dAtom = (DirectionalAtom *)myAtoms[j];
116    
117     // get and convert the torque to body frame
118    
119     dAtom->getTrq( Tb );
120     dAtom->lab2Body( Tb );
121    
122     // get the angular momentum, and propagate a half step
123    
124     dAtom->getJ( ji );
125    
126     for (k=0; k < 3; k++)
127     ji[k] += dt2 * (Tb[k] * eConvert - ji[k]*chi);
128    
129     // use the angular velocities to propagate the rotation matrix a
130     // full time step
131    
132     dAtom->getA(A);
133     dAtom->getI(I);
134    
135     // rotate about the x-axis
136     angle = dt2 * ji[0] / I[0][0];
137     this->rotate( 1, 2, angle, ji, A );
138    
139     // rotate about the y-axis
140     angle = dt2 * ji[1] / I[1][1];
141     this->rotate( 2, 0, angle, ji, A );
142    
143     // rotate about the z-axis
144     angle = dt * ji[2] / I[2][2];
145     this->rotate( 0, 1, angle, ji, A);
146    
147     // rotate about the y-axis
148     angle = dt2 * ji[1] / I[1][1];
149     this->rotate( 2, 0, angle, ji, A );
150    
151     // rotate about the x-axis
152     angle = dt2 * ji[0] / I[0][0];
153     this->rotate( 1, 2, angle, ji, A );
154    
155     dAtom->setJ( ji );
156     dAtom->setA( A );
157     }
158     }
159     }
160     }
161    
162     // Scale the box after all the positions have been moved:
163    
164     scaleFactorX = exp(dt*etaX);
165     scaleFactorY = exp(dt*etaY);
166     scaleFactor = exp(dt*eta);
167    
168     bigFactor = abs( 1.0 - scaleFactorX );
169     if( abs(1.0 - scaleFactorY) > bigFactor )
170     bigFactor = abs(1.0 - scaleFactorY);
171     if( abs(1.0 - scaleFactor) > bigFactor )
172     bigFactor = abs(1.0 - scaleFactor);
173    
174     if (bigFactor > 0.1) {
175     sprintf( painCave.errMsg,
176     "NPTxym error: Attempting a Box scaling of more than 10 percent"
177     " check your tauBarostat, as it is probably too small!\n"
178     " eta = %lf, scaleFactor = %lf\n"
179     " etaX = %lf, scaleFactorX = %lf\n",
180     " etaY = %lf, scaleFactorY = %lf\n",
181     eta, scaleFactor,
182     etaX, scaleFactorX,
183     etaY, scaleFactorY
184     );
185     painCave.isFatal = 1;
186     simError();
187     } else {
188    
189     for(i=0;i<3;i++)
190     for(j=0;j<3;j++)
191     scaleBox[i][j] = 0.0;
192    
193     scF3 = scaleFactor * scaleFactor * scaleFactor;
194     scaleFactorZ = scF3 / (scaleFactorX * scaleFactorY);
195    
196     scaleBox[0][0] = scaleFactorX;
197     scaleBox[1][1] = scaleFactorY;
198     scaleBox[2][2] = scaleFactorZ;
199    
200     info->getBoxM( hm );
201     info->matMul3( hm, scaleBox, hmnew );
202    
203     info->setBoxM( hmnew );
204     }
205     }
206    
207     template<typename T> void NPTxym<T>::moveB( void ){
208     int i, j;
209     DirectionalAtom* dAtom;
210     double Tb[3], ji[3];
211     double vel[3], frc[3];
212     double mass;
213    
214     double instaTemp, instaPress, instaPressX, instaPressY, instaVol;
215     double tt2, tb2;
216    
217     tt2 = tauThermostat * tauThermostat;
218     tb2 = tauBarostat * tauBarostat;
219    
220     instaTemp = tStats->getTemperature();
221     instaPress = tStats->getPressure();
222     instaPressX = tStats->getPressureX();
223     instaPressY = tstats->getPressureY();
224     instaVol = tStats->getVolume();
225    
226     chi += dt2 * ( instaTemp / targetTemp - 1.0) / tt2;
227     eta += dt2 * ( instaVol * (instaPress - targetPressure) /
228     (p_convert*NkBT*tb2));
229     etaX += dt2 * ( instaVol * (instaPressX - targetPressure) /
230     (p_convert*NkBT*tb2));
231     etaY += dt2 * ( instaVol * (instaPressY - targetPressure) /
232     (p_convert*NkBT*tb2));
233    
234     for( i=0; i<nAtoms; i++ ){
235    
236     atoms[i]->getVel( vel );
237     atoms[i]->getFrc( frc );
238    
239     mass = atoms[i]->getMass();
240    
241     // velocity half step
242     for (j=0; j < 3; j++)
243     vel[j] += dt2 * ((frc[j] / mass ) * eConvert - vel[j]*(chi+eta));
244    
245     atoms[i]->setVel( vel );
246    
247     if( atoms[i]->isDirectional() ){
248    
249     dAtom = (DirectionalAtom *)atoms[i];
250    
251     // get and convert the torque to body frame
252    
253     dAtom->getTrq( Tb );
254     dAtom->lab2Body( Tb );
255    
256     // get the angular momentum, and propagate a half step
257    
258     dAtom->getJ( ji );
259    
260     for (j=0; j < 3; j++)
261     ji[j] += dt2 * (Tb[j] * eConvert - ji[j]*chi);
262    
263     dAtom->setJ( ji );
264     }
265     }
266     }
267    
268     template<typename T> void NPTxym<T>::resetIntegrator() {
269     chi = 0.0;
270     eta = 0.0;
271     etaX = 0.0;
272     etaY = 0.0;
273     }
274    
275     template<typename T> int NPTxym<T>::readyCheck() {
276    
277     //check parent's readyCheck() first
278     if (T::readyCheck() == -1)
279     return -1;
280    
281     // First check to see if we have a target temperature.
282     // Not having one is fatal.
283    
284     if (!have_target_temp) {
285     sprintf( painCave.errMsg,
286     "NPTxym error: You can't use the NPTxym integrator\n"
287     " without a targetTemp!\n"
288     );
289     painCave.isFatal = 1;
290     simError();
291     return -1;
292     }
293    
294     if (!have_target_pressure) {
295     sprintf( painCave.errMsg,
296     "NPTxym error: You can't use the NPTxym integrator\n"
297     " without a targetPressure!\n"
298     );
299     painCave.isFatal = 1;
300     simError();
301     return -1;
302     }
303    
304     // We must set tauThermostat.
305    
306     if (!have_tau_thermostat) {
307     sprintf( painCave.errMsg,
308     "NPTxym error: If you use the NPTxym\n"
309     " integrator, you must set tauThermostat.\n");
310     painCave.isFatal = 1;
311     simError();
312     return -1;
313     }
314    
315     // We must set tauBarostat.
316    
317     if (!have_tau_barostat) {
318     sprintf( painCave.errMsg,
319     "NPTxym error: If you use the NPTxym\n"
320     " integrator, you must set tauBarostat.\n");
321     painCave.isFatal = 1;
322     simError();
323     return -1;
324     }
325    
326     // We need NkBT a lot, so just set it here:
327    
328     NkBT = (double)info->ndf * kB * targetTemp;
329    
330     return 1;
331     }