48#include "nonbonded/Mie.hpp"
54#include "types/MieInteractionType.hpp"
55#include "utils/simError.h"
61 Mie::Mie() : initialized_(false), forceField_(NULL), name_(
"Mie") {}
63 void Mie::initialize() {
67 MieTids.resize(forceField_->getNAtomType(), -1);
69 ForceField::NonBondedInteractionTypeContainer* nbiTypes =
70 forceField_->getNonBondedInteractionTypes();
71 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
72 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
73 NonBondedInteractionType* nbt;
76 for (nbt = nbiTypes->beginType(j); nbt != NULL;
77 nbt = nbiTypes->nextType(j)) {
79 keys = nbiTypes->getKeys(j);
80 AtomType* at1 = forceField_->getAtomType(keys[0]);
82 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
83 "Mie::initialize could not find AtomType %s\n"
84 "\tto for for %s - %s interaction.\n",
85 keys[0].c_str(), keys[0].c_str(), keys[1].c_str());
86 painCave.severity = OPENMD_ERROR;
91 AtomType* at2 = forceField_->getAtomType(keys[1]);
93 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
94 "Mie::initialize could not find AtomType %s\n"
95 "\tfor %s - %s nonbonded interaction.\n",
96 keys[1].c_str(), keys[0].c_str(), keys[1].c_str());
97 painCave.severity = OPENMD_ERROR;
102 int atid1 = at1->getIdent();
103 if (MieTids[atid1] == -1) {
104 mietid1 = MieTypes.size();
105 MieTypes.insert(atid1);
106 MieTids[atid1] = mietid1;
108 int atid2 = at2->getIdent();
109 if (MieTids[atid2] == -1) {
110 mietid2 = MieTypes.size();
111 MieTypes.insert(atid2);
112 MieTids[atid2] = mietid2;
115 MieInteractionType* mit =
dynamic_cast<MieInteractionType*
>(nbt);
118 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
119 "Mie::initialize could not convert NonBondedInteractionType\n"
120 "\tto MieInteractionType for %s - %s interaction.\n",
121 at1->getName().c_str(), at2->getName().c_str());
122 painCave.severity = OPENMD_ERROR;
123 painCave.isFatal = 1;
127 RealType sigma = mit->getSigma();
128 RealType epsilon = mit->getEpsilon();
129 int nRep = mit->getNrep();
130 int mAtt = mit->getMatt();
132 addExplicitInteraction(at1, at2, sigma, epsilon, nRep, mAtt);
138 void Mie::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
139 RealType sigma, RealType epsilon,
int nRep,
141 MieInteractionData mixer;
143 mixer.epsilon = epsilon;
144 mixer.sigmai = 1.0 / mixer.sigma;
148 RealType n = RealType(nRep);
149 RealType m = RealType(mAtt);
151 mixer.nmScale = n * pow(n / m, m / (n - m)) / (n - m);
153 int nMie = MieTypes.size();
154 int atid1 = atype1->getIdent();
155 int atid2 = atype2->getIdent();
156 int mietid1, mietid2;
158 pair<set<int>::iterator,
bool> ret;
159 ret = MieTypes.insert(atid1);
160 if (ret.second ==
false) {
162 mietid1 = MieTids[atid1];
166 MieTids[atid1] = nMie;
170 ret = MieTypes.insert(atid2);
171 if (ret.second ==
false) {
173 mietid2 = MieTids[atid2];
177 MieTids[atid2] = nMie;
181 MixingMap.resize(nMie);
182 MixingMap[mietid1].resize(nMie);
184 MixingMap[mietid1][mietid2] = mixer;
185 if (mietid2 != mietid1) {
186 MixingMap[mietid2].resize(nMie);
187 MixingMap[mietid2][mietid1] = mixer;
191 void Mie::calcForce(InteractionData& idat) {
192 if (!initialized_) initialize();
194 MieInteractionData& mixer =
195 MixingMap[MieTids[idat.atid1]][MieTids[idat.atid2]];
196 RealType sigmai = mixer.sigmai;
197 RealType epsilon = mixer.epsilon;
198 int nRep = mixer.nRep;
199 int mAtt = mixer.mAtt;
200 RealType nmScale = mixer.nmScale;
204 RealType myPot = 0.0;
205 RealType myPotC = 0.0;
206 RealType myDeriv = 0.0;
207 RealType myDerivC = 0.0;
209 ros = idat.rij * sigmai;
211 getMieFunc(ros, nRep, mAtt, myPot, myDeriv);
213 if (idat.shiftedPot) {
214 rcos = idat.rcut * sigmai;
215 getMieFunc(rcos, nRep, mAtt, myPotC, myDerivC);
217 }
else if (idat.shiftedForce) {
218 rcos = idat.rcut * sigmai;
219 getMieFunc(rcos, nRep, mAtt, myPotC, myDerivC);
220 myPotC = myPotC + myDerivC * (idat.rij - idat.rcut) * sigmai;
226 RealType pot_temp = idat.vdwMult * nmScale * epsilon * (myPot - myPotC);
227 idat.vpair += pot_temp;
229 RealType dudr = idat.sw * idat.vdwMult * nmScale * epsilon *
230 (myDeriv - myDerivC) * sigmai;
235 idat.f1 += idat.d * dudr / idat.rij;
240 void Mie::getMieFunc(
const RealType& r,
int& n,
int& m, RealType& pot,
242 RealType ri = 1.0 / r;
243 RealType rin = pow(ri, n);
244 RealType rim = pow(ri, m);
245 RealType rin1 = rin * ri;
246 RealType rim1 = rim * ri;
249 deriv = -n * rin1 + m * rim1;
253 RealType Mie::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
254 if (!initialized_) initialize();
256 int atid1 = atypes.first->getIdent();
257 int atid2 = atypes.second->getIdent();
258 int mietid1 = MieTids[atid1];
259 int mietid2 = MieTids[atid2];
261 if (mietid1 == -1 || mietid2 == -1)
264 MieInteractionData mixer = MixingMap[mietid1][mietid2];
265 return 2.5 * mixer.sigma;
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.