ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NVT.cpp
Revision: 560
Committed: Fri Jun 20 16:49:33 2003 UTC (21 years ago) by gezelter
File size: 5162 byte(s)
Log Message:
NVT additions

File Contents

# User Rev Content
1 gezelter 560 #include "Atom.hpp"
2     #include "SRI.hpp"
3     #include "AbstractClasses.hpp"
4     #include "SimInfo.hpp"
5     #include "ForceFields.hpp"
6     #include "Thermo.hpp"
7     #include "ReadWrite.hpp"
8     #include "Integrator.hpp"
9     #include "NVT.hpp"
10    
11     // Basic thermostating via Hoover, Phys.Rev.A, 1985, Vol. 31 (5) 1695-1697
12    
13     NVT::NVT() {
14     zeta = 0.0;
15     have_tau_thermostat = 0;
16     have_target_temp = 0;
17     have_qmass = 0;
18     }
19    
20     void NVT::moveA() {
21    
22     int i,j,k;
23     int atomIndex, aMatIndex;
24     DirectionalAtom* dAtom;
25     double Tb[3];
26     double ji[3];
27    
28     ke = tStats->getKinetic() * eConvert;
29     zeta += dt2 * ( (2.0 * ke - NkBT) / qmass );
30    
31     for( i=0; i<nAtoms; i++ ){
32     atomIndex = i * 3;
33     aMatIndex = i * 9;
34    
35     // velocity half step
36     for( j=atomIndex; j<(atomIndex+3); j++ )
37     vel[j] += dt2 * ((frc[j]/atoms[i]->getMass())*eConvert - vel[j]*zeta);
38    
39     // position whole step
40     for( j=atomIndex; j<(atomIndex+3); j++ )
41     pos[j] += dt * vel[j];
42    
43    
44     if( atoms[i]->isDirectional() ){
45    
46     dAtom = (DirectionalAtom *)atoms[i];
47    
48     // get and convert the torque to body frame
49    
50     Tb[0] = dAtom->getTx();
51     Tb[1] = dAtom->getTy();
52     Tb[2] = dAtom->getTz();
53    
54     dAtom->lab2Body( Tb );
55    
56     // get the angular momentum, and propagate a half step
57    
58     ji[0] = dAtom->getJx();
59     ji[1] = dAtom->getJy();
60     ji[2] = dAtom->getJz();
61    
62     ji[0] += dt2 * (Tb[0] * eConvert - ji[0]*zeta);
63     ji[1] += dt2 * (Tb[1] * eConvert - ji[1]*zeta);
64     ji[2] += dt2 * (Tb[2] * eConvert - ji[2]*zeta);
65    
66     // use the angular velocities to propagate the rotation matrix a
67     // full time step
68    
69     // rotate about the x-axis
70     angle = dt2 * ji[0] / dAtom->getIxx();
71     this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
72    
73     // rotate about the y-axis
74     angle = dt2 * ji[1] / dAtom->getIyy();
75     this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
76    
77     // rotate about the z-axis
78     angle = dt * ji[2] / dAtom->getIzz();
79     this->rotate( 0, 1, angle, ji, &aMat[aMatIndex] );
80    
81     // rotate about the y-axis
82     angle = dt2 * ji[1] / dAtom->getIyy();
83     this->rotate( 2, 0, angle, ji, &aMat[aMatIndex] );
84    
85     // rotate about the x-axis
86     angle = dt2 * ji[0] / dAtom->getIxx();
87     this->rotate( 1, 2, angle, ji, &aMat[aMatIndex] );
88    
89     dAtom->setJx( ji[0] );
90     dAtom->setJy( ji[1] );
91     dAtom->setJz( ji[2] );
92     }
93    
94     }
95     }
96    
97     void Integrator::moveB( void ){
98     int i,j,k;
99     int atomIndex;
100     DirectionalAtom* dAtom;
101     double Tb[3];
102     double ji[3];
103    
104     ke = tStats->getKinetic() * eConvert;
105     zeta += dt2 * ( (2.0 * ke - NkBT) / qmass );
106    
107     for( i=0; i<nAtoms; i++ ){
108     atomIndex = i * 3;
109    
110     // velocity half step
111     for( j=atomIndex; j<(atomIndex+3); j++ )
112     vel[j] += dt2 * ((frc[j]/atoms[i]->getMass())*eConvert - vel[j]*zeta);
113    
114     if( atoms[i]->isDirectional() ){
115    
116     dAtom = (DirectionalAtom *)atoms[i];
117    
118     // get and convert the torque to body frame
119    
120     Tb[0] = dAtom->getTx();
121     Tb[1] = dAtom->getTy();
122     Tb[2] = dAtom->getTz();
123    
124     dAtom->lab2Body( Tb );
125    
126     // get the angular momentum, and complete the angular momentum
127     // half step
128    
129     ji[0] = dAtom->getJx();
130     ji[1] = dAtom->getJy();
131     ji[2] = dAtom->getJz();
132    
133     ji[0] += dt2 * (Tb[0] * eConvert - ji[0]*zeta);
134     ji[1] += dt2 * (Tb[1] * eConvert - ji[1]*zeta);
135     ji[2] += dt2 * (Tb[2] * eConvert - ji[2]*zeta);
136    
137     jx2 = ji[0] * ji[0];
138     jy2 = ji[1] * ji[1];
139     jz2 = ji[2] * ji[2];
140    
141     dAtom->setJx( ji[0] );
142     dAtom->setJy( ji[1] );
143     dAtom->setJz( ji[2] );
144     }
145     }
146     }
147    
148     int NVT::readyCheck() {
149     double NkBT;
150    
151     // First check to see if we have a target temperature.
152     // Not having one is fatal.
153    
154     if (!have_target_temp) {
155     sprintf( painCave.errMsg,
156     "NVT error: You can't use the NVT integrator without a targetTemp!\n"
157     );
158     painCave.isFatal = 1;
159     simError();
160     return -1;
161     }
162    
163     // Next check to see that we have a reasonable number of degrees of freedom
164     // and then set NkBT if we do have it. Unreasonable numbers of DOFs
165     // are also fatal.
166    
167     if (entry_plug->ndf > 0) {
168     NkBT = (double)entry_plug->ndf * kB * targetTemp;
169     } else {
170     sprintf( painCave.errMsg,
171     "NVT error: We got a silly number of degrees of freedom!\n"
172     );
173     painCave.isFatal = 1;
174     simError();
175     return -1;
176     }
177    
178     // We have our choice on setting qmass or tauThermostat. One of them
179     // must be set.
180    
181     if (!have_qmass) {
182     if (have_tau_thermostat) {
183     sprintf( painCave.errMsg,
184     "NVT info: Setting qMass = %d\n", tauThermostat * NkBT);
185     this->setQmass(tauThermostat * NkBT);
186     painCave.isFatal = 0;
187     simError();
188     } else {
189     sprintf( painCave.errMsg,
190     "NVT error: If you use the constant temperature\n"
191     " integrator, you must set either tauThermostat or qMass.\n");
192     painCave.isFatal = 1;
193     simError();
194     return -1;
195     }
196     }
197    
198     return 1;
199     }
200    
201     #endif