24#ifdef ESPRESSO_DIPOLES
31#include "communication.hpp"
34#include "system/System.hpp"
36#include <Kokkos_Core.hpp>
37#include <Kokkos_ScatterView.hpp>
43#include <boost/mpi/collectives.hpp>
44#include <boost/mpi/communicator.hpp>
71 std::vector<Particle *> local_particles;
74 std::vector<boost::mpi::request>
reqs;
76 local_particles.reserve(particles.
size());
79 for (
auto &p : particles) {
80 if (p.dipm() != 0.0) {
81 local_particles.emplace_back(&p);
96 if (comm.size() > 1) {
104 return std::make_tuple(std::move(local_particles), std::move(
all_posmom),
105 std::move(
reqs), offset);
110 static_cast<int>(box_geo.
periodic(1)),
111 static_cast<int>(box_geo.
periodic(2))};
118static std::vector<Utils::Vector3d>
121 std::vector<Utils::Vector3d>
shifts;
122 shifts.push_back({0., 0., 0.});
126 if (
nx == 0 &&
ny == 0 &&
nz == 0)
159 auto const &box_geo = *
system.box_geo;
160 auto const &
box_l = box_geo.length();
161 auto const particles =
system.cell_structure->local_particles();
171 auto const n_local = local_particles.size();
181 using memory_space = Kokkos::HostSpace;
182 using execution_space = Kokkos::DefaultHostExecutionSpace;
184 Kokkos::View<double *[3], Kokkos::LayoutRight, Kokkos::HostSpace>;
186 Kokkos::Experimental::ScatterView<
double *[3], Kokkos::LayoutRight,
202 Kokkos::RangePolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>
205 Kokkos::parallel_for(
206 "dds_local_pairs",
policy_local, [=](std::size_t
const i) {
207 auto const gi = offset + i;
213 for (std::size_t s = 1; s <
n_shifts; ++s)
222 auto const &
m_j =
pm[
j].m;
225 auto const jl =
j - offset;
226 for (std::size_t s = 0; s <
n_shifts; ++s) {
230 fi.torque +=
pf.torque;
234 for (
int c = 0; c < 3; ++c) {
247 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
252 Kokkos::parallel_for(
253 "dds_remote_pairs",
policy_remote, [=](std::size_t
const i) {
254 auto const gi = offset + i;
262 std::size_t
const ranges[2][2] = {{std::size_t{0}, offset},
269 auto const &
m_j =
pm[
j].m;
272 for (std::size_t s = 0; s <
n_shifts; ++s) {
276 fi.torque +=
pf.torque;
286 Kokkos::Experimental::contribute(local_force,
scatter_force);
289 Kokkos::parallel_for(
306 if (
system.has_npt_enabled()) {
312#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
327 auto const &box_geo = *
system.box_geo;
328 auto const &
box_l = box_geo.length();
329 auto const particles =
system.cell_structure->local_particles();
339 auto const n_local = local_particles.size();
347 using execution_space = Kokkos::DefaultHostExecutionSpace;
358 Kokkos::RangePolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>
361 Kokkos::parallel_reduce(
363 [=](std::size_t
const i,
double &
u_local) {
364 auto const gi = offset + i;
369 for (std::size_t s = 1; s <
n_shifts; ++s)
375 auto const &
m_j =
pm[
j].m;
378 for (std::size_t s = 0; s <
n_shifts; ++s)
387 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
393 Kokkos::parallel_reduce(
395 [=](std::size_t
const i,
double &
u_local) {
396 auto const gi = offset + i;
402 auto const &
m_j =
pm[
j].m;
405 for (std::size_t s = 0; s <
n_shifts; ++s)
425 "DipolarDirectSum on GPU.";
430 auto const &box_geo = *
system.box_geo;
431 auto const &
box_l = box_geo.length();
432 auto const particles =
system.cell_structure->local_particles();
442 auto const n_local = local_particles.size();
450 using execution_space = Kokkos::DefaultHostExecutionSpace;
464 Kokkos::RangePolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>
470 auto reducerA = Reduction::make_kokkos_reducer<Utils::Vector9d>(
473 auto const gi = offset + i;
478 for (std::size_t s = 1; s <
n_shifts; ++s) {
487 auto const &
m_j =
pm[
j].m;
490 for (std::size_t s = 0; s <
n_shifts; ++s) {
503 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
509 auto reducerB = Reduction::make_kokkos_reducer<Utils::Vector9d>(
512 auto const gi = offset + i;
517 auto const &
m_j =
pm[
j].m;
520 for (std::size_t s = 0; s <
n_shifts; ++s) {
542#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
546 auto const &box_geo = *
system.box_geo;
547 auto const &
box_l = box_geo.length();
548 auto const particles =
system.cell_structure->local_particles();
558 auto const n_local = local_particles.size();
566 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
572 using execution_space = Kokkos::DefaultHostExecutionSpace;
579 Kokkos::RangePolicy<execution_space> policy(std::size_t{0},
n_local);
580 Kokkos::parallel_for(
"dds_dipole_field", policy, [=](std::size_t
const i) {
581 auto const gi = offset + i;
587 for (std::size_t s = 1; s <
n_shifts; ++s)
598 auto const &
m_j =
pm[
j].m;
601 for (std::size_t s = 0; s <
n_shifts; ++s)
616 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.
auto folded_position(Utils::Vector3d const &pos) const noexcept
Calculate coordinates folded to primary simulation box.
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
constexpr T norm2() const
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
boost::mpi::communicator comm_cart
The communicator.
static std::vector< Utils::Vector3d > make_image_shifts(Utils::Vector3i const &ncut, Utils::Vector3d const &box_l)
Real-space image shifts n x box_l inside the |ncut| sphere.
static auto gather_particle_data(BoxGeometry const &box_geo, ParticleRange const &particles)
static auto get_n_cut(BoxGeometry const &box_geo, int n_replicas)
__device__ void vector_product(float const *a, float const *b, float *out)
Utils::Vector3d dipole_field(Utils::Vector3d const &d, Utils::Vector3d const &m1)
Dipole field contribution from a dipole m1 at distance d.
PairForce pair_force(Utils::Vector3d const &d, Utils::Vector3d const &m1, Utils::Vector3d const &m2)
Pair force of two interacting dipoles (see dipolar_direct_sum.cpp).
double pair_potential(Utils::Vector3d const &d, Utils::Vector3d const &m1, Utils::Vector3d const &m2)
Pair potential for two interacting dipoles.
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
#define runtimeWarningMsg()
auto iall_gatherv(boost::mpi::communicator const &comm, T const *in_values, int in_size, T *out_values, int const *sizes)
void flatten(Range const &v, OutputIterator out)
Flatten a range of ranges.
Matrix< T, N, M > tensor_product(const Vector< T, N > &x, const Vector< T, M > &y)
double long_range_energy_cpu() const
Calculate the interaction potential.
void dipole_field_at_part_cpu() const
Calculate total dipole field of each particle.
Utils::Vector9d long_range_pressure() const
Calculate the dipolar pressure tensor.
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 and torque of one pair interaction.
Position and dipole moment of one particle.
void serialize(Archive &ar, long int)