30constexpr double kRSqrtPi = 0.5641895835477563;
35 const double rr1 = 1.0 / r;
36 const double rr2 = rr1 * rr1;
38 const double a3 = a1 * a1 * a1;
39 const double expTerm = kRSqrtPi * std::exp(-a1 * a1 * r * r);
42 b.
B0 = std::erfc(a1 * r) * rr1;
43 b.
B1 = rr2 * (b.
B0 + 2.0 * a1 * expTerm);
44 b.
B2 = rr2 * (3.0 * b.
B1 + 4.0 * a3 * expTerm);
51 const double rr1 = 1.0 / r;
52 const double rr3 = rr1 * rr1 * rr1;
54 b.
B0 = rr1 - erfc_b.
B0;
55 b.
B1 = rr3 - erfc_b.
B1;
56 b.
B2 = 3.0 * rr3 * rr1 * rr1 - erfc_b.
B2;
70 const double expUa = std::exp(-au3);
72 t.
l5 = 1.0 - (1.0 + au3) * expUa;
84struct ScreenedPotentialField {
86 Eigen::Vector3d field;
89ScreenedPotentialField EvaluateSource(
90 double q,
const Eigen::Vector3d& mu,
const Eigen::Vector3d& r_vec,
double r,
91 const EwaldRealSpaceInteractor::BFunctions& b) {
92 ScreenedPotentialField result;
93 const double mu_dot_r = mu.dot(r_vec);
96 result.phi = q * b.B0 + mu_dot_r * b.B1;
104 result.field = q * b.B1 * r_vec + mu_dot_r * b.B2 * r_vec - b.B1 * mu;
111template <
class T, enum Estatic CE>
114 const Eigen::Vector3d& source_shift)
const {
115 const Eigen::Vector3d r_vec =
116 site2.
getPos() - (site1.getPos() + source_shift);
117 const double r = r_vec.norm();
120 const double q1 = site1.getCharge();
121 const Eigen::Vector3d mu1 = site1.getStaticDipole();
122 const ScreenedPotentialField src = EvaluateSource(q1, mu1, r_vec, r, b);
125 site2.
V_noE() += src.field;
127 site2.
V() += src.field;
133 return q2 * src.phi - mu2.dot(src.field);
136template <
class T, enum Estatic CE>
139 const Eigen::Vector3d& source_shift)
const {
140 const Eigen::Vector3d r_vec =
141 site2.
getPos() - (site1.getPos() + source_shift);
142 const double r = r_vec.norm();
166 const Eigen::Vector3d self_field = -self_coeff * site1.getStaticDipole();
168 site2.
V_noE() -= self_field;
170 site2.
V() -= self_field;
176 const double q1 = site1.getCharge();
177 const Eigen::Vector3d mu1 = site1.getStaticDipole();
178 const ScreenedPotentialField src = EvaluateSource(q1, mu1, r_vec, r, b);
186 site2.
V_noE() -= src.field;
188 site2.
V() -= src.field;
192template <enum Estatic CE>
195 const Eigen::Vector3d& source_shift)
const {
196 const Eigen::Vector3d r_vec =
198 const double r = r_vec.norm();
228 site2.
V_noE() -= self_field;
230 site2.
V() -= self_field;
242 const ScreenedPotentialField src =
246 site2.
V_noE() -= src.field;
248 site2.
V() -= src.field;
252template <enum Estatic CE>
255 const Eigen::Vector3d& source_shift)
const {
256 const Eigen::Vector3d r_vec =
258 const double r = r_vec.norm();
264 const double mu_dot_r = mu1.dot(r_vec);
281 const double c3 = t.
l3 * b.
B1 + (t.
l3 - 1.0) * berf.
B1;
282 const double c5 = t.
l5 * b.
B2 + (t.
l5 - 1.0) * berf.
B2;
283 const Eigen::Vector3d field = mu_dot_r * c5 * r_vec - c3 * mu1;
286 site2.
V_noE() += field;
292 return -mu2.dot(field);
295template <
class S1,
class S2>
297 const S1& site1,
const S2& site2,
298 const Eigen::Vector3d& source_shift)
const {
299 const Eigen::Vector3d r_vec =
300 site2.getPos() - (site1.getPos() + source_shift);
301 const double r = r_vec.norm();
304 const double q1 = site1.getCharge();
305 const Eigen::Vector3d mu1 = site1.getStaticDipole();
306 const ScreenedPotentialField src = EvaluateSource(q1, mu1, r_vec, r, b);
308 const double q2 = site2.getCharge();
309 const Eigen::Vector3d mu2 = site2.getStaticDipole();
310 return q2 * src.phi - mu2.dot(src.field);
313template <
class S1,
class S2>
315 const S1& site1,
const S2& site2,
316 const Eigen::Vector3d& source_shift)
const {
317 const Eigen::Vector3d r_vec =
318 site2.getPos() - (site1.getPos() + source_shift);
319 const double r = r_vec.norm();
321 const double q1 = site1.getCharge();
322 const Eigen::Vector3d mu1 = site1.getStaticDipole();
323 const double q2 = site2.getCharge();
324 const Eigen::Vector3d mu2 = site2.getStaticDipole();
333 const double phi_self = 2.0 *
alpha_ / sqrt_pi;
344 return q2 * q1 * phi_self + dip_self * mu2.dot(mu1);
348 const ScreenedPotentialField src = EvaluateSource(q1, mu1, r_vec, r, b);
349 return q2 * src.phi - mu2.dot(src.field);
354 const Eigen::Vector3d& source_shift)
const {
358 const Eigen::Vector3d r_vec =
360 const double r = r_vec.norm();
375 return dip_self * mu2.dot(mu1);
379 const ScreenedPotentialField src = EvaluateSource(0.0, mu1, r_vec, r, b);
380 return q2 * src.phi - mu2.dot(src.field);
385 const Eigen::Vector3d r_vec = site2.
getPos() - site1.
getPos();
386 const double r = r_vec.norm();
393 const double mu1_dot_r = mu1.dot(r_vec);
401 const double c3 = t.
l3 * b.
B1 + (t.
l3 - 1.0) * berf.
B1;
402 const double c5 = t.
l5 * b.
B2 + (t.
l5 - 1.0) * berf.
B2;
403 const Eigen::Vector3d field1 = mu1_dot_r * c5 * r_vec - c3 * mu1;
404 return -mu2.dot(field1);
409 const Eigen::Vector3d& source_shift,
bool damp)
const {
414 const Eigen::Vector3d r_vec =
416 const double r = r_vec.norm();
423 const double mu_dot_r = mu1.dot(r_vec);
432 const double c3 = t.
l3 * b.
B1 + (t.
l3 - 1.0) * berf.
B1;
433 const double c5 = t.
l5 * b.
B2 + (t.
l5 - 1.0) * berf.
B2;
434 const double phi = c3 * mu_dot_r;
435 const Eigen::Vector3d field = mu_dot_r * c5 * r_vec - c3 * mu1;
441 return q2 * phi - mu2.dot(field);
460 const Eigen::Vector3d&)
const;
463 const Eigen::Vector3d&)
const;
466 const Eigen::Vector3d&)
const;
469 const Eigen::Vector3d&)
const;
BFunctions ComputeB(double r) const
double CalcInducedSourceEnergy(const PolarSite &site1, const PolarSite &site2, const Eigen::Vector3d &source_shift=Eigen::Vector3d::Zero(), bool damp=true) const
double CalcStaticEnergy(const S1 &site1, const S2 &site2, const Eigen::Vector3d &source_shift=Eigen::Vector3d::Zero()) const
BFunctions ComputeErfB(double r) const
TholeFactors ComputeThole(double r, const PolarSite &site1, const PolarSite &site2) const
static constexpr double kCoincidenceTol
void ApplyErfInducedFieldCorrection(const PolarSite &site1, PolarSite &site2, const Eigen::Vector3d &source_shift=Eigen::Vector3d::Zero()) const
double CalcInducedEnergy(const PolarSite &site1, const PolarSite &site2) const
double ApplyInducedField(const PolarSite &site1, PolarSite &site2, const Eigen::Vector3d &source_shift=Eigen::Vector3d::Zero()) const
double CalcErfInducedSourceEnergy(const PolarSite &site1, const PolarSite &site2, const Eigen::Vector3d &source_shift=Eigen::Vector3d::Zero()) const
double CalcErfStaticEnergy(const S1 &site1, const S2 &site2, const Eigen::Vector3d &source_shift=Eigen::Vector3d::Zero()) const
double ApplyStaticField(const T &site1, PolarSite &site2, const Eigen::Vector3d &source_shift=Eigen::Vector3d::Zero()) const
void ApplyErfStaticFieldCorrection(const T &site1, PolarSite &site2, const Eigen::Vector3d &source_shift=Eigen::Vector3d::Zero()) const
Class to represent Atom/Site in electrostatic+polarization.
double getSqrtInvEigenDamp() const
const Eigen::Vector3d & V_noE() const
Eigen::Vector3d getStaticDipole() const final
const Eigen::Vector3d & V() const
Eigen::Vector3d getInducedDipole() const final
Class to represent Atom/Site in electrostatic.
const Eigen::Vector3d & getPos() const
Charge transport classes.
Provides a means for comparing floating point numbers.