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