13#include <KokkosFFT.hpp>
14#include <Kokkos_Core.hpp>
19
20
21
22
23template <
typename Dim>
27
28
29
30
37
38
39
40
47
48
49
50
55namespace ddc::detail::fft {
64struct real_type<Kokkos::complex<T>>
70using real_type_t =
typename real_type<T>::type;
74struct is_complex : std::false_type
79struct is_complex<Kokkos::complex<T>> : std::true_type
84constexpr bool is_complex_v = is_complex<T>::value;
87template <
typename T,
typename Dim,
typename Last>
88KOKKOS_FUNCTION
constexpr T LastSelector(
const T a,
const T b)
90 return std::is_same_v<Dim, Last> ? a : b;
93template <
typename T,
typename Dim,
typename First,
typename Second,
typename... Tail>
94KOKKOS_FUNCTION
constexpr T LastSelector(
const T a,
const T b)
96 return LastSelector<T, Dim, Second, Tail...>(a, b);
100
101
102
103
112
113
114
115
116
117
118
119template <
typename DDim,
typename... DDimX>
123 (is_uniform_point_sampling_v<DDimX> && ...),
124 "DDimX dimensions should derive from UniformPointSampling");
125 return static_cast<
int>(x_mesh.
template extent<DDim>());
128template <
typename... DDimX>
129KokkosFFT::axis_type<
sizeof...(DDimX)> axes()
131 return KokkosFFT::axis_type<
sizeof...(DDimX)> {
132 static_cast<
int>(
ddc::type_seq_rank_v<DDimX,
ddc::detail::TypeSeq<DDimX...>>)...};
135inline KokkosFFT::Normalization ddc_fft_normalization_to_kokkos_fft(
140 return KokkosFFT::Normalization::none;
144 return KokkosFFT::Normalization::forward;
148 return KokkosFFT::Normalization::backward;
152 return KokkosFFT::Normalization::ortho;
155 throw std::runtime_error(
"ddc::FFT_Normalization not handled");
160 typename ElementType,
163 typename MemorySpace,
166 ExecSpace
const& exec_space,
167 ddc::
ChunkSpan<ElementType, DDom, Layout, MemorySpace>
const& chunk_span,
170 ddc::parallel_for_each(
171 "ddc_fft_normalization",
174 KOKKOS_LAMBDA(
typename DDom::discrete_element_type
const i) {
175 chunk_span(i) *= value;
180Real forward_full_norm_coef(
DiscreteDomain<DDim>
const& ddom)
noexcept
182 return rlength(ddom) / Kokkos::sqrt(2 * Kokkos::numbers::pi_v<Real>)
183 / (ddom.extents() - 1).value();
187Real backward_full_norm_coef(
DiscreteDomain<DDim>
const& ddom)
noexcept
189 return 1 / (forward_full_norm_coef(ddom) * ddom.extents().value());
197 typename MemorySpace,
203 ExecSpace
const& exec_space,
206 kwArgs_impl
const& kwargs)
209 std::is_same_v<real_type_t<Tin>,
float> || std::is_same_v<real_type_t<Tin>,
double>,
210 "Base type of Tin (and Tout) must be float or double.");
212 std::is_same_v<real_type_t<Tin>, real_type_t<Tout>>,
213 "Types Tin and Tout must be based on same type (float or double)");
215 Kokkos::SpaceAccessibility<ExecSpace, MemorySpace>::accessible,
216 "MemorySpace has to be accessible for ExecutionSpace.");
219 ddc::detail::mdspan_to_kokkos_element_t<Tin,
sizeof...(DDimIn)>,
220 ddc::detail::mdspan_to_kokkos_layout_t<LayoutIn>,
221 MemorySpace>
const in_view
222 = in.allocation_kokkos_view();
224 ddc::detail::mdspan_to_kokkos_element_t<Tout,
sizeof...(DDimIn)>,
225 ddc::detail::mdspan_to_kokkos_layout_t<LayoutOut>,
226 MemorySpace>
const out_view
227 = out.allocation_kokkos_view();
228 KokkosFFT::Normalization
const kokkos_fft_normalization
229 = ddc_fft_normalization_to_kokkos_fft(kwargs.normalization);
232 if constexpr (std::is_same_v<Tin, Tout>) {
239 kokkos_fft_normalization);
246 kokkos_fft_normalization);
250 if constexpr (is_complex_v<Tout>) {
251 assert(kwargs.direction == ddc::FFT_Direction::FORWARD);
257 kokkos_fft_normalization);
259 assert(kwargs.direction == ddc::FFT_Direction::BACKWARD);
265 kokkos_fft_normalization);
274 norm_coef = (forward_full_norm_coef(DiscreteDomain<DDimIn>(ddom_in)) * ...);
277 norm_coef = (backward_full_norm_coef(DiscreteDomain<DDimOut>(ddom_out)) * ...);
280 rescale(exec_space, out,
static_cast<real_type_t<Tout>>(norm_coef));
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307template <
typename DDimFx,
typename DDimX>
312 is_uniform_point_sampling_v<DDimX>,
313 "DDimX dimensions should derive from UniformPointSampling");
315 is_periodic_sampling_v<DDimFx>,
316 "DDimFx dimensions should derive from PeriodicSampling");
317 auto [impl, ddom] = DDimFx::
template init<DDimFx>(
318 ddc::Coordinate<
typename DDimFx::continuous_dimension_type>(0),
319 ddc::Coordinate<
typename DDimFx::continuous_dimension_type>(
320 2 * (
ddc::detail::fft::N<DDimX>(x_mesh) - 1)
321 * (
ddc::detail::fft::N<DDimX>(x_mesh) - 1)
322 /
static_cast<
double>(
323 ddc::detail::fft::N<DDimX>(x_mesh)
324 * (
ddc::coordinate(x_mesh.back()) -
ddc::coordinate(x_mesh.front())))
325 * Kokkos::numbers::pi),
328 return std::move(impl);
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346template <
typename... DDimFx,
typename... DDimX>
350 (is_uniform_point_sampling_v<DDimX> && ...),
351 "DDimX dimensions should derive from UniformPointSampling");
353 (is_periodic_sampling_v<DDimFx> && ...),
354 "DDimFx dimensions should derive from PeriodicPointSampling");
356 ddc::DiscreteElement<DDimFx>(0),
358 (C2C ?
ddc::detail::fft::N<DDimX>(x_mesh)
359 :
ddc::detail::fft::LastSelector<
int, DDimX, DDimX...>(
360 ddc::detail::fft::N<DDimX>(x_mesh) / 2 + 1,
361 ddc::detail::fft::N<DDimX>(x_mesh)))))...);
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381template <
typename... DDimFx,
typename... DDimX>
386 return fourier_mesh<DDimFx...>(x_mesh, C2C);
390
391
392
393
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
427 typename MemorySpace,
431 ExecSpace
const& exec_space,
437 std::is_same_v<LayoutIn, Kokkos::layout_right>
438 && std::is_same_v<LayoutOut, Kokkos::layout_right>,
439 "Layouts must be right-handed");
441 (is_uniform_point_sampling_v<DDimX> && ...),
442 "DDimX dimensions should derive from UniformPointSampling");
444 (is_periodic_sampling_v<DDimFx> && ...),
445 "DDimFx dimensions should derive from PeriodicPointSampling");
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
480 typename MemorySpace,
484 ExecSpace
const& exec_space,
490 std::is_same_v<LayoutIn, Kokkos::layout_right>
491 && std::is_same_v<LayoutOut, Kokkos::layout_right>,
492 "Layouts must be right-handed");
494 (is_uniform_point_sampling_v<DDimX> && ...),
495 "DDimX dimensions should derive from UniformPointSampling");
497 (is_periodic_sampling_v<DDimFx> && ...),
498 "DDimFx dimensions should derive from PeriodicPointSampling");
friend class DiscreteDomain
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector< OTags... > const &rhs) const noexcept
The top-level namespace of DDC.
ddc::FFT_Normalization normalization
Enum member to identify the type of normalization performed.
void ifft(ExecSpace const &exec_space, ddc::ChunkSpan< Tout, ddc::DiscreteDomain< DDimX... >, LayoutOut, MemorySpace > out, ddc::ChunkSpan< Tin, ddc::DiscreteDomain< DDimFx... >, LayoutIn, MemorySpace > in, ddc::kwArgs_fft kwargs={ddc::FFT_Normalization::OFF})
Perform an inverse Fast Fourier Transform.
void fft(ExecSpace const &exec_space, ddc::ChunkSpan< Tout, ddc::DiscreteDomain< DDimFx... >, LayoutOut, MemorySpace > out, ddc::ChunkSpan< Tin, ddc::DiscreteDomain< DDimX... >, LayoutIn, MemorySpace > in, ddc::kwArgs_fft kwargs={ddc::FFT_Normalization::OFF})
Perform a direct Fast Fourier Transform.
ddc::DiscreteDomain< DDimFx... > FourierMesh(ddc::DiscreteDomain< DDimX... > x_mesh, bool C2C)
Get the Fourier mesh.
FFT_Normalization
A named argument to choose the type of normalization of the FFT.
@ BACKWARD
No normalization for forward FFT, multiply by 1/N for backward FFT.
@ OFF
No normalization. Un-normalized FFT is sum_j f(x_j)*e^-ikx_j.
@ ORTHO
Multiply by 1/sqrt(N)
@ FULL
Multiply by dx/sqrt(2*pi) for forward FFT and dk/sqrt(2*pi) for backward FFT.
@ FORWARD
Multiply by 1/N for forward FFT, no normalization for backward FFT.
ddc::DiscreteDomain< DDimFx... > fourier_mesh(ddc::DiscreteDomain< DDimX... > x_mesh, bool C2C)
Get the Fourier mesh.
DDimFx::template Impl< DDimFx, Kokkos::HostSpace > init_fourier_space(ddc::DiscreteDomain< DDimX > x_mesh)
Initialize a Fourier discrete dimension.
FFT_Direction
A named argument to choose the direction of the FFT.
@ BACKWARD
Backward, corresponds to inverse FFT up to normalization.
@ FORWARD
Forward, corresponds to direct FFT up to normalization.
A structure embedding the configuration of the exposed FFT function with the type of normalization.