ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new-templateless/OOPSE/libmdtools/NPTf.cpp
Revision: 850
Committed: Mon Nov 3 22:07:17 2003 UTC (20 years, 9 months ago) by mmeineke
File size: 7406 byte(s)
Log Message:
begun work on removing templates and most of standard template library from OOPSE.

File Contents

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