121 const Eigen::VectorXd& v)
const {
126 using clock = std::chrono::steady_clock;
127 auto clk = []() {
return clock::now(); };
128 auto secs = [](clock::time_point a, clock::time_point b) {
129 return std::chrono::duration<double>(b - a).count();
132 auto t_phase = clk();
134 std::vector<std::pair<Index, PolarSite*>> targets;
135 targets.reserve(std::size_t(
size_ / 3));
137 for (std::size_t n = 0; n <
ids_.size(); ++n) {
140 for (
Index s = 0; s < segment.
size(); ++s) {
144 targets.push_back({
ids_[n], &site});
148 timings_.setup += secs(t_phase, clk());
161 const Index n_targets =
Index(targets.size());
162#pragma omp parallel for schedule(dynamic, 16)
163 for (
Index i = 0; i < n_targets; ++i) {
165 *targets[std::size_t(i)].second,
172 timings_.real_space += secs(t_phase, clk());
176 std::vector<PolarSite*> recip_targets;
177 recip_targets.reserve(targets.size());
178 for (
const auto& entry : targets) {
179 recip_targets.push_back(entry.second);
183 timings_.reciprocal += secs(t_phase, clk());
209 PolarSite shape_probe(-1,
"X", Eigen::Vector3d::Zero());
211 const Eigen::Vector3d shape_field = shape_probe.
V();
212 for (
const auto& entry : targets) {
213 entry.second->V() += shape_field;
217 timings_.shape += secs(t_phase, clk());
220 Eigen::VectorXd result(
size_);
221 for (std::size_t n = 0; n <
ids_.size(); ++n) {
225 for (
Index s = 0; s < segment.
size(); ++s) {
254 result.segment<3>(base + 3 * s) =
255 site.
getPInv() * v.segment<3>(base + 3 * s) - site.
V() -
265 timings_.assemble += secs(t_phase, clk());
268 Eigen::VectorXd intra = Eigen::VectorXd::Zero(
size_);
272 timings_.intra += secs(t_phase, clk());
277 const Eigen::VectorXd& v, Eigen::VectorXd& result)
const {
300 for (std::size_t n = 0; n <
ids_.size(); ++n) {
308 for (
Index i = 0; i < n_sites; ++i) {
310 for (
Index j = i + 1; j < n_sites; ++j) {
316 const Eigen::Vector3d r_vec = site_i.
getPos() - site_j.
getPos();
317 const double r = r_vec.norm();
357 const double c3 = t.
l3 * b.
B1 + (t.
l3 - 1.0) * berf.
B1;
358 const double c5 = t.
l5 * b.
B2 + (t.
l5 - 1.0) * berf.
B2;
359 Eigen::Matrix3d block =
360 c5 * (r_vec * r_vec.transpose()) - c3 * Eigen::Matrix3d::Identity();
361 result.segment<3>(base + 3 * i) += block * v.segment<3>(base + 3 * j);
362 result.segment<3>(base + 3 * j) +=
363 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)