Commit e16c2223 authored by Zheng Dawei's avatar Zheng Dawei
Browse files

update efficient Poisson solver for the first phrase, to be debugged and tested with examples next

parent de0c7799
......@@ -52,7 +52,10 @@ class SineTransform {};
Tag classes for cosine types of Fourier transforms
*/
class CosTransform {};
/**
Tag classes for implicitly zero padded CC types of Fourier transforms
*/
class ImPadTransform {};
/**
Non-specialized FFT class. We specialize based on Transform tag class
*/
......@@ -470,6 +473,32 @@ public:
*/
FFT(const Domain_t& rdomain, const Domain_t& cdomain,
const bool& compressTemps=false, int serialAxes = 1);
/** The constracnt function within IMP CC FFT inside, parallel to the above
*/
/*
FFT( const typename FFT<RCTransform,Dim,T>::Domain_t& rdomain,
const typename FFT<RCTransform,Dim,T>::Domain_t& cdomain,
const typename FFT<RCTransform,Dim,T>::Domain_t& ddomain,
const typename FFT<RCTransform,Dim,T>::Domain_t& edomain,
const typename FFT<RCTransform,Dim,T>::Domain_t& fdomain,
const bool& compressTemps= false);
*/
FFT( const typename FFT<RCTransform,Dim,T>::Domain_t& rdomain,
const typename FFT<RCTransform,Dim,T>::Domain_t& cdomain,
const typename FFT<RCTransform,Dim,T>::Domain_t& ddomain,
const typename FFT<RCTransform,Dim,T>::Domain_t& edomain,
const typename FFT<RCTransform,Dim,T>::Domain_t& fdomain,
const bool& compressTemps= false,
int serialAxes=1);
/*
FFT(const Domain_t& rdomain, const Domain_t ** cdomain,
const bool transformTheseDims[Dim], const bool& compressTemps=false);
FFT(const Domain_t& rdomain, const Domain_t ** cdomain,
const bool& compressTemps=false, int serialAxes = 1);
*/
// Destructor
~FFT(void);
......@@ -485,6 +514,26 @@ public:
const bool& constInput=false);
void transform(const char* directionName, RealField_t& f,
ComplexField_t& g, const bool& constInput=false);
/** real-to-complex FFT combining the IMP-CC FFT, only for 3D situation
*/
void transform(int direction, RealField_t& f,
ComplexField_t& g, ComplexField_t& g01,
ComplexField_t& g10, ComplexField_t& g11,
const bool& constInput=false);
void transform(const char* directionName, RealField_t& f,
ComplexField_t& g, ComplexField_t& g01,
ComplexField_t& g10, ComplexField_t& g11,
const bool& constInput=false);
/** real-to-complex FFT combining the IMP-CC FFT for future
*/
void transform(int direction, RealField_t& f, ComplexField_t **g,
const bool& constInput=false);
void transform(const char* directionName, RealField_t& f,
ComplexField_t **g, const bool& constInput=false);
/** real-to-complex FFT on GPU: transfer the real field to GPU execute FFT
return the pointer to memory on GPU where complex results are stored
......@@ -500,6 +549,23 @@ public:
const bool& constInput=false);
void transform(const char* directionName, ComplexField_t& f,
RealField_t& g, const bool& constInput=false);
void transform(int direction,
ComplexField_t& g, ComplexField_t& g01,
ComplexField_t& g10, ComplexField_t& g11,
RealField_t& f,
const bool& constInput=false);
void transform(const char* directionName,
ComplexField_t& g, ComplexField_t& g01,
ComplexField_t& g10, ComplexField_t& g11,
RealField_t& f,
const bool& constInput=false);
void transform(int direction, ComplexField_t **f, RealField_t& g,
const bool& constInput=false);
void transform(const char* directionName, ComplexField_t **f,
RealField_t& g, const bool& constInput=false);
/** complex-to-real FFT on GPU: pass pointer to GPU memory where complex field
is stored, do the inverse FFT and transfer real field back to host memory
......@@ -517,12 +583,17 @@ private:
*/
void setup(void);
void setupRCIMP(void);
/** How the temporary fields are laid out; these are computed from the
input Field's domain. This will be allocated as an array of FieldLayouts
with nTransformDims elements. Each is SERIAL along the zeroth dimension
and the axes are permuted so that the transform direction is first
*/
Layout_t** tempLayouts_m;
Layout_t** tempLayouts_m01;
Layout_t** tempLayouts_m10;
Layout_t** tempLayouts_m11;
/**
extra layout for the one real Field needed
......@@ -533,6 +604,9 @@ private:
These use the corresponding tempLayouts.
*/
ComplexField_t** tempFields_m;
ComplexField_t** tempFields_m01;
ComplexField_t** tempFields_m10;
ComplexField_t** tempFields_m11;
/**
We need one real internal Field in this case.
......@@ -544,6 +618,9 @@ private:
const Domain_t& complexDomain_m;
*/
Domain_t complexDomain_m;
Domain_t complexDomain_m01;
Domain_t complexDomain_m10;
Domain_t complexDomain_m11;
/**
number of axes to make serial
......@@ -568,6 +645,18 @@ FFT<RCTransform,Dim,T>::transform(
transform(dir, f, g, constInput);
return;
}
template <unsigned Dim, class T>
inline void
FFT<RCTransform,Dim,T>::transform(
const char* directionName,
typename FFT<RCTransform,Dim,T>::RealField_t& f,
typename FFT<RCTransform,Dim,T>::ComplexField_t **g,
const bool& constInput)
{
int dir = this->getDirection(directionName);
transform(dir, f, g, constInput);
return;
}
/**
invoke complex-to-real transform using string for transform direction
......@@ -585,6 +674,49 @@ FFT<RCTransform,Dim,T>::transform(
return;
}
template <unsigned Dim, class T>
inline void
FFT<RCTransform,Dim,T>::transform(
const char* directionName,
typename FFT<RCTransform,Dim,T>::ComplexField_t **f,
typename FFT<RCTransform,Dim,T>::RealField_t& g,
const bool& constInput)
{
int dir = this->getDirection(directionName);
transform(dir, f, g, constInput);
return;
}
template <unsigned Dim, class T>
inline void
FFT<RCTransform,Dim,T>::transform(
const char* directionName, RealField_t& f,
ComplexField_t& g, ComplexField_t& g01,
ComplexField_t& g10, ComplexField_t& g11,
const bool& constInput)
{
int dir = this->getDirection(directionName);
transform(dir, f, g, g01, g10, g11, constInput);
return;
}
template <unsigned Dim, class T>
inline void
FFT<RCTransform,Dim,T>::transform(
const char* directionName,
ComplexField_t& g, ComplexField_t& g01,
ComplexField_t& g10, ComplexField_t& g11,
RealField_t& f,
const bool& constInput)
{
int dir = this->getDirection(directionName);
transform(dir, g, g01, g10, g11, f, constInput);
return;
}
/**
1D real-to-complex FFT class
......@@ -618,6 +750,20 @@ public:
*/
FFT(const Domain_t& rdomain, const Domain_t& cdomain,
const bool& compressTemps=false);
/* The routine for ImPadded transform*/
FFT(const Domain_t& rdomain, const Domain_t& cdomain,
const Domain_t& ddomain, const Domain_t& edomain,
const Domain_t& fdomain,
const bool& compressTemps=false);
FFT(const Domain_t& rdomain, const Domain_t **cdomain,
const bool transformTheseDims[1U], const bool& compressTemps=false);
/**
Same as above, but transform all dims:
*/
FFT(const Domain_t& rdomain, const Domain_t **cdomain,
const bool& compressTemps=false);
/**
Destructor
......@@ -634,9 +780,15 @@ public:
*/
void transform(int direction, RealField_t& f, ComplexField_t& g,
const bool& constInput=false);
void transform(int direction, RealField_t& f, ComplexField_t& g,
ComplexField_t& g01, ComplexField_t& g10,
ComplexField_t& g11, const bool& constInput=false);
void transform(const char* directionName, RealField_t& f,
ComplexField_t& g, const bool& constInput=false);
/**
complex-to-real FFT
Same as above, but with input and output field types reversed.
......@@ -646,6 +798,18 @@ public:
void transform(const char* directionName, ComplexField_t& f,
RealField_t& g, const bool& constInput=false);
/**
* real-to-complex FFT, complex-to-real FFT, together with IMP CC FFT
* **/
void transform(int direction, RealField_t& f, ComplexField_t **g,
const bool& constInput=false);
void transform(const char* directionName, RealField_t& f,
ComplexField_t **g, const bool& constInput=false);
void transform(int direction, ComplexField_t **f, RealField_t& g,
const bool& constInput=false);
void transform(const char* directionName, ComplexField_t **f,
RealField_t& g, const bool& constInput=false);
private:
/**
......@@ -693,6 +857,19 @@ FFT<RCTransform,1U,T>::transform(
return;
}
template <class T>
inline void
FFT<RCTransform,1U,T>::transform(
const char* directionName,
typename FFT<RCTransform,1U,T>::RealField_t& f,
typename FFT<RCTransform,1U,T>::ComplexField_t **g,
const bool& constInput)
{
int dir = this->getDirection(directionName);
transform(dir, f, g, constInput);
return;
}
/**
invoke complex-to-real transform using string for transform direction
*/
......@@ -709,6 +886,19 @@ FFT<RCTransform,1U,T>::transform(
return;
}
template <class T>
inline void
FFT<RCTransform,1U,T>::transform(
const char* directionName,
typename FFT<RCTransform,1U,T>::ComplexField_t **f,
typename FFT<RCTransform,1U,T>::RealField_t& g,
const bool& constInput)
{
int dir = this->getDirection(directionName);
transform(dir, f, g, constInput);
return;
}
/**
sine transform class
*/
......@@ -1132,7 +1322,7 @@ public:
/** Constructor for doing cosine transform(s) followed by RC FFT
Create a new FFT object with the given domains for input/output Fields
Specify which dimensions to transform along.
Also specify which of these are sine transforms
Also specify which of these are cosine transforms
Optional argument compress indicates whether or not to compress
temporary Fields in between uses.
*/
......@@ -1157,7 +1347,12 @@ public:
Same as above, but transform all dims:
*/
FFT(const Domain_t& rdomain, const bool& compressTemps=false);
/**
Transform for all dims, specified for efficient Poisson solver
*/
FFT(const Domain_t& rdomain, const Domain_t& gdomain, const bool& compressTemps=false);
~FFT(void);
/**
......@@ -1186,13 +1381,17 @@ public:
/**
These transforms are for doing sine transforms only
sine transform: specify +1 or -1 to indicate forward or inverse
cosine transform: specify +1 or -1 to indicate forward or inverse
transform, or specify the user-defined name string for the direction.
Supply a second BareField to store the output.
optional argument constInput indicates whether or not to treat the
input Field argument f as const. If not, we can use it as a temporary
in order to avoid an additional data transpose.
*/
// This transform is customerized for the efficieint Poisson solver
void transform(int direction, RealField_t& f, RealField_t& g0, RealField_t& g1, const bool& constInput=false);
void transform(int direction, RealField_t& f, RealField_t& g,
const bool& constInput=false);
void transform(const char* directionName, RealField_t& f,
......@@ -1211,9 +1410,14 @@ private:
directions have been specified.
*/
void setup(void);
// For the efficient FFT Poisson solver
void setupg01(void);
Domain_t Domain_jik;
/// get our domain_jik
const Domain_t& getDomain_jik(void) const { return Domain_jik; }
/**
which dimensions are sine transformed
*/
......@@ -1237,7 +1441,7 @@ private:
layouts for the temporary real Fields
*/
Layout_t** tempRLayouts_m;
/** The array of temporary complex Fields
These use the corresponding tempLayouts.
*/
......@@ -1247,6 +1451,14 @@ private:
These use the corresponding tempRLayouts.
*/
RealField_t** tempRFields_m;
// only for specified cosine transform
//Domain_t* domain_jik;
Layout_t* tempRg0Layouts_jik;
Layout_t* tempRg1Layouts_jik;
RealField_t* temp_g0_RFields_jik;
RealField_t* temp_g1_RFields_jik;
/**
domain of the resulting complex Field for real-to-complex transform
......@@ -1254,6 +1466,247 @@ private:
const Domain_t* complexDomain_m;
};
/**
The implicit zero padded c2c transform class */
template <unsigned Dim, class T>
class FFT<ImPadTransform,Dim,T> : public FFTBase<Dim,T> {
private:
/*
#ifdef IPPL_DKS
DKSBase base;
#endif
*/
public:
// typedefs
typedef FieldLayout<Dim> Layout_t;
typedef std::complex<T> Complex_t;
typedef BareField<Complex_t,Dim> ComplexField_t;
typedef LField<Complex_t,Dim> ComplexLField_t;
typedef typename FFTBase<Dim,T>::Domain_t Domain_t;
/** Create a new FFT object with the given domain for the input Field.
Specify which dimensions to transform along.
Optional argument compressTemps indicates whether or not to compress
temporary Fields in between uses.
*/
/* Not imply sofar*/
FFT(const Domain_t& cdomain, const Domain_t **ddomain,
const bool transformTheseDims[Dim], const bool& compressTemps=false);
/**
Create a new FFT object of type ImPadTransform, with a
given domain. Default case of transforming along all dimensions.
Note this was formerly in the .cpp file, but the IBM linker
could not find it!
*/
FFT(const Domain_t& cdomain, const Domain_t **ddomain,
const bool& compressTemps=false)
: FFTBase<Dim,T>(FFT<ImPadTransform,Dim,T>::impFFT, cdomain,compressTemps) {
// construct array of axis lengths
int lengths[Dim];
unsigned d;
for (d=0; d<Dim; ++d)
lengths[d] = cdomain[d].length();
// construct array of transform types for FFT Engine, compute normalization
int transformTypes[Dim];
T& normFact = this->getNormFact();
normFact = 1.0;
for (d=0; d<Dim; ++d) {
transformTypes[d] = FFTBase<Dim,T>::impFFT; // all transforms are complex-to-complex
normFact /= lengths[d];
}
/*
#ifdef IPPL_DKS
#ifdef IPPL_DKS_OPENCL
INFOMSG("Init DKS base opencl" << endl);
base.setAPI("OpenCL", 6);
base.setDevice("-gpu", 4);
base.initDevice();
#endif
#ifdef IPPL_DKS_CUDA
INFOMSG("Init DKS base cuda" << endl);
base.setAPI("Cuda", 4);
base.setDevice("-gpu", 4);
base.initDevice();
#endif
#ifdef IPPL_DKS_MIC
INFOMSG("Init DKS base MIC" << endl);
base.setAPI("OpenMP", 6);
base.setDevice("-mic", 4);
base.initDevice();
#endif
#endif
*/
// set up FFT Engine
this->getEngine().setup(Dim, transformTypes, lengths);
// set up the temporary fields
setup();
}
/** Creat a new FFT object with the given domain for the input field.
* Customized to for 3D r2c transform **/
FFT(const Domain_t& cdomain, const Domain_t& ddomain,const Domain_t& edomain,
const Domain_t& fdomain, const bool& compressTemps=false);
// Destructor
~FFT(void);
/** Do the FFT: specify +1 or -1 to indicate forward or inverse
transform, or specify the user-defined name string for the direction.
User provides separate input and output fields
optional argument constInput indicates whether or not to treat the
input Field argument f as const. If not, we can use it as a temporary
in order to avoid an additional data transpose.
*/
void transform(int direction, ComplexField_t& f, ComplexField_t **g,
const bool& constInput=false);
/**
invoke using string for direction name
*/
void transform(const char* directionName, ComplexField_t& f,
ComplexField_t **g, const bool& constInput=false);
private:
/**
setup performs all the initializations necessary after the transform
directions have been specified.
*/
void setup(void);
/**
How the temporary field's are laid out; these are computed from the
input Field's domain. This will be allocated as an array of FieldLayouts
with nTransformDims elements. Each is SERIAL along the zeroth dimension
and the axes are permuted so that the transform direction is first
*/
Layout_t** tempLayouts_m;
/*The array of temporary fields, one for each transform direction
These use the corresponding tempLayouts.
*/
ComplexField_t** tempFields_m;
ComplexField_t * tempFields_00;/*Need to confirm for impfft--Dawei*/
};
/**
invoke two-field transform function using direction name string
*/
template <unsigned Dim, class T>
inline void
FFT<ImPadTransform,Dim,T>::transform(
const char* directionName,
typename FFT<ImPadTransform,Dim,T>::ComplexField_t& f,
typename FFT<ImPadTransform,Dim,T>::ComplexField_t **g,
const bool& constInput)
{
int dir = this->getDirection(directionName);
transform(dir, f, g, constInput);
return;
}
/**
1D complex-to-complex FFT class
*/
template <class T>
class FFT<ImPadTransform,1U,T> : public FFTBase<1U,T> {
public:
// typedefs
typedef FieldLayout<1U> Layout_t;
typedef std::complex<T> Complex_t;
typedef BareField<Complex_t,1U> ComplexField_t;
typedef LField<Complex_t,1U> ComplexLField_t;
typedef typename FFTBase<1U,T>::Domain_t Domain_t;
// Constructors:
/** Create a new FFT object with the given domain for the input Field.
Specify which dimensions to transform along.
Optional argument compressTemps indicates whether or not to compress
temporary Fields in between uses.
*/
FFT(const Domain_t& cdomain, const Domain_t& ddomain,
const bool transformTheseDims[1U], const bool& compressTemps=false);
/** Create a new FFT object with the given domain for the input Field.
Transform along all dimensions.
Optional argument compressTemps indicates whether or not to compress
temporary Fields in between uses.
*/
FFT(const Domain_t& cdomain, const Domain_t& ddmain,
const bool& compressTemps=false);
// Destructor
~FFT(void);
/** Do the FFT: specify +1 or -1 to indicate forward or inverse
transform, or specify the user-defined name string for the direction.
User provides separate input and output fields
optional argument constInput indicates whether or not to treat the
input Field argument f as const. If not, we can use it as a temporary
in order to avoid an additional data transpose.
*/
void transform(int direction, ComplexField_t& f, ComplexField_t& g,
const bool& constInput=false);
/**
invoke using string for direction name
*/
void transform(const char* directionName, ComplexField_t& f,
ComplexField_t& g, const bool& constInput=false);
private:
/**
setup performs all the initializations necessary after the transform
directions have been specified.
*/
void setup(void);
/**
The temporary field layout
*/
Layout_t* tempLayouts_m;
/**
The temporary field
*/
ComplexField_t* tempFields_m;
};
// inline function definitions
/**
invoke two-field transform function using direction name string
*/
template <class T>
inline void
FFT<ImPadTransform,1U,T>::transform(
const char* directionName,
typename FFT<ImPadTransform,1U,T>::ComplexField_t& f,
typename FFT<ImPadTransform,1U,T>::ComplexField_t& g,
const bool& constInput)
{
int dir = this->getDirection(directionName);
transform(dir, f, g, constInput);
return;
}
#include "FFT/FFT.hpp"
#endif // IPPL_FFT_FFT_H
......
This diff is collapsed.
......@@ -38,12 +38,13 @@ std::ostream& operator<<(std::ostream&, const FFTBase<Dim,T>&);
inline