aboutsummaryrefslogtreecommitdiff
path: root/Source/FieldSolver/SpectralSolver/AnyFFT.H
diff options
context:
space:
mode:
Diffstat (limited to 'Source/FieldSolver/SpectralSolver/AnyFFT.H')
-rw-r--r--Source/FieldSolver/SpectralSolver/AnyFFT.H91
1 files changed, 91 insertions, 0 deletions
diff --git a/Source/FieldSolver/SpectralSolver/AnyFFT.H b/Source/FieldSolver/SpectralSolver/AnyFFT.H
new file mode 100644
index 000000000..a02f86343
--- /dev/null
+++ b/Source/FieldSolver/SpectralSolver/AnyFFT.H
@@ -0,0 +1,91 @@
+#ifndef ANYFFT_H_
+#define ANYFFT_H_
+
+#ifdef AMREX_USE_GPU
+# include <cufft.h>
+#else
+# include <fftw3.h>
+#endif
+
+#include <AMReX_LayoutData.H>
+
+/**
+ * Wrapper around FFT libraries. The header file defines the API and the base types
+ * (Complex and VendorFFTPlan), and the implementation for different FFT libraries is
+ * done in different cpp files. This wrapper only depends on the underlying FFT library
+ * AND on AMReX (There is no dependence on WarpX).
+ */
+namespace AnyFFT
+{
+ // First, define library-dependent types (complex, FFT plan)
+
+ /** Complex type for FFT, depends on FFT library */
+#ifdef AMREX_USE_GPU
+# ifdef AMREX_USE_FLOAT
+ using Complex = cuComplex;
+# else
+ using Complex = cuDoubleComplex;
+# endif
+#else
+# ifdef AMREX_USE_FLOAT
+ using Complex = fftwf_complex;
+# else
+ using Complex = fftw_complex;
+# endif
+#endif
+
+ /** Library-dependent FFT plans type, which holds one fft plan per box
+ * (plans are only initialized for the boxes that are owned by the local MPI rank).
+ */
+#ifdef AMREX_USE_GPU
+ using VendorFFTPlan = cufftHandle;
+#else
+# ifdef AMREX_USE_FLOAT
+ using VendorFFTPlan = fftwf_plan;
+# else
+ using VendorFFTPlan = fftw_plan;
+# endif
+#endif
+
+ // Second, define library-independent API
+
+ /** Direction in which the FFT is performed. */
+ enum struct direction {R2C, C2R};
+
+ /** This struct contains the vendor FFT plan and additional metadata
+ */
+ struct FFTplan
+ {
+ amrex::Real* m_real_array; /**< pointer to real array */
+ Complex* m_complex_array; /**< pointer to complex array */
+ VendorFFTPlan m_plan; /**< Vendor FFT plan */
+ direction m_dir; /**< direction (C2R or R2C) */
+ int m_dim; /**< Dimensionality of the FFT plan */
+ };
+
+ /** Collection of FFT plans, one FFTplan per box */
+ using FFTplans = amrex::LayoutData<FFTplan>;
+
+ /** \brief create FFT plan for the backend FFT library.
+ * \param[in] real_size Size of the real array, along each dimension.
+ * Only the first dim elements are used.
+ * \param[out] real_array Real array from/to where R2C/C2R FFT is performed
+ * \param[out] complex_array Complex array to/from where R2C/C2R FFT is performed
+ * \param[in] dir direction, either R2C or C2R
+ * \param[in] dim direction, number of dimensions of the arrays. Must be <= AMREX_SPACEDIM.
+ */
+ FFTplan CreatePlan(const amrex::IntVect& real_size, amrex::Real * const real_array,
+ Complex * const complex_array, const direction dir, const int dim);
+
+ /** \brief Destroy library FFT plan.
+ * \param[out] fft_plan plan to destroy
+ */
+ void DestroyPlan(FFTplan& fft_plan);
+
+ /** \brief Perform FFT with backend library.
+ * \param[out] fft_plan plan for which the FFT is performed
+ */
+ void Execute(FFTplan& fft_plan);
+}
+
+#endif // ANYFFT_H_