ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
fft.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2024 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/** \file
25 *
26 * Routines, row decomposition, data structures and communication for the
27 * 3D-FFT.
28 *
29 * The 3D-FFT is split into three 1D-FFTs. The data is
30 * distributed in such a way, that for the actual direction of the
31 * FFT each node has a certain number of rows for which it performs a
32 * 1D-FFT. After performing the FFT on that direction the data is
33 * redistributed.
34 *
35 * For simplicity, a full complex-to-complex FFT is implemented,
36 * even though a real-to-complex FFT would be sufficient.
37 */
38
39#include "vector.hpp"
40
41#include <utils/Vector.hpp>
42
43#include <array>
44#include <cstddef>
45#include <memory>
46#include <optional>
47#include <span>
48#include <type_traits>
49#include <utility>
50#include <vector>
51
52struct fftw_plan_s;
53struct fftwf_plan_s;
54namespace boost::mpi {
55class environment;
56class communicator;
57} // namespace boost::mpi
58
59namespace fft {
60
61template <typename FloatType> struct fft_plan {
62 static_assert(std::is_same_v<FloatType, float> or
63 std::is_same_v<FloatType, double>,
64 "FFTW only implements float and double");
65 using fftw_plan = std::conditional_t<std::is_same_v<FloatType, double>,
66 fftw_plan_s *, fftwf_plan_s *>;
67
69
70 /** plan direction: forward or backward FFT (enum value from FFTW). */
71 int dir;
72 /** plan for the FFT. */
74 /** packing function for send blocks. */
75 void (*pack_function)(FloatType const *const, FloatType *const, int const *,
76 int const *, int const *, int);
77 void destroy_plan();
78};
79
80/** @brief Plan for a forward 1D FFT of a flattened 3D array. */
81template <typename FloatType>
82struct fft_forw_plan : public fft_plan<FloatType> {
83 /** row direction of that FFT. */
85 /** permutations from normal coordinate system. */
87 /** number of 1D FFTs. */
88 int n_ffts;
89
90 /** size of local mesh before communication. */
91 std::array<int, 3u> old_mesh;
92 /** size of local mesh after communication, also used for actual FFT. */
93 std::array<int, 3u> new_mesh;
94 /** lower left point of local FFT mesh in global FFT mesh coordinates. */
95 std::array<int, 3u> start;
96 /** size of new mesh (number of mesh points). */
98
99 /** group of nodes which have to communicate with each other. */
100 std::vector<int> group;
101
102 /** Send block specification. 6 integers for each node: start[3], size[3]. */
103 std::vector<int> send_block;
104 /** Send block communication sizes. */
105 std::vector<int> send_size;
106 /** Recv block specification. 6 integers for each node: start[3], size[3]. */
107 std::vector<int> recv_block;
108 /** Recv block communication sizes. */
109 std::vector<int> recv_size;
110 /** size of send block elements, i.e. 1 for real, 2 for complex. */
112};
113
114/** @brief Plan for a backward 1D FFT of a flattened 3D array. */
115template <typename FloatType>
116struct fft_back_plan : public fft_plan<FloatType> {};
117
118/**
119 * @brief Information about the three one dimensional FFTs and how the nodes
120 * have to communicate inbetween.
121 *
122 * @note FFT numbering starts with 1 for technical reasons (because we have 4
123 * node grids, the index 0 is used for the real space charge assignment grid).
124 */
125template <typename FloatType> struct fft_data_struct {
126private:
127 /**
128 * @brief Handle to the MPI environment.
129 * Has to be the first member in the class definition, so that FFT plans
130 * are destroyed before the MPI environment expires (non-static class
131 * members are destroyed in the reverse order of their initialization).
132 */
133 std::shared_ptr<boost::mpi::environment> m_mpi_env;
134
135 /** Information for forward FFTs. */
136 std::array<fft_forw_plan<FloatType>, 4u> forw;
137 /** Information for backward FFTs. */
138 std::array<fft_back_plan<FloatType>, 4u> back;
139
140 /** Whether FFT is initialized or not. */
141 bool init_tag = false;
142
143 /** Maximal size of the communication buffers. */
144 int max_comm_size = 0;
145
146 /** Maximal local mesh size. */
147 int max_mesh_size = 0;
148
149 /** send buffer. */
150 std::vector<FloatType> send_buf;
151 /** receive buffer. */
152 std::vector<FloatType> recv_buf;
153 /** Buffer for receive data. */
154 fft::vector<FloatType> data_buf;
155
156public:
157 explicit fft_data_struct(decltype(m_mpi_env) mpi_env)
158 : m_mpi_env{std::move(mpi_env)} {}
159
160 // disable copy construction: unsafe because we store raw pointers
161 // to FFT plans (avoids double-free and use-after-free)
164
165 /** Initialize everything connected to the 3D-FFT.
166 *
167 * \param[in] comm MPI communicator.
168 * \param[in] ca_mesh_dim Local CA mesh dimensions.
169 * \param[in] ca_mesh_margin Local CA mesh margins.
170 * \param[in] global_mesh_dim Global CA mesh dimensions.
171 * \param[in] global_mesh_off Global CA mesh offset.
172 * \param[out] ks_pnum Number of permutations in k-space.
173 * \param[in] grid Number of nodes in each spatial dimension.
174 * \return Maximal size of local fft mesh (needed for allocation of ca_mesh).
175 */
176 int initialize_fft(boost::mpi::communicator const &comm,
177 Utils::Vector3i const &ca_mesh_dim,
178 int const *ca_mesh_margin,
179 Utils::Vector3i const &global_mesh_dim,
180 Utils::Vector3d const &global_mesh_off, int &ks_pnum,
181 Utils::Vector3i const &grid);
182
183 /** Perform an in-place forward 3D FFT.
184 * \warning The content of \a data is overwritten.
185 * \param[in,out] data Mesh.
186 * \param[in] comm MPI communicator
187 */
188 void forward_fft(boost::mpi::communicator const &comm, FloatType *data);
189
190 /** Perform an in-place backward 3D FFT.
191 * \warning The content of \a data is overwritten.
192 * \param[in,out] data Mesh.
193 * \param[in] check_complex Throw an error if the complex component is
194 * non-zero.
195 * \param[in] comm MPI communicator.
196 */
197 void backward_fft(boost::mpi::communicator const &comm, FloatType *data,
198 bool check_complex);
199
200 auto const &get_mesh_size() const { return forw[3u].new_mesh; }
201
202 auto const &get_mesh_start() const { return forw[3u].start; }
203
204private:
205 void forw_grid_comm(boost::mpi::communicator const &comm,
206 fft_forw_plan<FloatType> const &plan, FloatType const *in,
207 FloatType *out);
208 void back_grid_comm(boost::mpi::communicator const &comm,
209 fft_forw_plan<FloatType> const &plan_f,
210 fft_back_plan<FloatType> const &plan_b,
211 FloatType const *in, FloatType *out);
212};
213
214int map_3don2d_grid(int const g3d[3], int g2d[3]);
215
216std::optional<std::vector<int>> find_comm_groups(Utils::Vector3i const &,
217 Utils::Vector3i const &,
218 std::span<int const>,
219 std::span<int>, std::span<int>,
220 std::span<int>, int);
221
222} // namespace fft
Vector implementation and trait types for boost qvm interoperability.
Communicator communicator
Definition fft.cpp:74
std::optional< std::vector< int > > find_comm_groups(Utils::Vector3i const &grid1, Utils::Vector3i const &grid2, std::span< int const > node_list1, std::span< int > node_list2, std::span< int > pos, std::span< int > my_pos, int rank)
This ugly function does the bookkeeping: which nodes have to communicate to each other,...
Definition fft.cpp:117
std::vector< T, allocator< T > > vector
Definition vector.hpp:52
int map_3don2d_grid(int const g3d[3], int g2d[3])
Calculate 'best' mapping between a 2D and 3D grid.
Definition fft.cpp:459
Plan for a backward 1D FFT of a flattened 3D array.
Definition fft.hpp:116
Information about the three one dimensional FFTs and how the nodes have to communicate inbetween.
Definition fft.hpp:125
void forward_fft(boost::mpi::communicator const &comm, FloatType *data)
Perform an in-place forward 3D FFT.
Definition fft.cpp:716
fft_data_struct & operator=(fft_data_struct< FloatType > const &)=delete
fft_data_struct(decltype(m_mpi_env) mpi_env)
Definition fft.hpp:157
auto const & get_mesh_size() const
Definition fft.hpp:200
fft_data_struct(fft_data_struct< FloatType > const &)=delete
auto const & get_mesh_start() const
Definition fft.hpp:202
void backward_fft(boost::mpi::communicator const &comm, FloatType *data, bool check_complex)
Perform an in-place backward 3D FFT.
Definition fft.cpp:748
int initialize_fft(boost::mpi::communicator const &comm, Utils::Vector3i const &ca_mesh_dim, int const *ca_mesh_margin, Utils::Vector3i const &global_mesh_dim, Utils::Vector3d const &global_mesh_off, int &ks_pnum, Utils::Vector3i const &grid)
Initialize everything connected to the 3D-FFT.
Definition fft.cpp:516
Plan for a forward 1D FFT of a flattened 3D array.
Definition fft.hpp:82
std::array< int, 3u > new_mesh
size of local mesh after communication, also used for actual FFT.
Definition fft.hpp:93
int n_ffts
number of 1D FFTs.
Definition fft.hpp:88
std::array< int, 3u > old_mesh
size of local mesh before communication.
Definition fft.hpp:91
std::vector< int > recv_block
Recv block specification.
Definition fft.hpp:107
std::vector< int > group
group of nodes which have to communicate with each other.
Definition fft.hpp:100
int new_size
size of new mesh (number of mesh points).
Definition fft.hpp:97
std::array< int, 3u > start
lower left point of local FFT mesh in global FFT mesh coordinates.
Definition fft.hpp:95
std::vector< int > send_size
Send block communication sizes.
Definition fft.hpp:105
std::vector< int > send_block
Send block specification.
Definition fft.hpp:103
int row_dir
row direction of that FFT.
Definition fft.hpp:84
int n_permute
permutations from normal coordinate system.
Definition fft.hpp:86
std::vector< int > recv_size
Recv block communication sizes.
Definition fft.hpp:109
int element
size of send block elements, i.e.
Definition fft.hpp:111
int dir
plan direction: forward or backward FFT (enum value from FFTW).
Definition fft.hpp:71
std::conditional_t< std::is_same_v< FloatType, double >, fftw_plan_s *, fftwf_plan_s * > fftw_plan
Definition fft.hpp:66
void destroy_plan()
Definition fft.cpp:787
fftw_plan plan_handle
plan for the FFT.
Definition fft.hpp:73
void(* pack_function)(FloatType const *const, FloatType *const, int const *, int const *, int const *, int)
packing function for send blocks.
Definition fft.hpp:75