30 const Eigen::Vector3d& posA = siteA.
getPos();
31 const Eigen::Vector3d& posB = siteB.
getPos();
35 const double R = a.norm();
36 const double fac1 = 1.0 / R;
38 Eigen::Matrix<double, N, 1>
V;
41 if (N > 1 || rankB > 0) {
42 const double fac2 = std::pow(fac1, 2);
44 if constexpr (N > 1) {
45 V.template segment<3>(1) =
51 fac2 * a.dot(siteB.
Q().segment<3>(1));
54 const double fac3 = std::pow(fac1, 3);
55 if (N > 1 && rankB > 0) {
57 Eigen::Vector3d result =
58 -3 * a * (a.transpose() * siteB.
Q().segment<3>(1));
59 result += siteB.
Q().segment<3>(1);
61 V.template segment<3>(1) += result;
65 if (N > 4 || rankB > 1) {
66 const double sqr3 = std::sqrt(3);
70 Eigen::Matrix<double, 1, 5> Qq;
71 Qq(0) = 1.5 * r.
zz() - 0.5;
74 Qq(3) = 0.5 * (r.
xx() - r.
yy());
77 if constexpr (N > 4) {
78 V.template segment<5>(4) = fac3 * Qq.transpose() * siteB.
getCharge();
81 V(0) += fac3 * Qq * siteB.
Q().segment<5>(4);
84 if ((N > 4 || rankB > 0) || (N > 1 || rankB > 1)) {
86 Eigen::Matrix<double, 3, 5> dQ;
87 const double fac4 = std::pow(fac1, 4);
89 const Eigen::Vector3d afac = a * fac4;
91 dQ.col(0) = (1.5 - 7.5 * r.
zz()) * afac;
92 dQ.col(0).z() += 3 * afac.z();
94 dQ.col(1) = -5 * r.
xz() * afac;
95 dQ.col(1).z() += afac.x();
96 dQ.col(1).x() += afac.z();
98 dQ.col(2) = -5 * r.
yz() * afac;
99 dQ.col(2).z() += afac.y();
100 dQ.col(2).y() += afac.z();
102 dQ.col(3) = -2.5 * (r.
xx() - r.
yy()) * afac;
103 dQ.col(3).x() += afac.x();
104 dQ.col(3).y() -= afac.y();
106 dQ.col(4) = -5 * r.
xy() * afac;
107 dQ.col(4).y() += afac.x();
108 dQ.col(4).x() += afac.y();
110 dQ.rightCols<4>() *= sqr3;
112 if constexpr (N > 4) {
113 V.template segment<5>(4) += dQ.transpose() * siteB.
Q().segment<3>(1);
116 V.template segment<3>(1) -= dQ * siteB.
Q().segment<5>(4);
120 if (N > 4 && rankB > 1) {
123 Eigen::Matrix<double, 5, 5> QQ;
124 QQ(0, 0) = 0.75 * ((35 * r.
zz() - 30) * r.
zz() + 3);
125 double temp = 0.5 * sqr3 * (35 * r.
zz() - 15);
126 QQ(1, 0) = temp * r.
xz();
127 QQ(2, 0) = temp * r.
yz();
129 temp = 5 * (7 * r.
zz() - 1);
130 QQ(3, 0) = sqr3 * 0.25 * temp * (r.
xx() - r.
yy());
131 QQ(4, 0) = sqr3 * 0.5 * temp * r.
xy();
133 35 * r.
zz() * r.
xx() - 5 * (r.
xx() + r.
zz()) + 1;
134 QQ(2, 1) = r.
xy() * temp;
135 QQ(3, 1) = 0.5 * r.
xz() * (35 * (r.
xx() - r.
yy()) - 10);
136 QQ(4, 1) = r.
yz() * 5 * (7 * r.
xx() - 1);
138 5 * (7 * r.
yy() * r.
zz() - (r.
yy() + r.
zz())) + 1;
139 QQ(3, 2) = 0.5 * r.
yz() * (35 * (r.
xx() - r.
yy()) + 10);
140 QQ(4, 2) = r.
xz() * 5 * (7 * r.
yy() - 1);
141 QQ(3, 3) = 8.75 * std::pow(r.
xx() - r.
yy(), 2) - 5 * (r.
xx() + r.
yy()) +
143 QQ(4, 3) = 17.5 * r.
xy() * (r.
xx() - r.
yy());
145 5 * (7 * r.
xx() * r.
yy() - (r.
xx() + r.
yy())) + 1;
147 const double fac5 = std::pow(fac1, 5);
148 V.template segment<5>(4) +=
149 fac5 * QQ.selfadjointView<Eigen::Lower>() * siteB.
Q().segment<5>(4);
364 Eigen::MatrixXd A = Eigen::MatrixXd::Zero(size, size);
366 for (
Index j = 0; j < i; j++) {
372 A.block<3, 3>(3 * i, 3 * i) = seg[i].getPInv();
374 Eigen::VectorXd b = Eigen::VectorXd(size);
376 const Eigen::Vector3d
V = seg[i].V() + seg[i].V_noE();
377 b.segment<3>(3 * i) = -
V;
380 Eigen::LLT<Eigen::Ref<Eigen::MatrixXd>> lltOfA(A);
381 return lltOfA.solve(b);