00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef IPPL_FFT_FFT_H
00016 #define IPPL_FFT_FFT_H
00017
00018
00019 #include "FFT/FFTBase.h"
00020
00021
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
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
00091 int lengths[Dim];
00092 unsigned d;
00093 for (d=0; d<Dim; ++d)
00094 lengths[d] = cdomain[d].length();
00095
00096
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;
00102 normFact /= lengths[d];
00103 }
00104
00105
00106 this->getEngine().setup(Dim, transformTypes, lengths);
00107
00108 setup();
00109 }
00110
00111
00112
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
00135 int direction = this->getDirection(directionName);
00136
00137
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
00143 unsigned d;
00144 int idim;
00145 int begdim, enddim;
00146 unsigned nTransformDims = this->numTransformDims();
00147
00148 ComplexField_t* temp = &f;
00149
00150 Complex_t* localdata;
00151
00152
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
00158
00159 bool skipTranspose = false;
00160
00161
00162 if (idim == begdim) {
00163
00164 const Domain_t& first_dom = tempLayouts_m[idim]->getDomain();
00165
00166
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
00174
00175 if (idim == enddim-direction) {
00176
00177 const Domain_t& last_dom = tempLayouts_m[idim]->getDomain();
00178
00179
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
00188 (*tempFields_m[idim])[tempLayouts_m[idim]->getDomain()] =
00189 (*temp)[temp->getLayout().getDomain()];
00190
00191
00192 if (this->compressTemps() && temp != &f) *temp = 0;
00193 temp = tempFields_m[idim];
00194 }
00195 else if (idim == enddim-direction && temp != &f) {
00196
00197
00198
00199
00200 f[in_dom] = (*temp)[temp->getLayout().getDomain()];
00201
00202
00203 if (this->compressTemps()) *temp = 0;
00204 temp = &f;
00205 }
00206 TAU_PROFILE_STOP(timer_swap);
00207
00208 TAU_PROFILE_START(timer_fft);
00209
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
00214 ComplexLField_t* ldf = (*l_i).second.get();
00215
00216 ldf->Uncompress();
00217
00218 localdata = ldf->getP();
00219
00220
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
00225 this->getEngine().callFFT(idim, direction, localdata);
00226
00227 localdata += length;
00228 }
00229 }
00230 TAU_PROFILE_STOP(timer_fft);
00231
00232 }
00233
00234
00235 if (temp != &f) {
00236 TAU_PROFILE_START(timer_swap);
00237
00238 f[in_dom] = (*temp)[temp->getLayout().getDomain()];
00239 if (this->compressTemps()) *temp = 0;
00240 TAU_PROFILE_STOP(timer_swap);
00241 }
00242
00243
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
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
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
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
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
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
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
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
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
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
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
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
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
00981
00982
00983
00984
00985