48#include "nonbonded/InversePowerSeries.hpp"
54#include "types/InversePowerSeriesInteractionType.hpp"
55#include "utils/simError.h"
61 InversePowerSeries::InversePowerSeries() :
62 initialized_(false), forceField_(NULL), name_(
"InversePowerSeries") {}
64 void InversePowerSeries::initialize() {
65 InversePowerSeriesTypes.clear();
66 InversePowerSeriesTids.clear();
68 InversePowerSeriesTids.resize(forceField_->getNAtomType(), -1);
70 ForceField::NonBondedInteractionTypeContainer* nbiTypes =
71 forceField_->getNonBondedInteractionTypes();
72 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
73 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
74 NonBondedInteractionType* nbt;
77 for (nbt = nbiTypes->beginType(j); nbt != NULL;
78 nbt = nbiTypes->nextType(j)) {
79 if (nbt->isInversePowerSeries()) {
80 keys = nbiTypes->getKeys(j);
81 AtomType* at1 = forceField_->getAtomType(keys[0]);
83 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
84 "InversePowerSeries::initialize could not find AtomType %s\n"
85 "\tto for for %s - %s interaction.\n",
86 keys[0].c_str(), keys[0].c_str(), keys[1].c_str());
87 painCave.severity = OPENMD_ERROR;
92 AtomType* at2 = forceField_->getAtomType(keys[1]);
94 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
95 "InversePowerSeries::initialize could not find AtomType %s\n"
96 "\tfor %s - %s nonbonded interaction.\n",
97 keys[1].c_str(), keys[0].c_str(), keys[1].c_str());
98 painCave.severity = OPENMD_ERROR;
103 int atid1 = at1->getIdent();
104 if (InversePowerSeriesTids[atid1] == -1) {
105 ipstid1 = InversePowerSeriesTypes.size();
106 InversePowerSeriesTypes.insert(atid1);
107 InversePowerSeriesTids[atid1] = ipstid1;
109 int atid2 = at2->getIdent();
110 if (InversePowerSeriesTids[atid2] == -1) {
111 ipstid2 = InversePowerSeriesTypes.size();
112 InversePowerSeriesTypes.insert(atid2);
113 InversePowerSeriesTids[atid2] = ipstid2;
116 InversePowerSeriesInteractionType* ipsit =
117 dynamic_cast<InversePowerSeriesInteractionType*
>(nbt);
119 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
120 "InversePowerSeries::initialize could not convert "
121 "NonBondedInteractionType\n"
122 "\tto InversePowerSeriesInteractionType for %s - %s "
124 at1->getName().c_str(), at2->getName().c_str());
125 painCave.severity = OPENMD_ERROR;
126 painCave.isFatal = 1;
130 std::vector<int> powers = ipsit->getPowers();
131 std::vector<RealType> coefficients = ipsit->getCoefficients();
133 addExplicitInteraction(at1, at2, powers, coefficients);
139 void InversePowerSeries::addExplicitInteraction(
140 AtomType* atype1, AtomType* atype2, std::vector<int> powers,
141 std::vector<RealType> coefficients) {
142 InversePowerSeriesInteractionData mixer;
143 mixer.powers = powers;
144 mixer.coefficients = coefficients;
146 int ipstid1 = InversePowerSeriesTids[atype1->getIdent()];
147 int ipstid2 = InversePowerSeriesTids[atype2->getIdent()];
148 int nInversePowerSeries = InversePowerSeriesTypes.size();
150 MixingMap.resize(nInversePowerSeries);
151 MixingMap[ipstid1].resize(nInversePowerSeries);
153 MixingMap[ipstid1][ipstid2] = mixer;
154 if (ipstid2 != ipstid1) {
155 MixingMap[ipstid2].resize(nInversePowerSeries);
156 MixingMap[ipstid2][ipstid1] = mixer;
160 void InversePowerSeries::calcForce(InteractionData& idat) {
161 if (!initialized_) initialize();
163 InversePowerSeriesInteractionData& mixer =
164 MixingMap[InversePowerSeriesTids[idat.atid1]]
165 [InversePowerSeriesTids[idat.atid2]];
166 std::vector<int> powers = mixer.powers;
167 std::vector<RealType> coefficients = mixer.coefficients;
169 RealType myPot = 0.0;
170 RealType myPotC = 0.0;
171 RealType myDeriv = 0.0;
172 RealType myDerivC = 0.0;
174 RealType ri = 1.0 / idat.rij;
175 RealType ric = 1.0 / idat.rcut;
179 for (
unsigned int i = 0; i < powers.size(); i++) {
180 fn = coefficients[i] * pow(ri, powers[i]);
181 fnc = coefficients[i] * pow(ric, powers[i]);
184 myDeriv -= powers[i] * fn * ri;
185 myDerivC -= powers[i] * fnc * ric;
188 if (idat.shiftedPot) {
190 }
else if (idat.shiftedForce) {
191 myPotC = myPotC + myDerivC * (idat.rij - idat.rcut);
197 RealType pot_temp = idat.vdwMult * (myPot - myPotC);
198 idat.vpair += pot_temp;
200 RealType dudr = idat.sw * idat.vdwMult * (myDeriv - myDerivC);
205 idat.f1 += idat.d * dudr / idat.rij;
210 RealType InversePowerSeries::getSuggestedCutoffRadius(
211 pair<AtomType*, AtomType*> atypes) {
212 if (!initialized_) initialize();
214 int atid1 = atypes.first->getIdent();
215 int atid2 = atypes.second->getIdent();
216 int ipstid1 = InversePowerSeriesTids[atid1];
217 int ipstid2 = InversePowerSeriesTids[atid2];
219 if (ipstid1 == -1 || ipstid2 == -1)
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
@ VANDERWAALS_FAMILY
Long-range dispersion and short-range pauli repulsion.