OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
Molecule.cpp
Go to the documentation of this file.
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/**
49 * @file Molecule.cpp
50 * @author tlin
51 * @date 10/28/2004
52 * @version 1.0
53 */
54
56
57#include <algorithm>
58#include <memory>
59#include <set>
60
61#include "types/FixedChargeAdapter.hpp"
62#include "utils/MemoryUtils.hpp"
63#include "utils/StringUtils.hpp"
64#include "utils/simError.h"
65
66namespace OpenMD {
67 Molecule::Molecule(int globalIndex, MoleculeStamp* molStamp) :
68 globalIndex_(globalIndex), molStamp_ {molStamp},
69 constrainTotalCharge_(false) {}
70
71 Molecule::~Molecule() {
72 Utils::deletePointers(atoms_);
73 Utils::deletePointers(bonds_);
74 Utils::deletePointers(bends_);
75 Utils::deletePointers(torsions_);
76 Utils::deletePointers(inversions_);
77 Utils::deletePointers(rigidBodies_);
78 Utils::deletePointers(cutoffGroups_);
79 Utils::deletePointers(constraintPairs_);
80 Utils::deletePointers(constraintElems_);
81 Utils::deletePointers(hBondDonors_);
82
83 // integrableObjects_ don't own the objects
84 integrableObjects_.clear();
85 fluctuatingCharges_.clear();
86 }
87
88 void Molecule::addAtom(Atom* atom) {
89 if (std::find(atoms_.begin(), atoms_.end(), atom) == atoms_.end()) {
90 atoms_.push_back(atom);
91 }
92 }
93
94 void Molecule::addBond(Bond* bond) {
95 if (std::find(bonds_.begin(), bonds_.end(), bond) == bonds_.end()) {
96 bonds_.push_back(bond);
97 }
98 }
99
101 if (std::find(bends_.begin(), bends_.end(), bend) == bends_.end()) {
102 bends_.push_back(bend);
103 }
104 }
105
107 if (std::find(torsions_.begin(), torsions_.end(), torsion) ==
108 torsions_.end()) {
109 torsions_.push_back(torsion);
110 }
111 }
112
114 if (std::find(inversions_.begin(), inversions_.end(), inversion) ==
115 inversions_.end()) {
116 inversions_.push_back(inversion);
117 }
118 }
119
121 if (std::find(rigidBodies_.begin(), rigidBodies_.end(), rb) ==
122 rigidBodies_.end()) {
123 rigidBodies_.push_back(rb);
124 }
125 }
126
128 if (std::find(cutoffGroups_.begin(), cutoffGroups_.end(), cp) ==
129 cutoffGroups_.end()) {
130 cutoffGroups_.push_back(cp);
131 }
132 }
133
134 void Molecule::addConstraintPair(ConstraintPair* cp) {
135 if (std::find(constraintPairs_.begin(), constraintPairs_.end(), cp) ==
136 constraintPairs_.end()) {
137 constraintPairs_.push_back(cp);
138 }
139 }
140
141 void Molecule::addConstraintElem(ConstraintElem* cp) {
142 if (std::find(constraintElems_.begin(), constraintElems_.end(), cp) ==
143 constraintElems_.end()) {
144 constraintElems_.push_back(cp);
145 }
146 }
147
148 void Molecule::complete() {
149 std::set<Atom*> rigidAtoms;
150 Atom* atom;
151 Atom* atom1;
152 Atom* atom2;
153 AtomIterator ai, aj;
154 RigidBody* rb;
155 RigidBodyIterator rbIter;
156 Bond* bond;
157 BondIterator bi;
158
159 // Get list of all the atoms that are part of rigid bodies
160
161 for (rb = beginRigidBody(rbIter); rb != NULL; rb = nextRigidBody(rbIter)) {
162 rigidAtoms.insert(rb->getBeginAtomIter(), rb->getEndAtomIter());
163 }
164
165 // add any atom that wasn't part of a rigid body to the list of
166 // integrableObjects
167
168 for (atom = beginAtom(ai); atom != NULL; atom = nextAtom(ai)) {
169 if (rigidAtoms.find(atom) == rigidAtoms.end()) {
170 // If an atom does not belong to a rigid body, it is an
171 // integrable object
172
173 integrableObjects_.push_back(atom);
174 }
175 }
176
177 // then add the rigid bodies themselves to the integrableObjects
178
179 for (rb = beginRigidBody(rbIter); rb != NULL; rb = nextRigidBody(rbIter)) {
180 integrableObjects_.push_back(rb);
181 }
182
183 // find the atoms that are fluctuating charges and add them to the
184 // fluctuatingCharges_ vector
185
186 for (atom = beginAtom(ai); atom != NULL; atom = nextAtom(ai)) {
187 if (atom->isFluctuatingCharge()) fluctuatingCharges_.push_back(atom);
188 }
189
190 // find the electronegative atoms and add them to the
191 // hBondAcceptors_ vector:
192
193 for (atom = beginAtom(ai); atom != NULL; atom = nextAtom(ai)) {
194 AtomType* at = atom->getAtomType();
195 // get the chain of base types for this atom type:
196 std::vector<AtomType*> ayb = at->allYourBase();
197 // use the last type in the chain of base types for the name:
198 std::string bn = UpperCase(ayb[ayb.size() - 1]->getName());
199
200 if (bn.compare("O") == 0 || bn.compare("N") == 0 || bn.compare("F") == 0)
201 hBondAcceptors_.push_back(atom);
202 }
203
204 // find electronegative atoms that are either bonded to
205 // hydrogens or are present in the same rigid bodies:
206
207 for (bond = beginBond(bi); bond != NULL; bond = nextBond(bi)) {
208 Atom* atom1 = bond->getAtomA();
209 Atom* atom2 = bond->getAtomB();
210 AtomType* at1 = atom1->getAtomType();
211 AtomType* at2 = atom2->getAtomType();
212 // get the chain of base types for this atom type:
213 std::vector<AtomType*> ayb1 = at1->allYourBase();
214 std::vector<AtomType*> ayb2 = at2->allYourBase();
215 // use the last type in the chain of base types for the name:
216 std::string bn1 = UpperCase(ayb1[ayb1.size() - 1]->getName());
217 std::string bn2 = UpperCase(ayb2[ayb2.size() - 1]->getName());
218
219 if (bn1.compare("H") == 0) {
220 if (bn2.compare("O") == 0 || bn2.compare("N") == 0 ||
221 bn2.compare("F") == 0) {
222 HBondDonor* donor = new HBondDonor();
223 donor->donorAtom = atom2;
224 donor->donatedHydrogen = atom1;
225 hBondDonors_.push_back(donor);
226 }
227 }
228 if (bn2.compare("H") == 0) {
229 if (bn1.compare("O") == 0 || bn1.compare("N") == 0 ||
230 bn1.compare("F") == 0) {
231 HBondDonor* donor = new HBondDonor();
232 donor->donorAtom = atom1;
233 donor->donatedHydrogen = atom2;
234 hBondDonors_.push_back(donor);
235 }
236 }
237 }
238
239 for (rb = beginRigidBody(rbIter); rb != NULL; rb = nextRigidBody(rbIter)) {
240 for (atom1 = rb->beginAtom(ai); atom1 != NULL; atom1 = rb->nextAtom(ai)) {
241 AtomType* at1 = atom1->getAtomType();
242 // get the chain of base types for this atom type:
243 std::vector<AtomType*> ayb1 = at1->allYourBase();
244 // use the last type in the chain of base types for the name:
245 std::string bn1 = UpperCase(ayb1[ayb1.size() - 1]->getName());
246
247 if (bn1.compare("O") == 0 || bn1.compare("N") == 0 ||
248 bn1.compare("F") == 0) {
249 for (atom2 = rb->beginAtom(aj); atom2 != NULL;
250 atom2 = rb->nextAtom(aj)) {
251 AtomType* at2 = atom2->getAtomType();
252 // get the chain of base types for this atom type:
253 std::vector<AtomType*> ayb2 = at2->allYourBase();
254 // use the last type in the chain of base types for the name:
255 std::string bn2 = UpperCase(ayb2[ayb2.size() - 1]->getName());
256 if (bn2.compare("H") == 0) {
257 HBondDonor* donor = new HBondDonor();
258 donor->donorAtom = atom1;
259 donor->donatedHydrogen = atom2;
260 hBondDonors_.push_back(donor);
261 }
262 }
263 }
264 }
265 }
266 }
267
268 RealType Molecule::getMass() {
269 StuntDouble* sd;
270 std::vector<StuntDouble*>::iterator i;
271 RealType mass = 0.0;
272
273 for (sd = beginIntegrableObject(i); sd != NULL;
274 sd = nextIntegrableObject(i)) {
275 mass += sd->getMass();
276 }
277
278 return mass;
279 }
280
282 Atom* atom;
283 std::vector<Atom*>::iterator i;
284 RealType q = 0.0;
285
286 for (atom = beginAtom(i); atom != NULL; atom = nextAtom(i)) {
287 AtomType* atomType = atom->getAtomType();
288
290 if (fca.isFixedCharge()) { q += fca.getCharge(); }
291 }
292
293 return q;
294 }
295
297 StuntDouble* sd;
298 std::vector<StuntDouble*>::iterator i;
299 Vector3d com {};
300 RealType totalMass {};
301 RealType mass {};
302
303 for (sd = beginIntegrableObject(i); sd != NULL;
304 sd = nextIntegrableObject(i)) {
305 mass = sd->getMass();
306 totalMass += mass;
307 com += sd->getPrevPos() * mass;
308 }
309
310 com /= totalMass;
311
312 return com;
313 }
314
315 Vector3d Molecule::getCom() {
316 StuntDouble* sd;
317 std::vector<StuntDouble*>::iterator i;
318 Vector3d com {};
319 RealType totalMass {};
320 RealType mass {};
321
322 for (sd = beginIntegrableObject(i); sd != NULL;
323 sd = nextIntegrableObject(i)) {
324 mass = sd->getMass();
325 totalMass += mass;
326 com += sd->getPos() * mass;
327 }
328
329 com /= totalMass;
330
331 return com;
332 }
333
334 Vector3d Molecule::getCom(int snapshotNo) {
335 StuntDouble* sd;
336 std::vector<StuntDouble*>::iterator i;
337 Vector3d com {};
338 RealType totalMass {};
339 RealType mass {};
340
341 for (sd = beginIntegrableObject(i); sd != NULL;
342 sd = nextIntegrableObject(i)) {
343 mass = sd->getMass();
344 totalMass += mass;
345 com += sd->getPos(snapshotNo) * mass;
346 }
347
348 com /= totalMass;
349
350 return com;
351 }
352
353 void Molecule::setCom(const Vector3d& newCom) {
354 Vector3d delta = newCom - getCom();
355 moveCom(delta);
356 }
357
358 void Molecule::moveCom(const Vector3d& delta) {
359 StuntDouble* sd;
360 std::vector<StuntDouble*>::iterator i;
361
362 for (sd = beginIntegrableObject(i); sd != NULL;
363 sd = nextIntegrableObject(i)) {
364 sd->setPos(sd->getPos() + delta);
365 }
366 }
367
369 StuntDouble* sd;
370 std::vector<StuntDouble*>::iterator i;
371 Vector3d velCom(0.0);
372 RealType totalMass = 0;
373 RealType mass;
374
375 for (sd = beginIntegrableObject(i); sd != NULL;
376 sd = nextIntegrableObject(i)) {
377 mass = sd->getMass();
378 totalMass += mass;
379 velCom += sd->getVel() * mass;
380 }
381
382 velCom /= totalMass;
383
384 return velCom;
385 }
386
388 Bond* bond;
389 Bend* bend;
390 Torsion* torsion;
391 Inversion* inversion;
392 Molecule::BondIterator bondIter;
393 ;
394 Molecule::BendIterator bendIter;
395 Molecule::TorsionIterator torsionIter;
396 Molecule::InversionIterator inversionIter;
397
398 RealType potential = 0.0;
399
400 for (bond = beginBond(bondIter); bond != NULL; bond = nextBond(bondIter)) {
401 potential += bond->getPotential();
402 }
403
404 for (bend = beginBend(bendIter); bend != NULL; bend = nextBend(bendIter)) {
405 potential += bend->getPotential();
406 }
407
408 for (torsion = beginTorsion(torsionIter); torsion != NULL;
409 torsion = nextTorsion(torsionIter)) {
410 potential += torsion->getPotential();
411 }
412
413 for (inversion = beginInversion(inversionIter); inversion != NULL;
414 inversion = nextInversion(inversionIter)) {
415 potential += inversion->getPotential();
416 }
417
418 return potential;
419 }
420
421 void Molecule::addProperty(std::shared_ptr<GenericData> genData) {
422 properties_.addProperty(genData);
423 }
424
425 void Molecule::removeProperty(const std::string& propName) {
426 properties_.removeProperty(propName);
427 }
428
429 std::vector<std::string> Molecule::getPropertyNames() {
430 return properties_.getPropertyNames();
431 }
432
433 std::vector<std::shared_ptr<GenericData>> Molecule::getProperties() {
434 return properties_.getProperties();
435 }
436
437 std::shared_ptr<GenericData> Molecule::getPropertyByName(
438 const std::string& propName) {
439 return properties_.getPropertyByName(propName);
440 }
441
442 std::ostream& operator<<(std::ostream& o, Molecule& mol) {
443 o << std::endl;
444 o << "Molecule " << mol.getGlobalIndex() << "has: " << std::endl;
445 o << mol.getNAtoms() << " atoms" << std::endl;
446 o << mol.getNBonds() << " bonds" << std::endl;
447 o << mol.getNBends() << " bends" << std::endl;
448 o << mol.getNTorsions() << " torsions" << std::endl;
449 o << mol.getNInversions() << " inversions" << std::endl;
450 o << mol.getNRigidBodies() << " rigid bodies" << std::endl;
451 o << mol.getNIntegrableObjects() << " integrable objects" << std::endl;
452 o << mol.getNCutoffGroups() << " cutoff groups" << std::endl;
453 o << mol.getNConstraintPairs() << " constraint pairs" << std::endl;
454 o << mol.getNFluctuatingCharges() << " fluctuating charges" << std::endl;
455 return o;
456 }
457
458} // 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
Vector3d getPrevCom()
Returns the center of mass position of this molecule in the previous snapshot.
Definition Molecule.cpp:296
void addAtom(Atom *atom)
add an atom into this molecule
Definition Molecule.cpp:88
void addInversion(Inversion *inversion)
add an improper torsion into this molecule
Definition Molecule.cpp:113
size_t getNIntegrableObjects()
Returns the total number of integrable objects in this molecule.
Definition Molecule.hpp:183
RealType getMass()
get total mass of this molecule
Definition Molecule.cpp:268
size_t getNFluctuatingCharges()
Returns the total number of fluctuating charges in this molecule.
Definition Molecule.hpp:192
std::vector< std::string > getPropertyNames()
Returns all names of properties.
Definition Molecule.cpp:429
size_t getNInversions()
Returns the total number of improper torsions in this molecule.
Definition Molecule.hpp:177
void removeProperty(const std::string &propName)
Removes property from PropertyMap by name.
Definition Molecule.cpp:425
void addBend(Bend *bend)
add a bend into this molecule
Definition Molecule.cpp:100
void addRigidBody(RigidBody *rb)
add a rigidbody into this molecule
Definition Molecule.cpp:120
int getGlobalIndex()
Returns the global index of this molecule.
Definition Molecule.hpp:109
std::vector< std::shared_ptr< GenericData > > getProperties()
Returns all of the properties in PropertyMap.
Definition Molecule.cpp:433
size_t getNBends()
Returns the total number of bends in this molecule.
Definition Molecule.hpp:171
std::shared_ptr< GenericData > getPropertyByName(const std::string &propName)
Returns property.
Definition Molecule.cpp:437
size_t getNConstraintPairs()
Returns the total number of constraints in this molecule.
Definition Molecule.hpp:189
void addCutoffGroup(CutoffGroup *cp)
add a cutoff group into this molecule
Definition Molecule.cpp:127
Vector3d getComVel()
Returns the velocity of center of mass of this molecule.
Definition Molecule.cpp:368
void addBond(Bond *bond)
add a bond into this molecule
Definition Molecule.cpp:94
size_t getNAtoms()
Returns the total number of atoms in this molecule.
Definition Molecule.hpp:165
size_t getNRigidBodies()
Returns the total number of rigid bodies in this molecule.
Definition Molecule.hpp:180
size_t getNBonds()
Returns the total number of bonds in this molecule.
Definition Molecule.hpp:168
void addProperty(std::shared_ptr< GenericData > genData)
Adds property into property map.
Definition Molecule.cpp:421
RealType getPotential()
Returns the total potential energy of short range interaction of this molecule.
Definition Molecule.cpp:387
void moveCom(const Vector3d &delta)
Moves the center of this molecule.
Definition Molecule.cpp:358
size_t getNCutoffGroups()
Returns the total number of cutoff groups in this molecule.
Definition Molecule.hpp:186
void addTorsion(Torsion *torsion)
add a torsion into this molecule
Definition Molecule.cpp:106
size_t getNTorsions()
Returns the total number of torsions in this molecule.
Definition Molecule.hpp:174
RealType getFixedCharge()
get total fixed charge of this molecule
Definition Molecule.cpp:281
void setCom(const Vector3d &newCom)
Sets the center of this molecule.
Definition Molecule.cpp:353
Vector3d getCom()
Returns the current center of mass position of this molecule.
Definition Molecule.cpp:315
"Don't move, or you're dead! Stand up! Captain, we've got them!"
Vector3d getVel()
Returns the current velocity of this stuntDouble.
RealType getMass()
Returns the mass of this stuntDouble.
Vector3d getPos()
Returns the current position of this stuntDouble.
void setPos(const Vector3d &pos)
Sets the current position of this stuntDouble.
Vector3d getPrevPos()
Returns the previous position of this stuntDouble.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string UpperCase(const std::string &S)
Converts a string to UPPER CASE.