ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/integrators/NPTf.cpp
Revision: 2759
Committed: Wed May 17 21:51:42 2006 UTC (18 years, 2 months ago) by tim
File size: 9202 byte(s)
Log Message:
Adding single precision capabilities to c++ side

File Contents

# User Rev Content
1 gezelter 2204 /*
2 gezelter 1930 * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9     * 1. Acknowledgement of the program authors must be made in any
10     * publication of scientific results based in part on use of the
11     * program. An acceptable form of acknowledgement is citation of
12     * the article in which the program was described (Matthew
13     * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14     * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15     * Parallel Simulation Engine for Molecular Dynamics,"
16     * J. Comput. Chem. 26, pp. 252-271 (2005))
17     *
18     * 2. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 3. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in the
23     * documentation and/or other materials provided with the
24     * distribution.
25     *
26     * This software is provided "AS IS," without a warranty of any
27     * kind. All express or implied conditions, representations and
28     * warranties, including any implied warranty of merchantability,
29     * fitness for a particular purpose or non-infringement, are hereby
30     * excluded. The University of Notre Dame and its licensors shall not
31     * be liable for any damages suffered by licensee as a result of
32     * using, modifying or distributing the software or its
33     * derivatives. In no event will the University of Notre Dame or its
34     * licensors be liable for any lost revenue, profit or data, or for
35     * direct, indirect, special, consequential, incidental or punitive
36     * damages, however caused and regardless of the theory of liability,
37     * arising out of the use of or inability to use software, even if the
38     * University of Notre Dame has been advised of the possibility of
39     * such damages.
40     */
41    
42 tim 1492 #include "brains/SimInfo.hpp"
43     #include "brains/Thermo.hpp"
44 gezelter 1930 #include "integrators/IntegratorCreator.hpp"
45     #include "integrators/NPTf.hpp"
46     #include "primitives/Molecule.hpp"
47     #include "utils/OOPSEConstant.hpp"
48 tim 1492 #include "utils/simError.h"
49 gezelter 1490
50 gezelter 1930 namespace oopse {
51 gezelter 1490
52 gezelter 2204 // Basic non-isotropic thermostating and barostating via the Melchionna
53     // modification of the Hoover algorithm:
54     //
55     // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
56     // Molec. Phys., 78, 533.
57     //
58     // and
59     //
60     // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
61 gezelter 1490
62 gezelter 2204 void NPTf::evolveEtaA() {
63 gezelter 1490
64 gezelter 2204 int i, j;
65 gezelter 1490
66 gezelter 1930 for(i = 0; i < 3; i ++){
67 gezelter 2204 for(j = 0; j < 3; j++){
68     if( i == j) {
69     eta(i, j) += dt2 * instaVol * (press(i, j) - targetPressure/OOPSEConstant::pressureConvert) / (NkBT*tb2);
70     } else {
71     eta(i, j) += dt2 * instaVol * press(i, j) / (NkBT*tb2);
72     }
73     }
74 gezelter 1490 }
75 gezelter 1930
76     for(i = 0; i < 3; i++) {
77 gezelter 2204 for (j = 0; j < 3; j++) {
78 gezelter 1930 oldEta(i, j) = eta(i, j);
79 gezelter 2204 }
80 gezelter 1490 }
81 gezelter 1930
82 gezelter 2204 }
83 gezelter 1490
84 gezelter 2204 void NPTf::evolveEtaB() {
85 gezelter 1490
86 gezelter 1930 int i;
87     int j;
88 gezelter 1490
89 gezelter 1930 for(i = 0; i < 3; i++) {
90 gezelter 2204 for (j = 0; j < 3; j++) {
91     prevEta(i, j) = eta(i, j);
92     }
93 gezelter 1930 }
94 gezelter 1490
95 gezelter 1930 for(i = 0; i < 3; i ++){
96 gezelter 2204 for(j = 0; j < 3; j++){
97     if( i == j) {
98     eta(i, j) = oldEta(i, j) + dt2 * instaVol *
99     (press(i, j) - targetPressure/OOPSEConstant::pressureConvert) / (NkBT*tb2);
100     } else {
101     eta(i, j) = oldEta(i, j) + dt2 * instaVol * press(i, j) / (NkBT*tb2);
102     }
103     }
104 gezelter 1930 }
105 gezelter 1490
106    
107 gezelter 2204 }
108 gezelter 1490
109 gezelter 2204 void NPTf::calcVelScale(){
110 gezelter 1490
111 gezelter 2204 for (int i = 0; i < 3; i++ ) {
112     for (int j = 0; j < 3; j++ ) {
113     vScale(i, j) = eta(i, j);
114 gezelter 1490
115 gezelter 2204 if (i == j) {
116     vScale(i, j) += chi;
117     }
118 gezelter 1490 }
119     }
120     }
121    
122 gezelter 2204 void NPTf::getVelScaleA(Vector3d& sc, const Vector3d& vel){
123 gezelter 1930 sc = vScale * vel;
124 gezelter 2204 }
125 gezelter 1490
126 gezelter 2204 void NPTf::getVelScaleB(Vector3d& sc, int index ) {
127     sc = vScale * oldVel[index];
128     }
129 gezelter 1490
130 gezelter 2204 void NPTf::getPosScale(const Vector3d& pos, const Vector3d& COM, int index, Vector3d& sc) {
131 gezelter 1490
132 gezelter 1930 /**@todo */
133 tim 2759 Vector3d rj = (oldPos[index] + pos)/(RealType)2.0 -COM;
134 gezelter 1930 sc = eta * rj;
135 gezelter 2204 }
136 gezelter 1490
137 gezelter 2204 void NPTf::scaleSimBox(){
138 gezelter 1490
139 gezelter 2204 int i;
140     int j;
141     int k;
142     Mat3x3d scaleMat;
143 tim 2759 RealType eta2ij;
144     RealType bigScale, smallScale, offDiagMax;
145 gezelter 2204 Mat3x3d hm;
146     Mat3x3d hmnew;
147 gezelter 1490
148    
149    
150 gezelter 2204 // Scale the box after all the positions have been moved:
151 gezelter 1490
152 gezelter 2204 // Use a taylor expansion for eta products: Hmat = Hmat . exp(dt * etaMat)
153     // Hmat = Hmat . ( Ident + dt * etaMat + dt^2 * etaMat*etaMat / 2)
154 gezelter 1490
155 gezelter 2204 bigScale = 1.0;
156     smallScale = 1.0;
157     offDiagMax = 0.0;
158 gezelter 1490
159 gezelter 2204 for(i=0; i<3; i++){
160     for(j=0; j<3; j++){
161 gezelter 1490
162 gezelter 2204 // Calculate the matrix Product of the eta array (we only need
163     // the ij element right now):
164 gezelter 1490
165 gezelter 2204 eta2ij = 0.0;
166     for(k=0; k<3; k++){
167     eta2ij += eta(i, k) * eta(k, j);
168     }
169 gezelter 1490
170 gezelter 2204 scaleMat(i, j) = 0.0;
171     // identity matrix (see above):
172     if (i == j) scaleMat(i, j) = 1.0;
173     // Taylor expansion for the exponential truncated at second order:
174     scaleMat(i, j) += dt*eta(i, j) + 0.5*dt*dt*eta2ij;
175 gezelter 1490
176    
177 gezelter 2204 if (i != j)
178     if (fabs(scaleMat(i, j)) > offDiagMax)
179     offDiagMax = fabs(scaleMat(i, j));
180     }
181    
182     if (scaleMat(i, i) > bigScale) bigScale = scaleMat(i, i);
183     if (scaleMat(i, i) < smallScale) smallScale = scaleMat(i, i);
184 gezelter 1490 }
185    
186 gezelter 2204 if ((bigScale > 1.01) || (smallScale < 0.99)) {
187     sprintf( painCave.errMsg,
188     "NPTf error: Attempting a Box scaling of more than 1 percent.\n"
189     " Check your tauBarostat, as it is probably too small!\n\n"
190     " scaleMat = [%lf\t%lf\t%lf]\n"
191     " [%lf\t%lf\t%lf]\n"
192     " [%lf\t%lf\t%lf]\n"
193     " eta = [%lf\t%lf\t%lf]\n"
194     " [%lf\t%lf\t%lf]\n"
195     " [%lf\t%lf\t%lf]\n",
196     scaleMat(0, 0),scaleMat(0, 1),scaleMat(0, 2),
197     scaleMat(1, 0),scaleMat(1, 1),scaleMat(1, 2),
198     scaleMat(2, 0),scaleMat(2, 1),scaleMat(2, 2),
199     eta(0, 0),eta(0, 1),eta(0, 2),
200     eta(1, 0),eta(1, 1),eta(1, 2),
201     eta(2, 0),eta(2, 1),eta(2, 2));
202     painCave.isFatal = 1;
203     simError();
204     } else if (offDiagMax > 0.01) {
205     sprintf( painCave.errMsg,
206     "NPTf error: Attempting an off-diagonal Box scaling of more than 1 percent.\n"
207     " Check your tauBarostat, as it is probably too small!\n\n"
208     " scaleMat = [%lf\t%lf\t%lf]\n"
209     " [%lf\t%lf\t%lf]\n"
210     " [%lf\t%lf\t%lf]\n"
211     " eta = [%lf\t%lf\t%lf]\n"
212     " [%lf\t%lf\t%lf]\n"
213     " [%lf\t%lf\t%lf]\n",
214     scaleMat(0, 0),scaleMat(0, 1),scaleMat(0, 2),
215     scaleMat(1, 0),scaleMat(1, 1),scaleMat(1, 2),
216     scaleMat(2, 0),scaleMat(2, 1),scaleMat(2, 2),
217     eta(0, 0),eta(0, 1),eta(0, 2),
218     eta(1, 0),eta(1, 1),eta(1, 2),
219     eta(2, 0),eta(2, 1),eta(2, 2));
220     painCave.isFatal = 1;
221     simError();
222     } else {
223 gezelter 1490
224 gezelter 2204 Mat3x3d hmat = currentSnapshot_->getHmat();
225     hmat = hmat *scaleMat;
226     currentSnapshot_->setHmat(hmat);
227 gezelter 1930
228 gezelter 2204 }
229 gezelter 1490 }
230    
231 gezelter 2204 bool NPTf::etaConverged() {
232 gezelter 1930 int i;
233 tim 2759 RealType diffEta, sumEta;
234 gezelter 1490
235 gezelter 1930 sumEta = 0;
236     for(i = 0; i < 3; i++) {
237 gezelter 2204 sumEta += pow(prevEta(i, i) - eta(i, i), 2);
238 gezelter 1930 }
239    
240     diffEta = sqrt( sumEta / 3.0 );
241 gezelter 1490
242 gezelter 1930 return ( diffEta <= etaTolerance );
243 gezelter 2204 }
244 gezelter 1490
245 tim 2759 RealType NPTf::calcConservedQuantity(){
246 gezelter 1490
247 gezelter 1930 chi= currentSnapshot_->getChi();
248     integralOfChidt = currentSnapshot_->getIntegralOfChiDt();
249     loadEta();
250    
251     // We need NkBT a lot, so just set it here: This is the RAW number
252     // of integrableObjects, so no subtraction or addition of constraints or
253     // orientational degrees of freedom:
254     NkBT = info_->getNGlobalIntegrableObjects()*OOPSEConstant::kB *targetTemp;
255 gezelter 1490
256 gezelter 1930 // fkBT is used because the thermostat operates on more degrees of freedom
257     // than the barostat (when there are particles with orientational degrees
258     // of freedom).
259     fkBT = info_->getNdf()*OOPSEConstant::kB *targetTemp;
260    
261 tim 2759 RealType conservedQuantity;
262     RealType totalEnergy;
263     RealType thermostat_kinetic;
264     RealType thermostat_potential;
265     RealType barostat_kinetic;
266     RealType barostat_potential;
267     RealType trEta;
268 gezelter 1490
269 gezelter 1930 totalEnergy = thermo.getTotalE();
270 gezelter 1490
271 gezelter 1930 thermostat_kinetic = fkBT * tt2 * chi * chi /(2.0 * OOPSEConstant::energyConvert);
272 gezelter 1490
273 gezelter 1930 thermostat_potential = fkBT* integralOfChidt / OOPSEConstant::energyConvert;
274 gezelter 1490
275 tim 2759 SquareMatrix<RealType, 3> tmp = eta.transpose() * eta;
276 gezelter 1930 trEta = tmp.trace();
277    
278     barostat_kinetic = NkBT * tb2 * trEta /(2.0 * OOPSEConstant::energyConvert);
279 gezelter 1490
280 gezelter 1930 barostat_potential = (targetPressure * thermo.getVolume() / OOPSEConstant::pressureConvert) /OOPSEConstant::energyConvert;
281 gezelter 1490
282 gezelter 1930 conservedQuantity = totalEnergy + thermostat_kinetic + thermostat_potential +
283 gezelter 2204 barostat_kinetic + barostat_potential;
284 gezelter 1490
285 gezelter 1930 return conservedQuantity;
286 gezelter 1490
287 gezelter 2204 }
288 gezelter 1490
289 gezelter 2204 void NPTf::loadEta() {
290 gezelter 1930 eta= currentSnapshot_->getEta();
291 gezelter 1490
292 gezelter 1930 //if (!eta.isDiagonal()) {
293     // sprintf( painCave.errMsg,
294     // "NPTf error: the diagonal elements of eta matrix are not the same or etaMat is not a diagonal matrix");
295     // painCave.isFatal = 1;
296     // simError();
297     //}
298 gezelter 2204 }
299 gezelter 1490
300 gezelter 2204 void NPTf::saveEta() {
301 gezelter 1930 currentSnapshot_->setEta(eta);
302 gezelter 2204 }
303 gezelter 1490
304     }