31 const Eigen::Vector3d& posA = siteA.
getPos();
32 const Eigen::Vector3d& posB = siteB.
getPos();
36 const double R = a.norm();
37 const double fac1 = 1.0 / R;
39 Eigen::Matrix<double, N, 1>
V;
42 if (N > 1 || rankB > 0) {
43 const double fac2 = std::pow(fac1, 2);
45 if constexpr (N > 1) {
46 V.template segment<3>(1) =
52 fac2 * a.dot(siteB.
Q().segment<3>(1));
55 const double fac3 = std::pow(fac1, 3);
56 if (N > 1 && rankB > 0) {
58 Eigen::Vector3d result =
59 -3 * a * (a.transpose() * siteB.
Q().segment<3>(1));
60 result += siteB.
Q().segment<3>(1);
62 V.template segment<3>(1) += result;
66 if (N > 4 || rankB > 1) {
67 const double sqr3 = std::sqrt(3);
71 Eigen::Matrix<double, 1, 5> Qq;
72 Qq(0) = 1.5 * r.
zz() - 0.5;
75 Qq(3) = 0.5 * (r.
xx() - r.
yy());
78 if constexpr (N > 4) {
79 V.template segment<5>(4) = fac3 * Qq.transpose() * siteB.
getCharge();
82 V(0) += fac3 * Qq * siteB.
Q().segment<5>(4);
85 if ((N > 4 || rankB > 0) || (N > 1 || rankB > 1)) {
87 Eigen::Matrix<double, 3, 5> dQ;
88 const double fac4 = std::pow(fac1, 4);
90 const Eigen::Vector3d afac = a * fac4;
92 dQ.col(0) = (1.5 - 7.5 * r.
zz()) * afac;
93 dQ.col(0).z() += 3 * afac.z();
95 dQ.col(1) = -5 * r.
xz() * afac;
96 dQ.col(1).z() += afac.x();
97 dQ.col(1).x() += afac.z();
99 dQ.col(2) = -5 * r.
yz() * afac;
100 dQ.col(2).z() += afac.y();
101 dQ.col(2).y() += afac.z();
103 dQ.col(3) = -2.5 * (r.
xx() - r.
yy()) * afac;
104 dQ.col(3).x() += afac.x();
105 dQ.col(3).y() -= afac.y();
107 dQ.col(4) = -5 * r.
xy() * afac;
108 dQ.col(4).y() += afac.x();
109 dQ.col(4).x() += afac.y();
111 dQ.rightCols<4>() *= sqr3;
113 if constexpr (N > 4) {
114 V.template segment<5>(4) += dQ.transpose() * siteB.
Q().segment<3>(1);
117 V.template segment<3>(1) -= dQ * siteB.
Q().segment<5>(4);
121 if (N > 4 && rankB > 1) {
124 Eigen::Matrix<double, 5, 5> QQ;
125 QQ(0, 0) = 0.75 * ((35 * r.
zz() - 30) * r.
zz() + 3);
126 double temp = 0.5 * sqr3 * (35 * r.
zz() - 15);
127 QQ(1, 0) = temp * r.
xz();
128 QQ(2, 0) = temp * r.
yz();
130 temp = 5 * (7 * r.
zz() - 1);
131 QQ(3, 0) = sqr3 * 0.25 * temp * (r.
xx() - r.
yy());
132 QQ(4, 0) = sqr3 * 0.5 * temp * r.
xy();
134 35 * r.
zz() * r.
xx() - 5 * (r.
xx() + r.
zz()) + 1;
135 QQ(2, 1) = r.
xy() * temp;
136 QQ(3, 1) = 0.5 * r.
xz() * (35 * (r.
xx() - r.
yy()) - 10);
137 QQ(4, 1) = r.
yz() * 5 * (7 * r.
xx() - 1);
139 5 * (7 * r.
yy() * r.
zz() - (r.
yy() + r.
zz())) + 1;
140 QQ(3, 2) = 0.5 * r.
yz() * (35 * (r.
xx() - r.
yy()) + 10);
141 QQ(4, 2) = r.
xz() * 5 * (7 * r.
yy() - 1);
142 QQ(3, 3) = 8.75 * std::pow(r.
xx() - r.
yy(), 2) - 5 * (r.
xx() + r.
yy()) +
144 QQ(4, 3) = 17.5 * r.
xy() * (r.
xx() - r.
yy());
146 5 * (7 * r.
xx() * r.
yy() - (r.
xx() + r.
yy())) + 1;
148 const double fac5 = std::pow(fac1, 5);
149 V.template segment<5>(4) +=
150 fac5 * QQ.selfadjointView<Eigen::Lower>() * siteB.
Q().segment<5>(4);
422 throw std::runtime_error(
423 "Cholesky_IntraSegment: segment " + seg.
getType() +
424 " has a charge response; it is solved with its region (PolarRegion)");
428 Eigen::MatrixXd A = Eigen::MatrixXd::Zero(size, size);
430 for (
Index j = 0; j < i; j++) {
436 A.block<3, 3>(3 * i, 3 * i) = seg[i].getPInv();
438 Eigen::VectorXd b = Eigen::VectorXd(size);
440 const Eigen::Vector3d
V = seg[i].V() + seg[i].V_noE();
441 b.segment<3>(3 * i) = -
V;
444 Eigen::LLT<Eigen::Ref<Eigen::MatrixXd>> lltOfA(A);
445 return lltOfA.solve(b);