ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NVT.cpp
Revision: 561
Committed: Fri Jun 20 20:29:36 2003 UTC (21 years ago) by mmeineke
File size: 5157 byte(s)
Log Message:
Most of the integrator and NVT seem to be working now.

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