OpenMD 3.2
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 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 "brains/Velocitizer.hpp"
49
50#include <memory>
51#include <random>
52
53#include "brains/Thermo.hpp"
54#include "flucq/FluctuatingChargeConstraints.hpp"
58#include "types/FluctuatingChargeAdapter.hpp"
59#include "utils/Constants.hpp"
60#include "utils/RandNumGen.hpp"
61
62namespace OpenMD {
63
64 Velocitizer::Velocitizer(SimInfo* info) :
65 info_(info), thermo_(info), globals_(info->getSimParams()),
66 randNumGen_(info->getRandomNumberGenerator()) {}
67
68 void Velocitizer::scale(RealType lambda) {
69 SimInfo::MoleculeIterator mi;
70 Molecule::IntegrableObjectIterator ioi;
71 Molecule* mol;
72 StuntDouble* sd;
73 Vector3d v, j;
74
75 for (mol = info_->beginMolecule(mi); mol != NULL;
76 mol = info_->nextMolecule(mi)) {
77 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
78 sd = mol->nextIntegrableObject(ioi)) {
79 v = sd->getVel();
80 v *= lambda;
81 sd->setVel(v);
82
83 if (sd->isDirectional()) {
84 j = sd->getJ();
85 j *= lambda;
86 sd->setJ(j);
87 }
88 }
89 }
90
91 // We've modified velocities, so clear any derived properties in
92 // the Snapshot:
93 info_->getSnapshotManager()->getCurrentSnapshot()->clearDerivedProperties();
94
96
97 // Remove angular drift if we are not using periodic boundary
98 // conditions:
99 if (!globals_->getUsePeriodicBoundaryConditions()) removeAngularDrift();
100 }
101
102 void Velocitizer::randomize(RealType temperature) {
103 Vector3d v;
104 Vector3d j;
105 Mat3x3d I;
106 int l, m, n;
107 Vector3d vdrift;
108 RealType vbar;
109 RealType jbar;
110 RealType av2;
111 RealType kebar;
112
113 SimInfo::MoleculeIterator mi;
114 Molecule::IntegrableObjectIterator ioi;
115 Molecule* mol;
116 StuntDouble* sd;
117
118 std::normal_distribution<RealType> normalDistribution {0.0, 1.0};
119
120 kebar = Constants::kB * temperature * info_->getNdfRaw() /
121 (2.0 * info_->getNdf());
122 for (mol = info_->beginMolecule(mi); mol != NULL;
123 mol = info_->nextMolecule(mi)) {
124 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
125 sd = mol->nextIntegrableObject(ioi)) {
126 // uses equipartition theory to solve for vbar in angstrom/fs
127
128 av2 = 2.0 * kebar / sd->getMass();
129 vbar = sqrt(av2);
130
131 // picks random velocities from a gaussian distribution
132 // centered on vbar
133
134 for (int k = 0; k < 3; k++) {
135 v[k] = vbar * normalDistribution(*randNumGen_);
136 }
137 sd->setVel(v);
138
139 if (sd->isDirectional()) {
140 I = sd->getI();
141
142 if (sd->isLinear()) {
143 l = sd->linearAxis();
144 m = (l + 1) % 3;
145 n = (l + 2) % 3;
146
147 j[l] = 0.0;
148 jbar = sqrt(2.0 * kebar * I(m, m));
149 j[m] = jbar * normalDistribution(*randNumGen_);
150 jbar = sqrt(2.0 * kebar * I(n, n));
151 j[n] = jbar * normalDistribution(*randNumGen_);
152 } else {
153 for (int k = 0; k < 3; k++) {
154 jbar = sqrt(2.0 * kebar * I(k, k));
155 j[k] = jbar * normalDistribution(*randNumGen_);
156 }
157 }
158
159 sd->setJ(j);
160 }
161 }
162 }
163
164 // We've modified velocities, so clear any derived properties in
165 // the Snapshot:
166 info_->getSnapshotManager()->getCurrentSnapshot()->clearDerivedProperties();
167
169
170 // Remove angular drift if we are not using periodic boundary
171 // conditions:
172 if (!globals_->getUsePeriodicBoundaryConditions()) removeAngularDrift();
173
174 }
175
176 void Velocitizer::randomizeChargeVelocity(RealType temperature) {
177 RealType aw2;
178 RealType kebar;
179 RealType wbar;
180
181 SimInfo::MoleculeIterator mi;
182 Molecule::IntegrableObjectIterator ioi;
183 Molecule* mol;
184 StuntDouble* sd;
186 FluctuatingChargeConstraints* fqConstraints;
187
188 std::normal_distribution<RealType> normalDistribution {0.0, 1.0};
189
190 Globals* simParams = info_->getSimParams();
191 fqParams = simParams->getFluctuatingChargeParameters();
192
193 fqConstraints = new FluctuatingChargeConstraints(info_);
194 fqConstraints->setConstrainRegions(fqParams->getConstrainRegions());
195
196 int nConstrain =
197 fqConstraints
198 ->getNumberOfFlucQConstraints(); // no of constraints in charge
199 int dfRaw = fqConstraints->getNumberOfFlucQAtoms(); // no of FlucQ freedom
200 int dfActual = dfRaw - nConstrain;
201 kebar = dfRaw * Constants::kb * temperature / (2 * dfActual);
202
203 for (mol = info_->beginMolecule(mi); mol != NULL;
204 mol = info_->nextMolecule(mi)) {
205 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
206 sd = mol->nextIntegrableObject(ioi)) {
207 if (sd->isAtom()) {
208 Atom* atom = static_cast<Atom*>(sd);
209 AtomType* atomType = atom->getAtomType();
211 if (fqa.isFluctuatingCharge()) {
212 // uses equipartition theory to solve for vbar in angstrom/fs
213
214 aw2 = 2.0 * kebar / atom->getChargeMass();
215 wbar = sqrt(aw2);
216
217 // picks random velocities from a gaussian distribution
218 // centered on vbar
219 atom->setFlucQVel(wbar * normalDistribution(*randNumGen_));
220 }
221 }
222
223 // randomization of the charge velocities for atoms in the rigidbody
224
225 if (sd->isRigidBody()) {
226 RigidBody* rigidbody = static_cast<RigidBody*>(sd);
227 vector<Atom*> atomList;
228 atomList = rigidbody->getAtoms();
229
230 for (size_t i = 0; i < atomList.size(); ++i) {
231 Atom* atom = atomList[i];
232 AtomType* atomType = atom->getAtomType();
234 if (fqa.isFluctuatingCharge()) {
235 // uses equipartition theory to solve for vbar in angstrom/fs
236 aw2 = 2.0 * kebar / atom->getChargeMass();
237 wbar = sqrt(aw2);
238 // picks random velocities from a gaussian distribution
239 // centered on vbar
240 atom->setFlucQVel(wbar * normalDistribution(*randNumGen_));
241 }
242 }
243 }
244 }
245 }
246 fqConstraints->applyConstraintsOnChargeVelocities();
247 }
248
250 // Get the Center of Mass drift velocity.
251 Vector3d vdrift = thermo_.getComVel();
252
253 SimInfo::MoleculeIterator mi;
254 Molecule::IntegrableObjectIterator ioi;
255 Molecule* mol;
256 StuntDouble* sd;
257
258 // Corrects for the center of mass drift.
259 // sums all the momentum and divides by total mass.
260 for (mol = info_->beginMolecule(mi); mol != NULL;
261 mol = info_->nextMolecule(mi)) {
262 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
263 sd = mol->nextIntegrableObject(ioi)) {
264 sd->setVel(sd->getVel() - vdrift);
265 }
266 }
267
268 // We've modified velocities, so clear any derived properties in
269 // the Snapshot:
270 info_->getSnapshotManager()->getCurrentSnapshot()->clearDerivedProperties();
271 }
272
274 // Get the Center of Mass drift velocity.
275 Vector3d vdrift;
276 Vector3d com;
277
278 thermo_.getComAll(com, vdrift);
279
280 Mat3x3d inertiaTensor;
281 Vector3d angularMomentum;
282 Vector3d omega;
283
284 thermo_.getInertiaTensor(inertiaTensor, angularMomentum);
285
286 // We now need the inverse of the inertia tensor.
287 inertiaTensor = inertiaTensor.inverse();
288 omega = inertiaTensor * angularMomentum;
289
290 SimInfo::MoleculeIterator mi;
291 Molecule::IntegrableObjectIterator ioi;
292 Molecule* mol;
293 StuntDouble* sd;
294 Vector3d tempComPos;
295
296 // Corrects for the center of mass angular drift by summing all
297 // the angular momentum and dividing by the total mass.
298
299 for (mol = info_->beginMolecule(mi); mol != NULL;
300 mol = info_->nextMolecule(mi)) {
301 for (sd = mol->beginIntegrableObject(ioi); sd != NULL;
302 sd = mol->nextIntegrableObject(ioi)) {
303 tempComPos = sd->getPos() - com;
304 sd->setVel((sd->getVel() - vdrift) - cross(omega, tempComPos));
305 }
306 }
307
308 // We've modified velocities, so clear any derived properties in
309 // the Snapshot:
310 info_->getSnapshotManager()->getCurrentSnapshot()->clearDerivedProperties();
311 }
312} // namespace OpenMD
AtomType * getAtomType()
Returns the AtomType of this Atom.
Definition Atom.hpp:86
AtomType is what OpenMD looks to for unchanging data about an atom.
Definition AtomType.hpp:69
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:96
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!"
void setFlucQVel(RealType cvel)
Sets the current charge velocity of this stuntDouble.
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 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:139