OpenMD 3.1
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
FluctuatingChargeNVT.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 appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45#include "FluctuatingChargeNVT.hpp"
46
48#include "utils/Constants.hpp"
49#include "utils/simError.h"
50
51namespace OpenMD {
52
53 FluctuatingChargeNVT::FluctuatingChargeNVT(SimInfo* info) :
54 FluctuatingChargePropagator(info), maxIterNum_(4), chiTolerance_(1e-6),
55 snap(info->getSnapshotManager()->getCurrentSnapshot()), thermo(info) {}
56
57 void FluctuatingChargeNVT::initialize() {
58 FluctuatingChargePropagator::initialize();
59 if (hasFlucQ_) {
60 if (info_->getSimParams()->haveDt()) {
61 dt_ = info_->getSimParams()->getDt();
62 dt2_ = dt_ * 0.5;
63 } else {
64 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
65 "FluctuatingChargeNVT Error: dt is not set\n");
66 painCave.isFatal = 1;
67 simError();
68 }
69
70 if (!info_->getSimParams()->getUseIntialExtendedSystemState()) {
71 snap->setElectronicThermostat(make_pair(0.0, 0.0));
72 }
73
74 if (!fqParams_->haveTargetTemp()) {
75 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
76 "You can't use the FluctuatingChargeNVT "
77 "propagator without a flucQ.targetTemp!\n");
78 painCave.isFatal = 1;
79 painCave.severity = OPENMD_ERROR;
80 simError();
81 } else {
82 targetTemp_ = fqParams_->getTargetTemp();
83 }
84
85 // We must set tauThermostat.
86
87 if (!fqParams_->haveTauThermostat()) {
88 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
89 "If you use the FluctuatingChargeNVT\n"
90 "\tpropagator, you must set flucQ.tauThermostat .\n");
91
92 painCave.severity = OPENMD_ERROR;
93 painCave.isFatal = 1;
94 simError();
95 } else {
96 tauThermostat_ = fqParams_->getTauThermostat();
97 }
98 updateSizes();
99 }
100 }
101
102 void FluctuatingChargeNVT::moveA() {
103 if (!hasFlucQ_) return;
104
105 SimInfo::MoleculeIterator i;
106 Molecule::FluctuatingChargeIterator j;
107 Molecule* mol;
108 Atom* atom;
109 RealType cvel, cpos, cfrc, cmass;
110
111 pair<RealType, RealType> thermostat = snap->getElectronicThermostat();
112 RealType chi = thermostat.first;
113 RealType integralOfChidt = thermostat.second;
114 RealType instTemp = thermo.getElectronicTemperature();
115
116 for (mol = info_->beginMolecule(i); mol != NULL;
117 mol = info_->nextMolecule(i)) {
118 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
119 atom = mol->nextFluctuatingCharge(j)) {
120 cvel = atom->getFlucQVel();
121 cpos = atom->getFlucQPos();
122 cfrc = atom->getFlucQFrc();
123 cmass = atom->getChargeMass();
124
125 // velocity half step
126 cvel += dt2_ * cfrc / cmass - dt2_ * chi * cvel;
127 // position whole step
128 cpos += dt_ * cvel;
129
130 atom->setFlucQVel(cvel);
131 atom->setFlucQPos(cpos);
132 }
133 }
134
135 chi += dt2_ * (instTemp / targetTemp_ - 1.0) /
136 (tauThermostat_ * tauThermostat_);
137
138 integralOfChidt += chi * dt2_;
139 snap->setElectronicThermostat(make_pair(chi, integralOfChidt));
140 }
141
142 void FluctuatingChargeNVT::updateSizes() {
143 oldVel_.resize(info_->getNFluctuatingCharges());
144 }
145
146 void FluctuatingChargeNVT::moveB() {
147 if (!hasFlucQ_) return;
148 SimInfo::MoleculeIterator i;
149 Molecule::FluctuatingChargeIterator j;
150 Molecule* mol;
151 Atom* atom;
152 RealType instTemp;
153 pair<RealType, RealType> thermostat = snap->getElectronicThermostat();
154 RealType chi = thermostat.first;
155 RealType oldChi = chi;
156 RealType prevChi;
157 RealType integralOfChidt = thermostat.second;
158 int index;
159 RealType cfrc, cvel, cmass;
160
161 index = 0;
162 for (mol = info_->beginMolecule(i); mol != NULL;
163 mol = info_->nextMolecule(i)) {
164 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
165 atom = mol->nextFluctuatingCharge(j)) {
166 oldVel_[index] = atom->getFlucQVel();
167 ++index;
168 }
169 }
170
171 // do the iteration:
172
173 for (int k = 0; k < maxIterNum_; k++) {
174 index = 0;
175 instTemp = thermo.getElectronicTemperature();
176 // evolve chi another half step using the temperature at t + dt/2
177 prevChi = chi;
178 chi = oldChi + dt2_ * (instTemp / targetTemp_ - 1.0) /
179 (tauThermostat_ * tauThermostat_);
180
181 for (mol = info_->beginMolecule(i); mol != NULL;
182 mol = info_->nextMolecule(i)) {
183 for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
184 atom = mol->nextFluctuatingCharge(j)) {
185 cfrc = atom->getFlucQFrc();
186 cmass = atom->getChargeMass();
187
188 // velocity half step
189 cvel = oldVel_[index] + dt2_ * cfrc / cmass -
190 dt2_ * chi * oldVel_[index];
191 atom->setFlucQVel(cvel);
192 ++index;
193 }
194 }
195 if (fabs(prevChi - chi) <= chiTolerance_) break;
196 }
197 integralOfChidt += dt2_ * chi;
198 snap->setElectronicThermostat(make_pair(chi, integralOfChidt));
199 }
200
201 void FluctuatingChargeNVT::resetPropagator() {
202 if (!hasFlucQ_) return;
203 snap->setElectronicThermostat(make_pair(0.0, 0.0));
204 }
205
206 RealType FluctuatingChargeNVT::calcConservedQuantity() {
207 if (!hasFlucQ_) return 0.0;
208 pair<RealType, RealType> thermostat = snap->getElectronicThermostat();
209 RealType chi = thermostat.first;
210 RealType integralOfChidt = thermostat.second;
211 RealType fkBT =
212 info_->getNFluctuatingCharges() * Constants::kB * targetTemp_;
213
214 RealType thermostat_kinetic = fkBT * tauThermostat_ * tauThermostat_ * chi *
215 chi / (2.0 * Constants::energyConvert);
216
217 RealType thermostat_potential =
218 fkBT * integralOfChidt / Constants::energyConvert;
219
220 return thermostat_kinetic + thermostat_potential;
221 }
222} // namespace OpenMD
abstract class for propagating fluctuating charge variables
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:93
Molecule * beginMolecule(MoleculeIterator &i)
Returns the first molecule in this SimInfo and intialize the iterator.
Definition SimInfo.cpp:240
int getNFluctuatingCharges()
Returns the total number of fluctuating charges that are present.
Definition SimInfo.hpp:217
Molecule * nextMolecule(MoleculeIterator &i)
Returns the next avaliable Molecule based on the iterator.
Definition SimInfo.cpp:245
void setFlucQVel(RealType cvel)
Sets the current charge velocity of this stuntDouble.
void setFlucQPos(RealType charge)
Sets the current fluctuating charge of this stuntDouble.
RealType getFlucQFrc()
Returns the current charge force of this stuntDouble.
RealType getFlucQPos()
Returns the current fluctuating charge of this stuntDouble.
RealType getFlucQVel()
Returns the current charge velocity of this stuntDouble.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.