//////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008 The Regents of the University of California // // This file is part of Qbox // // Qbox is distributed under the terms of the GNU General Public License // as published by the Free Software Foundation, either version 2 of // the License, or (at your option) any later version. // See the file COPYING in the root directory of this distribution // or . // //////////////////////////////////////////////////////////////////////////////// // // FourierTransform.h // //////////////////////////////////////////////////////////////////////////////// #ifndef FOURIERTRANSFORM_H #define FOURIERTRANSFORM_H #include #include #if !( defined(USE_FFTW2) || defined(USE_FFTW3) || defined(USE_ESSL_FFT) || defined(FFT_NOLIB) ) #error "Must define USE_FFTW2, USE_FFTW3, USE_ESSL_FFT or FFT_NOLIB" #endif #if defined(USE_FFTW2) && defined(USE_FFTW3) #error "Cannot define USE_FFTW2 and USE_FFTW3" #endif #if USE_FFTW2 #if USE_DFFTW #include "dfftw.h" #else #include "fftw.h" #endif #endif #if USE_FFTW3 #include "fftw3.h" #if USE_FFTW3MKL #include "fftw3_mkl.h" #endif #endif #if USE_MPI #include #endif #include "Timer.h" class Basis; class FourierTransform { private: MPI_Comm comm_; const Basis& basis_; int nprocs_, myproc_; int np0_,np1_,np2_; int ntrans0_,ntrans1_,ntrans2_; int nvec_; std::vector np2_loc_; // np2_loc_[iproc], iproc=0, nprocs_-1 std::vector np2_first_; // np2_first_[iproc], iproc=0, nprocs_-1 std::vector > zvec_; std::vector scounts, sdispl, rcounts, rdispl; std::vector > sbuf, rbuf; std::vector ifftp_, ifftm_; std::vector ipack_, iunpack_; void init_lib(void); #if USE_ESSL_FFT #if USE_ESSL_2DFFT std::vector aux1xyf,aux1zf; std::vector aux1xyb,aux1zb; std::vector aux2; int naux1xy,naux1z,naux2; #else std::vector aux1xf, aux1yf, aux1zf; std::vector aux1xb, aux1yb, aux1zb; std::vector aux2; int naux1x,naux1y,naux1z,naux2; #endif #elif USE_FFTW2 fftw_plan fwplan0,fwplan1,fwplan2,bwplan0,bwplan1,bwplan2; #elif USE_FFTW3 //plans for np2_ fftw_plan fwplan, bwplan; #if defined(USE_FFTW3_2D) || defined(USE_FFTW3_THREADS) fftw_plan fwplan2d, bwplan2d; #else fftw_plan fwplanx, fwplany, bwplanx, bwplany; #endif #elif defined(FFT_NOLIB) // no library #else #error "Must define USE_FFTW2, USE_FFTW3, USE_ESSL_FFT or FFT_NOLIB" #endif void vector_to_zvec(const std::complex* c); void zvec_to_vector(std::complex* c); void doublevector_to_zvec(const std::complex* c1, const std::complex *c2); void zvec_to_doublevector(std::complex* c1, std::complex* c2); void fwd(std::complex* val); void bwd(std::complex* val); public: FourierTransform (const Basis &basis, int np0, int np1, int np2); ~FourierTransform (); MPI_Comm comm(void) const { return comm_; } // backward: Fourier synthesis, compute real-space function // forward: Fourier analysis, compute Fourier coefficients // forward transform includes scaling by 1/np012 // single transforms: c -> f, f -> c void backward (const std::complex* c, std::complex* f); // Note: forward transforms overwrite the array f void forward(std::complex* f, std::complex* c); // double transforms: c1 + i*c2 -> f, f -> c1 + i*c2 void backward (const std::complex* c1, const std::complex* c2, std::complex* f); // Note: forward transforms overwrite the array f void forward(std::complex* f, std::complex* c1, std::complex* c2); int np0() const { return np0_; } int np1() const { return np1_; } int np2() const { return np2_; } int np2_loc() const { return np2_loc_[myproc_]; } int np2_loc(int iproc) const { return np2_loc_[iproc]; } int np2_first() const { return np2_first_[myproc_]; } int np2_first(int iproc) const { return np2_first_[iproc]; } long int np012() const { return ((long int)np0_) * np1_ * np2_; } int np012loc(int iproc) const { return np0_ * np1_ * np2_loc_[iproc]; } int np012loc() const { return np0_ * np1_ * np2_loc_[myproc_]; } int index(int i, int j, int k) const { return i + np0_ * ( j + np1_ * k ); } int i(int ind) const { return ind % np0_; } int j(int ind) const { return (ind / np0_) % np1_; } int k(int ind) const { return (ind / np0_) / np1_ + np2_first(); } void reset_timers(void); Timer tm_f_map, tm_f_fft, tm_f_pack, tm_f_mpi, tm_f_zero, tm_f_unpack, tm_b_map, tm_b_fft, tm_b_pack, tm_b_mpi, tm_b_zero, tm_b_unpack, tm_f_xy, tm_f_z, tm_f_x, tm_f_y, tm_b_xy, tm_b_z, tm_b_x, tm_b_y, tm_init, tm_b_com, tm_f_com; }; #endif