IPPL API Reference
Independent Parallel Particle Layer C++ API
Loading...
Searching...
No Matches
FFT.h
1//
2// Class FFT
3// The FFT class performs complex-to-complex,
4// real-to-complex on IPPL Fields.
5// FFT is templated on the type of transform to be performed,
6// the dimensionality of the Field to transform, and the
7// floating-point precision type of the Field (float or double).
8// Currently, we use heffte for taking the transforms and the class FFT
9// serves as an interface between IPPL and heffte. In making this interface,
10// we have referred Cabana library
11// https://github.com/ECP-copa/Cabana.
12//
13//
14
15#ifndef IPPL_FFT_FFT_H
16#define IPPL_FFT_FFT_H
17
18#include <Kokkos_Complex.hpp>
19#include <array>
20#include <heffte_fft3d.h>
21#include <heffte_fft3d_r2c.h>
22#include <memory>
23#include <type_traits>
24
25#include "Utility/IpplException.h"
27
28#include "Field/Field.h"
29
30#include "FieldLayout/FieldLayout.h"
31#include "Index/NDIndex.h"
32
33namespace heffte {
34 template <>
35 struct is_ccomplex<Kokkos::complex<float>> : std::true_type {};
36
37 template <>
38 struct is_zcomplex<Kokkos::complex<double>> : std::true_type {};
39} // namespace heffte
40
41namespace ippl {
42
46 class CCTransform {};
47 class RCTransform {};
48 class SineTransform {};
49 class CosTransform {};
53 class Cos1Transform {};
54
55 enum FFTComm {
56 a2av = 0,
57 a2a = 1,
58 p2p = 2,
59 p2p_pl = 3
60 };
61
62 enum TransformDirection {
63 FORWARD,
64 BACKWARD
65 };
66
67 namespace detail {
72 template <typename>
74
75#if defined(Heffte_ENABLE_FFTW)
76 template <>
77 struct HeffteBackendType<Kokkos::HostSpace> {
78 using backend = heffte::backend::fftw;
79 using backendSine = heffte::backend::fftw_sin;
80 using backendCos = heffte::backend::fftw_cos;
81 using backendCos1 = heffte::backend::fftw_cos1;
82 };
83#elif defined(Heffte_ENABLE_MKL)
84 template <>
85 struct HeffteBackendType<Kokkos::HostSpace> {
86 using backend = heffte::backend::mkl;
87 using backendSine = heffte::backend::mkl_sin;
88 using backendCos = heffte::backend::mkl_cos;
89 };
90#endif
91
92#ifdef Heffte_ENABLE_CUDA
93#ifdef KOKKOS_ENABLE_CUDA
94 template <>
95 struct HeffteBackendType<Kokkos::CudaSpace> {
96 using backend = heffte::backend::cufft;
97 using backendSine = heffte::backend::cufft_sin;
98 using backendCos = heffte::backend::cufft_cos;
99 using backendCos1 = heffte::backend::cufft_cos1;
100 };
101#else
102#error cuFFT backend is enabled for heFFTe but CUDA is not enabled for Kokkos!
103#endif
104#endif
105
106#ifdef KOKKOS_ENABLE_HIP
107#ifdef Heffte_ENABLE_ROCM
108 template <>
109 struct HeffteBackendType<Kokkos::HIPSpace> {
110 using backend = heffte::backend::rocfft;
111 using backendSine = heffte::backend::rocfft_sin;
112 using backendCos = heffte::backend::rocfft_cos;
113 using backendCos1 = heffte::backend::rocfft_cos1;
114 };
115#else
116 template <>
117 struct HeffteBackendType<Kokkos::HIPSpace> {
118 using backend = heffte::backend::stock;
119 using backendSine = heffte::backend::stock_sin;
120 using backendCos = heffte::backend::stock_cos;
121 using backendCos1 = heffte::backend::stock_cos1;
122 };
123#endif
124#endif
125
126#ifdef KOKKOS_ENABLE_SYCL
127 // No SYCL-specific Heffte backend wired up yet. Heffte's oneMKL backend
128 // would go here when Heffte_ENABLE_ONEAPI plumbing is added in IPPL's
129 // Dependencies.cmake. For now, fall back to the stock CPU backend so
130 // SYCL builds at least compile (FFTs will run on the host).
131 template <>
132 struct HeffteBackendType<Kokkos::SYCLDeviceUSMSpace> {
133 using backend = heffte::backend::stock;
134 using backendSine = heffte::backend::stock_sin;
135 using backendCos = heffte::backend::stock_cos;
136 using backendCos1 = heffte::backend::stock_cos1;
137 };
138#endif
139
140#if !defined(Heffte_ENABLE_MKL) && !defined(Heffte_ENABLE_FFTW)
145 template <>
146 struct HeffteBackendType<Kokkos::HostSpace> {
147 using backend = heffte::backend::stock;
148 using backendSine = heffte::backend::stock_sin;
149 using backendCos = heffte::backend::stock_cos;
150 using backendCos1 = heffte::backend::stock_cos1;
151 };
152#endif
153
154 } // namespace detail
155
156 template <typename Field, template <typename...> class FFT, typename Backend,
157 typename BufferType = typename Field::value_type>
158 class FFTBase {
159 constexpr static unsigned Dim = Field::dim;
160
161 public:
162 using heffteBackend = Backend;
163 using workspace_t = typename FFT<heffteBackend>::template buffer_container<BufferType>;
165
166 FFTBase(const Layout_t& layout, const ParameterList& params);
167 ~FFTBase() = default;
168
169 protected:
170 FFTBase() = default;
171
172 void domainToBounds(const NDIndex<Dim>& domain, std::array<long long, 3>& low,
173 std::array<long long, 3>& high);
174 void setup(const heffte::box3d<long long>& inbox, const heffte::box3d<long long>& outbox,
175 const ParameterList& params);
176
177 std::shared_ptr<FFT<heffteBackend, long long>> heffte_m;
178 workspace_t workspace_m;
179
180 template <typename FieldType>
181 using temp_view_type =
182 typename Kokkos::View<typename FieldType::view_type::data_type, Kokkos::LayoutLeft,
183 typename FieldType::memory_space>::uniform_type;
184 temp_view_type<Field> tempField;
185 };
186
187#define IN_PLACE_FFT_BASE_CLASS(Field, Backend) \
188 FFTBase<Field, heffte::fft3d, \
189 typename detail::HeffteBackendType<typename Field::memory_space>::Backend>
190#define EXT_FFT_BASE_CLASS(Field, Backend, Type) \
191 FFTBase<Field, heffte::fft3d_r2c, \
192 typename detail::HeffteBackendType<typename Field::memory_space>::Backend, \
193 typename Type>
194
198 template <class Transform, typename Field>
199 class FFT {};
200
204 template <typename ComplexField>
205 class FFT<CCTransform, ComplexField> : public IN_PLACE_FFT_BASE_CLASS(ComplexField, backend) {
206 constexpr static unsigned Dim = ComplexField::dim;
207 using Base = IN_PLACE_FFT_BASE_CLASS(ComplexField, backend);
208
209 public:
210 using Complex_t = typename ComplexField::value_type;
211
212 using Base::Base;
213 using typename Base::heffteBackend, typename Base::workspace_t, typename Base::Layout_t;
214
219 void warmup(ComplexField& f);
220
226 void transform(TransformDirection direction, ComplexField& f);
227 };
228
232 template <typename RealField>
233 class FFT<RCTransform, RealField>
234 : public EXT_FFT_BASE_CLASS(RealField, backend,
235 Kokkos::complex<typename RealField::value_type>) {
236 constexpr static unsigned Dim = RealField::dim;
237 using Real_t = typename RealField::value_type;
238 using Base = EXT_FFT_BASE_CLASS(RealField, backend,
239 Kokkos::complex<typename RealField::value_type>);
240
241 public:
242 using Complex_t = Kokkos::complex<Real_t>;
243 using ComplexField = typename Field<Complex_t, Dim, typename RealField::Mesh_t,
244 typename RealField::Centering_t,
245 typename RealField::execution_space>::uniform_type;
246
247 using typename Base::heffteBackend, typename Base::workspace_t, typename Base::Layout_t;
248
252 FFT(const Layout_t& layoutInput, const Layout_t& layoutOutput, const ParameterList& params);
253
259 void warmup(RealField& f, ComplexField& g);
260
267 void transform(TransformDirection direction, RealField& f, ComplexField& g);
268
269 private:
270 typename Base::template temp_view_type<ComplexField> tempFieldComplex;
271 };
272
276 template <typename Field>
277 class FFT<SineTransform, Field> : public IN_PLACE_FFT_BASE_CLASS(Field, backendSine) {
278 constexpr static unsigned Dim = Field::dim;
279 using Base = IN_PLACE_FFT_BASE_CLASS(Field, backendSine);
280
281 public:
282 using Base::Base;
283 using typename Base::heffteBackend, typename Base::workspace_t, typename Base::Layout_t;
284
289 void warmup(Field& f);
290
296 void transform(TransformDirection direction, Field& f);
297 };
301 template <typename Field>
302 class FFT<CosTransform, Field> : public IN_PLACE_FFT_BASE_CLASS(Field, backendCos) {
303 constexpr static unsigned Dim = Field::dim;
304 using Base = IN_PLACE_FFT_BASE_CLASS(Field, backendCos);
305
306 public:
307 using Base::Base;
308 using typename Base::heffteBackend, typename Base::workspace_t, typename Base::Layout_t;
309
314 void warmup(Field& f);
315
321 void transform(TransformDirection direction, Field& f);
322 };
326 template <typename Field>
327 class FFT<Cos1Transform, Field> : public IN_PLACE_FFT_BASE_CLASS(Field, backendCos1) {
328 constexpr static unsigned Dim = Field::dim;
329 using Base = IN_PLACE_FFT_BASE_CLASS(Field, backendCos1);
330
331 public:
332 using Base::Base;
333 using typename Base::heffteBackend, typename Base::workspace_t, typename Base::Layout_t;
334
339 void warmup(Field& f);
340
346 void transform(TransformDirection direction, Field& f);
347 };
348} // namespace ippl
349
350#include "FFT/FFT.hpp"
351
352#endif // IPPL_FFT_FFT_H
353
354// vi: set et ts=4 sw=4 sts=4:
355// Local Variables:
356// mode:c
357// c-basic-offset: 4
358// indent-tabs-mode: nil
359// require-final-newline: nil
360// End:
Definition FFT.h:46
Definition FFT.h:53
Definition FFT.h:49
Definition FFT.h:158
void domainToBounds(const NDIndex< Dim > &domain, std::array< long long, 3 > &low, std::array< long long, 3 > &high)
Definition FFT.hpp:46
void setup(const heffte::box3d< long long > &inbox, const heffte::box3d< long long > &outbox, const ParameterList &params)
Definition FFT.hpp:66
Definition FFT.h:199
Definition FieldLayout.h:166
Definition Field.h:18
Definition NDIndex.h:21
Definition ParameterList.h:29
Definition FFT.h:47
Definition FFT.h:48
Definition Archive.h:20