13#include <KokkosFFT.hpp>
14#include <Kokkos_Core.hpp>
19
20
21
22
23template <
typename Dim>
29
30
31
32
39
40
41
42
49
50
51
52
57namespace ddc::detail::fft {
66struct RealType<Kokkos::complex<T>>
72using real_type_t = RealType<T>::type;
76struct is_complex : std::false_type
81struct is_complex<Kokkos::complex<T>> : std::true_type
86constexpr bool is_complex_v = is_complex<T>::value;
89
90
91
92
100template <
typename... DDimX>
101KokkosFFT::axis_type<
sizeof...(DDimX)> axes()
103 return KokkosFFT::axis_type<
sizeof...(DDimX)> {
104 static_cast<
int>(
ddc::type_seq_rank_v<DDimX,
ddc::detail::TypeSeq<DDimX...>>)...};
107KokkosFFT::Normalization ddc_fft_normalization_to_kokkos_fft(
116 explicit ScaleFn(T coef)
noexcept : m_coef(std::move(coef)) {}
119 [[nodiscard]] KOKKOS_FUNCTION U operator()(U
const& value)
const noexcept
121 return m_coef * value;
126Real forward_full_norm_coef(
DiscreteDomain<DDim>
const& ddom)
noexcept
128 return rlength(ddom) / Kokkos::sqrt(2 * Kokkos::numbers::pi_v<Real>)
129 / (ddom.extents() - 1).value();
133Real backward_full_norm_coef(
DiscreteDomain<DDim>
const& ddom)
noexcept
135 return 1 / (forward_full_norm_coef(ddom) * ddom.extents().value());
143 typename MemorySpace,
149 ExecSpace
const& exec_space,
152 KwArgsImpl
const& kwargs)
155 std::is_same_v<real_type_t<Tin>,
float> || std::is_same_v<real_type_t<Tin>,
double>,
156 "Base type of Tin (and Tout) must be float or double.");
158 std::is_same_v<real_type_t<Tin>, real_type_t<Tout>>,
159 "Types Tin and Tout must be based on same type (float or double)");
161 Kokkos::SpaceAccessibility<ExecSpace, MemorySpace>::accessible,
162 "MemorySpace has to be accessible for ExecutionSpace.");
165 ddc::detail::mdspan_to_kokkos_element_t<Tin,
sizeof...(DDimIn)>,
166 ddc::detail::mdspan_to_kokkos_layout_t<LayoutIn>,
167 MemorySpace>
const in_view
168 = in.allocation_kokkos_view();
170 ddc::detail::mdspan_to_kokkos_element_t<Tout,
sizeof...(DDimIn)>,
171 ddc::detail::mdspan_to_kokkos_layout_t<LayoutOut>,
172 MemorySpace>
const out_view
173 = out.allocation_kokkos_view();
174 KokkosFFT::Normalization
const kokkos_fft_normalization
175 = ddc_fft_normalization_to_kokkos_fft(kwargs.normalization);
178 if constexpr (std::is_same_v<Tin, Tout>) {
185 kokkos_fft_normalization);
192 kokkos_fft_normalization);
196 if constexpr (is_complex_v<Tout>) {
203 kokkos_fft_normalization);
211 kokkos_fft_normalization);
220 norm_coef = (forward_full_norm_coef(DiscreteDomain<DDimIn>(ddom_in)) * ...);
223 norm_coef = (backward_full_norm_coef(DiscreteDomain<DDimOut>(ddom_out)) * ...);
226 ddc::parallel_transform(
"ddc_fft", exec_space, out, ScaleFn<real_type_t<Tout>>(norm_coef));
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253template <
typename DDimFx,
typename DDimX>
258 is_uniform_point_sampling_v<DDimX>,
259 "DDimX dimension must derive from UniformPointSampling");
261 is_periodic_sampling_v<DDimFx>,
262 "DDimFx dimension must derive from PeriodicSampling");
263 using CDimFx = DDimFx::continuous_dimension_type;
264 using CDimX = DDimX::continuous_dimension_type;
267 "DDimX and DDimFx dimensions must be defined over the same continuous dimension");
269 DiscreteVectorElement
const nx = get<DDimX>(x_mesh.extents());
270 double const lx =
ddc::rlength(x_mesh);
271 auto [impl, ddom] = DDimFx::
template init<DDimFx>(
272 ddc::Coordinate<CDimFx>(0),
273 ddc::Coordinate<CDimFx>(2 * (nx - 1) * (nx - 1) / (nx * lx) * Kokkos::numbers::pi),
276 return std::move(impl);
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294template <
typename... DDimFx,
typename... DDimX>
298 (is_uniform_point_sampling_v<DDimX> && ...),
299 "DDimX dimensions should derive from UniformPointSampling");
301 (is_periodic_sampling_v<DDimFx> && ...),
302 "DDimFx dimensions should derive from PeriodicPointSampling");
305 detail::array(extents).back() = detail::array(extents).back() / 2 + 1;
308 ddc::DiscreteElement<DDimFx>(0),
313
314
315
316
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
350 typename MemorySpace,
354 ExecSpace
const& exec_space,
360 std::is_same_v<LayoutIn, Kokkos::layout_right>
361 && std::is_same_v<LayoutOut, Kokkos::layout_right>,
362 "Layouts must be right-handed");
364 (is_uniform_point_sampling_v<DDimX> && ...),
365 "DDimX dimensions should derive from UniformPointSampling");
367 (is_periodic_sampling_v<DDimFx> && ...),
368 "DDimFx dimensions should derive from PeriodicPointSampling");
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
403 typename MemorySpace,
407 ExecSpace
const& exec_space,
413 std::is_same_v<LayoutIn, Kokkos::layout_right>
414 && std::is_same_v<LayoutOut, Kokkos::layout_right>,
415 "Layouts must be right-handed");
417 (is_uniform_point_sampling_v<DDimX> && ...),
418 "DDimX dimensions should derive from UniformPointSampling");
420 (is_periodic_sampling_v<DDimFx> && ...),
421 "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 templated tag representing a continuous dimension in the Fourier space associated to the original c...
A structure embedding the configuration of the exposed FFT function with the type of normalization.