ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
dp3m_heffte.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2025 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
24#include <config/config.hpp>
25
26#ifdef ESPRESSO_DP3M
27
29
30#include "ParticleRange.hpp"
31#include "communication.hpp"
34#include "p3m/common.hpp"
35#include "p3m/data_struct.hpp"
36#include "p3m/interpolation.hpp"
37
38#include <utils/Vector.hpp>
39
40#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
41#include <Kokkos_Core.hpp>
42#include <omp.h>
43#endif
44
45#include <complex>
46#include <cstddef>
47#include <memory>
48#include <optional>
49#include <stdexcept>
50#include <type_traits>
51#include <utility>
52#include <vector>
53
54#ifdef ESPRESSO_ADDITIONAL_CHECKS
55#define ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
56#endif
57
58template <typename FloatType, class FFTConfig> class P3MFFT;
59
60/**
61 * @brief Base class for the magnetostatics P3M algorithm.
62 * Contains a handle to the FFT backend, information about the local
63 * mesh, the differential operator, and various buffers.
64 */
65template <typename FloatType, class FFTConfig>
66struct DipolarP3MState : public P3MStateCommon<FloatType> {
67 using value_type = FloatType;
68 using ComplexType = std::complex<FloatType>;
69 using P3MStateCommon<FloatType>::P3MStateCommon;
70 using P3MStateCommon<FloatType>::local_mesh;
71
72 /** number of dipolar particles. */
73 std::size_t sum_dip_part = 0;
74 /** Sum of square of magnetic dipoles. */
75 double sum_mu2 = 0.;
76
77 /** position shift for calculation of first assignment mesh point. */
78 double pos_shift = 0.;
79
80 /** cached k-space self-energy correction */
81 double energy_correction = 0.;
82 /** k-space scalar mesh for k-space calculations. */
83 std::vector<ComplexType> ks_scalar;
84
86
88
89 /** @brief FFT algorithm. */
90 std::unique_ptr<FFTBackend<FloatType>> fft;
91 /** @brief FFT buffers. */
92 std::unique_ptr<FFTBuffers<FloatType>> fft_buffers;
93
95 auto const mesh_size_ptr = fft->get_mesh_size();
96 auto const mesh_start_ptr = fft->get_mesh_start();
97 for (auto i = 0u; i < 3u; ++i) {
98 mesh.size[i] = mesh_size_ptr[i];
99 mesh.start[i] = mesh_start_ptr[i];
100 }
101 mesh.stop = mesh.start + mesh.size;
102 fft_buffers->update_mesh_views(mesh);
103 }
104
105 template <typename T, class... Args> void make_fft_instance(Args... args) {
106 assert(fft == nullptr);
107 fft = std::make_unique<T>(std::as_const(local_mesh), args...);
108 }
109
110 template <typename T, class... Args> void make_mesh_instance(Args... args) {
111 assert(fft_buffers == nullptr);
112 fft_buffers = std::make_unique<T>(std::as_const(local_mesh), args...);
113 }
114
115#ifdef ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
116 struct {
117 /** dipole density in real-space with halo */
118 std::array<std::vector<FloatType>, 3u> rs_dipole_density;
119 /** dipole density in k-space without halo */
120 std::array<std::vector<ComplexType>, 3u> ks_dipole_density;
121 /** magnetic fields in real-space with halo */
122 std::array<std::vector<FloatType>, 3> rs_B_fields;
123 /** magnetic fields in k-space without halo */
124 std::vector<ComplexType> ks_B_field_storage;
125 /** magnetic fields in real-space without halo */
126 std::array<std::vector<FloatType>, 3u> rs_B_fields_no_halo;
127 /** k-space workspace without halo */
128 std::vector<ComplexType> ks_scalar;
129 /** @brief Force optimised influence function (k-space) */
130 std::vector<FloatType> g_force;
131 /** @brief Energy optimised influence function (k-space) */
132 std::vector<FloatType> g_energy;
134 std::shared_ptr<P3MFFT<FloatType, FFTConfig>> fft;
138#endif // ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
139
140#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
143
144 void init_labels() {
145 assert(ks_scalar.empty());
146#ifdef ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
147 assert(heffte.rs_dipole_density[0u].empty());
148 assert(heffte.rs_dipole_density[1u].empty());
149 assert(heffte.rs_dipole_density[2u].empty());
150#endif // ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
152 "DipolarP3MState::rs_fields_kokkos", 0, 0, 0);
153 }
154#endif // ESPRESSO_SHARED_MEMORY_PARALLELISM
155};
156
157template <typename FloatType, Arch Architecture, class FFTConfig>
159 ~DipolarP3MHeffte() override = default;
160
161 // heFFTe checks are only implemented for row-major data
162 static_assert(FFTConfig::r_space_order == Utils::MemoryOrder::ROW_MAJOR);
163 static_assert(FFTConfig::k_space_order == Utils::MemoryOrder::ROW_MAJOR);
164
166 /** @brief Dipolar P3M parameters. */
168
169private:
170#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
171 // kokkos handle must outlive kokkos data structures from other class members
172 std::shared_ptr<KokkosHandle> m_kokkos_handle;
173#endif
174 /** @brief Dipolar P3M meshes and FFT algorithm. */
175 std::unique_ptr<DipolarP3MStateClass> dp3m_impl;
176 TuningParameters tuning;
177 bool m_is_tuned;
178
179public:
180 DipolarP3MHeffte(std::unique_ptr<DipolarP3MStateClass> &&dp3m_state,
184 m_kokkos_handle{::kokkos_handle},
185#endif
186 dp3m_impl{std::move(dp3m_state)}, tuning{std::move(tuning_params)} {
187
188 if (tuning.timings <= 0) {
189 throw std::domain_error("Parameter 'timings' must be > 0");
190 }
192 throw std::domain_error("DipolarP3M requires a cubic mesh");
193 }
194 m_is_tuned = not dp3m.params.tuning;
195 dp3m.params.tuning = false;
197#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
199#endif
200 }
201
202 void init() override {
203 if constexpr (Architecture == Arch::CPU) {
205 }
206 }
207 void tune() override;
208 void count_magnetic_particles() override;
209
210 [[nodiscard]] bool is_tuned() const noexcept override { return m_is_tuned; }
211 [[nodiscard]] bool is_gpu() const noexcept override {
212 return Architecture != Arch::CPU;
213 }
215 return std::is_same_v<FloatType, double>;
216 }
217
218 void on_activation() override {
220 tune();
221 }
222
223 double long_range_energy(ParticleRange const &particles) override {
224 return long_range_kernel(false, true, particles);
225 }
226
227 void add_long_range_forces(ParticleRange const &particles) override {
228 if constexpr (Architecture == Arch::CPU) {
229 long_range_kernel(true, false, particles);
230 }
231 }
232
233 void dipole_assign(ParticleRange const &particles) override;
234
235private:
236 void prepare_fft_mesh() {
238#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
239 using execution_space = Kokkos::DefaultExecutionSpace;
240 auto const num_threads = execution_space().concurrency();
241 Kokkos::realloc(Kokkos::WithoutInitializing, dp3m.rs_fields_kokkos,
243 Kokkos::deep_copy(dp3m.rs_fields_kokkos, FloatType{0});
244#endif // ESPRESSO_SHARED_MEMORY_PARALLELISM
245 for (auto &rs_mesh_field : dp3m.mesh.rs_fields) {
246 std::ranges::fill(rs_mesh_field, FloatType{0});
247 }
248#ifdef ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
249 for (auto dir : {0u, 1u, 2u}) {
251 std::ranges::fill(dp3m.heffte.rs_dipole_density[dir], FloatType{0});
252 }
253#endif // ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
254 }
255
256protected:
257 /** Compute the k-space part of forces and energies. */
258 double long_range_kernel(bool force_flag, bool energy_flag,
259 ParticleRange const &particles);
260 double calc_average_self_energy_k_space() const override;
261 void calc_energy_correction() override;
262 void calc_influence_function_force() override;
263 void calc_influence_function_energy() override;
264 double calc_surface_term(bool force_flag, bool energy_flag,
265 ParticleRange const &particles) override;
266 void init_cpu_kernels();
267 void scaleby_box_l() override;
268#ifdef ESPRESSO_NPT
269 void npt_add_virial_contribution(double energy) const override;
270#endif
271};
272
273#endif // ESPRESSO_DP3M
Vector implementation and trait types for boost qvm interoperability.
void set_prefactor(double new_prefactor)
double prefactor
Magnetostatics prefactor.
FFT manager.
Definition P3MFFT.hpp:38
A range of particles.
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value) noexcept
Create a vector that has all entries set to the same value.
Definition Vector.hpp:132
Cache for interpolation weights.
void reset(int cao)
Reset the cache.
P3M halo communicator.
Definition send_mesh.hpp:38
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
std::shared_ptr< KokkosHandle > kokkos_handle
P3M algorithm for long-range magnetic dipole-dipole interaction.
Definition fft.cpp:78
STL namespace.
Common functions for dipolar and charge P3M.
static SteepestDescentParameters params
Currently active steepest descent instance.
bool is_double_precision() const noexcept override
void npt_add_virial_contribution(double energy) const override
DipolarP3MHeffte(std::unique_ptr< DipolarP3MStateClass > &&dp3m_state, TuningParameters tuning_params, double prefactor)
void init() override
double long_range_energy(ParticleRange const &particles) override
double long_range_kernel(bool force_flag, bool energy_flag, ParticleRange const &particles)
Compute the k-space part of forces and energies.
~DipolarP3MHeffte() override=default
double calc_surface_term(bool force_flag, bool energy_flag, ParticleRange const &particles) override
void calc_influence_function_energy() override
void scaleby_box_l() override
void calc_influence_function_force() override
void count_magnetic_particles() override
void add_long_range_forces(ParticleRange const &particles) override
DipolarP3MStateClass & dp3m
Dipolar P3M parameters.
void on_activation() override
double calc_average_self_energy_k_space() const override
void dipole_assign(ParticleRange const &particles) override
void calc_energy_correction() override
bool is_gpu() const noexcept override
bool is_tuned() const noexcept override
Base class for the magnetostatics P3M algorithm.
std::vector< FloatType > g_force
Force optimised influence function (k-space)
std::vector< ComplexType > ks_B_field_storage
magnetic fields in k-space without halo
double sum_mu2
Sum of square of magnetic dipoles.
p3m_interpolation_cache inter_weights
std::complex< FloatType > ComplexType
std::array< std::vector< FloatType >, 3 > rs_B_fields
magnetic fields in real-space with halo
FloatType value_type
std::size_t sum_dip_part
number of dipolar particles.
std::unique_ptr< FFTBackend< FloatType > > fft
FFT algorithm.
void update_mesh_views()
P3MFFTMesh< FloatType > mesh
std::array< std::vector< FloatType >, 3u > rs_dipole_density
dipole density in real-space with halo
p3m_send_mesh< FloatType > halo_comm
std::vector< FloatType > g_energy
Energy optimised influence function (k-space)
std::unique_ptr< FFTBuffers< FloatType > > fft_buffers
FFT buffers.
std::array< std::vector< FloatType >, 3u > rs_B_fields_no_halo
magnetic fields in real-space without halo
double pos_shift
position shift for calculation of first assignment mesh point.
void make_fft_instance(Args... args)
double energy_correction
cached k-space self-energy correction
std::vector< ComplexType > ks_scalar
k-space scalar mesh for k-space calculations.
std::shared_ptr< P3MFFT< FloatType, FFTConfig > > fft
void resize_heffte_buffers()
struct DipolarP3MState::@1 heffte
Kokkos::View< FloatType ***, Kokkos::LayoutRight, Kokkos::HostSpace > rs_fields_kokkos
std::array< std::vector< ComplexType >, 3u > ks_dipole_density
dipole density in k-space without halo
void make_mesh_instance(Args... args)
Dipolar P3M solver.
Definition dp3m.hpp:55
void sanity_checks() const
Definition dp3m.hpp:79
Local mesh FFT buffers.
std::size_t size
number of local mesh points including halo layers.
int cao
charge assignment order ([0,7]).
bool tuning
tuning or production?
Utils::Vector3i mesh
number of mesh points per coordinate direction (>0), in real space.
State of the p3m methods, the part which applies to both, electrostatic and dipolar p3m.
P3MParameters params
P3M base parameters.
P3MLocalMesh local_mesh
Local mesh geometry information for this MPI rank.