00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef IPPL_FFT_FFTBASE_H
00016 #define IPPL_FFT_FFTBASE_H
00017
00018
00019 #include "Utility/PAssert.h"
00020 #include "Index/NDIndex.h"
00021 #include "Field/GuardCellSizes.h"
00022
00023 #if defined(IPPL_USE_SCSL_FFT)
00024 #include "FFT/SCSL_FFT.h"
00025 #else
00026 #include "FFT/fftpack_FFT.h"
00027 #endif
00028
00029 #ifdef IPPL_STDSTL
00030 #include <map>
00031 using std::map;
00032 #else
00033 #include <map.h>
00034 #endif
00035
00036 #ifdef IPPL_USE_STANDARD_HEADERS
00037 #include <iostream>
00038 using namespace std;
00039 #else
00040 #include <iostream.h>
00041 #endif
00042
00043
00044 template <unsigned Dim, class T> class FFTBase;
00045 template <unsigned Dim, class T>
00046 ostream& operator<<(ostream&, const FFTBase<Dim,T>&);
00047
00049 static char* transformTypeString_g[3] = { "complex-to-complex FFT",
00050 "real-to-complex FFT",
00051 "sine transform" };
00060 template <unsigned Dim, class T>
00061 class FFTBase {
00062
00063 public:
00064
00065
00066 enum { dimensions = Dim };
00067 typedef T Precision_t;
00068 typedef NDIndex<Dim> Domain_t;
00069
00070
00071 enum FFT_e { ccFFT, rcFFT, sineFFT };
00072
00073
00074 #if defined(IPPL_USE_SCSL_FFT)
00075 typedef SCSL<T> InternalFFT_t;
00076 #else
00077 typedef FFTPACK<T> InternalFFT_t;
00078 #endif
00079
00080 FFTBase() {}
00081
00093 FFTBase(FFT_e transform, const Domain_t& domain,
00094 const bool transformTheseDims[Dim], bool compressTemps);
00095
00104 FFTBase(FFT_e transform, const Domain_t& domain, bool compressTemps);
00105
00106
00107 virtual ~FFTBase(void) { delete [] activeDims_m; }
00108
00114 void write(ostream& out) const;
00115
00122 void setDirectionName(int direction, const char* directionName);
00123
00129 void setNormFact(Precision_t nf) { normFact_m = nf; }
00130
00137 int transVnodes() const {
00138 if (Ippl::maxFFTNodes() > 0 && Ippl::maxFFTNodes() <= Ippl::getNodes())
00139 return Ippl::maxFFTNodes();
00140 else
00141 return (-1);
00142 }
00143
00144 protected:
00145
00150
00151 static GuardCellSizes<Dim> nullGC;
00152
00154 int getDirection(const char* directionName) const;
00155
00157 bool transformDim(unsigned d) const;
00158
00160 unsigned numTransformDims(void) const { return nTransformDims_m; }
00161
00163 unsigned activeDimension(unsigned d) const;
00164
00166 InternalFFT_t& getEngine(void) { return FFTEngine_m; }
00167
00169 Precision_t& getNormFact(void) { return normFact_m; }
00170
00172 const Domain_t& getDomain(void) const { return Domain_m; }
00173
00175 bool checkDomain(const Domain_t& dom1, const Domain_t& dom2) const;
00176
00178 bool compressTemps(void) const { return compressTempFields_m; }
00179
00180 private:
00181
00183 map<const char*,int> directions_m;
00184
00185 FFT_e transformType_m;
00186 bool transformDims_m[Dim];
00187 unsigned nTransformDims_m;
00188 unsigned* activeDims_m;
00189
00191 InternalFFT_t FFTEngine_m;
00192
00194 Precision_t normFact_m;
00195
00197 Domain_t Domain_m;
00198
00200 bool compressTempFields_m;
00201 };
00202
00203
00204
00205
00207 template <unsigned Dim, class T>
00208 inline ostream&
00209 operator<<(ostream& out, const FFTBase<Dim,T>& fft)
00210 {
00211 fft.write(out);
00212 return out;
00213 }
00214
00219 template <unsigned Dim, class T>
00220 inline void
00221 FFTBase<Dim,T>::setDirectionName(int direction,
00222 const char* directionName) {
00223 PAssert(direction==+1 || direction==-1);
00224 directions_m[directionName] = direction;
00225 return;
00226 }
00227
00235 template <unsigned Dim, class T>
00236 inline int
00237 FFTBase<Dim,T>::getDirection(const char* directionName) const {
00238 return (*(directions_m.find(directionName))).second;
00239 }
00240
00248 template <unsigned Dim, class T>
00249 inline bool
00250 FFTBase<Dim,T>::transformDim(unsigned d) const {
00251 PAssert(d<Dim);
00252 return transformDims_m[d];
00253 }
00254
00262 template <unsigned Dim, class T>
00263 inline unsigned
00264 FFTBase<Dim,T>::activeDimension(unsigned d) const {
00265 PAssert(d<nTransformDims_m);
00266 return activeDims_m[d];
00267 }
00268
00279 template <unsigned Dim, class T>
00280 inline bool
00281 FFTBase<Dim,T>::checkDomain(const FFTBase<Dim,T>::Domain_t& dom1,
00282 const FFTBase<Dim,T>::Domain_t& dom2) const {
00283
00284
00285 static bool matched[Dim];
00286 bool found;
00287 unsigned d, d1;
00288
00289 for (d=0; d<Dim; ++d) matched[d] = false;
00290 d=0;
00291 while (d<Dim) {
00292 d1=0;
00293 found = false;
00294 while (!found && d1<Dim) {
00295
00296
00297 if (!matched[d1]) {
00298 found = ( dom1[d].length()==dom2[d1].length() &&
00299 dom1[d].sameBase(dom2[d1]) );
00300
00301 if (found) matched[d1] = true;
00302 }
00303 ++d1;
00304 }
00305 if (!found) return false;
00306 ++d;
00307 }
00308 return true;
00309 }
00310
00311 #include "FFT/FFTBase.cpp"
00312
00313 #endif // IPPL_FFT_FFTBASE_H
00314
00315
00316
00317
00318
00319
00320