104 const Eigen::VectorXd& v)
const {
107 using clock = std::chrono::steady_clock;
108 auto clk = []() {
return clock::now(); };
109 auto secs = [](clock::time_point a, clock::time_point b) {
110 return std::chrono::duration<double>(b - a).count();
113 auto t_phase = clk();
115 std::vector<std::pair<Index, PolarSite*>> targets;
116 targets.reserve(std::size_t(
size_ / 3));
118 for (std::size_t n = 0; n <
ids_.size(); ++n) {
121 for (
Index s = 0; s < segment.
size(); ++s) {
125 targets.push_back({
ids_[n], &site});
129 timings_.setup += secs(t_phase, clk());
140 const Index n_targets =
Index(targets.size());
141#pragma omp parallel for schedule(dynamic, 16)
142 for (
Index i = 0; i < n_targets; ++i) {
144 *targets[std::size_t(i)].second,
148 timings_.real_space += secs(t_phase, clk());
152 std::vector<PolarSite*> recip_targets;
153 recip_targets.reserve(targets.size());
154 for (
const auto& entry : targets) {
155 recip_targets.push_back(entry.second);
159 timings_.reciprocal += secs(t_phase, clk());
171 PolarSite shape_probe(-1,
"X", Eigen::Vector3d::Zero());
173 const Eigen::Vector3d shape_field = shape_probe.
V();
174 for (
const auto& entry : targets) {
175 entry.second->V() += shape_field;
179 timings_.shape += secs(t_phase, clk());
182 Eigen::VectorXd result(
size_);
183 for (std::size_t n = 0; n <
ids_.size(); ++n) {
187 for (
Index s = 0; s < segment.
size(); ++s) {
194 result.segment<3>(base + 3 * s) =
195 site.
getPInv() * v.segment<3>(base + 3 * s) - site.
V() -
202 timings_.assemble += secs(t_phase, clk());
205 Eigen::VectorXd intra = Eigen::VectorXd::Zero(
size_);
209 timings_.intra += secs(t_phase, clk());
214 const Eigen::VectorXd& v, Eigen::VectorXd& result)
const {
220#pragma omp parallel for schedule(dynamic, 4)
222 const std::size_t n = std::size_t(nn);
230 for (
Index i = 0; i < n_sites; ++i) {
232 for (
Index j = i + 1; j < n_sites; ++j) {
236 const Eigen::Vector3d r_vec = site_i.
getPos() - site_j.
getPos();
237 const double r = r_vec.norm();
255 const double c3 = t.
l3 * b.
B1 + (t.
l3 - 1.0) * berf.
B1;
256 const double c5 = t.
l5 * b.
B2 + (t.
l5 - 1.0) * berf.
B2;
257 Eigen::Matrix3d block =
258 c5 * (r_vec * r_vec.transpose()) - c3 * Eigen::Matrix3d::Identity();
259 result.segment<3>(base + 3 * i) += block * v.segment<3>(base + 3 * j);
260 result.segment<3>(base + 3 * j) +=
261 block.transpose() * v.segment<3>(base + 3 * i);
EwaldPeriodicDipoleOperator(EwaldRegistry ®istry, const EwaldRealSpaceSum &real_sum, const EwaldReciprocalSpaceSum &recip_sum, const EwaldShapeCorrection &shape, std::vector< Index > ids, double alpha_ewald, double thole_a)