OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
NPTi.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48#include "NPTi.hpp"
49
50#include "brains/SimInfo.hpp"
51#include "brains/Thermo.hpp"
52#include "integrators/NPT.hpp"
54#include "utils/Constants.hpp"
55#include "utils/simError.h"
56
57namespace OpenMD {
58
59 // Basic isotropic thermostating and barostating via the Melchionna
60 // modification of the Hoover algorithm:
61 //
62 // Melchionna, S., Ciccotti, G., and Holian, B. L., 1993,
63 // Molec. Phys., 78, 533.
64 //
65 // and
66 //
67 // Hoover, W. G., 1986, Phys. Rev. A, 34, 2499.
68
69 NPTi::NPTi(SimInfo* info) : NPT(info) {}
70
71 void NPTi::evolveEtaA() {
72 eta += dt2 * (instaVol * (instaPress - targetPressure) /
73 (Constants::pressureConvert * NkBT * tb2));
74 oldEta = eta;
75 }
76
77 void NPTi::evolveEtaB() {
78 prevEta = eta;
79 eta = oldEta + dt2 * (instaVol * (instaPress - targetPressure) /
80 (Constants::pressureConvert * NkBT * tb2));
81 }
82
83 void NPTi::calcVelScale() { vScale = thermostat.first + eta; }
84
85 void NPTi::getVelScaleA(Vector3d& sc, const Vector3d& vel) {
86 sc = vel * vScale;
87 }
88
89 void NPTi::getVelScaleB(Vector3d& sc, int index) {
90 sc = oldVel[index] * vScale;
91 }
92
93 void NPTi::getPosScale(const Vector3d& pos, const Vector3d& COM, int index,
94 Vector3d& sc) {
95 /**@todo*/
96 sc = (oldPos[index] + pos) / (RealType)2.0 - COM;
97 sc *= eta;
98 }
99
100 void NPTi::scaleSimBox() {
101 RealType scaleFactor;
102
103 scaleFactor = exp(dt * eta);
104
105 if ((scaleFactor > 1.1) || (scaleFactor < 0.9)) {
106 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
107 "NPTi error: Attempting a Box scaling of more than 10 percent"
108 " check your tauBarostat, as it is probably too small!\n"
109 " eta = %lf, scaleFactor = %lf\n",
110 eta, scaleFactor);
111 painCave.isFatal = 1;
112 simError();
113 } else {
114 Mat3x3d hmat = snap->getHmat();
115 hmat *= scaleFactor;
116 snap->setHmat(hmat);
117 }
118 }
119
120 bool NPTi::etaConverged() { return (fabs(prevEta - eta) <= etaTolerance); }
121
122 RealType NPTi::calcConservedQuantity() {
123 thermostat = snap->getThermostat();
124 loadEta();
125 // We need NkBT a lot, so just set it here: This is the RAW number
126 // of integrableObjects, so no subtraction or addition of constraints or
127 // orientational degrees of freedom:
128 NkBT = info_->getNGlobalIntegrableObjects() * Constants::kB * targetTemp;
129
130 // fkBT is used because the thermostat operates on more degrees of freedom
131 // than the barostat (when there are particles with orientational degrees
132 // of freedom).
133 fkBT = info_->getNdf() * Constants::kB * targetTemp;
134
135 RealType conservedQuantity;
136 RealType Energy;
137 RealType thermostat_kinetic;
138 RealType thermostat_potential;
139 RealType barostat_kinetic;
140 RealType barostat_potential;
141
142 Energy = thermo.getTotalEnergy();
143
144 thermostat_kinetic = fkBT * tt2 * thermostat.first * thermostat.first /
145 (2.0 * Constants::energyConvert);
146
147 thermostat_potential = fkBT * thermostat.second / Constants::energyConvert;
148
149 barostat_kinetic =
150 3.0 * NkBT * tb2 * eta * eta / (2.0 * Constants::energyConvert);
151
152 barostat_potential =
153 (targetPressure * thermo.getVolume() / Constants::pressureConvert) /
154 Constants::energyConvert;
155
156 conservedQuantity = Energy + thermostat_kinetic + thermostat_potential +
157 barostat_kinetic + barostat_potential;
158
159 return conservedQuantity;
160 }
161
162 void NPTi::loadEta() {
163 Mat3x3d etaMat = snap->getBarostat();
164 eta = etaMat(0, 0);
165 // if (fabs(etaMat(1,1) - eta) >= OpenMD::epsilon || fabs(etaMat(1,1) - eta)
166 // >= OpenMD::epsilon || !etaMat.isDiagonal()) {
167 // snprintf( painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
168 // "NPTi error: the diagonal elements of eta matrix are not the
169 // same or etaMat is not a diagonal matrix");
170 // painCave.isFatal = 1;
171 // simError();
172 //}
173 }
174
175 void NPTi::saveEta() {
176 Mat3x3d etaMat(0.0);
177 etaMat(0, 0) = eta;
178 etaMat(1, 1) = eta;
179 etaMat(2, 2) = eta;
180 snap->setBarostat(etaMat);
181 }
182} // namespace OpenMD
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:96
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.