45#include "nonbonded/Mie.hpp"
51#include "types/MieInteractionType.hpp"
52#include "utils/simError.h"
58 Mie::Mie() : initialized_(false), forceField_(NULL), name_(
"Mie") {}
60 void Mie::initialize() {
64 MieTids.resize(forceField_->getNAtomType(), -1);
66 ForceField::NonBondedInteractionTypeContainer* nbiTypes =
67 forceField_->getNonBondedInteractionTypes();
68 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
69 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
70 NonBondedInteractionType* nbt;
73 for (nbt = nbiTypes->beginType(j); nbt != NULL;
74 nbt = nbiTypes->nextType(j)) {
76 keys = nbiTypes->getKeys(j);
77 AtomType* at1 = forceField_->getAtomType(keys[0]);
79 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
80 "Mie::initialize could not find AtomType %s\n"
81 "\tto for for %s - %s interaction.\n",
82 keys[0].c_str(), keys[0].c_str(), keys[1].c_str());
83 painCave.severity = OPENMD_ERROR;
88 AtomType* at2 = forceField_->getAtomType(keys[1]);
90 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
91 "Mie::initialize could not find AtomType %s\n"
92 "\tfor %s - %s nonbonded interaction.\n",
93 keys[1].c_str(), keys[0].c_str(), keys[1].c_str());
94 painCave.severity = OPENMD_ERROR;
99 int atid1 = at1->getIdent();
100 if (MieTids[atid1] == -1) {
101 mietid1 = MieTypes.size();
102 MieTypes.insert(atid1);
103 MieTids[atid1] = mietid1;
105 int atid2 = at2->getIdent();
106 if (MieTids[atid2] == -1) {
107 mietid2 = MieTypes.size();
108 MieTypes.insert(atid2);
109 MieTids[atid2] = mietid2;
112 MieInteractionType* mit =
dynamic_cast<MieInteractionType*
>(nbt);
115 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
116 "Mie::initialize could not convert NonBondedInteractionType\n"
117 "\tto MieInteractionType for %s - %s interaction.\n",
118 at1->getName().c_str(), at2->getName().c_str());
119 painCave.severity = OPENMD_ERROR;
120 painCave.isFatal = 1;
124 RealType sigma = mit->getSigma();
125 RealType epsilon = mit->getEpsilon();
126 int nRep = mit->getNrep();
127 int mAtt = mit->getMatt();
129 addExplicitInteraction(at1, at2, sigma, epsilon, nRep, mAtt);
135 void Mie::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
136 RealType sigma, RealType epsilon,
int nRep,
138 MieInteractionData mixer;
140 mixer.epsilon = epsilon;
141 mixer.sigmai = 1.0 / mixer.sigma;
145 RealType n = RealType(nRep);
146 RealType m = RealType(mAtt);
148 mixer.nmScale = n * pow(n / m, m / (n - m)) / (n - m);
150 int nMie = MieTypes.size();
151 int atid1 = atype1->getIdent();
152 int atid2 = atype2->getIdent();
153 int mietid1, mietid2;
155 pair<set<int>::iterator,
bool> ret;
156 ret = MieTypes.insert(atid1);
157 if (ret.second ==
false) {
159 mietid1 = MieTids[atid1];
163 MieTids[atid1] = nMie;
167 ret = MieTypes.insert(atid2);
168 if (ret.second ==
false) {
170 mietid2 = MieTids[atid2];
174 MieTids[atid2] = nMie;
178 MixingMap.resize(nMie);
179 MixingMap[mietid1].resize(nMie);
181 MixingMap[mietid1][mietid2] = mixer;
182 if (mietid2 != mietid1) {
183 MixingMap[mietid2].resize(nMie);
184 MixingMap[mietid2][mietid1] = mixer;
188 void Mie::calcForce(InteractionData& idat) {
189 if (!initialized_) initialize();
191 MieInteractionData& mixer =
192 MixingMap[MieTids[idat.atid1]][MieTids[idat.atid2]];
193 RealType sigmai = mixer.sigmai;
194 RealType epsilon = mixer.epsilon;
195 int nRep = mixer.nRep;
196 int mAtt = mixer.mAtt;
197 RealType nmScale = mixer.nmScale;
201 RealType myPot = 0.0;
202 RealType myPotC = 0.0;
203 RealType myDeriv = 0.0;
204 RealType myDerivC = 0.0;
206 ros = idat.rij * sigmai;
208 getMieFunc(ros, nRep, mAtt, myPot, myDeriv);
210 if (idat.shiftedPot) {
211 rcos = idat.rcut * sigmai;
212 getMieFunc(rcos, nRep, mAtt, myPotC, myDerivC);
214 }
else if (idat.shiftedForce) {
215 rcos = idat.rcut * sigmai;
216 getMieFunc(rcos, nRep, mAtt, myPotC, myDerivC);
217 myPotC = myPotC + myDerivC * (idat.rij - idat.rcut) * sigmai;
223 RealType pot_temp = idat.vdwMult * nmScale * epsilon * (myPot - myPotC);
224 idat.vpair += pot_temp;
226 RealType dudr = idat.sw * idat.vdwMult * nmScale * epsilon *
227 (myDeriv - myDerivC) * sigmai;
232 idat.f1 += idat.d * dudr / idat.rij;
237 void Mie::getMieFunc(
const RealType& r,
int& n,
int& m, RealType& pot,
239 RealType ri = 1.0 / r;
240 RealType rin = pow(ri, n);
241 RealType rim = pow(ri, m);
242 RealType rin1 = rin * ri;
243 RealType rim1 = rim * ri;
246 deriv = -n * rin1 + m * rim1;
250 RealType Mie::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
251 if (!initialized_) initialize();
253 int atid1 = atypes.first->getIdent();
254 int atid2 = atypes.second->getIdent();
255 int mietid1 = MieTids[atid1];
256 int mietid2 = MieTids[atid2];
258 if (mietid1 == -1 || mietid2 == -1)
261 MieInteractionData mixer = MixingMap[mietid1][mietid2];
262 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.