59#include "primitives/GhostTorsion.hpp"
60#include "types/AtomType.hpp"
61#include "types/BendTypeParser.hpp"
62#include "types/BondTypeParser.hpp"
64#include "types/FixedChargeAdapter.hpp"
65#include "types/InversionTypeParser.hpp"
66#include "types/TorsionTypeParser.hpp"
68#include "utils/simError.h"
72 Molecule* MoleculeCreator::createMolecule(ForceField* ff,
73 MoleculeStamp* molStamp,
74 int stampId,
int globalIndex,
75 LocalIndexManager* localIndexMan) {
76 Molecule* mol =
new Molecule(stampId, globalIndex, molStamp->getName(),
77 molStamp->getRegion());
81 AtomStamp* currentAtomStamp;
82 size_t nAtom = molStamp->getNAtoms();
83 for (
size_t i = 0; i < nAtom; ++i) {
84 currentAtomStamp = molStamp->getAtomStamp(i);
85 atom =
createAtom(ff, mol, currentAtomStamp, localIndexMan);
91 RigidBodyStamp* currentRigidBodyStamp;
92 size_t nRigidbodies = molStamp->getNRigidBodies();
94 for (
size_t i = 0; i < nRigidbodies; ++i) {
95 currentRigidBodyStamp = molStamp->getRigidBodyStamp(i);
96 rb = createRigidBody(molStamp, mol, currentRigidBodyStamp, localIndexMan);
97 mol->addRigidBody(rb);
102 BondStamp* currentBondStamp;
103 size_t nBonds = molStamp->getNBonds();
105 for (
size_t i = 0; i < nBonds; ++i) {
106 currentBondStamp = molStamp->getBondStamp(i);
107 bond = createBond(ff, mol, currentBondStamp, localIndexMan);
113 BendStamp* currentBendStamp;
114 size_t nBends = molStamp->getNBends();
115 for (
size_t i = 0; i < nBends; ++i) {
116 currentBendStamp = molStamp->getBendStamp(i);
117 bend = createBend(ff, mol, currentBendStamp, localIndexMan);
123 TorsionStamp* currentTorsionStamp;
124 size_t nTorsions = molStamp->getNTorsions();
125 for (
size_t i = 0; i < nTorsions; ++i) {
126 currentTorsionStamp = molStamp->getTorsionStamp(i);
127 torsion = createTorsion(ff, mol, currentTorsionStamp, localIndexMan);
128 mol->addTorsion(torsion);
132 Inversion* inversion;
133 InversionStamp* currentInversionStamp;
134 size_t nInversions = molStamp->getNInversions();
135 for (
size_t i = 0; i < nInversions; ++i) {
136 currentInversionStamp = molStamp->getInversionStamp(i);
138 createInversion(ff, mol, currentInversionStamp, localIndexMan);
139 if (inversion != NULL) { mol->addInversion(inversion); }
143 CutoffGroup* cutoffGroup;
144 CutoffGroupStamp* currentCutoffGroupStamp;
145 size_t nCutoffGroups = molStamp->getNCutoffGroups();
146 for (
size_t i = 0; i < nCutoffGroups; ++i) {
147 currentCutoffGroupStamp = molStamp->getCutoffGroupStamp(i);
149 createCutoffGroup(mol, currentCutoffGroupStamp, localIndexMan);
150 mol->addCutoffGroup(cutoffGroup);
154 std::vector<Atom*> freeAtoms;
155 std::vector<Atom*>::iterator ai;
156 std::vector<Atom*>::iterator fai;
159 for (atom = mol->beginAtom(fai); atom != NULL; atom = mol->nextAtom(fai)) {
160 freeAtoms.push_back(atom);
163 Molecule::CutoffGroupIterator ci;
166 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
167 cg = mol->nextCutoffGroup(ci)) {
168 for (atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
170 freeAtoms.erase(std::remove(freeAtoms.begin(), freeAtoms.end(), atom),
178 for (fai = freeAtoms.begin(); fai != freeAtoms.end(); ++fai) {
179 cutoffGroup = createCutoffGroup(mol, *fai, localIndexMan);
180 mol->addCutoffGroup(cutoffGroup);
184 createConstraintPair(mol);
187 for (std::size_t i = 0; i < molStamp->getNConstraints(); ++i) {
188 ConstraintStamp* cStamp = molStamp->getConstraintStamp(i);
192 atomA = mol->getAtomAt(cStamp->getA());
193 atomB = mol->getAtomAt(cStamp->getB());
194 assert(atomA && atomB);
196 bool printConstraintForce =
false;
198 if (cStamp->havePrintConstraintForce()) {
199 printConstraintForce = cStamp->getPrintConstraintForce();
202 if (!cStamp->haveConstrainedDistance()) {
203 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
204 "Constraint Error: A non-bond constraint was specified\n"
205 "\twithout providing a value for the constrainedDistance.\n");
206 painCave.isFatal = 1;
209 RealType
distance = cStamp->getConstrainedDistance();
210 ConstraintElem* consElemA =
new ConstraintElem(atomA);
211 ConstraintElem* consElemB =
new ConstraintElem(atomB);
212 ConstraintPair* cPair =
new ConstraintPair(
213 consElemA, consElemB,
distance, printConstraintForce);
214 mol->addConstraintPair(cPair);
220 createConstraintElem(mol);
224 if (molStamp->haveConstrainTotalCharge()) {
225 mol->setConstrainTotalCharge(molStamp->getConstrainTotalCharge());
235 LocalIndexManager* localIndexMan) {
240 if (atomType == NULL) {
241 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
242 "Can not find Matching Atom Type for[%s]",
243 stamp->getType().c_str());
245 painCave.isFatal = 1;
249 if (stamp->hasOverride()) {
250 std::string baseType = atomType->getName();
251 RealType oc = stamp->getOverrideCharge();
254 std::ostringstream ss;
256 std::string atomTypeOverrideName = baseType +
"_q=" + ss.str();
260 AtomType* atB = ff->getAtomType(atomTypeOverrideName);
264 AtomType* atomTypeOverride =
new AtomType();
266 atomTypeOverride->useBase(atomType);
267 int ident = ff->getNAtomType();
268 atomTypeOverride->setIdent(ident);
269 atomTypeOverride->setName(atomTypeOverrideName);
270 ff->addAtomType(atomTypeOverrideName, atomTypeOverride);
271 FixedChargeAdapter fca = FixedChargeAdapter(atomTypeOverride);
273 ff->getForceFieldOptions().getChargeUnitScaling() * oc;
274 fca.makeFixedCharge(charge);
276 atomType = atomTypeOverride;
285 if (atomType->isDirectional()) {
286 DirectionalAtom* dAtom;
287 dAtom =
new DirectionalAtom(atomType);
290 atom =
new Atom(atomType);
293 atom->setLocalIndex(localIndexMan->getNextAtomIndex());
298 RigidBody* MoleculeCreator::createRigidBody(
299 MoleculeStamp* molStamp, Molecule* mol, RigidBodyStamp* rbStamp,
300 LocalIndexManager* localIndexMan) {
304 AtomStamp* atomStamp;
306 RigidBody* rb =
new RigidBody();
307 nAtoms = rbStamp->getNMembers();
308 for (std::size_t i = 0; i < nAtoms; ++i) {
312 atom = mol->getAtomAt(rbStamp->getMemberAt(i));
313 atomStamp = molStamp->getAtomStamp(rbStamp->getMemberAt(i));
314 rb->addAtom(atom, atomStamp);
322 rb->setLocalIndex(localIndexMan->getNextRigidBodyIndex());
330 std::string s = OpenMD_itoa(mol->getNRigidBodies(), 10);
331 rb->setType(mol->getType() +
"_RB_" + s.c_str());
335 Bond* MoleculeCreator::createBond(ForceField* ff, Molecule* mol,
337 LocalIndexManager* localIndexMan) {
338 BondTypeParser btParser;
339 BondType* bondType = NULL;
343 atomA = mol->getAtomAt(stamp->getA());
344 atomB = mol->getAtomAt(stamp->getB());
346 assert(atomA && atomB);
348 if (stamp->hasOverride()) {
350 bondType = btParser.parseTypeAndPars(stamp->getOverrideType(),
351 stamp->getOverridePars());
352 }
catch (OpenMDException& e) {
353 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
354 "MoleculeCreator Error: %s "
356 e.what(), mol->getType().c_str());
357 painCave.isFatal = 1;
362 bondType = ff->getBondType(atomA->getType(), atomB->getType());
364 if (bondType == NULL) {
365 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
366 "Can not find Matching Bond Type for[%s, %s]",
367 atomA->getType().c_str(), atomB->getType().c_str());
369 painCave.isFatal = 1;
374 Bond* bond =
new Bond(atomA, atomB, bondType);
377 bond->setLocalIndex(localIndexMan->getNextBondIndex());
385 std::string s = OpenMD_itoa(mol->getNBonds(), 10);
386 bond->setName(mol->getType() +
"_Bond_" + s.c_str());
390 Bend* MoleculeCreator::createBend(ForceField* ff, Molecule* mol,
392 LocalIndexManager* localIndexMan) {
393 BendTypeParser btParser;
394 BendType* bendType = NULL;
397 std::vector<int> bendAtoms = stamp->getMembers();
398 if (bendAtoms.size() == 3) {
399 Atom* atomA = mol->getAtomAt(bendAtoms[0]);
400 Atom* atomB = mol->getAtomAt(bendAtoms[1]);
401 Atom* atomC = mol->getAtomAt(bendAtoms[2]);
403 assert(atomA && atomB && atomC);
405 if (stamp->hasOverride()) {
407 bendType = btParser.parseTypeAndPars(stamp->getOverrideType(),
408 stamp->getOverridePars());
409 }
catch (OpenMDException& e) {
410 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
411 "MoleculeCreator Error: %s "
413 e.what(), mol->getType().c_str());
414 painCave.isFatal = 1;
419 ff->getBendType(atomA->getType().c_str(), atomB->getType().c_str(),
420 atomC->getType().c_str());
422 if (bendType == NULL) {
423 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
424 "Can not find Matching Bend Type for[%s, %s, %s]",
425 atomA->getType().c_str(), atomB->getType().c_str(),
426 atomC->getType().c_str());
428 painCave.isFatal = 1;
433 bend =
new Bend(atomA, atomB, atomC, bendType);
435 }
else if (bendAtoms.size() == 2 && stamp->haveGhostVectorSource()) {
436 int ghostIndex = stamp->getGhostVectorSource();
438 ghostIndex != bendAtoms[0] ? bendAtoms[0] : bendAtoms[1];
439 Atom* normalAtom = mol->getAtomAt(normalIndex);
440 DirectionalAtom* ghostAtom =
441 dynamic_cast<DirectionalAtom*
>(mol->getAtomAt(ghostIndex));
442 if (ghostAtom == NULL) {
443 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
444 "Can not cast Atom to DirectionalAtom");
445 painCave.isFatal = 1;
449 if (stamp->hasOverride()) {
451 bendType = btParser.parseTypeAndPars(stamp->getOverrideType(),
452 stamp->getOverridePars());
453 }
catch (OpenMDException& e) {
454 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
455 "MoleculeCreator Error: %s "
457 e.what(), mol->getType().c_str());
458 painCave.isFatal = 1;
462 bendType = ff->getBendType(normalAtom->getType(), ghostAtom->getType(),
465 if (bendType == NULL) {
466 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
467 "Can not find Matching Bend Type for[%s, %s, %s]",
468 normalAtom->getType().c_str(), ghostAtom->getType().c_str(),
471 painCave.isFatal = 1;
476 bend =
new GhostBend(normalAtom, ghostAtom, bendType);
480 bend->setLocalIndex(localIndexMan->getNextBendIndex());
488 std::string s = OpenMD_itoa(mol->getNBends(), 10);
489 bend->setName(mol->getType() +
"_Bend_" + s.c_str());
493 Torsion* MoleculeCreator::createTorsion(ForceField* ff, Molecule* mol,
495 LocalIndexManager* localIndexMan) {
496 TorsionTypeParser ttParser;
497 TorsionType* torsionType = NULL;
498 Torsion* torsion = NULL;
500 std::vector<int> torsionAtoms = stamp->getMembers();
501 if (torsionAtoms.size() < 3) {
return torsion; }
503 Atom* atomA = mol->getAtomAt(torsionAtoms[0]);
504 Atom* atomB = mol->getAtomAt(torsionAtoms[1]);
505 Atom* atomC = mol->getAtomAt(torsionAtoms[2]);
507 if (torsionAtoms.size() == 4) {
508 Atom* atomD = mol->getAtomAt(torsionAtoms[3]);
510 assert(atomA && atomB && atomC && atomD);
512 if (stamp->hasOverride()) {
514 torsionType = ttParser.parseTypeAndPars(stamp->getOverrideType(),
515 stamp->getOverridePars());
516 }
catch (OpenMDException& e) {
517 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
518 "MoleculeCreator Error: %s "
520 e.what(), mol->getType().c_str());
521 painCave.isFatal = 1;
525 torsionType = ff->getTorsionType(atomA->getType(), atomB->getType(),
526 atomC->getType(), atomD->getType());
527 if (torsionType == NULL) {
528 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
529 "Can not find Matching Torsion Type for[%s, %s, %s, %s]",
530 atomA->getType().c_str(), atomB->getType().c_str(),
531 atomC->getType().c_str(), atomD->getType().c_str());
533 painCave.isFatal = 1;
538 torsion =
new Torsion(atomA, atomB, atomC, atomD, torsionType);
540 DirectionalAtom* dAtom =
dynamic_cast<DirectionalAtom*
>(
541 mol->getAtomAt(stamp->getGhostVectorSource()));
543 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
544 "Can not cast Atom to DirectionalAtom");
545 painCave.isFatal = 1;
549 if (stamp->hasOverride()) {
551 torsionType = ttParser.parseTypeAndPars(stamp->getOverrideType(),
552 stamp->getOverridePars());
553 }
catch (OpenMDException& e) {
554 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
555 "MoleculeCreator Error: %s "
557 e.what(), mol->getType().c_str());
558 painCave.isFatal = 1;
562 torsionType = ff->getTorsionType(atomA->getType(), atomB->getType(),
563 atomC->getType(),
"GHOST");
565 if (torsionType == NULL) {
566 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
567 "Can not find Matching Torsion Type for[%s, %s, %s, %s]",
568 atomA->getType().c_str(), atomB->getType().c_str(),
569 atomC->getType().c_str(),
"GHOST");
571 painCave.isFatal = 1;
576 torsion =
new GhostTorsion(atomA, atomB, dAtom, torsionType);
580 torsion->setLocalIndex(localIndexMan->getNextTorsionIndex());
589 std::string s = OpenMD_itoa(mol->getNTorsions(), 10);
590 torsion->setName(mol->getType() +
"_Torsion_" + s.c_str());
594 Inversion* MoleculeCreator::createInversion(
595 ForceField* ff, Molecule* mol, InversionStamp* stamp,
596 LocalIndexManager* localIndexMan) {
597 InversionTypeParser itParser;
598 InversionType* inversionType = NULL;
599 Inversion* inversion = NULL;
601 int center = stamp->getCenter();
602 std::vector<int> satellites = stamp->getSatellites();
603 if (satellites.size() != 3) {
return inversion; }
605 Atom* atomA = mol->getAtomAt(center);
606 Atom* atomB = mol->getAtomAt(satellites[0]);
607 Atom* atomC = mol->getAtomAt(satellites[1]);
608 Atom* atomD = mol->getAtomAt(satellites[2]);
610 assert(atomA && atomB && atomC && atomD);
612 if (stamp->hasOverride()) {
614 inversionType = itParser.parseTypeAndPars(stamp->getOverrideType(),
615 stamp->getOverridePars());
616 }
catch (OpenMDException& e) {
617 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
618 "MoleculeCreator Error: %s "
620 e.what(), mol->getType().c_str());
621 painCave.isFatal = 1;
625 inversionType = ff->getInversionType(atomA->getType(), atomB->getType(),
626 atomC->getType(), atomD->getType());
628 if (inversionType == NULL) {
630 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
631 "No Matching Inversion Type for[%s, %s, %s, %s]\n"
632 "\t(May not be a problem: not all inversions are parametrized)\n",
633 atomA->getType().c_str(), atomB->getType().c_str(),
634 atomC->getType().c_str(), atomD->getType().c_str());
636 painCave.isFatal = 0;
637 painCave.severity = OPENMD_INFO;
641 if (inversionType != NULL) {
642 inversion =
new Inversion(atomA, atomB, atomC, atomD, inversionType);
646 inversion->setLocalIndex(localIndexMan->getNextInversionIndex());
655 std::string s = OpenMD_itoa(mol->getNInversions(), 10);
656 inversion->setName(mol->getType() +
"_Inversion_" + s.c_str());
663 CutoffGroup* MoleculeCreator::createCutoffGroup(
664 Molecule* mol, CutoffGroupStamp* stamp,
665 LocalIndexManager* localIndexMan) {
669 cg =
new CutoffGroup();
671 nAtoms = stamp->getNMembers();
672 for (
size_t i = 0; i < nAtoms; ++i) {
673 atom = mol->getAtomAt(stamp->getMemberAt(i));
679 cg->setLocalIndex(localIndexMan->getNextCutoffGroupIndex());
684 CutoffGroup* MoleculeCreator::createCutoffGroup(
685 Molecule*, Atom* atom, LocalIndexManager* localIndexMan) {
687 cg =
new CutoffGroup();
691 cg->setLocalIndex(localIndexMan->getNextCutoffGroupIndex());
696 void MoleculeCreator::createConstraintPair(Molecule* mol) {
698 Molecule::BondIterator bi;
700 ConstraintPair* cPair;
702 for (bond = mol->beginBond(bi); bond != NULL; bond = mol->nextBond(bi)) {
703 BondType* bt = bond->getBondType();
705 if (
typeid(FixedBondType) ==
typeid(*bt)) {
706 FixedBondType* fbt =
dynamic_cast<FixedBondType*
>(bt);
708 ConstraintElem* consElemA =
new ConstraintElem(bond->getAtomA());
709 ConstraintElem* consElemB =
new ConstraintElem(bond->getAtomB());
710 cPair =
new ConstraintPair(consElemA, consElemB,
711 fbt->getEquilibriumBondLength(),
false);
712 mol->addConstraintPair(cPair);
719 void MoleculeCreator::createConstraintElem(Molecule* mol) {
720 ConstraintPair* consPair;
721 Molecule::ConstraintPairIterator cpi;
722 std::set<StuntDouble*> sdSet;
723 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
724 consPair = mol->nextConstraintPair(cpi)) {
725 StuntDouble* sdA = consPair->getConsElem1()->getStuntDouble();
726 if (sdSet.find(sdA) == sdSet.end()) {
728 mol->addConstraintElem(
new ConstraintElem(sdA));
731 StuntDouble* sdB = consPair->getConsElem2()->getStuntDouble();
732 if (sdSet.find(sdB) == sdSet.end()) {
734 mol->addConstraintElem(
new ConstraintElem(sdB));
AtomType * getAtomType()
Returns the AtomType of this Atom.
virtual Atom * createAtom(ForceField *ff, Molecule *, AtomStamp *stamp, LocalIndexManager *localIndexMan)
Create an atom by its stamp.
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.