48#include "nonbonded/MAW.hpp"
54#include "utils/simError.h"
60 MAW::MAW() : initialized_(false), forceField_(NULL), name_(
"MAW") {}
62 void MAW::initialize() {
66 MAWtids.resize(forceField_->getNAtomType(), -1);
68 ForceField::NonBondedInteractionTypeContainer* nbiTypes =
69 forceField_->getNonBondedInteractionTypes();
70 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
71 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
72 NonBondedInteractionType* nbt;
75 for (nbt = nbiTypes->beginType(j); nbt != NULL;
76 nbt = nbiTypes->nextType(j)) {
78 keys = nbiTypes->getKeys(j);
79 AtomType* at1 = forceField_->getAtomType(keys[0]);
81 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
82 "MAW::initialize could not find AtomType %s\n"
83 "\tto for for %s - %s interaction.\n",
84 keys[0].c_str(), keys[0].c_str(), keys[1].c_str());
85 painCave.severity = OPENMD_ERROR;
90 AtomType* at2 = forceField_->getAtomType(keys[1]);
92 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
93 "MAW::initialize could not find AtomType %s\n"
94 "\tfor %s - %s nonbonded interaction.\n",
95 keys[1].c_str(), keys[0].c_str(), keys[1].c_str());
96 painCave.severity = OPENMD_ERROR;
101 int atid1 = at1->getIdent();
102 if (MAWtids[atid1] == -1) {
103 mtid1 = MAWtypes.size();
104 MAWtypes.insert(atid1);
105 MAWtids[atid1] = mtid1;
107 int atid2 = at2->getIdent();
108 if (MAWtids[atid2] == -1) {
109 mtid2 = MAWtypes.size();
110 MAWtypes.insert(atid2);
111 MAWtids[atid2] = mtid2;
114 MAWInteractionType* mit =
dynamic_cast<MAWInteractionType*
>(nbt);
118 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
119 "MAW::initialize could not convert NonBondedInteractionType\n"
120 "\tto MAWInteractionType 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 De = mit->getD();
128 RealType beta = mit->getBeta();
129 RealType Re = mit->getR();
130 RealType ca1 = mit->getCA1();
131 RealType cb1 = mit->getCB1();
133 addExplicitInteraction(at1, at2, De, beta, Re, ca1, cb1);
139 void MAW::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
140 RealType De, RealType beta, RealType Re,
141 RealType ca1, RealType cb1) {
142 MAWInteractionData mixer;
148 mixer.j_is_Metal = atype2->isMetal();
150 int mtid1 = MAWtids[atype1->getIdent()];
151 int mtid2 = MAWtids[atype2->getIdent()];
152 int nM = MAWtypes.size();
154 MixingMap.resize(nM);
155 MixingMap[mtid1].resize(nM);
157 MixingMap[mtid1][mtid2] = mixer;
158 if (mtid2 != mtid1) {
159 MixingMap[mtid2].resize(nM);
160 mixer.j_is_Metal = atype1->isMetal();
161 MixingMap[mtid2][mtid1] = mixer;
165 void MAW::calcForce(InteractionData& idat) {
166 if (!initialized_) initialize();
168 MAWInteractionData& mixer =
169 MixingMap[MAWtids[idat.atid1]][MAWtids[idat.atid2]];
171 RealType myPot = 0.0;
172 RealType myPotC = 0.0;
173 RealType myDeriv = 0.0;
174 RealType myDerivC = 0.0;
176 RealType D_e = mixer.De;
177 RealType R_e = mixer.Re;
178 RealType beta = mixer.beta;
179 RealType ca1 = mixer.ca1;
180 RealType cb1 = mixer.cb1;
184 if (mixer.j_is_Metal) {
187 r = idat.A1 * idat.d;
188 Atrans = idat.A1.transpose();
191 r = -idat.A2 * idat.d;
192 Atrans = idat.A2.transpose();
197 RealType expt = -beta * (idat.rij - R_e);
198 RealType expfnc = exp(expt);
199 RealType expfnc2 = expfnc * expfnc;
201 RealType exptC = 0.0;
202 RealType expfncC = 0.0;
203 RealType expfnc2C = 0.0;
205 myPot = D_e * (expfnc2 - 2.0 * expfnc);
206 myDeriv = 2.0 * D_e * beta * (expfnc - expfnc2);
208 if (idat.shiftedPot || idat.shiftedForce) {
209 exptC = -beta * (idat.rcut - R_e);
210 expfncC = exp(exptC);
211 expfnc2C = expfncC * expfncC;
214 if (idat.shiftedPot) {
215 myPotC = D_e * (expfnc2C - 2.0 * expfncC);
217 }
else if (idat.shiftedForce) {
218 myPotC = D_e * (expfnc2C - 2.0 * expfncC);
219 myDerivC = 2.0 * D_e * beta * (expfncC - expfnc2C);
220 myPotC += myDerivC * (idat.rij - idat.rcut);
232 RealType r3 = idat.r2 * idat.rij;
233 RealType r4 = idat.r2 * idat.r2;
250 RealType Vmorse = (myPot - myPotC);
251 RealType Vang = ca1 * x2 / idat.r2 + cb1 * z / idat.rij + (0.8 - ca1 / 3.0);
253 RealType pot_temp = idat.vdwMult * Vmorse * Vang;
254 idat.vpair += pot_temp;
257 Vector3d dVmorsedr = (myDeriv - myDerivC) * Vector3d(x, y, z) / idat.rij;
259 Vector3d dVangdr = Vector3d(
260 -2.0 * ca1 * x2 * x / r4 + 2.0 * ca1 * x / idat.r2 - cb1 * x * z / r3,
261 -2.0 * ca1 * x2 * y / r4 - cb1 * z * y / r3,
262 -2.0 * ca1 * x2 * z / r4 + cb1 / idat.rij - cb1 * z2 / r3);
266 Vector3d dvdr = Vang * dVmorsedr + Vmorse * dVangdr;
271 Vector3d dVangdu = Vector3d(
272 cb1 * y / idat.rij, 2.0 * ca1 * x * z / idat.r2 - cb1 * x / idat.rij,
273 -2.0 * ca1 * y * x / idat.r2);
278 Vector3d trq = idat.vdwMult * Vmorse * dVangdu * idat.sw;
282 if (mixer.j_is_Metal) {
283 idat.t1 += Atrans * trq;
285 idat.t2 += Atrans * trq;
290 Vector3d ftmp = idat.vdwMult * idat.sw * dvdr;
294 if (mixer.j_is_Metal) {
295 flab = Atrans * ftmp;
297 flab = -Atrans * ftmp;
305 RealType MAW::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
306 if (!initialized_) initialize();
307 int atid1 = atypes.first->getIdent();
308 int atid2 = atypes.second->getIdent();
309 int mtid1 = MAWtids[atid1];
310 int mtid2 = MAWtids[atid2];
312 if (mtid1 == -1 || mtid2 == -1)
315 MAWInteractionData mixer = MixingMap[mtid1][mtid2];
316 RealType R_e = mixer.Re;
317 RealType beta = mixer.beta;
322 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.