122 const Eigen::VectorXd& v)
const {
127 using clock = std::chrono::steady_clock;
128 auto clk = []() {
return clock::now(); };
129 auto secs = [](clock::time_point a, clock::time_point b) {
130 return std::chrono::duration<double>(b - a).count();
133 auto t_phase = clk();
135 std::vector<std::pair<Index, PolarSite*>> targets;
136 targets.reserve(std::size_t(
size_ / 3));
138 for (std::size_t n = 0; n <
ids_.size(); ++n) {
141 for (
Index s = 0; s < segment.
size(); ++s) {
145 targets.push_back({
ids_[n], &site});
149 timings_.setup += secs(t_phase, clk());
162 const Index n_targets =
Index(targets.size());
163#pragma omp parallel for schedule(dynamic, 16)
164 for (
Index i = 0; i < n_targets; ++i) {
166 *targets[std::size_t(i)].second,
173 timings_.real_space += secs(t_phase, clk());
177 std::vector<PolarSite*> recip_targets;
178 recip_targets.reserve(targets.size());
179 for (
const auto& entry : targets) {
180 recip_targets.push_back(entry.second);
184 timings_.reciprocal += secs(t_phase, clk());
210 PolarSite shape_probe(-1,
"X", Eigen::Vector3d::Zero());
212 const Eigen::Vector3d shape_field = shape_probe.
V();
213 for (
const auto& entry : targets) {
214 entry.second->V() += shape_field;
218 timings_.shape += secs(t_phase, clk());
221 Eigen::VectorXd result(
size_);
222 for (std::size_t n = 0; n <
ids_.size(); ++n) {
226 for (
Index s = 0; s < segment.
size(); ++s) {
255 result.segment<3>(base + 3 * s) =
256 site.
getPInv() * v.segment<3>(base + 3 * s) - site.
V() -
266 timings_.assemble += secs(t_phase, clk());
269 Eigen::VectorXd intra = Eigen::VectorXd::Zero(
size_);
273 timings_.intra += secs(t_phase, clk());
278 const Eigen::VectorXd& v, Eigen::VectorXd& result)
const {
302#pragma omp parallel for schedule(dynamic, 4)
304 const std::size_t n = std::size_t(nn);
312 for (
Index i = 0; i < n_sites; ++i) {
314 for (
Index j = i + 1; j < n_sites; ++j) {
320 const Eigen::Vector3d r_vec = site_i.
getPos() - site_j.
getPos();
321 const double r = r_vec.norm();
361 const double c3 = t.
l3 * b.
B1 + (t.
l3 - 1.0) * berf.
B1;
362 const double c5 = t.
l5 * b.
B2 + (t.
l5 - 1.0) * berf.
B2;
363 Eigen::Matrix3d block =
364 c5 * (r_vec * r_vec.transpose()) - c3 * Eigen::Matrix3d::Identity();
365 result.segment<3>(base + 3 * i) += block * v.segment<3>(base + 3 * j);
366 result.segment<3>(base + 3 * j) +=
367 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)