24#ifdef ESPRESSO_DIPOLES
30#include "communication.hpp"
32#include "system/System.hpp"
38#include <boost/mpi/collectives.hpp>
39#include <boost/mpi/communicator.hpp>
64 auto const pe2 =
m1 * d;
65 auto const pe3 =
m2 * d;
68 auto const r = std::sqrt(
r2);
69 auto const r5 =
r2 *
r2 * r;
72 auto const a = 3.0 * (
m1 *
m2) /
r5;
73 auto const b = -15.0 *
pe2 *
pe3 /
r7;
75 auto const f = (a + b) * d + 3.0 * (
pe3 *
m1 +
pe2 *
m2) /
r5;
76 auto const r3 =
r2 * r;
94 auto const r2 = d * d;
95 auto const r = sqrt(
r2);
96 auto const r3 =
r2 * r;
100 auto const pe2 =
m1 * d;
101 auto const pe3 =
m2 * d;
106#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
117 auto const r2 = d * d;
118 auto const r = sqrt(
r2);
119 auto const r3 =
r2 * r;
121 auto const pe2 =
m1 * d;
151 [&](
int nx,
int ny,
int nz) {
156 std::views::iota(-
ncut[0],
ncut[0] + 1),
157 std::views::iota(-
ncut[1],
ncut[1] + 1),
158 std::views::iota(-
ncut[2],
ncut[2] + 1));
198template <
class InputIterator,
class T,
class F>
204 for (
auto jt = begin;
jt != end; ++
jt) {
207 ? (
it->pos -
jt->pos)
215 init += f(
rn,
jt->m);
226 std::vector<Particle *> local_particles;
229 std::vector<boost::mpi::request>
reqs;
231 local_particles.reserve(particles.
size());
234 for (
auto &p : particles) {
235 if (p.dipm() != 0.0) {
236 local_particles.emplace_back(&p);
251 if (comm.size() > 1) {
259 return std::make_tuple(std::move(local_particles), std::move(
all_posmom),
260 std::move(
reqs), offset);
265 static_cast<int>(box_geo.
periodic(1)),
266 static_cast<int>(box_geo.
periodic(2))};
294 auto const &box_geo = *
system.box_geo;
295 auto const &
box_l = box_geo.length();
296 auto const particles =
system.cell_structure->local_particles();
310 auto p = local_particles.begin();
322 auto q = std::next(p);
325 : box_geo.get_mi_vector(
it->pos,
jt->pos);
350 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
353 p = local_particles.begin();
362 return pair_force(rn, it->m, mj);
369 return pair_force(rn, it->m, mj);
375#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
390 auto const &box_geo = *
system.box_geo;
391 auto const particles =
system.cell_structure->local_particles();
400 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
411 return pair_potential(rn, it->m, mj);
427#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
431 auto const &box_geo = *
system.box_geo;
432 auto const particles =
system.cell_structure->local_particles();
440 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
447 auto p = local_particles.
begin();
452 return dipole_field(rn, mj);
464 throw std::domain_error(
"Parameter 'n_replicas' must be >= 0");
Vector implementation and trait types for boost qvm interoperability.
This file contains everything related to the global cell structure / cell system.
ESPRESSO_ATTR_ALWAYS_INLINE Utils::Vector3< T > get_mi_vector(Utils::Vector3< T > const &a, Utils::Vector3< T > const &b) const
Get the minimum-image vector between two coordinates.
auto folded_position(Utils::Vector3d const &pos) const
Calculate coordinates folded to primary simulation box.
Utils::Vector3d const & length() const
Box length.
constexpr bool periodic(unsigned coord) const
Check periodicity in direction.
void set_prefactor(double new_prefactor)
double prefactor
Magnetostatics prefactor.
base_type::size_type size() const
DEVICE_QUALIFIER constexpr iterator begin() noexcept
constexpr T norm2() const
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
boost::mpi::communicator comm_cart
The communicator.
T image_sum(InputIterator begin, InputIterator end, InputIterator it, bool with_replicas, Utils::Vector3i const &ncut, BoxGeometry const &box_geo, T init, F f)
Sum over all pairs with periodic images.
void for_each_image(Utils::Vector3i const &ncut, F f)
Call kernel for every 3d index in a sphere around the origin.
static auto dipole_field(Utils::Vector3d const &d, Utils::Vector3d const &m1)
Dipole field contribution from a particle with dipole moment m1 at a distance d.
static auto pair_potential(Utils::Vector3d const &d, Utils::Vector3d const &m1, Utils::Vector3d const &m2)
Pair potential for two interacting dipoles.
static auto gather_particle_data(BoxGeometry const &box_geo, ParticleRange const &particles)
static auto get_n_cut(BoxGeometry const &box_geo, int n_replicas)
static auto pair_force(Utils::Vector3d const &d, Utils::Vector3d const &m1, Utils::Vector3d const &m2)
Pair force of two interacting dipoles.
__device__ void vector_product(float const *a, float const *b, float *out)
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
auto iall_gatherv(boost::mpi::communicator const &comm, T const *in_values, int in_size, T *out_values, int const *sizes)
void cartesian_product(const Body &op, const ForwardRange &...rng)
Call op with each element of the Cartesian product set of rng.
double long_range_energy_cpu() const
Calculate the interaction potential.
void dipole_field_at_part_cpu() const
Calculate total dipole field of each particle.
DipolarDirectSum(double prefactor, int n_replicas, bool gpu)
void add_long_range_forces_cpu() const
Calculate and add the interaction forces/torques to the particles.
Force information on a particle.
Position and dipole moment of one particle.
void serialize(Archive &ar, long int)