45#include "nonbonded/Sticky.hpp"
51#include "nonbonded/LJ.hpp"
52#include "types/StickyAdapter.hpp"
53#include "utils/simError.h"
58 Sticky::Sticky() : initialized_(false), forceField_(NULL), name_(
"Sticky") {}
60 void Sticky::initialize() {
66 Stids.resize(forceField_->getNAtomType(), -1);
70 AtomTypeSet::iterator at;
71 for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
72 if ((*at)->isSticky()) nSticky_++;
75 MixingMap.resize(nSticky_);
77 for (at = simTypes_.begin(); at != simTypes_.end(); ++at) {
78 if ((*at)->isSticky()) addType(*at);
84 void Sticky::addType(AtomType* atomType) {
85 StickyAdapter sticky1 = StickyAdapter(atomType);
89 int atid = atomType->getIdent();
90 int stid = Stypes.size();
92 pair<set<int>::iterator,
bool> ret;
93 ret = Stypes.insert(atid);
94 if (ret.second ==
false) {
95 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
96 "Sticky already had a previous entry with ident %d\n", atid);
97 painCave.severity = OPENMD_INFO;
103 MixingMap[stid].resize(nSticky_);
107 std::set<int>::iterator it;
108 for (it = Stypes.begin(); it != Stypes.end(); ++it) {
109 int stid2 = Stids[(*it)];
110 AtomType* atype2 = forceField_->getAtomType((*it));
111 StickyAdapter sticky2 = StickyAdapter(atype2);
113 StickyInteractionData mixer;
120 mixer.rl = 0.5 * (sticky1.getRl() + sticky2.getRl());
121 mixer.ru = 0.5 * (sticky1.getRu() + sticky2.getRu());
122 mixer.rlp = 0.5 * (sticky1.getRlp() + sticky2.getRlp());
123 mixer.rup = 0.5 * (sticky1.getRup() + sticky2.getRup());
124 mixer.rbig = max(mixer.ru, mixer.rup);
125 mixer.w0 = sqrt(sticky1.getW0() * sticky2.getW0());
126 mixer.v0 = sqrt(sticky1.getV0() * sticky2.getV0());
127 mixer.v0p = sqrt(sticky1.getV0p() * sticky2.getV0p());
128 mixer.isPower = sticky1.isStickyPower() && sticky2.isStickyPower();
130 CubicSpline* s =
new CubicSpline();
131 s->addPoint(mixer.rl, 1.0);
132 s->addPoint(mixer.ru, 0.0);
135 CubicSpline* sp =
new CubicSpline();
136 sp->addPoint(mixer.rlp, 1.0);
137 sp->addPoint(mixer.rup, 0.0);
140 MixingMap[stid2].resize(nSticky_);
142 MixingMap[stid][stid2] = mixer;
143 if (stid2 != stid) { MixingMap[stid2][stid] = mixer; }
157 if (!initialized_) initialize();
160 MixingMap[Stids[idat.
atid1]][Stids[idat.
atid2]];
162 RealType w0 = mixer.w0;
163 RealType v0 = mixer.v0;
164 RealType v0p = mixer.v0p;
165 RealType rl = mixer.rl;
166 RealType ru = mixer.ru;
167 RealType rlp = mixer.rlp;
168 RealType rup = mixer.rup;
169 RealType rbig = mixer.rbig;
170 bool isPower = mixer.isPower;
172 if (idat.
rij <= rbig) {
173 RealType r3 = idat.
r2 * idat.
rij;
174 RealType r5 = r3 * idat.
r2;
188 RealType xi = ri.
x();
189 RealType yi = ri.
y();
190 RealType zi = ri.
z();
192 RealType xj = rj.
x();
193 RealType yj = rj.
y();
194 RealType zj = rj.
z();
196 RealType xi2 = xi * xi;
197 RealType yi2 = yi * yi;
198 RealType zi2 = zi * zi;
200 RealType xj2 = xj * xj;
201 RealType yj2 = yj * yj;
202 RealType zj2 = zj * zj;
209 RealType dspdr = 0.0;
217 mixer.s->getValueAndDerivativeAt(idat.
rij, s, dsdr);
221 if (idat.
rij < rup) {
222 if (idat.
rij < rlp) {
227 mixer.sp->getValueAndDerivativeAt(idat.
rij, sp, dspdr);
231 RealType wi = 2.0 * (xi2 - yi2) * zi / r3;
232 RealType wj = 2.0 * (xj2 - yj2) * zj / r3;
233 RealType w = wi + wj;
235 RealType zif = zi / idat.
rij - 0.6;
236 RealType zis = zi / idat.
rij + 0.8;
238 RealType zjf = zj / idat.
rij - 0.6;
239 RealType zjs = zj / idat.
rij + 0.8;
241 RealType wip = zif * zif * zis * zis - w0;
242 RealType wjp = zjf * zjf * zjs * zjs - w0;
243 RealType wp = wip + wjp;
245 Vector3d dwi(4.0 * xi * zi / r3 - 6.0 * xi * zi * (xi2 - yi2) / r5,
246 -4.0 * yi * zi / r3 - 6.0 * yi * zi * (xi2 - yi2) / r5,
247 2.0 * (xi2 - yi2) / r3 - 6.0 * zi2 * (xi2 - yi2) / r5);
249 Vector3d dwj(4.0 * xj * zj / r3 - 6.0 * xj * zj * (xj2 - yj2) / r5,
250 -4.0 * yj * zj / r3 - 6.0 * yj * zj * (xj2 - yj2) / r5,
251 2.0 * (xj2 - yj2) / r3 - 6.0 * zj2 * (xj2 - yj2) / r5);
253 RealType uglyi = zif * zif * zis + zif * zis * zis;
254 RealType uglyj = zjf * zjf * zjs + zjf * zjs * zjs;
256 Vector3d dwip(-2.0 * xi * zi * uglyi / r3, -2.0 * yi * zi * uglyi / r3,
257 2.0 * (1.0 / idat.
rij - zi2 / r3) * uglyi);
259 Vector3d dwjp(-2.0 * xj * zj * uglyj / r3, -2.0 * yj * zj * uglyj / r3,
260 2.0 * (1.0 / idat.
rij - zj2 / r3) * uglyj);
262 Vector3d dwidu(4.0 * (yi * zi2 + 0.5 * yi * (xi2 - yi2)) / r3,
263 4.0 * (xi * zi2 - 0.5 * xi * (xi2 - yi2)) / r3,
264 -8.0 * xi * yi * zi / r3);
266 Vector3d dwjdu(4.0 * (yj * zj2 + 0.5 * yj * (xj2 - yj2)) / r3,
267 4.0 * (xj * zj2 - 0.5 * xj * (xj2 - yj2)) / r3,
268 -8.0 * xj * yj * zj / r3);
270 Vector3d dwipdu(2.0 * yi * uglyi / idat.
rij, -2.0 * xi * uglyi / idat.
rij,
273 Vector3d dwjpdu(2.0 * yj * uglyj / idat.
rij, -2.0 * xj * uglyj / idat.
rij,
277 cerr <<
"This is probably an error!\n";
278 RealType frac1 = 0.25;
279 RealType frac2 = 0.75;
280 RealType wi2 = wi * wi;
281 RealType wj2 = wj * wj;
283 w = frac1 * wi * wi2 + frac2 * wi + frac1 * wj * wj2 + frac2 * wj + v0p;
285 dwi = frac1 * RealType(3.0) * wi2 * dwi + frac2 * dwi;
286 dwj = frac1 * RealType(3.0) * wj2 * dwi + frac2 * dwi;
289 dwidu = frac1 * RealType(3.0) * wi2 * dwidu + frac2 * dwidu;
290 dwidu = frac1 * RealType(3.0) * wj2 * dwjdu + frac2 * dwjdu;
297 idat.
vpair += 0.5 * (v0 * s * w + v0p * sp * wp);
299 0.5 * (v0 * s * w + v0p * sp * wp) * idat.
sw;
302 0.5 * (v0 * s * w + v0p * sp * wp) * idat.
sw;
307 Vector3d ti = 0.5 * idat.
sw * (v0 * s * dwidu + v0p * sp * dwipdu);
308 Vector3d tj = 0.5 * idat.
sw * (v0 * s * dwjdu + v0p * sp * dwjpdu);
312 idat.
t1 += A1trans * ti;
313 idat.
t2 += A2trans * tj;
319 Vector3d radcomi = (v0 * s * dwi + v0p * sp * dwip) * idat.
sw;
320 Vector3d radcomj = (v0 * s * dwj + v0p * sp * dwjp) * idat.
sw;
327 idat.
f1 += 0.5 * ((v0 * dsdr * w + v0p * dspdr * wp) * idat.
d / idat.
rij +
334 RealType Sticky::getSuggestedCutoffRadius(pair<AtomType*, AtomType*> atypes) {
335 if (!initialized_) initialize();
336 int atid1 = atypes.first->getIdent();
337 int atid2 = atypes.second->getIdent();
338 int stid1 = Stids[atid1];
339 int stid2 = Stids[atid2];
341 if (stid1 == -1 || stid2 == -1)
343 else {
return MixingMap[stid1][stid2].rbig; }
Real & z()
Returns reference of the third element of Vector3.
Real & x()
Returns reference of the first element of Vector3.
Real & y()
Returns reference of the second element of Vector3.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
@ HYDROGENBONDING_FAMILY
Short-range directional interactions.
The InteractionData struct.
Vector3d d
interatomic vector (already wrapped into box)
int atid1
atomType ident for atom 1
potVec pot
total potential
potVec selePot
potential energies of the selected sites
RealType sw
switching function value at rij
RotMat3x3d A2
rotation matrix of second atom
bool isSelected
one of the particles has been selected for selection potential
RotMat3x3d A1
rotation matrix of first atom
Vector3d t1
torque on first atom
Vector3d t2
torque on second atom
RealType vpair
pair potential
int atid2
atomType ident for atom 2
Vector3d f1
force between the two atoms
RealType rij
interatomic separation