14#include <KokkosFFT.hpp>
15#include <Kokkos_Core.hpp>
20
21
22
23
24template <
typename Dim>
28
29
30
31
38
39
40
41
48
49
50
51
56namespace ddc::detail::fft {
65struct RealType<Kokkos::complex<T>>
71using real_type_t =
typename RealType<T>::type;
75struct is_complex : std::false_type
80struct is_complex<Kokkos::complex<T>> : std::true_type
85constexpr bool is_complex_v = is_complex<T>::value;
88
89
90
91
99template <
typename... DDimX>
100KokkosFFT::axis_type<
sizeof...(DDimX)> axes()
102 return KokkosFFT::axis_type<
sizeof...(DDimX)> {
103 static_cast<
int>(
ddc::type_seq_rank_v<DDimX,
ddc::detail::TypeSeq<DDimX...>>)...};
106inline KokkosFFT::Normalization ddc_fft_normalization_to_kokkos_fft(
111 return KokkosFFT::Normalization::none;
115 return KokkosFFT::Normalization::forward;
119 return KokkosFFT::Normalization::backward;
123 return KokkosFFT::Normalization::ortho;
126 throw std::runtime_error(
"ddc::FFT_Normalization not handled");
131 typename ElementType,
134 typename MemorySpace,
137 ExecSpace
const& exec_space,
138 ddc::
ChunkSpan<ElementType, DDom, Layout, MemorySpace>
const& chunk_span,
141 ddc::parallel_for_each(
142 "ddc_fft_normalization",
145 KOKKOS_LAMBDA(
typename DDom::discrete_element_type
const i) {
146 chunk_span(i) *= value;
151Real forward_full_norm_coef(
DiscreteDomain<DDim>
const& ddom)
noexcept
153 return rlength(ddom) / Kokkos::sqrt(2 * Kokkos::numbers::pi_v<Real>)
154 / (ddom.extents() - 1).value();
158Real backward_full_norm_coef(
DiscreteDomain<DDim>
const& ddom)
noexcept
160 return 1 / (forward_full_norm_coef(ddom) * ddom.extents().value());
168 typename MemorySpace,
174 ExecSpace
const& exec_space,
177 KwArgsImpl
const& kwargs)
180 std::is_same_v<real_type_t<Tin>,
float> || std::is_same_v<real_type_t<Tin>,
double>,
181 "Base type of Tin (and Tout) must be float or double.");
183 std::is_same_v<real_type_t<Tin>, real_type_t<Tout>>,
184 "Types Tin and Tout must be based on same type (float or double)");
186 Kokkos::SpaceAccessibility<ExecSpace, MemorySpace>::accessible,
187 "MemorySpace has to be accessible for ExecutionSpace.");
190 ddc::detail::mdspan_to_kokkos_element_t<Tin,
sizeof...(DDimIn)>,
191 ddc::detail::mdspan_to_kokkos_layout_t<LayoutIn>,
192 MemorySpace>
const in_view
193 = in.allocation_kokkos_view();
195 ddc::detail::mdspan_to_kokkos_element_t<Tout,
sizeof...(DDimIn)>,
196 ddc::detail::mdspan_to_kokkos_layout_t<LayoutOut>,
197 MemorySpace>
const out_view
198 = out.allocation_kokkos_view();
199 KokkosFFT::Normalization
const kokkos_fft_normalization
200 = ddc_fft_normalization_to_kokkos_fft(kwargs.normalization);
203 if constexpr (std::is_same_v<Tin, Tout>) {
210 kokkos_fft_normalization);
217 kokkos_fft_normalization);
221 if constexpr (is_complex_v<Tout>) {
222 assert(kwargs.direction == ddc::FFT_Direction::FORWARD);
228 kokkos_fft_normalization);
230 assert(kwargs.direction == ddc::FFT_Direction::BACKWARD);
236 kokkos_fft_normalization);
245 norm_coef = (forward_full_norm_coef(DiscreteDomain<DDimIn>(ddom_in)) * ...);
248 norm_coef = (backward_full_norm_coef(DiscreteDomain<DDimOut>(ddom_out)) * ...);
251 rescale(exec_space, out,
static_cast<real_type_t<Tout>>(norm_coef));
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278template <
typename DDimFx,
typename DDimX>
283 is_uniform_point_sampling_v<DDimX>,
284 "DDimX dimension must derive from UniformPointSampling");
286 is_periodic_sampling_v<DDimFx>,
287 "DDimFx dimension must derive from PeriodicSampling");
288 using CDimFx =
typename DDimFx::continuous_dimension_type;
289 using CDimX =
typename DDimX::continuous_dimension_type;
291 std::is_same_v<CDimFx,
ddc::Fourier<CDimX>>,
292 "DDimX and DDimFx dimensions must be defined over the same continuous dimension");
294 DiscreteVectorElement
const nx = get<DDimX>(x_mesh.extents());
295 double const lx =
ddc::rlength(x_mesh);
296 auto [impl, ddom] = DDimFx::
template init<DDimFx>(
297 ddc::Coordinate<CDimFx>(0),
298 ddc::Coordinate<CDimFx>(2 * (nx - 1) * (nx - 1) / (nx * lx) * Kokkos::numbers::pi),
301 return std::move(impl);
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319template <
typename... DDimFx,
typename... DDimX>
323 (is_uniform_point_sampling_v<DDimX> && ...),
324 "DDimX dimensions should derive from UniformPointSampling");
326 (is_periodic_sampling_v<DDimFx> && ...),
327 "DDimFx dimensions should derive from PeriodicPointSampling");
330 detail::array(extents).back() = detail::array(extents).back() / 2 + 1;
333 ddc::DiscreteElement<DDimFx>(0),
338
339
340
341
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
375 typename MemorySpace,
379 ExecSpace
const& exec_space,
385 std::is_same_v<LayoutIn, Kokkos::layout_right>
386 && std::is_same_v<LayoutOut, Kokkos::layout_right>,
387 "Layouts must be right-handed");
389 (is_uniform_point_sampling_v<DDimX> && ...),
390 "DDimX dimensions should derive from UniformPointSampling");
392 (is_periodic_sampling_v<DDimFx> && ...),
393 "DDimFx dimensions should derive from PeriodicPointSampling");
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
428 typename MemorySpace,
432 ExecSpace
const& exec_space,
438 std::is_same_v<LayoutIn, Kokkos::layout_right>
439 && std::is_same_v<LayoutOut, Kokkos::layout_right>,
440 "Layouts must be right-handed");
442 (is_uniform_point_sampling_v<DDimX> && ...),
443 "DDimX dimensions should derive from UniformPointSampling");
445 (is_periodic_sampling_v<DDimFx> && ...),
446 "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.
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.