#ifndef __COSMOTOOL_FOURIER_EUCLIDIAN_HPP #define __COSMOTOOL_FOURIER_EUCLIDIAN_HPP #include #include #include "base_types.hpp" #include "fft/fftw_calls.hpp" namespace CosmoTool { template class EuclidianFourierMap: public FourierMap { private: boost::shared_ptr m_data; std::vector m_dims; long m_size; public: EuclidianFourierMap(boost::shared_ptr indata, std::vector indims) { m_data = indata; m_dims = indims; m_size = 1; for (int i = 0; i < m_dims.size(); i++) m_size *= m_dims[i]; } virtual ~EuclidianFourierMap() { } virtual const T *data() const { return m_data.get(); } virtual T *data() { return m_data.get(); } virtual long size() const { return m_size; } virtual FourierMap *copy() const { FourierMap *m = this->mimick(); m->eigen() = this->eigen(); return m; } virtual FourierMap *mimick() const { return new EuclidianFourierMap( boost::shared_ptr((T *)fftw_malloc(sizeof(T)*m_size), std::ptr_fun(fftw_free)), m_dims); } }; template class EuclidianFourierTransform: public FourierTransform { private: typedef FFTW_Calls calls; EuclidianFourierMap *realMap; EuclidianFourierMap > *fourierMap; typename calls::plan_type m_analysis, m_synthesis; double volume; long N; std::vector m_dims; std::vector m_L; public: EuclidianFourierTransform(const std::vector& dims, const std::vector& L) { assert(L.size() == dims.size()); m_dims = dims; m_L = L; N = 1; volume = 1; for (int i = 0; i < dims.size(); i++) { N *= dims[i]; volume *= L[i]; } realMap = new EuclidianFourierMap( boost::shared_ptr(calls::alloc_real(N), std::ptr_fun(calls::free)), dims); fourierMap = new EuclidianFourierMap >( boost::shared_ptr >((std::complex*)calls::alloc_complex(N), std::ptr_fun(calls::free)), dims); m_analysis = calls::plan_dft_r2c(dims.size(), &dims[0], realMap->data(), (typename calls::complex_type *)fourierMap->data(), FFTW_MEASURE); m_synthesis = calls::plan_dft_c2r(dims.size(), &dims[0], (typename calls::complex_type *)fourierMap->data(), realMap->data(), FFTW_MEASURE); } virtual ~EuclidianFourierTransform() { delete realMap; delete fourierMap; calls::destroy_plan(m_synthesis); calls::destroy_plan(m_analysis); } void synthesis() { calls::execute(m_synthesis); realMap->scale(1/volume); } void analysis() { calls::execute(m_analysis); fourierMap->scale(volume/N); } void synthesis_conjugate() { calls::execute(m_analysis); fourierMap->scale(1/volume); } void analysis_conjugate() { calls::execute(m_synthesis); realMap->scale(volume/N); } const FourierMap >& fourierSpace() const { return *fourierMap; } FourierMap >& fourierSpace() { return *fourierMap; } const FourierMap& realSpace() const { return *realMap; } FourierMap& realSpace() { return *realMap; } FourierTransform *mimick() const { return new EuclidianFourierTransform(m_dims, m_L); } }; template class EuclidianFourierTransform_2d: public EuclidianFourierTransform { private: template static std::vector make_2d_vector(T2 a, T2 b) { T2 arr[2] = { a, b}; return std::vector(&arr[0], &arr[2]); } public: EuclidianFourierTransform_2d(int Nx, int Ny, double Lx, double Ly) : EuclidianFourierTransform(make_2d_vector(Nx, Ny), make_2d_vector(Lx, Ly)) { } virtual ~EuclidianFourierTransform_2d() {} }; template class EuclidianFourierTransform_3d: public EuclidianFourierTransform { private: template static std::vector make_3d_vector(T2 a, T2 b, T2 c) { T2 arr[2] = { a, b, c}; return std::vector(&arr[0], &arr[3]); } public: EuclidianFourierTransform_3d(int Nx, int Ny, int Nz, double Lx, double Ly, double Lz) : EuclidianFourierTransform(make_3d_vector(Nx, Ny, Nz), make_3d_vector(Lx, Ly, Lz)) { } virtual ~EuclidianFourierTransform_3d() {} }; }; #endif