48#include "nonbonded/InteractionManager.hpp"
50#include "types/InversePowerSeriesInteractionType.hpp"
51#include "types/LennardJonesInteractionType.hpp"
52#include "types/MAWInteractionType.hpp"
53#include "types/MieInteractionType.hpp"
54#include "types/MorseInteractionType.hpp"
55#include "types/RepulsivePowerInteractionType.hpp"
59 InteractionManager::InteractionManager() {
62 lj_ = std::make_shared<LJ>();
63 gb_ = std::make_shared<GB>();
64 sticky_ = std::make_shared<Sticky>();
65 morse_ = std::make_shared<Morse>();
66 repulsivePower_ = std::make_shared<RepulsivePower>();
67 mie_ = std::make_shared<Mie>();
68 eam_ = std::make_shared<EAM>();
69 sc_ = std::make_shared<SC>();
70 electrostatic_ = std::make_shared<Electrostatic>();
71 maw_ = std::make_shared<MAW>();
72 inversePowerSeries_ = std::make_shared<InversePowerSeries>();
75 void InteractionManager::initialize() {
76 if (initialized_)
return;
78 ForceField* forceField_ = info_->getForceField();
80 lj_->setForceField(forceField_);
81 gb_->setForceField(forceField_);
82 sticky_->setForceField(forceField_);
83 eam_->setForceField(forceField_);
84 eam_->setElectrostatic(electrostatic_.get());
85 sc_->setForceField(forceField_);
86 morse_->setForceField(forceField_);
87 electrostatic_->setSimInfo(info_);
88 electrostatic_->setForceField(forceField_);
89 maw_->setForceField(forceField_);
90 repulsivePower_->setForceField(forceField_);
91 mie_->setForceField(forceField_);
92 inversePowerSeries_->setForceField(forceField_);
94 ForceField::AtomTypeContainer* atomTypes = forceField_->getAtomTypes();
95 int nTypes = atomTypes->size();
96 sHash_.resize(nTypes);
97 iHash_.resize(nTypes);
98 interactions_.resize(nTypes);
99 ForceField::AtomTypeContainer::MapTypeIterator i1, i2;
107 AtomTypeSet atypes = info_->getSimulatedAtomTypes();
109 lj_->setSimulatedAtomTypes(atypes);
110 gb_->setSimulatedAtomTypes(atypes);
111 sticky_->setSimulatedAtomTypes(atypes);
112 eam_->setSimulatedAtomTypes(atypes);
113 sc_->setSimulatedAtomTypes(atypes);
114 morse_->setSimulatedAtomTypes(atypes);
115 electrostatic_->setSimInfo(info_);
116 electrostatic_->setSimulatedAtomTypes(atypes);
117 maw_->setSimulatedAtomTypes(atypes);
118 repulsivePower_->setSimulatedAtomTypes(atypes);
119 mie_->setSimulatedAtomTypes(atypes);
120 inversePowerSeries_->setSimulatedAtomTypes(atypes);
122 AtomTypeSet::iterator at;
123 set<NonBondedInteractionPtr>::iterator it;
125 for (at = atypes.begin(); at != atypes.end(); ++at) {
127 atid1 = atype1->getIdent();
128 iHash_[atid1].resize(nTypes);
129 interactions_[atid1].resize(nTypes);
132 pair<map<int, AtomType*>::iterator,
bool> ret;
133 ret = typeMap_.insert(pair<int, AtomType*>(atid1, atype1));
134 if (ret.second ==
false) {
136 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
137 "InteractionManager already had a previous entry with ident %d\n",
139 painCave.severity = OPENMD_INFO;
140 painCave.isFatal = 0;
144 if (atype1->isLennardJones()) { sHash_[atid1] |= LJ_INTERACTION; }
145 if (atype1->isElectrostatic()) {
148 if (atype1->isSticky()) { sHash_[atid1] |= STICKY_INTERACTION; }
149 if (atype1->isStickyPower()) { sHash_[atid1] |= STICKY_INTERACTION; }
150 if (atype1->isEAM()) { sHash_[atid1] |= EAM_INTERACTION; }
151 if (atype1->isSC()) { sHash_[atid1] |= SC_INTERACTION; }
152 if (atype1->isGayBerne()) { sHash_[atid1] |= GB_INTERACTION; }
156 map<int, AtomType*>::iterator it1, it2;
157 for (it1 = typeMap_.begin(); it1 != typeMap_.end(); ++it1) {
158 atype1 = (*it1).second;
159 atid1 = atype1->getIdent();
161 for (it2 = typeMap_.begin(); it2 != typeMap_.end(); ++it2) {
162 atype2 = (*it2).second;
163 atid2 = atype2->getIdent();
165 iHash_[atid1][atid2] = 0;
167 if (atype1->isLennardJones() && atype2->isLennardJones()) {
168 interactions_[atid1][atid2].insert(lj_);
169 iHash_[atid1][atid2] |= LJ_INTERACTION;
171 if (atype1->isElectrostatic() && atype2->isElectrostatic()) {
172 interactions_[atid1][atid2].insert(electrostatic_);
177 if (info_->getSimParams()->getOutputElectricField()) {
178 if (atype1->isElectrostatic() || atype2->isElectrostatic()) {
179 interactions_[atid1][atid2].insert(electrostatic_);
184 if (atype1->isSticky() && atype2->isSticky()) {
185 interactions_[atid1][atid2].insert(sticky_);
186 iHash_[atid1][atid2] |= STICKY_INTERACTION;
188 if (atype1->isStickyPower() && atype2->isStickyPower()) {
189 interactions_[atid1][atid2].insert(sticky_);
190 iHash_[atid1][atid2] |= STICKY_INTERACTION;
192 if (atype1->isEAM() && atype2->isEAM()) {
193 interactions_[atid1][atid2].insert(eam_);
194 iHash_[atid1][atid2] |= EAM_INTERACTION;
196 if (atype1->isSC() && atype2->isSC()) {
197 interactions_[atid1][atid2].insert(sc_);
198 iHash_[atid1][atid2] |= SC_INTERACTION;
200 if (atype1->isGayBerne() && atype2->isGayBerne()) {
201 interactions_[atid1][atid2].insert(gb_);
202 iHash_[atid1][atid2] |= GB_INTERACTION;
204 if ((atype1->isGayBerne() && atype2->isLennardJones()) ||
205 (atype1->isLennardJones() && atype2->isGayBerne())) {
206 interactions_[atid1][atid2].insert(gb_);
207 iHash_[atid1][atid2] |= GB_INTERACTION;
212 NonBondedInteractionType* nbiType =
213 forceField_->getNonBondedInteractionType(atype1->getName(),
216 if (nbiType != NULL) {
217 bool vdwExplicit =
false;
218 bool metExplicit =
false;
221 if (nbiType->isLennardJones()) {
224 for (it = interactions_[atid1][atid2].begin();
225 it != interactions_[atid1][atid2].end();) {
228 iHash_[atid1][atid2] ^= (*it)->getHash();
229 interactions_[atid1][atid2].erase(it++);
234 interactions_[atid1][atid2].insert(lj_);
235 iHash_[atid1][atid2] |= LJ_INTERACTION;
236 LennardJonesInteractionType* ljit =
237 dynamic_cast<LennardJonesInteractionType*
>(nbiType);
238 lj_->addExplicitInteraction(atype1, atype2, ljit->getSigma(),
243 if (nbiType->isMorse()) {
245 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
246 "InteractionManager::initialize found more than one "
248 "\tvan der Waals interaction for atom types %s - %s\n",
249 atype1->getName().c_str(), atype2->getName().c_str());
250 painCave.severity = OPENMD_ERROR;
251 painCave.isFatal = 1;
256 for (it = interactions_[atid1][atid2].begin();
257 it != interactions_[atid1][atid2].end();) {
260 iHash_[atid1][atid2] ^= (*it)->getHash();
261 interactions_[atid1][atid2].erase(it++);
266 interactions_[atid1][atid2].insert(morse_);
267 iHash_[atid1][atid2] |= MORSE_INTERACTION;
268 MorseInteractionType* mit =
269 dynamic_cast<MorseInteractionType*
>(nbiType);
270 morse_->addExplicitInteraction(atype1, atype2, mit->getD(),
271 mit->getR(), mit->getBeta(),
272 mit->getInteractionType());
276 if (nbiType->isRepulsivePower()) {
278 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
279 "InteractionManager::initialize found more than one "
281 "\tvan der Waals interaction for atom types %s - %s\n",
282 atype1->getName().c_str(), atype2->getName().c_str());
283 painCave.severity = OPENMD_ERROR;
284 painCave.isFatal = 1;
289 for (it = interactions_[atid1][atid2].begin();
290 it != interactions_[atid1][atid2].end();) {
293 iHash_[atid1][atid2] ^= (*it)->getHash();
294 interactions_[atid1][atid2].erase(it++);
299 interactions_[atid1][atid2].insert(repulsivePower_);
300 iHash_[atid1][atid2] |= REPULSIVEPOWER_INTERACTION;
301 RepulsivePowerInteractionType* rpit =
302 dynamic_cast<RepulsivePowerInteractionType*
>(nbiType);
304 repulsivePower_->addExplicitInteraction(
305 atype1, atype2, rpit->getSigma(), rpit->getEpsilon(),
311 if (nbiType->isMie()) {
313 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
314 "InteractionManager::initialize found more than one "
316 "\tvan der Waals interaction for atom types %s - %s\n",
317 atype1->getName().c_str(), atype2->getName().c_str());
318 painCave.severity = OPENMD_ERROR;
319 painCave.isFatal = 1;
324 for (it = interactions_[atid1][atid2].begin();
325 it != interactions_[atid1][atid2].end();) {
328 iHash_[atid1][atid2] ^= (*it)->getHash();
329 interactions_[atid1][atid2].erase(it++);
334 interactions_[atid1][atid2].insert(mie_);
335 iHash_[atid1][atid2] |= MIE_INTERACTION;
336 MieInteractionType* mit =
337 dynamic_cast<MieInteractionType*
>(nbiType);
339 mie_->addExplicitInteraction(atype1, atype2, mit->getSigma(),
340 mit->getEpsilon(), mit->getNrep(),
346 if (nbiType->isEAMTable() || nbiType->isEAMZhou()) {
349 for (it = interactions_[atid1][atid2].begin();
350 it != interactions_[atid1][atid2].end();) {
353 iHash_[atid1][atid2] ^= (*it)->getHash();
354 interactions_[atid1][atid2].erase(it++);
359 interactions_[atid1][atid2].insert(eam_);
360 iHash_[atid1][atid2] |= EAM_INTERACTION;
364 if (nbiType->isSC()) {
366 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
367 "InteractionManager::initialize found more than one "
369 "\tmetallic interaction for atom types %s - %s\n",
370 atype1->getName().c_str(), atype2->getName().c_str());
371 painCave.severity = OPENMD_ERROR;
372 painCave.isFatal = 1;
377 for (it = interactions_[atid1][atid2].begin();
378 it != interactions_[atid1][atid2].end();) {
381 iHash_[atid1][atid2] ^= (*it)->getHash();
382 interactions_[atid1][atid2].erase(it++);
387 interactions_[atid1][atid2].insert(sc_);
388 iHash_[atid1][atid2] |= SC_INTERACTION;
392 if (nbiType->isMAW()) {
394 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
395 "InteractionManager::initialize found more than one "
397 "\tvan der Waals interaction for atom types %s - %s\n",
398 atype1->getName().c_str(), atype2->getName().c_str());
399 painCave.severity = OPENMD_ERROR;
400 painCave.isFatal = 1;
405 for (it = interactions_[atid1][atid2].begin();
406 it != interactions_[atid1][atid2].end();) {
409 iHash_[atid1][atid2] ^= (*it)->getHash();
410 interactions_[atid1][atid2].erase(it++);
415 interactions_[atid1][atid2].insert(maw_);
416 iHash_[atid1][atid2] |= MAW_INTERACTION;
417 MAWInteractionType* mit =
418 dynamic_cast<MAWInteractionType*
>(nbiType);
419 maw_->addExplicitInteraction(atype1, atype2, mit->getD(),
420 mit->getBeta(), mit->getR(),
421 mit->getCA1(), mit->getCB1());
425 if (nbiType->isInversePowerSeries()) {
427 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
428 "InteractionManager::initialize found more than one "
430 "\tvan der Waals interaction for atom types %s - %s\n",
431 atype1->getName().c_str(), atype2->getName().c_str());
432 painCave.severity = OPENMD_ERROR;
433 painCave.isFatal = 1;
438 for (it = interactions_[atid1][atid2].begin();
439 it != interactions_[atid1][atid2].end();) {
442 iHash_[atid1][atid2] ^= (*it)->getHash();
443 interactions_[atid1][atid2].erase(it++);
448 interactions_[atid1][atid2].insert(inversePowerSeries_);
449 iHash_[atid1][atid2] |= INVERSEPOWERSERIES_INTERACTION;
450 InversePowerSeriesInteractionType* ipsit =
451 dynamic_cast<InversePowerSeriesInteractionType*
>(nbiType);
453 inversePowerSeries_->addExplicitInteraction(
454 atype1, atype2, ipsit->getPowers(), ipsit->getCoefficients());
464 AtomTypeSet simTypes = info_->getSimulatedAtomTypes();
465 AtomTypeSet::iterator bt;
467 for (at = simTypes.begin(); at != simTypes.end(); ++at) {
469 atid1 = atype1->getIdent();
470 for (bt = at; bt != simTypes.end(); ++bt) {
472 atid2 = atype2->getIdent();
474 if (interactions_[atid1][atid2].size() == 0) {
475 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
476 "InteractionManager could not find a matching non-bonded\n"
477 "\tinteraction for atom types %s - %s\n"
478 "\tProceeding without this interaction.\n",
479 atype1->getName().c_str(), atype2->getName().c_str());
480 painCave.severity = OPENMD_INFO;
481 painCave.isFatal = 0;
490 void InteractionManager::setCutoffRadius(RealType rcut) {
491 electrostatic_->setCutoffRadius(rcut);
492 eam_->setCutoffRadius(rcut);
496 if (!initialized_) initialize();
499 if (idat.excluded)
return;
501 int& iHash = iHash_[idat.atid1][idat.atid2];
503 if ((iHash & EAM_INTERACTION) != 0) eam_->calcDensity(idat);
504 if ((iHash & SC_INTERACTION) != 0) sc_->calcDensity(idat);
518 void InteractionManager::doPreForce(
SelfData& sdat) {
519 if (!initialized_) initialize();
521 int& sHash = sHash_[sdat.atid];
523 if ((sHash & EAM_INTERACTION) != 0) eam_->calcFunctional(sdat);
524 if ((sHash & SC_INTERACTION) != 0) sc_->calcFunctional(sdat);
539 if (!initialized_) initialize();
541 int& iHash = iHash_[idat.atid1][idat.atid2];
544 electrostatic_->calcForce(idat);
549 if (idat.excluded)
return;
551 if ((iHash & LJ_INTERACTION) != 0) lj_->calcForce(idat);
552 if ((iHash & GB_INTERACTION) != 0) gb_->calcForce(idat);
553 if ((iHash & STICKY_INTERACTION) != 0) sticky_->calcForce(idat);
554 if ((iHash & MORSE_INTERACTION) != 0) morse_->calcForce(idat);
555 if ((iHash & REPULSIVEPOWER_INTERACTION) != 0)
556 repulsivePower_->calcForce(idat);
557 if ((iHash & MIE_INTERACTION) != 0) mie_->calcForce(idat);
558 if ((iHash & EAM_INTERACTION) != 0) eam_->calcForce(idat);
559 if ((iHash & SC_INTERACTION) != 0) sc_->calcForce(idat);
560 if ((iHash & MAW_INTERACTION) != 0) maw_->calcForce(idat);
561 if ((iHash & INVERSEPOWERSERIES_INTERACTION) != 0)
562 inversePowerSeries_->calcForce(idat);
577 void InteractionManager::doSelfCorrection(
SelfData& sdat) {
578 if (!initialized_) initialize();
580 int& sHash = sHash_[sdat.atid];
583 electrostatic_->calcSelfCorrection(sdat);
598 void InteractionManager::doSurfaceTerm(
bool slabGeometry,
int axis,
600 if (!initialized_) initialize();
601 electrostatic_->calcSurfaceTerm(slabGeometry, axis, pot);
604 void InteractionManager::doReciprocalSpaceSum(RealType& pot) {
605 if (!initialized_) initialize();
606 electrostatic_->ReciprocalSpaceSum(pot);
609 RealType InteractionManager::getSuggestedCutoffRadius(
int* atid) {
610 if (!initialized_) initialize();
612 AtomType* atype = typeMap_[*atid];
614 set<NonBondedInteractionPtr>::iterator it;
615 RealType cutoff = 0.0;
617 for (it = interactions_[*atid][*atid].begin();
618 it != interactions_[*atid][*atid].end(); ++it) {
620 max(cutoff, (*it)->getSuggestedCutoffRadius(make_pair(atype, atype)));
625 RealType InteractionManager::getSuggestedCutoffRadius(
AtomType* atype) {
626 if (!initialized_) initialize();
628 int atid = atype->getIdent();
630 set<NonBondedInteractionPtr>::iterator it;
631 RealType cutoff = 0.0;
633 for (it = interactions_[atid][atid].begin();
634 it != interactions_[atid][atid].end(); ++it) {
636 max(cutoff, (*it)->getSuggestedCutoffRadius(make_pair(atype, atype)));
AtomType is what OpenMD looks to for unchanging data about an atom.
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.