Gyselalib++
 
Loading...
Searching...
No Matches
fft_poisson_solver.hpp
1// SPDX-License-Identifier: MIT
2#pragma once
3#include <ddc/ddc.hpp>
4#include <ddc/kernels/fft.hpp>
5
6#include "ddc_alias_inline_functions.hpp"
7#include "ddc_aliases.hpp"
8#include "ddc_helper.hpp"
9#include "directional_tag.hpp"
10#include "ipoisson_solver.hpp"
11
15template <
16 class IdxRangeLaplacian,
17 class IdxRangeFull = IdxRangeLaplacian,
18 class ExecSpace = Kokkos::DefaultExecutionSpace,
19 class LayoutSpace = Kokkos::layout_right>
21
36template <class... GridPDEDim1D, class IdxRangeFull, class ExecSpace, class LayoutSpace>
37class FFTPoissonSolver<IdxRange<GridPDEDim1D...>, IdxRangeFull, ExecSpace, LayoutSpace>
38 : public IPoissonSolver<
39 IdxRange<GridPDEDim1D...>,
40 IdxRangeFull,
41 typename ExecSpace::memory_space,
42 LayoutSpace>
43{
44private:
46 IdxRange<GridPDEDim1D...>,
47 IdxRangeFull,
48 typename ExecSpace::memory_space,
49 LayoutSpace>;
50
51public:
52 template <class Dim>
53 struct GridFourier : ddc::PeriodicSampling<ddc::Fourier<Dim>>
54 {
55 };
56
57public:
59 using field_type = typename base_type::field_type;
61 using const_field_type = typename base_type::const_field_type;
62
64 using vector_field_type = typename base_type::vector_field_type;
65
67 using batch_idx_range_type = typename base_type::batch_idx_range_type;
69 using batch_index_type = typename base_type::batch_index_type;
70
72 using laplacian_idx_range_type = typename base_type::laplacian_idx_range_type;
73
75 using layout_space = typename base_type::layout_space;
77 using memory_space = typename base_type::memory_space;
78
81 = IdxRange<GridFourier<typename GridPDEDim1D::continuous_dimension_type>...>;
83 using fourier_index_type = typename fourier_idx_range_type::discrete_element_type;
84
87 = FieldMem<Kokkos::complex<double>, fourier_idx_range_type, memory_space>;
89 using fourier_field_type = typename fourier_field_mem_type::span_type;
90
91private:
93 static constexpr ddc::FFT_Normalization m_norm = ddc::FFT_Normalization::BACKWARD;
94
95private:
102 template <class... FDim>
103 KOKKOS_FUNCTION static double get_laplace_operator(Idx<FDim...> index)
104 {
105 return (((double)ddc::coordinate(ddc::select<FDim>(index))
106 * (double)ddc::coordinate(ddc::select<FDim>(index)))
107 + ...);
108 }
109
120 template <class Dim>
121 void differentiate_and_invert_fourier_values(
122 DField<laplacian_idx_range_type, memory_space, LayoutSpace> derivative,
123 fourier_field_type fourier_derivative,
124 fourier_field_type values) const
125 {
126 negative_differentiate_equation<Dim>(fourier_derivative, values);
127 // Perform the inverse 1D FFT of the solution to deduce the electric field
128 ddc::
129 ifft(ExecSpace(),
130 get_field(derivative),
131 get_field(fourier_derivative),
132 ddc::kwArgs_fft {m_norm});
133 }
134
142 void get_gradient(
143 DField<laplacian_idx_range_type, memory_space, LayoutSpace> gradient,
144 fourier_field_type fourier_derivative,
145 fourier_field_type values) const
146 {
147 using Dim =
148 typename ddc::type_seq_element_t<0, ddc::to_type_seq_t<laplacian_idx_range_type>>::
149 continuous_dimension_type;
150 using FourierDim = GridFourier<Dim>;
151 differentiate_and_invert_fourier_values<FourierDim>(gradient, fourier_derivative, values);
152 }
153
161 template <class... Dims>
162 void get_gradient(
164 double,
165 laplacian_idx_range_type,
166 NDTag<Dims...>,
167 memory_space,
168 layout_space> gradient,
169 fourier_field_type fourier_derivative,
170 fourier_field_type values) const
171 {
172 ((differentiate_and_invert_fourier_values<
173 GridFourier<Dims>>(ddcHelper::get<Dims>(gradient), fourier_derivative, values)),
174 ...);
175 }
176
177 template <class Grid1D>
178 void init_fourier_space(IdxRange<Grid1D> idx_range)
179 {
180 using GridFFT = GridFourier<typename Grid1D::continuous_dimension_type>;
181 ddc::init_discrete_space<GridFFT>(ddc::init_fourier_space<GridFFT>(idx_range));
182 }
183
184public:
192 template <class Layout>
194 fourier_field_type intermediate_chunk,
195 DField<laplacian_idx_range_type, memory_space, Layout> rho) const
196 {
197 // Compute FFT(rho)
198 ddc::fft(ExecSpace(), intermediate_chunk, rho, ddc::kwArgs_fft {m_norm});
199
200 fourier_idx_range_type const k_mesh = get_idx_range(intermediate_chunk);
201
202 // Solve Poisson's equation -\Delta phi = -(\sum_j \partial_j^2) \phi = rho
203 // in Fourier space as -(\sum_j i*k_i * i*k_i) FFT(Phi) = FFT(rho))
204 ddc::parallel_for_each(
205 ExecSpace(),
206 k_mesh,
207 KOKKOS_LAMBDA(fourier_index_type const ik) {
208 if (ik != k_mesh.front()) {
209 intermediate_chunk(ik) = intermediate_chunk(ik) / get_laplace_operator(ik);
210 } else {
211 intermediate_chunk(ik) = 0.;
212 }
213 });
214 }
215
225 template <class Dim>
227 const
228 {
229 Kokkos::complex<double> imaginary_unit(0.0, 1.0);
230 ddc::parallel_for_each(
231 ExecSpace(),
232 get_idx_range(values),
233 KOKKOS_LAMBDA(fourier_index_type const ik) {
234 Idx<Dim> const ikx = ddc::select<Dim>(ik);
235 derivative(ik) = -imaginary_unit * ddc::coordinate(ikx) * values(ik);
236 });
237 }
238
239public:
247 explicit FFTPoissonSolver(laplacian_idx_range_type laplacian_idx_range)
248 {
249 ((init_fourier_space<GridPDEDim1D>(ddc::select<GridPDEDim1D>(laplacian_idx_range))), ...);
250 }
251
261 virtual field_type operator()(field_type phi, field_type rho) const final
262 {
263 Kokkos::Profiling::pushRegion("FFTPoissonSolver");
264
265 laplacian_idx_range_type idx_range(get_idx_range(phi));
266 batch_idx_range_type batch_idx_range(get_idx_range(phi));
267
268 // Build a mesh in the fourier space, for N points
269 fourier_idx_range_type const k_mesh = ddc::fourier_mesh<
270 GridFourier<typename GridPDEDim1D::continuous_dimension_type>...>(idx_range, false);
271
272 fourier_field_mem_type intermediate_chunk_alloc(k_mesh);
273 fourier_field_type intermediate_chunk = get_field(intermediate_chunk_alloc);
274
275 ddc::for_each(batch_idx_range, [&](batch_index_type ib) {
276 solve_poisson_equation(intermediate_chunk, rho[ib]);
277
278 // Perform the inverse 1D FFT of the solution to deduce the electrostatic potential
279 ddc::
280 ifft(ExecSpace(),
281 phi[ib],
282 get_field(intermediate_chunk),
283 ddc::kwArgs_fft {m_norm});
284 });
285
286 Kokkos::Profiling::popRegion();
287 return phi;
288 }
289
303 {
304 Kokkos::Profiling::pushRegion("FFTPoissonSolver");
305
306 laplacian_idx_range_type idx_range(get_idx_range(phi));
307 batch_idx_range_type batch_idx_range(get_idx_range(phi));
308
309 // Build a mesh in the fourier space, for N points
310 fourier_idx_range_type const k_mesh = ddc::fourier_mesh<
311 GridFourier<typename GridPDEDim1D::continuous_dimension_type>...>(idx_range, false);
312
313 fourier_field_mem_type intermediate_chunk_alloc(k_mesh);
314 fourier_field_mem_type fourier_efield_alloc(k_mesh);
315
316 fourier_field_type intermediate_chunk = get_field(intermediate_chunk_alloc);
317 fourier_field_type fourier_efield = get_field(fourier_efield_alloc);
318
319 ddc::for_each(batch_idx_range, [&](batch_index_type ib) {
320 solve_poisson_equation(intermediate_chunk, rho[ib]);
321 get_gradient(E[ib], fourier_efield, intermediate_chunk);
322
323 // Perform the inverse 1D FFT of the solution to deduce the electrostatic potential
324 ddc::
325 ifft(ExecSpace(),
326 phi[ib],
327 get_field(intermediate_chunk),
328 ddc::kwArgs_fft {m_norm});
329 });
330 Kokkos::Profiling::popRegion();
331 return phi;
332 }
333};
IdxRange< GridFourier< typename GridPDEDim1D::continuous_dimension_type >... > fourier_idx_range_type
The type of the Fourier space index range.
Definition fft_poisson_solver.hpp:81
void solve_poisson_equation(fourier_field_type intermediate_chunk, DField< laplacian_idx_range_type, memory_space, Layout > rho) const
A function to solve the Poisson equation in Fourier space This function should be private.
Definition fft_poisson_solver.hpp:193
typename base_type::vector_field_type vector_field_type
The type of the derivative of .
Definition fft_poisson_solver.hpp:64
FFTPoissonSolver(laplacian_idx_range_type laplacian_idx_range)
A constructor for the FFT Poisson solver.
Definition fft_poisson_solver.hpp:247
typename base_type::layout_space layout_space
The layout space of the Fields passed to operator().
Definition fft_poisson_solver.hpp:75
virtual field_type operator()(field_type phi, field_type rho) const final
An operator which calculates the solution to Poisson's equation: .
Definition fft_poisson_solver.hpp:261
typename base_type::batch_index_type batch_index_type
The index type for indexing a batch dimension.
Definition fft_poisson_solver.hpp:69
typename base_type::memory_space memory_space
The space (CPU/GPU) where the Fields passed to operator() are saved.
Definition fft_poisson_solver.hpp:77
typename base_type::field_type field_type
The Field type of the arguments to operator().
Definition fft_poisson_solver.hpp:59
virtual field_type operator()(field_type phi, vector_field_type E, field_type rho) const final
An operator which calculates the solution to Poisson's equation and its derivative: .
Definition fft_poisson_solver.hpp:302
FieldMem< Kokkos::complex< double >, fourier_idx_range_type, memory_space > fourier_field_mem_type
The type of a Field storing the Fourier transform of a function.
Definition fft_poisson_solver.hpp:87
typename base_type::batch_idx_range_type batch_idx_range_type
The index range type describing the batch dimensions.
Definition fft_poisson_solver.hpp:67
typename fourier_idx_range_type::discrete_element_type fourier_index_type
The type of an index of the Fourier space index range.
Definition fft_poisson_solver.hpp:83
typename fourier_field_mem_type::span_type fourier_field_type
The type of a Field storing the Fourier transform of a function.
Definition fft_poisson_solver.hpp:89
void negative_differentiate_equation(fourier_field_type derivative, fourier_field_type values) const
Differentiate and multiply by -1 an expression in Fourier space by multiplying by -i * k This functio...
Definition fft_poisson_solver.hpp:226
typename base_type::const_field_type const_field_type
The const Field type of the arguments to operator().
Definition fft_poisson_solver.hpp:61
typename base_type::laplacian_idx_range_type laplacian_idx_range_type
The type of the index range on which the equation is defined.
Definition fft_poisson_solver.hpp:72
See FFTPoissonSolverImplementation.
Definition fft_poisson_solver.hpp:20
Definition ipoisson_solver.hpp:10
A class which holds multiple (scalar) fields in order to represent a vector field.
Definition vector_field.hpp:64