45#include "nonbonded/InteractionManager.hpp"
47#include "types/InversePowerSeriesInteractionType.hpp"
48#include "types/LennardJonesInteractionType.hpp"
49#include "types/MAWInteractionType.hpp"
50#include "types/MieInteractionType.hpp"
51#include "types/MorseInteractionType.hpp"
52#include "types/RepulsivePowerInteractionType.hpp"
56 InteractionManager::InteractionManager() {
59 lj_ = std::make_shared<LJ>();
60 gb_ = std::make_shared<GB>();
61 sticky_ = std::make_shared<Sticky>();
62 morse_ = std::make_shared<Morse>();
63 repulsivePower_ = std::make_shared<RepulsivePower>();
64 mie_ = std::make_shared<Mie>();
65 eam_ = std::make_shared<EAM>();
66 sc_ = std::make_shared<SC>();
67 electrostatic_ = std::make_shared<Electrostatic>();
68 maw_ = std::make_shared<MAW>();
69 inversePowerSeries_ = std::make_shared<InversePowerSeries>();
72 void InteractionManager::initialize() {
73 if (initialized_)
return;
77 lj_->setForceField(forceField_);
78 gb_->setForceField(forceField_);
79 sticky_->setForceField(forceField_);
80 eam_->setForceField(forceField_);
81 eam_->setElectrostatic(electrostatic_.get());
82 sc_->setForceField(forceField_);
83 morse_->setForceField(forceField_);
84 electrostatic_->setSimInfo(info_);
85 electrostatic_->setForceField(forceField_);
86 maw_->setForceField(forceField_);
87 repulsivePower_->setForceField(forceField_);
88 mie_->setForceField(forceField_);
89 inversePowerSeries_->setForceField(forceField_);
92 int nTypes = atomTypes->size();
93 sHash_.resize(nTypes);
94 iHash_.resize(nTypes);
95 interactions_.resize(nTypes);
96 ForceField::AtomTypeContainer::MapTypeIterator i1, i2;
106 lj_->setSimulatedAtomTypes(atypes);
107 gb_->setSimulatedAtomTypes(atypes);
108 sticky_->setSimulatedAtomTypes(atypes);
109 eam_->setSimulatedAtomTypes(atypes);
110 sc_->setSimulatedAtomTypes(atypes);
111 morse_->setSimulatedAtomTypes(atypes);
112 electrostatic_->setSimInfo(info_);
113 electrostatic_->setSimulatedAtomTypes(atypes);
114 maw_->setSimulatedAtomTypes(atypes);
115 repulsivePower_->setSimulatedAtomTypes(atypes);
116 mie_->setSimulatedAtomTypes(atypes);
117 inversePowerSeries_->setSimulatedAtomTypes(atypes);
119 AtomTypeSet::iterator at;
120 set<NonBondedInteractionPtr>::iterator it;
122 for (at = atypes.begin(); at != atypes.end(); ++at) {
124 atid1 = atype1->getIdent();
125 iHash_[atid1].resize(nTypes);
126 interactions_[atid1].resize(nTypes);
129 pair<map<int, AtomType*>::iterator,
bool> ret;
130 ret = typeMap_.insert(pair<int, AtomType*>(atid1, atype1));
131 if (ret.second ==
false) {
133 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
134 "InteractionManager already had a previous entry with ident %d\n",
136 painCave.severity = OPENMD_INFO;
137 painCave.isFatal = 0;
141 if (atype1->isLennardJones()) { sHash_[atid1] |= LJ_INTERACTION; }
142 if (atype1->isElectrostatic()) {
145 if (atype1->isSticky()) { sHash_[atid1] |= STICKY_INTERACTION; }
146 if (atype1->isStickyPower()) { sHash_[atid1] |= STICKY_INTERACTION; }
147 if (atype1->isEAM()) { sHash_[atid1] |= EAM_INTERACTION; }
148 if (atype1->isSC()) { sHash_[atid1] |= SC_INTERACTION; }
149 if (atype1->isGayBerne()) { sHash_[atid1] |= GB_INTERACTION; }
153 map<int, AtomType*>::iterator it1, it2;
154 for (it1 = typeMap_.begin(); it1 != typeMap_.end(); ++it1) {
155 atype1 = (*it1).second;
156 atid1 = atype1->getIdent();
158 for (it2 = typeMap_.begin(); it2 != typeMap_.end(); ++it2) {
159 atype2 = (*it2).second;
160 atid2 = atype2->getIdent();
162 iHash_[atid1][atid2] = 0;
164 if (atype1->isLennardJones() && atype2->isLennardJones()) {
165 interactions_[atid1][atid2].insert(lj_);
166 iHash_[atid1][atid2] |= LJ_INTERACTION;
168 if (atype1->isElectrostatic() && atype2->isElectrostatic()) {
169 interactions_[atid1][atid2].insert(electrostatic_);
174 if (info_->getSimParams()->getOutputElectricField()) {
175 if (atype1->isElectrostatic() || atype2->isElectrostatic()) {
176 interactions_[atid1][atid2].insert(electrostatic_);
181 if (atype1->isSticky() && atype2->isSticky()) {
182 interactions_[atid1][atid2].insert(sticky_);
183 iHash_[atid1][atid2] |= STICKY_INTERACTION;
185 if (atype1->isStickyPower() && atype2->isStickyPower()) {
186 interactions_[atid1][atid2].insert(sticky_);
187 iHash_[atid1][atid2] |= STICKY_INTERACTION;
189 if (atype1->isEAM() && atype2->isEAM()) {
190 interactions_[atid1][atid2].insert(eam_);
191 iHash_[atid1][atid2] |= EAM_INTERACTION;
193 if (atype1->isSC() && atype2->isSC()) {
194 interactions_[atid1][atid2].insert(sc_);
195 iHash_[atid1][atid2] |= SC_INTERACTION;
197 if (atype1->isGayBerne() && atype2->isGayBerne()) {
198 interactions_[atid1][atid2].insert(gb_);
199 iHash_[atid1][atid2] |= GB_INTERACTION;
201 if ((atype1->isGayBerne() && atype2->isLennardJones()) ||
202 (atype1->isLennardJones() && atype2->isGayBerne())) {
203 interactions_[atid1][atid2].insert(gb_);
204 iHash_[atid1][atid2] |= GB_INTERACTION;
210 forceField_->getNonBondedInteractionType(atype1->getName(),
213 if (nbiType != NULL) {
214 bool vdwExplicit =
false;
215 bool metExplicit =
false;
218 if (nbiType->isLennardJones()) {
221 for (it = interactions_[atid1][atid2].begin();
222 it != interactions_[atid1][atid2].end();) {
225 iHash_[atid1][atid2] ^= (*it)->getHash();
226 interactions_[atid1][atid2].erase(it++);
231 interactions_[atid1][atid2].insert(lj_);
232 iHash_[atid1][atid2] |= LJ_INTERACTION;
235 lj_->addExplicitInteraction(atype1, atype2, ljit->getSigma(),
240 if (nbiType->isMorse()) {
242 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
243 "InteractionManager::initialize found more than one "
245 "\tvan der Waals interaction for atom types %s - %s\n",
246 atype1->getName().c_str(), atype2->getName().c_str());
247 painCave.severity = OPENMD_ERROR;
248 painCave.isFatal = 1;
253 for (it = interactions_[atid1][atid2].begin();
254 it != interactions_[atid1][atid2].end();) {
257 iHash_[atid1][atid2] ^= (*it)->getHash();
258 interactions_[atid1][atid2].erase(it++);
263 interactions_[atid1][atid2].insert(morse_);
264 iHash_[atid1][atid2] |= MORSE_INTERACTION;
267 morse_->addExplicitInteraction(atype1, atype2, mit->getD(),
268 mit->getR(), mit->getBeta(),
269 mit->getInteractionType());
273 if (nbiType->isRepulsivePower()) {
275 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
276 "InteractionManager::initialize found more than one "
278 "\tvan der Waals interaction for atom types %s - %s\n",
279 atype1->getName().c_str(), atype2->getName().c_str());
280 painCave.severity = OPENMD_ERROR;
281 painCave.isFatal = 1;
286 for (it = interactions_[atid1][atid2].begin();
287 it != interactions_[atid1][atid2].end();) {
290 iHash_[atid1][atid2] ^= (*it)->getHash();
291 interactions_[atid1][atid2].erase(it++);
296 interactions_[atid1][atid2].insert(repulsivePower_);
297 iHash_[atid1][atid2] |= REPULSIVEPOWER_INTERACTION;
301 repulsivePower_->addExplicitInteraction(
302 atype1, atype2, rpit->getSigma(), rpit->getEpsilon(),
308 if (nbiType->isMie()) {
310 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
311 "InteractionManager::initialize found more than one "
313 "\tvan der Waals interaction for atom types %s - %s\n",
314 atype1->getName().c_str(), atype2->getName().c_str());
315 painCave.severity = OPENMD_ERROR;
316 painCave.isFatal = 1;
321 for (it = interactions_[atid1][atid2].begin();
322 it != interactions_[atid1][atid2].end();) {
325 iHash_[atid1][atid2] ^= (*it)->getHash();
326 interactions_[atid1][atid2].erase(it++);
331 interactions_[atid1][atid2].insert(mie_);
332 iHash_[atid1][atid2] |= MIE_INTERACTION;
336 mie_->addExplicitInteraction(atype1, atype2, mit->getSigma(),
337 mit->getEpsilon(), mit->getNrep(),
343 if (nbiType->isEAMTable() || nbiType->isEAMZhou()) {
346 for (it = interactions_[atid1][atid2].begin();
347 it != interactions_[atid1][atid2].end();) {
350 iHash_[atid1][atid2] ^= (*it)->getHash();
351 interactions_[atid1][atid2].erase(it++);
356 interactions_[atid1][atid2].insert(eam_);
357 iHash_[atid1][atid2] |= EAM_INTERACTION;
361 if (nbiType->isSC()) {
363 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
364 "InteractionManager::initialize found more than one "
366 "\tmetallic interaction for atom types %s - %s\n",
367 atype1->getName().c_str(), atype2->getName().c_str());
368 painCave.severity = OPENMD_ERROR;
369 painCave.isFatal = 1;
374 for (it = interactions_[atid1][atid2].begin();
375 it != interactions_[atid1][atid2].end();) {
378 iHash_[atid1][atid2] ^= (*it)->getHash();
379 interactions_[atid1][atid2].erase(it++);
384 interactions_[atid1][atid2].insert(sc_);
385 iHash_[atid1][atid2] |= SC_INTERACTION;
389 if (nbiType->isMAW()) {
391 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
392 "InteractionManager::initialize found more than one "
394 "\tvan der Waals interaction for atom types %s - %s\n",
395 atype1->getName().c_str(), atype2->getName().c_str());
396 painCave.severity = OPENMD_ERROR;
397 painCave.isFatal = 1;
402 for (it = interactions_[atid1][atid2].begin();
403 it != interactions_[atid1][atid2].end();) {
406 iHash_[atid1][atid2] ^= (*it)->getHash();
407 interactions_[atid1][atid2].erase(it++);
412 interactions_[atid1][atid2].insert(maw_);
413 iHash_[atid1][atid2] |= MAW_INTERACTION;
416 maw_->addExplicitInteraction(atype1, atype2, mit->getD(),
417 mit->getBeta(), mit->getR(),
418 mit->getCA1(), mit->getCB1());
422 if (nbiType->isInversePowerSeries()) {
424 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
425 "InteractionManager::initialize found more than one "
427 "\tvan der Waals interaction for atom types %s - %s\n",
428 atype1->getName().c_str(), atype2->getName().c_str());
429 painCave.severity = OPENMD_ERROR;
430 painCave.isFatal = 1;
435 for (it = interactions_[atid1][atid2].begin();
436 it != interactions_[atid1][atid2].end();) {
439 iHash_[atid1][atid2] ^= (*it)->getHash();
440 interactions_[atid1][atid2].erase(it++);
445 interactions_[atid1][atid2].insert(inversePowerSeries_);
446 iHash_[atid1][atid2] |= INVERSEPOWERSERIES_INTERACTION;
450 inversePowerSeries_->addExplicitInteraction(
451 atype1, atype2, ipsit->getPowers(), ipsit->getCoefficients());
462 AtomTypeSet::iterator bt;
464 for (at = simTypes.begin(); at != simTypes.end(); ++at) {
466 atid1 = atype1->getIdent();
467 for (bt = at; bt != simTypes.end(); ++bt) {
469 atid2 = atype2->getIdent();
471 if (interactions_[atid1][atid2].size() == 0) {
472 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
473 "InteractionManager could not find a matching non-bonded\n"
474 "\tinteraction for atom types %s - %s\n"
475 "\tProceeding without this interaction.\n",
476 atype1->getName().c_str(), atype2->getName().c_str());
477 painCave.severity = OPENMD_INFO;
478 painCave.isFatal = 0;
487 void InteractionManager::setCutoffRadius(RealType rcut) {
488 electrostatic_->setCutoffRadius(rcut);
489 eam_->setCutoffRadius(rcut);
493 if (!initialized_) initialize();
500 if ((iHash & EAM_INTERACTION) != 0) eam_->calcDensity(idat);
501 if ((iHash & SC_INTERACTION) != 0) sc_->calcDensity(idat);
515 void InteractionManager::doPreForce(
SelfData& sdat) {
516 if (!initialized_) initialize();
518 int& sHash = sHash_[sdat.
atid];
520 if ((sHash & EAM_INTERACTION) != 0) eam_->calcFunctional(sdat);
521 if ((sHash & SC_INTERACTION) != 0) sc_->calcFunctional(sdat);
536 if (!initialized_) initialize();
541 electrostatic_->calcForce(idat);
548 if ((iHash & LJ_INTERACTION) != 0) lj_->calcForce(idat);
549 if ((iHash & GB_INTERACTION) != 0) gb_->calcForce(idat);
550 if ((iHash & STICKY_INTERACTION) != 0) sticky_->calcForce(idat);
551 if ((iHash & MORSE_INTERACTION) != 0) morse_->calcForce(idat);
552 if ((iHash & REPULSIVEPOWER_INTERACTION) != 0)
553 repulsivePower_->calcForce(idat);
554 if ((iHash & MIE_INTERACTION) != 0) mie_->calcForce(idat);
555 if ((iHash & EAM_INTERACTION) != 0) eam_->calcForce(idat);
556 if ((iHash & SC_INTERACTION) != 0) sc_->calcForce(idat);
557 if ((iHash & MAW_INTERACTION) != 0) maw_->calcForce(idat);
558 if ((iHash & INVERSEPOWERSERIES_INTERACTION) != 0)
559 inversePowerSeries_->calcForce(idat);
574 void InteractionManager::doSelfCorrection(
SelfData& sdat) {
575 if (!initialized_) initialize();
577 int& sHash = sHash_[sdat.
atid];
580 electrostatic_->calcSelfCorrection(sdat);
595 void InteractionManager::doSurfaceTerm(
bool slabGeometry,
int axis,
597 if (!initialized_) initialize();
598 electrostatic_->calcSurfaceTerm(slabGeometry, axis, pot);
601 void InteractionManager::doReciprocalSpaceSum(RealType& pot) {
602 if (!initialized_) initialize();
603 electrostatic_->ReciprocalSpaceSum(pot);
606 RealType InteractionManager::getSuggestedCutoffRadius(
int* atid) {
607 if (!initialized_) initialize();
611 set<NonBondedInteractionPtr>::iterator it;
612 RealType cutoff = 0.0;
614 for (it = interactions_[*atid][*atid].begin();
615 it != interactions_[*atid][*atid].end(); ++it) {
617 max(cutoff, (*it)->getSuggestedCutoffRadius(make_pair(atype, atype)));
622 RealType InteractionManager::getSuggestedCutoffRadius(
AtomType* atype) {
623 if (!initialized_) initialize();
625 int atid = atype->getIdent();
627 set<NonBondedInteractionPtr>::iterator it;
628 RealType cutoff = 0.0;
630 for (it = interactions_[atid][atid].begin();
631 it != interactions_[atid][atid].end(); ++it) {
633 max(cutoff, (*it)->getSuggestedCutoffRadius(make_pair(atype, atype)));
AtomType is what OpenMD looks to for unchanging data about an atom.
InversePowerSeriesInteractionType is a sum of powers in the inverse of r:
LennardJonesInteractionType is one of the basic interaction types.
MAWInteractionType (Metal-Angular-Water) is one of the basic Metal-to-NonMetal interaction types.
MieInteractionType is one of the basic interaction types.
MorseInteractionType is one of the basic non-bonded interactions.
NonBondedInteractionType class is responsible for keeping track of static (unchanging) parameters for...
RepulsivePowerInteractionType is one of the basic interaction types.
ForceField * getForceField()
Returns the force field.
AtomTypeSet getSimulatedAtomTypes()
Returns the set of atom types present in this simulation.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
static const int ELECTROSTATIC_INTERACTION
Boolean flags for the iHash_ and sHash_ data structures.
InteractionFamily
The InteractionFamily enum.
@ VANDERWAALS_FAMILY
Long-range dispersion and short-range pauli repulsion.
@ METALLIC_EMBEDDING_FAMILY
Transition metal interactions involving electron density.
The InteractionData struct.
int atid1
atomType ident for atom 1
bool excluded
is this excluded from direct pairwise interactions? (some indirect interactions may still apply)
int atid2
atomType ident for atom 2
int atid
atomType ident for the atom