1
0
mirror of https://github.com/paboyle/Grid.git synced 2024-11-16 02:35:36 +00:00
Grid/lib/qcd/action/scalar/ScalarImpl.h

264 lines
7.3 KiB
C
Raw Normal View History

2017-01-26 15:24:49 +00:00
#ifndef SCALAR_IMPL
#define SCALAR_IMPL
namespace Grid {
//namespace QCD {
template <class S>
class ScalarImplTypes {
public:
2017-01-26 15:24:49 +00:00
typedef S Simd;
2017-01-26 15:24:49 +00:00
template <typename vtype>
using iImplField = iScalar<iScalar<iScalar<vtype> > >;
2017-01-26 15:24:49 +00:00
typedef iImplField<Simd> SiteField;
typedef SiteField SitePropagator;
typedef SiteField SiteComplex;
2017-01-26 15:24:49 +00:00
typedef Lattice<SiteField> Field;
typedef Field ComplexField;
typedef Field FermionField;
typedef Field PropagatorField;
2017-01-26 15:24:49 +00:00
static inline void generate_momenta(Field& P, GridParallelRNG& pRNG){
gaussian(pRNG, P);
}
2017-01-26 15:24:49 +00:00
static inline Field projectForce(Field& P){return P;}
static inline void update_field(Field& P, Field& U, double ep) {
2017-01-26 15:24:49 +00:00
U += P*ep;
}
static inline RealD FieldSquareNorm(Field& U) {
2017-01-26 15:24:49 +00:00
return (- sum(trace(U*U))/2.0);
}
2017-01-26 15:24:49 +00:00
static inline void HotConfiguration(GridParallelRNG &pRNG, Field &U) {
gaussian(pRNG, U);
}
2017-01-26 15:24:49 +00:00
static inline void TepidConfiguration(GridParallelRNG &pRNG, Field &U) {
gaussian(pRNG, U);
}
2017-01-26 15:24:49 +00:00
static inline void ColdConfiguration(GridParallelRNG &pRNG, Field &U) {
U = 1.0;
}
static void MomentumSpacePropagator(Field &out, RealD m)
{
GridBase *grid = out._grid;
Field kmu(grid), one(grid);
const unsigned int nd = grid->_ndimension;
std::vector<int> &l = grid->_fdimensions;
one = Complex(1.0,0.0);
out = m*m;
for(int mu = 0; mu < nd; mu++)
{
Real twoPiL = M_PI*2./l[mu];
LatticeCoordinate(kmu,mu);
kmu = 2.*sin(.5*twoPiL*kmu);
out = out + kmu*kmu;
}
out = one/out;
}
static void FreePropagator(const Field &in, Field &out,
const Field &momKernel)
{
FFT fft((GridCartesian *)in._grid);
Field inFT(in._grid);
fft.FFT_all_dim(inFT, in, FFT::forward);
inFT = inFT*momKernel;
fft.FFT_all_dim(out, inFT, FFT::backward);
}
static void FreePropagator(const Field &in, Field &out, RealD m)
{
Field momKernel(in._grid);
MomentumSpacePropagator(momKernel, m);
FreePropagator(in, out, momKernel);
}
2017-01-26 15:24:49 +00:00
};
2017-02-09 15:18:38 +00:00
#ifdef USE_FFT_ACCELERATION
#ifndef FFT_MASS
#error "USE_FFT_ACCELERATION is defined but not FFT_MASS"
2017-09-15 11:48:36 +01:00
#endif
#endif
2017-02-09 15:18:38 +00:00
template <class S, unsigned int N>
class ScalarAdjMatrixImplTypes {
2017-02-09 15:18:38 +00:00
public:
typedef S Simd;
2017-06-24 23:04:05 +01:00
typedef QCD::SU<N> Group;
2017-02-09 15:18:38 +00:00
template <typename vtype>
using iImplField = iScalar<iScalar<iMatrix<vtype, N>>>;
template <typename vtype>
using iImplComplex = iScalar<iScalar<iScalar<vtype>>>;
typedef iImplField<Simd> SiteField;
typedef SiteField SitePropagator;
typedef iImplComplex<Simd> SiteComplex;
typedef Lattice<SiteField> Field;
typedef Lattice<SiteComplex> ComplexField;
typedef Field FermionField;
typedef Field PropagatorField;
2017-09-15 11:48:36 +01:00
static void MomentaSquare(ComplexField &out)
{
GridBase *grid = out._grid;
const std::vector<int> &l = grid->FullDimensions();
ComplexField kmu(grid);
2017-09-15 11:48:36 +01:00
for (int mu = 0; mu < grid->Nd(); mu++)
{
2017-09-15 11:48:36 +01:00
Real twoPiL = M_PI * 2.0 / l[mu];
LatticeCoordinate(kmu, mu);
kmu = 2.0 * sin(0.5 * twoPiL * kmu);
out += kmu * kmu;
}
}
static void MomentumSpacePropagator(ComplexField &out, RealD m)
{
2017-09-15 11:48:36 +01:00
GridBase *grid = out._grid;
ComplexField one(grid);
one = Complex(1.0, 0.0);
out = m * m;
MomentaSquare(out);
2017-09-15 11:48:36 +01:00
out = one / out;
}
2017-09-15 11:48:36 +01:00
static inline void generate_momenta(Field &P, GridParallelRNG &pRNG)
{
#ifndef USE_FFT_ACCELERATION
2017-06-24 23:04:05 +01:00
Group::GaussianFundamentalLieAlgebraMatrix(pRNG, P);
2017-09-15 11:48:36 +01:00
#else
Field Pgaussian(P._grid), Pp(P._grid);
ComplexField p2(P._grid); p2 = zero;
RealD M = FFT_MASS;
2017-09-15 11:48:36 +01:00
Group::GaussianFundamentalLieAlgebraMatrix(pRNG, Pgaussian);
FFT theFFT((GridCartesian*)P._grid);
theFFT.FFT_all_dim(Pp, Pgaussian, FFT::forward);
MomentaSquare(p2);
2017-09-15 11:48:36 +01:00
p2 += M * M;
p2 = sqrt(p2);
Pp *= p2;
2017-09-15 11:48:36 +01:00
theFFT.FFT_all_dim(P, Pp, FFT::backward);
#endif //USE_FFT_ACCELERATION
2017-02-09 15:18:38 +00:00
}
static inline Field projectForce(Field& P) {return P;}
2017-09-15 11:48:36 +01:00
static inline void update_field(Field &P, Field &U, double ep)
{
#ifndef USE_FFT_ACCELERATION
double t0=usecond();
2017-09-15 11:48:36 +01:00
U += P * ep;
double t1=usecond();
double total_time = (t1-t0)/1e6;
std::cout << GridLogIntegrator << "Total time for updating field (s) : " << total_time << std::endl;
2017-09-15 11:48:36 +01:00
#else
// FFT transform P(x) -> P(p)
// divide by (M^2+p^2) M external parameter (how to pass?)
// P'(p) = P(p)/(M^2+p^2)
// Transform back -> P'(x)
// U += P'(x)*ep
2017-09-15 11:48:36 +01:00
Field Pp(U._grid), P_FFT(U._grid);
static ComplexField p2(U._grid);
RealD M = FFT_MASS;
2017-09-15 11:48:36 +01:00
FFT theFFT((GridCartesian*)U._grid);
theFFT.FFT_all_dim(Pp, P, FFT::forward);
static bool first_call = true;
2017-09-15 11:48:36 +01:00
if (first_call)
{
// avoid recomputing
MomentumSpacePropagator(p2, M);
first_call = false;
}
Pp *= p2;
2017-09-15 11:48:36 +01:00
theFFT.FFT_all_dim(P_FFT, Pp, FFT::backward);
U += P_FFT * ep;
#endif //USE_FFT_ACCELERATION
2017-02-09 15:18:38 +00:00
}
static inline RealD FieldSquareNorm(Field &U)
{
2017-09-15 11:48:36 +01:00
#ifndef USE_FFT_ACCELERATION
return (TensorRemove(sum(trace(U * U))).real());
#else
// In case of Fourier acceleration we have to:
// compute U(p)*U(p)/(M^2+p^2)) Parseval theorem
// 1 FFT needed U(x) -> U(p)
// M to be passed
2017-09-15 11:48:36 +01:00
FFT theFFT((GridCartesian*)U._grid);
Field Up(U._grid);
theFFT.FFT_all_dim(Up, U, FFT::forward);
2017-09-15 11:48:36 +01:00
RealD M = FFT_MASS;
ComplexField p2(U._grid);
MomentumSpacePropagator(p2, M);
Field Up2 = Up * p2;
// from the definition of the DFT we need to divide by the volume
2017-09-15 11:48:36 +01:00
return (-TensorRemove(sum(trace(adj(Up) * Up2))).real() / U._grid->gSites());
#endif //USE_FFT_ACCELERATION
2017-02-09 15:18:38 +00:00
}
2017-02-09 15:18:38 +00:00
static inline void HotConfiguration(GridParallelRNG &pRNG, Field &U) {
2017-06-28 12:45:44 +01:00
Group::GaussianFundamentalLieAlgebraMatrix(pRNG, U);
2017-02-09 15:18:38 +00:00
}
2017-02-09 15:18:38 +00:00
static inline void TepidConfiguration(GridParallelRNG &pRNG, Field &U) {
2017-06-28 12:45:44 +01:00
Group::GaussianFundamentalLieAlgebraMatrix(pRNG, U, 0.01);
2017-02-09 15:18:38 +00:00
}
2017-02-09 15:18:38 +00:00
static inline void ColdConfiguration(GridParallelRNG &pRNG, Field &U) {
U = zero;
2017-02-09 15:18:38 +00:00
}
2017-02-09 15:18:38 +00:00
};
2017-01-26 15:24:49 +00:00
typedef ScalarImplTypes<vReal> ScalarImplR;
typedef ScalarImplTypes<vRealF> ScalarImplF;
typedef ScalarImplTypes<vRealD> ScalarImplD;
typedef ScalarImplTypes<vComplex> ScalarImplCR;
typedef ScalarImplTypes<vComplexF> ScalarImplCF;
typedef ScalarImplTypes<vComplexD> ScalarImplCD;
// Hardcoding here the size of the matrices
typedef ScalarAdjMatrixImplTypes<vComplex, QCD::Nc> ScalarAdjImplR;
typedef ScalarAdjMatrixImplTypes<vComplexF, QCD::Nc> ScalarAdjImplF;
typedef ScalarAdjMatrixImplTypes<vComplexD, QCD::Nc> ScalarAdjImplD;
template <int Colours > using ScalarNxNAdjImplR = ScalarAdjMatrixImplTypes<vComplex, Colours >;
template <int Colours > using ScalarNxNAdjImplF = ScalarAdjMatrixImplTypes<vComplexF, Colours >;
template <int Colours > using ScalarNxNAdjImplD = ScalarAdjMatrixImplTypes<vComplexD, Colours >;
//}
}
2017-01-26 15:24:49 +00:00
#endif