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 "communication.hpp"
33#include "p3m/common.hpp"
34#include "p3m/data_struct.hpp"
35#include "p3m/interpolation.hpp"
36
37#include <utils/Vector.hpp>
38
39#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
40#include <Kokkos_Core.hpp>
41#include <omp.h>
42#endif
43
44#include <complex>
45#include <cstddef>
46#include <memory>
47#include <optional>
48#include <stdexcept>
49#include <type_traits>
50#include <utility>
51#include <vector>
52
53#ifdef ESPRESSO_ADDITIONAL_CHECKS
54#define ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
55#endif
56
57template <typename FloatType, class FFTConfig> class P3MFFT;
58
59/**
60 * @brief Base class for the magnetostatics P3M algorithm.
61 * Contains a handle to the FFT backend, information about the local
62 * mesh, the differential operator, and various buffers.
63 */
64template <typename FloatType, class FFTConfig>
65struct DipolarP3MState : public P3MStateCommon<FloatType> {
66 using value_type = FloatType;
67 using ComplexType = std::complex<FloatType>;
68 using P3MStateCommon<FloatType>::P3MStateCommon;
69 using P3MStateCommon<FloatType>::local_mesh;
70
71 /** number of dipolar particles. */
72 std::size_t sum_dip_part = 0;
73 /** Sum of square of magnetic dipoles. */
74 double sum_mu2 = 0.;
75
76 /** position shift for calculation of first assignment mesh point. */
77 double pos_shift = 0.;
78
79 /** cached k-space self-energy correction */
80 double energy_correction = 0.;
81 /** k-space scalar mesh for k-space calculations. */
82 std::vector<ComplexType> ks_scalar;
83
85
87
88 /** @brief FFT algorithm. */
89 std::unique_ptr<FFTBackend<FloatType>> fft;
90 /** @brief FFT buffers. */
91 std::unique_ptr<FFTBuffers<FloatType>> fft_buffers;
92
94 auto const mesh_size_ptr = fft->get_mesh_size();
95 auto const mesh_start_ptr = fft->get_mesh_start();
96 for (auto i = 0u; i < 3u; ++i) {
97 mesh.size[i] = mesh_size_ptr[i];
98 mesh.start[i] = mesh_start_ptr[i];
99 }
100 mesh.stop = mesh.start + mesh.size;
101 fft_buffers->update_mesh_views(mesh);
102 }
103
104 template <typename T, class... Args> void make_fft_instance(Args... args) {
105 assert(fft == nullptr);
106 fft = std::make_unique<T>(std::as_const(local_mesh), args...);
107 }
108
109 template <typename T, class... Args> void make_mesh_instance(Args... args) {
110 assert(fft_buffers == nullptr);
111 fft_buffers = std::make_unique<T>(std::as_const(local_mesh), args...);
112 }
113
114#ifdef ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
115 struct {
116 /** dipole density in real-space with halo */
117 std::array<std::vector<FloatType>, 3u> rs_dipole_density;
118 /** dipole density in k-space without halo */
119 std::array<std::vector<ComplexType>, 3u> ks_dipole_density;
120 /** magnetic fields in real-space with halo */
121 std::array<std::vector<FloatType>, 3> rs_B_fields;
122 /** magnetic fields in k-space without halo */
123 std::vector<ComplexType> ks_B_field_storage;
124 /** magnetic fields in real-space without halo */
125 std::array<std::vector<FloatType>, 3u> rs_B_fields_no_halo;
126 /** k-space workspace without halo */
127 std::vector<ComplexType> ks_scalar;
128 /** @brief Force optimised influence function (k-space) */
129 std::vector<FloatType> g_force;
130 /** @brief Energy optimised influence function (k-space) */
131 std::vector<FloatType> g_energy;
133 std::shared_ptr<P3MFFT<FloatType, FFTConfig>> fft;
137#endif // ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
138
139#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
142
143 void init_labels() {
144 assert(ks_scalar.empty());
145#ifdef ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
146 assert(heffte.rs_dipole_density[0u].empty());
147 assert(heffte.rs_dipole_density[1u].empty());
148 assert(heffte.rs_dipole_density[2u].empty());
149#endif // ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
151 "DipolarP3MState::rs_fields_kokkos", 0, 0, 0);
152 }
153#endif // ESPRESSO_SHARED_MEMORY_PARALLELISM
154};
155
156template <typename FloatType, Arch Architecture, class FFTConfig>
158 ~DipolarP3MHeffte() override = default;
159
160 // heFFTe checks are only implemented for row-major data
161 static_assert(FFTConfig::r_space_order == Utils::MemoryOrder::ROW_MAJOR);
162 static_assert(FFTConfig::k_space_order == Utils::MemoryOrder::ROW_MAJOR);
163
165 /** @brief Dipolar P3M parameters. */
167
168private:
169#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
170 // kokkos handle must outlive kokkos data structures from other class members
171 std::shared_ptr<KokkosHandle> m_kokkos_handle;
172#endif
173 /** @brief Dipolar P3M meshes and FFT algorithm. */
174 std::unique_ptr<DipolarP3MStateClass> dp3m_impl;
175 TuningParameters tuning;
176 bool m_is_tuned;
177
178public:
179 DipolarP3MHeffte(std::unique_ptr<DipolarP3MStateClass> &&dp3m_state,
180 TuningParameters tuning_params, double prefactor)
181 : DipolarP3M(dp3m_state->params), dp3m{*dp3m_state},
182#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
183 m_kokkos_handle{::kokkos_handle},
184#endif
185 dp3m_impl{std::move(dp3m_state)}, tuning{std::move(tuning_params)} {
186
187 if (tuning.timings <= 0) {
188 throw std::domain_error("Parameter 'timings' must be > 0");
189 }
191 throw std::domain_error("DipolarP3M requires a cubic mesh");
192 }
193 m_is_tuned = not dp3m.params.tuning;
194 dp3m.params.tuning = false;
196#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
198#endif
199 }
200
201 void init() override {
202 if constexpr (Architecture == Arch::CPU) {
204 }
205 }
206 void tune() override;
207 void count_magnetic_particles() override;
208
209 [[nodiscard]] bool is_tuned() const noexcept override { return m_is_tuned; }
210 [[nodiscard]] bool is_gpu() const noexcept override {
211 return Architecture != Arch::CPU;
212 }
213 [[nodiscard]] bool is_double_precision() const noexcept override {
214 return std::is_same_v<FloatType, double>;
215 }
216
217 void on_activation() override {
219 tune();
220 }
221
222 double long_range_energy() override { return long_range_kernel(false, true); }
223
224 void add_long_range_forces() override {
225 if constexpr (Architecture == Arch::CPU) {
226 long_range_kernel(true, false);
227 }
228 }
229
230 void dipole_assign() override;
231
232private:
233 void prepare_fft_mesh() {
235#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
236 using execution_space = Kokkos::DefaultExecutionSpace;
237 auto const num_threads = execution_space().concurrency();
238 Kokkos::realloc(Kokkos::WithoutInitializing, dp3m.rs_fields_kokkos,
239 num_threads, 3, dp3m.local_mesh.size);
240 Kokkos::deep_copy(dp3m.rs_fields_kokkos, FloatType{0});
241#endif // ESPRESSO_SHARED_MEMORY_PARALLELISM
242 for (auto &rs_mesh_field : dp3m.mesh.rs_fields) {
243 std::ranges::fill(rs_mesh_field, FloatType{0});
244 }
245#ifdef ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
246 for (auto dir : {0u, 1u, 2u}) {
248 std::ranges::fill(dp3m.heffte.rs_dipole_density[dir], FloatType{0});
249 }
250#endif // ESPRESSO_DP3M_HEFFTE_CROSS_CHECKS
251 }
252
253protected:
254 /** Compute the k-space part of forces and energies. */
255 double long_range_kernel(bool force_flag, bool energy_flag);
256 double calc_average_self_energy_k_space() const override;
257 void calc_energy_correction() override;
258 void calc_influence_function_force() override;
259 void calc_influence_function_energy() override;
260 double calc_surface_term(bool force_flag, bool energy_flag) override;
261 void init_cpu_kernels();
262 void scaleby_box_l() override;
263#ifdef ESPRESSO_NPT
264 void npt_add_virial_contribution(double energy) const override;
265#endif
266};
267
268#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
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
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.
double calc_surface_term(bool force_flag, bool energy_flag) override
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
void dipole_assign() override
~DipolarP3MHeffte() override=default
void calc_influence_function_energy() override
void scaleby_box_l() override
void calc_influence_function_force() override
void count_magnetic_particles() override
DipolarP3MStateClass & dp3m
Dipolar P3M parameters.
void add_long_range_forces() override
double long_range_kernel(bool force_flag, bool energy_flag)
Compute the k-space part of forces and energies.
void on_activation() override
double calc_average_self_energy_k_space() const override
double long_range_energy() 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:54
void sanity_checks() const
Definition dp3m.hpp:78
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.