Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
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