ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/NPTf.cpp
Revision: 857
Committed: Fri Nov 7 17:09:48 2003 UTC (20 years, 8 months ago) by mmeineke
File size: 7196 byte(s)
Log Message:
moved the velocity scale matrix calculation outside of the atom loop in the NPT family of integrators.

File Contents

# Content
1 #include <math.h>
2
3 #include "Atom.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 #ifdef IS_MPI
14 #include "mpiSimulation.hpp"
15 #endif
16
17 // Basic non-isotropic thermostating and barostating via the Melchionna
18 // modification of the Hoover algorithm:
19 //
20 // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
21 // Molec. Phys., 78, 533.
22 //
23 // and
24 //
25 // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
26
27 template<typename T> NPTf<T>::NPTf ( SimInfo *theInfo, ForceFields* the_ff):
28 T( theInfo, the_ff )
29 {
30 GenericData* data;
31 DoubleArrayData * etaValue;
32 vector<double> etaArray;
33 int i,j;
34
35 for(i = 0; i < 3; i++){
36 for (j = 0; j < 3; j++){
37
38 eta[i][j] = 0.0;
39 oldEta[i][j] = 0.0;
40 }
41 }
42
43
44 if( theInfo->useInitXSstate ){
45 // retrieve eta array from simInfo if it exists
46 data = info->getProperty(ETAVALUE_ID);
47 if(data){
48 etaValue = dynamic_cast<DoubleArrayData*>(data);
49
50 if(etaValue){
51 etaArray = etaValue->getData();
52
53 for(i = 0; i < 3; i++){
54 for (j = 0; j < 3; j++){
55 eta[i][j] = etaArray[3*i+j];
56 oldEta[i][j] = eta[i][j];
57 }
58 }
59 }
60 }
61 }
62
63 }
64
65 template<typename T> NPTf<T>::~NPTf() {
66
67 // empty for now
68 }
69
70 template<typename T> void NPTf<T>::resetIntegrator() {
71
72 int i, j;
73
74 for(i = 0; i < 3; i++)
75 for (j = 0; j < 3; j++)
76 eta[i][j] = 0.0;
77
78 T::resetIntegrator();
79 }
80
81 template<typename T> void NPTf<T>::evolveEtaA() {
82
83 int i, j;
84
85 for(i = 0; i < 3; i ++){
86 for(j = 0; j < 3; j++){
87 if( i == j)
88 eta[i][j] += dt2 * instaVol *
89 (press[i][j] - targetPressure/p_convert) / (NkBT*tb2);
90 else
91 eta[i][j] += dt2 * instaVol * press[i][j] / (NkBT*tb2);
92 }
93 }
94
95 for(i = 0; i < 3; i++)
96 for (j = 0; j < 3; j++)
97 oldEta[i][j] = eta[i][j];
98 }
99
100 template<typename T> void NPTf<T>::evolveEtaB() {
101
102 int i,j;
103
104 for(i = 0; i < 3; i++)
105 for (j = 0; j < 3; j++)
106 prevEta[i][j] = eta[i][j];
107
108 for(i = 0; i < 3; i ++){
109 for(j = 0; j < 3; j++){
110 if( i == j) {
111 eta[i][j] = oldEta[i][j] + dt2 * instaVol *
112 (press[i][j] - targetPressure/p_convert) / (NkBT*tb2);
113 } else {
114 eta[i][j] = oldEta[i][j] + dt2 * instaVol * press[i][j] / (NkBT*tb2);
115 }
116 }
117 }
118 }
119
120 template<typename T> void NPTf<T>::calcVelScale(void){
121 int i,j;
122
123 for (i = 0; i < 3; i++ ) {
124 for (j = 0; j < 3; j++ ) {
125 vScale[i][j] = eta[i][j];
126
127 if (i == j) {
128 vScale[i][j] += chi;
129 }
130 }
131 }
132 }
133
134 template<typename T> void NPTf<T>::getVelScaleA(double sc[3], double vel[3]) {
135
136 info->matVecMul3( vScale, vel, sc );
137 }
138
139 template<typename T> void NPTf<T>::getVelScaleB(double sc[3], int index ){
140 int j;
141 double myVel[3];
142 double vScale[3][3];
143
144 for (j = 0; j < 3; j++)
145 myVel[j] = oldVel[3*index + j];
146
147 info->matVecMul3( vScale, myVel, sc );
148 }
149
150 template<typename T> void NPTf<T>::getPosScale(double pos[3], double COM[3],
151 int index, double sc[3]){
152 int j;
153 double rj[3];
154
155 for(j=0; j<3; j++)
156 rj[j] = ( oldPos[index*3+j] + pos[j]) / 2.0 - COM[j];
157
158 info->matVecMul3( eta, rj, sc );
159 }
160
161 template<typename T> void NPTf<T>::scaleSimBox( void ){
162
163 int i,j,k;
164 double scaleMat[3][3];
165 double eta2ij;
166 double bigScale, smallScale, offDiagMax;
167 double hm[3][3], hmnew[3][3];
168
169
170
171 // Scale the box after all the positions have been moved:
172
173 // Use a taylor expansion for eta products: Hmat = Hmat . exp(dt * etaMat)
174 // Hmat = Hmat . ( Ident + dt * etaMat + dt^2 * etaMat*etaMat / 2)
175
176 bigScale = 1.0;
177 smallScale = 1.0;
178 offDiagMax = 0.0;
179
180 for(i=0; i<3; i++){
181 for(j=0; j<3; j++){
182
183 // Calculate the matrix Product of the eta array (we only need
184 // the ij element right now):
185
186 eta2ij = 0.0;
187 for(k=0; k<3; k++){
188 eta2ij += eta[i][k] * eta[k][j];
189 }
190
191 scaleMat[i][j] = 0.0;
192 // identity matrix (see above):
193 if (i == j) scaleMat[i][j] = 1.0;
194 // Taylor expansion for the exponential truncated at second order:
195 scaleMat[i][j] += dt*eta[i][j] + 0.5*dt*dt*eta2ij;
196
197 if (i != j)
198 if (fabs(scaleMat[i][j]) > offDiagMax)
199 offDiagMax = fabs(scaleMat[i][j]);
200 }
201
202 if (scaleMat[i][i] > bigScale) bigScale = scaleMat[i][i];
203 if (scaleMat[i][i] < smallScale) smallScale = scaleMat[i][i];
204 }
205
206 if ((bigScale > 1.01) || (smallScale < 0.99)) {
207 sprintf( painCave.errMsg,
208 "NPTf error: Attempting a Box scaling of more than 1 percent.\n"
209 " Check your tauBarostat, as it is probably too small!\n\n"
210 " scaleMat = [%lf\t%lf\t%lf]\n"
211 " [%lf\t%lf\t%lf]\n"
212 " [%lf\t%lf\t%lf]\n",
213 scaleMat[0][0],scaleMat[0][1],scaleMat[0][2],
214 scaleMat[1][0],scaleMat[1][1],scaleMat[1][2],
215 scaleMat[2][0],scaleMat[2][1],scaleMat[2][2]);
216 painCave.isFatal = 1;
217 simError();
218 } else if (offDiagMax > 0.01) {
219 sprintf( painCave.errMsg,
220 "NPTf error: Attempting an off-diagonal Box scaling of more than 1 percent.\n"
221 " Check your tauBarostat, as it is probably too small!\n\n"
222 " scaleMat = [%lf\t%lf\t%lf]\n"
223 " [%lf\t%lf\t%lf]\n"
224 " [%lf\t%lf\t%lf]\n",
225 scaleMat[0][0],scaleMat[0][1],scaleMat[0][2],
226 scaleMat[1][0],scaleMat[1][1],scaleMat[1][2],
227 scaleMat[2][0],scaleMat[2][1],scaleMat[2][2]);
228 painCave.isFatal = 1;
229 simError();
230 } else {
231 info->getBoxM(hm);
232 info->matMul3(hm, scaleMat, hmnew);
233 info->setBoxM(hmnew);
234 }
235 }
236
237 template<typename T> bool NPTf<T>::etaConverged() {
238 int i;
239 double diffEta, sumEta;
240
241 sumEta = 0;
242 for(i = 0; i < 3; i++)
243 sumEta += pow(prevEta[i][i] - eta[i][i], 2);
244
245 diffEta = sqrt( sumEta / 3.0 );
246
247 return ( diffEta <= etaTolerance );
248 }
249
250 template<typename T> double NPTf<T>::getConservedQuantity(void){
251
252 double conservedQuantity;
253 double totalEnergy;
254 double thermostat_kinetic;
255 double thermostat_potential;
256 double barostat_kinetic;
257 double barostat_potential;
258 double trEta;
259 double a[3][3], b[3][3];
260
261 totalEnergy = tStats->getTotalE();
262
263 thermostat_kinetic = fkBT * tt2 * chi * chi /
264 (2.0 * eConvert);
265
266 thermostat_potential = fkBT* integralOfChidt / eConvert;
267
268 info->transposeMat3(eta, a);
269 info->matMul3(a, eta, b);
270 trEta = info->matTrace3(b);
271
272 barostat_kinetic = NkBT * tb2 * trEta /
273 (2.0 * eConvert);
274
275 barostat_potential = (targetPressure * tStats->getVolume() / p_convert) /
276 eConvert;
277
278 conservedQuantity = totalEnergy + thermostat_kinetic + thermostat_potential +
279 barostat_kinetic + barostat_potential;
280
281 return conservedQuantity;
282
283 }
284
285 template<typename T> string NPTf<T>::getAdditionalParameters(void){
286 string parameters;
287 const int BUFFERSIZE = 2000; // size of the read buffer
288 char buffer[BUFFERSIZE];
289
290 sprintf(buffer,"\t%G\t%G;", chi, integralOfChidt);
291 parameters += buffer;
292
293 for(int i = 0; i < 3; i++){
294 sprintf(buffer,"\t%G\t%G\t%G;", eta[i][0], eta[i][1], eta[i][2]);
295 parameters += buffer;
296 }
297
298 return parameters;
299
300 }