OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
MoleculeCreator.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 MoleculeCreator.cpp
50 * @author tlin
51 * @date 11/04/2004
52 * @version 1.0
53 */
54
56
57#include <cassert>
58#include <set>
59#include <typeinfo>
60
62#include "primitives/GhostTorsion.hpp"
63#include "types/AtomType.hpp"
64#include "types/BendTypeParser.hpp"
65#include "types/BondTypeParser.hpp"
67#include "types/FixedChargeAdapter.hpp"
68#include "types/InversionTypeParser.hpp"
69#include "types/TorsionTypeParser.hpp"
70#include "utils/StringUtils.hpp"
71#include "utils/simError.h"
72
73namespace OpenMD {
74
75 void MoleculeCreator::createOverrideAtomTypes(ForceField* ff,
76 MoleculeStamp* molStamp) {
77
78 // Some stamps have overrides of default types in the force field.
79 // This runs through atomStamps which can have overrides and makes sure
80 // that the types are created, even if this processor doesn't end up
81 // owning that molecule:
82
83 AtomStamp* stamp;
84 size_t nAtom = molStamp->getNAtoms();
85
86 for (size_t i = 0; i < nAtom; ++i) {
87 stamp = molStamp->getAtomStamp(i);
88 AtomType* atomType = ff->getAtomType(stamp->getType());
89
90 if (atomType == NULL) {
91 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
92 "Can not find Matching Atom Type for[%s]",
93 stamp->getType().c_str());
94
95 painCave.isFatal = 1;
96 simError();
97 }
98
99 if (stamp->hasOverride()) {
100 std::string baseType = atomType->getName();
101 RealType oc = stamp->getOverrideCharge();
102
103 // Create a new atom type name that builds in the override charge:
104 std::ostringstream ss;
105 ss << oc;
106 std::string atomTypeOverrideName = baseType + "_q=" + ss.str();
107
108 // Maybe we've seen this before?
109
110 AtomType* atB = ff->getAtomType(atomTypeOverrideName);
111
112 if (atB == NULL) {
113 // Nope, we've never seen it before, so make a new one:
114 AtomType* atomTypeOverride = new AtomType();
115 // Base points to the atomType we already found
116 atomTypeOverride->useBase(atomType);
117 int ident = ff->getNAtomType();
118 atomTypeOverride->setIdent(ident);
119 atomTypeOverride->setName(atomTypeOverrideName);
120 ff->addAtomType(atomTypeOverrideName, atomTypeOverride);
121 FixedChargeAdapter fca = FixedChargeAdapter(atomTypeOverride);
122 RealType charge =
123 ff->getForceFieldOptions().getChargeUnitScaling() * oc;
124 fca.makeFixedCharge(charge);
125 }
126 }
127 }
128 }
129
130 Molecule* MoleculeCreator::createMolecule(ForceField* ff,
131 MoleculeStamp* molStamp,
132 int globalIndex,
133 LocalIndexManager* localIndexMan) {
134 Molecule* mol = new Molecule(globalIndex, molStamp);
135
136 // create atoms
137 Atom* atom;
138 AtomStamp* currentAtomStamp;
139 size_t nAtom = molStamp->getNAtoms();
140 for (size_t i = 0; i < nAtom; ++i) {
141 currentAtomStamp = molStamp->getAtomStamp(i);
142 atom = createAtom(ff, currentAtomStamp, localIndexMan);
143 mol->addAtom(atom);
144 }
145
146 // create rigidbodies
147 RigidBody* rb;
148 RigidBodyStamp* currentRigidBodyStamp;
149 size_t nRigidbodies = molStamp->getNRigidBodies();
150
151 for (size_t i = 0; i < nRigidbodies; ++i) {
152 currentRigidBodyStamp = molStamp->getRigidBodyStamp(i);
153 rb = createRigidBody(molStamp, mol, currentRigidBodyStamp, localIndexMan);
154 mol->addRigidBody(rb);
155 }
156
157 // create bonds
158 Bond* bond;
159 BondStamp* currentBondStamp;
160 size_t nBonds = molStamp->getNBonds();
161
162 for (size_t i = 0; i < nBonds; ++i) {
163 currentBondStamp = molStamp->getBondStamp(i);
164 bond = createBond(ff, mol, currentBondStamp, localIndexMan);
165 mol->addBond(bond);
166 }
167
168 // create bends
169 Bend* bend;
170 BendStamp* currentBendStamp;
171 size_t nBends = molStamp->getNBends();
172 for (size_t i = 0; i < nBends; ++i) {
173 currentBendStamp = molStamp->getBendStamp(i);
174 bend = createBend(ff, mol, currentBendStamp, localIndexMan);
175 mol->addBend(bend);
176 }
177
178 // create torsions
179 Torsion* torsion;
180 TorsionStamp* currentTorsionStamp;
181 size_t nTorsions = molStamp->getNTorsions();
182 for (size_t i = 0; i < nTorsions; ++i) {
183 currentTorsionStamp = molStamp->getTorsionStamp(i);
184 torsion = createTorsion(ff, mol, currentTorsionStamp, localIndexMan);
185 mol->addTorsion(torsion);
186 }
187
188 // create inversions
189 Inversion* inversion;
190 InversionStamp* currentInversionStamp;
191 size_t nInversions = molStamp->getNInversions();
192 for (size_t i = 0; i < nInversions; ++i) {
193 currentInversionStamp = molStamp->getInversionStamp(i);
194 inversion =
195 createInversion(ff, mol, currentInversionStamp, localIndexMan);
196 if (inversion != NULL) { mol->addInversion(inversion); }
197 }
198
199 // create cutoffGroups
200 CutoffGroup* cutoffGroup;
201 CutoffGroupStamp* currentCutoffGroupStamp;
202 size_t nCutoffGroups = molStamp->getNCutoffGroups();
203 for (size_t i = 0; i < nCutoffGroups; ++i) {
204 currentCutoffGroupStamp = molStamp->getCutoffGroupStamp(i);
205 cutoffGroup =
206 createCutoffGroup(mol, currentCutoffGroupStamp, localIndexMan);
207 mol->addCutoffGroup(cutoffGroup);
208 }
209
210 // every free atom is a cutoff group
211 std::vector<Atom*> freeAtoms;
212 std::vector<Atom*>::iterator ai;
213 std::vector<Atom*>::iterator fai;
214
215 // add all atoms into allAtoms set
216 for (atom = mol->beginAtom(fai); atom != NULL; atom = mol->nextAtom(fai)) {
217 freeAtoms.push_back(atom);
218 }
219
220 Molecule::CutoffGroupIterator ci;
221 CutoffGroup* cg;
222
223 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
224 cg = mol->nextCutoffGroup(ci)) {
225 for (atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
226 // erase the atoms belong to cutoff groups from freeAtoms vector
227 freeAtoms.erase(std::remove(freeAtoms.begin(), freeAtoms.end(), atom),
228 freeAtoms.end());
229 }
230 }
231
232 // loop over the free atoms and then create one cutoff group for
233 // every single free atom
234
235 for (fai = freeAtoms.begin(); fai != freeAtoms.end(); ++fai) {
236 cutoffGroup = createCutoffGroup(mol, *fai, localIndexMan);
237 mol->addCutoffGroup(cutoffGroup);
238 }
239
240 // create bonded constraintPairs:
241 createConstraintPair(mol);
242
243 // create non-bonded constraintPairs
244 for (std::size_t i = 0; i < molStamp->getNConstraints(); ++i) {
245 ConstraintStamp* cStamp = molStamp->getConstraintStamp(i);
246 Atom* atomA;
247 Atom* atomB;
248
249 atomA = mol->getAtomAt(cStamp->getA());
250 atomB = mol->getAtomAt(cStamp->getB());
251 assert(atomA && atomB);
252
253 bool printConstraintForce = false;
254
255 if (cStamp->havePrintConstraintForce()) {
256 printConstraintForce = cStamp->getPrintConstraintForce();
257 }
258
259 if (!cStamp->haveConstrainedDistance()) {
260 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
261 "Constraint Error: A non-bond constraint was specified\n"
262 "\twithout providing a value for the constrainedDistance.\n");
263 painCave.isFatal = 1;
264 simError();
265 } else {
266 RealType distance = cStamp->getConstrainedDistance();
267 ConstraintElem* consElemA = new ConstraintElem(atomA);
268 ConstraintElem* consElemB = new ConstraintElem(atomB);
269 ConstraintPair* cPair = new ConstraintPair(
270 consElemA, consElemB, distance, printConstraintForce);
271 mol->addConstraintPair(cPair);
272 }
273 }
274
275 // now create the constraint elements:
276
277 createConstraintElem(mol);
278
279 // Does this molecule stamp define a total constrained charge value?
280 // If so, let the created molecule know about it.
281 if (molStamp->haveConstrainTotalCharge()) {
282 mol->setConstrainTotalCharge(molStamp->getConstrainTotalCharge());
283 }
284
285 // The construction of this molecule is finished:
286 mol->complete();
287
288 return mol;
289 }
290
292 LocalIndexManager* localIndexMan) {
293 AtomType* atomType;
294 Atom* atom;
295
296 atomType = ff->getAtomType(stamp->getType());
297 if (atomType == NULL) {
298 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
299 "Can not find Matching Atom Type for[%s]",
300 stamp->getType().c_str());
301
302 painCave.isFatal = 1;
303 simError();
304 }
305
306 if (stamp->hasOverride()) {
307 std::string baseType = atomType->getName();
308 RealType oc = stamp->getOverrideCharge();
309
310 // Create a new atom type name that builds in the override charge:
311 std::ostringstream ss;
312 ss << oc;
313 std::string atomTypeOverrideName = baseType + "_q=" + ss.str();
314
315 // Maybe we've seen this before?
316
317 AtomType* atB = ff->getAtomType(atomTypeOverrideName);
318
319 if (atB == NULL) {
320 // Nope, we've never seen it before, so make a new one:
321 AtomType* atomTypeOverride = new AtomType();
322 // Base points to the atomType we already found
323 atomTypeOverride->useBase(atomType);
324 int ident = ff->getNAtomType();
325 atomTypeOverride->setIdent(ident);
326 atomTypeOverride->setName(atomTypeOverrideName);
327 ff->addAtomType(atomTypeOverrideName, atomTypeOverride);
328 FixedChargeAdapter fca = FixedChargeAdapter(atomTypeOverride);
329 RealType charge =
330 ff->getForceFieldOptions().getChargeUnitScaling() * oc;
331 fca.makeFixedCharge(charge);
332 // officially use override type for this atom
333 atomType = atomTypeOverride;
334 } else {
335 // we've previously created the override type for this atom, so use that
336 // one:
337 atomType = atB;
338 }
339 }
340
341 // below code still have some kind of hard-coding smell
342 if (atomType->isDirectional()) {
343 DirectionalAtom* dAtom;
344 dAtom = new DirectionalAtom(atomType);
345 atom = dAtom;
346 } else {
347 atom = new Atom(atomType);
348 }
349
350 atom->setLocalIndex(localIndexMan->getNextAtomIndex());
351
352 return atom;
353 }
354
355 RigidBody* MoleculeCreator::createRigidBody(
356 MoleculeStamp* molStamp, Molecule* mol, RigidBodyStamp* rbStamp,
357 LocalIndexManager* localIndexMan) {
358 Atom* atom;
359 size_t nAtoms;
360 Vector3d refCoor;
361 AtomStamp* atomStamp;
362
363 RigidBody* rb = new RigidBody();
364 nAtoms = rbStamp->getNMembers();
365 for (std::size_t i = 0; i < nAtoms; ++i) {
366 // rbStamp->getMember(i) return the local index of current atom
367 // inside the molecule. It is not the same as local index of
368 // atom which is the index of atom at DataStorage class
369 atom = mol->getAtomAt(rbStamp->getMemberAt(i));
370 atomStamp = molStamp->getAtomStamp(rbStamp->getMemberAt(i));
371 rb->addAtom(atom, atomStamp);
372 }
373
374 // after all of the atoms are added, we need to calculate the
375 // reference coordinates
376 rb->calcRefCoords();
377
378 // set the local index of this rigid body, global index will be set later
379 rb->setLocalIndex(localIndexMan->getNextRigidBodyIndex());
380
381 // The rule for naming a rigidbody is: MoleculeName_RB_Integer
382 // The first part is the name of the molecule
383 // The second part is always fixed as "RB"
384 // The third part is the index of the rigidbody defined in meta-data file
385 // For example, Butane_RB_0 is a valid rigid body name of butane molecule
386
387 std::string s = OpenMD_itoa(mol->getNRigidBodies(), 10);
388 rb->setType(mol->getType() + "_RB_" + s.c_str());
389 return rb;
390 }
391
392
393 Bond* MoleculeCreator::createBond(ForceField* ff, Molecule* mol,
394 BondStamp* stamp,
395 LocalIndexManager* localIndexMan) {
396 BondTypeParser btParser;
397 BondType* bondType = NULL;
398 Atom* atomA;
399 Atom* atomB;
400
401 atomA = mol->getAtomAt(stamp->getA());
402 atomB = mol->getAtomAt(stamp->getB());
403
404 assert(atomA && atomB);
405
406 if (stamp->hasOverride()) {
407 try {
408 bondType = btParser.parseTypeAndPars(stamp->getOverrideType(),
409 stamp->getOverridePars());
410 } catch (OpenMDException& e) {
411 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
412 "MoleculeCreator Error: %s "
413 "for molecule %s\n",
414 e.what(), mol->getType().c_str());
415 painCave.isFatal = 1;
416 simError();
417 }
418
419 } else {
420 bondType = ff->getBondType(atomA->getType(), atomB->getType());
421
422 if (bondType == NULL) {
423 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
424 "Can not find Matching Bond Type for[%s, %s]",
425 atomA->getType().c_str(), atomB->getType().c_str());
426
427 painCave.isFatal = 1;
428 simError();
429 }
430 }
431
432 Bond* bond = new Bond(atomA, atomB, bondType);
433
434 // set the local index of this bond, the global index will be set later
435 bond->setLocalIndex(localIndexMan->getNextBondIndex());
436
437 // The rule for naming a bond is: MoleculeName_Bond_Integer
438 // The first part is the name of the molecule
439 // The second part is always fixed as "Bond"
440 // The third part is the index of the bond defined in meta-data file
441 // For example, Butane_bond_0 is a valid Bond name in a butane molecule
442
443 std::string s = OpenMD_itoa(mol->getNBonds(), 10);
444 bond->setName(mol->getType() + "_Bond_" + s.c_str());
445 return bond;
446 }
447
448 Bend* MoleculeCreator::createBend(ForceField* ff, Molecule* mol,
449 BendStamp* stamp,
450 LocalIndexManager* localIndexMan) {
451 BendTypeParser btParser;
452 BendType* bendType = NULL;
453 Bend* bend = NULL;
454
455 std::vector<int> bendAtoms = stamp->getMembers();
456 if (bendAtoms.size() == 3) {
457 Atom* atomA = mol->getAtomAt(bendAtoms[0]);
458 Atom* atomB = mol->getAtomAt(bendAtoms[1]);
459 Atom* atomC = mol->getAtomAt(bendAtoms[2]);
460
461 assert(atomA && atomB && atomC);
462
463 if (stamp->hasOverride()) {
464 try {
465 bendType = btParser.parseTypeAndPars(stamp->getOverrideType(),
466 stamp->getOverridePars());
467 } catch (OpenMDException& e) {
468 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
469 "MoleculeCreator Error: %s "
470 "for molecule %s\n",
471 e.what(), mol->getType().c_str());
472 painCave.isFatal = 1;
473 simError();
474 }
475 } else {
476 bendType =
477 ff->getBendType(atomA->getType().c_str(), atomB->getType().c_str(),
478 atomC->getType().c_str());
479
480 if (bendType == NULL) {
481 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
482 "Can not find Matching Bend Type for[%s, %s, %s]",
483 atomA->getType().c_str(), atomB->getType().c_str(),
484 atomC->getType().c_str());
485
486 painCave.isFatal = 1;
487 simError();
488 }
489 }
490
491 bend = new Bend(atomA, atomB, atomC, bendType);
492
493 } else if (bendAtoms.size() == 2 && stamp->haveGhostVectorSource()) {
494 int ghostIndex = stamp->getGhostVectorSource();
495 int normalIndex =
496 ghostIndex != bendAtoms[0] ? bendAtoms[0] : bendAtoms[1];
497 Atom* normalAtom = mol->getAtomAt(normalIndex);
498 DirectionalAtom* ghostAtom =
499 dynamic_cast<DirectionalAtom*>(mol->getAtomAt(ghostIndex));
500 if (ghostAtom == NULL) {
501 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
502 "Can not cast Atom to DirectionalAtom");
503 painCave.isFatal = 1;
504 simError();
505 }
506
507 if (stamp->hasOverride()) {
508 try {
509 bendType = btParser.parseTypeAndPars(stamp->getOverrideType(),
510 stamp->getOverridePars());
511 } catch (OpenMDException& e) {
512 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
513 "MoleculeCreator Error: %s "
514 "for molecule %s\n",
515 e.what(), mol->getType().c_str());
516 painCave.isFatal = 1;
517 simError();
518 }
519 } else {
520 bendType = ff->getBendType(normalAtom->getType(), ghostAtom->getType(),
521 "GHOST");
522
523 if (bendType == NULL) {
524 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
525 "Can not find Matching Bend Type for[%s, %s, %s]",
526 normalAtom->getType().c_str(), ghostAtom->getType().c_str(),
527 "GHOST");
528
529 painCave.isFatal = 1;
530 simError();
531 }
532 }
533
534 bend = new GhostBend(normalAtom, ghostAtom, bendType);
535 }
536
537 // set the local index of this bend, the global index will be set later
538 bend->setLocalIndex(localIndexMan->getNextBendIndex());
539
540 // The rule for naming a bend is: MoleculeName_Bend_Integer
541 // The first part is the name of the molecule
542 // The second part is always fixed as "Bend"
543 // The third part is the index of the bend defined in meta-data file
544 // For example, Butane_Bend_0 is a valid Bend name in a butane molecule
545
546 std::string s = OpenMD_itoa(mol->getNBends(), 10);
547 bend->setName(mol->getType() + "_Bend_" + s.c_str());
548 return bend;
549 }
550
551 Torsion* MoleculeCreator::createTorsion(ForceField* ff, Molecule* mol,
552 TorsionStamp* stamp,
553 LocalIndexManager* localIndexMan) {
554 TorsionTypeParser ttParser;
555 TorsionType* torsionType = NULL;
556 Torsion* torsion = NULL;
557
558 std::vector<int> torsionAtoms = stamp->getMembers();
559 if (torsionAtoms.size() < 3) { return torsion; }
560
561 Atom* atomA = mol->getAtomAt(torsionAtoms[0]);
562 Atom* atomB = mol->getAtomAt(torsionAtoms[1]);
563 Atom* atomC = mol->getAtomAt(torsionAtoms[2]);
564
565 if (torsionAtoms.size() == 4) {
566 Atom* atomD = mol->getAtomAt(torsionAtoms[3]);
567
568 assert(atomA && atomB && atomC && atomD);
569
570 if (stamp->hasOverride()) {
571 try {
572 torsionType = ttParser.parseTypeAndPars(stamp->getOverrideType(),
573 stamp->getOverridePars());
574 } catch (OpenMDException& e) {
575 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
576 "MoleculeCreator Error: %s "
577 "for molecule %s\n",
578 e.what(), mol->getType().c_str());
579 painCave.isFatal = 1;
580 simError();
581 }
582 } else {
583 torsionType = ff->getTorsionType(atomA->getType(), atomB->getType(),
584 atomC->getType(), atomD->getType());
585 if (torsionType == NULL) {
586 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
587 "Can not find Matching Torsion Type for[%s, %s, %s, %s]",
588 atomA->getType().c_str(), atomB->getType().c_str(),
589 atomC->getType().c_str(), atomD->getType().c_str());
590
591 painCave.isFatal = 1;
592 simError();
593 }
594 }
595
596 torsion = new Torsion(atomA, atomB, atomC, atomD, torsionType);
597 } else {
598 DirectionalAtom* dAtom = dynamic_cast<DirectionalAtom*>(
599 mol->getAtomAt(stamp->getGhostVectorSource()));
600 if (dAtom == NULL) {
601 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
602 "Can not cast Atom to DirectionalAtom");
603 painCave.isFatal = 1;
604 simError();
605 }
606
607 if (stamp->hasOverride()) {
608 try {
609 torsionType = ttParser.parseTypeAndPars(stamp->getOverrideType(),
610 stamp->getOverridePars());
611 } catch (OpenMDException& e) {
612 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
613 "MoleculeCreator Error: %s "
614 "for molecule %s\n",
615 e.what(), mol->getType().c_str());
616 painCave.isFatal = 1;
617 simError();
618 }
619 } else {
620 torsionType = ff->getTorsionType(atomA->getType(), atomB->getType(),
621 atomC->getType(), "GHOST");
622
623 if (torsionType == NULL) {
624 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
625 "Can not find Matching Torsion Type for[%s, %s, %s, %s]",
626 atomA->getType().c_str(), atomB->getType().c_str(),
627 atomC->getType().c_str(), "GHOST");
628
629 painCave.isFatal = 1;
630 simError();
631 }
632 }
633
634 torsion = new GhostTorsion(atomA, atomB, dAtom, torsionType);
635 }
636
637 // set the local index of this torsion, the global index will be set later
638 torsion->setLocalIndex(localIndexMan->getNextTorsionIndex());
639
640 // The rule for naming a torsion is: MoleculeName_Torsion_Integer
641 // The first part is the name of the molecule
642 // The second part is always fixed as "Torsion"
643 // The third part is the index of the torsion defined in meta-data file
644 // For example, Butane_Torsion_0 is a valid Torsion name in a
645 // butane molecule
646
647 std::string s = OpenMD_itoa(mol->getNTorsions(), 10);
648 torsion->setName(mol->getType() + "_Torsion_" + s.c_str());
649 return torsion;
650 }
651
652 Inversion* MoleculeCreator::createInversion(
653 ForceField* ff, Molecule* mol, InversionStamp* stamp,
654 LocalIndexManager* localIndexMan) {
655 InversionTypeParser itParser;
656 InversionType* inversionType = NULL;
657 Inversion* inversion = NULL;
658
659 int center = stamp->getCenter();
660 std::vector<int> satellites = stamp->getSatellites();
661 if (satellites.size() != 3) { return inversion; }
662
663 Atom* atomA = mol->getAtomAt(center);
664 Atom* atomB = mol->getAtomAt(satellites[0]);
665 Atom* atomC = mol->getAtomAt(satellites[1]);
666 Atom* atomD = mol->getAtomAt(satellites[2]);
667
668 assert(atomA && atomB && atomC && atomD);
669
670 if (stamp->hasOverride()) {
671 try {
672 inversionType = itParser.parseTypeAndPars(stamp->getOverrideType(),
673 stamp->getOverridePars());
674 } catch (OpenMDException& e) {
675 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
676 "MoleculeCreator Error: %s "
677 "for molecule %s\n",
678 e.what(), mol->getType().c_str());
679 painCave.isFatal = 1;
680 simError();
681 }
682 } else {
683 inversionType = ff->getInversionType(atomA->getType(), atomB->getType(),
684 atomC->getType(), atomD->getType());
685
686 if (inversionType == NULL) {
687 snprintf(
688 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
689 "No Matching Inversion Type for[%s, %s, %s, %s]\n"
690 "\t(May not be a problem: not all inversions are parametrized)\n",
691 atomA->getType().c_str(), atomB->getType().c_str(),
692 atomC->getType().c_str(), atomD->getType().c_str());
693
694 painCave.isFatal = 0;
695 painCave.severity = OPENMD_INFO;
696 simError();
697 }
698 }
699 if (inversionType != NULL) {
700 inversion = new Inversion(atomA, atomB, atomC, atomD, inversionType);
701
702 // set the local index of this inversion, the global index will
703 // be set later
704 inversion->setLocalIndex(localIndexMan->getNextInversionIndex());
705
706 // The rule for naming an inversion is: MoleculeName_Inversion_Integer
707 // The first part is the name of the molecule
708 // The second part is always fixed as "Inversion"
709 // The third part is the index of the inversion defined in meta-data file
710 // For example, Benzene_Inversion_0 is a valid Inversion name in a
711 // Benzene molecule
712
713 std::string s = OpenMD_itoa(mol->getNInversions(), 10);
714 inversion->setName(mol->getType() + "_Inversion_" + s.c_str());
715 return inversion;
716 } else {
717 return NULL;
718 }
719 }
720
721 CutoffGroup* MoleculeCreator::createCutoffGroup(
722 Molecule* mol, CutoffGroupStamp* stamp,
723 LocalIndexManager* localIndexMan) {
724 size_t nAtoms;
725 CutoffGroup* cg;
726 Atom* atom;
727 cg = new CutoffGroup();
728
729 nAtoms = stamp->getNMembers();
730 for (size_t i = 0; i < nAtoms; ++i) {
731 atom = mol->getAtomAt(stamp->getMemberAt(i));
732 assert(atom);
733 cg->addAtom(atom);
734 }
735
736 // set the local index of this cutoffGroup, global index will be set later
737 cg->setLocalIndex(localIndexMan->getNextCutoffGroupIndex());
738
739 return cg;
740 }
741
742 CutoffGroup* MoleculeCreator::createCutoffGroup(
743 Molecule*, Atom* atom, LocalIndexManager* localIndexMan) {
744 CutoffGroup* cg;
745 cg = new CutoffGroup();
746 cg->addAtom(atom);
747
748 // set the local index of this cutoffGroup, global index will be set later
749 cg->setLocalIndex(localIndexMan->getNextCutoffGroupIndex());
750
751 return cg;
752 }
753
754 void MoleculeCreator::createConstraintPair(Molecule* mol) {
755 // add bond constraints
756 Molecule::BondIterator bi;
757 Bond* bond;
758 ConstraintPair* cPair;
759
760 for (bond = mol->beginBond(bi); bond != NULL; bond = mol->nextBond(bi)) {
761 BondType* bt = bond->getBondType();
762
763 if (typeid(FixedBondType) == typeid(*bt)) {
764 FixedBondType* fbt = dynamic_cast<FixedBondType*>(bt);
765
766 ConstraintElem* consElemA = new ConstraintElem(bond->getAtomA());
767 ConstraintElem* consElemB = new ConstraintElem(bond->getAtomB());
768 cPair = new ConstraintPair(consElemA, consElemB,
769 fbt->getEquilibriumBondLength(), false);
770 mol->addConstraintPair(cPair);
771 }
772 }
773
774 // rigidbody -- rigidbody constraint is not support yet
775 }
776
777 void MoleculeCreator::createConstraintElem(Molecule* mol) {
778 ConstraintPair* consPair;
779 Molecule::ConstraintPairIterator cpi;
780 std::set<StuntDouble*> sdSet;
781 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
782 consPair = mol->nextConstraintPair(cpi)) {
783 StuntDouble* sdA = consPair->getConsElem1()->getStuntDouble();
784 if (sdSet.find(sdA) == sdSet.end()) {
785 sdSet.insert(sdA);
786 mol->addConstraintElem(new ConstraintElem(sdA));
787 }
788
789 StuntDouble* sdB = consPair->getConsElem2()->getStuntDouble();
790 if (sdSet.find(sdB) == sdSet.end()) {
791 sdSet.insert(sdB);
792 mol->addConstraintElem(new ConstraintElem(sdB));
793 }
794 }
795 }
796} // namespace OpenMD
AtomType is what OpenMD looks to for unchanging data about an atom.
Definition AtomType.hpp:69
AtomType * getAtomType(const std::string &at)
getAtomType by string
"utils/LocalIndexManager.hpp"
virtual Atom * createAtom(ForceField *ff, AtomStamp *stamp, LocalIndexManager *localIndexMan)
Create an atom by its stamp.
size_t getNRigidBodies()
Returns the total number of rigid bodies in this molecule.
Definition Molecule.hpp:180
std::string getType()
Returns the name of the molecule.
Definition Molecule.hpp:124
virtual void setType(const std::string &name)
Sets the name of this stuntRealType.
Definition RigidBody.hpp:74
void calcRefCoords()
calculates the reference coordinates
void setLocalIndex(int index)
Sets the local index of this ShortRangeInteraction.
void setLocalIndex(int index)
Sets the local index of this stuntDouble.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.