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 execution_space = Kokkos::DefaultExecutionSpace;
183 Kokkos::View<double *[3], Kokkos::LayoutRight, Kokkos::HostSpace>;
185 Kokkos::Experimental::ScatterView<double *[3], Kokkos::LayoutRight>;
200 Kokkos::RangePolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>
203 Kokkos::parallel_for(
204 "dds_local_pairs",
policy_local, [=](std::size_t
const i) {
205 auto const gi = offset + i;
211 for (std::size_t s = 1; s <
n_shifts; ++s)
220 auto const &
m_j =
pm[
j].m;
223 auto const jl =
j - offset;
224 for (std::size_t s = 0; s <
n_shifts; ++s) {
228 fi.torque +=
pf.torque;
232 for (
int c = 0; c < 3; ++c) {
245 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
250 Kokkos::parallel_for(
251 "dds_remote_pairs",
policy_remote, [=](std::size_t
const i) {
252 auto const gi = offset + i;
260 std::size_t
const ranges[2][2] = {{std::size_t{0}, offset},
267 auto const &
m_j =
pm[
j].m;
270 for (std::size_t s = 0; s <
n_shifts; ++s) {
274 fi.torque +=
pf.torque;
284 Kokkos::Experimental::contribute(local_force,
scatter_force);
287 Kokkos::parallel_for(
304 if (
system.has_npt_enabled()) {
310#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
325 auto const &box_geo = *
system.box_geo;
326 auto const &
box_l = box_geo.length();
327 auto const particles =
system.cell_structure->local_particles();
337 auto const n_local = local_particles.size();
345 using execution_space = Kokkos::DefaultExecutionSpace;
356 Kokkos::RangePolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>
359 Kokkos::parallel_reduce(
361 [=](std::size_t
const i,
double &
u_local) {
362 auto const gi = offset + i;
367 for (std::size_t s = 1; s <
n_shifts; ++s)
373 auto const &
m_j =
pm[
j].m;
376 for (std::size_t s = 0; s <
n_shifts; ++s)
385 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
391 Kokkos::parallel_reduce(
393 [=](std::size_t
const i,
double &
u_local) {
394 auto const gi = offset + i;
400 auto const &
m_j =
pm[
j].m;
403 for (std::size_t s = 0; s <
n_shifts; ++s)
423 "DipolarDirectSum on GPU.";
428 auto const &box_geo = *
system.box_geo;
429 auto const &
box_l = box_geo.length();
430 auto const particles =
system.cell_structure->local_particles();
440 auto const n_local = local_particles.size();
448 using execution_space = Kokkos::DefaultExecutionSpace;
462 Kokkos::RangePolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>
468 auto reducerA = Reduction::make_kokkos_reducer<Utils::Vector9d>(
471 auto const gi = offset + i;
476 for (std::size_t s = 1; s <
n_shifts; ++s) {
485 auto const &
m_j =
pm[
j].m;
488 for (std::size_t s = 0; s <
n_shifts; ++s) {
501 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
507 auto reducerB = Reduction::make_kokkos_reducer<Utils::Vector9d>(
510 auto const gi = offset + i;
515 auto const &
m_j =
pm[
j].m;
518 for (std::size_t s = 0; s <
n_shifts; ++s) {
540#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
544 auto const &box_geo = *
system.box_geo;
545 auto const &
box_l = box_geo.length();
546 auto const particles =
system.cell_structure->local_particles();
556 auto const n_local = local_particles.size();
564 boost::mpi::wait_all(
reqs.begin(),
reqs.end());
570 using execution_space = Kokkos::DefaultExecutionSpace;
577 Kokkos::RangePolicy<execution_space> policy(std::size_t{0},
n_local);
578 Kokkos::parallel_for(
"dds_dipole_field", policy, [=](std::size_t
const i) {
579 auto const gi = offset + i;
585 for (std::size_t s = 1; s <
n_shifts; ++s)
596 auto const &
m_j =
pm[
j].m;
599 for (std::size_t s = 0; s <
n_shifts; ++s)
614 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
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)