OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
Velocitizer.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 "brains/Velocitizer.hpp"
46
47#include <memory>
48#include <random>
49
50#include "brains/Thermo.hpp"
51#include "flucq/FluctuatingChargeConstraints.hpp"
55#include "types/FluctuatingChargeAdapter.hpp"
56#include "utils/Constants.hpp"
57#include "utils/RandNumGen.hpp"
58
59namespace OpenMD {
60
61 Velocitizer::Velocitizer(SimInfo* info) :
62 info_(info), thermo_(info), globals_(info->getSimParams()),
63 randNumGen_(info->getRandomNumberGenerator()) {}
64
65 void Velocitizer::scale(RealType lambda) {
66 SimInfo::MoleculeIterator mi;
67 Molecule::IntegrableObjectIterator ioi;
68 Molecule* mol;
69 StuntDouble* sd;
70 Vector3d v, j;
71
72 for (mol = info_->beginMolecule(mi); mol != NULL;
73 mol = info_->nextMolecule(mi)) {
74 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
75 sd = mol->nextIntegrableObject(ioi)) {
76 v = sd->getVel();
77 v *= lambda;
78 sd->setVel(v);
79
80 if (sd->isDirectional()) {
81 j = sd->getJ();
82 j *= lambda;
83 sd->setJ(j);
84 }
85 }
86 }
87
89
90 // Remove angular drift if we are not using periodic boundary
91 // conditions:
92
93 if (!globals_->getUsePeriodicBoundaryConditions()) removeAngularDrift();
94 }
95
96 void Velocitizer::randomize(RealType temperature) {
97 Vector3d v;
98 Vector3d j;
99 Mat3x3d I;
100 int l, m, n;
101 Vector3d vdrift;
102 RealType vbar;
103 RealType jbar;
104 RealType av2;
105 RealType kebar;
106
107 SimInfo::MoleculeIterator mi;
108 Molecule::IntegrableObjectIterator ioi;
109 Molecule* mol;
110 StuntDouble* sd;
111
112 std::normal_distribution<RealType> normalDistribution {0.0, 1.0};
113
114 kebar = Constants::kB * temperature * info_->getNdfRaw() /
115 (2.0 * info_->getNdf());
116 for (mol = info_->beginMolecule(mi); mol != NULL;
117 mol = info_->nextMolecule(mi)) {
118 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
119 sd = mol->nextIntegrableObject(ioi)) {
120 // uses equipartition theory to solve for vbar in angstrom/fs
121
122 av2 = 2.0 * kebar / sd->getMass();
123 vbar = sqrt(av2);
124
125 // picks random velocities from a gaussian distribution
126 // centered on vbar
127
128 for (int k = 0; k < 3; k++) {
129 v[k] = vbar * normalDistribution(*randNumGen_);
130 }
131 sd->setVel(v);
132
133 if (sd->isDirectional()) {
134 I = sd->getI();
135
136 if (sd->isLinear()) {
137 l = sd->linearAxis();
138 m = (l + 1) % 3;
139 n = (l + 2) % 3;
140
141 j[l] = 0.0;
142 jbar = sqrt(2.0 * kebar * I(m, m));
143 j[m] = jbar * normalDistribution(*randNumGen_);
144 jbar = sqrt(2.0 * kebar * I(n, n));
145 j[n] = jbar * normalDistribution(*randNumGen_);
146 } else {
147 for (int k = 0; k < 3; k++) {
148 jbar = sqrt(2.0 * kebar * I(k, k));
149 j[k] = jbar * normalDistribution(*randNumGen_);
150 }
151 }
152
153 sd->setJ(j);
154 }
155 }
156 }
157
159
160 // Remove angular drift if we are not using periodic boundary
161 // conditions:
162
163 if (!globals_->getUsePeriodicBoundaryConditions()) removeAngularDrift();
164 }
165
166 void Velocitizer::randomizeChargeVelocity(RealType temperature) {
167 RealType aw2;
168 RealType kebar;
169 RealType wbar;
170
171 SimInfo::MoleculeIterator mi;
172 Molecule::IntegrableObjectIterator ioi;
173 Molecule* mol;
174 StuntDouble* sd;
176 FluctuatingChargeConstraints* fqConstraints;
177
178 std::normal_distribution<RealType> normalDistribution {0.0, 1.0};
179
180 Globals* simParams = info_->getSimParams();
181 fqParams = simParams->getFluctuatingChargeParameters();
182
183 fqConstraints = new FluctuatingChargeConstraints(info_);
184 fqConstraints->setConstrainRegions(fqParams->getConstrainRegions());
185
186 int nConstrain =
187 fqConstraints
188 ->getNumberOfFlucQConstraints(); // no of constraints in charge
189 int dfRaw = fqConstraints->getNumberOfFlucQAtoms(); // no of FlucQ freedom
190 int dfActual = dfRaw - nConstrain;
191 kebar = dfRaw * Constants::kb * temperature / (2 * dfActual);
192
193 for (mol = info_->beginMolecule(mi); mol != NULL;
194 mol = info_->nextMolecule(mi)) {
195 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
196 sd = mol->nextIntegrableObject(ioi)) {
197 if (sd->isAtom()) {
198 Atom* atom = static_cast<Atom*>(sd);
199 AtomType* atomType = atom->getAtomType();
201 if (fqa.isFluctuatingCharge()) {
202 // uses equipartition theory to solve for vbar in angstrom/fs
203
204 aw2 = 2.0 * kebar / atom->getChargeMass();
205 wbar = sqrt(aw2);
206
207 // picks random velocities from a gaussian distribution
208 // centered on vbar
209 atom->setFlucQVel(wbar * normalDistribution(*randNumGen_));
210 }
211 }
212
213 // randomization of the charge velocities for atoms in the rigidbody
214
215 if (sd->isRigidBody()) {
216 RigidBody* rigidbody = static_cast<RigidBody*>(sd);
217 vector<Atom*> atomList;
218 atomList = rigidbody->getAtoms();
219
220 for (size_t i = 0; i < atomList.size(); ++i) {
221 Atom* atom = atomList[i];
222 AtomType* atomType = atom->getAtomType();
224 if (fqa.isFluctuatingCharge()) {
225 // uses equipartition theory to solve for vbar in angstrom/fs
226 aw2 = 2.0 * kebar / atom->getChargeMass();
227 wbar = sqrt(aw2);
228 // picks random velocities from a gaussian distribution
229 // centered on vbar
230 atom->setFlucQVel(wbar * normalDistribution(*randNumGen_));
231 }
232 }
233 }
234 }
235 }
236 fqConstraints->applyConstraintsOnChargeVelocities();
237 }
238
240 // Get the Center of Mass drift velocity.
241 Vector3d vdrift = thermo_.getComVel();
242
243 SimInfo::MoleculeIterator mi;
244 Molecule::IntegrableObjectIterator ioi;
245 Molecule* mol;
246 StuntDouble* sd;
247
248 // Corrects for the center of mass drift.
249 // sums all the momentum and divides by total mass.
250 for (mol = info_->beginMolecule(mi); mol != NULL;
251 mol = info_->nextMolecule(mi)) {
252 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
253 sd = mol->nextIntegrableObject(ioi)) {
254 sd->setVel(sd->getVel() - vdrift);
255 }
256 }
257 }
258
260 // Get the Center of Mass drift velocity.
261
262 Vector3d vdrift;
263 Vector3d com;
264
265 thermo_.getComAll(com, vdrift);
266
267 Mat3x3d inertiaTensor;
268 Vector3d angularMomentum;
269 Vector3d omega;
270
271 thermo_.getInertiaTensor(inertiaTensor, angularMomentum);
272
273 // We now need the inverse of the inertia tensor.
274 inertiaTensor = inertiaTensor.inverse();
275 omega = inertiaTensor * angularMomentum;
276
277 SimInfo::MoleculeIterator mi;
278 Molecule::IntegrableObjectIterator ioi;
279 Molecule* mol;
280 StuntDouble* sd;
281 Vector3d tempComPos;
282
283 // Corrects for the center of mass angular drift by summing all
284 // the angular momentum and dividing by the total mass.
285
286 for (mol = info_->beginMolecule(mi); mol != NULL;
287 mol = info_->nextMolecule(mi)) {
288 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
289 sd = mol->nextIntegrableObject(ioi)) {
290 tempComPos = sd->getPos() - com;
291 sd->setVel((sd->getVel() - vdrift) - cross(omega, tempComPos));
292 }
293 }
294 }
295} // namespace OpenMD
AtomType is what OpenMD looks to for unchanging data about an atom.
Definition AtomType.hpp:66
std::vector< Atom * > getAtoms()
Returns the atoms of this rigid body.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:93
int getNdf()
Returns the number of degrees of freedom.
Definition SimInfo.hpp:220
int getNdfRaw()
Returns the number of raw degrees of freedom.
Definition SimInfo.hpp:226
Molecule * beginMolecule(MoleculeIterator &i)
Returns the first molecule in this SimInfo and intialize the iterator.
Definition SimInfo.cpp:240
Molecule * nextMolecule(MoleculeIterator &i)
Returns the next avaliable Molecule based on the iterator.
Definition SimInfo.cpp:245
SquareMatrix3< Real > inverse() const
Sets the value of this matrix to the inverse of itself.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
Vector3d getVel()
Returns the current velocity of this stuntDouble.
int linearAxis()
Returns the linear axis of the rigidbody, atom and directional atom will always return -1.
RealType getMass()
Returns the mass of this stuntDouble.
virtual Mat3x3d getI()=0
Returns the inertia tensor of this stuntDouble.
bool isLinear()
Tests the if this stuntDouble is a linear rigidbody.
Vector3d getPos()
Returns the current position of this stuntDouble.
void setVel(const Vector3d &vel)
Sets the current velocity of this stuntDouble.
bool isRigidBody()
Tests if this stuntDouble is a rigid body.
Vector3d getJ()
Returns the current angular momentum of this stuntDouble (body -fixed).
bool isAtom()
Tests if this stuntDouble is an atom.
bool isDirectional()
Tests if this stuntDouble is a directional one.
void setJ(const Vector3d &angMom)
Sets the current angular momentum of this stuntDouble (body-fixed).
void getComAll(Vector3d &com, Vector3d &comVel)
Returns the center of the mass and Center of Mass velocity of the whole system.
Definition Thermo.cpp:839
void getInertiaTensor(Mat3x3d &inertiaTensor, Vector3d &angularMomentum)
Returns the inertia tensor and the total angular momentum for for the entire system.
Definition Thermo.cpp:888
Vector3d getComVel()
Returns the velocity of center of mass of the whole system.
Definition Thermo.cpp:775
void randomize(RealType ct)
Resamples velocities and angular momenta Resamples velocities and angular momenta from a Maxwell-Bolt...
void randomizeChargeVelocity(RealType ct)
Resamples charge velocities Resamples charge velocities from a Maxwell-Boltzmann distribution.
void removeComDrift()
Removes Center of Mass Drift Velocity Removes the center of mass drift velocity (required for accurat...
void scale(RealType lambda)
Scales velocities and angular momenta by a scaling factor Rescales velocity (and angular momenta) by ...
void removeAngularDrift()
Removes Center of Mass Angular momentum Removes the center of mass angular momentum (particularly use...
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Definition Vector3.hpp:136