45#include "nonbonded/MAW.hpp"
51#include "utils/simError.h"
57 MAW::MAW() : initialized_(false), forceField_(NULL), name_(
"MAW") {}
59 void MAW::initialize() {
63 MAWtids.resize(forceField_->getNAtomType(), -1);
65 ForceField::NonBondedInteractionTypeContainer* nbiTypes =
66 forceField_->getNonBondedInteractionTypes();
67 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
68 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
69 NonBondedInteractionType* nbt;
72 for (nbt = nbiTypes->beginType(j); nbt != NULL;
73 nbt = nbiTypes->nextType(j)) {
75 keys = nbiTypes->getKeys(j);
76 AtomType* at1 = forceField_->getAtomType(keys[0]);
78 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
79 "MAW::initialize could not find AtomType %s\n"
80 "\tto for for %s - %s interaction.\n",
81 keys[0].c_str(), keys[0].c_str(), keys[1].c_str());
82 painCave.severity = OPENMD_ERROR;
87 AtomType* at2 = forceField_->getAtomType(keys[1]);
89 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
90 "MAW::initialize could not find AtomType %s\n"
91 "\tfor %s - %s nonbonded interaction.\n",
92 keys[1].c_str(), keys[0].c_str(), keys[1].c_str());
93 painCave.severity = OPENMD_ERROR;
98 int atid1 = at1->getIdent();
99 if (MAWtids[atid1] == -1) {
100 mtid1 = MAWtypes.size();
101 MAWtypes.insert(atid1);
102 MAWtids[atid1] = mtid1;
104 int atid2 = at2->getIdent();
105 if (MAWtids[atid2] == -1) {
106 mtid2 = MAWtypes.size();
107 MAWtypes.insert(atid2);
108 MAWtids[atid2] = mtid2;
111 MAWInteractionType* mit =
dynamic_cast<MAWInteractionType*
>(nbt);
115 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
116 "MAW::initialize could not convert NonBondedInteractionType\n"
117 "\tto MAWInteractionType 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 De = mit->getD();
125 RealType beta = mit->getBeta();
126 RealType Re = mit->getR();
127 RealType ca1 = mit->getCA1();
128 RealType cb1 = mit->getCB1();
130 addExplicitInteraction(at1, at2, De, beta, Re, ca1, cb1);
136 void MAW::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
137 RealType De, RealType beta, RealType Re,
138 RealType ca1, RealType cb1) {
139 MAWInteractionData mixer;
145 mixer.j_is_Metal = atype2->isMetal();
147 int mtid1 = MAWtids[atype1->getIdent()];
148 int mtid2 = MAWtids[atype2->getIdent()];
149 int nM = MAWtypes.size();
151 MixingMap.resize(nM);
152 MixingMap[mtid1].resize(nM);
154 MixingMap[mtid1][mtid2] = mixer;
155 if (mtid2 != mtid1) {
156 MixingMap[mtid2].resize(nM);
157 mixer.j_is_Metal = atype1->isMetal();
158 MixingMap[mtid2][mtid1] = mixer;
162 void MAW::calcForce(InteractionData& idat) {
163 if (!initialized_) initialize();
165 MAWInteractionData& mixer =
166 MixingMap[MAWtids[idat.atid1]][MAWtids[idat.atid2]];
168 RealType myPot = 0.0;
169 RealType myPotC = 0.0;
170 RealType myDeriv = 0.0;
171 RealType myDerivC = 0.0;
173 RealType D_e = mixer.De;
174 RealType R_e = mixer.Re;
175 RealType beta = mixer.beta;
176 RealType ca1 = mixer.ca1;
177 RealType cb1 = mixer.cb1;
181 if (mixer.j_is_Metal) {
184 r = idat.A1 * idat.d;
185 Atrans = idat.A1.transpose();
188 r = -idat.A2 * idat.d;
189 Atrans = idat.A2.transpose();
194 RealType expt = -beta * (idat.rij - R_e);
195 RealType expfnc = exp(expt);
196 RealType expfnc2 = expfnc * expfnc;
198 RealType exptC = 0.0;
199 RealType expfncC = 0.0;
200 RealType expfnc2C = 0.0;
202 myPot = D_e * (expfnc2 - 2.0 * expfnc);
203 myDeriv = 2.0 * D_e * beta * (expfnc - expfnc2);
205 if (idat.shiftedPot || idat.shiftedForce) {
206 exptC = -beta * (idat.rcut - R_e);
207 expfncC = exp(exptC);
208 expfnc2C = expfncC * expfncC;
211 if (idat.shiftedPot) {
212 myPotC = D_e * (expfnc2C - 2.0 * expfncC);
214 }
else if (idat.shiftedForce) {
215 myPotC = D_e * (expfnc2C - 2.0 * expfncC);
216 myDerivC = 2.0 * D_e * beta * (expfncC - expfnc2C);
217 myPotC += myDerivC * (idat.rij - idat.rcut);
229 RealType r3 = idat.r2 * idat.rij;
230 RealType r4 = idat.r2 * idat.r2;
247 RealType Vmorse = (myPot - myPotC);
248 RealType Vang = ca1 * x2 / idat.r2 + cb1 * z / idat.rij + (0.8 - ca1 / 3.0);
250 RealType pot_temp = idat.vdwMult * Vmorse * Vang;
251 idat.vpair += pot_temp;
254 Vector3d dVmorsedr = (myDeriv - myDerivC) * Vector3d(x, y, z) / idat.rij;
256 Vector3d dVangdr = Vector3d(
257 -2.0 * ca1 * x2 * x / r4 + 2.0 * ca1 * x / idat.r2 - cb1 * x * z / r3,
258 -2.0 * ca1 * x2 * y / r4 - cb1 * z * y / r3,
259 -2.0 * ca1 * x2 * z / r4 + cb1 / idat.rij - cb1 * z2 / r3);
263 Vector3d dvdr = Vang * dVmorsedr + Vmorse * dVangdr;
268 Vector3d dVangdu = Vector3d(
269 cb1 * y / idat.rij, 2.0 * ca1 * x * z / idat.r2 - cb1 * x / idat.rij,
270 -2.0 * ca1 * y * x / idat.r2);
275 Vector3d trq = idat.vdwMult * Vmorse * dVangdu * idat.sw;
279 if (mixer.j_is_Metal) {
280 idat.t1 += Atrans * trq;
282 idat.t2 += Atrans * trq;
287 Vector3d ftmp = idat.vdwMult * idat.sw * dvdr;
291 if (mixer.j_is_Metal) {
292 flab = Atrans * ftmp;
294 flab = -Atrans * ftmp;
302 RealType MAW::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
303 if (!initialized_) initialize();
304 int atid1 = atypes.first->getIdent();
305 int atid2 = atypes.second->getIdent();
306 int mtid1 = MAWtids[atid1];
307 int mtid2 = MAWtids[atid2];
309 if (mtid1 == -1 || mtid2 == -1)
312 MAWInteractionData mixer = MixingMap[mtid1][mtid2];
313 RealType R_e = mixer.Re;
314 RealType beta = mixer.beta;
319 return (4.9 + beta * R_e) / beta;
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.