45#include "nonbonded/LJ.hpp"
51#include "types/LennardJonesAdapter.hpp"
52#include "types/LennardJonesInteractionType.hpp"
53#include "utils/simError.h"
57 LJ::LJ() : initialized_(false), forceField_(NULL), name_(
"LJ") {}
59 RealType LJ::getSigma(AtomType* atomType1, AtomType* atomType2) {
60 LennardJonesAdapter lja1 = LennardJonesAdapter(atomType1);
61 LennardJonesAdapter lja2 = LennardJonesAdapter(atomType2);
62 RealType sigma1 = lja1.getSigma();
63 RealType sigma2 = lja2.getSigma();
65 ForceFieldOptions& fopts = forceField_->getForceFieldOptions();
66 string DistanceMix = fopts.getDistanceMixingRule();
69 if (DistanceMix ==
"GEOMETRIC")
70 return sqrt(sigma1 * sigma2);
72 return 0.5 * (sigma1 + sigma2);
75 RealType LJ::getEpsilon(AtomType* atomType1, AtomType* atomType2) {
76 LennardJonesAdapter lja1 = LennardJonesAdapter(atomType1);
77 LennardJonesAdapter lja2 = LennardJonesAdapter(atomType2);
79 RealType epsilon1 = lja1.getEpsilon();
80 RealType epsilon2 = lja2.getEpsilon();
81 return sqrt(epsilon1 * epsilon2);
84 void LJ::initialize() {
90 LJtids.resize(forceField_->getNAtomType(), -1);
92 AtomTypeSet::iterator at;
93 for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
94 if ((*at)->isLennardJones()) nLJ_++;
97 MixingMap.resize(nLJ_);
99 for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
100 if ((*at)->isLennardJones()) addType(*at);
103 ForceField::NonBondedInteractionTypeContainer* nbiTypes =
104 forceField_->getNonBondedInteractionTypes();
105 ForceField::NonBondedInteractionTypeContainer::MapTypeIterator j;
106 NonBondedInteractionType* nbt;
107 ForceField::NonBondedInteractionTypeContainer::KeyType keys;
109 for (nbt = nbiTypes->beginType(j); nbt != NULL;
110 nbt = nbiTypes->nextType(j)) {
111 if (nbt->isLennardJones()) {
112 keys = nbiTypes->getKeys(j);
113 keys = nbiTypes->getKeys(j);
114 AtomType* at1 = forceField_->getAtomType(keys[0]);
116 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
117 "LennardJones::initialize could not find AtomType %s\n"
118 "\tto for for %s - %s interaction.\n",
119 keys[0].c_str(), keys[0].c_str(), keys[1].c_str());
120 painCave.severity = OPENMD_ERROR;
121 painCave.isFatal = 1;
125 AtomType* at2 = forceField_->getAtomType(keys[1]);
127 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
128 "LennardJones::initialize could not find AtomType %s\n"
129 "\tfor %s - %s nonbonded interaction.\n",
130 keys[1].c_str(), keys[0].c_str(), keys[1].c_str());
131 painCave.severity = OPENMD_ERROR;
132 painCave.isFatal = 1;
136 LennardJonesInteractionType* ljit =
137 dynamic_cast<LennardJonesInteractionType*
>(nbt);
141 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
142 "LJ::initialize could not convert NonBondedInteractionType\n"
143 "\tto LennardJonesInteractionType for %s - %s interaction.\n",
144 at1->getName().c_str(), at2->getName().c_str());
145 painCave.severity = OPENMD_ERROR;
146 painCave.isFatal = 1;
150 RealType sigma = ljit->getSigma();
151 RealType epsilon = ljit->getEpsilon();
152 addExplicitInteraction(at1, at2, sigma, epsilon);
158 void LJ::addType(AtomType* atomType) {
160 int atid = atomType->getIdent();
161 int ljtid = LJtypes.size();
163 pair<set<int>::iterator,
bool> ret;
164 ret = LJtypes.insert(atid);
165 if (ret.second ==
false) {
166 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
167 "LJ already had a previous entry with ident %d\n", atid);
168 painCave.severity = OPENMD_INFO;
169 painCave.isFatal = 0;
174 RealType s = getSigma(atomType, atomType);
175 if (fabs(s) < std::numeric_limits<RealType>::epsilon()) {
176 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
177 "Lennard-Jones atom %s was defined with a sigma value (%f)\n"
178 "\tthat was too close to zero.",
179 atomType->getName().c_str(), s);
180 painCave.severity = OPENMD_ERROR;
181 painCave.isFatal = 1;
185 LJtids[atid] = ljtid;
186 MixingMap[ljtid].resize(nLJ_);
190 std::set<int>::iterator it;
191 for (it = LJtypes.begin(); it != LJtypes.end(); ++it) {
192 int ljtid2 = LJtids[(*it)];
193 AtomType* atype2 = forceField_->getAtomType((*it));
195 LJInteractionData mixer;
196 mixer.sigma = getSigma(atomType, atype2);
197 mixer.epsilon = getEpsilon(atomType, atype2);
198 mixer.sigmai = 1.0 / mixer.sigma;
199 mixer.explicitlySet =
false;
200 MixingMap[ljtid2].resize(nLJ_);
202 MixingMap[ljtid][ljtid2] = mixer;
203 if (ljtid2 != ljtid) { MixingMap[ljtid2][ljtid] = mixer; }
207 void LJ::addExplicitInteraction(AtomType* atype1, AtomType* atype2,
208 RealType sigma, RealType epsilon) {
209 LJInteractionData mixer;
211 mixer.epsilon = epsilon;
212 mixer.sigmai = 1.0 / mixer.sigma;
213 mixer.explicitlySet =
true;
215 int atid1 = atype1->getIdent();
216 int atid2 = atype2->getIdent();
220 pair<set<int>::iterator,
bool> ret;
221 ret = LJtypes.insert(atid1);
222 if (ret.second ==
false) {
224 ljtid1 = LJtids[atid1];
228 LJtids[atid1] = nLJ_;
232 ret = LJtypes.insert(atid2);
233 if (ret.second ==
false) {
235 ljtid2 = LJtids[atid2];
239 LJtids[atid2] = nLJ_;
243 MixingMap.resize(nLJ_);
244 MixingMap[ljtid1].resize(nLJ_);
246 MixingMap[ljtid1][ljtid2] = mixer;
247 if (ljtid2 != ljtid1) {
248 MixingMap[ljtid2].resize(nLJ_);
249 MixingMap[ljtid2][ljtid1] = mixer;
253 void LJ::calcForce(InteractionData& idat) {
254 if (!initialized_) initialize();
256 LJInteractionData& mixer =
257 MixingMap[LJtids[idat.atid1]][LJtids[idat.atid2]];
259 RealType sigmai = mixer.sigmai;
260 RealType epsilon = mixer.epsilon;
264 RealType myPot = 0.0;
265 RealType myPotC = 0.0;
266 RealType myDeriv = 0.0;
267 RealType myDerivC = 0.0;
269 ros = idat.rij * sigmai;
271 getLJfunc(ros, myPot, myDeriv);
273 if (idat.shiftedPot) {
274 rcos = idat.rcut * sigmai;
275 getLJfunc(rcos, myPotC, myDerivC);
277 }
else if (idat.shiftedForce) {
278 rcos = idat.rcut * sigmai;
279 getLJfunc(rcos, myPotC, myDerivC);
280 myPotC = myPotC + myDerivC * (idat.rij - idat.rcut) * sigmai;
286 RealType pot_temp = idat.vdwMult * epsilon * (myPot - myPotC);
287 idat.vpair += pot_temp;
290 idat.sw * idat.vdwMult * epsilon * (myDeriv - myDerivC) * sigmai;
295 idat.f1 += idat.d * dudr / idat.rij;
300 void LJ::getLJfunc(RealType r, RealType& pot, RealType& deriv) {
301 RealType ri = 1.0 / r;
302 RealType ri2 = ri * ri;
303 RealType ri6 = ri2 * ri2 * ri2;
304 RealType ri7 = ri6 * ri;
305 RealType ri12 = ri6 * ri6;
306 RealType ri13 = ri12 * ri;
308 pot = 4.0 * (ri12 - ri6);
309 deriv = 24.0 * (ri7 - 2.0 * ri13);
314 RealType LJ::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
315 if (!initialized_) initialize();
317 int atid1 = atypes.first->getIdent();
318 int atid2 = atypes.second->getIdent();
319 int ljtid1 = LJtids[atid1];
320 int ljtid2 = LJtids[atid2];
322 if (ljtid1 == -1 || ljtid2 == -1)
325 LJInteractionData mixer = MixingMap[ljtid1][ljtid2];
326 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.