24#ifdef ESPRESSO_KOKKOS_FFT
30#include <boost/mpi/communicator.hpp>
32#include <KokkosFFT.hpp>
33#include <Kokkos_Core.hpp>
66template <
typename FloatType,
class FFTConfig>
67struct P3MFFTKokkos final :
public P3MFFTBackend<FloatType, FFTConfig> {
68 static_assert(FFTConfig::use_r2c,
69 "kokkos-fft P3M backend implements the r2c transform only");
70 static_assert(FFTConfig::r2c_dir == 2u,
71 "kokkos-fft P3M backend reduces the contiguous last axis");
74 "kokkos-fft P3M backend supports row-major layout only");
77 using ComplexType =
typename Base::ComplexType;
78 using RSpaceScalar =
typename Base::RSpaceScalar;
79 using KComplex = Kokkos::complex<FloatType>;
80 using ExecSpace = Kokkos::DefaultHostExecutionSpace;
83 Kokkos::View<FloatType ***, Kokkos::LayoutRight, Kokkos::HostSpace>;
85 Kokkos::View<FloatType ***, Kokkos::LayoutRight, Kokkos::HostSpace,
86 Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
88 Kokkos::View<KComplex ***, Kokkos::LayoutRight, Kokkos::HostSpace,
89 Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
90 using ForwardPlan = KokkosFFT::Plan<ExecSpace, RealViewU, CplxViewU, 3>;
91 using BackwardPlan = KokkosFFT::Plan<ExecSpace, CplxViewU, RealViewU, 3>;
93 P3MFFTKokkos(boost::mpi::communicator comm,
98 : m_mesh{global_mesh},
99 m_ks_size{global_mesh[0], global_mesh[1], global_mesh[2] / 2 + 1} {
102 assert(comm.size() == 1);
103 assert((rs_local_ur_index - rs_local_ld_index) == global_mesh);
104 static_cast<void>(comm);
105 static_cast<void>(rs_local_ld_index);
106 static_cast<void>(rs_local_ur_index);
108 m_real_scratch = RealView(Kokkos::view_alloc(Kokkos::WithoutInitializing,
109 "P3MFFTKokkos::real_scratch"),
110 m_mesh[0], m_mesh[1], m_mesh[2]);
113 Utils::Vector3i ks_local_ld_index()
const override {
return {0, 0, 0}; }
114 Utils::Vector3i ks_local_ur_index()
const override {
return m_ks_size; }
120 RSpaceScalar *forward_input_buffer()
override {
121 return m_real_scratch.
data();
124 void forward(RSpaceScalar
const *in, ComplexType *out)
override {
125 RealViewU
const scratch_view(m_real_scratch.data(), m_mesh[0], m_mesh[1],
129 if (in != m_real_scratch.data()) {
130 RealViewU
const in_view(
const_cast<FloatType *
>(in), m_mesh[0], m_mesh[1],
132 Kokkos::deep_copy(m_real_scratch, in_view);
134 CplxViewU
const out_view(
reinterpret_cast<KComplex *
>(out), m_ks_size[0],
135 m_ks_size[1], m_ks_size[2]);
136 if (not m_forward or m_forward_out != out) {
137 m_forward = std::make_unique<ForwardPlan>(
138 ExecSpace{}, scratch_view, out_view, KokkosFFT::Direction::forward,
139 KokkosFFT::axis_type<3>({0, 1, 2}));
142 KokkosFFT::execute(*m_forward, scratch_view, out_view,
143 KokkosFFT::Normalization::none);
146 void backward(ComplexType *in, RSpaceScalar *out)
override {
150 CplxViewU
const in_view(
reinterpret_cast<KComplex *
>(in), m_ks_size[0],
151 m_ks_size[1], m_ks_size[2]);
152 RealViewU
const out_view(out, m_mesh[0], m_mesh[1], m_mesh[2]);
153 KokkosFFT::execute(backward_plan(in, out, in_view, out_view), in_view,
154 out_view, KokkosFFT::Normalization::none);
159 struct BackwardEntry {
162 std::unique_ptr<BackwardPlan> plan;
173 BackwardPlan &backward_plan(
void const *in,
void const *out,
174 CplxViewU
const &in_view,
175 RealViewU
const &out_view) {
176 for (
auto &entry : m_backward) {
177 if (entry.in == in and entry.out == out) {
181 auto plan = std::make_unique<BackwardPlan>(
182 ExecSpace{}, in_view, out_view, KokkosFFT::Direction::backward,
183 KokkosFFT::axis_type<3>({0, 1, 2}));
184 m_backward.push_back({in, out, std::move(plan)});
185 return *m_backward.back().plan;
190 RealView m_real_scratch;
191 ComplexType
const *m_forward_out =
nullptr;
192 std::unique_ptr<ForwardPlan> m_forward;
193 std::vector<BackwardEntry> m_backward;
Vector implementation and trait types for boost qvm interoperability.
DEVICE_QUALIFIER constexpr pointer data() noexcept
Abstract interface for the P3M reciprocal-space FFT.