src/FFT/FFT.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 //--------------------------------------------------------------------------
00012 // Class FFT
00013 //--------------------------------------------------------------------------
00014 
00015 #ifndef IPPL_FFT_FFT_H
00016 #define IPPL_FFT_FFT_H
00017 
00018 // include files
00019 #include "FFT/FFTBase.h"
00020 
00021 // forward declarations
00022 template <unsigned Dim> class FieldLayout;
00023 template <class T, unsigned Dim> class BareField;
00024 template <class T, unsigned Dim> class LField;
00025 
00026 
00037 class CCTransform {};
00041 class RCTransform {};
00045 class SineTransform {};
00046 
00050 template <class Transform, unsigned Dim, class T>
00051 class FFT : public FFTBase<Dim,T> {};
00052 
00053 
00057 template <unsigned Dim, class T>
00058 class FFT<CCTransform,Dim,T> : public FFTBase<Dim,T> {
00059 
00060 public: 
00061   
00062   // typedefs
00063   typedef FieldLayout<Dim> Layout_t;
00064 #ifdef IPPL_HAS_TEMPLATED_COMPLEX
00065   typedef complex<T> Complex_t;
00066 #else
00067   typedef complex Complex_t;
00068 #endif
00069   typedef BareField<Complex_t,Dim> ComplexField_t;
00070   typedef LField<Complex_t,Dim> ComplexLField_t;
00071   typedef typename FFTBase<Dim,T>::Domain_t Domain_t;
00072   
00078   FFT(const Domain_t& cdomain, const bool transformTheseDims[Dim],
00079       const bool& compressTemps=false);
00080   
00087   FFT(const Domain_t& cdomain, const bool& compressTemps=false)
00088     : FFTBase<Dim,T>(FFT<CCTransform,Dim,T>::ccFFT, cdomain,compressTemps) { 
00089     
00090     // construct array of axis lengths
00091     int lengths[Dim];
00092     unsigned d;
00093     for (d=0; d<Dim; ++d)
00094       lengths[d] = cdomain[d].length();
00095         
00096     // construct array of transform types for FFT Engine, compute normalization
00097     int transformTypes[Dim];
00098     T& normFact = this->getNormFact();
00099     normFact = 1.0;
00100     for (d=0; d<Dim; ++d) {
00101       transformTypes[d] = FFTBase<Dim,T>::ccFFT;  // all transforms are complex-to-complex
00102       normFact /= lengths[d];
00103     }
00104         
00105     // set up FFT Engine
00106     this->getEngine().setup(Dim, transformTypes, lengths);
00107     // set up the temporary fields
00108     setup();
00109   }
00110   
00111   
00112   // Destructor
00113   ~FFT(void);
00114 
00122   void transform(int direction, ComplexField_t& f, ComplexField_t& g,
00123                  const bool& constInput=false);
00127   void transform(const char* directionName, ComplexField_t& f,
00128                  ComplexField_t& g, const bool& constInput=false);
00129 
00132   void transform(int direction, ComplexField_t& f);
00133   void transform(const char* directionName, ComplexField_t& f) {
00134     // invoke in-place transform function using direction name string
00135     int direction = this->getDirection(directionName);
00136     
00137     // Check domain of incoming Field
00138     const Layout_t& in_layout = f.getLayout();
00139     const Domain_t& in_dom = in_layout.getDomain();
00140     PAssert(checkDomain(this->getDomain(),in_dom));
00141 
00142     // Common loop iterate and other vars:
00143     unsigned d;
00144     int idim;            // idim loops over the number of transform dims.
00145     int begdim, enddim;  // beginning and end of transform dim loop
00146     unsigned nTransformDims = this->numTransformDims();
00147     // Field* for temp Field management:
00148     ComplexField_t* temp = &f;
00149     // Local work array passed to FFT:
00150     Complex_t* localdata;
00151     
00152     // Loop over the dimensions be transformed:
00153     begdim = (direction == +1) ? 0 : (nTransformDims-1);
00154     enddim = (direction == +1) ? nTransformDims : -1;
00155     for (idim = begdim; idim != enddim; idim += direction) {
00156       TAU_PROFILE_START(timer_swap);
00157       // Now do the serial transforms along this dimension:
00158       
00159       bool skipTranspose = false;
00160       // if this is the first transform dimension, we might be able
00161       // to skip the transpose into the first temporary Field
00162       if (idim == begdim) {
00163         // get domain for comparison
00164         const Domain_t& first_dom = tempLayouts_m[idim]->getDomain();
00165         // check that zeroth axis is the same and is serial
00166         // and that there are no guard cells
00167         skipTranspose = ( (in_dom[0].sameBase(first_dom[0])) &&
00168                           (in_dom[0].length() == first_dom[0].length()) &&
00169                           (in_layout.getDistribution(0) == SERIAL) &&
00170                           (f.getGC() == FFT<CCTransform,Dim,T>::nullGC) );
00171       }
00172       
00173       // if this is the last transform dimension, we might be able
00174       // to skip the last temporary and transpose right into f
00175       if (idim == enddim-direction) {
00176         // get domain for comparison
00177         const Domain_t& last_dom = tempLayouts_m[idim]->getDomain();
00178         // check that zeroth axis is the same and is serial
00179         // and that there are no guard cells
00180         skipTranspose = ( (in_dom[0].sameBase(last_dom[0])) &&
00181                           (in_dom[0].length() == last_dom[0].length()) &&
00182                           (in_layout.getDistribution(0) == SERIAL) &&
00183                           (f.getGC() == FFT<CCTransform,Dim,T>::nullGC) );
00184       }
00185       
00186       if (!skipTranspose) {
00187         // transpose and permute to Field with transform dim first
00188         (*tempFields_m[idim])[tempLayouts_m[idim]->getDomain()] = 
00189           (*temp)[temp->getLayout().getDomain()];
00190         
00191         // Compress out previous iterate's storage:
00192         if (this->compressTemps() && temp != &f) *temp = 0;
00193         temp = tempFields_m[idim];  // Field* management aid
00194       }
00195       else if (idim == enddim-direction && temp != &f) {
00196         // last transform and we can skip the last temporary field
00197         // so do the transpose here using f instead
00198         
00199         // transpose and permute to Field with transform dim first
00200         f[in_dom] = (*temp)[temp->getLayout().getDomain()];
00201         
00202         // Compress out previous iterate's storage:
00203         if (this->compressTemps()) *temp = 0;
00204         temp = &f;  // Field* management aid
00205       }
00206       TAU_PROFILE_STOP(timer_swap);
00207       
00208       TAU_PROFILE_START(timer_fft);
00209       // Loop over all the Vnodes, working on the LField in each.
00210       typename ComplexField_t::const_iterator_if l_i, l_end = temp->end_if();
00211       for (l_i = temp->begin_if(); l_i != l_end; ++l_i) {
00212 
00213         // Get the LField
00214         ComplexLField_t* ldf = (*l_i).second.get();
00215         // make sure we are uncompressed
00216         ldf->Uncompress();
00217         // get the raw data pointer
00218         localdata = ldf->getP();
00219 
00220         // Do 1D complex-to-complex FFT's on all the strips in the LField:
00221         int nstrips = 1, length = ldf->size(0);
00222         for (d=1; d<Dim; ++d) nstrips *= ldf->size(d);
00223         for (int istrip=0; istrip<nstrips; ++istrip) {
00224           // Do the 1D FFT:
00225           this->getEngine().callFFT(idim, direction, localdata);
00226           // advance the data pointer
00227           localdata += length;
00228         } // loop over 1D strips
00229       } // loop over all the LFields
00230       TAU_PROFILE_STOP(timer_fft);
00231       
00232     } // loop over all transformed dimensions 
00233 
00234     // skip final assignment and compress if we used f as final temporary
00235     if (temp != &f) {
00236       TAU_PROFILE_START(timer_swap);
00237       // Now assign back into original Field, and compress last temp's storage:
00238       f[in_dom] = (*temp)[temp->getLayout().getDomain()];
00239       if (this->compressTemps()) *temp = 0;
00240       TAU_PROFILE_STOP(timer_swap);
00241     }
00242 
00243     // Normalize:
00244     if (direction == +1)
00245       f *= Complex_t(this->getNormFact(), 0.0);
00246     return;
00247   }
00248 private: 
00249   
00254   void setup(void);
00255 
00262   Layout_t** tempLayouts_m;
00263 
00267   ComplexField_t** tempFields_m;
00268   
00269 };
00270 
00271 
00275 template <unsigned Dim, class T>
00276 inline void
00277 FFT<CCTransform,Dim,T>::transform(
00278                                   const char* directionName,
00279                                   typename FFT<CCTransform,Dim,T>::ComplexField_t& f,
00280                                   typename FFT<CCTransform,Dim,T>::ComplexField_t& g,
00281                                   const bool& constInput)
00282 {
00283   int dir = this->getDirection(directionName);
00284   transform(dir, f, g, constInput);
00285   return;
00286 }
00287 
00288 
00292 template <class T>
00293 class FFT<CCTransform,1U,T> : public FFTBase<1U,T> {
00294   
00295 public: 
00296   
00297   // typedefs
00298   typedef FieldLayout<1U> Layout_t;
00299 #ifdef IPPL_HAS_TEMPLATED_COMPLEX
00300   typedef complex<T> Complex_t;
00301 #else
00302   typedef complex Complex_t;
00303 #endif
00304   typedef BareField<Complex_t,1U> ComplexField_t;
00305   typedef LField<Complex_t,1U> ComplexLField_t;
00306   typedef typename FFTBase<1U,T>::Domain_t Domain_t;
00307 
00308   // Constructors:
00309 
00315   FFT(const Domain_t& cdomain, const bool transformTheseDims[1U],
00316       const bool& compressTemps=false);
00323   FFT(const Domain_t& cdomain, const bool& compressTemps=false);
00324 
00325   // Destructor
00326   ~FFT(void);
00327   
00335   void transform(int direction, ComplexField_t& f, ComplexField_t& g,
00336                  const bool& constInput=false);
00340   void transform(const char* directionName, ComplexField_t& f,
00341                  ComplexField_t& g, const bool& constInput=false);
00342   
00346   void transform(int direction, ComplexField_t& f);
00347   void transform(const char* directionName, ComplexField_t& f);
00348 
00349 private: 
00350 
00355   void setup(void);
00356   
00360   Layout_t* tempLayouts_m;
00361 
00365   ComplexField_t* tempFields_m;
00366   
00367 };
00368 
00369 
00370 // inline function definitions
00371 
00375 template <class T>
00376 inline void
00377 FFT<CCTransform,1U,T>::transform(
00378                                  const char* directionName,
00379                                  typename FFT<CCTransform,1U,T>::ComplexField_t& f,
00380                                  typename FFT<CCTransform,1U,T>::ComplexField_t& g,
00381                                  const bool& constInput)
00382 {
00383   int dir = this->getDirection(directionName);
00384   transform(dir, f, g, constInput);
00385   return;
00386 }
00387 
00391 template <class T>
00392 inline void
00393 FFT<CCTransform,1U,T>::transform(
00394                                  const char* directionName,
00395                                  typename FFT<CCTransform,1U,T>::ComplexField_t& f)
00396 {
00397   int dir = this->getDirection(directionName);
00398   transform(dir, f);
00399   return;
00400 }
00401 
00402 
00403 
00404 
00408 template <unsigned Dim, class T>
00409 class FFT<RCTransform,Dim,T> : public FFTBase<Dim,T> {
00410   
00411 public: 
00412   
00413   // typedefs
00414   typedef FieldLayout<Dim> Layout_t;
00415   typedef BareField<T,Dim> RealField_t;
00416   typedef LField<T,Dim> RealLField_t;
00417 #ifdef IPPL_HAS_TEMPLATED_COMPLEX
00418   typedef complex<T> Complex_t;
00419 #else
00420   typedef complex Complex_t;
00421 #endif
00422   typedef BareField<Complex_t,Dim> ComplexField_t;
00423   typedef LField<Complex_t,Dim> ComplexLField_t;
00424   typedef typename FFTBase<Dim, T>::Domain_t Domain_t;
00425 
00426   // Constructors:
00427 
00433   FFT(const Domain_t& rdomain, const Domain_t& cdomain,
00434       const bool transformTheseDims[Dim], const bool& compressTemps=false);
00435 
00439   FFT(const Domain_t& rdomain, const Domain_t& cdomain,
00440       const bool& compressTemps=false, int serialAxes = 1);
00441 
00442   // Destructor
00443   ~FFT(void);
00444 
00452   void transform(int direction, RealField_t& f, ComplexField_t& g,
00453                  const bool& constInput=false);
00454   void transform(const char* directionName, RealField_t& f,
00455                  ComplexField_t& g, const bool& constInput=false);
00456 
00460   void transform(int direction, ComplexField_t& f, RealField_t& g,
00461                  const bool& constInput=false);
00462   void transform(const char* directionName, ComplexField_t& f,
00463                  RealField_t& g, const bool& constInput=false);
00464   
00465 private: 
00466   
00471   void setup(void);
00472   
00478   Layout_t** tempLayouts_m;
00479   
00483   Layout_t* tempRLayout_m;
00484 
00488   ComplexField_t** tempFields_m;
00489 
00493   RealField_t* tempRField_m;
00494 
00499   Domain_t complexDomain_m;
00500 
00504   int serialAxes_m;
00505 };
00506 
00507    // Inline function definitions
00508 
00512 template <unsigned Dim, class T>
00513 inline void
00514 FFT<RCTransform,Dim,T>::transform(
00515                                   const char* directionName,
00516                                   typename FFT<RCTransform,Dim,T>::RealField_t& f,
00517                                   typename FFT<RCTransform,Dim,T>::ComplexField_t& g,
00518                                   const bool& constInput)
00519 {
00520   int dir = this->getDirection(directionName);
00521   transform(dir, f, g, constInput);
00522   return;
00523 }
00524 
00528 template <unsigned Dim, class T>
00529 inline void
00530 FFT<RCTransform,Dim,T>::transform(
00531                                   const char* directionName,
00532                                   typename FFT<RCTransform,Dim,T>::ComplexField_t& f,
00533                                   typename FFT<RCTransform,Dim,T>::RealField_t& g,
00534                                   const bool& constInput)
00535 {
00536   int dir = this->getDirection(directionName);
00537   transform(dir, f, g, constInput);
00538   return;
00539 }
00540 
00541 
00545 template <class T>
00546 class FFT<RCTransform,1U,T> : public FFTBase<1U,T> {
00547   
00548 public: 
00549   
00550   // typedefs
00551   typedef FieldLayout<1U> Layout_t;
00552   typedef BareField<T,1U> RealField_t;
00553   typedef LField<T,1U> RealLField_t;
00554 #ifdef IPPL_HAS_TEMPLATED_COMPLEX
00555   typedef complex<T> Complex_t;
00556 #else
00557   typedef complex Complex_t;
00558 #endif
00559   typedef BareField<Complex_t,1U> ComplexField_t;
00560   typedef LField<Complex_t,1U> ComplexLField_t;
00561   typedef typename FFTBase<1U,T>::Domain_t Domain_t;
00562   
00563   // Constructors:
00564   
00571   FFT(const Domain_t& rdomain, const Domain_t& cdomain,
00572       const bool transformTheseDims[1U], const bool& compressTemps=false);
00576   FFT(const Domain_t& rdomain, const Domain_t& cdomain,
00577       const bool& compressTemps=false);
00578 
00582   ~FFT(void);
00583   
00592   void transform(int direction, RealField_t& f, ComplexField_t& g,
00593                  const bool& constInput=false);
00594   void transform(const char* directionName, RealField_t& f,
00595                  ComplexField_t& g, const bool& constInput=false);
00596 
00601   void transform(int direction, ComplexField_t& f, RealField_t& g,
00602                  const bool& constInput=false);
00603   void transform(const char* directionName, ComplexField_t& f,
00604                  RealField_t& g, const bool& constInput=false);
00605   
00606 private: 
00607   
00612   void setup(void);
00613    
00617   Layout_t* tempLayouts_m;
00618 
00622   ComplexField_t* tempFields_m;
00623 
00627   Layout_t* tempRLayout_m;
00628 
00633   //  const Domain_t& complexDomain_m;
00634   Domain_t complexDomain_m;
00635 };
00636 
00640 template <class T>
00641    inline void
00642 FFT<RCTransform,1U,T>::transform(
00643                                  const char* directionName,
00644                                  typename FFT<RCTransform,1U,T>::RealField_t& f,
00645                                  typename FFT<RCTransform,1U,T>::ComplexField_t& g,
00646                                  const bool& constInput)
00647 {
00648   int dir = this->getDirection(directionName);
00649   transform(dir, f, g, constInput);
00650   return;
00651 }
00652 
00656 template <class T>
00657 inline void
00658 FFT<RCTransform,1U,T>::transform(
00659                                  const char* directionName,
00660                                  typename FFT<RCTransform,1U,T>::ComplexField_t& f,
00661                                  typename FFT<RCTransform,1U,T>::RealField_t& g,
00662                                  const bool& constInput)
00663 {
00664   int dir = this->getDirection(directionName);
00665   transform(dir, f, g, constInput);
00666   return;
00667 }
00668 
00672 template <unsigned Dim, class T>
00673 class FFT<SineTransform,Dim,T> : public FFTBase<Dim,T> {
00674   
00675 public: 
00676   
00677   // typedefs
00678   typedef FieldLayout<Dim> Layout_t;
00679   typedef BareField<T,Dim> RealField_t;
00680   typedef LField<T,Dim> RealLField_t;
00681 #ifdef IPPL_HAS_TEMPLATED_COMPLEX
00682   typedef complex<T> Complex_t;
00683 #else
00684   typedef complex Complex_t;
00685 #endif
00686   typedef BareField<Complex_t,Dim> ComplexField_t;
00687   typedef LField<Complex_t,Dim> ComplexLField_t;
00688   typedef typename FFTBase<Dim,T>::Domain_t Domain_t;
00689   
00697   FFT(const Domain_t& rdomain, const Domain_t& cdomain,
00698       const bool transformTheseDims[Dim],
00699       const bool sineTransformDims[Dim], const bool& compressTemps=false);
00703   FFT(const Domain_t& rdomain, const Domain_t& cdomain,
00704       const bool sineTransformDims[Dim], const bool& compressTemps=false);
00712   FFT(const Domain_t& rdomain, const bool sineTransformDims[Dim],
00713       const bool& compressTemps=false);
00717   FFT(const Domain_t& rdomain, const bool& compressTemps=false);
00718   
00719   ~FFT(void);
00720 
00731   void transform(int direction, RealField_t& f, ComplexField_t& g,
00732                  const bool& constInput=false);
00733   void transform(const char* directionName, RealField_t& f,
00734                  ComplexField_t& g, const bool& constInput=false);
00735 
00740   void transform(int direction, ComplexField_t& f, RealField_t& g,
00741                  const bool& constInput=false);
00742   void transform(const char* directionName, ComplexField_t& f,
00743                  RealField_t& g, const bool& constInput=false);
00744 
00754   void transform(int direction, RealField_t& f, RealField_t& g,
00755                  const bool& constInput=false);
00756   void transform(const char* directionName, RealField_t& f,
00757                  RealField_t& g, const bool& constInput=false);
00758   
00762   void transform(int direction, RealField_t& f);
00763   void transform(const char* directionName, RealField_t& f);
00764   
00765 private: 
00766   
00771   void setup(void);
00772   
00773   
00774   
00778   bool sineTransformDims_m[Dim]; 
00779   
00783   unsigned numSineTransforms_m;  
00784   
00792   Layout_t** tempLayouts_m;
00793 
00797   Layout_t** tempRLayouts_m;
00798 
00802   ComplexField_t** tempFields_m;
00803   
00807   RealField_t** tempRFields_m;
00808 
00812   const Domain_t* complexDomain_m;  
00813 };
00814 
00818 template <unsigned Dim, class T>
00819 inline void
00820 FFT<SineTransform,Dim,T>::transform(
00821                                     const char* directionName,
00822                                     typename FFT<SineTransform,Dim,T>::RealField_t& f,
00823                                     typename FFT<SineTransform,Dim,T>::ComplexField_t& g,
00824                                     const bool& constInput)
00825 {
00826   int dir = this->getDirection(directionName);
00827   transform(dir, f, g, constInput);
00828   return;
00829 }
00830 
00834 template <unsigned Dim, class T>
00835 inline void
00836 FFT<SineTransform,Dim,T>::transform(
00837                                     const char* directionName,
00838                                     typename FFT<SineTransform,Dim,T>::ComplexField_t& f,
00839                                     typename FFT<SineTransform,Dim,T>::RealField_t& g,
00840                                     const bool& constInput)
00841 {
00842   int dir = this->getDirection(directionName);
00843    transform(dir, f, g, constInput);
00844    return;
00845 }
00846 
00850 template <unsigned Dim, class T>
00851 inline void
00852 FFT<SineTransform,Dim,T>::transform(
00853                                     const char* directionName,
00854                                     typename FFT<SineTransform,Dim,T>::RealField_t& f,
00855                                     typename FFT<SineTransform,Dim,T>::RealField_t& g,
00856                                     const bool& constInput)
00857 {
00858   int dir = this->getDirection(directionName);
00859   transform(dir, f, g, constInput);
00860   return;
00861 }
00862 
00866 template <unsigned Dim, class T>
00867 inline void
00868 FFT<SineTransform,Dim,T>::transform(
00869                                     const char* directionName,
00870                                     typename FFT<SineTransform,Dim,T>::RealField_t& f)
00871 {
00872   int dir = this->getDirection(directionName);
00873   transform(dir, f);
00874   return;
00875 }
00876 
00877 
00881  template <class T>
00882  class FFT<SineTransform,1U,T> : public FFTBase<1U,T> {
00883    
00884  public: 
00885    
00886    typedef FieldLayout<1U> Layout_t;
00887    typedef BareField<T,1U> RealField_t;
00888    typedef LField<T,1U> RealLField_t;
00889    typedef typename FFTBase<1U,T>::Domain_t Domain_t;
00890    
00898    FFT(const Domain_t& rdomain, const bool sineTransformDims[1U],
00899        const bool& compressTemps=false);
00903    FFT(const Domain_t& rdomain, const bool& compressTemps=false);
00904 
00905    
00906    ~FFT(void);
00907 
00916    void transform(int direction, RealField_t& f, RealField_t& g,
00917                   const bool& constInput=false);
00918    void transform(const char* directionName, RealField_t& f,
00919                   RealField_t& g, const bool& constInput=false);
00920    
00924    void transform(int direction, RealField_t& f);
00925    void transform(const char* directionName, RealField_t& f);
00926    
00927    private: 
00928 
00933    void setup(void);
00934 
00938    Layout_t* tempRLayouts_m;
00939 
00943    RealField_t* tempRFields_m;
00944 
00945  };
00946 
00950 template <class T>
00951 inline void
00952 FFT<SineTransform,1U,T>::transform(
00953                                    const char* directionName,
00954                                    typename FFT<SineTransform,1U,T>::RealField_t& f,
00955                                    typename FFT<SineTransform,1U,T>::RealField_t& g,
00956                                    const bool& constInput)
00957 {
00958   int dir = this->getDirection(directionName);
00959   transform(dir, f, g, constInput);
00960   return;
00961 }
00962 
00966 template <class T>
00967 inline void
00968 FFT<SineTransform,1U,T>::transform(
00969                                    const char* directionName,
00970                                    typename FFT<SineTransform,1U,T>::RealField_t& f)
00971 {
00972   int dir = this->getDirection(directionName);
00973   transform(dir, f);
00974   return;
00975 }
00976 #include "FFT/FFT.cpp"
00977 #endif // IPPL_FFT_FFT_H
00978 
00979 /***************************************************************************
00980  * $RCSfile: FFT.h,v $   $Author: adelmann $
00981  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:25 $
00982  * IPPL_VERSION_ID: $Id: FFT.h,v 1.1.1.1 2003/01/23 07:40:25 adelmann Exp $ 
00983  ***************************************************************************/
00984 
00985 

Generated on Mon Jan 16 13:23:42 2006 for IPPL by  doxygen 1.4.6