ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-4/src/integrators/NPTf.cpp
Revision: 1774
Committed: Tue Nov 23 23:12:23 2004 UTC (19 years, 7 months ago) by tim
File size: 6924 byte(s)
Log Message:
refactory NPT integrator

File Contents

# Content
1 #include <math.h>
2
3 #include "math/MatVec3.h"
4 #include "primitives/Atom.hpp"
5 #include "primitives/SRI.hpp"
6 #include "primitives/AbstractClasses.hpp"
7 #include "brains/SimInfo.hpp"
8 #include "UseTheForce/ForceFields.hpp"
9 #include "brains/Thermo.hpp"
10 #include "io/ReadWrite.hpp"
11 #include "integrators/Integrator.hpp"
12 #include "utils/simError.h"
13
14 #ifdef IS_MPI
15 #include "brains/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* info): NPT(info){
29 GenericData* data;
30 DoubleVectorGenericData * etaValue;
31 int i,j;
32
33 for(i = 0; i < 3; i++){
34 for (j = 0; j < 3; j++){
35
36 eta(i, j) = 0.0;
37 oldEta(i, j) = 0.0;
38 }
39 }
40
41
42 if( theInfo->useInitXSstate ){
43 // retrieve eta array from simInfo if it exists
44 data = info->getPropertyByName(ETAVALUE_ID);
45 if(data){
46 etaValue = dynamic_cast<DoubleVectorGenericData*>(data);
47
48 if(etaValue){
49
50 for(i = 0; i < 3; i++){
51 for (j = 0; j < 3; j++){
52 eta(i, j) = (*etaValue)[3*i+j];
53 oldEta(i, j) = eta(i, j);
54 }
55 }
56 }
57 }
58 }
59
60 }
61
62 NPTf::~NPTf() {
63
64 // empty for now
65 }
66
67 void NPTf::evolveEtaA() {
68
69 int i, j;
70
71 for(i = 0; i < 3; i ++){
72 for(j = 0; j < 3; j++){
73 if( i == j) {
74 eta(i, j) += dt2 * instaVol * (press(i, j) - targetPressure/p_convert) / (NkBT*tb2);
75 } else {
76 eta(i, j) += dt2 * instaVol * press(i, j) / (NkBT*tb2);
77 }
78 }
79 }
80
81 for(i = 0; i < 3; i++) {
82 for (j = 0; j < 3; j++) {
83 oldEta(i, j) = eta(i, j);
84 }
85 }
86
87 }
88
89 void NPTf::evolveEtaB() {
90
91 int i;
92 int j;
93
94 for(i = 0; i < 3; i++) {
95 for (j = 0; j < 3; j++) {
96 prevEta(i, j) = eta(i, j);
97 }
98 }
99
100 for(i = 0; i < 3; i ++){
101 for(j = 0; j < 3; j++){
102 if( i == j) {
103 eta(i, j) = oldEta(i, j) + dt2 * instaVol *
104 (press(i, j) - targetPressure/p_convert) / (NkBT*tb2);
105 } else {
106 eta(i, j) = oldEta(i, j) + dt2 * instaVol * press(i, j) / (NkBT*tb2);
107 }
108 }
109 }
110
111
112 }
113
114 void NPTf::calcVelScale(){
115
116 for (int i = 0; i < 3; i++ ) {
117 for (int j = 0; j < 3; j++ ) {
118 vScale(i, j) = eta(i, j);
119
120 if (i == j) {
121 vScale(i, j) += chi;
122 }
123 }
124 }
125 }
126
127 void NPTf::getVelScaleA(Vector3d& sc, const Vector3d& vel);{
128 sc = vScale * vel;
129 }
130
131 void NPTf::getVelScaleB(Vector3d& sc, int index ) {
132 sc = vScale * oldVel[index];
133 }
134
135 void NPTf::getPosScale(const Vector3d& pos, const Vector3d& COM,
136 int index, Vector3d& sc) {
137
138 /**@todo */
139 Vector3d rj = (oldPos[index] + pos[j])/2.0 -COM;
140 sc = eta * rj;
141 }
142
143 void NPTf::scaleSimBox(){
144
145 int i;
146 int j;
147 int k;
148 Mat3x3d scaleMat;
149 double eta2ij;
150 double bigScale, smallScale, offDiagMax;
151 Mat3x3d hm;
152 Mat3x3d hmnew;
153
154
155
156 // Scale the box after all the positions have been moved:
157
158 // Use a taylor expansion for eta products: Hmat = Hmat . exp(dt * etaMat)
159 // Hmat = Hmat . ( Ident + dt * etaMat + dt^2 * etaMat*etaMat / 2)
160
161 bigScale = 1.0;
162 smallScale = 1.0;
163 offDiagMax = 0.0;
164
165 for(i=0; i<3; i++){
166 for(j=0; j<3; j++){
167
168 // Calculate the matrix Product of the eta array (we only need
169 // the ij element right now):
170
171 eta2ij = 0.0;
172 for(k=0; k<3; k++){
173 eta2ij += eta(i, k) * eta(k, j);
174 }
175
176 scaleMat(i, j) = 0.0;
177 // identity matrix (see above):
178 if (i == j) scaleMat(i, j) = 1.0;
179 // Taylor expansion for the exponential truncated at second order:
180 scaleMat(i, j) += dt*eta(i, j) + 0.5*dt*dt*eta2ij;
181
182
183 if (i != j)
184 if (fabs(scaleMat(i, j)) > offDiagMax)
185 offDiagMax = fabs(scaleMat(i, j));
186 }
187
188 if (scaleMat(i, i) > bigScale) bigScale = scaleMat(i, i);
189 if (scaleMat(i, i) < smallScale) smallScale = scaleMat(i, i);
190 }
191
192 if ((bigScale > 1.01) || (smallScale < 0.99)) {
193 sprintf( painCave.errMsg,
194 "NPTf error: Attempting a Box scaling of more than 1 percent.\n"
195 " Check your tauBarostat, as it is probably too small!\n\n"
196 " scaleMat = [%lf\t%lf\t%lf]\n"
197 " [%lf\t%lf\t%lf]\n"
198 " [%lf\t%lf\t%lf]\n"
199 " eta = [%lf\t%lf\t%lf]\n"
200 " [%lf\t%lf\t%lf]\n"
201 " [%lf\t%lf\t%lf]\n",
202 scaleMat(0, 0),scaleMat(0, 1),scaleMat(0, 2),
203 scaleMat(1, 0),scaleMat(1, 1),scaleMat(1, 2),
204 scaleMat(2, 0),scaleMat(2, 1),scaleMat(2, 2),
205 eta(0, 0),eta(0, 1),eta(0, 2),
206 eta(1, 0),eta(1, 1),eta(1, 2),
207 eta(2, 0),eta(2, 1),eta(2, 2));
208 painCave.isFatal = 1;
209 simError();
210 } else if (offDiagMax > 0.01) {
211 sprintf( painCave.errMsg,
212 "NPTf error: Attempting an off-diagonal Box scaling of more than 1 percent.\n"
213 " Check your tauBarostat, as it is probably too small!\n\n"
214 " scaleMat = [%lf\t%lf\t%lf]\n"
215 " [%lf\t%lf\t%lf]\n"
216 " [%lf\t%lf\t%lf]\n"
217 " eta = [%lf\t%lf\t%lf]\n"
218 " [%lf\t%lf\t%lf]\n"
219 " [%lf\t%lf\t%lf]\n",
220 scaleMat(0, 0),scaleMat(0, 1),scaleMat(0, 2),
221 scaleMat(1, 0),scaleMat(1, 1),scaleMat(1, 2),
222 scaleMat(2, 0),scaleMat(2, 1),scaleMat(2, 2),
223 eta(0, 0),eta(0, 1),eta(0, 2),
224 eta(1, 0),eta(1, 1),eta(1, 2),
225 eta(2, 0),eta(2, 1),eta(2, 2));
226 painCave.isFatal = 1;
227 simError();
228 } else {
229 info->getBoxM(hm);
230 matMul3(hm, scaleMat, hmnew);
231 info->setBoxM(hmnew);
232 }
233 }
234
235 bool NPTf::etaConverged() {
236 int i;
237 double diffEta, sumEta;
238
239 sumEta = 0;
240 for(i = 0; i < 3; i++) {
241 sumEta += pow(prevEta(i, i) - eta(i, i), 2);
242 }
243
244 diffEta = sqrt( sumEta / 3.0 );
245
246 return ( diffEta <= etaTolerance );
247 }
248
249 double NPTf::calcConservedQuantity(){
250
251 double conservedQuantity;
252 double totalEnergy;
253 double thermostat_kinetic;
254 double thermostat_potential;
255 double barostat_kinetic;
256 double barostat_potential;
257 double trEta;
258
259 totalEnergy = tStats->getTotalE();
260
261 thermostat_kinetic = fkBT * tt2 * chi * chi /(2.0 * eConvert);
262
263 thermostat_potential = fkBT* integralOfChidt / eConvert;
264
265 trEta = (eta.transpose() * eta).trace();
266
267 barostat_kinetic = NkBT * tb2 * trEta /(2.0 * eConvert);
268
269 barostat_potential = (targetPressure * tStats->getVolume() / p_convert) /eConvert;
270
271 conservedQuantity = totalEnergy + thermostat_kinetic + thermostat_potential +
272 barostat_kinetic + barostat_potential;
273
274 return conservedQuantity;
275
276 }
277