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

# Content
1 #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