56#include "primitives/GhostTorsion.hpp"
57#include "types/AtomType.hpp"
59#include "types/BondTypeParser.hpp"
60#include "types/BendTypeParser.hpp"
61#include "types/TorsionTypeParser.hpp"
62#include "types/InversionTypeParser.hpp"
63#include "types/UFFAdapter.hpp"
64#include "types/HarmonicBondType.hpp"
66#include "utils/simError.h"
68#include "forcefields/UFF.hpp"
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 int nAtom = molStamp->getNAtoms();
83 for (
int i = 0; i < nAtom; ++i) {
84 currentAtomStamp = molStamp->getAtomStamp(i);
85 atom =
createAtom(ff, mol, currentAtomStamp, localIndexMan);
91 RigidBodyStamp * currentRigidBodyStamp;
92 int nRigidbodies = molStamp->getNRigidBodies();
94 for (
int i = 0; i < nRigidbodies; ++i) {
95 currentRigidBodyStamp = molStamp->getRigidBodyStamp(i);
96 rb = createRigidBody(molStamp, mol, currentRigidBodyStamp,
98 mol->addRigidBody(rb);
103 BondStamp* currentBondStamp;
104 int nBonds = molStamp->getNBonds();
106 for (
int i = 0; i < nBonds; ++i) {
107 currentBondStamp = molStamp->getBondStamp(i);
108 bond = createBond(ff, mol, currentBondStamp, localIndexMan);
114 BendStamp* currentBendStamp;
115 int nBends = molStamp->getNBends();
116 for (
int i = 0; i < nBends; ++i) {
117 currentBendStamp = molStamp->getBendStamp(i);
118 bend = createBend(ff, mol, currentBendStamp, localIndexMan);
124 TorsionStamp* currentTorsionStamp;
125 int nTorsions = molStamp->getNTorsions();
126 for (
int i = 0; i < nTorsions; ++i) {
127 currentTorsionStamp = molStamp->getTorsionStamp(i);
128 torsion = createTorsion(ff, mol, currentTorsionStamp, localIndexMan);
129 mol->addTorsion(torsion);
133 Inversion* inversion;
134 InversionStamp* currentInversionStamp;
135 int nInversions = molStamp->getNInversions();
136 for (
int i = 0; i < nInversions; ++i) {
137 currentInversionStamp = molStamp->getInversionStamp(i);
138 inversion = createInversion(ff, mol, currentInversionStamp,
140 if (inversion != NULL ) {
141 mol->addInversion(inversion);
146 CutoffGroup* cutoffGroup;
147 CutoffGroupStamp* currentCutoffGroupStamp;
148 int nCutoffGroups = molStamp->getNCutoffGroups();
149 for (
int i = 0; i < nCutoffGroups; ++i) {
150 currentCutoffGroupStamp = molStamp->getCutoffGroupStamp(i);
151 cutoffGroup = createCutoffGroup(mol, currentCutoffGroupStamp,
153 mol->addCutoffGroup(cutoffGroup);
157 std::vector<Atom*> freeAtoms;
158 std::vector<Atom*>::iterator ai;
159 std::vector<Atom*>::iterator fai;
162 for(atom = mol->beginAtom(fai); atom != NULL; atom = mol->nextAtom(fai)) {
163 freeAtoms.push_back(atom);
166 Molecule::CutoffGroupIterator ci;
169 for (cg = mol->beginCutoffGroup(ci); cg != NULL;
170 cg = mol->nextCutoffGroup(ci)) {
172 for(atom = cg->beginAtom(ai); atom != NULL; atom = cg->nextAtom(ai)) {
174 freeAtoms.erase(std::remove(freeAtoms.begin(), freeAtoms.end(), atom),
182 for (fai = freeAtoms.begin(); fai != freeAtoms.end(); ++fai) {
183 cutoffGroup = createCutoffGroup(mol, *fai, localIndexMan);
184 mol->addCutoffGroup(cutoffGroup);
188 createConstraintPair(mol);
191 for (std::size_t i = 0; i < molStamp->getNConstraints(); ++i) {
192 ConstraintStamp* cStamp = molStamp->getConstraintStamp(i);
196 atomA = mol->getAtomAt(cStamp->getA());
197 atomB = mol->getAtomAt(cStamp->getB());
198 assert( atomA && atomB );
200 bool printConstraintForce =
false;
202 if (cStamp->havePrintConstraintForce()) {
203 printConstraintForce = cStamp->getPrintConstraintForce();
206 if (!cStamp->haveConstrainedDistance()) {
207 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
208 "Constraint Error: A non-bond constraint was specified\n"
209 "\twithout providing a value for the constrainedDistance.\n");
210 painCave.isFatal = 1;
213 RealType
distance = cStamp->getConstrainedDistance();
214 ConstraintElem* consElemA =
new ConstraintElem(atomA);
215 ConstraintElem* consElemB =
new ConstraintElem(atomB);
216 ConstraintPair* cPair =
new ConstraintPair(consElemA, consElemB,
218 printConstraintForce);
219 mol->addConstraintPair(cPair);
225 createConstraintElem(mol);
229 if (molStamp->haveConstrainTotalCharge() ) {
230 mol->setConstrainTotalCharge( molStamp->getConstrainTotalCharge() );
248 if (atomType == NULL) {
249 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"Can not find Matching Atom Type for[%s]",
250 stamp->getType().c_str());
252 painCave.isFatal = 1;
257 if (atomType->isDirectional()){
264 atom =
new Atom(atomType);
282 nAtoms = rbStamp->getNMembers();
283 for (
int i = 0; i < nAtoms; ++i) {
287 atom = mol->getAtomAt(rbStamp->getMemberAt(i));
288 atomStamp= molStamp->getAtomStamp(rbStamp->getMemberAt(i));
289 rb->addAtom(atom, atomStamp);
310 Bond* MoleculeCreator::createBond(ForceField* ff, Molecule* mol,
312 LocalIndexManager* localIndexMan) {
313 BondTypeParser btParser;
314 BondType* bondType = NULL;
318 atomA = mol->getAtomAt(stamp->getA());
319 atomB = mol->getAtomAt(stamp->getB());
321 assert( atomA && atomB);
323 if (stamp->hasOverride()) {
325 bondType = btParser.parseTypeAndPars(stamp->getOverrideType(),
326 stamp->getOverridePars() );
328 catch( OpenMDException& e) {
329 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"MoleculeCreator Error: %s "
331 e.what(), mol->getType().c_str() );
332 painCave.isFatal = 1;
338 bondType = ff->getBondType(atomA->getType(), atomB->getType());
340 if (bondType == NULL) {
342 if (ff->getForceFieldOptions().getDelayedParameterCalculation()) {
344 RealType bondorder = stamp->getBondOrder();
346 RealType b0 = UFF::calcBondRestLength(bondorder,
347 atomA->getAtomType(),
348 atomB->getAtomType() );
350 RealType kb = UFF::calcBondForceConstant(b0,
351 atomA->getAtomType(),
352 atomB->getAtomType() );
354 bondType =
new HarmonicBondType(b0, kb);
356 ff->addBondType(atomA->getType(), atomB->getType(), bondType);
360 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"Can not find Matching Bond Type for[%s, %s]",
361 atomA->getType().c_str(),
362 atomB->getType().c_str());
364 painCave.isFatal = 1;
370 Bond* bond =
new Bond(atomA, atomB, bondType);
373 bond->setLocalIndex(localIndexMan->getNextBondIndex());
381 std::string s = OpenMD_itoa(mol->getNBonds(), 10);
382 bond->setName(mol->getType() +
"_Bond_" + s.c_str());
386 Bend* MoleculeCreator::createBend(ForceField* ff, Molecule* mol,
388 LocalIndexManager* localIndexMan) {
389 BendTypeParser btParser;
390 BendType* bendType = NULL;
393 std::vector<int> bendAtoms = stamp->getMembers();
394 if (bendAtoms.size() == 3) {
395 Atom* atomA = mol->getAtomAt(bendAtoms[0]);
396 Atom* atomB = mol->getAtomAt(bendAtoms[1]);
397 Atom* atomC = mol->getAtomAt(bendAtoms[2]);
399 assert( atomA && atomB && atomC );
401 if (stamp->hasOverride()) {
404 bendType = btParser.parseTypeAndPars(stamp->getOverrideType(),
405 stamp->getOverridePars() );
407 catch( OpenMDException& e) {
408 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"MoleculeCreator Error: %s "
410 e.what(), mol->getType().c_str() );
411 painCave.isFatal = 1;
416 bendType = ff->getBendType(atomA->getType().c_str(),
417 atomB->getType().c_str(),
418 atomC->getType().c_str());
420 if (bendType == NULL) {
422 if (ff->getForceFieldOptions().getDelayedParameterCalculation()) {
423 UFFAdapter uffj = UFFAdapter(atomB->getAtomType());
424 RealType theta0 = uffj.getTheta0() * Constants::PI / 180.0;
428 RealType ktheta = UFF:calcAngleForceConstant(theta0, bo12, bo23,
429 atomA->getAtomType(),
430 atomB->getAtomType(),
431 atomC->getAtomType());
432 bendType =
new HarmonicBendType(theta0, ktheta);
434 ff->addBendType(atomA->getType(), atomB->getType(),
435 atomC->getType(), bendType);
439 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
440 "Can not find Matching Bend Type for[%s, %s, %s]",
441 atomA->getType().c_str(),
442 atomB->getType().c_str(),
443 atomC->getType().c_str());
445 painCave.isFatal = 1;
450 bend =
new Bend(atomA, atomB, atomC, bendType);
453 }
else if ( bendAtoms.size() == 2 && stamp->haveGhostVectorSource()) {
454 int ghostIndex = stamp->getGhostVectorSource();
455 int normalIndex = ghostIndex != bendAtoms[0] ?
456 bendAtoms[0] : bendAtoms[1];
457 Atom* normalAtom = mol->getAtomAt(normalIndex) ;
458 DirectionalAtom* ghostAtom =
dynamic_cast<DirectionalAtom*
>(mol->getAtomAt(ghostIndex));
459 if (ghostAtom == NULL) {
460 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"Can not cast Atom to DirectionalAtom");
461 painCave.isFatal = 1;
465 if (stamp->hasOverride()) {
468 bendType = btParser.parseTypeAndPars(stamp->getOverrideType(),
469 stamp->getOverridePars() );
471 catch( OpenMDException& e) {
472 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"MoleculeCreator Error: %s "
474 e.what(), mol->getType().c_str() );
475 painCave.isFatal = 1;
480 bendType = ff->getBendType(normalAtom->getType(),
481 ghostAtom->getType(),
484 if (bendType == NULL) {
485 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
486 "Can not find Matching Bend Type for[%s, %s, %s]",
487 normalAtom->getType().c_str(),
488 ghostAtom->getType().c_str(),
491 painCave.isFatal = 1;
496 bend =
new GhostBend(normalAtom, ghostAtom, bendType);
501 bend->setLocalIndex(localIndexMan->getNextBendIndex());
509 std::string s = OpenMD_itoa(mol->getNBends(), 10);
510 bend->setName(mol->getType() +
"_Bend_" + s.c_str());
515 Torsion* MoleculeCreator::createTorsion(ForceField* ff, Molecule* mol,
517 LocalIndexManager* localIndexMan) {
519 TorsionTypeParser ttParser;
520 TorsionType* torsionType = NULL;
521 Torsion* torsion = NULL;
523 std::vector<int> torsionAtoms = stamp->getMembers();
524 if (torsionAtoms.size() < 3) {
528 Atom* atomA = mol->getAtomAt(torsionAtoms[0]);
529 Atom* atomB = mol->getAtomAt(torsionAtoms[1]);
530 Atom* atomC = mol->getAtomAt(torsionAtoms[2]);
532 if (torsionAtoms.size() == 4) {
533 Atom* atomD = mol->getAtomAt(torsionAtoms[3]);
535 assert(atomA && atomB && atomC && atomD );
537 if (stamp->hasOverride()) {
540 torsionType = ttParser.parseTypeAndPars(stamp->getOverrideType(),
541 stamp->getOverridePars() );
543 catch( OpenMDException& e) {
544 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"MoleculeCreator Error: %s "
546 e.what(), mol->getType().c_str() );
547 painCave.isFatal = 1;
553 torsionType = ff->getTorsionType(atomA->getType(),
557 if (torsionType == NULL) {
558 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
559 "Can not find Matching Torsion Type for[%s, %s, %s, %s]",
560 atomA->getType().c_str(),
561 atomB->getType().c_str(),
562 atomC->getType().c_str(),
563 atomD->getType().c_str());
565 painCave.isFatal = 1;
570 torsion =
new Torsion(atomA, atomB, atomC, atomD, torsionType);
573 DirectionalAtom* dAtom =
dynamic_cast<DirectionalAtom*
>(mol->getAtomAt(stamp->getGhostVectorSource()));
575 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"Can not cast Atom to DirectionalAtom");
576 painCave.isFatal = 1;
580 if (stamp->hasOverride()) {
583 torsionType = ttParser.parseTypeAndPars(stamp->getOverrideType(),
584 stamp->getOverridePars() );
586 catch( OpenMDException& e) {
587 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"MoleculeCreator Error: %s "
589 e.what(), mol->getType().c_str() );
590 painCave.isFatal = 1;
594 torsionType = ff->getTorsionType(atomA->getType(), atomB->getType(),
595 atomC->getType(),
"GHOST");
597 if (torsionType == NULL) {
598 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
599 "Can not find Matching Torsion Type for[%s, %s, %s, %s]",
600 atomA->getType().c_str(),
601 atomB->getType().c_str(),
602 atomC->getType().c_str(),
605 painCave.isFatal = 1;
610 torsion =
new GhostTorsion(atomA, atomB, dAtom, torsionType);
614 torsion->setLocalIndex(localIndexMan->getNextTorsionIndex());
623 std::string s = OpenMD_itoa(mol->getNTorsions(), 10);
624 torsion->setName(mol->getType() +
"_Torsion_" + s.c_str());
628 Inversion* MoleculeCreator::createInversion(ForceField* ff, Molecule* mol,
629 InversionStamp* stamp,
630 LocalIndexManager* localIndexMan) {
632 InversionTypeParser itParser;
633 InversionType* inversionType = NULL;
634 Inversion* inversion = NULL;
636 int center = stamp->getCenter();
637 std::vector<int> satellites = stamp->getSatellites();
638 if (satellites.size() != 3) {
642 Atom* atomA = mol->getAtomAt(center);
643 Atom* atomB = mol->getAtomAt(satellites[0]);
644 Atom* atomC = mol->getAtomAt(satellites[1]);
645 Atom* atomD = mol->getAtomAt(satellites[2]);
647 assert(atomA && atomB && atomC && atomD);
649 if (stamp->hasOverride()) {
652 inversionType = itParser.parseTypeAndPars(stamp->getOverrideType(),
653 stamp->getOverridePars() );
655 catch( OpenMDException& e) {
656 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
"MoleculeCreator Error: %s "
658 e.what(), mol->getType().c_str() );
659 painCave.isFatal = 1;
664 inversionType = ff->getInversionType(atomA->getType(),
669 if (inversionType == NULL) {
670 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
671 "No Matching Inversion Type for[%s, %s, %s, %s]\n"
672 "\t(May not be a problem: not all inversions are parametrized)\n",
673 atomA->getType().c_str(),
674 atomB->getType().c_str(),
675 atomC->getType().c_str(),
676 atomD->getType().c_str());
678 painCave.isFatal = 0;
679 painCave.severity = OPENMD_INFO;
683 if (inversionType != NULL) {
685 inversion =
new Inversion(atomA, atomB, atomC, atomD, inversionType);
689 inversion->setLocalIndex(localIndexMan->getNextInversionIndex());
698 std::string s = OpenMD_itoa(mol->getNInversions(), 10);
699 inversion->setName(mol->getType() +
"_Inversion_" + s.c_str());
707 CutoffGroup* MoleculeCreator::createCutoffGroup(Molecule* mol,
708 CutoffGroupStamp* stamp,
709 LocalIndexManager* localIndexMan) {
713 cg =
new CutoffGroup();
715 nAtoms = stamp->getNMembers();
716 for (
int i =0; i < nAtoms; ++i) {
717 atom = mol->getAtomAt(stamp->getMemberAt(i));
723 cg->setLocalIndex(localIndexMan->getNextCutoffGroupIndex());
728 CutoffGroup* MoleculeCreator::createCutoffGroup(Molecule * mol, Atom* atom,
729 LocalIndexManager* localIndexMan) {
731 cg =
new CutoffGroup();
735 cg->setLocalIndex(localIndexMan->getNextCutoffGroupIndex());
740 void MoleculeCreator::createConstraintPair(Molecule* mol) {
743 Molecule::BondIterator bi;
745 ConstraintPair* cPair;
747 for (bond = mol->beginBond(bi); bond != NULL; bond = mol->nextBond(bi)) {
749 BondType* bt = bond->getBondType();
751 if (
typeid(FixedBondType) ==
typeid(*bt)) {
752 FixedBondType* fbt =
dynamic_cast<FixedBondType*
>(bt);
754 ConstraintElem* consElemA =
new ConstraintElem(bond->getAtomA());
755 ConstraintElem* consElemB =
new ConstraintElem(bond->getAtomB());
756 cPair =
new ConstraintPair(consElemA, consElemB,
757 fbt->getEquilibriumBondLength(),
false);
758 mol->addConstraintPair(cPair);
765 void MoleculeCreator::createConstraintElem(Molecule* mol) {
767 ConstraintPair* consPair;
768 Molecule::ConstraintPairIterator cpi;
769 std::set<StuntDouble*> sdSet;
770 for (consPair = mol->beginConstraintPair(cpi); consPair != NULL;
771 consPair = mol->nextConstraintPair(cpi)) {
773 StuntDouble* sdA = consPair->getConsElem1()->getStuntDouble();
774 if (sdSet.find(sdA) == sdSet.end()){
776 mol->addConstraintElem(
new ConstraintElem(sdA));
779 StuntDouble* sdB = consPair->getConsElem2()->getStuntDouble();
780 if (sdSet.find(sdB) == sdSet.end()){
782 mol->addConstraintElem(
new ConstraintElem(sdB));
AtomType is what OpenMD looks to for unchanging data about an atom.
AtomType * getAtomType(const std::string &at)
getAtomType by string
"utils/LocalIndexManager.hpp"
virtual Atom * createAtom(ForceField *ff, Molecule *, AtomStamp *stamp, LocalIndexManager *localIndexMan)
Create an atom by its stamp.
size_t getNRigidBodies()
Returns the total number of rigid bodies in this molecule.
std::string getType()
Returns the name of the molecule.
virtual void setType(const std::string &name)
Sets the name of this stuntRealType.
void calcRefCoords()
calculates the reference coordinates
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.