Perform forward real-to-complex FFT transform.
Perform forward real-to-complex FFT transformTransforms real-space data to Fourier-space (k-space) using a distributed 3D FFT. The output exploits conjugate symmetry (half-space representation).
#pragma once
#include <heffte.h>
#include <iostream>
#include <memory>
#include <mpi.h>
namespace pfc {
namespace fft {
namespace layout {
struct FFTLayout {
};
const FFTLayout
create(
const Decomposition &decomposition,
int r2c_direction);
inline const auto &get_real_box(const FFTLayout &layout, int i) {
return layout.m_real_boxes.at(i);
}
inline const auto &get_complex_box(const FFTLayout &layout, int i) {
return layout.m_complex_boxes.at(i);
}
inline auto get_r2c_direction(const FFTLayout &layout) {
return layout.m_r2c_direction;
}
}
using pfc::types::Real3;
using RealVector = std::vector<double>;
using ComplexVector = std::vector<std::complex<double>>;
using RealDataBuffer = core::DataBuffer<backend::CpuTag, double>;
using ComplexDataBuffer = core::DataBuffer<backend::CpuTag, std::complex<double>>;
#if defined(OpenPFC_ENABLE_CUDA)
using RealDataBufferCUDA = core::DataBuffer<backend::CudaTag, double>;
using ComplexDataBufferCUDA =
core::DataBuffer<backend::CudaTag, std::complex<double>>;
#endif
};
#if defined(OpenPFC_ENABLE_CUDA)
using fft_r2c_cuda =
#endif
struct IFFT {
virtual ~IFFT() = default;
virtual void forward(
const RealVector &in, ComplexVector &out) = 0;
virtual void backward(
const ComplexVector &in, RealVector &out) = 0;
virtual void reset_fft_time() = 0;
virtual double get_fft_time() const = 0;
virtual size_t size_inbox() const = 0;
virtual size_t size_outbox() const = 0;
virtual size_t size_workspace() const = 0;
};
template <typename BackendTag = heffte::backend::fftw> struct FFT_Impl : IFFT {
BackendTag>::template buffer_container<std::complex<double>>;
workspace_type
FFT_Impl(fft_type fft) :
m_fft(std::move(fft)),
m_wrk(
m_fft.size_workspace()) {}
template <typename RealBackendTag, typename ComplexBackendTag, typename RealType>
void forward(const core::DataBuffer<RealBackendTag, RealType> &in,
core::DataBuffer<ComplexBackendTag, std::complex<RealType>> &out) {
static_assert(std::is_same_v<RealBackendTag, ComplexBackendTag>,
"Input and output must use the same backend");
std::complex<RealType>>(
m_fft.size_workspace());
m_fft.forward(in.data(), out.data(), wrk.data());
}
void forward(const RealVector &in, ComplexVector &out) override {
if constexpr (std::is_same_v<BackendTag, heffte::backend::fftw>) {
m_fft.forward(in.data(), out.data(),
m_wrk.data());
} else {
throw std::runtime_error(
"GPU FFT requires DataBuffer, not std::vector. Use forward(DataBuffer, "
"DataBuffer) instead.");
}
}
template <typename ComplexBackendTag, typename RealBackendTag, typename RealType>
void
backward(const core::DataBuffer<ComplexBackendTag, std::complex<RealType>> &in,
core::DataBuffer<RealBackendTag, RealType> &out) {
static_assert(std::is_same_v<ComplexBackendTag, RealBackendTag>,
"Input and output must use the same backend");
std::complex<RealType>>(
m_fft.size_workspace());
}
void backward(const ComplexVector &in, RealVector &out) override {
if constexpr (std::is_same_v<BackendTag, heffte::backend::fftw>) {
} else {
throw std::runtime_error(
"GPU FFT requires DataBuffer, not std::vector. Use backward(DataBuffer, "
"DataBuffer) instead.");
}
}
return m_wrk.size() *
sizeof(
typename workspace_type::value_type);
}
};
using FFT = FFT_Impl<heffte::backend::fftw>;
template <typename BackendTag>
inline const auto &get_fft_object(const FFT_Impl<BackendTag> &fft) noexcept {
return fft.m_fft;
}
template <typename BackendTag>
inline auto get_inbox(const FFT_Impl<BackendTag> &fft) noexcept {
return get_fft_object(fft).inbox();
}
template <typename BackendTag>
inline auto get_outbox(const FFT_Impl<BackendTag> &fft) noexcept {
return get_fft_object(fft).outbox();
}
using heffte::plan_options;
using layout::FFTLayout;
FFT
create(
const FFTLayout &fft_layout,
int rank_id, plan_options options);
FFT create(const Decomposition &decomposition, int rank_id);
FFT create(const Decomposition &decomposition);
std::unique_ptr<IFFT>
create_with_backend(
const FFTLayout &fft_layout,
int rank_id,
plan_options options, Backend backend);
std::unique_ptr<IFFT> create_with_backend(const Decomposition &decomposition,
int rank_id, Backend backend);
}
using FFTLayout = fft::layout::FFTLayout;
}
std::array< int, 3 > Int3
Type aliases for clarity.
Definition types.hpp:45
Backend-agnostic memory buffer with tag-based dispatch.
Domain decomposition for parallel MPI simulations.
Adapter functions for HeFFTe library integration.
K-space (Fourier space) helper functions for spectral methods.
Describes a static, pure partitioning of the global simulation domain into local subdomains.
Definition decomposition.hpp:182
void reset_fft_time() override
Resets the recorded FFT computation time to zero.
Definition fft.hpp:416
size_t size_inbox() const override
Returns the associated Decomposition object.
Definition fft.hpp:437
size_t size_outbox() const override
Returns the size of the outbox used for FFT computations.
Definition fft.hpp:444
double m_fft_time
Definition fft.hpp:255
size_t size_workspace() const override
Returns the size of the workspace used for FFT computations.
Definition fft.hpp:451
const fft_type m_fft
Definition fft.hpp:254
double get_fft_time() const override
Returns the recorded FFT computation time.
Definition fft.hpp:423
workspace_type m_wrk
Definition fft.hpp:262
size_t get_allocated_memory_bytes() const override
Returns the total memory allocated by HeFFTe in bytes.
Definition fft.hpp:460
virtual void backward(const ComplexVector &in, RealVector &out)=0
Performs the backward (inverse) FFT transformation.
virtual void forward(const RealVector &in, ComplexVector &out)=0
Performs the forward FFT transformation.
virtual size_t get_allocated_memory_bytes() const =0
Returns the total memory allocated by HeFFTe in bytes.
const Decomposition m_decomposition
The Decomposition object.
Definition fft.hpp:73
const std::vector< heffte::box3d< int > > m_complex_boxes
Complex boxes for FFT.
Definition fft.hpp:76
const int m_r2c_direction
Real-to-complex symmetry direction.
Definition fft.hpp:74
const std::vector< heffte::box3d< int > > m_real_boxes
Real boxes for FFT.
Definition fft.hpp:75
World(const Int3 &lower, const Int3 &upper, const CoordinateSystem< T > &cs)
Constructs a World object.
World class definition and unified interface.