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

# User Rev Content
1 gezelter 829 #include <math.h>
2 mmeineke 857
3 gezelter 576 #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 tim 837 #include "simError.h"
12 gezelter 576
13 gezelter 772 #ifdef IS_MPI
14     #include "mpiSimulation.hpp"
15     #endif
16 gezelter 576
17 gezelter 578 // Basic non-isotropic thermostating and barostating via the Melchionna
18 gezelter 576 // modification of the Hoover algorithm:
19     //
20     // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
21 tim 837 // Molec. Phys., 78, 533.
22 gezelter 576 //
23     // and
24 tim 837 //
25 gezelter 576 // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
26    
27 tim 645 template<typename T> NPTf<T>::NPTf ( SimInfo *theInfo, ForceFields* the_ff):
28     T( theInfo, the_ff )
29 gezelter 576 {
30 tim 837 GenericData* data;
31     DoubleArrayData * etaValue;
32     vector<double> etaArray;
33 mmeineke 780 int i,j;
34 tim 837
35 mmeineke 780 for(i = 0; i < 3; i++){
36     for (j = 0; j < 3; j++){
37 tim 837
38 gezelter 588 eta[i][j] = 0.0;
39 mmeineke 780 oldEta[i][j] = 0.0;
40     }
41     }
42 tim 837
43 mmeineke 855
44     if( theInfo->useInitXSstate ){
45 tim 837 // retrieve eta array from simInfo if it exists
46     data = info->getProperty(ETAVALUE_ID);
47     if(data){
48     etaValue = dynamic_cast<DoubleArrayData*>(data);
49 mmeineke 855
50 tim 837 if(etaValue){
51 mmeineke 855 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 tim 837 }
60     }
61 mmeineke 855 }
62 tim 837
63 mmeineke 780 }
64 gezelter 588
65 mmeineke 780 template<typename T> NPTf<T>::~NPTf() {
66 tim 767
67 mmeineke 780 // empty for now
68     }
69 tim 767
70 mmeineke 780 template<typename T> void NPTf<T>::resetIntegrator() {
71 tim 837
72 mmeineke 780 int i, j;
73 tim 837
74 mmeineke 780 for(i = 0; i < 3; i++)
75     for (j = 0; j < 3; j++)
76     eta[i][j] = 0.0;
77 tim 837
78 mmeineke 780 T::resetIntegrator();
79 gezelter 576 }
80    
81 mmeineke 780 template<typename T> void NPTf<T>::evolveEtaA() {
82 tim 837
83 mmeineke 780 int i, j;
84 tim 837
85 mmeineke 780 for(i = 0; i < 3; i ++){
86     for(j = 0; j < 3; j++){
87     if( i == j)
88 tim 837 eta[i][j] += dt2 * instaVol *
89 mmeineke 780 (press[i][j] - targetPressure/p_convert) / (NkBT*tb2);
90     else
91     eta[i][j] += dt2 * instaVol * press[i][j] / (NkBT*tb2);
92     }
93     }
94 tim 837
95 mmeineke 780 for(i = 0; i < 3; i++)
96     for (j = 0; j < 3; j++)
97     oldEta[i][j] = eta[i][j];
98 tim 767 }
99    
100 mmeineke 780 template<typename T> void NPTf<T>::evolveEtaB() {
101 tim 837
102 mmeineke 780 int i,j;
103 gezelter 772
104 mmeineke 780 for(i = 0; i < 3; i++)
105     for (j = 0; j < 3; j++)
106     prevEta[i][j] = eta[i][j];
107 mmeineke 778
108 mmeineke 780 for(i = 0; i < 3; i ++){
109     for(j = 0; j < 3; j++){
110     if( i == j) {
111 tim 837 eta[i][j] = oldEta[i][j] + dt2 * instaVol *
112 mmeineke 780 (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 gezelter 600
120 mmeineke 857 template<typename T> void NPTf<T>::calcVelScale(void){
121 mmeineke 780 int i,j;
122 gezelter 576
123 gezelter 588 for (i = 0; i < 3; i++ ) {
124     for (j = 0; j < 3; j++ ) {
125 tim 767 vScale[i][j] = eta[i][j];
126 tim 837
127 gezelter 588 if (i == j) {
128 tim 837 vScale[i][j] += chi;
129     }
130 gezelter 588 }
131     }
132 mmeineke 857 }
133 tim 837
134 mmeineke 857 template<typename T> void NPTf<T>::getVelScaleA(double sc[3], double vel[3]) {
135    
136 mmeineke 780 info->matVecMul3( vScale, vel, sc );
137     }
138 gezelter 600
139 mmeineke 780 template<typename T> void NPTf<T>::getVelScaleB(double sc[3], int index ){
140 mmeineke 857 int j;
141 mmeineke 780 double myVel[3];
142     double vScale[3][3];
143 gezelter 600
144 mmeineke 780 for (j = 0; j < 3; j++)
145     myVel[j] = oldVel[3*index + j];
146 tim 767
147 mmeineke 780 info->matVecMul3( vScale, myVel, sc );
148     }
149 tim 767
150 tim 837 template<typename T> void NPTf<T>::getPosScale(double pos[3], double COM[3],
151 mmeineke 780 int index, double sc[3]){
152     int j;
153     double rj[3];
154 tim 767
155 mmeineke 780 for(j=0; j<3; j++)
156     rj[j] = ( oldPos[index*3+j] + pos[j]) / 2.0 - COM[j];
157 tim 767
158 mmeineke 780 info->matVecMul3( eta, rj, sc );
159     }
160 tim 767
161 mmeineke 780 template<typename T> void NPTf<T>::scaleSimBox( void ){
162 tim 767
163 mmeineke 780 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 tim 767
169 mmeineke 780
170 tim 837
171 gezelter 577 // Scale the box after all the positions have been moved:
172 tim 837
173 gezelter 578 // Use a taylor expansion for eta products: Hmat = Hmat . exp(dt * etaMat)
174     // Hmat = Hmat . ( Ident + dt * etaMat + dt^2 * etaMat*etaMat / 2)
175 tim 837
176 gezelter 617 bigScale = 1.0;
177     smallScale = 1.0;
178     offDiagMax = 0.0;
179 tim 837
180 gezelter 578 for(i=0; i<3; i++){
181     for(j=0; j<3; j++){
182 tim 837
183 gezelter 588 // Calculate the matrix Product of the eta array (we only need
184     // the ij element right now):
185 tim 837
186 gezelter 588 eta2ij = 0.0;
187 gezelter 578 for(k=0; k<3; k++){
188 gezelter 588 eta2ij += eta[i][k] * eta[k][j];
189 gezelter 578 }
190 tim 837
191 gezelter 588 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 gezelter 617
197     if (i != j)
198 tim 837 if (fabs(scaleMat[i][j]) > offDiagMax)
199 gezelter 617 offDiagMax = fabs(scaleMat[i][j]);
200 gezelter 578 }
201 gezelter 617
202     if (scaleMat[i][i] > bigScale) bigScale = scaleMat[i][i];
203     if (scaleMat[i][i] < smallScale) smallScale = scaleMat[i][i];
204 gezelter 578 }
205 tim 837
206 mmeineke 853 if ((bigScale > 1.01) || (smallScale < 0.99)) {
207 gezelter 617 sprintf( painCave.errMsg,
208 mmeineke 853 "NPTf error: Attempting a Box scaling of more than 1 percent.\n"
209 gezelter 617 " 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 mmeineke 853 } else if (offDiagMax > 0.01) {
219 gezelter 617 sprintf( painCave.errMsg,
220 mmeineke 853 "NPTf error: Attempting an off-diagonal Box scaling of more than 1 percent.\n"
221 gezelter 617 " 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 gezelter 576 }
236    
237 mmeineke 780 template<typename T> bool NPTf<T>::etaConverged() {
238     int i;
239     double diffEta, sumEta;
240 gezelter 600
241 mmeineke 780 sumEta = 0;
242 tim 767 for(i = 0; i < 3; i++)
243 tim 837 sumEta += pow(prevEta[i][i] - eta[i][i], 2);
244    
245 mmeineke 780 diffEta = sqrt( sumEta / 3.0 );
246 tim 837
247 mmeineke 780 return ( diffEta <= etaTolerance );
248 gezelter 576 }
249    
250 mmeineke 780 template<typename T> double NPTf<T>::getConservedQuantity(void){
251 tim 837
252 tim 763 double conservedQuantity;
253 mmeineke 782 double totalEnergy;
254 gezelter 772 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 tim 763
261 mmeineke 782 totalEnergy = tStats->getTotalE();
262 tim 763
263 tim 837 thermostat_kinetic = fkBT * tt2 * chi * chi /
264 gezelter 772 (2.0 * eConvert);
265 tim 763
266 gezelter 772 thermostat_potential = fkBT* integralOfChidt / eConvert;
267 tim 763
268 gezelter 772 info->transposeMat3(eta, a);
269     info->matMul3(a, eta, b);
270     trEta = info->matTrace3(b);
271 tim 767
272 tim 837 barostat_kinetic = NkBT * tb2 * trEta /
273 gezelter 772 (2.0 * eConvert);
274 tim 837
275     barostat_potential = (targetPressure * tStats->getVolume() / p_convert) /
276 gezelter 772 eConvert;
277 tim 767
278 mmeineke 782 conservedQuantity = totalEnergy + thermostat_kinetic + thermostat_potential +
279 gezelter 772 barostat_kinetic + barostat_potential;
280 tim 837
281     return conservedQuantity;
282    
283 tim 763 }
284 tim 837
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 mmeineke 853 sprintf(buffer,"\t%G\t%G;", chi, integralOfChidt);
291 tim 837 parameters += buffer;
292    
293     for(int i = 0; i < 3; i++){
294 mmeineke 853 sprintf(buffer,"\t%G\t%G\t%G;", eta[i][0], eta[i][1], eta[i][2]);
295 tim 837 parameters += buffer;
296     }
297    
298     return parameters;
299    
300     }