mirror of
https://github.com/paboyle/Grid.git
synced 2024-11-09 23:45:36 +00:00
Merge branch 'develop' into feature/gpu-port
This commit is contained in:
commit
fa9cd50c5b
1
.gitignore
vendored
1
.gitignore
vendored
@ -114,3 +114,4 @@ gh-pages/
|
||||
#####################
|
||||
Grid/qcd/spin/gamma-gen/*.h
|
||||
Grid/qcd/spin/gamma-gen/*.cc
|
||||
Grid/util/Version.h
|
||||
|
@ -0,0 +1,5 @@
|
||||
Version : 0.8.0
|
||||
|
||||
- Clang 3.5 and above, ICPC v16 and above, GCC 6.3 and above recommended
|
||||
- MPI and MPI3 comms optimisations for KNL and OPA finished
|
||||
- Half precision comms
|
@ -1,4 +1,4 @@
|
||||
/*************************************************************************************
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
@ -25,8 +25,8 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
//
|
||||
// Grid.h
|
||||
// simd
|
||||
@ -42,9 +42,8 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
|
||||
#include <Grid/GridQCDcore.h>
|
||||
#include <Grid/qcd/action/Action.h>
|
||||
#include <Grid/qcd/utils/GaugeFix.h>
|
||||
NAMESPACE_CHECK(GaugeFix);
|
||||
#include <Grid/qcd/utils/CovariantSmearing.h>
|
||||
#include <Grid/qcd/smearing/Smearing.h>
|
||||
NAMESPACE_CHECK(Smearing);
|
||||
#include <Grid/parallelIO/MetaData.h>
|
||||
#include <Grid/qcd/hmc/HMC_aggregate.h>
|
||||
|
||||
|
@ -55,13 +55,9 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
#include <Grid/algorithms/iterative/FlexibleCommunicationAvoidingGeneralisedMinimalResidual.h>
|
||||
#include <Grid/algorithms/iterative/MixedPrecisionFlexibleGeneralisedMinimalResidual.h>
|
||||
#include <Grid/algorithms/iterative/ImplicitlyRestartedLanczos.h>
|
||||
#include <Grid/algorithms/iterative/PowerMethod.h>
|
||||
|
||||
#include <Grid/algorithms/CoarsenedMatrix.h>
|
||||
#include <Grid/algorithms/FFT.h>
|
||||
|
||||
// EigCg
|
||||
// Pcg
|
||||
// Hdcg
|
||||
// GCR
|
||||
// etc..
|
||||
|
||||
#endif
|
||||
|
@ -171,144 +171,142 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Even Odd Schur decomp operators; there are several
|
||||
// ways to introduce the even odd checkerboarding
|
||||
//////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////
|
||||
// Even Odd Schur decomp operators; there are several
|
||||
// ways to introduce the even odd checkerboarding
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
template<class Field>
|
||||
class SchurOperatorBase : public LinearOperatorBase<Field> {
|
||||
public:
|
||||
virtual RealD Mpc (const Field &in, Field &out) =0;
|
||||
virtual RealD MpcDag (const Field &in, Field &out) =0;
|
||||
virtual void MpcDagMpc(const Field &in, Field &out,RealD &ni,RealD &no)
|
||||
{
|
||||
Field tmp(in.Grid());
|
||||
tmp.Checkerboard() = in.Checkerboard();
|
||||
ni=Mpc(in,tmp);
|
||||
no=MpcDag(tmp,out);
|
||||
}
|
||||
virtual void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){
|
||||
out.Checkerboard() = in.Checkerboard();
|
||||
MpcDagMpc(in,out,n1,n2);
|
||||
}
|
||||
virtual void HermOp(const Field &in, Field &out){
|
||||
RealD n1,n2;
|
||||
HermOpAndNorm(in,out,n1,n2);
|
||||
}
|
||||
void Op (const Field &in, Field &out){
|
||||
Mpc(in,out);
|
||||
}
|
||||
void AdjOp (const Field &in, Field &out){
|
||||
MpcDag(in,out);
|
||||
}
|
||||
// Support for coarsening to a multigrid
|
||||
void OpDiag (const Field &in, Field &out) {
|
||||
assert(0); // must coarsen the unpreconditioned system
|
||||
}
|
||||
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
||||
assert(0);
|
||||
}
|
||||
};
|
||||
template<class Matrix,class Field>
|
||||
class SchurDiagMooeeOperator : public SchurOperatorBase<Field> {
|
||||
protected:
|
||||
Matrix &_Mat;
|
||||
public:
|
||||
SchurDiagMooeeOperator (Matrix &Mat): _Mat(Mat){};
|
||||
virtual RealD Mpc (const Field &in, Field &out) {
|
||||
Field tmp(in.Grid());
|
||||
// std::cout <<"grid pointers: in.Grid()="<< in.Grid() << " out.Grid()=" << out.Grid() << " _Mat.Grid=" << _Mat.Grid() << " _Mat.RedBlackGrid=" << _Mat.RedBlackGrid() << std::endl;
|
||||
tmp.Checkerboard() = !in.Checkerboard();
|
||||
template<class Field>
|
||||
class SchurOperatorBase : public LinearOperatorBase<Field> {
|
||||
public:
|
||||
virtual RealD Mpc (const Field &in, Field &out) =0;
|
||||
virtual RealD MpcDag (const Field &in, Field &out) =0;
|
||||
virtual void MpcDagMpc(const Field &in, Field &out,RealD &ni,RealD &no) {
|
||||
Field tmp(in.Grid());
|
||||
tmp.Checkerboard() = in.Checkerboard();
|
||||
ni=Mpc(in,tmp);
|
||||
no=MpcDag(tmp,out);
|
||||
}
|
||||
virtual void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){
|
||||
out.Checkerboard() = in.Checkerboard();
|
||||
MpcDagMpc(in,out,n1,n2);
|
||||
}
|
||||
virtual void HermOp(const Field &in, Field &out){
|
||||
RealD n1,n2;
|
||||
HermOpAndNorm(in,out,n1,n2);
|
||||
}
|
||||
void Op (const Field &in, Field &out){
|
||||
Mpc(in,out);
|
||||
}
|
||||
void AdjOp (const Field &in, Field &out){
|
||||
MpcDag(in,out);
|
||||
}
|
||||
// Support for coarsening to a multigrid
|
||||
void OpDiag (const Field &in, Field &out) {
|
||||
assert(0); // must coarsen the unpreconditioned system
|
||||
}
|
||||
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
||||
assert(0);
|
||||
}
|
||||
};
|
||||
template<class Matrix,class Field>
|
||||
class SchurDiagMooeeOperator : public SchurOperatorBase<Field> {
|
||||
public:
|
||||
Matrix &_Mat;
|
||||
SchurDiagMooeeOperator (Matrix &Mat): _Mat(Mat){};
|
||||
virtual RealD Mpc (const Field &in, Field &out) {
|
||||
Field tmp(in.Grid());
|
||||
tmp.Checkerboard() = !in.Checkerboard();
|
||||
//std::cout <<"grid pointers: in._grid="<< in._grid << " out._grid=" << out._grid << " _Mat.Grid=" << _Mat.Grid() << " _Mat.RedBlackGrid=" << _Mat.RedBlackGrid() << std::endl;
|
||||
|
||||
_Mat.Meooe(in,tmp);
|
||||
_Mat.MooeeInv(tmp,out);
|
||||
_Mat.Meooe(out,tmp);
|
||||
_Mat.Meooe(in,tmp);
|
||||
_Mat.MooeeInv(tmp,out);
|
||||
_Mat.Meooe(out,tmp);
|
||||
|
||||
//std::cout << "cb in " << in.Checkerboard() << " cb out " << out.Checkerboard() << std::endl;
|
||||
_Mat.Mooee(in,out);
|
||||
return axpy_norm(out,-1.0,tmp,out);
|
||||
}
|
||||
virtual RealD MpcDag (const Field &in, Field &out){
|
||||
Field tmp(in.Grid());
|
||||
_Mat.Mooee(in,out);
|
||||
return axpy_norm(out,-1.0,tmp,out);
|
||||
}
|
||||
virtual RealD MpcDag (const Field &in, Field &out){
|
||||
Field tmp(in.Grid());
|
||||
|
||||
_Mat.MeooeDag(in,tmp);
|
||||
_Mat.MooeeInvDag(tmp,out);
|
||||
_Mat.MeooeDag(out,tmp);
|
||||
_Mat.MeooeDag(in,tmp);
|
||||
_Mat.MooeeInvDag(tmp,out);
|
||||
_Mat.MeooeDag(out,tmp);
|
||||
|
||||
_Mat.MooeeDag(in,out);
|
||||
return axpy_norm(out,-1.0,tmp,out);
|
||||
}
|
||||
};
|
||||
template<class Matrix,class Field>
|
||||
class SchurDiagOneOperator : public SchurOperatorBase<Field> {
|
||||
protected:
|
||||
Matrix &_Mat;
|
||||
public:
|
||||
SchurDiagOneOperator (Matrix &Mat): _Mat(Mat){};
|
||||
_Mat.MooeeDag(in,out);
|
||||
return axpy_norm(out,-1.0,tmp,out);
|
||||
}
|
||||
};
|
||||
template<class Matrix,class Field>
|
||||
class SchurDiagOneOperator : public SchurOperatorBase<Field> {
|
||||
protected:
|
||||
Matrix &_Mat;
|
||||
public:
|
||||
SchurDiagOneOperator (Matrix &Mat): _Mat(Mat){};
|
||||
|
||||
virtual RealD Mpc (const Field &in, Field &out) {
|
||||
Field tmp(in.Grid());
|
||||
virtual RealD Mpc (const Field &in, Field &out) {
|
||||
Field tmp(in.Grid());
|
||||
|
||||
_Mat.Meooe(in,out);
|
||||
_Mat.MooeeInv(out,tmp);
|
||||
_Mat.Meooe(tmp,out);
|
||||
_Mat.MooeeInv(out,tmp);
|
||||
_Mat.Meooe(in,out);
|
||||
_Mat.MooeeInv(out,tmp);
|
||||
_Mat.Meooe(tmp,out);
|
||||
_Mat.MooeeInv(out,tmp);
|
||||
|
||||
return axpy_norm(out,-1.0,tmp,in);
|
||||
}
|
||||
virtual RealD MpcDag (const Field &in, Field &out){
|
||||
Field tmp(in.Grid());
|
||||
return axpy_norm(out,-1.0,tmp,in);
|
||||
}
|
||||
virtual RealD MpcDag (const Field &in, Field &out){
|
||||
Field tmp(in.Grid());
|
||||
|
||||
_Mat.MooeeInvDag(in,out);
|
||||
_Mat.MeooeDag(out,tmp);
|
||||
_Mat.MooeeInvDag(tmp,out);
|
||||
_Mat.MeooeDag(out,tmp);
|
||||
_Mat.MooeeInvDag(in,out);
|
||||
_Mat.MeooeDag(out,tmp);
|
||||
_Mat.MooeeInvDag(tmp,out);
|
||||
_Mat.MeooeDag(out,tmp);
|
||||
|
||||
return axpy_norm(out,-1.0,tmp,in);
|
||||
}
|
||||
};
|
||||
template<class Matrix,class Field>
|
||||
class SchurDiagTwoOperator : public SchurOperatorBase<Field> {
|
||||
protected:
|
||||
Matrix &_Mat;
|
||||
public:
|
||||
SchurDiagTwoOperator (Matrix &Mat): _Mat(Mat){};
|
||||
return axpy_norm(out,-1.0,tmp,in);
|
||||
}
|
||||
};
|
||||
template<class Matrix,class Field>
|
||||
class SchurDiagTwoOperator : public SchurOperatorBase<Field> {
|
||||
protected:
|
||||
Matrix &_Mat;
|
||||
public:
|
||||
SchurDiagTwoOperator (Matrix &Mat): _Mat(Mat){};
|
||||
|
||||
virtual RealD Mpc (const Field &in, Field &out) {
|
||||
Field tmp(in.Grid());
|
||||
virtual RealD Mpc (const Field &in, Field &out) {
|
||||
Field tmp(in.Grid());
|
||||
|
||||
_Mat.MooeeInv(in,out);
|
||||
_Mat.Meooe(out,tmp);
|
||||
_Mat.MooeeInv(tmp,out);
|
||||
_Mat.Meooe(out,tmp);
|
||||
_Mat.MooeeInv(in,out);
|
||||
_Mat.Meooe(out,tmp);
|
||||
_Mat.MooeeInv(tmp,out);
|
||||
_Mat.Meooe(out,tmp);
|
||||
|
||||
return axpy_norm(out,-1.0,tmp,in);
|
||||
}
|
||||
virtual RealD MpcDag (const Field &in, Field &out){
|
||||
Field tmp(in.Grid());
|
||||
return axpy_norm(out,-1.0,tmp,in);
|
||||
}
|
||||
virtual RealD MpcDag (const Field &in, Field &out){
|
||||
Field tmp(in.Grid());
|
||||
|
||||
_Mat.MeooeDag(in,out);
|
||||
_Mat.MooeeInvDag(out,tmp);
|
||||
_Mat.MeooeDag(tmp,out);
|
||||
_Mat.MooeeInvDag(out,tmp);
|
||||
_Mat.MeooeDag(in,out);
|
||||
_Mat.MooeeInvDag(out,tmp);
|
||||
_Mat.MeooeDag(tmp,out);
|
||||
_Mat.MooeeInvDag(out,tmp);
|
||||
|
||||
return axpy_norm(out,-1.0,tmp,in);
|
||||
}
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Left handed Moo^-1 ; (Moo - Moe Mee^-1 Meo) psi = eta --> ( 1 - Moo^-1 Moe Mee^-1 Meo ) psi = Moo^-1 eta
|
||||
// Right handed Moo^-1 ; (Moo - Moe Mee^-1 Meo) Moo^-1 Moo psi = eta --> ( 1 - Moe Mee^-1 Meo ) Moo^-1 phi=eta ; psi = Moo^-1 phi
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class Matrix,class Field> using SchurDiagOneRH = SchurDiagTwoOperator<Matrix,Field> ;
|
||||
template<class Matrix,class Field> using SchurDiagOneLH = SchurDiagOneOperator<Matrix,Field> ;
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Staggered use
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class Matrix,class Field>
|
||||
class SchurStaggeredOperator : public SchurOperatorBase<Field> {
|
||||
protected:
|
||||
Matrix &_Mat;
|
||||
return axpy_norm(out,-1.0,tmp,in);
|
||||
}
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Left handed Moo^-1 ; (Moo - Moe Mee^-1 Meo) psi = eta --> ( 1 - Moo^-1 Moe Mee^-1 Meo ) psi = Moo^-1 eta
|
||||
// Right handed Moo^-1 ; (Moo - Moe Mee^-1 Meo) Moo^-1 Moo psi = eta --> ( 1 - Moe Mee^-1 Meo ) Moo^-1 phi=eta ; psi = Moo^-1 phi
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class Matrix,class Field> using SchurDiagOneRH = SchurDiagTwoOperator<Matrix,Field> ;
|
||||
template<class Matrix,class Field> using SchurDiagOneLH = SchurDiagOneOperator<Matrix,Field> ;
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Staggered use
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class Matrix,class Field>
|
||||
class SchurStaggeredOperator : public SchurOperatorBase<Field> {
|
||||
protected:
|
||||
Matrix &_Mat;
|
||||
Field tmp;
|
||||
RealD mass;
|
||||
double tMpc;
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
// Query the even even properties to make algorithmic decisions
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
virtual RealD Mass(void) { return 0.0; };
|
||||
virtual int ConstEE(void) { return 0; }; // Disable assumptions unless overridden
|
||||
virtual int ConstEE(void) { return 1; }; // Disable assumptions unless overridden
|
||||
virtual int isTrivialEE(void) { return 0; }; // by a derived class that knows better
|
||||
|
||||
// half checkerboard operaions
|
||||
|
@ -93,6 +93,8 @@ public:
|
||||
|
||||
// Check if guess is really REALLY good :)
|
||||
if (cp <= rsq) {
|
||||
std::cout << GridLogMessage << "ConjugateGradient guess is converged already " << std::endl;
|
||||
IterationsToComplete = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -108,7 +110,7 @@ public:
|
||||
|
||||
SolverTimer.Start();
|
||||
int k;
|
||||
for (k = 1; k <= MaxIterations*1000; k++) {
|
||||
for (k = 1; k <= MaxIterations; k++) {
|
||||
c = cp;
|
||||
|
||||
MatrixTimer.Start();
|
||||
@ -172,8 +174,7 @@ public:
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::cout << GridLogMessage << "ConjugateGradient did NOT converge"
|
||||
<< std::endl;
|
||||
std::cout << GridLogMessage << "ConjugateGradient did NOT converge "<<k<<" / "<< MaxIterations<< std::endl;
|
||||
|
||||
if (ErrorOnNoConverge) assert(0);
|
||||
IterationsToComplete = k;
|
||||
|
@ -30,36 +30,41 @@ Author: Christopher Kelly <ckelly@phys.columbia.edu>
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
//Mixed precision restarted defect correction CG
|
||||
template<class FieldD,class FieldF,
|
||||
typename std::enable_if< getPrecision<FieldD>::value == 2, int>::type = 0,
|
||||
typename std::enable_if< getPrecision<FieldF>::value == 1, int>::type = 0>
|
||||
class MixedPrecisionConjugateGradient : public LinearFunction<FieldD> {
|
||||
public:
|
||||
RealD Tolerance;
|
||||
RealD InnerTolerance; //Initial tolerance for inner CG. Defaults to Tolerance but can be changed
|
||||
Integer MaxInnerIterations;
|
||||
Integer MaxOuterIterations;
|
||||
GridBase* SinglePrecGrid; //Grid for single-precision fields
|
||||
RealD OuterLoopNormMult; //Stop the outer loop and move to a final double prec solve when the residual is OuterLoopNormMult * Tolerance
|
||||
LinearOperatorBase<FieldF> &Linop_f;
|
||||
LinearOperatorBase<FieldD> &Linop_d;
|
||||
//Mixed precision restarted defect correction CG
|
||||
template<class FieldD,class FieldF,
|
||||
typename std::enable_if< getPrecision<FieldD>::value == 2, int>::type = 0,
|
||||
typename std::enable_if< getPrecision<FieldF>::value == 1, int>::type = 0>
|
||||
class MixedPrecisionConjugateGradient : public LinearFunction<FieldD> {
|
||||
public:
|
||||
RealD Tolerance;
|
||||
RealD InnerTolerance; //Initial tolerance for inner CG. Defaults to Tolerance but can be changed
|
||||
Integer MaxInnerIterations;
|
||||
Integer MaxOuterIterations;
|
||||
GridBase* SinglePrecGrid; //Grid for single-precision fields
|
||||
RealD OuterLoopNormMult; //Stop the outer loop and move to a final double prec solve when the residual is OuterLoopNormMult * Tolerance
|
||||
LinearOperatorBase<FieldF> &Linop_f;
|
||||
LinearOperatorBase<FieldD> &Linop_d;
|
||||
|
||||
Integer TotalInnerIterations; //Number of inner CG iterations
|
||||
Integer TotalOuterIterations; //Number of restarts
|
||||
Integer TotalFinalStepIterations; //Number of CG iterations in final patch-up step
|
||||
Integer TotalInnerIterations; //Number of inner CG iterations
|
||||
Integer TotalOuterIterations; //Number of restarts
|
||||
Integer TotalFinalStepIterations; //Number of CG iterations in final patch-up step
|
||||
|
||||
//Option to speed up *inner single precision* solves using a LinearFunction that produces a guess
|
||||
LinearFunction<FieldF> *guesser;
|
||||
//Option to speed up *inner single precision* solves using a LinearFunction that produces a guess
|
||||
LinearFunction<FieldF> *guesser;
|
||||
|
||||
MixedPrecisionConjugateGradient(RealD tol, Integer maxinnerit, Integer maxouterit, GridBase* _sp_grid, LinearOperatorBase<FieldF> &_Linop_f, LinearOperatorBase<FieldD> &_Linop_d) :
|
||||
Linop_f(_Linop_f), Linop_d(_Linop_d),
|
||||
Tolerance(tol), InnerTolerance(tol), MaxInnerIterations(maxinnerit), MaxOuterIterations(maxouterit), SinglePrecGrid(_sp_grid),
|
||||
OuterLoopNormMult(100.), guesser(NULL){ };
|
||||
MixedPrecisionConjugateGradient(RealD tol,
|
||||
Integer maxinnerit,
|
||||
Integer maxouterit,
|
||||
GridBase* _sp_grid,
|
||||
LinearOperatorBase<FieldF> &_Linop_f,
|
||||
LinearOperatorBase<FieldD> &_Linop_d) :
|
||||
Linop_f(_Linop_f), Linop_d(_Linop_d),
|
||||
Tolerance(tol), InnerTolerance(tol), MaxInnerIterations(maxinnerit), MaxOuterIterations(maxouterit), SinglePrecGrid(_sp_grid),
|
||||
OuterLoopNormMult(100.), guesser(NULL){ };
|
||||
|
||||
void useGuesser(LinearFunction<FieldF> &g){
|
||||
guesser = &g;
|
||||
}
|
||||
void useGuesser(LinearFunction<FieldF> &g){
|
||||
guesser = &g;
|
||||
}
|
||||
|
||||
void operator() (const FieldD &src_d_in, FieldD &sol_d){
|
||||
TotalInnerIterations = 0;
|
||||
|
@ -35,7 +35,11 @@ class ZeroGuesser: public LinearFunction<Field> {
|
||||
public:
|
||||
virtual void operator()(const Field &src, Field &guess) { guess = Zero(); };
|
||||
};
|
||||
|
||||
template<class Field>
|
||||
class DoNothingGuesser: public LinearFunction<Field> {
|
||||
public:
|
||||
virtual void operator()(const Field &src, Field &guess) { };
|
||||
};
|
||||
template<class Field>
|
||||
class SourceGuesser: public LinearFunction<Field> {
|
||||
public:
|
||||
|
45
Grid/algorithms/iterative/PowerMethod.h
Normal file
45
Grid/algorithms/iterative/PowerMethod.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
namespace Grid {
|
||||
template<class Field> class PowerMethod
|
||||
{
|
||||
public:
|
||||
|
||||
template<typename T> static RealD normalise(T& v)
|
||||
{
|
||||
RealD nn = norm2(v);
|
||||
nn = sqrt(nn);
|
||||
v = v * (1.0/nn);
|
||||
return nn;
|
||||
}
|
||||
|
||||
RealD operator()(LinearOperatorBase<Field> &HermOp, const Field &src)
|
||||
{
|
||||
GridBase *grid = src._grid;
|
||||
|
||||
// quickly get an idea of the largest eigenvalue to more properly normalize the residuum
|
||||
RealD evalMaxApprox = 0.0;
|
||||
auto src_n = src;
|
||||
auto tmp = src;
|
||||
const int _MAX_ITER_EST_ = 50;
|
||||
|
||||
for (int i=0;i<_MAX_ITER_EST_;i++) {
|
||||
|
||||
normalise(src_n);
|
||||
HermOp.HermOp(src_n,tmp);
|
||||
RealD vnum = real(innerProduct(src_n,tmp)); // HermOp.
|
||||
RealD vden = norm2(src_n);
|
||||
RealD na = vnum/vden;
|
||||
|
||||
if ( (fabs(evalMaxApprox/na - 1.0) < 0.01) || (i==_MAX_ITER_EST_-1) ) {
|
||||
evalMaxApprox = na;
|
||||
return evalMaxApprox;
|
||||
}
|
||||
evalMaxApprox = na;
|
||||
std::cout << GridLogMessage << " Approximation of largest eigenvalue: " << evalMaxApprox << std::endl;
|
||||
src_n = tmp;
|
||||
}
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
@ -99,10 +99,13 @@ namespace Grid {
|
||||
OperatorFunction<Field> & _HermitianRBSolver;
|
||||
int CBfactorise;
|
||||
bool subGuess;
|
||||
bool useSolnAsInitGuess; // if true user-supplied solution vector is used as initial guess for solver
|
||||
public:
|
||||
|
||||
SchurRedBlackBase(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false) :
|
||||
_HermitianRBSolver(HermitianRBSolver)
|
||||
SchurRedBlackBase(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false,
|
||||
const bool _solnAsInitGuess = false) :
|
||||
_HermitianRBSolver(HermitianRBSolver),
|
||||
useSolnAsInitGuess(_solnAsInitGuess)
|
||||
{
|
||||
CBfactorise = 0;
|
||||
subtractGuess(initSubGuess);
|
||||
@ -156,7 +159,11 @@ namespace Grid {
|
||||
if ( subGuess ) guess_save.resize(nblock,grid);
|
||||
|
||||
for(int b=0;b<nblock;b++){
|
||||
guess(src_o[b],sol_o[b]);
|
||||
if(useSolnAsInitGuess) {
|
||||
pickCheckerboard(Odd, sol_o[b], out[b]);
|
||||
} else {
|
||||
guess(src_o[b],sol_o[b]);
|
||||
}
|
||||
|
||||
if ( subGuess ) {
|
||||
guess_save[b] = sol_o[b];
|
||||
@ -216,8 +223,11 @@ namespace Grid {
|
||||
////////////////////////////////
|
||||
// Construct the guess
|
||||
////////////////////////////////
|
||||
Field tmp(grid);
|
||||
guess(src_o,sol_o);
|
||||
if(useSolnAsInitGuess) {
|
||||
pickCheckerboard(Odd, sol_o, out);
|
||||
} else {
|
||||
guess(src_o,sol_o);
|
||||
}
|
||||
|
||||
Field guess_save(grid);
|
||||
guess_save = sol_o;
|
||||
@ -251,7 +261,7 @@ namespace Grid {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Override in derived. Not virtual as template methods
|
||||
// Override in derived.
|
||||
/////////////////////////////////////////////////////////////
|
||||
virtual void RedBlackSource (Matrix & _Matrix,const Field &src, Field &src_e,Field &src_o) =0;
|
||||
virtual void RedBlackSolution(Matrix & _Matrix,const Field &sol_o, const Field &src_e,Field &sol) =0;
|
||||
@ -264,8 +274,9 @@ namespace Grid {
|
||||
public:
|
||||
typedef CheckerBoardedSparseMatrixBase<Field> Matrix;
|
||||
|
||||
SchurRedBlackStaggeredSolve(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false)
|
||||
: SchurRedBlackBase<Field> (HermitianRBSolver,initSubGuess)
|
||||
SchurRedBlackStaggeredSolve(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false,
|
||||
const bool _solnAsInitGuess = false)
|
||||
: SchurRedBlackBase<Field> (HermitianRBSolver,initSubGuess,_solnAsInitGuess)
|
||||
{
|
||||
}
|
||||
|
||||
@ -333,8 +344,9 @@ namespace Grid {
|
||||
public:
|
||||
typedef CheckerBoardedSparseMatrixBase<Field> Matrix;
|
||||
|
||||
SchurRedBlackDiagMooeeSolve(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false)
|
||||
: SchurRedBlackBase<Field> (HermitianRBSolver,initSubGuess) {};
|
||||
SchurRedBlackDiagMooeeSolve(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false,
|
||||
const bool _solnAsInitGuess = false)
|
||||
: SchurRedBlackBase<Field> (HermitianRBSolver,initSubGuess,_solnAsInitGuess) {};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
@ -405,8 +417,9 @@ namespace Grid {
|
||||
/////////////////////////////////////////////////////
|
||||
// Wrap the usual normal equations Schur trick
|
||||
/////////////////////////////////////////////////////
|
||||
SchurRedBlackDiagTwoSolve(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false)
|
||||
: SchurRedBlackBase<Field>(HermitianRBSolver,initSubGuess) {};
|
||||
SchurRedBlackDiagTwoSolve(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false,
|
||||
const bool _solnAsInitGuess = false)
|
||||
: SchurRedBlackBase<Field>(HermitianRBSolver,initSubGuess,_solnAsInitGuess) {};
|
||||
|
||||
virtual void RedBlackSource(Matrix & _Matrix,const Field &src, Field &src_e,Field &src_o)
|
||||
{
|
||||
|
@ -44,10 +44,13 @@ void CartesianCommunicator::Init(int *argc, char ***argv)
|
||||
MPI_Initialized(&flag); // needed to coexist with other libs apparently
|
||||
if ( !flag ) {
|
||||
MPI_Init_thread(argc,argv,MPI_THREAD_MULTIPLE,&provided);
|
||||
// assert (provided == MPI_THREAD_MULTIPLE);
|
||||
|
||||
//If only 1 comms thread we require any threading mode other than SINGLE, but for multiple comms threads we need MULTIPLE
|
||||
if( (nCommThreads == 1 && provided == MPI_THREAD_SINGLE) ||
|
||||
(nCommThreads > 1 && provided != MPI_THREAD_MULTIPLE) ) {
|
||||
if( (nCommThreads == 1) && (provided == MPI_THREAD_SINGLE) ) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if( (nCommThreads > 1) && (provided != MPI_THREAD_MULTIPLE) ) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
@ -55,9 +58,12 @@ void CartesianCommunicator::Init(int *argc, char ***argv)
|
||||
// Never clean up as done once.
|
||||
MPI_Comm_dup (MPI_COMM_WORLD,&communicator_world);
|
||||
|
||||
Grid_quiesce_nodes();
|
||||
GlobalSharedMemory::Init(communicator_world);
|
||||
GlobalSharedMemory::SharedMemoryAllocate(GlobalSharedMemory::MAX_MPI_SHM_BYTES,
|
||||
GlobalSharedMemory::Hugepages);
|
||||
GlobalSharedMemory::SharedMemoryAllocate(
|
||||
GlobalSharedMemory::MAX_MPI_SHM_BYTES,
|
||||
GlobalSharedMemory::Hugepages);
|
||||
Grid_unquiesce_nodes();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -106,8 +112,7 @@ CartesianCommunicator::CartesianCommunicator(const Coordinate &processors)
|
||||
//////////////////////////////////
|
||||
CartesianCommunicator::CartesianCommunicator(const Coordinate &processors,const CartesianCommunicator &parent,int &srank)
|
||||
{
|
||||
_ndimension = processors.size();
|
||||
|
||||
_ndimension = processors.size(); assert(_ndimension>=1);
|
||||
int parent_ndimension = parent._ndimension; assert(_ndimension >= parent._ndimension);
|
||||
Coordinate parent_processor_coor(_ndimension,0);
|
||||
Coordinate parent_processors (_ndimension,1);
|
||||
|
@ -52,7 +52,7 @@ CartesianCommunicator::CartesianCommunicator(const Coordinate &processors,const
|
||||
CartesianCommunicator::CartesianCommunicator(const Coordinate &processors)
|
||||
{
|
||||
_processors = processors;
|
||||
_ndimension = processors.size();
|
||||
_ndimension = processors.size(); assert(_ndimension>=1);
|
||||
_processor_coor.resize(_ndimension);
|
||||
|
||||
// Require 1^N processor grid for fake
|
||||
|
@ -90,7 +90,9 @@ public:
|
||||
// Create an optimal reordered communicator that makes MPI_Cart_create get it right
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
static void Init(Grid_MPI_Comm comm); // Typically MPI_COMM_WORLD
|
||||
static void OptimalCommunicator(const Coordinate &processors,Grid_MPI_Comm & optimal_comm); // Turns MPI_COMM_WORLD into right layout for Cartesian
|
||||
static void OptimalCommunicator (const Coordinate &processors,Grid_MPI_Comm & optimal_comm); // Turns MPI_COMM_WORLD into right layout for Cartesian
|
||||
static void OptimalCommunicatorHypercube (const Coordinate &processors,Grid_MPI_Comm & optimal_comm); // Turns MPI_COMM_WORLD into right layout for Cartesian
|
||||
static void OptimalCommunicatorSharedMemory(const Coordinate &processors,Grid_MPI_Comm & optimal_comm); // Turns MPI_COMM_WORLD into right layout for Cartesian
|
||||
///////////////////////////////////////////////////
|
||||
// Provide shared memory facilities off comm world
|
||||
///////////////////////////////////////////////////
|
||||
|
@ -141,8 +141,22 @@ int Log2Size(int TwoToPower,int MAXLOG2)
|
||||
}
|
||||
void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_MPI_Comm & optimal_comm)
|
||||
{
|
||||
#ifdef HYPERCUBE
|
||||
#warning "HPE 8600 Hypercube optimisations enabled"
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Look and see if it looks like an HPE 8600 based on hostname conventions
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
const int namelen = _POSIX_HOST_NAME_MAX;
|
||||
char name[namelen];
|
||||
int R;
|
||||
int I;
|
||||
int N;
|
||||
gethostname(name,namelen);
|
||||
int nscan = sscanf(name,"r%di%dn%d",&R,&I,&N) ;
|
||||
|
||||
if(nscan==3) OptimalCommunicatorHypercube(processors,optimal_comm);
|
||||
else OptimalCommunicatorSharedMemory(processors,optimal_comm);
|
||||
}
|
||||
void GlobalSharedMemory::OptimalCommunicatorHypercube(const Coordinate &processors,Grid_MPI_Comm & optimal_comm)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Assert power of two shm_size.
|
||||
////////////////////////////////////////////////////////////////
|
||||
@ -208,7 +222,8 @@ void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_M
|
||||
////////////////////////////////////////////////////////////////
|
||||
int ndimension = processors.size();
|
||||
std::vector<int> processor_coor(ndimension);
|
||||
std::vector<int> WorldDims = processors; std::vector<int> ShmDims (ndimension,1); std::vector<int> NodeDims (ndimension);
|
||||
std::vector<int> WorldDims = processors.toVector();
|
||||
std::vector<int> ShmDims (ndimension,1); std::vector<int> NodeDims (ndimension);
|
||||
std::vector<int> ShmCoor (ndimension); std::vector<int> NodeCoor (ndimension); std::vector<int> WorldCoor(ndimension);
|
||||
std::vector<int> HyperCoor(ndimension);
|
||||
int dim = 0;
|
||||
@ -263,7 +278,9 @@ void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_M
|
||||
/////////////////////////////////////////////////////////////////
|
||||
int ierr= MPI_Comm_split(WorldComm,0,rank,&optimal_comm);
|
||||
assert(ierr==0);
|
||||
#else
|
||||
}
|
||||
void GlobalSharedMemory::OptimalCommunicatorSharedMemory(const Coordinate &processors,Grid_MPI_Comm & optimal_comm)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Assert power of two shm_size.
|
||||
////////////////////////////////////////////////////////////////
|
||||
@ -316,7 +333,6 @@ void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_M
|
||||
/////////////////////////////////////////////////////////////////
|
||||
int ierr= MPI_Comm_split(WorldComm,0,rank,&optimal_comm);
|
||||
assert(ierr==0);
|
||||
#endif
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SHMGET
|
||||
@ -347,7 +363,7 @@ void GlobalSharedMemory::SharedMemoryAllocate(uint64_t bytes, int flags)
|
||||
int errsv = errno;
|
||||
printf("Errno %d\n",errsv);
|
||||
printf("key %d\n",key);
|
||||
printf("size %lld\n",size);
|
||||
printf("size %ld\n",size);
|
||||
printf("flags %d\n",flags);
|
||||
perror("shmget");
|
||||
exit(1);
|
||||
|
@ -77,19 +77,18 @@ void GridLogConfigure(std::vector<std::string> &logstreams) {
|
||||
GridLogIterative.Active(0);
|
||||
GridLogDebug.Active(0);
|
||||
GridLogPerformance.Active(0);
|
||||
GridLogIntegrator.Active(0);
|
||||
GridLogIntegrator.Active(1);
|
||||
GridLogColours.Active(0);
|
||||
|
||||
for (int i = 0; i < logstreams.size(); i++) {
|
||||
if (logstreams[i] == std::string("Error")) GridLogError.Active(1);
|
||||
if (logstreams[i] == std::string("Warning")) GridLogWarning.Active(1);
|
||||
if (logstreams[i] == std::string("NoMessage")) GridLogMessage.Active(0);
|
||||
if (logstreams[i] == std::string("Iterative")) GridLogIterative.Active(1);
|
||||
if (logstreams[i] == std::string("Debug")) GridLogDebug.Active(1);
|
||||
if (logstreams[i] == std::string("Performance"))
|
||||
GridLogPerformance.Active(1);
|
||||
if (logstreams[i] == std::string("Integrator")) GridLogIntegrator.Active(1);
|
||||
if (logstreams[i] == std::string("Colours")) GridLogColours.Active(1);
|
||||
if (logstreams[i] == std::string("Error")) GridLogError.Active(1);
|
||||
if (logstreams[i] == std::string("Warning")) GridLogWarning.Active(1);
|
||||
if (logstreams[i] == std::string("NoMessage")) GridLogMessage.Active(0);
|
||||
if (logstreams[i] == std::string("Iterative")) GridLogIterative.Active(1);
|
||||
if (logstreams[i] == std::string("Debug")) GridLogDebug.Active(1);
|
||||
if (logstreams[i] == std::string("Performance")) GridLogPerformance.Active(1);
|
||||
if (logstreams[i] == std::string("Integrator")) GridLogIntegrator.Active(1);
|
||||
if (logstreams[i] == std::string("Colours")) GridLogColours.Active(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,10 +204,10 @@ class BinaryIO {
|
||||
static inline void le32toh_v(void *file_object,uint64_t bytes)
|
||||
{
|
||||
uint32_t *fp = (uint32_t *)file_object;
|
||||
uint32_t f;
|
||||
|
||||
uint64_t count = bytes/sizeof(uint32_t);
|
||||
thread_for(i,count,{
|
||||
uint32_t f;
|
||||
f = fp[i];
|
||||
// got network order and the network to host
|
||||
f = ((f&0xFF)<<24) | ((f&0xFF00)<<8) | ((f&0xFF0000)>>8) | ((f&0xFF000000UL)>>24) ;
|
||||
@ -229,10 +229,9 @@ class BinaryIO {
|
||||
static inline void le64toh_v(void *file_object,uint64_t bytes)
|
||||
{
|
||||
uint64_t *fp = (uint64_t *)file_object;
|
||||
uint64_t f,g;
|
||||
|
||||
uint64_t count = bytes/sizeof(uint64_t);
|
||||
thread_for( i, count, {
|
||||
uint64_t f,g;
|
||||
f = fp[i];
|
||||
// got network order and the network to host
|
||||
g = ((f&0xFF)<<24) | ((f&0xFF00)<<8) | ((f&0xFF0000)>>8) | ((f&0xFF000000UL)>>24) ;
|
||||
@ -343,7 +342,8 @@ class BinaryIO {
|
||||
int ieee32 = (format == std::string("IEEE32"));
|
||||
int ieee64big = (format == std::string("IEEE64BIG"));
|
||||
int ieee64 = (format == std::string("IEEE64"));
|
||||
|
||||
assert(ieee64||ieee32|ieee64big||ieee32big);
|
||||
assert((ieee64+ieee32+ieee64big+ieee32big)==1);
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Do the I/O
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -613,6 +613,7 @@ class BinaryIO {
|
||||
{
|
||||
std::cout << GridLogMessage << "writeLatticeObject: read test checksum failure, re-writing (" << attemptsLeft << " attempt(s) remaining)" << std::endl;
|
||||
offset = offsetCopy;
|
||||
thread_for(x,lsites, { munge(scalardata[x],iodata[x]); });
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -44,6 +44,12 @@ extern "C" {
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
#define GRID_FIELD_NORM "FieldNormMetaData"
|
||||
#define GRID_FIELD_NORM_CALC(FieldNormMetaData_, n2ck) \
|
||||
0.5*fabs(FieldNormMetaData_.norm2 - n2ck)/(FieldNormMetaData_.norm2 + n2ck)
|
||||
#define GRID_FIELD_NORM_CHECK(FieldNormMetaData_, n2ck) \
|
||||
assert(GRID_FIELD_NORM_CALC(FieldNormMetaData_, n2ck) < 1.0e-5);
|
||||
|
||||
/////////////////////////////////
|
||||
// Encode word types as strings
|
||||
/////////////////////////////////
|
||||
@ -203,6 +209,7 @@ class GridLimeReader : public BinaryIO {
|
||||
{
|
||||
typedef typename vobj::scalar_object sobj;
|
||||
scidacChecksum scidacChecksum_;
|
||||
FieldNormMetaData FieldNormMetaData_;
|
||||
uint32_t nersc_csum,scidac_csuma,scidac_csumb;
|
||||
|
||||
std::string format = getFormatString<vobj>();
|
||||
@ -231,21 +238,52 @@ class GridLimeReader : public BinaryIO {
|
||||
// std::cout << " ReadLatticeObject from offset "<<offset << std::endl;
|
||||
BinarySimpleMunger<sobj,sobj> munge;
|
||||
BinaryIO::readLatticeObject< vobj, sobj >(field, filename, munge, offset, format,nersc_csum,scidac_csuma,scidac_csumb);
|
||||
std::cout << GridLogMessage << "SciDAC checksum A " << std::hex << scidac_csuma << std::dec << std::endl;
|
||||
std::cout << GridLogMessage << "SciDAC checksum B " << std::hex << scidac_csumb << std::dec << std::endl;
|
||||
std::cout << GridLogMessage << "SciDAC checksum A " << std::hex << scidac_csuma << std::dec << std::endl;
|
||||
std::cout << GridLogMessage << "SciDAC checksum B " << std::hex << scidac_csumb << std::dec << std::endl;
|
||||
/////////////////////////////////////////////
|
||||
// Insist checksum is next record
|
||||
/////////////////////////////////////////////
|
||||
readLimeObject(scidacChecksum_,std::string("scidacChecksum"),std::string(SCIDAC_CHECKSUM));
|
||||
|
||||
readScidacChecksum(scidacChecksum_,FieldNormMetaData_);
|
||||
/////////////////////////////////////////////
|
||||
// Verify checksums
|
||||
/////////////////////////////////////////////
|
||||
if(FieldNormMetaData_.norm2 != 0.0){
|
||||
RealD n2ck = norm2(field);
|
||||
std::cout << GridLogMessage << "Field norm: metadata= " << FieldNormMetaData_.norm2
|
||||
<< " / field= " << n2ck << " / rdiff= " << GRID_FIELD_NORM_CALC(FieldNormMetaData_,n2ck) << std::endl;
|
||||
GRID_FIELD_NORM_CHECK(FieldNormMetaData_,n2ck);
|
||||
}
|
||||
assert(scidacChecksumVerify(scidacChecksum_,scidac_csuma,scidac_csumb)==1);
|
||||
|
||||
// find out if next field is a GridFieldNorm
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void readScidacChecksum(scidacChecksum &scidacChecksum_,
|
||||
FieldNormMetaData &FieldNormMetaData_)
|
||||
{
|
||||
FieldNormMetaData_.norm2 =0.0;
|
||||
std::string scidac_str(SCIDAC_CHECKSUM);
|
||||
std::string field_norm_str(GRID_FIELD_NORM);
|
||||
while ( limeReaderNextRecord(LimeR) == LIME_SUCCESS ) {
|
||||
uint64_t nbytes = limeReaderBytes(LimeR);//size of this record (configuration)
|
||||
std::vector<char> xmlc(nbytes+1,'\0');
|
||||
limeReaderReadData((void *)&xmlc[0], &nbytes, LimeR);
|
||||
std::string xmlstring = std::string(&xmlc[0]);
|
||||
XmlReader RD(xmlstring, true, "");
|
||||
if ( !strncmp(limeReaderType(LimeR), field_norm_str.c_str(),strlen(field_norm_str.c_str()) ) ) {
|
||||
// std::cout << "FieldNormMetaData "<<xmlstring<<std::endl;
|
||||
read(RD,field_norm_str,FieldNormMetaData_);
|
||||
}
|
||||
if ( !strncmp(limeReaderType(LimeR), scidac_str.c_str(),strlen(scidac_str.c_str()) ) ) {
|
||||
// std::cout << SCIDAC_CHECKSUM << " " <<xmlstring<<std::endl;
|
||||
read(RD,std::string("scidacChecksum"),scidacChecksum_);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
////////////////////////////////////////////
|
||||
// Read a generic serialisable object
|
||||
////////////////////////////////////////////
|
||||
@ -264,7 +302,7 @@ class GridLimeReader : public BinaryIO {
|
||||
limeReaderReadData((void *)&xmlc[0], &nbytes, LimeR);
|
||||
// std::cout << GridLogMessage<< " readLimeObject matches XML " << &xmlc[0] <<std::endl;
|
||||
|
||||
xmlstring = std::string(&xmlc[0]);
|
||||
xmlstring = std::string(&xmlc[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -278,8 +316,8 @@ class GridLimeReader : public BinaryIO {
|
||||
std::string xmlstring;
|
||||
|
||||
readLimeObject(xmlstring, record_name);
|
||||
XmlReader RD(xmlstring, true, "");
|
||||
read(RD,object_name,object);
|
||||
XmlReader RD(xmlstring, true, "");
|
||||
read(RD,object_name,object);
|
||||
}
|
||||
};
|
||||
|
||||
@ -388,6 +426,8 @@ class GridLimeWriter : public BinaryIO
|
||||
GridBase *grid = field.Grid();
|
||||
assert(boss_node == field.Grid()->IsBoss() );
|
||||
|
||||
FieldNormMetaData FNMD; FNMD.norm2 = norm2(field);
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Create record header
|
||||
////////////////////////////////////////////
|
||||
@ -446,6 +486,7 @@ class GridLimeWriter : public BinaryIO
|
||||
checksum.suma= streama.str();
|
||||
checksum.sumb= streamb.str();
|
||||
if ( boss_node ) {
|
||||
writeLimeObject(0,0,FNMD,std::string(GRID_FIELD_NORM),std::string(GRID_FIELD_NORM));
|
||||
writeLimeObject(0,1,checksum,std::string("scidacChecksum"),std::string(SCIDAC_CHECKSUM));
|
||||
}
|
||||
}
|
||||
@ -623,6 +664,12 @@ class IldgWriter : public ScidacWriter {
|
||||
assert(header.nd==4);
|
||||
assert(header.nd==header.dimension.size());
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Field norm tests
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
FieldNormMetaData FieldNormMetaData_;
|
||||
FieldNormMetaData_.norm2 = norm2(Umu);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Fill the USQCD info field
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -631,11 +678,12 @@ class IldgWriter : public ScidacWriter {
|
||||
info.plaq = header.plaquette;
|
||||
info.linktr = header.link_trace;
|
||||
|
||||
std::cout << GridLogMessage << " Writing config; IldgIO "<<std::endl;
|
||||
// std::cout << GridLogMessage << " Writing config; IldgIO n2 "<< FieldNormMetaData_.norm2<<std::endl;
|
||||
//////////////////////////////////////////////
|
||||
// Fill the Lime file record by record
|
||||
//////////////////////////////////////////////
|
||||
writeLimeObject(1,0,header ,std::string("FieldMetaData"),std::string(GRID_FORMAT)); // Open message
|
||||
writeLimeObject(0,0,FieldNormMetaData_,FieldNormMetaData_.SerialisableClassName(),std::string(GRID_FIELD_NORM));
|
||||
writeLimeObject(0,0,_scidacFile,_scidacFile.SerialisableClassName(),std::string(SCIDAC_PRIVATE_FILE_XML));
|
||||
writeLimeObject(0,1,info,info.SerialisableClassName(),std::string(SCIDAC_FILE_XML));
|
||||
writeLimeObject(1,0,_scidacRecord,_scidacRecord.SerialisableClassName(),std::string(SCIDAC_PRIVATE_RECORD_XML));
|
||||
@ -678,6 +726,7 @@ class IldgReader : public GridLimeReader {
|
||||
std::string ildgLFN_ ;
|
||||
scidacChecksum scidacChecksum_;
|
||||
usqcdInfo usqcdInfo_ ;
|
||||
FieldNormMetaData FieldNormMetaData_;
|
||||
|
||||
// track what we read from file
|
||||
int found_ildgFormat =0;
|
||||
@ -686,7 +735,7 @@ class IldgReader : public GridLimeReader {
|
||||
int found_usqcdInfo =0;
|
||||
int found_ildgBinary =0;
|
||||
int found_FieldMetaData =0;
|
||||
|
||||
int found_FieldNormMetaData =0;
|
||||
uint32_t nersc_csum;
|
||||
uint32_t scidac_csuma;
|
||||
uint32_t scidac_csumb;
|
||||
@ -773,11 +822,17 @@ class IldgReader : public GridLimeReader {
|
||||
found_scidacChecksum = 1;
|
||||
}
|
||||
|
||||
if ( !strncmp(limeReaderType(LimeR), GRID_FIELD_NORM,strlen(GRID_FIELD_NORM)) ) {
|
||||
XmlReader RD(xmlstring, true, "");
|
||||
read(RD,GRID_FIELD_NORM,FieldNormMetaData_);
|
||||
found_FieldNormMetaData = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
/////////////////////////////////
|
||||
// Binary data
|
||||
/////////////////////////////////
|
||||
std::cout << GridLogMessage << "ILDG Binary record found : " ILDG_BINARY_DATA << std::endl;
|
||||
// std::cout << GridLogMessage << "ILDG Binary record found : " ILDG_BINARY_DATA << std::endl;
|
||||
uint64_t offset= ftello(File);
|
||||
if ( format == std::string("IEEE64BIG") ) {
|
||||
GaugeSimpleMunger<dobj, sobj> munge;
|
||||
@ -845,6 +900,13 @@ class IldgReader : public GridLimeReader {
|
||||
////////////////////////////////////////////////////////////
|
||||
// Really really want to mandate a scidac checksum
|
||||
////////////////////////////////////////////////////////////
|
||||
if ( found_FieldNormMetaData ) {
|
||||
RealD nn = norm2(Umu);
|
||||
GRID_FIELD_NORM_CHECK(FieldNormMetaData_,nn);
|
||||
std::cout << GridLogMessage<<"FieldNormMetaData matches " << std::endl;
|
||||
} else {
|
||||
std::cout << GridLogWarning<<"FieldNormMetaData not found. " << std::endl;
|
||||
}
|
||||
if ( found_scidacChecksum ) {
|
||||
FieldMetaData_.scidac_checksuma = stoull(scidacChecksum_.suma,0,16);
|
||||
FieldMetaData_.scidac_checksumb = stoull(scidacChecksum_.sumb,0,16);
|
||||
|
@ -52,35 +52,40 @@ template<class vobj> static std::string getFormatString (void)
|
||||
format = std::string("IEEE64BIG");
|
||||
}
|
||||
return format;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// header specification/interpretation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FieldMetaData : Serializable {
|
||||
public:
|
||||
};
|
||||
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(FieldMetaData,
|
||||
int, nd,
|
||||
std::vector<int>, dimension,
|
||||
std::vector<std::string>, boundary,
|
||||
int, data_start,
|
||||
std::string, hdr_version,
|
||||
std::string, storage_format,
|
||||
double, link_trace,
|
||||
double, plaquette,
|
||||
uint32_t, checksum,
|
||||
uint32_t, scidac_checksuma,
|
||||
uint32_t, scidac_checksumb,
|
||||
unsigned int, sequence_number,
|
||||
std::string, data_type,
|
||||
std::string, ensemble_id,
|
||||
std::string, ensemble_label,
|
||||
std::string, ildg_lfn,
|
||||
std::string, creator,
|
||||
std::string, creator_hardware,
|
||||
std::string, creation_date,
|
||||
std::string, archive_date,
|
||||
std::string, floating_point);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// header specification/interpretation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FieldNormMetaData : Serializable {
|
||||
public:
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(FieldNormMetaData, double, norm2);
|
||||
};
|
||||
class FieldMetaData : Serializable {
|
||||
public:
|
||||
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(FieldMetaData,
|
||||
int, nd,
|
||||
std::vector<int>, dimension,
|
||||
std::vector<std::string>, boundary,
|
||||
int, data_start,
|
||||
std::string, hdr_version,
|
||||
std::string, storage_format,
|
||||
double, link_trace,
|
||||
double, plaquette,
|
||||
uint32_t, checksum,
|
||||
uint32_t, scidac_checksuma,
|
||||
uint32_t, scidac_checksumb,
|
||||
unsigned int, sequence_number,
|
||||
std::string, data_type,
|
||||
std::string, ensemble_id,
|
||||
std::string, ensemble_label,
|
||||
std::string, ildg_lfn,
|
||||
std::string, creator,
|
||||
std::string, creator_hardware,
|
||||
std::string, creation_date,
|
||||
std::string, archive_date,
|
||||
std::string, floating_point);
|
||||
// WARNING: non-initialised values might lead to twisted parallel IO
|
||||
// issues, std::string are fine because they initliase to size 0
|
||||
// as per C++ standard.
|
||||
@ -89,7 +94,7 @@ public:
|
||||
link_trace(0.), plaquette(0.), checksum(0),
|
||||
scidac_checksuma(0), scidac_checksumb(0), sequence_number(0)
|
||||
{}
|
||||
};
|
||||
};
|
||||
|
||||
// PB disable using namespace - this is a header and forces namesapce visibility for all
|
||||
// including files
|
||||
|
@ -57,14 +57,15 @@ struct StaggeredImplParams {
|
||||
StaggeredImplParams() {};
|
||||
};
|
||||
|
||||
struct OneFlavourRationalParams : Serializable {
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(OneFlavourRationalParams,
|
||||
RealD, lo,
|
||||
RealD, hi,
|
||||
int, MaxIter,
|
||||
RealD, tolerance,
|
||||
int, degree,
|
||||
int, precision);
|
||||
struct OneFlavourRationalParams : Serializable {
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(OneFlavourRationalParams,
|
||||
RealD, lo,
|
||||
RealD, hi,
|
||||
int, MaxIter,
|
||||
RealD, tolerance,
|
||||
int, degree,
|
||||
int, precision,
|
||||
int, BoundsCheckFreq);
|
||||
|
||||
// MaxIter and tolerance, vectors??
|
||||
|
||||
@ -74,15 +75,17 @@ struct OneFlavourRationalParams : Serializable {
|
||||
int _maxit = 1000,
|
||||
RealD tol = 1.0e-8,
|
||||
int _degree = 10,
|
||||
int _precision = 64)
|
||||
: lo(_lo),
|
||||
hi(_hi),
|
||||
MaxIter(_maxit),
|
||||
tolerance(tol),
|
||||
degree(_degree),
|
||||
precision(_precision){};
|
||||
};
|
||||
|
||||
int _precision = 64,
|
||||
int _BoundsCheckFreq=20)
|
||||
: lo(_lo),
|
||||
hi(_hi),
|
||||
MaxIter(_maxit),
|
||||
tolerance(tol),
|
||||
degree(_degree),
|
||||
precision(_precision),
|
||||
BoundsCheckFreq(_BoundsCheckFreq){};
|
||||
};
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
||||
#endif
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
public:
|
||||
|
||||
void FreePropagator(const FermionField &in,FermionField &out,RealD mass, std::vector<double> twist, bool fiveD) {
|
||||
void FreePropagator(const FermionField &in,FermionField &out,RealD mass,std::vector<Complex> boundary, std::vector<double> twist, bool fiveD) {
|
||||
FermionField in_k(in.Grid());
|
||||
FermionField prop_k(in.Grid());
|
||||
|
||||
@ -54,15 +54,19 @@ public:
|
||||
typedef typename Simd::scalar_type Scalar;
|
||||
Scalar ci(0.0,1.0);
|
||||
assert(twist.size() == Nd);//check that twist is Nd
|
||||
assert(boundary.size() == Nd);//check that boundary conditions is Nd
|
||||
int shift = 0;
|
||||
if(fiveD) shift = 1;
|
||||
for(unsigned int nu = 0; nu < Nd; nu++)
|
||||
{
|
||||
// Shift coordinate lattice index by 1 to account for 5th dimension.
|
||||
LatticeCoordinate(coor, nu + shift);
|
||||
ph = ph + twist[nu]*coor*((1./(in.Grid()->FullDimensions()[nu+shift])));
|
||||
double boundary_phase = ::acos(real(boundary[nu]));
|
||||
ph = ph + boundary_phase*coor*((1./(in.Grid()->_fdimensions[nu+shift])));
|
||||
//momenta for propagator shifted by twist+boundary
|
||||
twist[nu] = twist[nu] + boundary_phase/((2.0*M_PI));
|
||||
}
|
||||
in_buf = exp(Scalar(2.0*M_PI)*ci*ph*(-1.0))*in;
|
||||
in_buf = exp(ci*ph*(-1.0))*in;
|
||||
|
||||
if(fiveD){//FFT only on temporal and spatial dimensions
|
||||
std::vector<int> mask(Nd+1,1); mask[0] = 0;
|
||||
@ -75,26 +79,29 @@ public:
|
||||
this->MomentumSpacePropagatorHt(prop_k,in_k,mass,twist);
|
||||
theFFT.FFT_all_dim(out,prop_k,FFT::backward);
|
||||
}
|
||||
|
||||
//phase for boundary condition
|
||||
out = out * exp(Scalar(2.0*M_PI)*ci*ph);
|
||||
};
|
||||
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass,std::vector<double> twist) {
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass,std::vector<Complex> boundary,std::vector<double> twist) {
|
||||
bool fiveD = true; //5d propagator by default
|
||||
FreePropagator(in,out,mass,twist,fiveD);
|
||||
FreePropagator(in,out,mass,boundary,twist,fiveD);
|
||||
};
|
||||
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass, bool fiveD) {
|
||||
std::vector<double> twist(Nd,0.0); //default: periodic boundarys in all directions
|
||||
FreePropagator(in,out,mass,twist,fiveD);
|
||||
std::vector<Complex> boundary;
|
||||
for(int i=0;i<Nd;i++) boundary.push_back(1);//default: periodic boundary conditions
|
||||
FreePropagator(in,out,mass,boundary,twist,fiveD);
|
||||
};
|
||||
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass) {
|
||||
bool fiveD = true; //5d propagator by default
|
||||
std::vector<double> twist(Nd,0.0); //default: periodic boundarys in all directions
|
||||
FreePropagator(in,out,mass,twist,fiveD);
|
||||
};
|
||||
std::vector<double> twist(Nd,0.0); //default: twist angle 0
|
||||
std::vector<Complex> boundary;
|
||||
for(int i=0;i<Nd;i++) boundary.push_back(1); //default: periodic boundary conditions
|
||||
FreePropagator(in,out,mass,boundary,twist,fiveD);
|
||||
};
|
||||
|
||||
virtual void Instantiatable(void) {};
|
||||
// Constructors
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
|
||||
virtual void MomentumSpacePropagator(FermionField &out,const FermionField &in,RealD _m,std::vector<double> twist) { assert(0);};
|
||||
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass,std::vector<double> twist)
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass,std::vector<Complex> boundary,std::vector<double> twist)
|
||||
{
|
||||
FFT theFFT((GridCartesian *) in.Grid());
|
||||
|
||||
@ -106,27 +106,35 @@ public:
|
||||
ComplexField coor(in.Grid());
|
||||
ComplexField ph(in.Grid()); ph = Zero();
|
||||
FermionField in_buf(in.Grid()); in_buf = Zero();
|
||||
|
||||
Scalar ci(0.0,1.0);
|
||||
assert(twist.size() == Nd);//check that twist is Nd
|
||||
assert(boundary.size() == Nd);//check that boundary conditions is Nd
|
||||
for(unsigned int nu = 0; nu < Nd; nu++)
|
||||
{
|
||||
LatticeCoordinate(coor, nu);
|
||||
ph = ph + twist[nu]*coor*((1./(in.Grid()->_fdimensions[nu])));
|
||||
double boundary_phase = ::acos(real(boundary[nu]));
|
||||
ph = ph + boundary_phase*coor*((1./(in.Grid()->_fdimensions[nu])));
|
||||
//momenta for propagator shifted by twist+boundary
|
||||
twist[nu] = twist[nu] + boundary_phase/((2.0*M_PI));
|
||||
}
|
||||
in_buf = (exp(Scalar(2.0*M_PI)*ci*ph*(-1.0)))*in;
|
||||
in_buf = exp(ci*ph*(-1.0))*in;
|
||||
|
||||
theFFT.FFT_all_dim(in_k,in_buf,FFT::forward);
|
||||
this->MomentumSpacePropagator(prop_k,in_k,mass,twist);
|
||||
theFFT.FFT_all_dim(out,prop_k,FFT::backward);
|
||||
theFFT.FFT_all_dim(out,prop_k,FFT::backward);
|
||||
|
||||
//phase for boundary condition
|
||||
out = out * exp(Scalar(2.0*M_PI)*ci*ph);
|
||||
|
||||
};
|
||||
|
||||
virtual void FreePropagator(const FermionField &in,FermionField &out,RealD mass) {
|
||||
std::vector<double> twist(Nd,0.0); //default: periodic boundarys in all directions
|
||||
FreePropagator(in,out,mass,twist);
|
||||
};
|
||||
std::vector<Complex> boundary;
|
||||
for(int i=0;i<Nd;i++) boundary.push_back(1);//default: periodic boundary conditions
|
||||
std::vector<double> twist(Nd,0.0); //default: periodic boundarys in all directions
|
||||
FreePropagator(in,out,mass,boundary,twist);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// Updates gauge field during HMC
|
||||
@ -146,8 +154,14 @@ public:
|
||||
Current curr_type,
|
||||
unsigned int mu,
|
||||
unsigned int tmin,
|
||||
unsigned int tmax,
|
||||
ComplexField &lattice_cmplx)=0;
|
||||
unsigned int tmax,
|
||||
ComplexField &lattice_cmplx)=0;
|
||||
|
||||
// Only reimplemented in Wilson5D
|
||||
// Default to just a zero correlation function
|
||||
virtual void ContractJ5q(FermionField &q_in ,ComplexField &J5q) { J5q=Zero(); };
|
||||
virtual void ContractJ5q(PropagatorField &q_in,ComplexField &J5q) { J5q=Zero(); };
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// Physical field import/export
|
||||
///////////////////////////////////////////////
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
public:
|
||||
typedef WilsonFermion<Impl> WilsonBase;
|
||||
|
||||
virtual int ConstEE(void) { return 0; };
|
||||
virtual void Instantiatable(void){};
|
||||
// Constructors
|
||||
WilsonCloverFermion(GaugeField &_Umu, GridCartesian &Fgrid,
|
||||
|
@ -229,6 +229,10 @@ public:
|
||||
unsigned int tmin,
|
||||
unsigned int tmax,
|
||||
ComplexField &lattice_cmplx);
|
||||
|
||||
void ContractJ5q(PropagatorField &q_in,ComplexField &J5q);
|
||||
void ContractJ5q(FermionField &q_in,ComplexField &J5q);
|
||||
|
||||
};
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
@ -898,6 +898,79 @@ void WilsonFermion5D<Impl>::MomentumSpacePropagatorHw(FermionField &out,const Fe
|
||||
merge(qSiteRev, qSiteVec); \
|
||||
}
|
||||
|
||||
// psi = chiralProjectPlus(Result_s[Ls/2-1]);
|
||||
// psi+= chiralProjectMinus(Result_s[Ls/2]);
|
||||
// PJ5q+=localInnerProduct(psi,psi);
|
||||
|
||||
template<class vobj>
|
||||
Lattice<vobj> spProj5p(const Lattice<vobj> & in)
|
||||
{
|
||||
GridBase *grid=in.Grid();
|
||||
Gamma G5(Gamma::Algebra::Gamma5);
|
||||
Lattice<vobj> ret(grid);
|
||||
auto ret_v = ret.View();
|
||||
auto in_v = in.View();
|
||||
thread_for(ss,grid->oSites(),{
|
||||
ret_v[ss] = in_v[ss] + G5*in_v[ss];
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
template<class vobj>
|
||||
Lattice<vobj> spProj5m(const Lattice<vobj> & in)
|
||||
{
|
||||
Gamma G5(Gamma::Algebra::Gamma5);
|
||||
GridBase *grid=in.Grid();
|
||||
Lattice<vobj> ret(grid);
|
||||
auto ret_v = ret.View();
|
||||
auto in_v = in.View();
|
||||
thread_for(ss,grid->oSites(),{
|
||||
ret_v[ss] = in_v[ss] - G5*in_v[ss];
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void WilsonFermion5D<Impl>::ContractJ5q(FermionField &q_in,ComplexField &J5q)
|
||||
{
|
||||
conformable(GaugeGrid(), J5q.Grid());
|
||||
conformable(q_in.Grid(), FermionGrid());
|
||||
|
||||
// 4d field
|
||||
int Ls = this->Ls;
|
||||
FermionField psi(GaugeGrid());
|
||||
FermionField p_plus (GaugeGrid());
|
||||
FermionField p_minus(GaugeGrid());
|
||||
FermionField p(GaugeGrid());
|
||||
|
||||
ExtractSlice(p_plus , q_in, Ls/2 , 0);
|
||||
ExtractSlice(p_minus, q_in, Ls/2-1 , 0);
|
||||
p_plus = spProj5p(p_plus );
|
||||
p_minus= spProj5m(p_minus);
|
||||
p=p_plus+p_minus;
|
||||
J5q = localInnerProduct(p,p);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void WilsonFermion5D<Impl>::ContractJ5q(PropagatorField &q_in,ComplexField &J5q)
|
||||
{
|
||||
conformable(GaugeGrid(), J5q.Grid());
|
||||
conformable(q_in.Grid(), FermionGrid());
|
||||
|
||||
// 4d field
|
||||
int Ls = this->Ls;
|
||||
PropagatorField psi(GaugeGrid());
|
||||
PropagatorField p_plus (GaugeGrid());
|
||||
PropagatorField p_minus(GaugeGrid());
|
||||
PropagatorField p(GaugeGrid());
|
||||
|
||||
ExtractSlice(p_plus , q_in, Ls/2 , 0);
|
||||
ExtractSlice(p_minus, q_in, Ls/2-1 , 0);
|
||||
p_plus = spProj5p(p_plus );
|
||||
p_minus= spProj5m(p_minus);
|
||||
p=p_plus+p_minus;
|
||||
J5q = localInnerProduct(p,p);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void WilsonFermion5D<Impl>::ContractConservedCurrent(PropagatorField &q_in_1,
|
||||
PropagatorField &q_in_2,
|
||||
@ -908,6 +981,7 @@ void WilsonFermion5D<Impl>::ContractConservedCurrent(PropagatorField &q_in_1,
|
||||
conformable(q_in_1.Grid(), FermionGrid());
|
||||
conformable(q_in_1.Grid(), q_in_2.Grid());
|
||||
conformable(_FourDimGrid, q_out.Grid());
|
||||
|
||||
PropagatorField tmp1(FermionGrid()), tmp2(FermionGrid());
|
||||
unsigned int LLs = q_in_1.Grid()->_rdimensions[0];
|
||||
q_out = Zero();
|
||||
@ -960,7 +1034,6 @@ void WilsonFermion5D<Impl>::ContractConservedCurrent(PropagatorField &q_in_1,
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class Impl>
|
||||
void WilsonFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in,
|
||||
PropagatorField &q_out,
|
||||
|
@ -29,14 +29,24 @@ directory
|
||||
#ifndef GRID_GAUGE_IMPL_TYPES_H
|
||||
#define GRID_GAUGE_IMPL_TYPES_H
|
||||
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
#define CPS_MD_TIME
|
||||
|
||||
#ifdef CPS_MD_TIME
|
||||
#define HMC_MOMENTUM_DENOMINATOR (2.0)
|
||||
#else
|
||||
#define HMC_MOMENTUM_DENOMINATOR (1.0)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation dependent gauge types
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define INHERIT_GIMPL_TYPES(GImpl) \
|
||||
typedef typename GImpl::Simd Simd; \
|
||||
typedef typename GImpl::Scalar Scalar; \
|
||||
typedef typename GImpl::LinkField GaugeLinkField; \
|
||||
typedef typename GImpl::Field GaugeField; \
|
||||
typedef typename GImpl::ComplexField ComplexField;\
|
||||
@ -54,7 +64,8 @@ NAMESPACE_BEGIN(Grid);
|
||||
template <class S, int Nrepresentation = Nc, int Nexp = 12 > class GaugeImplTypes {
|
||||
public:
|
||||
typedef S Simd;
|
||||
|
||||
typedef typename Simd::scalar_type scalar_type;
|
||||
typedef scalar_type Scalar;
|
||||
template <typename vtype> using iImplScalar = iScalar<iScalar<iScalar<vtype> > >;
|
||||
template <typename vtype> using iImplGaugeLink = iScalar<iScalar<iMatrix<vtype, Nrepresentation> > >;
|
||||
template <typename vtype> using iImplGaugeField = iVector<iScalar<iMatrix<vtype, Nrepresentation> >, Nd>;
|
||||
@ -85,12 +96,10 @@ public:
|
||||
///////////////////////////////////////////////////////////
|
||||
// Move these to another class
|
||||
// HMC auxiliary functions
|
||||
static inline void generate_momenta(Field &P, GridParallelRNG &pRNG) {
|
||||
// specific for SU gauge fields
|
||||
LinkField Pmu(P.Grid());
|
||||
Pmu = Zero();
|
||||
//
|
||||
static inline void generate_momenta(Field &P, GridParallelRNG &pRNG)
|
||||
{
|
||||
// Zbigniew Srocinsky thesis:
|
||||
//
|
||||
// P(p) = N \Prod_{x\mu}e^-{1/2 Tr (p^2_mux)}
|
||||
//
|
||||
// p_x,mu = c_x,mu,a T_a
|
||||
@ -101,26 +110,16 @@ public:
|
||||
//
|
||||
// = N \Prod_{x,\mu,a} e^-{1/2 (c_xmua/sqrt{2})^2 }
|
||||
//
|
||||
// Expect cx' = cxmua/sqrt(2) to be a unit variance gaussian.
|
||||
//
|
||||
// Expect cxmua_new variance sqrt(2).
|
||||
// Was variance cxmua_old variance 1
|
||||
//
|
||||
// tau_old * Pold = 1 = tau_old/sqrt(2) * [Pold * sqrt(2)]
|
||||
// = tau_new * Pnew
|
||||
// Expect cxmua variance sqrt(2).
|
||||
//
|
||||
// Hence tau_new = tau_cps = tau_guido/sqrt(2).
|
||||
// Must scale the momentum by sqrt(2) to invoke CPS and UKQCD conventions
|
||||
//
|
||||
//
|
||||
// Must scale the momentum by sqrt(2) up to invoke CPS and UKQCD conventions
|
||||
//
|
||||
//
|
||||
// Hence expect cxmua = cx'*sqrt(2).
|
||||
//
|
||||
// Seek the scale parameter to be
|
||||
LinkField Pmu(P.Grid());
|
||||
Pmu = Zero();
|
||||
for (int mu = 0; mu < Nd; mu++) {
|
||||
SU<Nrepresentation>::GaussianFundamentalLieAlgebraMatrix(pRNG, Pmu);
|
||||
RealD scale = ::sqrt(2) ;
|
||||
RealD scale = ::sqrt(HMC_MOMENTUM_DENOMINATOR) ;
|
||||
Pmu = Pmu*scale;
|
||||
PokeIndex<LorentzIndex>(P, Pmu, mu);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ NAMESPACE_BEGIN(Grid);
|
||||
{
|
||||
public:
|
||||
typedef S Simd;
|
||||
typedef typename Simd::scalar_type Scalar;
|
||||
|
||||
template <typename vtype>
|
||||
using iImplGaugeLink = iScalar<iScalar<iScalar<vtype>>>;
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
virtual void deriv(const GaugeField &Umu,GaugeField & dSdU) {
|
||||
//extend Ta to include Lorentz indexes
|
||||
RealD factor_p = c_plaq/RealD(Nc)*0.5;
|
||||
RealD factor_r = c_rect/RealD(Nc)*0.5;
|
||||
RealD factor_r = c_rect/RealD(Nc)*0.5;
|
||||
|
||||
GridBase *grid = Umu.Grid();
|
||||
|
||||
|
53
Grid/qcd/action/pseudofermion/Bounds.h
Normal file
53
Grid/qcd/action/pseudofermion/Bounds.h
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
namespace Grid{
|
||||
namespace QCD{
|
||||
|
||||
template<class Field>
|
||||
void HighBoundCheck(LinearOperatorBase<Field> &HermOp,
|
||||
Field &Phi,
|
||||
RealD hi)
|
||||
{
|
||||
// Eigenvalue bound check at high end
|
||||
PowerMethod<Field> power_method;
|
||||
auto lambda_max = power_method(HermOp,Phi);
|
||||
std::cout << GridLogMessage << "Pseudofermion action lamda_max "<<lambda_max<<"( bound "<<hi<<")"<<std::endl;
|
||||
assert( (lambda_max < hi) && " High Bounds Check on operator failed" );
|
||||
}
|
||||
|
||||
template<class Field> void InverseSqrtBoundsCheck(int MaxIter,double tol,
|
||||
LinearOperatorBase<Field> &HermOp,
|
||||
Field &GaussNoise,
|
||||
MultiShiftFunction &PowerNegHalf)
|
||||
{
|
||||
GridBase *FermionGrid = GaussNoise._grid;
|
||||
|
||||
Field X(FermionGrid);
|
||||
Field Y(FermionGrid);
|
||||
Field Z(FermionGrid);
|
||||
|
||||
X=GaussNoise;
|
||||
RealD Nx = norm2(X);
|
||||
|
||||
ConjugateGradientMultiShift<Field> msCG(MaxIter,PowerNegHalf);
|
||||
msCG(HermOp,X,Y);
|
||||
msCG(HermOp,Y,Z);
|
||||
|
||||
RealD Nz = norm2(Z);
|
||||
|
||||
HermOp.HermOp(Z,Y);
|
||||
RealD Ny = norm2(Y);
|
||||
|
||||
X=X-Y;
|
||||
RealD Nd = norm2(X);
|
||||
std::cout << "************************* "<<std::endl;
|
||||
std::cout << " noise = "<<Nx<<std::endl;
|
||||
std::cout << " (MdagM^-1/2)^2 noise = "<<Nz<<std::endl;
|
||||
std::cout << " MdagM (MdagM^-1/2)^2 noise = "<<Ny<<std::endl;
|
||||
std::cout << " noise - MdagM (MdagM^-1/2)^2 noise = "<<Nd<<std::endl;
|
||||
std::cout << "************************* "<<std::endl;
|
||||
assert( (std::sqrt(Nd/Nx)<tol) && " InverseSqrtBoundsCheck ");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -25,240 +25,302 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
/* END LEGAL */
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Implementation of exact one flavour algorithm (EOFA) //
|
||||
// using fermion classes defined in: //
|
||||
// Grid/qcd/action/fermion/DomainWallEOFAFermion.h (Shamir) //
|
||||
// Grid/qcd/action/fermion/MobiusEOFAFermion.h (Mobius) //
|
||||
// arXiv: 1403.1683, 1706.05843 //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Implementation of exact one flavour algorithm (EOFA) //
|
||||
// using fermion classes defined in: //
|
||||
// Grid/qcd/action/fermion/DomainWallEOFAFermion.h (Shamir) //
|
||||
// Grid/qcd/action/fermion/MobiusEOFAFermion.h (Mobius) //
|
||||
// arXiv: 1403.1683, 1706.05843 //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef QCD_PSEUDOFERMION_EXACT_ONE_FLAVOUR_RATIO_H
|
||||
#define QCD_PSEUDOFERMION_EXACT_ONE_FLAVOUR_RATIO_H
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
namespace Grid{
|
||||
namespace QCD{
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Exact one flavour implementation of DWF determinant ratio //
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Exact one flavour implementation of DWF determinant ratio //
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Impl>
|
||||
class ExactOneFlavourRatioPseudoFermionAction : public Action<typename Impl::GaugeField>
|
||||
{
|
||||
public:
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
typedef OneFlavourRationalParams Params;
|
||||
Params param;
|
||||
MultiShiftFunction PowerNegHalf;
|
||||
|
||||
private:
|
||||
bool use_heatbath_forecasting;
|
||||
AbstractEOFAFermion<Impl>& Lop; // the basic LH operator
|
||||
AbstractEOFAFermion<Impl>& Rop; // the basic RH operator
|
||||
SchurRedBlackDiagMooeeSolve<FermionField> Solver;
|
||||
FermionField Phi; // the pseudofermion field for this trajectory
|
||||
|
||||
public:
|
||||
ExactOneFlavourRatioPseudoFermionAction(AbstractEOFAFermion<Impl>& _Lop, AbstractEOFAFermion<Impl>& _Rop,
|
||||
OperatorFunction<FermionField>& S, Params& p, bool use_fc=false) : Lop(_Lop), Rop(_Rop), Solver(S),
|
||||
Phi(_Lop.FermionGrid()), param(p), use_heatbath_forecasting(use_fc)
|
||||
template<class Impl>
|
||||
class ExactOneFlavourRatioPseudoFermionAction : public Action<typename Impl::GaugeField>
|
||||
{
|
||||
AlgRemez remez(param.lo, param.hi, param.precision);
|
||||
public:
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
typedef OneFlavourRationalParams Params;
|
||||
Params param;
|
||||
MultiShiftFunction PowerNegHalf;
|
||||
|
||||
// MdagM^(+- 1/2)
|
||||
std::cout << GridLogMessage << "Generating degree " << param.degree << " for x^(-1/2)" << std::endl;
|
||||
remez.generateApprox(param.degree, 1, 2);
|
||||
PowerNegHalf.Init(remez, param.tolerance, true);
|
||||
};
|
||||
private:
|
||||
bool use_heatbath_forecasting;
|
||||
AbstractEOFAFermion<Impl>& Lop; // the basic LH operator
|
||||
AbstractEOFAFermion<Impl>& Rop; // the basic RH operator
|
||||
SchurRedBlackDiagMooeeSolve<FermionField> SolverHB;
|
||||
SchurRedBlackDiagMooeeSolve<FermionField> SolverL;
|
||||
SchurRedBlackDiagMooeeSolve<FermionField> SolverR;
|
||||
SchurRedBlackDiagMooeeSolve<FermionField> DerivativeSolverL;
|
||||
SchurRedBlackDiagMooeeSolve<FermionField> DerivativeSolverR;
|
||||
FermionField Phi; // the pseudofermion field for this trajectory
|
||||
|
||||
virtual std::string action_name() { return "ExactOneFlavourRatioPseudoFermionAction"; }
|
||||
public:
|
||||
ExactOneFlavourRatioPseudoFermionAction(AbstractEOFAFermion<Impl>& _Lop,
|
||||
AbstractEOFAFermion<Impl>& _Rop,
|
||||
OperatorFunction<FermionField>& HeatbathCG,
|
||||
OperatorFunction<FermionField>& ActionCGL, OperatorFunction<FermionField>& ActionCGR,
|
||||
OperatorFunction<FermionField>& DerivCGL , OperatorFunction<FermionField>& DerivCGR,
|
||||
Params& p,
|
||||
bool use_fc=false) :
|
||||
Lop(_Lop),
|
||||
Rop(_Rop),
|
||||
SolverHB(HeatbathCG,false,true),
|
||||
SolverL(ActionCGL, false, true), SolverR(ActionCGR, false, true),
|
||||
DerivativeSolverL(DerivCGL, false, true), DerivativeSolverR(DerivCGR, false, true),
|
||||
Phi(_Lop.FermionGrid()),
|
||||
param(p),
|
||||
use_heatbath_forecasting(use_fc)
|
||||
{
|
||||
AlgRemez remez(param.lo, param.hi, param.precision);
|
||||
|
||||
virtual std::string LogParameters() {
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Low :" << param.lo << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] High :" << param.hi << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Max iterations :" << param.MaxIter << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Tolerance :" << param.tolerance << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Degree :" << param.degree << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Precision :" << param.precision << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
// MdagM^(+- 1/2)
|
||||
std::cout << GridLogMessage << "Generating degree " << param.degree << " for x^(-1/2)" << std::endl;
|
||||
remez.generateApprox(param.degree, 1, 2);
|
||||
PowerNegHalf.Init(remez, param.tolerance, true);
|
||||
};
|
||||
|
||||
// Spin projection
|
||||
void spProj(const FermionField& in, FermionField& out, int sign, int Ls)
|
||||
{
|
||||
if(sign == 1){ for(int s=0; s<Ls; ++s){ axpby_ssp_pplus(out, 0.0, in, 1.0, in, s, s); } }
|
||||
else{ for(int s=0; s<Ls; ++s){ axpby_ssp_pminus(out, 0.0, in, 1.0, in, s, s); } }
|
||||
}
|
||||
virtual std::string action_name() { return "ExactOneFlavourRatioPseudoFermionAction"; }
|
||||
|
||||
// EOFA heatbath: see Eqn. (29) of arXiv:1706.05843
|
||||
// We generate a Gaussian noise vector \eta, and then compute
|
||||
// \Phi = M_{\rm EOFA}^{-1/2} * \eta
|
||||
// using a rational approximation to the inverse square root
|
||||
virtual void refresh(const GaugeField& U, GridParallelRNG& pRNG)
|
||||
{
|
||||
Lop.ImportGauge(U);
|
||||
Rop.ImportGauge(U);
|
||||
|
||||
FermionField eta (Lop.FermionGrid());
|
||||
FermionField CG_src (Lop.FermionGrid());
|
||||
FermionField CG_soln (Lop.FermionGrid());
|
||||
FermionField Forecast_src(Lop.FermionGrid());
|
||||
std::vector<FermionField> tmp(2, Lop.FermionGrid());
|
||||
|
||||
// Use chronological inverter to forecast solutions across poles
|
||||
std::vector<FermionField> prev_solns;
|
||||
if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); }
|
||||
ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast;
|
||||
|
||||
// Seed with Gaussian noise vector (var = 0.5)
|
||||
RealD scale = std::sqrt(0.5);
|
||||
gaussian(pRNG,eta);
|
||||
eta = eta * scale;
|
||||
printf("Heatbath source vector: <\\eta|\\eta> = %1.15e\n", norm2(eta));
|
||||
|
||||
// \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta
|
||||
RealD N(PowerNegHalf.norm);
|
||||
for(int k=0; k<param.degree; ++k){ N += PowerNegHalf.residues[k] / ( 1.0 + PowerNegHalf.poles[k] ); }
|
||||
Phi = eta * N;
|
||||
|
||||
// LH terms:
|
||||
// \Phi = \Phi + k \sum_{k=1}^{N_{p}} P_{-} \Omega_{-}^{\dagger} ( H(mf)
|
||||
// - \gamma_{l} \Delta_{-}(mf,mb) P_{-} )^{-1} \Omega_{-} P_{-} \eta
|
||||
RealD gamma_l(0.0);
|
||||
spProj(eta, tmp[0], -1, Lop.Ls);
|
||||
Lop.Omega(tmp[0], tmp[1], -1, 0);
|
||||
G5R5(CG_src, tmp[1]);
|
||||
tmp[1] = Zero();
|
||||
for(int k=0; k<param.degree; ++k){
|
||||
gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] );
|
||||
Lop.RefreshShiftCoefficients(-gamma_l);
|
||||
if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles
|
||||
Lop.Mdag(CG_src, Forecast_src);
|
||||
CG_soln = Forecast(Lop, Forecast_src, prev_solns);
|
||||
Solver(Lop, CG_src, CG_soln);
|
||||
prev_solns.push_back(CG_soln);
|
||||
} else {
|
||||
CG_soln = Zero(); // Just use zero as the initial guess
|
||||
Solver(Lop, CG_src, CG_soln);
|
||||
virtual std::string LogParameters() {
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Low :" << param.lo << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] High :" << param.hi << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Max iterations :" << param.MaxIter << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Tolerance :" << param.tolerance << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Degree :" << param.degree << std::endl;
|
||||
sstream << GridLogMessage << "[" << action_name() << "] Precision :" << param.precision << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
Lop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back
|
||||
tmp[1] = tmp[1] + ( PowerNegHalf.residues[k]*gamma_l*gamma_l*Lop.k ) * tmp[0];
|
||||
}
|
||||
Lop.Omega(tmp[1], tmp[0], -1, 1);
|
||||
spProj(tmp[0], tmp[1], -1, Lop.Ls);
|
||||
Phi = Phi + tmp[1];
|
||||
|
||||
// RH terms:
|
||||
// \Phi = \Phi - k \sum_{k=1}^{N_{p}} P_{+} \Omega_{+}^{\dagger} ( H(mb)
|
||||
// + \gamma_{l} \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} \eta
|
||||
spProj(eta, tmp[0], 1, Rop.Ls);
|
||||
Rop.Omega(tmp[0], tmp[1], 1, 0);
|
||||
G5R5(CG_src, tmp[1]);
|
||||
tmp[1] = Zero();
|
||||
if(use_heatbath_forecasting){ prev_solns.clear(); } // empirically, LH solns don't help for RH solves
|
||||
for(int k=0; k<param.degree; ++k){
|
||||
gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] );
|
||||
Rop.RefreshShiftCoefficients(-gamma_l*PowerNegHalf.poles[k]);
|
||||
if(use_heatbath_forecasting){
|
||||
Rop.Mdag(CG_src, Forecast_src);
|
||||
CG_soln = Forecast(Rop, Forecast_src, prev_solns);
|
||||
Solver(Rop, CG_src, CG_soln);
|
||||
prev_solns.push_back(CG_soln);
|
||||
} else {
|
||||
CG_soln = Zero();
|
||||
Solver(Rop, CG_src, CG_soln);
|
||||
// Spin projection
|
||||
void spProj(const FermionField& in, FermionField& out, int sign, int Ls)
|
||||
{
|
||||
if(sign == 1){ for(int s=0; s<Ls; ++s){ axpby_ssp_pplus(out, 0.0, in, 1.0, in, s, s); } }
|
||||
else{ for(int s=0; s<Ls; ++s){ axpby_ssp_pminus(out, 0.0, in, 1.0, in, s, s); } }
|
||||
}
|
||||
Rop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back
|
||||
tmp[1] = tmp[1] - ( PowerNegHalf.residues[k]*gamma_l*gamma_l*Rop.k ) * tmp[0];
|
||||
}
|
||||
Rop.Omega(tmp[1], tmp[0], 1, 1);
|
||||
spProj(tmp[0], tmp[1], 1, Rop.Ls);
|
||||
Phi = Phi + tmp[1];
|
||||
|
||||
// Reset shift coefficients for energy and force evals
|
||||
Lop.RefreshShiftCoefficients(0.0);
|
||||
Rop.RefreshShiftCoefficients(-1.0);
|
||||
// EOFA heatbath: see Eqn. (29) of arXiv:1706.05843
|
||||
// We generate a Gaussian noise vector \eta, and then compute
|
||||
// \Phi = M_{\rm EOFA}^{-1/2} * \eta
|
||||
// using a rational approximation to the inverse square root
|
||||
//
|
||||
// As a check of rational require \Phi^dag M_{EOFA} \Phi == eta^dag M^-1/2^dag M M^-1/2 eta = eta^dag eta
|
||||
//
|
||||
virtual void refresh(const GaugeField& U, GridParallelRNG& pRNG)
|
||||
{
|
||||
Lop.ImportGauge(U);
|
||||
Rop.ImportGauge(U);
|
||||
|
||||
FermionField eta (Lop.FermionGrid());
|
||||
FermionField CG_src (Lop.FermionGrid());
|
||||
FermionField CG_soln (Lop.FermionGrid());
|
||||
FermionField Forecast_src(Lop.FermionGrid());
|
||||
std::vector<FermionField> tmp(2, Lop.FermionGrid());
|
||||
|
||||
// Use chronological inverter to forecast solutions across poles
|
||||
std::vector<FermionField> prev_solns;
|
||||
if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); }
|
||||
ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast;
|
||||
|
||||
// Seed with Gaussian noise vector (var = 0.5)
|
||||
RealD scale = std::sqrt(0.5);
|
||||
gaussian(pRNG,eta);
|
||||
eta = eta * scale;
|
||||
|
||||
// \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta
|
||||
RealD N(PowerNegHalf.norm);
|
||||
for(int k=0; k<param.degree; ++k){ N += PowerNegHalf.residues[k] / ( 1.0 + PowerNegHalf.poles[k] ); }
|
||||
Phi = eta * N;
|
||||
|
||||
// LH terms:
|
||||
// \Phi = \Phi + k \sum_{k=1}^{N_{p}} P_{-} \Omega_{-}^{\dagger} ( H(mf)
|
||||
// - \gamma_{l} \Delta_{-}(mf,mb) P_{-} )^{-1} \Omega_{-} P_{-} \eta
|
||||
RealD gamma_l(0.0);
|
||||
spProj(eta, tmp[0], -1, Lop.Ls);
|
||||
Lop.Omega(tmp[0], tmp[1], -1, 0);
|
||||
G5R5(CG_src, tmp[1]);
|
||||
tmp[1] = zero;
|
||||
for(int k=0; k<param.degree; ++k){
|
||||
gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] );
|
||||
Lop.RefreshShiftCoefficients(-gamma_l);
|
||||
if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles
|
||||
Lop.Mdag(CG_src, Forecast_src);
|
||||
CG_soln = Forecast(Lop, Forecast_src, prev_solns);
|
||||
SolverHB(Lop, CG_src, CG_soln);
|
||||
prev_solns.push_back(CG_soln);
|
||||
} else {
|
||||
CG_soln = zero; // Just use zero as the initial guess
|
||||
SolverHB(Lop, CG_src, CG_soln);
|
||||
}
|
||||
Lop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back
|
||||
tmp[1] = tmp[1] + ( PowerNegHalf.residues[k]*gamma_l*gamma_l*Lop.k ) * tmp[0];
|
||||
}
|
||||
Lop.Omega(tmp[1], tmp[0], -1, 1);
|
||||
spProj(tmp[0], tmp[1], -1, Lop.Ls);
|
||||
Phi = Phi + tmp[1];
|
||||
|
||||
// RH terms:
|
||||
// \Phi = \Phi - k \sum_{k=1}^{N_{p}} P_{+} \Omega_{+}^{\dagger} ( H(mb)
|
||||
// + \gamma_{l} \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} \eta
|
||||
spProj(eta, tmp[0], 1, Rop.Ls);
|
||||
Rop.Omega(tmp[0], tmp[1], 1, 0);
|
||||
G5R5(CG_src, tmp[1]);
|
||||
tmp[1] = zero;
|
||||
if(use_heatbath_forecasting){ prev_solns.clear(); } // empirically, LH solns don't help for RH solves
|
||||
for(int k=0; k<param.degree; ++k){
|
||||
gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] );
|
||||
Rop.RefreshShiftCoefficients(-gamma_l*PowerNegHalf.poles[k]);
|
||||
if(use_heatbath_forecasting){
|
||||
Rop.Mdag(CG_src, Forecast_src);
|
||||
CG_soln = Forecast(Rop, Forecast_src, prev_solns);
|
||||
SolverHB(Rop, CG_src, CG_soln);
|
||||
prev_solns.push_back(CG_soln);
|
||||
} else {
|
||||
CG_soln = zero;
|
||||
SolverHB(Rop, CG_src, CG_soln);
|
||||
}
|
||||
Rop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back
|
||||
tmp[1] = tmp[1] - ( PowerNegHalf.residues[k]*gamma_l*gamma_l*Rop.k ) * tmp[0];
|
||||
}
|
||||
Rop.Omega(tmp[1], tmp[0], 1, 1);
|
||||
spProj(tmp[0], tmp[1], 1, Rop.Ls);
|
||||
Phi = Phi + tmp[1];
|
||||
|
||||
// Reset shift coefficients for energy and force evals
|
||||
Lop.RefreshShiftCoefficients(0.0);
|
||||
Rop.RefreshShiftCoefficients(-1.0);
|
||||
|
||||
// Bounds check
|
||||
RealD EtaDagEta = norm2(eta);
|
||||
// RealD PhiDagMPhi= norm2(eta);
|
||||
|
||||
};
|
||||
|
||||
void Meofa(const GaugeField& U,const FermionField &phi, FermionField & Mphi)
|
||||
{
|
||||
#if 0
|
||||
Lop.ImportGauge(U);
|
||||
Rop.ImportGauge(U);
|
||||
|
||||
FermionField spProj_Phi(Lop.FermionGrid());
|
||||
FermionField mPhi(Lop.FermionGrid());
|
||||
std::vector<FermionField> tmp(2, Lop.FermionGrid());
|
||||
mPhi = phi;
|
||||
|
||||
// LH term: S = S - k <\Phi| P_{-} \Omega_{-}^{\dagger} H(mf)^{-1} \Omega_{-} P_{-} |\Phi>
|
||||
spProj(Phi, spProj_Phi, -1, Lop.Ls);
|
||||
Lop.Omega(spProj_Phi, tmp[0], -1, 0);
|
||||
G5R5(tmp[1], tmp[0]);
|
||||
tmp[0] = zero;
|
||||
SolverL(Lop, tmp[1], tmp[0]);
|
||||
Lop.Dtilde(tmp[0], tmp[1]); // We actually solved Cayley preconditioned system: transform back
|
||||
Lop.Omega(tmp[1], tmp[0], -1, 1);
|
||||
mPhi = mPhi - Lop.k * innerProduct(spProj_Phi, tmp[0]).real();
|
||||
|
||||
// RH term: S = S + k <\Phi| P_{+} \Omega_{+}^{\dagger} ( H(mb)
|
||||
// - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{-} P_{-} |\Phi>
|
||||
spProj(Phi, spProj_Phi, 1, Rop.Ls);
|
||||
Rop.Omega(spProj_Phi, tmp[0], 1, 0);
|
||||
G5R5(tmp[1], tmp[0]);
|
||||
tmp[0] = zero;
|
||||
SolverR(Rop, tmp[1], tmp[0]);
|
||||
Rop.Dtilde(tmp[0], tmp[1]);
|
||||
Rop.Omega(tmp[1], tmp[0], 1, 1);
|
||||
action += Rop.k * innerProduct(spProj_Phi, tmp[0]).real();
|
||||
#endif
|
||||
}
|
||||
|
||||
// EOFA action: see Eqn. (10) of arXiv:1706.05843
|
||||
virtual RealD S(const GaugeField& U)
|
||||
{
|
||||
Lop.ImportGauge(U);
|
||||
Rop.ImportGauge(U);
|
||||
|
||||
FermionField spProj_Phi(Lop.FermionGrid());
|
||||
std::vector<FermionField> tmp(2, Lop.FermionGrid());
|
||||
|
||||
// S = <\Phi|\Phi>
|
||||
RealD action(norm2(Phi));
|
||||
|
||||
// LH term: S = S - k <\Phi| P_{-} \Omega_{-}^{\dagger} H(mf)^{-1} \Omega_{-} P_{-} |\Phi>
|
||||
spProj(Phi, spProj_Phi, -1, Lop.Ls);
|
||||
Lop.Omega(spProj_Phi, tmp[0], -1, 0);
|
||||
G5R5(tmp[1], tmp[0]);
|
||||
tmp[0] = zero;
|
||||
SolverL(Lop, tmp[1], tmp[0]);
|
||||
Lop.Dtilde(tmp[0], tmp[1]); // We actually solved Cayley preconditioned system: transform back
|
||||
Lop.Omega(tmp[1], tmp[0], -1, 1);
|
||||
action -= Lop.k * innerProduct(spProj_Phi, tmp[0]).real();
|
||||
|
||||
// RH term: S = S + k <\Phi| P_{+} \Omega_{+}^{\dagger} ( H(mb)
|
||||
// - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{-} P_{-} |\Phi>
|
||||
spProj(Phi, spProj_Phi, 1, Rop.Ls);
|
||||
Rop.Omega(spProj_Phi, tmp[0], 1, 0);
|
||||
G5R5(tmp[1], tmp[0]);
|
||||
tmp[0] = zero;
|
||||
SolverR(Rop, tmp[1], tmp[0]);
|
||||
Rop.Dtilde(tmp[0], tmp[1]);
|
||||
Rop.Omega(tmp[1], tmp[0], 1, 1);
|
||||
action += Rop.k * innerProduct(spProj_Phi, tmp[0]).real();
|
||||
|
||||
return action;
|
||||
};
|
||||
|
||||
// EOFA pseudofermion force: see Eqns. (34)-(36) of arXiv:1706.05843
|
||||
virtual void deriv(const GaugeField& U, GaugeField& dSdU)
|
||||
{
|
||||
Lop.ImportGauge(U);
|
||||
Rop.ImportGauge(U);
|
||||
|
||||
FermionField spProj_Phi (Lop.FermionGrid());
|
||||
FermionField Omega_spProj_Phi(Lop.FermionGrid());
|
||||
FermionField CG_src (Lop.FermionGrid());
|
||||
FermionField Chi (Lop.FermionGrid());
|
||||
FermionField g5_R5_Chi (Lop.FermionGrid());
|
||||
|
||||
GaugeField force(Lop.GaugeGrid());
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// PAB:
|
||||
// Optional single precision derivative ?
|
||||
/////////////////////////////////////////////
|
||||
|
||||
// LH: dSdU = k \chi_{L}^{\dagger} \gamma_{5} R_{5} ( \partial_{x,\mu} D_{w} ) \chi_{L}
|
||||
// \chi_{L} = H(mf)^{-1} \Omega_{-} P_{-} \Phi
|
||||
spProj(Phi, spProj_Phi, -1, Lop.Ls);
|
||||
Lop.Omega(spProj_Phi, Omega_spProj_Phi, -1, 0);
|
||||
G5R5(CG_src, Omega_spProj_Phi);
|
||||
spProj_Phi = zero;
|
||||
DerivativeSolverL(Lop, CG_src, spProj_Phi);
|
||||
Lop.Dtilde(spProj_Phi, Chi);
|
||||
G5R5(g5_R5_Chi, Chi);
|
||||
Lop.MDeriv(force, g5_R5_Chi, Chi, DaggerNo);
|
||||
dSdU = -Lop.k * force;
|
||||
|
||||
// RH: dSdU = dSdU - k \chi_{R}^{\dagger} \gamma_{5} R_{5} ( \partial_{x,\mu} D_{w} ) \chi_{}
|
||||
// \chi_{R} = ( H(mb) - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} \Phi
|
||||
spProj(Phi, spProj_Phi, 1, Rop.Ls);
|
||||
Rop.Omega(spProj_Phi, Omega_spProj_Phi, 1, 0);
|
||||
G5R5(CG_src, Omega_spProj_Phi);
|
||||
spProj_Phi = zero;
|
||||
DerivativeSolverR(Rop, CG_src, spProj_Phi);
|
||||
Rop.Dtilde(spProj_Phi, Chi);
|
||||
G5R5(g5_R5_Chi, Chi);
|
||||
Lop.MDeriv(force, g5_R5_Chi, Chi, DaggerNo);
|
||||
dSdU = dSdU + Rop.k * force;
|
||||
};
|
||||
};
|
||||
|
||||
// EOFA action: see Eqn. (10) of arXiv:1706.05843
|
||||
virtual RealD S(const GaugeField& U)
|
||||
{
|
||||
Lop.ImportGauge(U);
|
||||
Rop.ImportGauge(U);
|
||||
|
||||
FermionField spProj_Phi(Lop.FermionGrid());
|
||||
std::vector<FermionField> tmp(2, Lop.FermionGrid());
|
||||
|
||||
// S = <\Phi|\Phi>
|
||||
RealD action(norm2(Phi));
|
||||
|
||||
// LH term: S = S - k <\Phi| P_{-} \Omega_{-}^{\dagger} H(mf)^{-1} \Omega_{-} P_{-} |\Phi>
|
||||
spProj(Phi, spProj_Phi, -1, Lop.Ls);
|
||||
Lop.Omega(spProj_Phi, tmp[0], -1, 0);
|
||||
G5R5(tmp[1], tmp[0]);
|
||||
tmp[0] = Zero();
|
||||
Solver(Lop, tmp[1], tmp[0]);
|
||||
Lop.Dtilde(tmp[0], tmp[1]); // We actually solved Cayley preconditioned system: transform back
|
||||
Lop.Omega(tmp[1], tmp[0], -1, 1);
|
||||
action -= Lop.k * innerProduct(spProj_Phi, tmp[0]).real();
|
||||
|
||||
// RH term: S = S + k <\Phi| P_{+} \Omega_{+}^{\dagger} ( H(mb)
|
||||
// - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{-} P_{-} |\Phi>
|
||||
spProj(Phi, spProj_Phi, 1, Rop.Ls);
|
||||
Rop.Omega(spProj_Phi, tmp[0], 1, 0);
|
||||
G5R5(tmp[1], tmp[0]);
|
||||
tmp[0] = Zero();
|
||||
Solver(Rop, tmp[1], tmp[0]);
|
||||
Rop.Dtilde(tmp[0], tmp[1]);
|
||||
Rop.Omega(tmp[1], tmp[0], 1, 1);
|
||||
action += Rop.k * innerProduct(spProj_Phi, tmp[0]).real();
|
||||
|
||||
return action;
|
||||
};
|
||||
|
||||
// EOFA pseudofermion force: see Eqns. (34)-(36) of arXiv:1706.05843
|
||||
virtual void deriv(const GaugeField& U, GaugeField& dSdU)
|
||||
{
|
||||
Lop.ImportGauge(U);
|
||||
Rop.ImportGauge(U);
|
||||
|
||||
FermionField spProj_Phi (Lop.FermionGrid());
|
||||
FermionField Omega_spProj_Phi(Lop.FermionGrid());
|
||||
FermionField CG_src (Lop.FermionGrid());
|
||||
FermionField Chi (Lop.FermionGrid());
|
||||
FermionField g5_R5_Chi (Lop.FermionGrid());
|
||||
|
||||
GaugeField force(Lop.GaugeGrid());
|
||||
|
||||
// LH: dSdU = k \chi_{L}^{\dagger} \gamma_{5} R_{5} ( \partial_{x,\mu} D_{w} ) \chi_{L}
|
||||
// \chi_{L} = H(mf)^{-1} \Omega_{-} P_{-} \Phi
|
||||
spProj(Phi, spProj_Phi, -1, Lop.Ls);
|
||||
Lop.Omega(spProj_Phi, Omega_spProj_Phi, -1, 0);
|
||||
G5R5(CG_src, Omega_spProj_Phi);
|
||||
spProj_Phi = Zero();
|
||||
Solver(Lop, CG_src, spProj_Phi);
|
||||
Lop.Dtilde(spProj_Phi, Chi);
|
||||
G5R5(g5_R5_Chi, Chi);
|
||||
Lop.MDeriv(force, g5_R5_Chi, Chi, DaggerNo);
|
||||
dSdU = Lop.k * force;
|
||||
|
||||
// RH: dSdU = dSdU - k \chi_{R}^{\dagger} \gamma_{5} R_{5} ( \partial_{x,\mu} D_{w} ) \chi_{}
|
||||
// \chi_{R} = ( H(mb) - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} \Phi
|
||||
spProj(Phi, spProj_Phi, 1, Rop.Ls);
|
||||
Rop.Omega(spProj_Phi, Omega_spProj_Phi, 1, 0);
|
||||
G5R5(CG_src, Omega_spProj_Phi);
|
||||
spProj_Phi = Zero();
|
||||
Solver(Rop, CG_src, spProj_Phi);
|
||||
Rop.Dtilde(spProj_Phi, Chi);
|
||||
G5R5(g5_R5_Chi, Chi);
|
||||
Lop.MDeriv(force, g5_R5_Chi, Chi, DaggerNo);
|
||||
dSdU = dSdU - Rop.k * force;
|
||||
};
|
||||
};
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
@ -156,6 +156,13 @@ public:
|
||||
|
||||
msCG(Mpc, PhiOdd, Y);
|
||||
|
||||
if ( (rand()%param.BoundsCheckFreq)==0 ) {
|
||||
FermionField gauss(FermOp.FermionRedBlackGrid());
|
||||
gauss = PhiOdd;
|
||||
HighBoundCheck(Mpc,gauss,param.hi);
|
||||
InverseSqrtBoundsCheck(param.MaxIter,param.tolerance*100,Mpc,gauss,PowerNegHalf);
|
||||
}
|
||||
|
||||
RealD action = norm2(Y);
|
||||
std::cout << GridLogMessage << "Pseudofermion action FIXME -- is -1/4 "
|
||||
"solve or -1/2 solve faster??? "
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*************************************************************************************
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
@ -23,257 +23,267 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef QCD_PSEUDOFERMION_ONE_FLAVOUR_EVEN_ODD_RATIONAL_RATIO_H
|
||||
#define QCD_PSEUDOFERMION_ONE_FLAVOUR_EVEN_ODD_RATIONAL_RATIO_H
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
///////////////////////////////////////
|
||||
// One flavour rational
|
||||
///////////////////////////////////////
|
||||
namespace Grid{
|
||||
namespace QCD{
|
||||
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// Here P/Q \sim R_{1/4} ~ (V^dagV)^{1/4}
|
||||
// Here N/D \sim R_{-1/2} ~ (M^dagM)^{-1/2}
|
||||
|
||||
template<class Impl>
|
||||
class OneFlavourEvenOddRatioRationalPseudoFermionAction : public Action<typename Impl::GaugeField> {
|
||||
public:
|
||||
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
|
||||
typedef OneFlavourRationalParams Params;
|
||||
Params param;
|
||||
|
||||
MultiShiftFunction PowerHalf ;
|
||||
MultiShiftFunction PowerNegHalf;
|
||||
MultiShiftFunction PowerQuarter;
|
||||
MultiShiftFunction PowerNegQuarter;
|
||||
|
||||
private:
|
||||
|
||||
FermionOperator<Impl> & NumOp;// the basic operator
|
||||
FermionOperator<Impl> & DenOp;// the basic operator
|
||||
FermionField PhiEven; // the pseudo fermion field for this trajectory
|
||||
FermionField PhiOdd; // the pseudo fermion field for this trajectory
|
||||
|
||||
public:
|
||||
|
||||
OneFlavourEvenOddRatioRationalPseudoFermionAction(FermionOperator<Impl> &_NumOp,
|
||||
FermionOperator<Impl> &_DenOp,
|
||||
Params & p
|
||||
) :
|
||||
NumOp(_NumOp),
|
||||
DenOp(_DenOp),
|
||||
PhiOdd (_NumOp.FermionRedBlackGrid()),
|
||||
PhiEven(_NumOp.FermionRedBlackGrid()),
|
||||
param(p)
|
||||
{
|
||||
AlgRemez remez(param.lo,param.hi,param.precision);
|
||||
|
||||
// MdagM^(+- 1/2)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,2);
|
||||
PowerHalf.Init(remez,param.tolerance,false);
|
||||
PowerNegHalf.Init(remez,param.tolerance,true);
|
||||
|
||||
// MdagM^(+- 1/4)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/4)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,4);
|
||||
PowerQuarter.Init(remez,param.tolerance,false);
|
||||
PowerNegQuarter.Init(remez,param.tolerance,true);
|
||||
};
|
||||
|
||||
virtual std::string action_name(){return "OneFlavourEvenOddRatioRationalPseudoFermionAction";}
|
||||
|
||||
virtual std::string LogParameters(){
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Low :" << param.lo << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] High :" << param.hi << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Tolerance :" << param.tolerance << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Degree :" << param.degree << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Precision :" << param.precision << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
|
||||
virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) {
|
||||
///////////////////////////////////////
|
||||
// One flavour rational
|
||||
///////////////////////////////////////
|
||||
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// P(phi) = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/2 (VdagV)^1/4 phi}
|
||||
// = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/4 (MdagM)^-1/4 (VdagV)^1/4 phi}
|
||||
//
|
||||
// Phi = (VdagV)^-1/4 Mdag^{1/4} eta
|
||||
//
|
||||
// P(eta) = e^{- eta^dag eta}
|
||||
//
|
||||
// e^{x^2/2 sig^2} => sig^2 = 0.5.
|
||||
//
|
||||
// So eta should be of width sig = 1/sqrt(2).
|
||||
// Here P/Q \sim R_{1/4} ~ (V^dagV)^{1/4}
|
||||
// Here N/D \sim R_{-1/2} ~ (M^dagM)^{-1/2}
|
||||
|
||||
template<class Impl>
|
||||
class OneFlavourEvenOddRatioRationalPseudoFermionAction : public Action<typename Impl::GaugeField> {
|
||||
public:
|
||||
|
||||
RealD scale = std::sqrt(0.5);
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
|
||||
FermionField eta(NumOp.FermionGrid());
|
||||
FermionField etaOdd (NumOp.FermionRedBlackGrid());
|
||||
FermionField etaEven(NumOp.FermionRedBlackGrid());
|
||||
FermionField tmp(NumOp.FermionRedBlackGrid());
|
||||
typedef OneFlavourRationalParams Params;
|
||||
Params param;
|
||||
|
||||
gaussian(pRNG,eta); eta=eta*scale;
|
||||
MultiShiftFunction PowerHalf ;
|
||||
MultiShiftFunction PowerNegHalf;
|
||||
MultiShiftFunction PowerQuarter;
|
||||
MultiShiftFunction PowerNegQuarter;
|
||||
|
||||
pickCheckerboard(Even,etaEven,eta);
|
||||
pickCheckerboard(Odd,etaOdd,eta);
|
||||
private:
|
||||
|
||||
FermionOperator<Impl> & NumOp;// the basic operator
|
||||
FermionOperator<Impl> & DenOp;// the basic operator
|
||||
FermionField PhiEven; // the pseudo fermion field for this trajectory
|
||||
FermionField PhiOdd; // the pseudo fermion field for this trajectory
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
public:
|
||||
|
||||
OneFlavourEvenOddRatioRationalPseudoFermionAction(FermionOperator<Impl> &_NumOp,
|
||||
FermionOperator<Impl> &_DenOp,
|
||||
Params & p
|
||||
) :
|
||||
NumOp(_NumOp),
|
||||
DenOp(_DenOp),
|
||||
PhiOdd (_NumOp.FermionRedBlackGrid()),
|
||||
PhiEven(_NumOp.FermionRedBlackGrid()),
|
||||
param(p)
|
||||
{
|
||||
AlgRemez remez(param.lo,param.hi,param.precision);
|
||||
|
||||
// MdagM^(+- 1/2)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,2);
|
||||
PowerHalf.Init(remez,param.tolerance,false);
|
||||
PowerNegHalf.Init(remez,param.tolerance,true);
|
||||
|
||||
// MdagM^(+- 1/4)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/4)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,4);
|
||||
PowerQuarter.Init(remez,param.tolerance,false);
|
||||
PowerNegQuarter.Init(remez,param.tolerance,true);
|
||||
};
|
||||
|
||||
virtual std::string action_name(){return "OneFlavourEvenOddRatioRationalPseudoFermionAction";}
|
||||
|
||||
virtual std::string LogParameters(){
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Low :" << param.lo << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] High :" << param.hi << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Tolerance :" << param.tolerance << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Degree :" << param.degree << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Precision :" << param.precision << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
|
||||
virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) {
|
||||
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// P(phi) = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/2 (VdagV)^1/4 phi}
|
||||
// = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/4 (MdagM)^-1/4 (VdagV)^1/4 phi}
|
||||
//
|
||||
// Phi = (VdagV)^-1/4 Mdag^{1/4} eta
|
||||
//
|
||||
// P(eta) = e^{- eta^dag eta}
|
||||
//
|
||||
// e^{x^2/2 sig^2} => sig^2 = 0.5.
|
||||
//
|
||||
// So eta should be of width sig = 1/sqrt(2).
|
||||
|
||||
RealD scale = std::sqrt(0.5);
|
||||
|
||||
FermionField eta(NumOp.FermionGrid());
|
||||
FermionField etaOdd (NumOp.FermionRedBlackGrid());
|
||||
FermionField etaEven(NumOp.FermionRedBlackGrid());
|
||||
FermionField tmp(NumOp.FermionRedBlackGrid());
|
||||
|
||||
gaussian(pRNG,eta); eta=eta*scale;
|
||||
|
||||
pickCheckerboard(Even,etaEven,eta);
|
||||
pickCheckerboard(Odd,etaOdd,eta);
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
|
||||
// MdagM^1/4 eta
|
||||
SchurDifferentiableOperator<Impl> MdagM(DenOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerQuarter);
|
||||
msCG_M(MdagM,etaOdd,tmp);
|
||||
// MdagM^1/4 eta
|
||||
SchurDifferentiableOperator<Impl> MdagM(DenOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerQuarter);
|
||||
msCG_M(MdagM,etaOdd,tmp);
|
||||
|
||||
// VdagV^-1/4 MdagM^1/4 eta
|
||||
SchurDifferentiableOperator<Impl> VdagV(NumOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerNegQuarter);
|
||||
msCG_V(VdagV,tmp,PhiOdd);
|
||||
// VdagV^-1/4 MdagM^1/4 eta
|
||||
SchurDifferentiableOperator<Impl> VdagV(NumOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerNegQuarter);
|
||||
msCG_V(VdagV,tmp,PhiOdd);
|
||||
|
||||
assert(NumOp.ConstEE() == 1);
|
||||
assert(DenOp.ConstEE() == 1);
|
||||
PhiEven = Zero();
|
||||
assert(NumOp.ConstEE() == 1);
|
||||
assert(DenOp.ConstEE() == 1);
|
||||
PhiEven = zero;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual RealD S(const GaugeField &U) {
|
||||
//////////////////////////////////////////////////////
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual RealD S(const GaugeField &U) {
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
FermionField X(NumOp.FermionRedBlackGrid());
|
||||
FermionField Y(NumOp.FermionRedBlackGrid());
|
||||
FermionField X(NumOp.FermionRedBlackGrid());
|
||||
FermionField Y(NumOp.FermionRedBlackGrid());
|
||||
|
||||
// VdagV^1/4 Phi
|
||||
SchurDifferentiableOperator<Impl> VdagV(NumOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter);
|
||||
msCG_V(VdagV,PhiOdd,X);
|
||||
// VdagV^1/4 Phi
|
||||
SchurDifferentiableOperator<Impl> VdagV(NumOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter);
|
||||
msCG_V(VdagV,PhiOdd,X);
|
||||
|
||||
// MdagM^-1/4 VdagV^1/4 Phi
|
||||
SchurDifferentiableOperator<Impl> MdagM(DenOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegQuarter);
|
||||
msCG_M(MdagM,X,Y);
|
||||
// MdagM^-1/4 VdagV^1/4 Phi
|
||||
SchurDifferentiableOperator<Impl> MdagM(DenOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegQuarter);
|
||||
msCG_M(MdagM,X,Y);
|
||||
|
||||
// Phidag VdagV^1/4 MdagM^-1/4 MdagM^-1/4 VdagV^1/4 Phi
|
||||
RealD action = norm2(Y);
|
||||
// Randomly apply rational bounds checks.
|
||||
if ( (rand()%param.BoundsCheckFreq)==0 ) {
|
||||
FermionField gauss(NumOp.FermionRedBlackGrid());
|
||||
gauss = PhiOdd;
|
||||
HighBoundCheck(MdagM,gauss,param.hi);
|
||||
InverseSqrtBoundsCheck(param.MaxIter,param.tolerance*100,MdagM,gauss,PowerNegHalf);
|
||||
}
|
||||
|
||||
return action;
|
||||
};
|
||||
// Phidag VdagV^1/4 MdagM^-1/4 MdagM^-1/4 VdagV^1/4 Phi
|
||||
RealD action = norm2(Y);
|
||||
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// Here, M is some 5D operator and V is the Pauli-Villars field
|
||||
// N and D makeup the rat. poly of the M term and P and & makeup the rat.poly of the denom term
|
||||
//
|
||||
// Need
|
||||
// dS_f/dU = chi^dag d[P/Q] N/D P/Q chi
|
||||
// + chi^dag P/Q d[N/D] P/Q chi
|
||||
// + chi^dag P/Q N/D d[P/Q] chi
|
||||
//
|
||||
// P/Q is expressed as partial fraction expansion:
|
||||
//
|
||||
// a0 + \sum_k ak/(V^dagV + bk)
|
||||
//
|
||||
// d[P/Q] is then
|
||||
//
|
||||
// \sum_k -ak [V^dagV+bk]^{-1} [ dV^dag V + V^dag dV ] [V^dag V + bk]^{-1}
|
||||
//
|
||||
// and similar for N/D.
|
||||
//
|
||||
// Need
|
||||
// MpvPhi_k = [Vdag V + bk]^{-1} chi
|
||||
// MpvPhi = {a0 + \sum_k ak [Vdag V + bk]^{-1} }chi
|
||||
//
|
||||
// MfMpvPhi_k = [MdagM+bk]^{-1} MpvPhi
|
||||
// MfMpvPhi = {a0 + \sum_k ak [Mdag M + bk]^{-1} } MpvPhi
|
||||
//
|
||||
// MpvMfMpvPhi_k = [Vdag V + bk]^{-1} MfMpvchi
|
||||
//
|
||||
return action;
|
||||
};
|
||||
|
||||
virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// Here, M is some 5D operator and V is the Pauli-Villars field
|
||||
// N and D makeup the rat. poly of the M term and P and & makeup the rat.poly of the denom term
|
||||
//
|
||||
// Need
|
||||
// dS_f/dU = chi^dag d[P/Q] N/D P/Q chi
|
||||
// + chi^dag P/Q d[N/D] P/Q chi
|
||||
// + chi^dag P/Q N/D d[P/Q] chi
|
||||
//
|
||||
// P/Q is expressed as partial fraction expansion:
|
||||
//
|
||||
// a0 + \sum_k ak/(V^dagV + bk)
|
||||
//
|
||||
// d[P/Q] is then
|
||||
//
|
||||
// \sum_k -ak [V^dagV+bk]^{-1} [ dV^dag V + V^dag dV ] [V^dag V + bk]^{-1}
|
||||
//
|
||||
// and similar for N/D.
|
||||
//
|
||||
// Need
|
||||
// MpvPhi_k = [Vdag V + bk]^{-1} chi
|
||||
// MpvPhi = {a0 + \sum_k ak [Vdag V + bk]^{-1} }chi
|
||||
//
|
||||
// MfMpvPhi_k = [MdagM+bk]^{-1} MpvPhi
|
||||
// MfMpvPhi = {a0 + \sum_k ak [Mdag M + bk]^{-1} } MpvPhi
|
||||
//
|
||||
// MpvMfMpvPhi_k = [Vdag V + bk]^{-1} MfMpvchi
|
||||
//
|
||||
|
||||
const int n_f = PowerNegHalf.poles.size();
|
||||
const int n_pv = PowerQuarter.poles.size();
|
||||
virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
|
||||
|
||||
std::vector<FermionField> MpvPhi_k (n_pv,NumOp.FermionRedBlackGrid());
|
||||
std::vector<FermionField> MpvMfMpvPhi_k(n_pv,NumOp.FermionRedBlackGrid());
|
||||
std::vector<FermionField> MfMpvPhi_k (n_f ,NumOp.FermionRedBlackGrid());
|
||||
const int n_f = PowerNegHalf.poles.size();
|
||||
const int n_pv = PowerQuarter.poles.size();
|
||||
|
||||
FermionField MpvPhi(NumOp.FermionRedBlackGrid());
|
||||
FermionField MfMpvPhi(NumOp.FermionRedBlackGrid());
|
||||
FermionField MpvMfMpvPhi(NumOp.FermionRedBlackGrid());
|
||||
FermionField Y(NumOp.FermionRedBlackGrid());
|
||||
std::vector<FermionField> MpvPhi_k (n_pv,NumOp.FermionRedBlackGrid());
|
||||
std::vector<FermionField> MpvMfMpvPhi_k(n_pv,NumOp.FermionRedBlackGrid());
|
||||
std::vector<FermionField> MfMpvPhi_k (n_f ,NumOp.FermionRedBlackGrid());
|
||||
|
||||
GaugeField tmp(NumOp.GaugeGrid());
|
||||
FermionField MpvPhi(NumOp.FermionRedBlackGrid());
|
||||
FermionField MfMpvPhi(NumOp.FermionRedBlackGrid());
|
||||
FermionField MpvMfMpvPhi(NumOp.FermionRedBlackGrid());
|
||||
FermionField Y(NumOp.FermionRedBlackGrid());
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
GaugeField tmp(NumOp.GaugeGrid());
|
||||
|
||||
SchurDifferentiableOperator<Impl> VdagV(NumOp);
|
||||
SchurDifferentiableOperator<Impl> MdagM(DenOp);
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegHalf);
|
||||
SchurDifferentiableOperator<Impl> VdagV(NumOp);
|
||||
SchurDifferentiableOperator<Impl> MdagM(DenOp);
|
||||
|
||||
msCG_V(VdagV,PhiOdd,MpvPhi_k,MpvPhi);
|
||||
msCG_M(MdagM,MpvPhi,MfMpvPhi_k,MfMpvPhi);
|
||||
msCG_V(VdagV,MfMpvPhi,MpvMfMpvPhi_k,MpvMfMpvPhi);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegHalf);
|
||||
|
||||
RealD ak;
|
||||
msCG_V(VdagV,PhiOdd,MpvPhi_k,MpvPhi);
|
||||
msCG_M(MdagM,MpvPhi,MfMpvPhi_k,MfMpvPhi);
|
||||
msCG_V(VdagV,MfMpvPhi,MpvMfMpvPhi_k,MpvMfMpvPhi);
|
||||
|
||||
dSdU = Zero();
|
||||
RealD ak;
|
||||
|
||||
// With these building blocks
|
||||
//
|
||||
// dS/dU =
|
||||
// \sum_k -ak MfMpvPhi_k^dag [ dM^dag M + M^dag dM ] MfMpvPhi_k (1)
|
||||
// + \sum_k -ak MpvMfMpvPhi_k^\dag [ dV^dag V + V^dag dV ] MpvPhi_k (2)
|
||||
// -ak MpvPhi_k^dag [ dV^dag V + V^dag dV ] MpvMfMpvPhi_k (3)
|
||||
dSdU = zero;
|
||||
|
||||
//(1)
|
||||
for(int k=0;k<n_f;k++){
|
||||
ak = PowerNegHalf.residues[k];
|
||||
MdagM.Mpc(MfMpvPhi_k[k],Y);
|
||||
MdagM.MpcDagDeriv(tmp , MfMpvPhi_k[k], Y ); dSdU=dSdU+ak*tmp;
|
||||
MdagM.MpcDeriv(tmp , Y, MfMpvPhi_k[k] ); dSdU=dSdU+ak*tmp;
|
||||
}
|
||||
// With these building blocks
|
||||
//
|
||||
// dS/dU =
|
||||
// \sum_k -ak MfMpvPhi_k^dag [ dM^dag M + M^dag dM ] MfMpvPhi_k (1)
|
||||
// + \sum_k -ak MpvMfMpvPhi_k^\dag [ dV^dag V + V^dag dV ] MpvPhi_k (2)
|
||||
// -ak MpvPhi_k^dag [ dV^dag V + V^dag dV ] MpvMfMpvPhi_k (3)
|
||||
|
||||
//(1)
|
||||
for(int k=0;k<n_f;k++){
|
||||
ak = PowerNegHalf.residues[k];
|
||||
MdagM.Mpc(MfMpvPhi_k[k],Y);
|
||||
MdagM.MpcDagDeriv(tmp , MfMpvPhi_k[k], Y ); dSdU=dSdU+ak*tmp;
|
||||
MdagM.MpcDeriv(tmp , Y, MfMpvPhi_k[k] ); dSdU=dSdU+ak*tmp;
|
||||
}
|
||||
|
||||
//(2)
|
||||
//(3)
|
||||
for(int k=0;k<n_pv;k++){
|
||||
//(2)
|
||||
//(3)
|
||||
for(int k=0;k<n_pv;k++){
|
||||
|
||||
ak = PowerQuarter.residues[k];
|
||||
ak = PowerQuarter.residues[k];
|
||||
|
||||
VdagV.Mpc(MpvPhi_k[k],Y);
|
||||
VdagV.MpcDagDeriv(tmp,MpvMfMpvPhi_k[k],Y); dSdU=dSdU+ak*tmp;
|
||||
VdagV.MpcDeriv (tmp,Y,MpvMfMpvPhi_k[k]); dSdU=dSdU+ak*tmp;
|
||||
VdagV.Mpc(MpvPhi_k[k],Y);
|
||||
VdagV.MpcDagDeriv(tmp,MpvMfMpvPhi_k[k],Y); dSdU=dSdU+ak*tmp;
|
||||
VdagV.MpcDeriv (tmp,Y,MpvMfMpvPhi_k[k]); dSdU=dSdU+ak*tmp;
|
||||
|
||||
VdagV.Mpc(MpvMfMpvPhi_k[k],Y); // V as we take Ydag
|
||||
VdagV.MpcDeriv (tmp,Y, MpvPhi_k[k]); dSdU=dSdU+ak*tmp;
|
||||
VdagV.MpcDagDeriv(tmp,MpvPhi_k[k], Y); dSdU=dSdU+ak*tmp;
|
||||
VdagV.Mpc(MpvMfMpvPhi_k[k],Y); // V as we take Ydag
|
||||
VdagV.MpcDeriv (tmp,Y, MpvPhi_k[k]); dSdU=dSdU+ak*tmp;
|
||||
VdagV.MpcDagDeriv(tmp,MpvPhi_k[k], Y); dSdU=dSdU+ak*tmp;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//dSdU = Ta(dSdU);
|
||||
//dSdU = Ta(dSdU);
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*************************************************************************************
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
@ -23,190 +23,199 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef QCD_PSEUDOFERMION_ONE_FLAVOUR_RATIONAL_H
|
||||
#define QCD_PSEUDOFERMION_ONE_FLAVOUR_RATIONAL_H
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
namespace Grid{
|
||||
namespace QCD{
|
||||
|
||||
///////////////////////////////////////
|
||||
// One flavour rational
|
||||
///////////////////////////////////////
|
||||
///////////////////////////////////////
|
||||
// One flavour rational
|
||||
///////////////////////////////////////
|
||||
|
||||
// S_f = chi^dag * N(M^dag*M)/D(M^dag*M) * chi
|
||||
//
|
||||
// Here, M is some operator
|
||||
// N and D makeup the rat. poly
|
||||
//
|
||||
// S_f = chi^dag * N(M^dag*M)/D(M^dag*M) * chi
|
||||
//
|
||||
// Here, M is some operator
|
||||
// N and D makeup the rat. poly
|
||||
//
|
||||
|
||||
template<class Impl>
|
||||
class OneFlavourRationalPseudoFermionAction : public Action<typename Impl::GaugeField> {
|
||||
public:
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
template<class Impl>
|
||||
class OneFlavourRationalPseudoFermionAction : public Action<typename Impl::GaugeField> {
|
||||
public:
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
|
||||
typedef OneFlavourRationalParams Params;
|
||||
Params param;
|
||||
typedef OneFlavourRationalParams Params;
|
||||
Params param;
|
||||
|
||||
MultiShiftFunction PowerHalf ;
|
||||
MultiShiftFunction PowerNegHalf;
|
||||
MultiShiftFunction PowerQuarter;
|
||||
MultiShiftFunction PowerNegQuarter;
|
||||
MultiShiftFunction PowerHalf ;
|
||||
MultiShiftFunction PowerNegHalf;
|
||||
MultiShiftFunction PowerQuarter;
|
||||
MultiShiftFunction PowerNegQuarter;
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
FermionOperator<Impl> & FermOp;// the basic operator
|
||||
FermionOperator<Impl> & FermOp;// the basic operator
|
||||
|
||||
// NOT using "Nroots"; IroIro is -- perhaps later, but this wasn't good for us historically
|
||||
// and hasenbusch works better
|
||||
// NOT using "Nroots"; IroIro is -- perhaps later, but this wasn't good for us historically
|
||||
// and hasenbusch works better
|
||||
|
||||
FermionField Phi; // the pseudo fermion field for this trajectory
|
||||
FermionField Phi; // the pseudo fermion field for this trajectory
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
OneFlavourRationalPseudoFermionAction(FermionOperator<Impl> &Op,
|
||||
Params & p
|
||||
) : FermOp(Op), Phi(Op.FermionGrid()), param(p)
|
||||
{
|
||||
AlgRemez remez(param.lo,param.hi,param.precision);
|
||||
OneFlavourRationalPseudoFermionAction(FermionOperator<Impl> &Op,
|
||||
Params & p
|
||||
) : FermOp(Op), Phi(Op.FermionGrid()), param(p)
|
||||
{
|
||||
AlgRemez remez(param.lo,param.hi,param.precision);
|
||||
|
||||
// MdagM^(+- 1/2)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,2);
|
||||
PowerHalf.Init(remez,param.tolerance,false);
|
||||
PowerNegHalf.Init(remez,param.tolerance,true);
|
||||
// MdagM^(+- 1/2)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,2);
|
||||
PowerHalf.Init(remez,param.tolerance,false);
|
||||
PowerNegHalf.Init(remez,param.tolerance,true);
|
||||
|
||||
// MdagM^(+- 1/4)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/4)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,4);
|
||||
PowerQuarter.Init(remez,param.tolerance,false);
|
||||
PowerNegQuarter.Init(remez,param.tolerance,true);
|
||||
};
|
||||
// MdagM^(+- 1/4)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/4)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,4);
|
||||
PowerQuarter.Init(remez,param.tolerance,false);
|
||||
PowerNegQuarter.Init(remez,param.tolerance,true);
|
||||
};
|
||||
|
||||
virtual std::string action_name(){return "OneFlavourRationalPseudoFermionAction";}
|
||||
virtual std::string action_name(){return "OneFlavourRationalPseudoFermionAction";}
|
||||
|
||||
virtual std::string LogParameters(){
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Low :" << param.lo << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] High :" << param.hi << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Tolerance :" << param.tolerance << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Degree :" << param.degree << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Precision :" << param.precision << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
virtual std::string LogParameters(){
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Low :" << param.lo << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] High :" << param.hi << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Tolerance :" << param.tolerance << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Degree :" << param.degree << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Precision :" << param.precision << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) {
|
||||
virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) {
|
||||
|
||||
|
||||
// P(phi) = e^{- phi^dag (MdagM)^-1/2 phi}
|
||||
// = e^{- phi^dag (MdagM)^-1/4 (MdagM)^-1/4 phi}
|
||||
// Phi = Mdag^{1/4} eta
|
||||
// P(eta) = e^{- eta^dag eta}
|
||||
//
|
||||
// e^{x^2/2 sig^2} => sig^2 = 0.5.
|
||||
//
|
||||
// So eta should be of width sig = 1/sqrt(2).
|
||||
// P(phi) = e^{- phi^dag (MdagM)^-1/2 phi}
|
||||
// = e^{- phi^dag (MdagM)^-1/4 (MdagM)^-1/4 phi}
|
||||
// Phi = Mdag^{1/4} eta
|
||||
// P(eta) = e^{- eta^dag eta}
|
||||
//
|
||||
// e^{x^2/2 sig^2} => sig^2 = 0.5.
|
||||
//
|
||||
// So eta should be of width sig = 1/sqrt(2).
|
||||
|
||||
RealD scale = std::sqrt(0.5);
|
||||
RealD scale = std::sqrt(0.5);
|
||||
|
||||
FermionField eta(FermOp.FermionGrid());
|
||||
FermionField eta(FermOp.FermionGrid());
|
||||
|
||||
gaussian(pRNG,eta);
|
||||
gaussian(pRNG,eta);
|
||||
|
||||
FermOp.ImportGauge(U);
|
||||
FermOp.ImportGauge(U);
|
||||
|
||||
// mutishift CG
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagMOp(FermOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG(param.MaxIter,PowerQuarter);
|
||||
msCG(MdagMOp,eta,Phi);
|
||||
// mutishift CG
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagMOp(FermOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG(param.MaxIter,PowerQuarter);
|
||||
msCG(MdagMOp,eta,Phi);
|
||||
|
||||
Phi=Phi*scale;
|
||||
Phi=Phi*scale;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// S = phi^dag (Mdag M)^-1/2 phi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual RealD S(const GaugeField &U) {
|
||||
//////////////////////////////////////////////////////
|
||||
// S = phi^dag (Mdag M)^-1/2 phi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual RealD S(const GaugeField &U) {
|
||||
|
||||
FermOp.ImportGauge(U);
|
||||
FermOp.ImportGauge(U);
|
||||
|
||||
FermionField Y(FermOp.FermionGrid());
|
||||
FermionField Y(FermOp.FermionGrid());
|
||||
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagMOp(FermOp);
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagMOp(FermOp);
|
||||
|
||||
ConjugateGradientMultiShift<FermionField> msCG(param.MaxIter,PowerNegQuarter);
|
||||
ConjugateGradientMultiShift<FermionField> msCG(param.MaxIter,PowerNegQuarter);
|
||||
|
||||
msCG(MdagMOp,Phi,Y);
|
||||
msCG(MdagMOp,Phi,Y);
|
||||
|
||||
RealD action = norm2(Y);
|
||||
std::cout << GridLogMessage << "Pseudofermion action FIXME -- is -1/4 solve or -1/2 solve faster??? "<<action<<std::endl;
|
||||
return action;
|
||||
};
|
||||
if ( (rand()%param.BoundsCheckFreq)==0 ) {
|
||||
FermionField gauss(FermOp.FermionGrid());
|
||||
gauss = Phi;
|
||||
HighBoundCheck(MdagMOp,gauss,param.hi);
|
||||
InverseSqrtBoundsCheck(param.MaxIter,param.tolerance*100,MdagMOp,gauss,PowerNegHalf);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Need
|
||||
// dS_f/dU = chi^dag d[N/D] chi
|
||||
//
|
||||
// N/D is expressed as partial fraction expansion:
|
||||
//
|
||||
// a0 + \sum_k ak/(M^dagM + bk)
|
||||
//
|
||||
// d[N/D] is then
|
||||
//
|
||||
// \sum_k -ak [M^dagM+bk]^{-1} [ dM^dag M + M^dag dM ] [M^dag M + bk]^{-1}
|
||||
//
|
||||
// Need
|
||||
// Mf Phi_k = [MdagM+bk]^{-1} Phi
|
||||
// Mf Phi = \sum_k ak [MdagM+bk]^{-1} Phi
|
||||
//
|
||||
// With these building blocks
|
||||
//
|
||||
// dS/dU = \sum_k -ak Mf Phi_k^dag [ dM^dag M + M^dag dM ] Mf Phi_k
|
||||
// S = innerprodReal(Phi,Mf Phi);
|
||||
//////////////////////////////////////////////////////
|
||||
virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
|
||||
|
||||
const int Npole = PowerNegHalf.poles.size();
|
||||
RealD action = norm2(Y);
|
||||
std::cout << GridLogMessage << "Pseudofermion action FIXME -- is -1/4 solve or -1/2 solve faster??? "<<action<<std::endl;
|
||||
return action;
|
||||
};
|
||||
|
||||
std::vector<FermionField> MPhi_k (Npole,FermOp.FermionGrid());
|
||||
//////////////////////////////////////////////////////
|
||||
// Need
|
||||
// dS_f/dU = chi^dag d[N/D] chi
|
||||
//
|
||||
// N/D is expressed as partial fraction expansion:
|
||||
//
|
||||
// a0 + \sum_k ak/(M^dagM + bk)
|
||||
//
|
||||
// d[N/D] is then
|
||||
//
|
||||
// \sum_k -ak [M^dagM+bk]^{-1} [ dM^dag M + M^dag dM ] [M^dag M + bk]^{-1}
|
||||
//
|
||||
// Need
|
||||
// Mf Phi_k = [MdagM+bk]^{-1} Phi
|
||||
// Mf Phi = \sum_k ak [MdagM+bk]^{-1} Phi
|
||||
//
|
||||
// With these building blocks
|
||||
//
|
||||
// dS/dU = \sum_k -ak Mf Phi_k^dag [ dM^dag M + M^dag dM ] Mf Phi_k
|
||||
// S = innerprodReal(Phi,Mf Phi);
|
||||
//////////////////////////////////////////////////////
|
||||
virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
|
||||
|
||||
FermionField X(FermOp.FermionGrid());
|
||||
FermionField Y(FermOp.FermionGrid());
|
||||
const int Npole = PowerNegHalf.poles.size();
|
||||
|
||||
GaugeField tmp(FermOp.GaugeGrid());
|
||||
std::vector<FermionField> MPhi_k (Npole,FermOp.FermionGrid());
|
||||
|
||||
FermOp.ImportGauge(U);
|
||||
FermionField X(FermOp.FermionGrid());
|
||||
FermionField Y(FermOp.FermionGrid());
|
||||
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagMOp(FermOp);
|
||||
GaugeField tmp(FermOp.GaugeGrid());
|
||||
|
||||
ConjugateGradientMultiShift<FermionField> msCG(param.MaxIter,PowerNegHalf);
|
||||
FermOp.ImportGauge(U);
|
||||
|
||||
msCG(MdagMOp,Phi,MPhi_k);
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagMOp(FermOp);
|
||||
|
||||
dSdU = Zero();
|
||||
for(int k=0;k<Npole;k++){
|
||||
ConjugateGradientMultiShift<FermionField> msCG(param.MaxIter,PowerNegHalf);
|
||||
|
||||
RealD ak = PowerNegHalf.residues[k];
|
||||
msCG(MdagMOp,Phi,MPhi_k);
|
||||
|
||||
X = MPhi_k[k];
|
||||
dSdU = zero;
|
||||
for(int k=0;k<Npole;k++){
|
||||
|
||||
FermOp.M(X,Y);
|
||||
RealD ak = PowerNegHalf.residues[k];
|
||||
|
||||
FermOp.MDeriv(tmp , Y, X,DaggerNo ); dSdU=dSdU+ak*tmp;
|
||||
FermOp.MDeriv(tmp , X, Y,DaggerYes); dSdU=dSdU+ak*tmp;
|
||||
X = MPhi_k[k];
|
||||
|
||||
}
|
||||
FermOp.M(X,Y);
|
||||
|
||||
//dSdU = Ta(dSdU);
|
||||
FermOp.MDeriv(tmp , Y, X,DaggerNo ); dSdU=dSdU+ak*tmp;
|
||||
FermOp.MDeriv(tmp , X, Y,DaggerYes); dSdU=dSdU+ak*tmp;
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
//dSdU = Ta(dSdU);
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*************************************************************************************
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
@ -23,243 +23,253 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef QCD_PSEUDOFERMION_ONE_FLAVOUR_RATIONAL_RATIO_H
|
||||
#define QCD_PSEUDOFERMION_ONE_FLAVOUR_RATIONAL_RATIO_H
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
///////////////////////////////////////
|
||||
// One flavour rational
|
||||
///////////////////////////////////////
|
||||
namespace Grid{
|
||||
namespace QCD{
|
||||
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// Here P/Q \sim R_{1/4} ~ (V^dagV)^{1/4}
|
||||
// Here N/D \sim R_{-1/2} ~ (M^dagM)^{-1/2}
|
||||
|
||||
template<class Impl>
|
||||
class OneFlavourRatioRationalPseudoFermionAction : public Action<typename Impl::GaugeField> {
|
||||
public:
|
||||
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
|
||||
typedef OneFlavourRationalParams Params;
|
||||
Params param;
|
||||
|
||||
MultiShiftFunction PowerHalf ;
|
||||
MultiShiftFunction PowerNegHalf;
|
||||
MultiShiftFunction PowerQuarter;
|
||||
MultiShiftFunction PowerNegQuarter;
|
||||
|
||||
private:
|
||||
|
||||
FermionOperator<Impl> & NumOp;// the basic operator
|
||||
FermionOperator<Impl> & DenOp;// the basic operator
|
||||
FermionField Phi; // the pseudo fermion field for this trajectory
|
||||
|
||||
public:
|
||||
|
||||
OneFlavourRatioRationalPseudoFermionAction(FermionOperator<Impl> &_NumOp,
|
||||
FermionOperator<Impl> &_DenOp,
|
||||
Params & p
|
||||
) : NumOp(_NumOp), DenOp(_DenOp), Phi(_NumOp.FermionGrid()), param(p)
|
||||
{
|
||||
AlgRemez remez(param.lo,param.hi,param.precision);
|
||||
|
||||
// MdagM^(+- 1/2)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,2);
|
||||
PowerHalf.Init(remez,param.tolerance,false);
|
||||
PowerNegHalf.Init(remez,param.tolerance,true);
|
||||
|
||||
// MdagM^(+- 1/4)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/4)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,4);
|
||||
PowerQuarter.Init(remez,param.tolerance,false);
|
||||
PowerNegQuarter.Init(remez,param.tolerance,true);
|
||||
};
|
||||
|
||||
virtual std::string action_name(){return "OneFlavourRatioRationalPseudoFermionAction";}
|
||||
|
||||
virtual std::string LogParameters(){
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Low :" << param.lo << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] High :" << param.hi << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Tolerance :" << param.tolerance << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Degree :" << param.degree << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Precision :" << param.precision << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
|
||||
virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) {
|
||||
///////////////////////////////////////
|
||||
// One flavour rational
|
||||
///////////////////////////////////////
|
||||
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// P(phi) = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/2 (VdagV)^1/4 phi}
|
||||
// = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/4 (MdagM)^-1/4 (VdagV)^1/4 phi}
|
||||
//
|
||||
// Phi = (VdagV)^-1/4 Mdag^{1/4} eta
|
||||
//
|
||||
// P(eta) = e^{- eta^dag eta}
|
||||
//
|
||||
// e^{x^2/2 sig^2} => sig^2 = 0.5.
|
||||
//
|
||||
// So eta should be of width sig = 1/sqrt(2).
|
||||
// Here P/Q \sim R_{1/4} ~ (V^dagV)^{1/4}
|
||||
// Here N/D \sim R_{-1/2} ~ (M^dagM)^{-1/2}
|
||||
|
||||
template<class Impl>
|
||||
class OneFlavourRatioRationalPseudoFermionAction : public Action<typename Impl::GaugeField> {
|
||||
public:
|
||||
|
||||
RealD scale = std::sqrt(0.5);
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
|
||||
FermionField tmp(NumOp.FermionGrid());
|
||||
FermionField eta(NumOp.FermionGrid());
|
||||
typedef OneFlavourRationalParams Params;
|
||||
Params param;
|
||||
|
||||
gaussian(pRNG,eta);
|
||||
MultiShiftFunction PowerHalf ;
|
||||
MultiShiftFunction PowerNegHalf;
|
||||
MultiShiftFunction PowerQuarter;
|
||||
MultiShiftFunction PowerNegQuarter;
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
private:
|
||||
|
||||
FermionOperator<Impl> & NumOp;// the basic operator
|
||||
FermionOperator<Impl> & DenOp;// the basic operator
|
||||
FermionField Phi; // the pseudo fermion field for this trajectory
|
||||
|
||||
// MdagM^1/4 eta
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagM(DenOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerQuarter);
|
||||
msCG_M(MdagM,eta,tmp);
|
||||
public:
|
||||
|
||||
// VdagV^-1/4 MdagM^1/4 eta
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> VdagV(NumOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerNegQuarter);
|
||||
msCG_V(VdagV,tmp,Phi);
|
||||
OneFlavourRatioRationalPseudoFermionAction(FermionOperator<Impl> &_NumOp,
|
||||
FermionOperator<Impl> &_DenOp,
|
||||
Params & p
|
||||
) : NumOp(_NumOp), DenOp(_DenOp), Phi(_NumOp.FermionGrid()), param(p)
|
||||
{
|
||||
AlgRemez remez(param.lo,param.hi,param.precision);
|
||||
|
||||
Phi=Phi*scale;
|
||||
// MdagM^(+- 1/2)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,2);
|
||||
PowerHalf.Init(remez,param.tolerance,false);
|
||||
PowerNegHalf.Init(remez,param.tolerance,true);
|
||||
|
||||
// MdagM^(+- 1/4)
|
||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/4)"<<std::endl;
|
||||
remez.generateApprox(param.degree,1,4);
|
||||
PowerQuarter.Init(remez,param.tolerance,false);
|
||||
PowerNegQuarter.Init(remez,param.tolerance,true);
|
||||
};
|
||||
|
||||
virtual std::string action_name(){return "OneFlavourRatioRationalPseudoFermionAction";}
|
||||
|
||||
virtual std::string LogParameters(){
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Low :" << param.lo << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] High :" << param.hi << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Tolerance :" << param.tolerance << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Degree :" << param.degree << std::endl;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] Precision :" << param.precision << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
|
||||
virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) {
|
||||
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// P(phi) = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/2 (VdagV)^1/4 phi}
|
||||
// = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/4 (MdagM)^-1/4 (VdagV)^1/4 phi}
|
||||
//
|
||||
// Phi = (VdagV)^-1/4 Mdag^{1/4} eta
|
||||
//
|
||||
// P(eta) = e^{- eta^dag eta}
|
||||
//
|
||||
// e^{x^2/2 sig^2} => sig^2 = 0.5.
|
||||
//
|
||||
// So eta should be of width sig = 1/sqrt(2).
|
||||
|
||||
RealD scale = std::sqrt(0.5);
|
||||
|
||||
FermionField tmp(NumOp.FermionGrid());
|
||||
FermionField eta(NumOp.FermionGrid());
|
||||
|
||||
gaussian(pRNG,eta);
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
// MdagM^1/4 eta
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagM(DenOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerQuarter);
|
||||
msCG_M(MdagM,eta,tmp);
|
||||
|
||||
// VdagV^-1/4 MdagM^1/4 eta
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> VdagV(NumOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerNegQuarter);
|
||||
msCG_V(VdagV,tmp,Phi);
|
||||
|
||||
Phi=Phi*scale;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual RealD S(const GaugeField &U) {
|
||||
//////////////////////////////////////////////////////
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual RealD S(const GaugeField &U) {
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
FermionField X(NumOp.FermionGrid());
|
||||
FermionField Y(NumOp.FermionGrid());
|
||||
FermionField X(NumOp.FermionGrid());
|
||||
FermionField Y(NumOp.FermionGrid());
|
||||
|
||||
// VdagV^1/4 Phi
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> VdagV(NumOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter);
|
||||
msCG_V(VdagV,Phi,X);
|
||||
// VdagV^1/4 Phi
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> VdagV(NumOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter);
|
||||
msCG_V(VdagV,Phi,X);
|
||||
|
||||
// MdagM^-1/4 VdagV^1/4 Phi
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagM(DenOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegQuarter);
|
||||
msCG_M(MdagM,X,Y);
|
||||
// MdagM^-1/4 VdagV^1/4 Phi
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagM(DenOp);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegQuarter);
|
||||
msCG_M(MdagM,X,Y);
|
||||
|
||||
// Phidag VdagV^1/4 MdagM^-1/4 MdagM^-1/4 VdagV^1/4 Phi
|
||||
RealD action = norm2(Y);
|
||||
// Randomly apply rational bounds checks.
|
||||
if ( (rand()%param.BoundsCheckFreq)==0 ) {
|
||||
FermionField gauss(NumOp.FermionGrid());
|
||||
gauss = Phi;
|
||||
HighBoundCheck(MdagM,gauss,param.hi);
|
||||
InverseSqrtBoundsCheck(param.MaxIter,param.tolerance*100,MdagM,gauss,PowerNegHalf);
|
||||
}
|
||||
|
||||
return action;
|
||||
};
|
||||
// Phidag VdagV^1/4 MdagM^-1/4 MdagM^-1/4 VdagV^1/4 Phi
|
||||
RealD action = norm2(Y);
|
||||
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// Here, M is some 5D operator and V is the Pauli-Villars field
|
||||
// N and D makeup the rat. poly of the M term and P and & makeup the rat.poly of the denom term
|
||||
//
|
||||
// Need
|
||||
// dS_f/dU = chi^dag d[P/Q] N/D P/Q chi
|
||||
// + chi^dag P/Q d[N/D] P/Q chi
|
||||
// + chi^dag P/Q N/D d[P/Q] chi
|
||||
//
|
||||
// P/Q is expressed as partial fraction expansion:
|
||||
//
|
||||
// a0 + \sum_k ak/(V^dagV + bk)
|
||||
//
|
||||
// d[P/Q] is then
|
||||
//
|
||||
// \sum_k -ak [V^dagV+bk]^{-1} [ dV^dag V + V^dag dV ] [V^dag V + bk]^{-1}
|
||||
//
|
||||
// and similar for N/D.
|
||||
//
|
||||
// Need
|
||||
// MpvPhi_k = [Vdag V + bk]^{-1} chi
|
||||
// MpvPhi = {a0 + \sum_k ak [Vdag V + bk]^{-1} }chi
|
||||
//
|
||||
// MfMpvPhi_k = [MdagM+bk]^{-1} MpvPhi
|
||||
// MfMpvPhi = {a0 + \sum_k ak [Mdag M + bk]^{-1} } MpvPhi
|
||||
//
|
||||
// MpvMfMpvPhi_k = [Vdag V + bk]^{-1} MfMpvchi
|
||||
//
|
||||
return action;
|
||||
};
|
||||
|
||||
virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
|
||||
// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
|
||||
//
|
||||
// Here, M is some 5D operator and V is the Pauli-Villars field
|
||||
// N and D makeup the rat. poly of the M term and P and & makeup the rat.poly of the denom term
|
||||
//
|
||||
// Need
|
||||
// dS_f/dU = chi^dag d[P/Q] N/D P/Q chi
|
||||
// + chi^dag P/Q d[N/D] P/Q chi
|
||||
// + chi^dag P/Q N/D d[P/Q] chi
|
||||
//
|
||||
// P/Q is expressed as partial fraction expansion:
|
||||
//
|
||||
// a0 + \sum_k ak/(V^dagV + bk)
|
||||
//
|
||||
// d[P/Q] is then
|
||||
//
|
||||
// \sum_k -ak [V^dagV+bk]^{-1} [ dV^dag V + V^dag dV ] [V^dag V + bk]^{-1}
|
||||
//
|
||||
// and similar for N/D.
|
||||
//
|
||||
// Need
|
||||
// MpvPhi_k = [Vdag V + bk]^{-1} chi
|
||||
// MpvPhi = {a0 + \sum_k ak [Vdag V + bk]^{-1} }chi
|
||||
//
|
||||
// MfMpvPhi_k = [MdagM+bk]^{-1} MpvPhi
|
||||
// MfMpvPhi = {a0 + \sum_k ak [Mdag M + bk]^{-1} } MpvPhi
|
||||
//
|
||||
// MpvMfMpvPhi_k = [Vdag V + bk]^{-1} MfMpvchi
|
||||
//
|
||||
|
||||
const int n_f = PowerNegHalf.poles.size();
|
||||
const int n_pv = PowerQuarter.poles.size();
|
||||
virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
|
||||
|
||||
std::vector<FermionField> MpvPhi_k (n_pv,NumOp.FermionGrid());
|
||||
std::vector<FermionField> MpvMfMpvPhi_k(n_pv,NumOp.FermionGrid());
|
||||
std::vector<FermionField> MfMpvPhi_k (n_f,NumOp.FermionGrid());
|
||||
const int n_f = PowerNegHalf.poles.size();
|
||||
const int n_pv = PowerQuarter.poles.size();
|
||||
|
||||
FermionField MpvPhi(NumOp.FermionGrid());
|
||||
FermionField MfMpvPhi(NumOp.FermionGrid());
|
||||
FermionField MpvMfMpvPhi(NumOp.FermionGrid());
|
||||
FermionField Y(NumOp.FermionGrid());
|
||||
std::vector<FermionField> MpvPhi_k (n_pv,NumOp.FermionGrid());
|
||||
std::vector<FermionField> MpvMfMpvPhi_k(n_pv,NumOp.FermionGrid());
|
||||
std::vector<FermionField> MfMpvPhi_k (n_f,NumOp.FermionGrid());
|
||||
|
||||
GaugeField tmp(NumOp.GaugeGrid());
|
||||
FermionField MpvPhi(NumOp.FermionGrid());
|
||||
FermionField MfMpvPhi(NumOp.FermionGrid());
|
||||
FermionField MpvMfMpvPhi(NumOp.FermionGrid());
|
||||
FermionField Y(NumOp.FermionGrid());
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
GaugeField tmp(NumOp.GaugeGrid());
|
||||
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagM(DenOp);
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> VdagV(NumOp);
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegHalf);
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> MdagM(DenOp);
|
||||
MdagMLinearOperator<FermionOperator<Impl> ,FermionField> VdagV(NumOp);
|
||||
|
||||
msCG_V(VdagV,Phi,MpvPhi_k,MpvPhi);
|
||||
msCG_M(MdagM,MpvPhi,MfMpvPhi_k,MfMpvPhi);
|
||||
msCG_V(VdagV,MfMpvPhi,MpvMfMpvPhi_k,MpvMfMpvPhi);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter);
|
||||
ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegHalf);
|
||||
|
||||
RealD ak;
|
||||
msCG_V(VdagV,Phi,MpvPhi_k,MpvPhi);
|
||||
msCG_M(MdagM,MpvPhi,MfMpvPhi_k,MfMpvPhi);
|
||||
msCG_V(VdagV,MfMpvPhi,MpvMfMpvPhi_k,MpvMfMpvPhi);
|
||||
|
||||
dSdU = Zero();
|
||||
RealD ak;
|
||||
|
||||
// With these building blocks
|
||||
//
|
||||
// dS/dU =
|
||||
// \sum_k -ak MfMpvPhi_k^dag [ dM^dag M + M^dag dM ] MfMpvPhi_k (1)
|
||||
// + \sum_k -ak MpvMfMpvPhi_k^\dag [ dV^dag V + V^dag dV ] MpvPhi_k (2)
|
||||
// -ak MpvPhi_k^dag [ dV^dag V + V^dag dV ] MpvMfMpvPhi_k (3)
|
||||
dSdU = zero;
|
||||
|
||||
//(1)
|
||||
for(int k=0;k<n_f;k++){
|
||||
ak = PowerNegHalf.residues[k];
|
||||
DenOp.M(MfMpvPhi_k[k],Y);
|
||||
DenOp.MDeriv(tmp , MfMpvPhi_k[k], Y,DaggerYes ); dSdU=dSdU+ak*tmp;
|
||||
DenOp.MDeriv(tmp , Y, MfMpvPhi_k[k], DaggerNo ); dSdU=dSdU+ak*tmp;
|
||||
}
|
||||
// With these building blocks
|
||||
//
|
||||
// dS/dU =
|
||||
// \sum_k -ak MfMpvPhi_k^dag [ dM^dag M + M^dag dM ] MfMpvPhi_k (1)
|
||||
// + \sum_k -ak MpvMfMpvPhi_k^\dag [ dV^dag V + V^dag dV ] MpvPhi_k (2)
|
||||
// -ak MpvPhi_k^dag [ dV^dag V + V^dag dV ] MpvMfMpvPhi_k (3)
|
||||
|
||||
//(1)
|
||||
for(int k=0;k<n_f;k++){
|
||||
ak = PowerNegHalf.residues[k];
|
||||
DenOp.M(MfMpvPhi_k[k],Y);
|
||||
DenOp.MDeriv(tmp , MfMpvPhi_k[k], Y,DaggerYes ); dSdU=dSdU+ak*tmp;
|
||||
DenOp.MDeriv(tmp , Y, MfMpvPhi_k[k], DaggerNo ); dSdU=dSdU+ak*tmp;
|
||||
}
|
||||
|
||||
//(2)
|
||||
//(3)
|
||||
for(int k=0;k<n_pv;k++){
|
||||
//(2)
|
||||
//(3)
|
||||
for(int k=0;k<n_pv;k++){
|
||||
|
||||
ak = PowerQuarter.residues[k];
|
||||
ak = PowerQuarter.residues[k];
|
||||
|
||||
NumOp.M(MpvPhi_k[k],Y);
|
||||
NumOp.MDeriv(tmp,MpvMfMpvPhi_k[k],Y,DaggerYes); dSdU=dSdU+ak*tmp;
|
||||
NumOp.MDeriv(tmp,Y,MpvMfMpvPhi_k[k],DaggerNo); dSdU=dSdU+ak*tmp;
|
||||
NumOp.M(MpvPhi_k[k],Y);
|
||||
NumOp.MDeriv(tmp,MpvMfMpvPhi_k[k],Y,DaggerYes); dSdU=dSdU+ak*tmp;
|
||||
NumOp.MDeriv(tmp,Y,MpvMfMpvPhi_k[k],DaggerNo); dSdU=dSdU+ak*tmp;
|
||||
|
||||
NumOp.M(MpvMfMpvPhi_k[k],Y); // V as we take Ydag
|
||||
NumOp.MDeriv(tmp,Y, MpvPhi_k[k], DaggerNo); dSdU=dSdU+ak*tmp;
|
||||
NumOp.MDeriv(tmp,MpvPhi_k[k], Y,DaggerYes); dSdU=dSdU+ak*tmp;
|
||||
NumOp.M(MpvMfMpvPhi_k[k],Y); // V as we take Ydag
|
||||
NumOp.MDeriv(tmp,Y, MpvPhi_k[k], DaggerNo); dSdU=dSdU+ak*tmp;
|
||||
NumOp.MDeriv(tmp,MpvPhi_k[k], Y,DaggerYes); dSdU=dSdU+ak*tmp;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//dSdU = Ta(dSdU);
|
||||
//dSdU = Ta(dSdU);
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,9 @@ directory
|
||||
#ifndef QCD_PSEUDOFERMION_AGGREGATE_H
|
||||
#define QCD_PSEUDOFERMION_AGGREGATE_H
|
||||
|
||||
// Rational functions
|
||||
#include <Grid/qcd/action/pseudofermion/Bounds.h>
|
||||
|
||||
#include <Grid/qcd/action/pseudofermion/EvenOddSchurDifferentiable.h>
|
||||
#include <Grid/qcd/action/pseudofermion/TwoFlavour.h>
|
||||
#include <Grid/qcd/action/pseudofermion/TwoFlavourRatio.h>
|
||||
|
@ -84,21 +84,20 @@ public:
|
||||
// and must multiply by 0.707....
|
||||
//
|
||||
// Chroma has this scale factor: two_flavor_monomial_w.h
|
||||
// CPS uses this factor
|
||||
// IroIro: does not use this scale. It is absorbed by a change of vars
|
||||
// in the Phi integral, and thus is only an irrelevant prefactor for
|
||||
// the partition function.
|
||||
//
|
||||
|
||||
RealD scale = std::sqrt(0.5);
|
||||
const RealD scale = std::sqrt(0.5);
|
||||
|
||||
FermionField eta(FermOp.FermionGrid());
|
||||
|
||||
gaussian(pRNG, eta);
|
||||
gaussian(pRNG, eta); eta = scale *eta;
|
||||
|
||||
FermOp.ImportGauge(U);
|
||||
FermOp.Mdag(eta, Phi);
|
||||
|
||||
Phi = Phi * scale;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*************************************************************************************
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
@ -24,186 +24,194 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef QCD_PSEUDOFERMION_TWO_FLAVOUR_EVEN_ODD_RATIO_H
|
||||
#define QCD_PSEUDOFERMION_TWO_FLAVOUR_EVEN_ODD_RATIO_H
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
namespace Grid{
|
||||
namespace QCD{
|
||||
|
||||
///////////////////////////////////////
|
||||
// Two flavour ratio
|
||||
///////////////////////////////////////
|
||||
template<class Impl>
|
||||
class TwoFlavourEvenOddRatioPseudoFermionAction : public Action<typename Impl::GaugeField> {
|
||||
public:
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
///////////////////////////////////////
|
||||
// Two flavour ratio
|
||||
///////////////////////////////////////
|
||||
template<class Impl>
|
||||
class TwoFlavourEvenOddRatioPseudoFermionAction : public Action<typename Impl::GaugeField> {
|
||||
public:
|
||||
INHERIT_IMPL_TYPES(Impl);
|
||||
|
||||
private:
|
||||
FermionOperator<Impl> & NumOp;// the basic operator
|
||||
FermionOperator<Impl> & DenOp;// the basic operator
|
||||
private:
|
||||
FermionOperator<Impl> & NumOp;// the basic operator
|
||||
FermionOperator<Impl> & DenOp;// the basic operator
|
||||
|
||||
OperatorFunction<FermionField> &DerivativeSolver;
|
||||
OperatorFunction<FermionField> &ActionSolver;
|
||||
OperatorFunction<FermionField> &DerivativeSolver;
|
||||
OperatorFunction<FermionField> &ActionSolver;
|
||||
OperatorFunction<FermionField> &HeatbathSolver;
|
||||
|
||||
FermionField PhiOdd; // the pseudo fermion field for this trajectory
|
||||
FermionField PhiEven; // the pseudo fermion field for this trajectory
|
||||
FermionField PhiOdd; // the pseudo fermion field for this trajectory
|
||||
FermionField PhiEven; // the pseudo fermion field for this trajectory
|
||||
|
||||
public:
|
||||
TwoFlavourEvenOddRatioPseudoFermionAction(FermionOperator<Impl> &_NumOp,
|
||||
FermionOperator<Impl> &_DenOp,
|
||||
OperatorFunction<FermionField> & DS,
|
||||
OperatorFunction<FermionField> & AS) :
|
||||
NumOp(_NumOp),
|
||||
DenOp(_DenOp),
|
||||
DerivativeSolver(DS),
|
||||
ActionSolver(AS),
|
||||
PhiEven(_NumOp.FermionRedBlackGrid()),
|
||||
PhiOdd(_NumOp.FermionRedBlackGrid())
|
||||
{
|
||||
conformable(_NumOp.FermionGrid(), _DenOp.FermionGrid());
|
||||
conformable(_NumOp.FermionRedBlackGrid(), _DenOp.FermionRedBlackGrid());
|
||||
conformable(_NumOp.GaugeGrid(), _DenOp.GaugeGrid());
|
||||
conformable(_NumOp.GaugeRedBlackGrid(), _DenOp.GaugeRedBlackGrid());
|
||||
};
|
||||
public:
|
||||
TwoFlavourEvenOddRatioPseudoFermionAction(FermionOperator<Impl> &_NumOp,
|
||||
FermionOperator<Impl> &_DenOp,
|
||||
OperatorFunction<FermionField> & DS,
|
||||
OperatorFunction<FermionField> & AS ) :
|
||||
TwoFlavourEvenOddRatioPseudoFermionAction(_NumOp,_DenOp, DS,AS,AS) {};
|
||||
|
||||
virtual std::string action_name(){return "TwoFlavourEvenOddRatioPseudoFermionAction";}
|
||||
TwoFlavourEvenOddRatioPseudoFermionAction(FermionOperator<Impl> &_NumOp,
|
||||
FermionOperator<Impl> &_DenOp,
|
||||
OperatorFunction<FermionField> & DS,
|
||||
OperatorFunction<FermionField> & AS, OperatorFunction<FermionField> & HS) :
|
||||
NumOp(_NumOp),
|
||||
DenOp(_DenOp),
|
||||
DerivativeSolver(DS),
|
||||
ActionSolver(AS),
|
||||
HeatbathSolver(HS),
|
||||
PhiEven(_NumOp.FermionRedBlackGrid()),
|
||||
PhiOdd(_NumOp.FermionRedBlackGrid())
|
||||
{
|
||||
conformable(_NumOp.FermionGrid(), _DenOp.FermionGrid());
|
||||
conformable(_NumOp.FermionRedBlackGrid(), _DenOp.FermionRedBlackGrid());
|
||||
conformable(_NumOp.GaugeGrid(), _DenOp.GaugeGrid());
|
||||
conformable(_NumOp.GaugeRedBlackGrid(), _DenOp.GaugeRedBlackGrid());
|
||||
};
|
||||
|
||||
virtual std::string LogParameters(){
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] has no parameters" << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
virtual std::string action_name(){return "TwoFlavourEvenOddRatioPseudoFermionAction";}
|
||||
|
||||
virtual std::string LogParameters(){
|
||||
std::stringstream sstream;
|
||||
sstream << GridLogMessage << "["<<action_name()<<"] has no parameters" << std::endl;
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
|
||||
virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) {
|
||||
virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) {
|
||||
|
||||
// P(phi) = e^{- phi^dag Vpc (MpcdagMpc)^-1 Vpcdag phi}
|
||||
//
|
||||
// NumOp == V
|
||||
// DenOp == M
|
||||
//
|
||||
// Take phi_o = Vpcdag^{-1} Mpcdag eta_o ; eta_o = Mpcdag^{-1} Vpcdag Phi
|
||||
//
|
||||
// P(eta_o) = e^{- eta_o^dag eta_o}
|
||||
//
|
||||
// e^{x^2/2 sig^2} => sig^2 = 0.5.
|
||||
//
|
||||
RealD scale = std::sqrt(0.5);
|
||||
// P(phi) = e^{- phi^dag Vpc (MpcdagMpc)^-1 Vpcdag phi}
|
||||
//
|
||||
// NumOp == V
|
||||
// DenOp == M
|
||||
//
|
||||
// Take phi_o = Vpcdag^{-1} Mpcdag eta_o ; eta_o = Mpcdag^{-1} Vpcdag Phi
|
||||
//
|
||||
// P(eta_o) = e^{- eta_o^dag eta_o}
|
||||
//
|
||||
// e^{x^2/2 sig^2} => sig^2 = 0.5.
|
||||
//
|
||||
RealD scale = std::sqrt(0.5);
|
||||
|
||||
FermionField eta (NumOp.FermionGrid());
|
||||
FermionField etaOdd (NumOp.FermionRedBlackGrid());
|
||||
FermionField etaEven(NumOp.FermionRedBlackGrid());
|
||||
FermionField tmp (NumOp.FermionRedBlackGrid());
|
||||
FermionField eta (NumOp.FermionGrid());
|
||||
FermionField etaOdd (NumOp.FermionRedBlackGrid());
|
||||
FermionField etaEven(NumOp.FermionRedBlackGrid());
|
||||
FermionField tmp (NumOp.FermionRedBlackGrid());
|
||||
|
||||
gaussian(pRNG,eta);
|
||||
gaussian(pRNG,eta);
|
||||
|
||||
pickCheckerboard(Even,etaEven,eta);
|
||||
pickCheckerboard(Odd,etaOdd,eta);
|
||||
pickCheckerboard(Even,etaEven,eta);
|
||||
pickCheckerboard(Odd,etaOdd,eta);
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
SchurDifferentiableOperator<Impl> Mpc(DenOp);
|
||||
SchurDifferentiableOperator<Impl> Vpc(NumOp);
|
||||
SchurDifferentiableOperator<Impl> Mpc(DenOp);
|
||||
SchurDifferentiableOperator<Impl> Vpc(NumOp);
|
||||
|
||||
// Odd det factors
|
||||
Mpc.MpcDag(etaOdd,PhiOdd);
|
||||
tmp=Zero();
|
||||
ActionSolver(Vpc,PhiOdd,tmp);
|
||||
Vpc.Mpc(tmp,PhiOdd);
|
||||
// Odd det factors
|
||||
Mpc.MpcDag(etaOdd,PhiOdd);
|
||||
tmp=zero;
|
||||
HeatbathSolver(Vpc,PhiOdd,tmp);
|
||||
Vpc.Mpc(tmp,PhiOdd);
|
||||
|
||||
// Even det factors
|
||||
DenOp.MooeeDag(etaEven,tmp);
|
||||
NumOp.MooeeInvDag(tmp,PhiEven);
|
||||
// Even det factors
|
||||
DenOp.MooeeDag(etaEven,tmp);
|
||||
NumOp.MooeeInvDag(tmp,PhiEven);
|
||||
|
||||
PhiOdd =PhiOdd*scale;
|
||||
PhiEven=PhiEven*scale;
|
||||
PhiOdd =PhiOdd*scale;
|
||||
PhiEven=PhiEven*scale;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// S = phi^dag V (Mdag M)^-1 Vdag phi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual RealD S(const GaugeField &U) {
|
||||
//////////////////////////////////////////////////////
|
||||
// S = phi^dag V (Mdag M)^-1 Vdag phi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual RealD S(const GaugeField &U) {
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
SchurDifferentiableOperator<Impl> Mpc(DenOp);
|
||||
SchurDifferentiableOperator<Impl> Vpc(NumOp);
|
||||
SchurDifferentiableOperator<Impl> Mpc(DenOp);
|
||||
SchurDifferentiableOperator<Impl> Vpc(NumOp);
|
||||
|
||||
FermionField X(NumOp.FermionRedBlackGrid());
|
||||
FermionField Y(NumOp.FermionRedBlackGrid());
|
||||
FermionField X(NumOp.FermionRedBlackGrid());
|
||||
FermionField Y(NumOp.FermionRedBlackGrid());
|
||||
|
||||
Vpc.MpcDag(PhiOdd,Y); // Y= Vdag phi
|
||||
X=Zero();
|
||||
ActionSolver(Mpc,Y,X); // X= (MdagM)^-1 Vdag phi
|
||||
//Mpc.Mpc(X,Y); // Y= Mdag^-1 Vdag phi
|
||||
// Multiply by Ydag
|
||||
RealD action = real(innerProduct(Y,X));
|
||||
Vpc.MpcDag(PhiOdd,Y); // Y= Vdag phi
|
||||
X=zero;
|
||||
ActionSolver(Mpc,Y,X); // X= (MdagM)^-1 Vdag phi
|
||||
//Mpc.Mpc(X,Y); // Y= Mdag^-1 Vdag phi
|
||||
// Multiply by Ydag
|
||||
RealD action = real(innerProduct(Y,X));
|
||||
|
||||
//RealD action = norm2(Y);
|
||||
//RealD action = norm2(Y);
|
||||
|
||||
// The EE factorised block; normally can replace with Zero() if det is constant (gauge field indept)
|
||||
// Only really clover term that creates this. Leave the EE portion as a future to do to make most
|
||||
// rapid progresss on DWF for now.
|
||||
//
|
||||
NumOp.MooeeDag(PhiEven,X);
|
||||
DenOp.MooeeInvDag(X,Y);
|
||||
action = action + norm2(Y);
|
||||
// The EE factorised block; normally can replace with zero if det is constant (gauge field indept)
|
||||
// Only really clover term that creates this. Leave the EE portion as a future to do to make most
|
||||
// rapid progresss on DWF for now.
|
||||
//
|
||||
NumOp.MooeeDag(PhiEven,X);
|
||||
DenOp.MooeeInvDag(X,Y);
|
||||
action = action + norm2(Y);
|
||||
|
||||
return action;
|
||||
};
|
||||
return action;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// dS/du = phi^dag dV (Mdag M)^-1 V^dag phi
|
||||
// - phi^dag V (Mdag M)^-1 [ Mdag dM + dMdag M ] (Mdag M)^-1 V^dag phi
|
||||
// + phi^dag V (Mdag M)^-1 dV^dag phi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
|
||||
//////////////////////////////////////////////////////
|
||||
// dS/du = phi^dag dV (Mdag M)^-1 V^dag phi
|
||||
// - phi^dag V (Mdag M)^-1 [ Mdag dM + dMdag M ] (Mdag M)^-1 V^dag phi
|
||||
// + phi^dag V (Mdag M)^-1 dV^dag phi
|
||||
//////////////////////////////////////////////////////
|
||||
virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
|
||||
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
NumOp.ImportGauge(U);
|
||||
DenOp.ImportGauge(U);
|
||||
|
||||
SchurDifferentiableOperator<Impl> Mpc(DenOp);
|
||||
SchurDifferentiableOperator<Impl> Vpc(NumOp);
|
||||
SchurDifferentiableOperator<Impl> Mpc(DenOp);
|
||||
SchurDifferentiableOperator<Impl> Vpc(NumOp);
|
||||
|
||||
FermionField X(NumOp.FermionRedBlackGrid());
|
||||
FermionField Y(NumOp.FermionRedBlackGrid());
|
||||
FermionField X(NumOp.FermionRedBlackGrid());
|
||||
FermionField Y(NumOp.FermionRedBlackGrid());
|
||||
|
||||
// This assignment is necessary to be compliant with the HMC grids
|
||||
GaugeField force(dSdU.Grid());
|
||||
// This assignment is necessary to be compliant with the HMC grids
|
||||
GaugeField force(dSdU._grid);
|
||||
|
||||
//Y=Vdag phi
|
||||
//X = (Mdag M)^-1 V^dag phi
|
||||
//Y = (Mdag)^-1 V^dag phi
|
||||
Vpc.MpcDag(PhiOdd,Y); // Y= Vdag phi
|
||||
X=Zero();
|
||||
DerivativeSolver(Mpc,Y,X); // X= (MdagM)^-1 Vdag phi
|
||||
Mpc.Mpc(X,Y); // Y= Mdag^-1 Vdag phi
|
||||
//Y=Vdag phi
|
||||
//X = (Mdag M)^-1 V^dag phi
|
||||
//Y = (Mdag)^-1 V^dag phi
|
||||
Vpc.MpcDag(PhiOdd,Y); // Y= Vdag phi
|
||||
X=zero;
|
||||
DerivativeSolver(Mpc,Y,X); // X= (MdagM)^-1 Vdag phi
|
||||
Mpc.Mpc(X,Y); // Y= Mdag^-1 Vdag phi
|
||||
|
||||
// phi^dag V (Mdag M)^-1 dV^dag phi
|
||||
Vpc.MpcDagDeriv(force , X, PhiOdd ); dSdU = force;
|
||||
// phi^dag V (Mdag M)^-1 dV^dag phi
|
||||
Vpc.MpcDagDeriv(force , X, PhiOdd ); dSdU = force;
|
||||
|
||||
// phi^dag dV (Mdag M)^-1 V^dag phi
|
||||
Vpc.MpcDeriv(force , PhiOdd, X ); dSdU = dSdU+force;
|
||||
// phi^dag dV (Mdag M)^-1 V^dag phi
|
||||
Vpc.MpcDeriv(force , PhiOdd, X ); dSdU = dSdU+force;
|
||||
|
||||
// - phi^dag V (Mdag M)^-1 Mdag dM (Mdag M)^-1 V^dag phi
|
||||
// - phi^dag V (Mdag M)^-1 dMdag M (Mdag M)^-1 V^dag phi
|
||||
Mpc.MpcDeriv(force,Y,X); dSdU = dSdU-force;
|
||||
Mpc.MpcDagDeriv(force,X,Y); dSdU = dSdU-force;
|
||||
// - phi^dag V (Mdag M)^-1 Mdag dM (Mdag M)^-1 V^dag phi
|
||||
// - phi^dag V (Mdag M)^-1 dMdag M (Mdag M)^-1 V^dag phi
|
||||
Mpc.MpcDeriv(force,Y,X); dSdU = dSdU-force;
|
||||
Mpc.MpcDagDeriv(force,X,Y); dSdU = dSdU-force;
|
||||
|
||||
// FIXME No force contribution from EvenEven assumed here
|
||||
// Needs a fix for clover.
|
||||
assert(NumOp.ConstEE() == 1);
|
||||
assert(DenOp.ConstEE() == 1);
|
||||
// FIXME No force contribution from EvenEven assumed here
|
||||
// Needs a fix for clover.
|
||||
assert(NumOp.ConstEE() == 1);
|
||||
assert(DenOp.ConstEE() == 1);
|
||||
|
||||
dSdU = -dSdU;
|
||||
dSdU = -dSdU;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -41,19 +41,16 @@ public:
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(IntegratorParameters,
|
||||
std::string, name, // name of the integrator
|
||||
unsigned int, MDsteps, // number of outer steps
|
||||
RealD, trajL, // trajectory length
|
||||
)
|
||||
RealD, trajL) // trajectory length
|
||||
|
||||
IntegratorParameters(int MDsteps_ = 10, RealD trajL_ = 1.0)
|
||||
: MDsteps(MDsteps_),
|
||||
trajL(trajL_){
|
||||
// empty body constructor
|
||||
};
|
||||
|
||||
trajL(trajL_) {};
|
||||
|
||||
template <class ReaderClass, typename std::enable_if<isReader<ReaderClass>::value, int >::type = 0 >
|
||||
IntegratorParameters(ReaderClass & Reader){
|
||||
std::cout << "Reading integrator\n";
|
||||
IntegratorParameters(ReaderClass & Reader)
|
||||
{
|
||||
std::cout << GridLogMessage << "Reading integrator\n";
|
||||
read(Reader, "Integrator", *this);
|
||||
}
|
||||
|
||||
@ -83,17 +80,18 @@ protected:
|
||||
|
||||
const ActionSet<Field, RepresentationPolicy> as;
|
||||
|
||||
void update_P(Field& U, int level, double ep) {
|
||||
void update_P(Field& U, int level, double ep)
|
||||
{
|
||||
t_P[level] += ep;
|
||||
update_P(P, U, level, ep);
|
||||
|
||||
std::cout << GridLogIntegrator << "[" << level << "] P "
|
||||
<< " dt " << ep << " : t_P " << t_P[level] << std::endl;
|
||||
std::cout << GridLogIntegrator << "[" << level << "] P " << " dt " << ep << " : t_P " << t_P[level] << std::endl;
|
||||
}
|
||||
|
||||
// to be used by the actionlevel class to iterate
|
||||
// over the representations
|
||||
struct _updateP {
|
||||
struct _updateP
|
||||
{
|
||||
template <class FieldType, class GF, class Repr>
|
||||
void operator()(std::vector<Action<FieldType>*> repr_set, Repr& Rep,
|
||||
GF& Mom, GF& U, double ep) {
|
||||
@ -104,7 +102,7 @@ protected:
|
||||
GF force = Rep.RtoFundamentalProject(forceR); // Ta for the fundamental rep
|
||||
Real force_abs = std::sqrt(norm2(force)/(U.Grid()->gSites()));
|
||||
std::cout << GridLogIntegrator << "Hirep Force average: " << force_abs << std::endl;
|
||||
Mom -= force * ep ;
|
||||
Mom -= force * ep* HMC_MOMENTUM_DENOMINATOR;;
|
||||
}
|
||||
}
|
||||
} update_P_hireps{};
|
||||
@ -128,18 +126,19 @@ protected:
|
||||
double end_force = usecond();
|
||||
Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites());
|
||||
std::cout << GridLogIntegrator << "["<<level<<"]["<<a<<"] Force average: " << force_abs << std::endl;
|
||||
Mom -= force * ep;
|
||||
Mom -= force * ep* HMC_MOMENTUM_DENOMINATOR;;
|
||||
double end_full = usecond();
|
||||
double time_full = (end_full - start_full) / 1e3;
|
||||
double time_force = (end_force - start_force) / 1e3;
|
||||
std::cout << GridLogIntegrator << "["<<level<<"]["<<a<<"] P update elapsed time: " << time_full << " ms (force: " << time_force << " ms)" << std::endl;
|
||||
std::cout << GridLogMessage << "["<<level<<"]["<<a<<"] P update elapsed time: " << time_full << " ms (force: " << time_force << " ms)" << std::endl;
|
||||
}
|
||||
|
||||
// Force from the other representations
|
||||
as[level].apply(update_P_hireps, Representations, Mom, U, ep);
|
||||
}
|
||||
|
||||
void update_U(Field& U, double ep) {
|
||||
void update_U(Field& U, double ep)
|
||||
{
|
||||
update_U(P, U, ep);
|
||||
|
||||
t_U += ep;
|
||||
@ -147,7 +146,8 @@ protected:
|
||||
std::cout << GridLogIntegrator << " " << "[" << fl << "] U " << " dt " << ep << " : t_U " << t_U << std::endl;
|
||||
}
|
||||
|
||||
void update_U(MomentaField& Mom, Field& U, double ep) {
|
||||
void update_U(MomentaField& Mom, Field& U, double ep)
|
||||
{
|
||||
// exponential of Mom*U in the gauge fields case
|
||||
FieldImplementation::update_field(Mom, U, ep);
|
||||
|
||||
@ -169,7 +169,8 @@ public:
|
||||
P(grid),
|
||||
levels(Aset.size()),
|
||||
Smearer(Sm),
|
||||
Representations(grid) {
|
||||
Representations(grid)
|
||||
{
|
||||
t_P.resize(levels, 0.0);
|
||||
t_U = 0.0;
|
||||
// initialization of smearer delegated outside of Integrator
|
||||
@ -179,12 +180,14 @@ public:
|
||||
|
||||
virtual std::string integrator_name() = 0;
|
||||
|
||||
void print_parameters(){
|
||||
void print_parameters()
|
||||
{
|
||||
std::cout << GridLogMessage << "[Integrator] Name : "<< integrator_name() << std::endl;
|
||||
Params.print_parameters();
|
||||
}
|
||||
|
||||
void print_actions(){
|
||||
void print_actions()
|
||||
{
|
||||
std::cout << GridLogMessage << ":::::::::::::::::::::::::::::::::::::::::" << std::endl;
|
||||
std::cout << GridLogMessage << "[Integrator] Action summary: "<<std::endl;
|
||||
for (int level = 0; level < as.size(); ++level) {
|
||||
@ -198,7 +201,8 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void reverse_momenta(){
|
||||
void reverse_momenta()
|
||||
{
|
||||
P *= -1.0;
|
||||
}
|
||||
|
||||
@ -217,7 +221,8 @@ public:
|
||||
} refresh_hireps{};
|
||||
|
||||
// Initialization of momenta and actions
|
||||
void refresh(Field& U, GridParallelRNG& pRNG) {
|
||||
void refresh(Field& U, GridParallelRNG& pRNG)
|
||||
{
|
||||
assert(P.Grid() == U.Grid());
|
||||
std::cout << GridLogIntegrator << "Integrator refresh\n";
|
||||
|
||||
@ -237,8 +242,7 @@ public:
|
||||
for (int actionID = 0; actionID < as[level].actions.size(); ++actionID) {
|
||||
// get gauge field from the SmearingPolicy and
|
||||
// based on the boolean is_smeared in actionID
|
||||
Field& Us =
|
||||
Smearer.get_U(as[level].actions.at(actionID)->is_smeared);
|
||||
Field& Us = Smearer.get_U(as[level].actions.at(actionID)->is_smeared);
|
||||
as[level].actions.at(actionID)->refresh(Us, pRNG);
|
||||
}
|
||||
|
||||
@ -251,13 +255,11 @@ public:
|
||||
// over the representations
|
||||
struct _S {
|
||||
template <class FieldType, class Repr>
|
||||
void operator()(std::vector<Action<FieldType>*> repr_set, Repr& Rep,
|
||||
int level, RealD& H) {
|
||||
void operator()(std::vector<Action<FieldType>*> repr_set, Repr& Rep, int level, RealD& H) {
|
||||
|
||||
for (int a = 0; a < repr_set.size(); ++a) {
|
||||
RealD Hterm = repr_set.at(a)->S(Rep.U);
|
||||
std::cout << GridLogMessage << "S Level " << level << " term " << a
|
||||
<< " H Hirep = " << Hterm << std::endl;
|
||||
std::cout << GridLogMessage << "S Level " << level << " term " << a << " H Hirep = " << Hterm << std::endl;
|
||||
H += Hterm;
|
||||
|
||||
}
|
||||
@ -265,22 +267,24 @@ public:
|
||||
} S_hireps{};
|
||||
|
||||
// Calculate action
|
||||
RealD S(Field& U) { // here also U not used
|
||||
RealD S(Field& U)
|
||||
{ // here also U not used
|
||||
|
||||
std::cout << GridLogIntegrator << "Integrator action\n";
|
||||
|
||||
RealD H = - FieldImplementation::FieldSquareNorm(P)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
|
||||
|
||||
RealD H = - FieldImplementation::FieldSquareNorm(P); // - trace (P*P)
|
||||
RealD Hterm;
|
||||
std::cout << GridLogMessage << "Momentum action H_p = " << H << "\n";
|
||||
|
||||
// Actions
|
||||
for (int level = 0; level < as.size(); ++level) {
|
||||
for (int actionID = 0; actionID < as[level].actions.size(); ++actionID) {
|
||||
// get gauge field from the SmearingPolicy and
|
||||
// based on the boolean is_smeared in actionID
|
||||
Field& Us =
|
||||
Smearer.get_U(as[level].actions.at(actionID)->is_smeared);
|
||||
Field& Us = Smearer.get_U(as[level].actions.at(actionID)->is_smeared);
|
||||
std::cout << GridLogMessage << "S [" << level << "][" << actionID << "] action eval " << std::endl;
|
||||
Hterm = as[level].actions.at(actionID)->S(Us);
|
||||
std::cout << GridLogMessage << "S Level " << level << " term "
|
||||
<< actionID << " H = " << Hterm << std::endl;
|
||||
std::cout << GridLogMessage << "S [" << level << "][" << actionID << "] H = " << Hterm << std::endl;
|
||||
H += Hterm;
|
||||
}
|
||||
as[level].apply(S_hireps, Representations, level, H);
|
||||
@ -289,7 +293,8 @@ public:
|
||||
return H;
|
||||
}
|
||||
|
||||
void integrate(Field& U) {
|
||||
void integrate(Field& U)
|
||||
{
|
||||
// reset the clocks
|
||||
t_U = 0;
|
||||
for (int level = 0; level < as.size(); ++level) {
|
||||
@ -305,8 +310,7 @@ public:
|
||||
// Check the clocks all match on all levels
|
||||
for (int level = 0; level < as.size(); ++level) {
|
||||
assert(fabs(t_U - t_P[level]) < 1.0e-6); // must be the same
|
||||
std::cout << GridLogIntegrator << " times[" << level
|
||||
<< "]= " << t_P[level] << " " << t_U << std::endl;
|
||||
std::cout << GridLogIntegrator << " times[" << level << "]= " << t_P[level] << " " << t_U << std::endl;
|
||||
}
|
||||
|
||||
// and that we indeed got to the end of the trajectory
|
||||
|
@ -26,15 +26,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
See the full license in the file "LICENSE" in the top level distribution
|
||||
directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
//--------------------------------------------------------------------
|
||||
/* END LEGAL */
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
|
||||
/*! @file Integrator_algorithm.h
|
||||
* @brief Declaration of classes for the Molecular Dynamics algorithms
|
||||
*
|
||||
*/
|
||||
//--------------------------------------------------------------------
|
||||
/*! @file Integrator_algorithm.h
|
||||
* @brief Declaration of classes for the Molecular Dynamics algorithms
|
||||
*
|
||||
*/
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifndef INTEGRATOR_ALG_INCLUDED
|
||||
#define INTEGRATOR_ALG_INCLUDED
|
||||
@ -92,22 +92,17 @@ NAMESPACE_BEGIN(Grid);
|
||||
* P 1/2 P 1/2
|
||||
*/
|
||||
|
||||
template <class FieldImplementation, class SmearingPolicy,
|
||||
class RepresentationPolicy =
|
||||
Representations<FundamentalRepresentation> >
|
||||
class LeapFrog : public Integrator<FieldImplementation, SmearingPolicy,
|
||||
RepresentationPolicy> {
|
||||
template <class FieldImplementation, class SmearingPolicy, class RepresentationPolicy = Representations<FundamentalRepresentation> >
|
||||
class LeapFrog : public Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>
|
||||
{
|
||||
public:
|
||||
typedef LeapFrog<FieldImplementation, SmearingPolicy, RepresentationPolicy>
|
||||
Algorithm;
|
||||
typedef LeapFrog<FieldImplementation, SmearingPolicy, RepresentationPolicy> Algorithm;
|
||||
INHERIT_FIELD_TYPES(FieldImplementation);
|
||||
|
||||
std::string integrator_name(){return "LeapFrog";}
|
||||
|
||||
LeapFrog(GridBase* grid, IntegratorParameters Par,
|
||||
ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
|
||||
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
|
||||
grid, Par, Aset, Sm){};
|
||||
LeapFrog(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
|
||||
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm){};
|
||||
|
||||
void step(Field& U, int level, int _first, int _last) {
|
||||
int fl = this->as.size() - 1;
|
||||
@ -140,21 +135,17 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class FieldImplementation, class SmearingPolicy,
|
||||
class RepresentationPolicy =
|
||||
Representations<FundamentalRepresentation> >
|
||||
class MinimumNorm2 : public Integrator<FieldImplementation, SmearingPolicy,
|
||||
RepresentationPolicy> {
|
||||
template <class FieldImplementation, class SmearingPolicy, class RepresentationPolicy = Representations<FundamentalRepresentation> >
|
||||
class MinimumNorm2 : public Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>
|
||||
{
|
||||
private:
|
||||
const RealD lambda = 0.1931833275037836;
|
||||
|
||||
public:
|
||||
INHERIT_FIELD_TYPES(FieldImplementation);
|
||||
|
||||
MinimumNorm2(GridBase* grid, IntegratorParameters Par,
|
||||
ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
|
||||
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
|
||||
grid, Par, Aset, Sm){};
|
||||
MinimumNorm2(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
|
||||
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm){};
|
||||
|
||||
std::string integrator_name(){return "MininumNorm2";}
|
||||
|
||||
@ -201,14 +192,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class FieldImplementation, class SmearingPolicy,
|
||||
class RepresentationPolicy =
|
||||
Representations<FundamentalRepresentation> >
|
||||
class ForceGradient : public Integrator<FieldImplementation, SmearingPolicy,
|
||||
RepresentationPolicy> {
|
||||
template <class FieldImplementation, class SmearingPolicy, class RepresentationPolicy = Representations<FundamentalRepresentation> >
|
||||
class ForceGradient : public Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>
|
||||
{
|
||||
private:
|
||||
const RealD lambda = 1.0 / 6.0;
|
||||
;
|
||||
const RealD chi = 1.0 / 72.0;
|
||||
const RealD xi = 0.0;
|
||||
const RealD theta = 0.0;
|
||||
@ -230,8 +218,7 @@ public:
|
||||
Field Pfg(U.Grid());
|
||||
Ufg = U;
|
||||
Pfg = Zero();
|
||||
std::cout << GridLogIntegrator << "FG update " << fg_dt << " " << ep
|
||||
<< std::endl;
|
||||
std::cout << GridLogIntegrator << "FG update " << fg_dt << " " << ep << std::endl;
|
||||
// prepare_fg; no prediction/result cache for now
|
||||
// could relax CG stopping conditions for the
|
||||
// derivatives in the small step since the force gets multiplied by
|
||||
@ -270,8 +257,7 @@ public:
|
||||
this->step(U, level + 1, first_step, 0);
|
||||
}
|
||||
|
||||
this->FG_update_P(U, level, 2 * Chi / ((1.0 - 2.0 * lambda) * eps),
|
||||
(1.0 - 2.0 * lambda) * eps);
|
||||
this->FG_update_P(U, level, 2 * Chi / ((1.0 - 2.0 * lambda) * eps), (1.0 - 2.0 * lambda) * eps);
|
||||
|
||||
if (level == fl) { // lowest level
|
||||
this->update_U(U, 0.5 * eps);
|
||||
|
@ -10,6 +10,24 @@ const std::array<const Gamma, 4> Gamma::gmu = {{
|
||||
Gamma(Gamma::Algebra::GammaZ),
|
||||
Gamma(Gamma::Algebra::GammaT)}};
|
||||
|
||||
const std::array<const Gamma, 16> Gamma::gall = {{
|
||||
Gamma(Gamma::Algebra::Identity),
|
||||
Gamma(Gamma::Algebra::Gamma5),
|
||||
Gamma(Gamma::Algebra::GammaX),
|
||||
Gamma(Gamma::Algebra::GammaY),
|
||||
Gamma(Gamma::Algebra::GammaZ),
|
||||
Gamma(Gamma::Algebra::GammaT),
|
||||
Gamma(Gamma::Algebra::GammaXGamma5),
|
||||
Gamma(Gamma::Algebra::GammaYGamma5),
|
||||
Gamma(Gamma::Algebra::GammaZGamma5),
|
||||
Gamma(Gamma::Algebra::GammaTGamma5),
|
||||
Gamma(Gamma::Algebra::SigmaXT),
|
||||
Gamma(Gamma::Algebra::SigmaXY),
|
||||
Gamma(Gamma::Algebra::SigmaXZ),
|
||||
Gamma(Gamma::Algebra::SigmaYT),
|
||||
Gamma(Gamma::Algebra::SigmaYZ),
|
||||
Gamma(Gamma::Algebra::SigmaZT)}};
|
||||
|
||||
const std::array<const char *, Gamma::nGamma> Gamma::name = {{
|
||||
"-Gamma5 ",
|
||||
"Gamma5 ",
|
||||
|
@ -47,6 +47,7 @@ class Gamma {
|
||||
static const std::array<std::array<Algebra, nGamma>, nGamma> mul;
|
||||
static const std::array<Algebra, nGamma> adj;
|
||||
static const std::array<const Gamma, 4> gmu;
|
||||
static const std::array<const Gamma, 16> gall;
|
||||
Algebra g;
|
||||
public:
|
||||
accelerator Gamma(Algebra initg): g(initg) {}
|
||||
|
@ -10,10 +10,10 @@
|
||||
NotebookFileLineBreakTest
|
||||
NotebookFileLineBreakTest
|
||||
NotebookDataPosition[ 158, 7]
|
||||
NotebookDataLength[ 75090, 1956]
|
||||
NotebookOptionsPosition[ 69536, 1867]
|
||||
NotebookOutlinePosition[ 69898, 1883]
|
||||
CellTagsIndexPosition[ 69855, 1880]
|
||||
NotebookDataLength[ 67118, 1714]
|
||||
NotebookOptionsPosition[ 63485, 1652]
|
||||
NotebookOutlinePosition[ 63842, 1668]
|
||||
CellTagsIndexPosition[ 63799, 1665]
|
||||
WindowFrame->Normal*)
|
||||
|
||||
(* Beginning of Notebook Content *)
|
||||
@ -76,234 +76,6 @@ Cell[BoxData["\<\"/Users/antonin/Development/Grid/lib/qcd/spin/gamma-gen\"\>"]\
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"FactorInteger", "[", "3152", "]"}]], "Input",
|
||||
CellChangeTimes->{{3.7432347536316767`*^9, 3.7432347764739027`*^9}, {
|
||||
3.743234833567358*^9,
|
||||
3.743234862146022*^9}},ExpressionUUID->"d1a0fd03-85e1-43af-ba80-\
|
||||
3ca4235675d8"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"2", ",", "4"}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"197", ",", "1"}], "}"}]}], "}"}]], "Output",
|
||||
CellChangeTimes->{{3.743234836792224*^9,
|
||||
3.743234862493619*^9}},ExpressionUUID->"16d3f953-4b24-4ed2-ae62-\
|
||||
306dcab66ca7"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"sol", "=",
|
||||
RowBox[{"Solve", "[",
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
SuperscriptBox["x", "2"], "+",
|
||||
SuperscriptBox["y", "2"], "+",
|
||||
SuperscriptBox["z", "2"]}], "\[Equal]", "2"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{"x", ",", "y", ",", "z"}], "}"}], ",", "Integers"}],
|
||||
"]"}]}]], "Input",
|
||||
CellChangeTimes->{{3.743235304127721*^9,
|
||||
3.7432353087929983`*^9}},ExpressionUUID->"f0fa2a5c-3d81-4d75-a447-\
|
||||
50c7ca3459ff"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}], ",",
|
||||
RowBox[{"y", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}], ",",
|
||||
RowBox[{"z", "\[Rule]", "0"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}], ",",
|
||||
RowBox[{"y", "\[Rule]", "0"}], ",",
|
||||
RowBox[{"z", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}], ",",
|
||||
RowBox[{"y", "\[Rule]", "0"}], ",",
|
||||
RowBox[{"z", "\[Rule]", "1"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}], ",",
|
||||
RowBox[{"y", "\[Rule]", "1"}], ",",
|
||||
RowBox[{"z", "\[Rule]", "0"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]", "0"}], ",",
|
||||
RowBox[{"y", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}], ",",
|
||||
RowBox[{"z", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]", "0"}], ",",
|
||||
RowBox[{"y", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}], ",",
|
||||
RowBox[{"z", "\[Rule]", "1"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]", "0"}], ",",
|
||||
RowBox[{"y", "\[Rule]", "1"}], ",",
|
||||
RowBox[{"z", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]", "0"}], ",",
|
||||
RowBox[{"y", "\[Rule]", "1"}], ",",
|
||||
RowBox[{"z", "\[Rule]", "1"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]", "1"}], ",",
|
||||
RowBox[{"y", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}], ",",
|
||||
RowBox[{"z", "\[Rule]", "0"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]", "1"}], ",",
|
||||
RowBox[{"y", "\[Rule]", "0"}], ",",
|
||||
RowBox[{"z", "\[Rule]",
|
||||
RowBox[{"-", "1"}]}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]", "1"}], ",",
|
||||
RowBox[{"y", "\[Rule]", "0"}], ",",
|
||||
RowBox[{"z", "\[Rule]", "1"}]}], "}"}], ",",
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
RowBox[{"x", "\[Rule]", "1"}], ",",
|
||||
RowBox[{"y", "\[Rule]", "1"}], ",",
|
||||
RowBox[{"z", "\[Rule]", "0"}]}], "}"}]}], "}"}]], "Output",
|
||||
CellChangeTimes->{{3.743235305220907*^9,
|
||||
3.743235309139554*^9}},ExpressionUUID->"d9825c95-24bb-442a-8734-\
|
||||
4c0f47e99dfc"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{"xmlElem", "[", "x_", "]"}], ":=",
|
||||
RowBox[{"Print", "[",
|
||||
RowBox[{"\"\<<elem>\>\"", "<>",
|
||||
RowBox[{"ToString", "[",
|
||||
RowBox[{"x", "[",
|
||||
RowBox[{"[", "1", "]"}], "]"}], "]"}], "<>", "\"\< \>\"", "<>",
|
||||
RowBox[{"ToString", "[",
|
||||
RowBox[{"x", "[",
|
||||
RowBox[{"[", "2", "]"}], "]"}], "]"}], "<>", "\"\< \>\"", "<>",
|
||||
RowBox[{"ToString", "[",
|
||||
RowBox[{"x", "[",
|
||||
RowBox[{"[", "3", "]"}], "]"}], "]"}], "<>", "\"\<</elem>\>\""}],
|
||||
"]"}]}]], "Input",
|
||||
CellChangeTimes->{{3.74323534002862*^9, 3.743235351000985*^9}, {
|
||||
3.743235403233039*^9, 3.743235413488028*^9}, {3.743235473169856*^9,
|
||||
3.7432354747126904`*^9}},ExpressionUUID->"aea76313-c89e-45e8-b429-\
|
||||
3f454091666d"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
RowBox[{
|
||||
RowBox[{"xmlElem", "[",
|
||||
RowBox[{
|
||||
RowBox[{"{",
|
||||
RowBox[{"x", ",", "y", ",", "z"}], "}"}], "/.", "#"}], "]"}], "&"}], "/@",
|
||||
"sol"}]], "Input",
|
||||
CellChangeTimes->{{3.743235415820318*^9,
|
||||
3.743235467025091*^9}},ExpressionUUID->"07da3998-8eab-40ba-8c0b-\
|
||||
ac6b130cb4fb"],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell[BoxData["\<\"<elem>-1 -1 0</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476581676*^9},ExpressionUUID->"c577ba06-b67a-405a-9ff5-\
|
||||
2bf7dc898d03"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>-1 0 -1</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476588011*^9},ExpressionUUID->"d041aa36-0cea-457c-9d4b-\
|
||||
1fe9be66e2ab"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>-1 0 1</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476596887*^9},ExpressionUUID->"bf141b55-86b2-4430-a994-\
|
||||
5c03d5a19441"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>-1 1 0</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476605785*^9},ExpressionUUID->"4968a660-4ecf-4b66-9071-\
|
||||
8bd798c18d21"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>0 -1 -1</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476613523*^9},ExpressionUUID->"4e22d943-2680-416b-a1d7-\
|
||||
a16ca20b781f"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>0 -1 1</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.7432354766218576`*^9},ExpressionUUID->"6dd38385-08b3-4dd9-932f-\
|
||||
98a00c6db1b2"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>0 1 -1</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476629427*^9},ExpressionUUID->"ef3baad3-91d1-4735-9a22-\
|
||||
53495a624c15"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>0 1 1</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476638257*^9},ExpressionUUID->"413fbb68-5017-4272-a62a-\
|
||||
fa234e6daaea"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>1 -1 0</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476646203*^9},ExpressionUUID->"3a832a60-ae00-414b-a9ac-\
|
||||
f5e86e67e917"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>1 0 -1</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476653907*^9},ExpressionUUID->"bfc79ef6-f6c7-4f1e-88e8-\
|
||||
005ac314be9c"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>1 0 1</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.743235476662575*^9},ExpressionUUID->"0f892891-f885-489c-9925-\
|
||||
ddef4d698410"],
|
||||
|
||||
Cell[BoxData["\<\"<elem>1 1 0</elem>\"\>"], "Print",
|
||||
CellChangeTimes->{
|
||||
3.7432354766702337`*^9},ExpressionUUID->"2906f190-e673-4f33-9c34-\
|
||||
e8e56efe7a27"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{"{",
|
||||
RowBox[{
|
||||
"Null", ",", "Null", ",", "Null", ",", "Null", ",", "Null", ",", "Null",
|
||||
",", "Null", ",", "Null", ",", "Null", ",", "Null", ",", "Null", ",",
|
||||
"Null"}], "}"}]], "Output",
|
||||
CellChangeTimes->{
|
||||
3.7432354246225967`*^9, {3.7432354674878073`*^9,
|
||||
3.743235476678007*^9}},ExpressionUUID->"500ca3c1-88d8-46e5-a1a1-\
|
||||
86a7878e5638"]
|
||||
}, Open ]],
|
||||
|
||||
Cell[CellGroupData[{
|
||||
|
||||
Cell["Clifford algebra generation", "Section",
|
||||
CellChangeTimes->{{3.6942089434583883`*^9,
|
||||
3.694208978559093*^9}},ExpressionUUID->"a5b064b3-3011-4922-8559-\
|
||||
@ -1048,9 +820,10 @@ generated by the Mathematica notebook gamma-gen/gamma-gen.nb\n\n#include \
|
||||
"\"\< static const std::array<const char *, nGamma> \
|
||||
name;\n static const std::array<std::array<Algebra, nGamma>, nGamma> mul;\n\
|
||||
static const std::array<Algebra, nGamma> adj;\n \
|
||||
static const std::array<const Gamma, 4> gmu;\n \
|
||||
Algebra g;\n public:\n \
|
||||
Gamma(Algebra initg): g(initg) {} \n};\n\n\>\""}]}], ";",
|
||||
static const std::array<const Gamma, 4> gmu;\n static \
|
||||
const std::array<const Gamma, 16> gall;\n Algebra \
|
||||
g;\n public:\n \
|
||||
Gamma(Algebra initg): g(initg) {} \n};\n\n\>\""}]}], ";",
|
||||
"\[IndentingNewLine]",
|
||||
RowBox[{"out", " ", "=",
|
||||
RowBox[{"out", "<>", "funcCode"}]}], ";", "\[IndentingNewLine]",
|
||||
@ -1076,7 +849,8 @@ Algebra g;\n public:\n \
|
||||
3.694963343265525*^9}, {3.694964367519239*^9, 3.69496439461199*^9}, {
|
||||
3.694964462130747*^9, 3.6949644669959793`*^9}, 3.694964509762739*^9, {
|
||||
3.694964705045744*^9, 3.694964723148797*^9}, {3.694964992988984*^9,
|
||||
3.6949649968504257`*^9}},ExpressionUUID->"c7103bd6-b539-4495-b98c-\
|
||||
3.6949649968504257`*^9}, {3.758291687176977*^9,
|
||||
3.758291694181189*^9}},ExpressionUUID->"c7103bd6-b539-4495-b98c-\
|
||||
d4d12ac6cad8"],
|
||||
|
||||
Cell["Gamma enum generation:", "Text",
|
||||
@ -1745,8 +1519,17 @@ namespace QCD {\>\""}]}], ";", "\[IndentingNewLine]",
|
||||
"\"\<\n\nconst std::array<const Gamma, 4> Gamma::gmu = {{\n \
|
||||
Gamma(Gamma::Algebra::GammaX),\n Gamma(Gamma::Algebra::GammaY),\n \
|
||||
Gamma(Gamma::Algebra::GammaZ),\n Gamma(Gamma::Algebra::GammaT)}};\n\nconst \
|
||||
std::array<const char *, Gamma::nGamma> Gamma::name = {{\n\>\""}]}], ";",
|
||||
"\[IndentingNewLine]",
|
||||
std::array<const Gamma, 16> Gamma::gall = {{\n \
|
||||
Gamma(Gamma::Algebra::Identity),\n Gamma(Gamma::Algebra::Gamma5),\n \
|
||||
Gamma(Gamma::Algebra::GammaX),\n Gamma(Gamma::Algebra::GammaY),\n \
|
||||
Gamma(Gamma::Algebra::GammaZ),\n Gamma(Gamma::Algebra::GammaT),\n \
|
||||
Gamma(Gamma::Algebra::GammaXGamma5),\n Gamma(Gamma::Algebra::GammaYGamma5),\n\
|
||||
Gamma(Gamma::Algebra::GammaZGamma5),\n \
|
||||
Gamma(Gamma::Algebra::GammaTGamma5),\n Gamma(Gamma::Algebra::SigmaXT), \
|
||||
\n Gamma(Gamma::Algebra::SigmaXY), \n Gamma(Gamma::Algebra::SigmaXZ), \
|
||||
\n Gamma(Gamma::Algebra::SigmaYT),\n Gamma(Gamma::Algebra::SigmaYZ),\n \
|
||||
Gamma(Gamma::Algebra::SigmaZT)}};\n\nconst std::array<const char *, \
|
||||
Gamma::nGamma> Gamma::name = {{\n\>\""}]}], ";", "\[IndentingNewLine]",
|
||||
RowBox[{"Do", "[", "\[IndentingNewLine]",
|
||||
RowBox[{
|
||||
RowBox[{"out", " ", "=", " ",
|
||||
@ -1847,7 +1630,9 @@ Gamma::nGamma> Gamma::mul = {{\\n\>\""}]}], ";", "\[IndentingNewLine]",
|
||||
3.694963031525289*^9}, {3.694963065828494*^9, 3.694963098327538*^9}, {
|
||||
3.6949632020836153`*^9, 3.6949632715940027`*^9}, {3.694963440035037*^9,
|
||||
3.6949634418966017`*^9}, {3.6949651447067547`*^9, 3.694965161228381*^9}, {
|
||||
3.694967957845581*^9, 3.694967958364184*^9}}],
|
||||
3.694967957845581*^9, 3.694967958364184*^9}, {3.758291673792514*^9,
|
||||
3.758291676983432*^9}},ExpressionUUID->"b1b309f8-a3a7-4081-a781-\
|
||||
c3845e3cd372"],
|
||||
|
||||
Cell[BoxData[
|
||||
RowBox[{
|
||||
@ -1867,8 +1652,8 @@ Cell[BoxData[""], "Input",
|
||||
},
|
||||
WindowSize->{1246, 1005},
|
||||
WindowMargins->{{282, Automatic}, {Automatic, 14}},
|
||||
FrontEndVersion->"11.2 for Mac OS X x86 (32-bit, 64-bit Kernel) (September \
|
||||
10, 2017)",
|
||||
FrontEndVersion->"11.3 for Mac OS X x86 (32-bit, 64-bit Kernel) (March 5, \
|
||||
2018)",
|
||||
StyleDefinitions->"Default.nb"
|
||||
]
|
||||
(* End of Notebook Content *)
|
||||
@ -1888,75 +1673,48 @@ Cell[1948, 43, 570, 11, 73, "Input",ExpressionUUID->"5c937a3e-adfd-4d7e-8fde-afb
|
||||
Cell[2521, 56, 1172, 17, 34, "Output",ExpressionUUID->"72817ba6-2f6a-4a4d-8212-6f0970f49e7c"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[3730, 78, 248, 5, 30, "Input",ExpressionUUID->"d1a0fd03-85e1-43af-ba80-3ca4235675d8"],
|
||||
Cell[3981, 85, 299, 9, 34, "Output",ExpressionUUID->"16d3f953-4b24-4ed2-ae62-306dcab66ca7"]
|
||||
Cell[3730, 78, 174, 3, 67, "Section",ExpressionUUID->"a5b064b3-3011-4922-8559-ead857cad102"],
|
||||
Cell[3907, 83, 535, 16, 52, "Input",ExpressionUUID->"aa28f02b-31e1-4df2-9b5d-482177464b59"],
|
||||
Cell[4445, 101, 250, 4, 35, "Text",ExpressionUUID->"c8896b88-f1db-4ce4-b7a6-0c9838bdb8f1"],
|
||||
Cell[4698, 107, 5511, 169, 425, "Input",ExpressionUUID->"52a96ff6-047e-4043-86d0-e303866e5f8e"],
|
||||
Cell[CellGroupData[{
|
||||
Cell[10234, 280, 2183, 58, 135, "Input",ExpressionUUID->"8b0f4955-2c3f-418c-9226-9be8f87621e8"],
|
||||
Cell[12420, 340, 1027, 27, 56, "Output",ExpressionUUID->"edd0619f-6f12-4070-a1d2-6b547877fadc"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[4317, 99, 469, 14, 33, "Input",ExpressionUUID->"f0fa2a5c-3d81-4d75-a447-50c7ca3459ff"],
|
||||
Cell[4789, 115, 2423, 77, 56, "Output",ExpressionUUID->"d9825c95-24bb-442a-8734-4c0f47e99dfc"]
|
||||
Cell[13484, 372, 1543, 46, 114, "Input",ExpressionUUID->"fb45123c-c610-4075-99b0-7cd71c728ae7"],
|
||||
Cell[15030, 420, 1311, 32, 87, "Output",ExpressionUUID->"2ae14565-b412-4dc0-9dce-bd6c1ba5ef27"]
|
||||
}, Open ]],
|
||||
Cell[7227, 195, 751, 18, 30, "Input",ExpressionUUID->"aea76313-c89e-45e8-b429-3f454091666d"],
|
||||
Cell[16356, 455, 179, 3, 35, "Text",ExpressionUUID->"af247231-a58d-417b-987a-26908dafffdb"],
|
||||
Cell[16538, 460, 2175, 65, 94, "Input",ExpressionUUID->"7c44cadd-e488-4f51-87d8-c64eef11f40c"],
|
||||
Cell[18716, 527, 193, 3, 35, "Text",ExpressionUUID->"856f1746-1107-4509-a5ce-ac9c7f56cdb1"],
|
||||
Cell[CellGroupData[{
|
||||
Cell[8003, 217, 323, 10, 30, "Input",ExpressionUUID->"07da3998-8eab-40ba-8c0b-ac6b130cb4fb"],
|
||||
Cell[CellGroupData[{
|
||||
Cell[8351, 231, 156, 3, 24, "Print",ExpressionUUID->"c577ba06-b67a-405a-9ff5-2bf7dc898d03"],
|
||||
Cell[8510, 236, 156, 3, 24, "Print",ExpressionUUID->"d041aa36-0cea-457c-9d4b-1fe9be66e2ab"],
|
||||
Cell[8669, 241, 155, 3, 24, "Print",ExpressionUUID->"bf141b55-86b2-4430-a994-5c03d5a19441"],
|
||||
Cell[8827, 246, 155, 3, 24, "Print",ExpressionUUID->"4968a660-4ecf-4b66-9071-8bd798c18d21"],
|
||||
Cell[8985, 251, 156, 3, 24, "Print",ExpressionUUID->"4e22d943-2680-416b-a1d7-a16ca20b781f"],
|
||||
Cell[9144, 256, 157, 3, 24, "Print",ExpressionUUID->"6dd38385-08b3-4dd9-932f-98a00c6db1b2"],
|
||||
Cell[9304, 261, 155, 3, 24, "Print",ExpressionUUID->"ef3baad3-91d1-4735-9a22-53495a624c15"],
|
||||
Cell[9462, 266, 154, 3, 24, "Print",ExpressionUUID->"413fbb68-5017-4272-a62a-fa234e6daaea"],
|
||||
Cell[9619, 271, 155, 3, 24, "Print",ExpressionUUID->"3a832a60-ae00-414b-a9ac-f5e86e67e917"],
|
||||
Cell[9777, 276, 155, 3, 24, "Print",ExpressionUUID->"bfc79ef6-f6c7-4f1e-88e8-005ac314be9c"],
|
||||
Cell[9935, 281, 154, 3, 24, "Print",ExpressionUUID->"0f892891-f885-489c-9925-ddef4d698410"],
|
||||
Cell[10092, 286, 156, 3, 24, "Print",ExpressionUUID->"2906f190-e673-4f33-9c34-e8e56efe7a27"]
|
||||
}, Open ]],
|
||||
Cell[10263, 292, 376, 9, 34, "Output",ExpressionUUID->"500ca3c1-88d8-46e5-a1a1-86a7878e5638"]
|
||||
Cell[18934, 534, 536, 16, 30, "Input",ExpressionUUID->"8674484a-8543-434f-b177-3b27f9353212"],
|
||||
Cell[19473, 552, 1705, 35, 87, "Output",ExpressionUUID->"c3b3f84d-91f6-41af-af6b-a394ca020511"]
|
||||
}, Open ]],
|
||||
Cell[21193, 590, 170, 3, 35, "Text",ExpressionUUID->"518a3040-54b1-4d43-8947-5c7d12efa94d"],
|
||||
Cell[CellGroupData[{
|
||||
Cell[10676, 306, 174, 3, 67, "Section",ExpressionUUID->"a5b064b3-3011-4922-8559-ead857cad102"],
|
||||
Cell[10853, 311, 535, 16, 52, "Input",ExpressionUUID->"aa28f02b-31e1-4df2-9b5d-482177464b59"],
|
||||
Cell[11391, 329, 250, 4, 35, "Text",ExpressionUUID->"c8896b88-f1db-4ce4-b7a6-0c9838bdb8f1"],
|
||||
Cell[11644, 335, 5511, 169, 425, "Input",ExpressionUUID->"52a96ff6-047e-4043-86d0-e303866e5f8e"],
|
||||
Cell[CellGroupData[{
|
||||
Cell[17180, 508, 2183, 58, 135, "Input",ExpressionUUID->"8b0f4955-2c3f-418c-9226-9be8f87621e8"],
|
||||
Cell[19366, 568, 1027, 27, 67, "Output",ExpressionUUID->"edd0619f-6f12-4070-a1d2-6b547877fadc"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[20430, 600, 1543, 46, 114, "Input",ExpressionUUID->"fb45123c-c610-4075-99b0-7cd71c728ae7"],
|
||||
Cell[21976, 648, 1311, 32, 98, "Output",ExpressionUUID->"2ae14565-b412-4dc0-9dce-bd6c1ba5ef27"]
|
||||
}, Open ]],
|
||||
Cell[23302, 683, 179, 3, 35, "Text",ExpressionUUID->"af247231-a58d-417b-987a-26908dafffdb"],
|
||||
Cell[23484, 688, 2175, 65, 94, "Input",ExpressionUUID->"7c44cadd-e488-4f51-87d8-c64eef11f40c"],
|
||||
Cell[25662, 755, 193, 3, 35, "Text",ExpressionUUID->"856f1746-1107-4509-a5ce-ac9c7f56cdb1"],
|
||||
Cell[CellGroupData[{
|
||||
Cell[25880, 762, 536, 16, 30, "Input",ExpressionUUID->"8674484a-8543-434f-b177-3b27f9353212"],
|
||||
Cell[26419, 780, 1705, 35, 87, "Output",ExpressionUUID->"c3b3f84d-91f6-41af-af6b-a394ca020511"]
|
||||
}, Open ]],
|
||||
Cell[28139, 818, 170, 3, 35, "Text",ExpressionUUID->"518a3040-54b1-4d43-8947-5c7d12efa94d"],
|
||||
Cell[CellGroupData[{
|
||||
Cell[28334, 825, 536, 14, 30, "Input",ExpressionUUID->"61a2e974-2b39-4a07-8043-2dfd39a70569"],
|
||||
Cell[28873, 841, 6754, 167, 303, "Output",ExpressionUUID->"73480ac0-3043-4077-80cc-b952a94c822a"]
|
||||
Cell[21388, 597, 536, 14, 30, "Input",ExpressionUUID->"61a2e974-2b39-4a07-8043-2dfd39a70569"],
|
||||
Cell[21927, 613, 6754, 167, 303, "Output",ExpressionUUID->"73480ac0-3043-4077-80cc-b952a94c822a"]
|
||||
}, Open ]]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[35676, 1014, 226, 4, 67, "Section",ExpressionUUID->"4e833cd6-9f0e-4aa3-a873-3d579e874720"],
|
||||
Cell[35905, 1020, 188, 4, 44, "Text",ExpressionUUID->"6d27fc04-3a60-4e03-8df7-3dd3aeee35b4"],
|
||||
Cell[36096, 1026, 2980, 53, 703, "Input",ExpressionUUID->"c7103bd6-b539-4495-b98c-d4d12ac6cad8"],
|
||||
Cell[39079, 1081, 221, 4, 44, "Text",ExpressionUUID->"0625593d-290f-4a39-9d80-8e2c6fdbc94e"],
|
||||
Cell[39303, 1087, 4936, 150, 682, "Input",ExpressionUUID->"1ad4904c-352f-4b1d-a7c7-91e1b0549409"],
|
||||
Cell[44242, 1239, 2645, 56, 199, "Input",ExpressionUUID->"0221674f-9b63-4662-91bc-ccc8c6ae9589"],
|
||||
Cell[46890, 1297, 209, 4, 44, "Text",ExpressionUUID->"d2d2257a-487b-416f-bc40-abd4482225f7"],
|
||||
Cell[47102, 1303, 15306, 397, 2131, "Input",ExpressionUUID->"daea68a9-c9e8-46ab-9bc8-5186e2cf477c"],
|
||||
Cell[62411, 1702, 137, 2, 44, "Text",ExpressionUUID->"76ba9d5a-7ee3-4888-be7e-6377003275e8"],
|
||||
Cell[62551, 1706, 521, 12, 30, "Input",ExpressionUUID->"4ec61f4c-3fd3-49ea-b5ef-6f7f04a16b34"]
|
||||
Cell[28730, 786, 226, 4, 67, "Section",ExpressionUUID->"4e833cd6-9f0e-4aa3-a873-3d579e874720"],
|
||||
Cell[28959, 792, 188, 4, 44, "Text",ExpressionUUID->"6d27fc04-3a60-4e03-8df7-3dd3aeee35b4"],
|
||||
Cell[29150, 798, 3104, 55, 724, "Input",ExpressionUUID->"c7103bd6-b539-4495-b98c-d4d12ac6cad8"],
|
||||
Cell[32257, 855, 221, 4, 44, "Text",ExpressionUUID->"0625593d-290f-4a39-9d80-8e2c6fdbc94e"],
|
||||
Cell[32481, 861, 4936, 150, 682, "Input",ExpressionUUID->"1ad4904c-352f-4b1d-a7c7-91e1b0549409"],
|
||||
Cell[37420, 1013, 2645, 56, 199, "Input",ExpressionUUID->"0221674f-9b63-4662-91bc-ccc8c6ae9589"],
|
||||
Cell[40068, 1071, 209, 4, 44, "Text",ExpressionUUID->"d2d2257a-487b-416f-bc40-abd4482225f7"],
|
||||
Cell[40280, 1077, 15306, 397, 2131, "Input",ExpressionUUID->"daea68a9-c9e8-46ab-9bc8-5186e2cf477c"],
|
||||
Cell[55589, 1476, 137, 2, 44, "Text",ExpressionUUID->"76ba9d5a-7ee3-4888-be7e-6377003275e8"],
|
||||
Cell[55729, 1480, 521, 12, 30, "Input",ExpressionUUID->"4ec61f4c-3fd3-49ea-b5ef-6f7f04a16b34"]
|
||||
}, Open ]],
|
||||
Cell[CellGroupData[{
|
||||
Cell[63109, 1723, 167, 2, 67, "Section",ExpressionUUID->"a4458b3a-09b5-4e36-a1fc-781d6702b2dc"],
|
||||
Cell[63279, 1727, 5693, 122, 829, "Input",ExpressionUUID->"b1b309f8-a3a7-4081-a781-c3845e3cd372"],
|
||||
Cell[68975, 1851, 448, 10, 30, "Input",ExpressionUUID->"cba42949-b0f2-42ce-aebd-ffadfd83ef88"],
|
||||
Cell[69426, 1863, 94, 1, 30, "Input",ExpressionUUID->"6175b72c-af9f-43c2-b4ca-bd84c48a456d"]
|
||||
Cell[56287, 1497, 167, 2, 67, "Section",ExpressionUUID->"a4458b3a-09b5-4e36-a1fc-781d6702b2dc"],
|
||||
Cell[56457, 1501, 6464, 133, 1207, "Input",ExpressionUUID->"b1b309f8-a3a7-4081-a781-c3845e3cd372"],
|
||||
Cell[62924, 1636, 448, 10, 30, "Input",ExpressionUUID->"cba42949-b0f2-42ce-aebd-ffadfd83ef88"],
|
||||
Cell[63375, 1648, 94, 1, 30, "Input",ExpressionUUID->"6175b72c-af9f-43c2-b4ca-bd84c48a456d"]
|
||||
}, Open ]]
|
||||
}
|
||||
]
|
||||
|
@ -995,21 +995,20 @@ void A2Autils<FImpl>::ContractWWVV(std::vector<PropagatorField> &WWVV,
|
||||
auto vs_v = vs[s].View();
|
||||
auto tmp1 = vs_v[ss];
|
||||
vobj tmp2 = Zero();
|
||||
|
||||
vobj tmp3 = Zero();
|
||||
for(int d=d_o;d<MIN(d_o+d_unroll,N_d);d++){
|
||||
Scalar_v coeff = WW_sd(t,s,d);
|
||||
auto vd_v = vd[d].View();
|
||||
mac(&tmp2 ,& coeff, & vd_v[ss]);
|
||||
Scalar_v coeff = WW_sd(t,s,d);
|
||||
tmp3 = conjugate(vd_v[ss]);
|
||||
mac(&tmp2, &coeff, &tmp3);
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Fast outer product of tmp1 with a sum of terms suppressed by d_unroll
|
||||
//////////////////////////
|
||||
tmp2 = conjugate(tmp2);
|
||||
auto WWVV_v = WWVV[t].View();
|
||||
for(int s1=0;s1<Ns;s1++){
|
||||
for(int s2=0;s2<Ns;s2++){
|
||||
|
||||
WWVV_v[ss]()(s1,s2)(0,0) += tmp1()(s1)(0)*tmp2()(s2)(0);
|
||||
WWVV_v[ss]()(s1,s2)(0,1) += tmp1()(s1)(0)*tmp2()(s2)(1);
|
||||
WWVV_v[ss]()(s1,s2)(0,2) += tmp1()(s1)(0)*tmp2()(s2)(2);
|
||||
|
87
Grid/qcd/utils/CovariantSmearing.h
Normal file
87
Grid/qcd/utils/CovariantSmearing.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./lib/qcd/action/scalar/CovariantLaplacian.h
|
||||
|
||||
Copyright (C) 2016
|
||||
|
||||
Author: Azusa Yamaguchi
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution
|
||||
directory
|
||||
*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
namespace Grid {
|
||||
namespace QCD {
|
||||
|
||||
template <class Gimpl> class CovariantSmearing : public Gimpl
|
||||
{
|
||||
public:
|
||||
INHERIT_GIMPL_TYPES(Gimpl);
|
||||
|
||||
typedef typename Gimpl::GaugeLinkField GaugeMat;
|
||||
typedef typename Gimpl::GaugeField GaugeLorentz;
|
||||
|
||||
template<typename T>
|
||||
static void GaussianSmear(const std::vector<LatticeColourMatrix>& U,
|
||||
T& chi,
|
||||
const Real& width, int Iterations, int orthog)
|
||||
{
|
||||
GridBase *grid = chi._grid;
|
||||
T psi(grid);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Follow Chroma conventions for width to keep compatibility with previous data
|
||||
// Free field iterates
|
||||
// chi = (1 - w^2/4N p^2)^N chi
|
||||
//
|
||||
// ~ (e^(-w^2/4N p^2)^N chi
|
||||
// ~ (e^(-w^2/4 p^2) chi
|
||||
// ~ (e^(-w'^2/2 p^2) chi [ w' = w/sqrt(2) ]
|
||||
//
|
||||
// Which in coordinate space is proportional to
|
||||
//
|
||||
// e^(-x^2/w^2) = e^(-x^2/2w'^2)
|
||||
//
|
||||
// The 4 is a bit unconventional from Gaussian width perspective, but... it's Chroma convention.
|
||||
// 2nd derivative approx d^2/dx^2 = x+mu + x-mu - 2x
|
||||
//
|
||||
// d^2/dx^2 = - p^2
|
||||
//
|
||||
// chi = ( 1 + w^2/4N d^2/dx^2 )^N chi
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
Real coeff = (width*width) / Real(4*Iterations);
|
||||
|
||||
int dims = Nd;
|
||||
if( orthog < Nd ) dims=Nd-1;
|
||||
|
||||
for(int n = 0; n < Iterations; ++n) {
|
||||
psi = (-2.0*dims)*chi;
|
||||
for(int mu=0;mu<Nd;mu++) {
|
||||
if ( mu != orthog ) {
|
||||
psi = psi + Gimpl::CovShiftForward(U[mu],mu,chi);
|
||||
psi = psi + Gimpl::CovShiftBackward(U[mu],mu,chi);
|
||||
}
|
||||
}
|
||||
chi = chi + coeff*psi;
|
||||
}
|
||||
}
|
||||
};
|
||||
}}
|
@ -31,6 +31,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
|
||||
template <class Gimpl>
|
||||
class FourierAcceleratedGaugeFixer : public Gimpl {
|
||||
public:
|
||||
@ -45,30 +46,57 @@ public:
|
||||
A[mu] = Ta(U[mu]) * cmi;
|
||||
}
|
||||
}
|
||||
static void DmuAmu(const std::vector<GaugeMat> &A,GaugeMat &dmuAmu) {
|
||||
static void DmuAmu(const std::vector<GaugeMat> &A,GaugeMat &dmuAmu,int orthog) {
|
||||
dmuAmu=Zero();
|
||||
for(int mu=0;mu<Nd;mu++){
|
||||
dmuAmu = dmuAmu + A[mu] - Cshift(A[mu],mu,-1);
|
||||
if ( mu != orthog ) {
|
||||
dmuAmu = dmuAmu + A[mu] - Cshift(A[mu],mu,-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void SteepestDescentGaugeFix(GaugeLorentz &Umu,Real & alpha,int maxiter,Real Omega_tol, Real Phi_tol,bool Fourier=false) {
|
||||
|
||||
static void SteepestDescentGaugeFix(GaugeLorentz &Umu,Real & alpha,int maxiter,Real Omega_tol, Real Phi_tol,bool Fourier=false,int orthog=-1) {
|
||||
GridBase *grid = Umu.Grid();
|
||||
GaugeMat xform(grid);
|
||||
SteepestDescentGaugeFix(Umu,xform,alpha,maxiter,Omega_tol,Phi_tol,Fourier,orthog);
|
||||
}
|
||||
static void SteepestDescentGaugeFix(GaugeLorentz &Umu,GaugeMat &xform,Real & alpha,int maxiter,Real Omega_tol, Real Phi_tol,bool Fourier=false,int orthog=-1) {
|
||||
|
||||
GridBase *grid = Umu.Grid();
|
||||
|
||||
Real org_plaq =WilsonLoops<Gimpl>::avgPlaquette(Umu);
|
||||
Real org_link_trace=WilsonLoops<Gimpl>::linkTrace(Umu);
|
||||
Real old_trace = org_link_trace;
|
||||
Real trG;
|
||||
|
||||
xform=1.0;
|
||||
|
||||
std::vector<GaugeMat> U(Nd,grid);
|
||||
GaugeMat dmuAmu(grid);
|
||||
|
||||
for(int i=0;i<maxiter;i++){
|
||||
for(int mu=0;mu<Nd;mu++) U[mu]= PeekIndex<LorentzIndex>(Umu,mu);
|
||||
if ( Fourier==false ) {
|
||||
trG = SteepestDescentStep(U,alpha,dmuAmu);
|
||||
{
|
||||
Real plaq =WilsonLoops<Gimpl>::avgPlaquette(Umu);
|
||||
Real link_trace=WilsonLoops<Gimpl>::linkTrace(Umu);
|
||||
if( (orthog>=0) && (orthog<Nd) ){
|
||||
std::cout << GridLogMessage << " Gauge fixing to Coulomb gauge time="<<orthog<< " plaq= "<<plaq<<" link trace = "<<link_trace<< std::endl;
|
||||
} else {
|
||||
trG = FourierAccelSteepestDescentStep(U,alpha,dmuAmu);
|
||||
std::cout << GridLogMessage << " Gauge fixing to Landau gauge plaq= "<<plaq<<" link trace = "<<link_trace<< std::endl;
|
||||
}
|
||||
}
|
||||
for(int i=0;i<maxiter;i++){
|
||||
|
||||
for(int mu=0;mu<Nd;mu++) U[mu]= PeekIndex<LorentzIndex>(Umu,mu);
|
||||
|
||||
if ( Fourier==false ) {
|
||||
trG = SteepestDescentStep(U,xform,alpha,dmuAmu,orthog);
|
||||
} else {
|
||||
trG = FourierAccelSteepestDescentStep(U,xform,alpha,dmuAmu,orthog);
|
||||
}
|
||||
|
||||
// std::cout << GridLogMessage << "trG "<< trG<< std::endl;
|
||||
// std::cout << GridLogMessage << "xform "<< norm2(xform)<< std::endl;
|
||||
// std::cout << GridLogMessage << "dmuAmu "<< norm2(dmuAmu)<< std::endl;
|
||||
|
||||
for(int mu=0;mu<Nd;mu++) PokeIndex<LorentzIndex>(Umu,U[mu],mu);
|
||||
// Monitor progress and convergence test
|
||||
// infrequently to minimise cost overhead
|
||||
@ -84,7 +112,6 @@ public:
|
||||
Real Phi = 1.0 - old_trace / link_trace ;
|
||||
Real Omega= 1.0 - trG;
|
||||
|
||||
|
||||
std::cout << GridLogMessage << " Iteration "<<i<< " Phi= "<<Phi<< " Omega= " << Omega<< " trG " << trG <<std::endl;
|
||||
if ( (Omega < Omega_tol) && ( ::fabs(Phi) < Phi_tol) ) {
|
||||
std::cout << GridLogMessage << "Converged ! "<<std::endl;
|
||||
@ -96,25 +123,26 @@ public:
|
||||
}
|
||||
}
|
||||
};
|
||||
static Real SteepestDescentStep(std::vector<GaugeMat> &U,Real & alpha, GaugeMat & dmuAmu) {
|
||||
static Real SteepestDescentStep(std::vector<GaugeMat> &U,GaugeMat &xform,Real & alpha, GaugeMat & dmuAmu,int orthog) {
|
||||
GridBase *grid = U[0].Grid();
|
||||
|
||||
std::vector<GaugeMat> A(Nd,grid);
|
||||
GaugeMat g(grid);
|
||||
|
||||
GaugeLinkToLieAlgebraField(U,A);
|
||||
ExpiAlphaDmuAmu(A,g,alpha,dmuAmu);
|
||||
ExpiAlphaDmuAmu(A,g,alpha,dmuAmu,orthog);
|
||||
|
||||
|
||||
Real vol = grid->gSites();
|
||||
Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc;
|
||||
|
||||
xform = g*xform ;
|
||||
SU<Nc>::GaugeTransform(U,g);
|
||||
|
||||
return trG;
|
||||
}
|
||||
|
||||
static Real FourierAccelSteepestDescentStep(std::vector<GaugeMat> &U,Real & alpha, GaugeMat & dmuAmu) {
|
||||
static Real FourierAccelSteepestDescentStep(std::vector<GaugeMat> &U,GaugeMat &xform,Real & alpha, GaugeMat & dmuAmu,int orthog) {
|
||||
|
||||
GridBase *grid = U[0].Grid();
|
||||
|
||||
@ -133,38 +161,41 @@ public:
|
||||
|
||||
GaugeLinkToLieAlgebraField(U,A);
|
||||
|
||||
DmuAmu(A,dmuAmu);
|
||||
DmuAmu(A,dmuAmu,orthog);
|
||||
|
||||
theFFT.FFT_all_dim(dmuAmu_p,dmuAmu,FFT::forward);
|
||||
std::vector<int> mask(Nd,1);
|
||||
for(int mu=0;mu<Nd;mu++) if (mu==orthog) mask[mu]=0;
|
||||
theFFT.FFT_dim_mask(dmuAmu_p,dmuAmu,mask,FFT::forward);
|
||||
|
||||
//////////////////////////////////
|
||||
// Work out Fp = psq_max/ psq...
|
||||
// Avoid singularities in Fp
|
||||
//////////////////////////////////
|
||||
Coordinate latt_size = grid->GlobalDimensions();
|
||||
Coordinate coor(grid->_ndimension,0);
|
||||
for(int mu=0;mu<Nd;mu++) {
|
||||
|
||||
Real TwoPiL = M_PI * 2.0/ latt_size[mu];
|
||||
LatticeCoordinate(pmu,mu);
|
||||
pmu = TwoPiL * pmu ;
|
||||
psq = psq + 4.0*sin(pmu*0.5)*sin(pmu*0.5);
|
||||
if ( mu != orthog ) {
|
||||
Real TwoPiL = M_PI * 2.0/ latt_size[mu];
|
||||
LatticeCoordinate(pmu,mu);
|
||||
pmu = TwoPiL * pmu ;
|
||||
psq = psq + 4.0*sin(pmu*0.5)*sin(pmu*0.5);
|
||||
}
|
||||
}
|
||||
|
||||
Complex psqMax(16.0);
|
||||
Fp = psqMax*one/psq;
|
||||
|
||||
/*
|
||||
static int once;
|
||||
if ( once == 0 ) {
|
||||
std::cout << " Fp " << Fp <<std::endl;
|
||||
once ++;
|
||||
}*/
|
||||
|
||||
pokeSite(TComplex(1.0),Fp,coor);
|
||||
|
||||
pokeSite(TComplex(16.0),Fp,coor);
|
||||
if( (orthog>=0) && (orthog<Nd) ){
|
||||
for(int t=0;t<grid->GlobalDimensions()[orthog];t++){
|
||||
coor[orthog]=t;
|
||||
pokeSite(TComplex(16.0),Fp,coor);
|
||||
}
|
||||
}
|
||||
|
||||
dmuAmu_p = dmuAmu_p * Fp;
|
||||
|
||||
theFFT.FFT_all_dim(dmuAmu,dmuAmu_p,FFT::backward);
|
||||
theFFT.FFT_dim_mask(dmuAmu,dmuAmu_p,mask,FFT::backward);
|
||||
|
||||
GaugeMat ciadmam(grid);
|
||||
Complex cialpha(0.0,-alpha);
|
||||
@ -173,16 +204,17 @@ public:
|
||||
|
||||
Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc;
|
||||
|
||||
xform = g*xform ;
|
||||
SU<Nc>::GaugeTransform(U,g);
|
||||
|
||||
return trG;
|
||||
}
|
||||
|
||||
static void ExpiAlphaDmuAmu(const std::vector<GaugeMat> &A,GaugeMat &g,Real & alpha, GaugeMat &dmuAmu) {
|
||||
static void ExpiAlphaDmuAmu(const std::vector<GaugeMat> &A,GaugeMat &g,Real & alpha, GaugeMat &dmuAmu,int orthog) {
|
||||
GridBase *grid = g.Grid();
|
||||
Complex cialpha(0.0,-alpha);
|
||||
GaugeMat ciadmam(grid);
|
||||
DmuAmu(A,dmuAmu);
|
||||
DmuAmu(A,dmuAmu,orthog);
|
||||
ciadmam = dmuAmu*cialpha;
|
||||
SU<Nc>::taExp(ciadmam,g);
|
||||
}
|
||||
|
@ -678,9 +678,18 @@ public:
|
||||
out += la;
|
||||
}
|
||||
}
|
||||
/*
|
||||
add GaugeTrans
|
||||
*/
|
||||
/*
|
||||
* Fundamental rep gauge xform
|
||||
*/
|
||||
template<typename Fundamental,typename GaugeMat>
|
||||
static void GaugeTransformFundamental( Fundamental &ferm, GaugeMat &g){
|
||||
GridBase *grid = ferm._grid;
|
||||
conformable(grid,g._grid);
|
||||
ferm = g*ferm;
|
||||
}
|
||||
/*
|
||||
* Adjoint rep gauge xform
|
||||
*/
|
||||
|
||||
template<typename GaugeField,typename GaugeMat>
|
||||
static void GaugeTransform( GaugeField &Umu, GaugeMat &g){
|
||||
|
@ -33,12 +33,76 @@ Author: Guido Cossu <guido.cossu@ed.ac.uk>
|
||||
#include <type_traits>
|
||||
#include <Grid/tensors/Tensors.h>
|
||||
#include <Grid/serialisation/VectorUtils.h>
|
||||
#include <Grid/Eigen/unsupported/CXX11/Tensor>
|
||||
|
||||
namespace Grid {
|
||||
namespace EigenIO {
|
||||
// EigenIO works for scalars that are not just Grid supported scalars
|
||||
template<typename T, typename V = void> struct is_complex : public std::false_type {};
|
||||
// Support all complex types (not just Grid complex types) - even if the definitions overlap (!)
|
||||
template<typename T> struct is_complex< T , typename
|
||||
std::enable_if< ::Grid::is_complex< T >::value>::type> : public std::true_type {};
|
||||
template<typename T> struct is_complex<std::complex<T>, typename
|
||||
std::enable_if<!::Grid::is_complex<std::complex<T>>::value>::type> : public std::true_type {};
|
||||
|
||||
// Helpers to support I/O for Eigen tensors of arithmetic scalars, complex types, or Grid tensors
|
||||
template<typename T, typename V = void> struct is_scalar : public std::false_type {};
|
||||
template<typename T> struct is_scalar<T, typename std::enable_if<std::is_arithmetic<T>::value || is_complex<T>::value>::type> : public std::true_type {};
|
||||
|
||||
// Is this an Eigen tensor
|
||||
template<typename T> struct is_tensor : std::integral_constant<bool,
|
||||
std::is_base_of<Eigen::TensorBase<T, Eigen::ReadOnlyAccessors>, T>::value> {};
|
||||
|
||||
// Is this an Eigen tensor of a supported scalar
|
||||
template<typename T, typename V = void> struct is_tensor_of_scalar : public std::false_type {};
|
||||
template<typename T> struct is_tensor_of_scalar<T, typename std::enable_if<is_tensor<T>::value && is_scalar<typename T::Scalar>::value>::type> : public std::true_type {};
|
||||
|
||||
// Is this an Eigen tensor of a supported container
|
||||
template<typename T, typename V = void> struct is_tensor_of_container : public std::false_type {};
|
||||
template<typename T> struct is_tensor_of_container<T, typename std::enable_if<is_tensor<T>::value && isGridTensor<typename T::Scalar>::value>::type> : public std::true_type {};
|
||||
|
||||
// These traits describe the scalars inside Eigen tensors
|
||||
// I wish I could define these in reference to the scalar type (so there would be fewer traits defined)
|
||||
// but I'm unable to find a syntax to make this work
|
||||
template<typename T, typename V = void> struct Traits {};
|
||||
// Traits are the default for scalars, or come from GridTypeMapper for GridTensors
|
||||
template<typename T> struct Traits<T, typename std::enable_if<is_tensor_of_scalar<T>::value>::type>
|
||||
: public GridTypeMapper_Base {
|
||||
using scalar_type = typename T::Scalar; // ultimate base scalar
|
||||
static constexpr bool is_complex = ::Grid::EigenIO::is_complex<scalar_type>::value;
|
||||
};
|
||||
// Traits are the default for scalars, or come from GridTypeMapper for GridTensors
|
||||
template<typename T> struct Traits<T, typename std::enable_if<is_tensor_of_container<T>::value>::type> {
|
||||
using BaseTraits = GridTypeMapper<typename T::Scalar>;
|
||||
using scalar_type = typename BaseTraits::scalar_type; // ultimate base scalar
|
||||
static constexpr bool is_complex = ::Grid::EigenIO::is_complex<scalar_type>::value;
|
||||
static constexpr int TensorLevel = BaseTraits::TensorLevel;
|
||||
static constexpr int Rank = BaseTraits::Rank;
|
||||
static constexpr std::size_t count = BaseTraits::count;
|
||||
static constexpr int Dimension(int dim) { return BaseTraits::Dimension(dim); }
|
||||
};
|
||||
|
||||
// Is this a fixed-size Eigen tensor
|
||||
template<typename T> struct is_tensor_fixed : public std::false_type {};
|
||||
template<typename Scalar_, typename Dimensions_, int Options_, typename IndexType>
|
||||
struct is_tensor_fixed<Eigen::TensorFixedSize<Scalar_, Dimensions_, Options_, IndexType>>
|
||||
: public std::true_type {};
|
||||
template<typename Scalar_, typename Dimensions_, int Options_, typename IndexType,
|
||||
int MapOptions_, template <class> class MapPointer_>
|
||||
struct is_tensor_fixed<Eigen::TensorMap<Eigen::TensorFixedSize<Scalar_, Dimensions_,
|
||||
Options_, IndexType>, MapOptions_, MapPointer_>>
|
||||
: public std::true_type {};
|
||||
|
||||
// Is this a variable-size Eigen tensor
|
||||
template<typename T, typename V = void> struct is_tensor_variable : public std::false_type {};
|
||||
template<typename T> struct is_tensor_variable<T, typename std::enable_if<is_tensor<T>::value
|
||||
&& !is_tensor_fixed<T>::value>::type> : public std::true_type {};
|
||||
}
|
||||
|
||||
// Abstract writer/reader classes ////////////////////////////////////////////
|
||||
// static polymorphism implemented using CRTP idiom
|
||||
class Serializable;
|
||||
|
||||
|
||||
// Static abstract writer
|
||||
template <typename T>
|
||||
class Writer
|
||||
@ -49,10 +113,10 @@ namespace Grid {
|
||||
void push(const std::string &s);
|
||||
void pop(void);
|
||||
template <typename U>
|
||||
typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<std::is_base_of<Serializable, U>::value>::type
|
||||
write(const std::string& s, const U &output);
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value && !EigenIO::is_tensor<U>::value>::type
|
||||
write(const std::string& s, const U &output);
|
||||
template <typename U>
|
||||
void write(const std::string &s, const iScalar<U> &output);
|
||||
@ -60,6 +124,42 @@ namespace Grid {
|
||||
void write(const std::string &s, const iVector<U, N> &output);
|
||||
template <typename U, int N>
|
||||
void write(const std::string &s, const iMatrix<U, N> &output);
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor<ETensor>::value>::type
|
||||
write(const std::string &s, const ETensor &output);
|
||||
|
||||
// Helper functions for Scalar vs Container specialisations
|
||||
template <typename ETensor>
|
||||
inline typename std::enable_if<EigenIO::is_tensor_of_scalar<ETensor>::value,
|
||||
const typename ETensor::Scalar *>::type
|
||||
getFirstScalar(const ETensor &output)
|
||||
{
|
||||
return output.data();
|
||||
}
|
||||
|
||||
template <typename ETensor>
|
||||
inline typename std::enable_if<EigenIO::is_tensor_of_container<ETensor>::value,
|
||||
const typename EigenIO::Traits<ETensor>::scalar_type *>::type
|
||||
getFirstScalar(const ETensor &output)
|
||||
{
|
||||
return output.data()->begin();
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline typename std::enable_if<EigenIO::is_scalar<S>::value, void>::type
|
||||
copyScalars(S * &pCopy, const S &Source)
|
||||
{
|
||||
* pCopy ++ = Source;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline typename std::enable_if<isGridTensor<S>::value, void>::type
|
||||
copyScalars(typename GridTypeMapper<S>::scalar_type * &pCopy, const S &Source)
|
||||
{
|
||||
for( const typename GridTypeMapper<S>::scalar_type &item : Source )
|
||||
* pCopy ++ = item;
|
||||
}
|
||||
|
||||
void scientificFormat(const bool set);
|
||||
bool isScientific(void);
|
||||
void setPrecision(const unsigned int prec);
|
||||
@ -83,7 +183,8 @@ namespace Grid {
|
||||
typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
|
||||
read(const std::string& s, U &output);
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value
|
||||
&& !EigenIO::is_tensor<U>::value, void>::type
|
||||
read(const std::string& s, U &output);
|
||||
template <typename U>
|
||||
void read(const std::string &s, iScalar<U> &output);
|
||||
@ -91,6 +192,32 @@ namespace Grid {
|
||||
void read(const std::string &s, iVector<U, N> &output);
|
||||
template <typename U, int N>
|
||||
void read(const std::string &s, iMatrix<U, N> &output);
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
|
||||
read(const std::string &s, ETensor &output);
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor_fixed<ETensor>::value, void>::type
|
||||
Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims );
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor_variable<ETensor>::value, void>::type
|
||||
Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims );
|
||||
|
||||
// Helper functions for Scalar vs Container specialisations
|
||||
template <typename S>
|
||||
inline typename std::enable_if<EigenIO::is_scalar<S>::value, void>::type
|
||||
copyScalars(S &Dest, const S * &pSource)
|
||||
{
|
||||
Dest = * pSource ++;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline typename std::enable_if<isGridTensor<S>::value, void>::type
|
||||
copyScalars(S &Dest, const typename GridTypeMapper<S>::scalar_type * &pSource)
|
||||
{
|
||||
for( typename GridTypeMapper<S>::scalar_type &item : Dest )
|
||||
item = * pSource ++;
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename U>
|
||||
void fromString(U &output, const std::string &s);
|
||||
@ -135,12 +262,14 @@ namespace Grid {
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value
|
||||
&& !EigenIO::is_tensor<U>::value, void>::type
|
||||
Writer<T>::write(const std::string &s, const U &output)
|
||||
{
|
||||
upcast->writeDefault(s, output);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
void Writer<T>::write(const std::string &s, const iScalar<U> &output)
|
||||
@ -161,6 +290,57 @@ namespace Grid {
|
||||
{
|
||||
upcast->writeDefault(s, tensorToVec(output));
|
||||
}
|
||||
|
||||
// Eigen::Tensors of Grid tensors (iScalar, iVector, iMatrix)
|
||||
template <typename T>
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
|
||||
Writer<T>::write(const std::string &s, const ETensor &output)
|
||||
{
|
||||
using Index = typename ETensor::Index;
|
||||
using Container = typename ETensor::Scalar; // NB: could be same as scalar
|
||||
using Traits = EigenIO::Traits<ETensor>;
|
||||
using Scalar = typename Traits::scalar_type; // type of the underlying scalar
|
||||
constexpr unsigned int TensorRank{ETensor::NumIndices};
|
||||
constexpr unsigned int ContainerRank{Traits::Rank}; // Only non-zero for containers
|
||||
constexpr unsigned int TotalRank{TensorRank + ContainerRank};
|
||||
const Index NumElements{output.size()};
|
||||
assert( NumElements > 0 );
|
||||
|
||||
// Get the dimensionality of the tensor
|
||||
std::vector<std::size_t> TotalDims(TotalRank);
|
||||
for(auto i = 0; i < TensorRank; i++ ) {
|
||||
auto dim = output.dimension(i);
|
||||
TotalDims[i] = static_cast<size_t>(dim);
|
||||
assert( TotalDims[i] == dim ); // check we didn't lose anything in the conversion
|
||||
}
|
||||
for(auto i = 0; i < ContainerRank; i++ )
|
||||
TotalDims[TensorRank + i] = Traits::Dimension(i);
|
||||
|
||||
// If the Tensor isn't in Row-Major order, then we'll need to copy it's data
|
||||
const bool CopyData{NumElements > 1 && ETensor::Layout != Eigen::StorageOptions::RowMajor};
|
||||
const Scalar * pWriteBuffer;
|
||||
std::vector<Scalar> CopyBuffer;
|
||||
const Index TotalNumElements = NumElements * Traits::count;
|
||||
if( !CopyData ) {
|
||||
pWriteBuffer = getFirstScalar( output );
|
||||
} else {
|
||||
// Regardless of the Eigen::Tensor storage order, the copy will be Row Major
|
||||
CopyBuffer.resize( TotalNumElements );
|
||||
Scalar * pCopy = &CopyBuffer[0];
|
||||
pWriteBuffer = pCopy;
|
||||
std::array<Index, TensorRank> MyIndex;
|
||||
for( auto &idx : MyIndex ) idx = 0;
|
||||
for( auto n = 0; n < NumElements; n++ ) {
|
||||
const Container & c = output( MyIndex );
|
||||
copyScalars( pCopy, c );
|
||||
// Now increment the index
|
||||
for( int i = output.NumDimensions - 1; i >= 0 && ++MyIndex[i] == output.dimension(i); i-- )
|
||||
MyIndex[i] = 0;
|
||||
}
|
||||
}
|
||||
upcast->template writeMultiDim<Scalar>(s, TotalDims, pWriteBuffer, TotalNumElements);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Writer<T>::scientificFormat(const bool set)
|
||||
@ -215,7 +395,8 @@ namespace Grid {
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
|
||||
typename std::enable_if<!std::is_base_of<Serializable, U>::value
|
||||
&& !EigenIO::is_tensor<U>::value, void>::type
|
||||
Reader<T>::read(const std::string &s, U &output)
|
||||
{
|
||||
upcast->readDefault(s, output);
|
||||
@ -251,6 +432,79 @@ namespace Grid {
|
||||
vecToTensor(output, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor<ETensor>::value, void>::type
|
||||
Reader<T>::read(const std::string &s, ETensor &output)
|
||||
{
|
||||
using Index = typename ETensor::Index;
|
||||
using Container = typename ETensor::Scalar; // NB: could be same as scalar
|
||||
using Traits = EigenIO::Traits<ETensor>;
|
||||
using Scalar = typename Traits::scalar_type; // type of the underlying scalar
|
||||
constexpr unsigned int TensorRank{ETensor::NumIndices};
|
||||
constexpr unsigned int ContainerRank{Traits::Rank}; // Only non-zero for containers
|
||||
constexpr unsigned int TotalRank{TensorRank + ContainerRank};
|
||||
using ETDims = std::array<Index, TensorRank>; // Dimensions of the tensor
|
||||
|
||||
// read the (flat) data and dimensionality
|
||||
std::vector<std::size_t> dimData;
|
||||
std::vector<Scalar> buf;
|
||||
upcast->readMultiDim( s, buf, dimData );
|
||||
assert(dimData.size() == TotalRank && "EigenIO: Tensor rank mismatch" );
|
||||
// Make sure that the number of elements read matches dimensions read
|
||||
std::size_t NumContainers = 1;
|
||||
for( auto i = 0 ; i < TensorRank ; i++ )
|
||||
NumContainers *= dimData[i];
|
||||
// If our scalar object is a Container, make sure it's dimensions match what we read back
|
||||
std::size_t ElementsPerContainer = 1;
|
||||
for( auto i = 0 ; i < ContainerRank ; i++ ) {
|
||||
assert( dimData[TensorRank+i] == Traits::Dimension(i) && "Tensor Container dimensions don't match data" );
|
||||
ElementsPerContainer *= dimData[TensorRank+i];
|
||||
}
|
||||
assert( NumContainers * ElementsPerContainer == buf.size() && "EigenIO: Number of elements != product of dimensions" );
|
||||
// Now see whether the tensor is the right shape, or can be made to be
|
||||
const auto & dims = output.dimensions();
|
||||
bool bShapeOK = (output.data() != nullptr);
|
||||
for( auto i = 0; bShapeOK && i < TensorRank ; i++ )
|
||||
if( dims[i] != dimData[i] )
|
||||
bShapeOK = false;
|
||||
// Make the tensor the same size as the data read
|
||||
ETDims MyIndex;
|
||||
if( !bShapeOK ) {
|
||||
for( auto i = 0 ; i < TensorRank ; i++ )
|
||||
MyIndex[i] = dimData[i];
|
||||
Reshape(output, MyIndex);
|
||||
}
|
||||
// Copy the data into the tensor
|
||||
for( auto &d : MyIndex ) d = 0;
|
||||
const Scalar * pSource = &buf[0];
|
||||
for( std::size_t n = 0 ; n < NumContainers ; n++ ) {
|
||||
Container & c = output( MyIndex );
|
||||
copyScalars( c, pSource );
|
||||
// Now increment the index
|
||||
for( int i = TensorRank - 1; i != -1 && ++MyIndex[i] == dims[i]; i-- )
|
||||
MyIndex[i] = 0;
|
||||
}
|
||||
assert( pSource == &buf[NumContainers * ElementsPerContainer] );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor_fixed<ETensor>::value, void>::type
|
||||
Reader<T>::Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims )
|
||||
{
|
||||
assert( 0 && "EigenIO: Fixed tensor dimensions can't be changed" );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename ETensor>
|
||||
typename std::enable_if<EigenIO::is_tensor_variable<ETensor>::value, void>::type
|
||||
Reader<T>::Reshape(ETensor &t, const std::array<typename ETensor::Index, ETensor::NumDimensions> &dims )
|
||||
{
|
||||
//t.reshape( dims );
|
||||
t.resize( dims );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
void Reader<T>::fromString(U &output, const std::string &s)
|
||||
@ -289,8 +543,70 @@ namespace Grid {
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
static inline typename std::enable_if<!EigenIO::is_tensor<T1>::value || !EigenIO::is_tensor<T2>::value, bool>::type
|
||||
CompareMember(const T1 &lhs, const T2 &rhs) {
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
static inline typename std::enable_if<EigenIO::is_tensor<T1>::value && EigenIO::is_tensor<T2>::value, bool>::type
|
||||
CompareMember(const T1 &lhs, const T2 &rhs) {
|
||||
// First check whether dimensions match (Eigen tensor library will assert if they don't match)
|
||||
bool bReturnValue = (T1::NumIndices == T2::NumIndices);
|
||||
for( auto i = 0 ; bReturnValue && i < T1::NumIndices ; i++ )
|
||||
bReturnValue = ( lhs.dimension(i) == rhs.dimension(i) );
|
||||
if( bReturnValue ) {
|
||||
Eigen::Tensor<bool, 0, T1::Options> bResult = (lhs == rhs).all();
|
||||
bReturnValue = bResult(0);
|
||||
}
|
||||
return bReturnValue;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline typename std::enable_if<EigenIO::is_tensor<T>::value, bool>::type
|
||||
CompareMember(const std::vector<T> &lhs, const std::vector<T> &rhs) {
|
||||
const auto NumElements = lhs.size();
|
||||
bool bResult = ( NumElements == rhs.size() );
|
||||
for( auto i = 0 ; i < NumElements && bResult ; i++ )
|
||||
bResult = CompareMember(lhs[i], rhs[i]);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline typename std::enable_if<!EigenIO::is_tensor<T>::value, void>::type
|
||||
WriteMember(std::ostream &os, const T &object) {
|
||||
os << object;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline typename std::enable_if<EigenIO::is_tensor<T>::value, void>::type
|
||||
WriteMember(std::ostream &os, const T &object) {
|
||||
using Index = typename T::Index;
|
||||
const Index NumElements{object.size()};
|
||||
assert( NumElements > 0 );
|
||||
Index count = 1;
|
||||
os << "T<";
|
||||
for( int i = 0; i < T::NumIndices; i++ ) {
|
||||
Index dim = object.dimension(i);
|
||||
count *= dim;
|
||||
if( i )
|
||||
os << ",";
|
||||
os << dim;
|
||||
}
|
||||
assert( count == NumElements && "Number of elements doesn't match tensor dimensions" );
|
||||
os << ">{";
|
||||
const typename T::Scalar * p = object.data();
|
||||
for( Index i = 0; i < count; i++ ) {
|
||||
if( i )
|
||||
os << ",";
|
||||
os << *p++;
|
||||
}
|
||||
os << "}";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Generic writer interface //////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline void push(Writer<T> &w, const std::string &s) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*************************************************************************************
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
@ -24,8 +24,8 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef GRID_SERIALISATION_BINARY_READER_H
|
||||
#define GRID_SERIALISATION_BINARY_READER_H
|
||||
|
||||
@ -37,83 +37,132 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
namespace Grid {
|
||||
|
||||
class BinaryWriter: public Writer<BinaryWriter>
|
||||
{
|
||||
public:
|
||||
BinaryWriter(const std::string &fileName);
|
||||
virtual ~BinaryWriter(void) = default;
|
||||
void push(const std::string &s) {};
|
||||
void pop(void) {};
|
||||
class BinaryWriter: public Writer<BinaryWriter>
|
||||
{
|
||||
public:
|
||||
BinaryWriter(const std::string &fileName);
|
||||
virtual ~BinaryWriter(void) = default;
|
||||
void push(const std::string &s) {};
|
||||
void pop(void) {};
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const U &x);
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
void writeDefault(const std::string &s, const char *x);
|
||||
template <typename U>
|
||||
void writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements);
|
||||
private:
|
||||
std::ofstream file_;
|
||||
};
|
||||
|
||||
class BinaryReader: public Reader<BinaryReader>
|
||||
{
|
||||
public:
|
||||
BinaryReader(const std::string &fileName);
|
||||
virtual ~BinaryReader(void) = default;
|
||||
bool push(const std::string &s) {return true;}
|
||||
void pop(void) {};
|
||||
template <typename U>
|
||||
void readDefault(const std::string &s, U &output);
|
||||
template <typename U>
|
||||
void readDefault(const std::string &s, std::vector<U> &output);
|
||||
template <typename U>
|
||||
void readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim);
|
||||
private:
|
||||
std::ifstream file_;
|
||||
};
|
||||
|
||||
// Writer template implementation ////////////////////////////////////////////
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const U &x);
|
||||
void BinaryWriter::writeDefault(const std::string &s, const U &x)
|
||||
{
|
||||
file_.write((char *)&x, sizeof(U));
|
||||
}
|
||||
|
||||
template <>
|
||||
void BinaryWriter::writeDefault(const std::string &s, const std::string &x);
|
||||
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
void writeDefault(const std::string &s, const char *x);
|
||||
private:
|
||||
std::ofstream file_;
|
||||
};
|
||||
|
||||
class BinaryReader: public Reader<BinaryReader>
|
||||
{
|
||||
public:
|
||||
BinaryReader(const std::string &fileName);
|
||||
virtual ~BinaryReader(void) = default;
|
||||
bool push(const std::string &s) {return true;}
|
||||
void pop(void) {};
|
||||
template <typename U>
|
||||
void readDefault(const std::string &s, U &output);
|
||||
template <typename U>
|
||||
void readDefault(const std::string &s, std::vector<U> &output);
|
||||
private:
|
||||
std::ifstream file_;
|
||||
};
|
||||
|
||||
// Writer template implementation ////////////////////////////////////////////
|
||||
template <typename U>
|
||||
void BinaryWriter::writeDefault(const std::string &s, const U &x)
|
||||
{
|
||||
file_.write((char *)&x, sizeof(U));
|
||||
}
|
||||
|
||||
template <>
|
||||
void BinaryWriter::writeDefault(const std::string &s, const std::string &x);
|
||||
|
||||
template <typename U>
|
||||
void BinaryWriter::writeDefault(const std::string &s, const std::vector<U> &x)
|
||||
{
|
||||
uint64_t sz = x.size();
|
||||
void BinaryWriter::writeDefault(const std::string &s, const std::vector<U> &x)
|
||||
{
|
||||
uint64_t sz = x.size();
|
||||
|
||||
write("", sz);
|
||||
for (uint64_t i = 0; i < sz; ++i)
|
||||
write("", sz);
|
||||
for (uint64_t i = 0; i < sz; ++i)
|
||||
{
|
||||
write("", x[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reader template implementation ////////////////////////////////////////////
|
||||
template <> void BinaryReader::readDefault(const std::string &s, std::string &output);
|
||||
template <typename U>
|
||||
void BinaryWriter::writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements)
|
||||
{
|
||||
uint64_t rank = static_cast<uint64_t>( Dimensions.size() );
|
||||
uint64_t tmp = 1;
|
||||
for( auto i = 0 ; i < rank ; i++ )
|
||||
tmp *= Dimensions[i];
|
||||
assert( tmp == NumElements && "Dimensions don't match size of data being written" );
|
||||
// Total number of elements
|
||||
write("", tmp);
|
||||
// Number of dimensions
|
||||
write("", rank);
|
||||
// Followed by each dimension
|
||||
for( auto i = 0 ; i < rank ; i++ ) {
|
||||
tmp = Dimensions[i];
|
||||
write("", tmp);
|
||||
}
|
||||
for( auto i = 0; i < NumElements; ++i)
|
||||
write("", pDataRowMajor[i]);
|
||||
}
|
||||
|
||||
// Reader template implementation ////////////////////////////////////////////
|
||||
template <typename U>
|
||||
void BinaryReader::readDefault(const std::string &s, U &output)
|
||||
{
|
||||
file_.read((char *)&output, sizeof(U));
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void BinaryReader::readDefault(const std::string &s, U &output)
|
||||
{
|
||||
file_.read((char *)&output, sizeof(U));
|
||||
}
|
||||
template <>
|
||||
void BinaryReader::readDefault(const std::string &s, std::string &output);
|
||||
|
||||
template <typename U>
|
||||
void BinaryReader::readDefault(const std::string &s, std::vector<U> &output)
|
||||
{
|
||||
uint64_t sz;
|
||||
template <typename U>
|
||||
void BinaryReader::readDefault(const std::string &s, std::vector<U> &output)
|
||||
{
|
||||
uint64_t sz;
|
||||
|
||||
read("", sz);
|
||||
output.resize(sz);
|
||||
for (uint64_t i = 0; i < sz; ++i)
|
||||
read("", sz);
|
||||
output.resize(sz);
|
||||
for (uint64_t i = 0; i < sz; ++i)
|
||||
{
|
||||
read("", output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void BinaryReader::readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim)
|
||||
{
|
||||
// Number of elements
|
||||
uint64_t NumElements;
|
||||
read("", NumElements);
|
||||
// Number of dimensions
|
||||
uint64_t rank;
|
||||
read("", rank);
|
||||
// Followed by each dimension
|
||||
uint64_t count = 1;
|
||||
dim.resize(rank);
|
||||
uint64_t tmp;
|
||||
for( auto i = 0 ; i < rank ; i++ ) {
|
||||
read("", tmp);
|
||||
dim[i] = tmp;
|
||||
count *= tmp;
|
||||
}
|
||||
assert( count == NumElements && "Dimensions don't match size of data being read" );
|
||||
buf.resize(count);
|
||||
for( auto i = 0; i < count; ++i)
|
||||
read("", buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <H5Cpp.h>
|
||||
#include <Grid/tensors/Tensors.h>
|
||||
@ -38,6 +39,8 @@ namespace Grid
|
||||
template <typename U>
|
||||
typename std::enable_if<!element<std::vector<U>>::is_number, void>::type
|
||||
writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
template <typename U>
|
||||
void writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements);
|
||||
H5NS::Group & getGroup(void);
|
||||
private:
|
||||
template <typename U>
|
||||
@ -48,7 +51,7 @@ namespace Grid
|
||||
std::vector<std::string> path_;
|
||||
H5NS::H5File file_;
|
||||
H5NS::Group group_;
|
||||
unsigned int dataSetThres_{HDF5_DEF_DATASET_THRES};
|
||||
const unsigned int dataSetThres_{HDF5_DEF_DATASET_THRES};
|
||||
};
|
||||
|
||||
class Hdf5Reader: public Reader<Hdf5Reader>
|
||||
@ -66,6 +69,8 @@ namespace Grid
|
||||
template <typename U>
|
||||
typename std::enable_if<!element<std::vector<U>>::is_number, void>::type
|
||||
readDefault(const std::string &s, std::vector<U> &x);
|
||||
template <typename U>
|
||||
void readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim);
|
||||
H5NS::Group & getGroup(void);
|
||||
private:
|
||||
template <typename U>
|
||||
@ -101,6 +106,75 @@ namespace Grid
|
||||
template <>
|
||||
void Hdf5Writer::writeDefault(const std::string &s, const std::string &x);
|
||||
|
||||
template <typename U>
|
||||
void Hdf5Writer::writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements)
|
||||
{
|
||||
// Hdf5 needs the dimensions as hsize_t
|
||||
const int rank = static_cast<int>(Dimensions.size());
|
||||
std::vector<hsize_t> dim(rank);
|
||||
for(int i = 0; i < rank; i++)
|
||||
dim[i] = Dimensions[i];
|
||||
// write the entire dataset to file
|
||||
H5NS::DataSpace dataSpace(rank, dim.data());
|
||||
|
||||
if (NumElements > dataSetThres_)
|
||||
{
|
||||
// Make sure 1) each dimension; and 2) chunk size is < 4GB
|
||||
const hsize_t MaxElements = ( sizeof( U ) == 1 ) ? 0xffffffff : 0x100000000 / sizeof( U );
|
||||
hsize_t ElementsPerChunk = 1;
|
||||
bool bTooBig = false;
|
||||
for( int i = rank - 1 ; i != -1 ; i-- ) {
|
||||
auto &d = dim[i];
|
||||
if( bTooBig )
|
||||
d = 1; // Chunk size is already as big as can be - remaining dimensions = 1
|
||||
else {
|
||||
// If individual dimension too big, reduce by prime factors if possible
|
||||
while( d > MaxElements && ( d & 1 ) == 0 )
|
||||
d >>= 1;
|
||||
const char ErrorMsg[] = " dimension > 4GB and not divisible by 2^n. "
|
||||
"Hdf5IO chunk size will be inefficient. NB Serialisation is not intended for large datasets - please consider alternatives.";
|
||||
if( d > MaxElements ) {
|
||||
std::cout << GridLogWarning << "Individual" << ErrorMsg << std::endl;
|
||||
hsize_t quotient = d / MaxElements;
|
||||
if( d % MaxElements )
|
||||
quotient++;
|
||||
d /= quotient;
|
||||
}
|
||||
// Now make sure overall size is not too big
|
||||
hsize_t OverflowCheck = ElementsPerChunk;
|
||||
ElementsPerChunk *= d;
|
||||
assert( OverflowCheck == ElementsPerChunk / d && "Product of dimensions overflowed hsize_t" );
|
||||
// If product of dimensions too big, reduce by prime factors
|
||||
while( ElementsPerChunk > MaxElements && ( ElementsPerChunk & 1 ) == 0 ) {
|
||||
bTooBig = true;
|
||||
d >>= 1;
|
||||
ElementsPerChunk >>= 1;
|
||||
}
|
||||
if( ElementsPerChunk > MaxElements ) {
|
||||
std::cout << GridLogWarning << "Product of" << ErrorMsg << std::endl;
|
||||
hsize_t quotient = ElementsPerChunk / MaxElements;
|
||||
if( ElementsPerChunk % MaxElements )
|
||||
quotient++;
|
||||
d /= quotient;
|
||||
ElementsPerChunk /= quotient;
|
||||
}
|
||||
}
|
||||
}
|
||||
H5NS::DataSet dataSet;
|
||||
H5NS::DSetCreatPropList plist;
|
||||
plist.setChunk(rank, dim.data());
|
||||
plist.setFletcher32();
|
||||
dataSet = group_.createDataSet(s, Hdf5Type<U>::type(), dataSpace, plist);
|
||||
dataSet.write(pDataRowMajor, Hdf5Type<U>::type());
|
||||
}
|
||||
else
|
||||
{
|
||||
H5NS::Attribute attribute;
|
||||
attribute = group_.createAttribute(s, Hdf5Type<U>::type(), dataSpace);
|
||||
attribute.write(Hdf5Type<U>::type(), pDataRowMajor);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
typename std::enable_if<element<std::vector<U>>::is_number, void>::type
|
||||
Hdf5Writer::writeDefault(const std::string &s, const std::vector<U> &x)
|
||||
@ -110,34 +184,11 @@ namespace Grid
|
||||
|
||||
// flatten the vector and getting dimensions
|
||||
Flatten<std::vector<U>> flat(x);
|
||||
std::vector<hsize_t> dim;
|
||||
std::vector<size_t> dim;
|
||||
const auto &flatx = flat.getFlatVector();
|
||||
|
||||
for (auto &d: flat.getDim())
|
||||
{
|
||||
dim.push_back(d);
|
||||
}
|
||||
|
||||
// write to file
|
||||
H5NS::DataSpace dataSpace(dim.size(), dim.data());
|
||||
|
||||
if (flatx.size() > dataSetThres_)
|
||||
{
|
||||
H5NS::DataSet dataSet;
|
||||
H5NS::DSetCreatPropList plist;
|
||||
|
||||
plist.setChunk(dim.size(), dim.data());
|
||||
plist.setFletcher32();
|
||||
dataSet = group_.createDataSet(s, Hdf5Type<Element>::type(), dataSpace, plist);
|
||||
dataSet.write(flatx.data(), Hdf5Type<Element>::type());
|
||||
}
|
||||
else
|
||||
{
|
||||
H5NS::Attribute attribute;
|
||||
|
||||
attribute = group_.createAttribute(s, Hdf5Type<Element>::type(), dataSpace);
|
||||
attribute.write(Hdf5Type<Element>::type(), flatx.data());
|
||||
}
|
||||
writeMultiDim<Element>(s, dim, &flatx[0], flatx.size());
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
@ -173,10 +224,9 @@ namespace Grid
|
||||
|
||||
template <>
|
||||
void Hdf5Reader::readDefault(const std::string &s, std::string &x);
|
||||
|
||||
|
||||
template <typename U>
|
||||
typename std::enable_if<element<std::vector<U>>::is_number, void>::type
|
||||
Hdf5Reader::readDefault(const std::string &s, std::vector<U> &x)
|
||||
void Hdf5Reader::readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim)
|
||||
{
|
||||
// alias to element type
|
||||
typedef typename element<std::vector<U>>::type Element;
|
||||
@ -184,7 +234,6 @@ namespace Grid
|
||||
// read the dimensions
|
||||
H5NS::DataSpace dataSpace;
|
||||
std::vector<hsize_t> hdim;
|
||||
std::vector<size_t> dim;
|
||||
hsize_t size = 1;
|
||||
|
||||
if (group_.attrExists(s))
|
||||
@ -204,8 +253,8 @@ namespace Grid
|
||||
}
|
||||
|
||||
// read the flat vector
|
||||
std::vector<Element> buf(size);
|
||||
|
||||
buf.resize(size);
|
||||
|
||||
if (size > dataSetThres_)
|
||||
{
|
||||
H5NS::DataSet dataSet;
|
||||
@ -220,7 +269,19 @@ namespace Grid
|
||||
attribute = group_.openAttribute(s);
|
||||
attribute.read(Hdf5Type<Element>::type(), buf.data());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
typename std::enable_if<element<std::vector<U>>::is_number, void>::type
|
||||
Hdf5Reader::readDefault(const std::string &s, std::vector<U> &x)
|
||||
{
|
||||
// alias to element type
|
||||
typedef typename element<std::vector<U>>::type Element;
|
||||
|
||||
std::vector<size_t> dim;
|
||||
std::vector<Element> buf;
|
||||
readMultiDim( s, buf, dim );
|
||||
|
||||
// reconstruct the multidimensional vector
|
||||
Reconstruct<std::vector<U>> r(buf, dim);
|
||||
|
||||
|
@ -107,9 +107,10 @@ THE SOFTWARE.
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define GRID_MACRO_MEMBER(A,B) A B;
|
||||
#define GRID_MACRO_COMP_MEMBER(A,B) result = (result and (lhs. B == rhs. B));
|
||||
#define GRID_MACRO_OS_WRITE_MEMBER(A,B) os<< #A <<" " #B << " = " << obj. B << " ; " <<std::endl;
|
||||
#define GRID_MACRO_READ_MEMBER(A,B) ::Grid::read(RD,#B,obj. B);
|
||||
|
||||
#define GRID_MACRO_COMP_MEMBER(A,B) result = (result and CompareMember(lhs. B, rhs. B));
|
||||
#define GRID_MACRO_OS_WRITE_MEMBER(A,B) os<< #A <<" " #B << " = "; WriteMember( os, obj. B ); os << " ; " <<std::endl;
|
||||
#define GRID_MACRO_READ_MEMBER(A,B) ::Grid::read(RD,#B,obj. B);
|
||||
#define GRID_MACRO_WRITE_MEMBER(A,B) ::Grid::write(WR,#B,obj. B);
|
||||
|
||||
#define GRID_SERIALIZABLE_CLASS_MEMBERS(cname,...)\
|
||||
|
@ -51,6 +51,8 @@ namespace Grid
|
||||
void writeDefault(const std::string &s, const U &x);
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
template <typename U>
|
||||
void writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements);
|
||||
private:
|
||||
void indent(void);
|
||||
private:
|
||||
@ -69,6 +71,8 @@ namespace Grid
|
||||
void readDefault(const std::string &s, U &output);
|
||||
template <typename U>
|
||||
void readDefault(const std::string &s, std::vector<U> &output);
|
||||
template <typename U>
|
||||
void readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim);
|
||||
private:
|
||||
void checkIndent(void);
|
||||
private:
|
||||
@ -95,7 +99,18 @@ namespace Grid
|
||||
write(s, x[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename U>
|
||||
void TextWriter::writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements)
|
||||
{
|
||||
uint64_t Rank = Dimensions.size();
|
||||
write(s, Rank);
|
||||
for( uint64_t d : Dimensions )
|
||||
write(s, d);
|
||||
while( NumElements-- )
|
||||
write(s, *pDataRowMajor++);
|
||||
}
|
||||
|
||||
// Reader template implementation ////////////////////////////////////////////
|
||||
template <>
|
||||
void TextReader::readDefault(const std::string &s, std::string &output);
|
||||
@ -122,7 +137,22 @@ namespace Grid
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename U>
|
||||
void TextReader::readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim)
|
||||
{
|
||||
const char sz[] = "";
|
||||
uint64_t Rank;
|
||||
read(sz, Rank);
|
||||
dim.resize( Rank );
|
||||
size_t NumElements = 1;
|
||||
for( auto &d : dim ) {
|
||||
read(sz, d);
|
||||
NumElements *= d;
|
||||
}
|
||||
buf.resize( NumElements );
|
||||
for( auto &x : buf )
|
||||
read(s, x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,32 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./Grid/serialisation/VectorUtils.h
|
||||
|
||||
Copyright (C) 2015
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
Author: paboyle <paboyle@ph.ed.ac.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef GRID_SERIALISATION_VECTORUTILS_H
|
||||
#define GRID_SERIALISATION_VECTORUTILS_H
|
||||
|
||||
@ -53,6 +82,17 @@ namespace Grid {
|
||||
return os;
|
||||
}
|
||||
|
||||
// std::vector<std:vector<...>> nested to specified Rank //////////////////////////////////
|
||||
template<typename T, unsigned int Rank>
|
||||
struct NestedStdVector {
|
||||
typedef typename std::vector<typename NestedStdVector<T, Rank - 1>::type> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct NestedStdVector<T,0> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// Grid scalar tensors to nested std::vectors //////////////////////////////////
|
||||
template <typename T>
|
||||
struct TensorToVec
|
||||
@ -436,4 +476,4 @@ std::string vecToStr(const std::vector<T> &v)
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -57,6 +57,8 @@ namespace Grid
|
||||
void writeDefault(const std::string &s, const U &x);
|
||||
template <typename U>
|
||||
void writeDefault(const std::string &s, const std::vector<U> &x);
|
||||
template <typename U>
|
||||
void writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements);
|
||||
std::string docString(void);
|
||||
std::string string(void);
|
||||
private:
|
||||
@ -78,6 +80,8 @@ namespace Grid
|
||||
template <typename U>
|
||||
void readDefault(const std::string &s, U &output);
|
||||
template <typename U> void readDefault(const std::string &s, std::vector<U> &output);
|
||||
template <typename U>
|
||||
void readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim);
|
||||
void readCurrentSubtree(std::string &s);
|
||||
|
||||
private:
|
||||
@ -122,13 +126,45 @@ namespace Grid
|
||||
void XmlWriter::writeDefault(const std::string &s, const std::vector<U> &x)
|
||||
{
|
||||
push(s);
|
||||
for (auto &x_i: x)
|
||||
for( auto &u : x )
|
||||
{
|
||||
write("elem", x_i);
|
||||
write("elem", u);
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
||||
|
||||
template <typename U>
|
||||
void XmlWriter::writeMultiDim(const std::string &s, const std::vector<size_t> & Dimensions, const U * pDataRowMajor, size_t NumElements)
|
||||
{
|
||||
push(s);
|
||||
size_t count = 1;
|
||||
const int Rank = static_cast<int>( Dimensions.size() );
|
||||
write("rank", Rank );
|
||||
std::vector<size_t> MyIndex( Rank );
|
||||
for( auto d : Dimensions ) {
|
||||
write("dim", d);
|
||||
count *= d;
|
||||
}
|
||||
assert( count == NumElements && "XmlIO : element count doesn't match dimensions" );
|
||||
static const char sName[] = "tensor";
|
||||
for( int i = 0 ; i < Rank ; i++ ) {
|
||||
MyIndex[i] = 0;
|
||||
push(sName);
|
||||
}
|
||||
while (NumElements--) {
|
||||
write("elem", *pDataRowMajor++);
|
||||
int i;
|
||||
for( i = Rank - 1 ; i != -1 && ++MyIndex[i] == Dimensions[i] ; i-- )
|
||||
MyIndex[i] = 0;
|
||||
int Rollover = Rank - 1 - i;
|
||||
for( i = 0 ; i < Rollover ; i++ )
|
||||
pop();
|
||||
for( i = 0 ; NumElements && i < Rollover ; i++ )
|
||||
push(sName);
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
||||
// Reader template implementation ////////////////////////////////////////////
|
||||
template <> void XmlReader::readDefault(const std::string &s, std::string &output);
|
||||
template <typename U>
|
||||
@ -143,25 +179,66 @@ namespace Grid
|
||||
template <typename U>
|
||||
void XmlReader::readDefault(const std::string &s, std::vector<U> &output)
|
||||
{
|
||||
std::string buf;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (!push(s))
|
||||
{
|
||||
std::cout << GridLogWarning << "XML: cannot open node '" << s << "'";
|
||||
std::cout << std::endl;
|
||||
|
||||
return;
|
||||
} else {
|
||||
for(unsigned int i = 0; node_.child("elem"); )
|
||||
{
|
||||
output.resize(i + 1);
|
||||
read("elem", output[i++]);
|
||||
node_.child("elem").set_name("elem-done");
|
||||
}
|
||||
pop();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void XmlReader::readMultiDim(const std::string &s, std::vector<U> &buf, std::vector<size_t> &dim)
|
||||
{
|
||||
if (!push(s))
|
||||
{
|
||||
std::cout << GridLogWarning << "XML: cannot open node '" << s << "'";
|
||||
std::cout << std::endl;
|
||||
} else {
|
||||
static const char sName[] = "tensor";
|
||||
static const char sNameDone[] = "tensor-done";
|
||||
int Rank;
|
||||
read("rank", Rank);
|
||||
dim.resize( Rank );
|
||||
size_t NumElements = 1;
|
||||
for( auto &d : dim )
|
||||
{
|
||||
read("dim", d);
|
||||
node_.child("dim").set_name("dim-done");
|
||||
NumElements *= d;
|
||||
}
|
||||
buf.resize( NumElements );
|
||||
std::vector<size_t> MyIndex( Rank );
|
||||
for( int i = 0 ; i < Rank ; i++ ) {
|
||||
MyIndex[i] = 0;
|
||||
push(sName);
|
||||
}
|
||||
|
||||
for( auto &x : buf )
|
||||
{
|
||||
NumElements--;
|
||||
read("elem", x);
|
||||
node_.child("elem").set_name("elem-done");
|
||||
int i;
|
||||
for( i = Rank - 1 ; i != -1 && ++MyIndex[i] == dim[i] ; i-- )
|
||||
MyIndex[i] = 0;
|
||||
int Rollover = Rank - 1 - i;
|
||||
for( i = 0 ; i < Rollover ; i++ ) {
|
||||
node_.set_name(sNameDone);
|
||||
pop();
|
||||
}
|
||||
for( i = 0 ; NumElements && i < Rollover ; i++ )
|
||||
push(sName);
|
||||
}
|
||||
pop();
|
||||
}
|
||||
while (node_.child("elem"))
|
||||
{
|
||||
output.resize(i + 1);
|
||||
read("elem", output[i]);
|
||||
node_.child("elem").set_name("elem-done");
|
||||
i++;
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -1,652 +0,0 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./lib/simd/Grid_gpu.h
|
||||
|
||||
Copyright (C) 2018
|
||||
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
//----------------------------------------------------------------------
|
||||
/*! @file Grid_gpu.h
|
||||
@brief Optimization libraries for GPU
|
||||
Use float4, double2
|
||||
*/
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
namespace Grid {
|
||||
|
||||
// re im, re, im, re, im etc..
|
||||
struct half8 {
|
||||
half ax, ay, az, aw, bx, by, bz, bw;
|
||||
};
|
||||
accelerator_inline float half2float(half h)
|
||||
{
|
||||
float f;
|
||||
#ifdef __CUDA_ARCH__
|
||||
f = __half2float(h);
|
||||
#else
|
||||
//f = __half2float(h);
|
||||
__half_raw hr(h);
|
||||
Grid_half hh;
|
||||
hh.x = hr.x;
|
||||
f= sfw_half_to_float(hh);
|
||||
#endif
|
||||
return f;
|
||||
}
|
||||
accelerator_inline half float2half(float f)
|
||||
{
|
||||
half h;
|
||||
#ifdef __CUDA_ARCH__
|
||||
h = __float2half(f);
|
||||
#else
|
||||
Grid_half hh = sfw_float_to_half(f);
|
||||
__half_raw hr;
|
||||
hr.x = hh.x;
|
||||
h = __half(hr);
|
||||
#endif
|
||||
return h;
|
||||
}
|
||||
|
||||
namespace Optimization {
|
||||
|
||||
inline accelerator float4 operator*(float4 a,float4 b) {return make_float4(a.x*b.x,a.y*b.y,a.z*b.z,a.w*b.w);}
|
||||
inline accelerator float4 operator+(float4 a,float4 b) {return make_float4(a.x+b.x,a.y+b.y,a.z+b.z,a.w+b.w);}
|
||||
inline accelerator float4 operator-(float4 a,float4 b) {return make_float4(a.x-b.x,a.y-b.y,a.z-b.z,a.w-b.w);}
|
||||
inline accelerator float4 operator/(float4 a,float4 b) {return make_float4(a.x/b.x,a.y/b.y,a.z/b.z,a.w/b.w);}
|
||||
|
||||
inline accelerator double2 operator*(double2 a,double2 b) {return make_double2(a.x*b.x,a.y*b.y);}
|
||||
inline accelerator double2 operator+(double2 a,double2 b) {return make_double2(a.x+b.x,a.y+b.y);}
|
||||
inline accelerator double2 operator-(double2 a,double2 b) {return make_double2(a.x-b.x,a.y-b.y);}
|
||||
inline accelerator double2 operator/(double2 a,double2 b) {return make_double2(a.x/b.x,a.y/b.y);}
|
||||
|
||||
inline accelerator int4 operator*(int4 a,int4 b) {return make_int4(a.x*b.x,a.y*b.y,a.z*b.z,a.w*b.w);}
|
||||
inline accelerator int4 operator+(int4 a,int4 b) {return make_int4(a.x+b.x,a.y+b.y,a.z+b.z,a.w+b.w);}
|
||||
inline accelerator int4 operator-(int4 a,int4 b) {return make_int4(a.x-b.x,a.y-b.y,a.z-b.z,a.w-b.w);}
|
||||
inline accelerator int4 operator/(int4 a,int4 b) {return make_int4(a.x/b.x,a.y/b.y,a.z/b.z,a.w/b.w);}
|
||||
|
||||
struct Vsplat{
|
||||
//Complex float
|
||||
accelerator_inline float4 operator()(float a, float b){
|
||||
float4 ret;
|
||||
ret.x=ret.z=a;
|
||||
ret.y=ret.w=b;
|
||||
return ret;
|
||||
}
|
||||
// Real float
|
||||
accelerator_inline float4 operator()(float a){
|
||||
float4 ret;
|
||||
ret.x=ret.y=ret.z=ret.w = a;
|
||||
return ret;
|
||||
}
|
||||
//Complex double
|
||||
accelerator_inline double2 operator()(double a, double b){
|
||||
double2 ret;
|
||||
ret.x=a;
|
||||
ret.y=b;
|
||||
return ret;
|
||||
}
|
||||
//Real double
|
||||
accelerator_inline double2 operator()(double a){
|
||||
double2 ret;
|
||||
ret.x = ret.y = a;
|
||||
return ret;
|
||||
}
|
||||
//Integer
|
||||
accelerator_inline int4 operator()(Integer a){
|
||||
int4 ret;
|
||||
ret.x=ret.y=ret.z=ret.w=a;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct Vstore{
|
||||
//Float
|
||||
accelerator_inline void operator()(float4 a, float* F){
|
||||
float4 *F4 = (float4 *)F;
|
||||
*F4 = a;
|
||||
}
|
||||
//Double
|
||||
accelerator_inline void operator()(double2 a, double* D){
|
||||
double2 *D2 = (double2 *)D;
|
||||
*D2 = a;
|
||||
}
|
||||
//Integer
|
||||
accelerator_inline void operator()(int4 a, Integer* I){
|
||||
int4 *I4 = (int4 *)I;
|
||||
*I4 = a;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct Vstream{
|
||||
//Float
|
||||
accelerator_inline void operator()(float * a, float4 b){
|
||||
float4 * a4 = (float4 *)a;
|
||||
*a4 = b;
|
||||
}
|
||||
//Double
|
||||
accelerator_inline void operator()(double * a, double2 b){
|
||||
double2 * a2 = (double2 *)a;
|
||||
*a2 = b;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct Vset{
|
||||
// Complex float
|
||||
accelerator_inline float4 operator()(Grid::ComplexF *a){
|
||||
float4 ret;
|
||||
ret.x = a[0].real();
|
||||
ret.y = a[0].imag();
|
||||
ret.z = a[1].real();
|
||||
ret.w = a[1].imag();
|
||||
return ret;
|
||||
}
|
||||
// Complex double
|
||||
accelerator_inline double2 operator()(Grid::ComplexD *a){
|
||||
double2 ret;
|
||||
ret.x = a[0].real();
|
||||
ret.y = a[0].imag();
|
||||
return ret;
|
||||
}
|
||||
// Real float
|
||||
accelerator_inline float4 operator()(float *a){
|
||||
float4 ret;
|
||||
ret.x = a[0];
|
||||
ret.y = a[1];
|
||||
ret.z = a[2];
|
||||
ret.w = a[3];
|
||||
return ret;
|
||||
}
|
||||
// Real double
|
||||
accelerator_inline double2 operator()(double *a){
|
||||
double2 ret;
|
||||
ret.x = a[0];
|
||||
ret.y = a[1];
|
||||
return ret;
|
||||
}
|
||||
// Integer
|
||||
accelerator_inline int4 operator()(Integer *a){
|
||||
int4 ret;
|
||||
ret.x = a[0];
|
||||
ret.y = a[1];
|
||||
ret.z = a[2];
|
||||
ret.w = a[3];
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Out_type, typename In_type>
|
||||
struct Reduce{
|
||||
//Need templated class to overload output type
|
||||
//General form must generate error if compiled
|
||||
accelerator_inline Out_type operator()(In_type in){
|
||||
printf("Error, using wrong Reduce function\n");
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Arithmetic operations
|
||||
/////////////////////////////////////////////////////
|
||||
struct Sum{
|
||||
//Complex/Real float
|
||||
accelerator_inline float4 operator()(float4 a, float4 b){
|
||||
return a+b;
|
||||
}
|
||||
//Complex/Real double
|
||||
accelerator_inline double2 operator()(double2 a, double2 b){
|
||||
return a+b;
|
||||
}
|
||||
//Integer
|
||||
accelerator_inline int4 operator()(int4 a,int4 b){
|
||||
return a+b;
|
||||
}
|
||||
};
|
||||
|
||||
struct Sub{
|
||||
//Complex/Real float
|
||||
accelerator_inline float4 operator()(float4 a, float4 b){
|
||||
return a-b;
|
||||
}
|
||||
//Complex/Real double
|
||||
accelerator_inline double2 operator()(double2 a, double2 b){
|
||||
return a-b;
|
||||
}
|
||||
//Integer
|
||||
accelerator_inline int4 operator()(int4 a, int4 b){
|
||||
return a-b;
|
||||
}
|
||||
};
|
||||
|
||||
struct MultRealPart{
|
||||
accelerator_inline float4 operator()(float4 a, float4 b){
|
||||
float4 ymm0;
|
||||
ymm0.x = a.x;
|
||||
ymm0.y = a.x;
|
||||
ymm0.z = a.z;
|
||||
ymm0.w = a.z;
|
||||
return ymm0*b;
|
||||
// ymm0 = _mm_shuffle_ps(a,a,_MM_SELECT_FOUR_FOUR(2,2,0,0)); // ymm0 <- ar ar,
|
||||
// return _mm_mul_ps(ymm0,b); // ymm0 <- ar bi, ar br
|
||||
}
|
||||
accelerator_inline double2 operator()(double2 a, double2 b){
|
||||
double2 ymm0;
|
||||
ymm0.x = a.x;
|
||||
ymm0.y = a.x;
|
||||
return ymm0*b;
|
||||
// ymm0 = _mm_shuffle_pd(a,a,0x0); // ymm0 <- ar ar, ar,ar b'00,00
|
||||
// return _mm_mul_pd(ymm0,b); // ymm0 <- ar bi, ar br
|
||||
}
|
||||
};
|
||||
struct MaddRealPart{
|
||||
accelerator_inline float4 operator()(float4 a, float4 b, float4 c){
|
||||
float4 ymm0; // = _mm_shuffle_ps(a,a,_MM_SELECT_FOUR_FOUR(2,2,0,0)); // ymm0 <- ar ar,
|
||||
ymm0.x = a.x;
|
||||
ymm0.y = a.x;
|
||||
ymm0.z = a.z;
|
||||
ymm0.w = a.z;
|
||||
return c+ymm0*b;
|
||||
}
|
||||
accelerator_inline double2 operator()(double2 a, double2 b, double2 c){
|
||||
// ymm0 = _mm_shuffle_pd( a, a, 0x0 );
|
||||
double2 ymm0;
|
||||
ymm0.x = a.x;
|
||||
ymm0.y = a.x;
|
||||
return c+ymm0*b;
|
||||
}
|
||||
};
|
||||
|
||||
struct MultComplex{
|
||||
// Complex float
|
||||
accelerator_inline float4 operator()(float4 a, float4 b){
|
||||
float4 ymm0;
|
||||
ymm0.x = a.x*b.x - a.y*b.y ; // rr - ii
|
||||
ymm0.y = a.x*b.y + a.y*b.x ; // ir + ri
|
||||
ymm0.z = a.z*b.z - a.w*b.w ; // rr - ii
|
||||
ymm0.w = a.w*b.z + a.z*b.w ; // ir + ri
|
||||
return ymm0;
|
||||
}
|
||||
// Complex double
|
||||
accelerator_inline double2 operator()(double2 a, double2 b){
|
||||
double2 ymm0;
|
||||
ymm0.x = a.x*b.x - a.y*b.y ; // rr - ii
|
||||
ymm0.y = a.x*b.y + a.y*b.x ; // ir + ri
|
||||
return ymm0;
|
||||
}
|
||||
};
|
||||
|
||||
struct Mult{
|
||||
|
||||
accelerator_inline void mac(float4 &a, float4 b, float4 c){
|
||||
a= a+b*c;
|
||||
}
|
||||
|
||||
accelerator_inline void mac(double2 &a, double2 b, double2 c){
|
||||
a= a+b*c;
|
||||
}
|
||||
|
||||
// Real float
|
||||
accelerator_inline float4 operator()(float4 a, float4 b){
|
||||
return a*b;
|
||||
}
|
||||
// Real double
|
||||
accelerator_inline double2 operator()(double2 a, double2 b){
|
||||
return a*b;
|
||||
}
|
||||
// Integer
|
||||
accelerator_inline int4 operator()(int4 a, int4 b){
|
||||
return a*b;
|
||||
}
|
||||
};
|
||||
|
||||
struct Div{
|
||||
// Real float
|
||||
accelerator_inline float4 operator()(float4 a, float4 b){
|
||||
return a/b;
|
||||
}
|
||||
// Real double
|
||||
accelerator_inline double2 operator()(double2 a, double2 b){
|
||||
return a/b;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Conj{
|
||||
// Complex single
|
||||
accelerator_inline float4 operator()(float4 in){
|
||||
float4 ret;
|
||||
ret.x = in.x;
|
||||
ret.y = - in.y;
|
||||
ret.z = in.z;
|
||||
ret.w = - in.w;
|
||||
return ret;
|
||||
}
|
||||
// Complex double
|
||||
accelerator_inline double2 operator()(double2 in){
|
||||
double2 ret;
|
||||
ret.x = in.x;
|
||||
ret.y = - in.y;
|
||||
return ret;
|
||||
}
|
||||
// do not define for integer input
|
||||
};
|
||||
|
||||
struct TimesMinusI{
|
||||
//Complex single
|
||||
accelerator_inline float4 operator()(float4 in, float4 ret){
|
||||
float4 tmp;
|
||||
tmp.x = in.y;
|
||||
tmp.y = - in.x;
|
||||
tmp.z = in.w;
|
||||
tmp.w = - in.z;
|
||||
return tmp;
|
||||
}
|
||||
//Complex double
|
||||
accelerator_inline double2 operator()(double2 in, double2 ret){
|
||||
double2 tmp;
|
||||
tmp.x = in.y;
|
||||
tmp.y = - in.x;
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
struct TimesI{
|
||||
//Complex single
|
||||
accelerator_inline float4 operator()(float4 in, float4 ret){
|
||||
float4 tmp;
|
||||
tmp.x = - in.y;
|
||||
tmp.y = in.x;
|
||||
tmp.z = - in.w;
|
||||
tmp.w = in.z;
|
||||
return tmp;
|
||||
}
|
||||
//Complex double
|
||||
accelerator_inline double2 operator()(double2 in, double2 ret){
|
||||
double2 tmp ;
|
||||
tmp.x = - in.y;
|
||||
tmp.y = in.x;
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
struct Permute{
|
||||
|
||||
static accelerator_inline float4 Permute0(float4 in){
|
||||
float4 tmp;
|
||||
tmp.x = in.z;
|
||||
tmp.y = in.w;
|
||||
tmp.z = in.x;
|
||||
tmp.w = in.y;
|
||||
return tmp;
|
||||
};
|
||||
static accelerator_inline float4 Permute1(float4 in){
|
||||
float4 tmp;
|
||||
tmp.x = in.y;
|
||||
tmp.y = in.x;
|
||||
tmp.z = in.w;
|
||||
tmp.w = in.z;
|
||||
return tmp;
|
||||
};
|
||||
static accelerator_inline float4 Permute2(float4 in){
|
||||
return in;
|
||||
};
|
||||
static accelerator_inline float4 Permute3(float4 in){
|
||||
return in;
|
||||
};
|
||||
|
||||
static accelerator_inline double2 Permute0(double2 in){ //AB -> BA
|
||||
double2 tmp;
|
||||
tmp.x = in.y;
|
||||
tmp.y = in.x;
|
||||
return tmp;
|
||||
};
|
||||
static accelerator_inline double2 Permute1(double2 in){
|
||||
return in;
|
||||
};
|
||||
static accelerator_inline double2 Permute2(double2 in){
|
||||
return in;
|
||||
};
|
||||
static accelerator_inline double2 Permute3(double2 in){
|
||||
return in;
|
||||
};
|
||||
};
|
||||
|
||||
struct PrecisionChange {
|
||||
static accelerator_inline half8 StoH (float4 a,float4 b) {
|
||||
half8 h;
|
||||
h.ax = float2half(a.x);
|
||||
h.ay = float2half(a.y);
|
||||
h.az = float2half(a.z);
|
||||
h.aw = float2half(a.w);
|
||||
h.bx = float2half(b.x);
|
||||
h.by = float2half(b.y);
|
||||
h.bz = float2half(b.z);
|
||||
h.bw = float2half(b.w);
|
||||
return h;
|
||||
}
|
||||
static accelerator_inline void HtoS (half8 h,float4 &sa,float4 &sb) {
|
||||
sa.x = half2float(h.ax);
|
||||
sa.y = half2float(h.ay);
|
||||
sa.z = half2float(h.az);
|
||||
sa.w = half2float(h.aw);
|
||||
sb.x = half2float(h.bx);
|
||||
sb.y = half2float(h.by);
|
||||
sb.z = half2float(h.bz);
|
||||
sb.w = half2float(h.bw);
|
||||
}
|
||||
static accelerator_inline float4 DtoS (double2 a,double2 b) {
|
||||
float4 s;
|
||||
s.x = a.x;
|
||||
s.y = a.y;
|
||||
s.z = b.x;
|
||||
s.w = b.y;
|
||||
return s;
|
||||
}
|
||||
static accelerator_inline void StoD (float4 s,double2 &a,double2 &b) {
|
||||
a.x = s.x;
|
||||
a.y = s.y;
|
||||
b.x = s.z;
|
||||
b.y = s.w;
|
||||
}
|
||||
static accelerator_inline half8 DtoH (double2 a,double2 b,double2 c,double2 d) {
|
||||
float4 sa,sb;
|
||||
sa = DtoS(a,b);
|
||||
sb = DtoS(c,d);
|
||||
return StoH(sa,sb);
|
||||
}
|
||||
static accelerator_inline void HtoD (half8 h,double2 &a,double2 &b,double2 &c,double2 &d) {
|
||||
float4 sa,sb;
|
||||
HtoS(h,sa,sb);
|
||||
StoD(sa,a,b);
|
||||
StoD(sb,c,d);
|
||||
}
|
||||
};
|
||||
|
||||
struct Exchange{
|
||||
// 3210 ordering
|
||||
|
||||
static accelerator_inline void Exchange0(float4 &out1,float4 &out2,float4 in1,float4 in2){
|
||||
out1.x = in1.x;
|
||||
out1.y = in1.y;
|
||||
out1.z = in2.x;
|
||||
out1.w = in2.y;
|
||||
|
||||
out2.x = in1.z;
|
||||
out2.y = in1.w;
|
||||
out2.z = in2.z;
|
||||
out2.w = in2.w;
|
||||
|
||||
// out1= _mm_shuffle_ps(in1,in2,_MM_SELECT_FOUR_FOUR(1,0,1,0));
|
||||
// out2= _mm_shuffle_ps(in1,in2,_MM_SELECT_FOUR_FOUR(3,2,3,2));
|
||||
return;
|
||||
};
|
||||
|
||||
static accelerator_inline void Exchange1(float4 &out1,float4 &out2,float4 in1,float4 in2){
|
||||
|
||||
out1.x = in1.x;
|
||||
out1.y = in2.x;
|
||||
out1.z = in1.z;
|
||||
out1.w = in2.z;
|
||||
|
||||
out2.x = in1.y;
|
||||
out2.y = in2.y;
|
||||
out2.z = in1.w;
|
||||
out2.w = in2.w;
|
||||
|
||||
// out1= _mm_shuffle_ps(in1,in2,_MM_SELECT_FOUR_FOUR(2,0,2,0)); /*ACEG*/
|
||||
// out2= _mm_shuffle_ps(in1,in2,_MM_SELECT_FOUR_FOUR(3,1,3,1)); /*BDFH*/
|
||||
// out1= _mm_shuffle_ps(out1,out1,_MM_SELECT_FOUR_FOUR(3,1,2,0)); /*AECG*/
|
||||
// out2= _mm_shuffle_ps(out2,out2,_MM_SELECT_FOUR_FOUR(3,1,2,0)); /*AECG*/
|
||||
};
|
||||
static accelerator_inline void Exchange2(float4 &out1,float4 &out2,float4 in1,float4 in2){
|
||||
assert(0);
|
||||
return;
|
||||
};
|
||||
static accelerator_inline void Exchange3(float4 &out1,float4 &out2,float4 in1,float4 in2){
|
||||
assert(0);
|
||||
return;
|
||||
};
|
||||
|
||||
static accelerator_inline void Exchange0(double2 &out1,double2 &out2,double2 in1,double2 in2){
|
||||
out1.x = in1.x;
|
||||
out1.y = in2.x;
|
||||
out2.x = in1.y;
|
||||
out2.y = in2.y;
|
||||
// out1= _mm_shuffle_pd(in1,in2,0x0);
|
||||
// out2= _mm_shuffle_pd(in1,in2,0x3);
|
||||
};
|
||||
static accelerator_inline void Exchange1(double2 &out1,double2 &out2,double2 in1,double2 in2){
|
||||
assert(0);
|
||||
return;
|
||||
};
|
||||
static accelerator_inline void Exchange2(double2 &out1,double2 &out2,double2 in1,double2 in2){
|
||||
assert(0);
|
||||
return;
|
||||
};
|
||||
static accelerator_inline void Exchange3(double2 &out1,double2 &out2,double2 in1,double2 in2){
|
||||
assert(0);
|
||||
return;
|
||||
};
|
||||
};
|
||||
|
||||
struct Rotate{
|
||||
|
||||
static accelerator_inline float4 rotate(float4 in,int n){
|
||||
float4 ret;
|
||||
switch(n){
|
||||
case 0: ret = in ; break;
|
||||
case 1: ret.x = in.y; ret.y = in.z ; ret.z = in.w ; ret.w = in.x; break;
|
||||
case 2: ret.x = in.z; ret.y = in.w ; ret.z = in.x ; ret.w = in.y; break;
|
||||
case 3: ret.x = in.w; ret.y = in.x ; ret.z = in.y ; ret.w = in.z; break;
|
||||
default: break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static accelerator_inline double2 rotate(double2 in,int n){
|
||||
double2 ret;
|
||||
switch(n){
|
||||
case 0: ret = in; break;
|
||||
case 1: ret.x = in.y; ret.y = in.x ; break;
|
||||
default: break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<int n> static accelerator_inline float4 tRotate(float4 in){
|
||||
return rotate(in,n);
|
||||
};
|
||||
template<int n> static accelerator_inline double2 tRotate(double2 in){
|
||||
return rotate(in,n);
|
||||
};
|
||||
|
||||
};
|
||||
//////////////////////////////////////////////
|
||||
// Some Template specialization
|
||||
|
||||
//Complex float Reduce
|
||||
template<>
|
||||
accelerator_inline Grid::ComplexF Reduce<Grid::ComplexF, float4>::operator()(float4 in){
|
||||
Grid::ComplexF ret(in.x+in.z,in.y+in.w);
|
||||
return ret;
|
||||
}
|
||||
//Real float Reduce
|
||||
template<>
|
||||
accelerator_inline Grid::RealF Reduce<Grid::RealF, float4>::operator()(float4 in){
|
||||
return in.x+in.y+in.z+in.w;
|
||||
}
|
||||
|
||||
//Complex double Reduce
|
||||
template<>
|
||||
accelerator_inline Grid::ComplexD Reduce<Grid::ComplexD, double2>::operator()(double2 in){
|
||||
return Grid::ComplexD(in.x,in.y);
|
||||
}
|
||||
|
||||
//Real double Reduce
|
||||
template<>
|
||||
accelerator_inline Grid::RealD Reduce<Grid::RealD, double2>::operator()(double2 in){
|
||||
return in.x+in.y;
|
||||
}
|
||||
|
||||
//Integer Reduce
|
||||
template<>
|
||||
accelerator_inline Integer Reduce<Integer, int4>::operator()(int4 in){
|
||||
return in.x+in.y+in.z+in.w;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// Here assign types
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef half8 SIMD_Htype; // Single precision type
|
||||
typedef float4 SIMD_Ftype; // Single precision type
|
||||
typedef double2 SIMD_Dtype; // Double precision type
|
||||
typedef int4 SIMD_Itype; // Integer type
|
||||
|
||||
// prefetch utilities
|
||||
accelerator_inline void v_prefetch0(int size, const char *ptr){};
|
||||
accelerator_inline void prefetch_HINT_T0(const char *ptr){};
|
||||
|
||||
// Function name aliases
|
||||
typedef Optimization::Vsplat VsplatSIMD;
|
||||
typedef Optimization::Vstore VstoreSIMD;
|
||||
typedef Optimization::Vset VsetSIMD;
|
||||
typedef Optimization::Vstream VstreamSIMD;
|
||||
template <typename S, typename T> using ReduceSIMD = Optimization::Reduce<S,T>;
|
||||
|
||||
// Arithmetic operations
|
||||
typedef Optimization::Sum SumSIMD;
|
||||
typedef Optimization::Sub SubSIMD;
|
||||
typedef Optimization::Div DivSIMD;
|
||||
typedef Optimization::Mult MultSIMD;
|
||||
typedef Optimization::MultComplex MultComplexSIMD;
|
||||
typedef Optimization::MultRealPart MultRealPartSIMD;
|
||||
typedef Optimization::MaddRealPart MaddRealPartSIMD;
|
||||
typedef Optimization::Conj ConjSIMD;
|
||||
typedef Optimization::TimesMinusI TimesMinusISIMD;
|
||||
typedef Optimization::TimesI TimesISIMD;
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ Author: Guido Cossu <cossu@iroiro-pc.kek.jp>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
Author: neo <cossu@post.kek.jp>
|
||||
Author: paboyle <paboyle@ph.ed.ac.uk>
|
||||
Author: Michael Marshall <michael.marshall@ed.ac.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -109,9 +110,6 @@ accelerator_inline Grid_half sfw_float_to_half(float ff) {
|
||||
#ifdef GPU_VEC
|
||||
#include "Grid_gpu_vec.h"
|
||||
#endif
|
||||
#ifdef GPU
|
||||
#include "Grid_gpu.h"
|
||||
#endif
|
||||
#ifdef GEN
|
||||
#include "Grid_generic.h"
|
||||
#endif
|
||||
@ -162,17 +160,25 @@ template <typename Condition, typename ReturnType> using NotEnableIf = Invoke<st
|
||||
////////////////////////////////////////////////////////
|
||||
// Check for complexity with type traits
|
||||
template <typename T> struct is_complex : public std::false_type {};
|
||||
template <> struct is_complex<complex<double> > : public std::true_type {};
|
||||
template <> struct is_complex<complex<float> > : public std::true_type {};
|
||||
template <> struct is_complex<ComplexD> : public std::true_type {};
|
||||
template <> struct is_complex<ComplexF> : public std::true_type {};
|
||||
|
||||
template <typename T> using IfReal = Invoke<std::enable_if<std::is_floating_point<T>::value, int> >;
|
||||
template<typename T, typename V=void> struct is_real : public std::false_type {};
|
||||
template<typename T> struct is_real<T, typename std::enable_if<std::is_floating_point<T>::value,
|
||||
void>::type> : public std::true_type {};
|
||||
|
||||
template<typename T, typename V=void> struct is_integer : public std::false_type {};
|
||||
template<typename T> struct is_integer<T, typename std::enable_if<std::is_integral<T>::value,
|
||||
void>::type> : public std::true_type {};
|
||||
|
||||
template <typename T> using IfReal = Invoke<std::enable_if<is_real<T>::value, int> >;
|
||||
template <typename T> using IfComplex = Invoke<std::enable_if<is_complex<T>::value, int> >;
|
||||
template <typename T> using IfInteger = Invoke<std::enable_if<std::is_integral<T>::value, int> >;
|
||||
template <typename T> using IfInteger = Invoke<std::enable_if<is_integer<T>::value, int> >;
|
||||
template <typename T1,typename T2> using IfSame = Invoke<std::enable_if<std::is_same<T1,T2>::value, int> >;
|
||||
|
||||
template <typename T> using IfNotReal = Invoke<std::enable_if<!std::is_floating_point<T>::value, int> >;
|
||||
template <typename T> using IfNotReal = Invoke<std::enable_if<!is_real<T>::value, int> >;
|
||||
template <typename T> using IfNotComplex = Invoke<std::enable_if<!is_complex<T>::value, int> >;
|
||||
template <typename T> using IfNotInteger = Invoke<std::enable_if<!std::is_integral<T>::value, int> >;
|
||||
template <typename T> using IfNotInteger = Invoke<std::enable_if<!is_integer<T>::value, int> >;
|
||||
template <typename T1,typename T2> using IfNotSame = Invoke<std::enable_if<!std::is_same<T1,T2>::value, int> >;
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
@ -957,8 +963,10 @@ template <typename T>
|
||||
struct is_simd : public std::false_type {};
|
||||
template <> struct is_simd<vRealF> : public std::true_type {};
|
||||
template <> struct is_simd<vRealD> : public std::true_type {};
|
||||
template <> struct is_simd<vRealH> : public std::true_type {};
|
||||
template <> struct is_simd<vComplexF> : public std::true_type {};
|
||||
template <> struct is_simd<vComplexD> : public std::true_type {};
|
||||
template <> struct is_simd<vComplexH> : public std::true_type {};
|
||||
template <> struct is_simd<vInteger> : public std::true_type {};
|
||||
|
||||
template <typename T> using IfSimd = Invoke<std::enable_if<is_simd<T>::value, int> >;
|
||||
|
@ -5,6 +5,7 @@ Copyright (C) 2015
|
||||
|
||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
Author: Michael Marshall <michael.marshall@ed.ac.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -21,8 +22,7 @@ See the full license in the file "LICENSE" in the top level distribution
|
||||
directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef GRID_MATH_TENSORS_H
|
||||
#define GRID_MATH_TENSORS_H
|
||||
#pragma once
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
|
||||
@ -42,27 +42,26 @@ NAMESPACE_BEGIN(Grid);
|
||||
//
|
||||
class GridTensorBase {};
|
||||
|
||||
// Too late to remove these traits from Grid Tensors, so inherit from GridTypeMapper
|
||||
#define GridVector_CopyTraits \
|
||||
using element = vtype; \
|
||||
using scalar_type = typename Traits::scalar_type; \
|
||||
using vector_type = typename Traits::vector_type; \
|
||||
using vector_typeD = typename Traits::vector_typeD; \
|
||||
using tensor_reduced = typename Traits::tensor_reduced; \
|
||||
using scalar_object = typename Traits::scalar_object; \
|
||||
using Complexified = typename Traits::Complexified; \
|
||||
using Realified = typename Traits::Realified; \
|
||||
using DoublePrecision = typename Traits::DoublePrecision; \
|
||||
static constexpr int TensorLevel = Traits::TensorLevel
|
||||
|
||||
template <class vtype>
|
||||
class iScalar {
|
||||
public:
|
||||
vtype _internal;
|
||||
|
||||
typedef vtype element;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_type scalar_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_type vector_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_typeD vector_typeD;
|
||||
typedef typename GridTypeMapper<vtype>::tensor_reduced tensor_reduced_v;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_object recurse_scalar_object;
|
||||
typedef iScalar<tensor_reduced_v> tensor_reduced;
|
||||
typedef iScalar<recurse_scalar_object> scalar_object;
|
||||
// substitutes a real or complex version with same tensor structure
|
||||
typedef iScalar<typename GridTypeMapper<vtype>::Complexified> Complexified;
|
||||
typedef iScalar<typename GridTypeMapper<vtype>::Realified> Realified;
|
||||
|
||||
// get double precision version
|
||||
typedef iScalar<typename GridTypeMapper<vtype>::DoublePrecision> DoublePrecision;
|
||||
|
||||
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 };
|
||||
using Traits = GridTypeMapper<iScalar<vtype> >;
|
||||
GridVector_CopyTraits;
|
||||
|
||||
static accelerator_inline constexpr int Nsimd(void) { return sizeof(vector_type)/sizeof(scalar_type); }
|
||||
|
||||
@ -160,6 +159,10 @@ public:
|
||||
stream << "S {" << o._internal << "}";
|
||||
return stream;
|
||||
};
|
||||
strong_inline const scalar_type * begin() const { return reinterpret_cast<const scalar_type *>(&_internal); }
|
||||
strong_inline scalar_type * begin() { return reinterpret_cast< scalar_type *>(&_internal); }
|
||||
strong_inline const scalar_type * end() const { return begin() + Traits::count; }
|
||||
strong_inline scalar_type * end() { return begin() + Traits::count; }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
@ -180,35 +183,22 @@ template <class vtype, int N>
|
||||
class iVector {
|
||||
public:
|
||||
vtype _internal[N];
|
||||
|
||||
using Traits = GridTypeMapper<iVector<vtype, N> >;
|
||||
|
||||
typedef vtype element;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_type scalar_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_type vector_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_typeD vector_typeD;
|
||||
typedef typename GridTypeMapper<vtype>::tensor_reduced tensor_reduced_v;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_object recurse_scalar_object;
|
||||
typedef iScalar<tensor_reduced_v> tensor_reduced;
|
||||
typedef iVector<recurse_scalar_object, N> scalar_object;
|
||||
|
||||
// substitutes a real or complex version with same tensor structure
|
||||
typedef iVector<typename GridTypeMapper<vtype>::Complexified, N> Complexified;
|
||||
typedef iVector<typename GridTypeMapper<vtype>::Realified, N> Realified;
|
||||
|
||||
// get double precision version
|
||||
typedef iVector<typename GridTypeMapper<vtype>::DoublePrecision, N> DoublePrecision;
|
||||
GridVector_CopyTraits;
|
||||
|
||||
static accelerator_inline constexpr int Nsimd(void) { return sizeof(vector_type)/sizeof(scalar_type); }
|
||||
|
||||
|
||||
template <class T, typename std::enable_if<!isGridTensor<T>::value, T>::type * = nullptr>
|
||||
accelerator_inline auto operator=(T arg) -> iVector<vtype, N> {
|
||||
strong_inline auto operator=(T arg) -> iVector<vtype, N> {
|
||||
zeroit(*this);
|
||||
for (int i = 0; i < N; i++) _internal[i] = arg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 };
|
||||
accelerator_inline iVector(const Zero &z) { zeroit(*this); };
|
||||
accelerator iVector() = default;
|
||||
accelerator_inline iVector(const Zero &z) { zeroit(*this); };
|
||||
|
||||
accelerator_inline iVector<vtype, N> &operator=(const Zero &hero) {
|
||||
zeroit(*this);
|
||||
@ -281,6 +271,15 @@ public:
|
||||
stream << "}";
|
||||
return stream;
|
||||
};
|
||||
// strong_inline vtype && operator ()(int i) {
|
||||
// return _internal[i];
|
||||
// }
|
||||
|
||||
strong_inline const scalar_type * begin() const { return reinterpret_cast<const scalar_type *>(_internal); }
|
||||
strong_inline scalar_type * begin() { return reinterpret_cast< scalar_type *>(_internal); }
|
||||
strong_inline const scalar_type * end() const { return begin() + Traits::count; }
|
||||
strong_inline scalar_type * end() { return begin() + Traits::count; }
|
||||
|
||||
};
|
||||
|
||||
template <class vtype, int N>
|
||||
@ -288,25 +287,9 @@ class iMatrix {
|
||||
public:
|
||||
vtype _internal[N][N];
|
||||
|
||||
typedef vtype element;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_type scalar_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_type vector_type;
|
||||
typedef typename GridTypeMapper<vtype>::vector_typeD vector_typeD;
|
||||
typedef typename GridTypeMapper<vtype>::tensor_reduced tensor_reduced_v;
|
||||
typedef typename GridTypeMapper<vtype>::scalar_object recurse_scalar_object;
|
||||
using Traits = GridTypeMapper<iMatrix<vtype, N> >;
|
||||
|
||||
// substitutes a real or complex version with same tensor structure
|
||||
typedef iMatrix<typename GridTypeMapper<vtype>::Complexified, N> Complexified;
|
||||
typedef iMatrix<typename GridTypeMapper<vtype>::Realified, N> Realified;
|
||||
|
||||
// get double precision version
|
||||
typedef iMatrix<typename GridTypeMapper<vtype>::DoublePrecision, N> DoublePrecision;
|
||||
|
||||
// Tensor removal
|
||||
typedef iScalar<tensor_reduced_v> tensor_reduced;
|
||||
typedef iMatrix<recurse_scalar_object, N> scalar_object;
|
||||
|
||||
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 };
|
||||
GridVector_CopyTraits;
|
||||
|
||||
static accelerator_inline constexpr int Nsimd(void) { return sizeof(vector_type)/sizeof(scalar_type); }
|
||||
|
||||
@ -428,6 +411,14 @@ public:
|
||||
return stream;
|
||||
};
|
||||
|
||||
// strong_inline vtype && operator ()(int i,int j) {
|
||||
// return _internal[i][j];
|
||||
// }
|
||||
|
||||
strong_inline const scalar_type * begin() const { return reinterpret_cast<const scalar_type *>(_internal[0]); }
|
||||
strong_inline scalar_type * begin() { return reinterpret_cast< scalar_type *>(_internal[0]); }
|
||||
strong_inline const scalar_type * end() const { return begin() + Traits::count; }
|
||||
strong_inline scalar_type * end() { return begin() + Traits::count; }
|
||||
};
|
||||
|
||||
template <class v> accelerator_inline
|
||||
@ -451,4 +442,3 @@ void vprefetch(const iMatrix<v, N> &vv) {
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
|
||||
#endif
|
||||
|
@ -1,10 +1,11 @@
|
||||
/*************************************************************************************
|
||||
/*************************************************************************************
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
Source file: ./lib/tensors/Tensor_traits.h
|
||||
Copyright (C) 2015
|
||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
Author: Christopher Kelly <ckelly@phys.columbia.edu>
|
||||
Author: Michael Marshall <michael.marshall@ed.ac.au>
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
@ -17,14 +18,25 @@ Author: Christopher Kelly <ckelly@phys.columbia.edu>
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
See the full license in the file "LICENSE" in the top level distribution directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#ifndef GRID_MATH_TRAITS_H
|
||||
#define GRID_MATH_TRAITS_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
NAMESPACE_BEGIN(Grid);
|
||||
namespace Grid {
|
||||
|
||||
// Forward declarations
|
||||
template<class T> class iScalar;
|
||||
template<class T, int N> class iVector;
|
||||
template<class T, int N> class iMatrix;
|
||||
|
||||
// These are the Grid tensors
|
||||
template<typename T> struct isGridTensor : public std::false_type { static constexpr bool notvalue = true; };
|
||||
template<class T> struct isGridTensor<iScalar<T>> : public std::true_type { static constexpr bool notvalue = false; };
|
||||
template<class T, int N> struct isGridTensor<iVector<T, N>> : public std::true_type { static constexpr bool notvalue = false; };
|
||||
template<class T, int N> struct isGridTensor<iMatrix<T, N>> : public std::true_type { static constexpr bool notvalue = false; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Want to recurse: GridTypeMapper<Matrix<vComplexD> >::scalar_type == ComplexD.
|
||||
@ -40,258 +52,236 @@ NAMESPACE_BEGIN(Grid);
|
||||
// to study C++11's type_traits.h file. (std::enable_if<isGridTensorType<vtype> >)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T> class GridTypeMapper {
|
||||
public:
|
||||
typedef typename T::scalar_type scalar_type;
|
||||
typedef typename T::vector_type vector_type;
|
||||
typedef typename T::vector_typeD vector_typeD;
|
||||
typedef typename T::tensor_reduced tensor_reduced;
|
||||
typedef typename T::scalar_object scalar_object;
|
||||
typedef typename T::Complexified Complexified;
|
||||
typedef typename T::Realified Realified;
|
||||
typedef typename T::DoublePrecision DoublePrecision;
|
||||
enum { TensorLevel = T::TensorLevel };
|
||||
};
|
||||
|
||||
// This saves repeating common properties for supported Grid Scalar types
|
||||
// TensorLevel How many nested grid tensors
|
||||
// Rank Rank of the grid tensor
|
||||
// count Total number of elements, i.e. product of dimensions
|
||||
// Dimension(dim) Size of dimension dim
|
||||
struct GridTypeMapper_Base {
|
||||
static constexpr int TensorLevel = 0;
|
||||
static constexpr int Rank = 0;
|
||||
static constexpr std::size_t count = 1;
|
||||
static constexpr int Dimension(int dim) { return 0; }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Recursion stops with these template specialisations
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
template<> class GridTypeMapper<RealF> {
|
||||
public:
|
||||
typedef RealF scalar_type;
|
||||
typedef RealF vector_type;
|
||||
typedef RealD vector_typeD;
|
||||
typedef RealF tensor_reduced ;
|
||||
typedef RealF scalar_object;
|
||||
typedef ComplexF Complexified;
|
||||
typedef RealF Realified;
|
||||
typedef RealD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<RealD> {
|
||||
public:
|
||||
typedef RealD scalar_type;
|
||||
typedef RealD vector_type;
|
||||
typedef RealD vector_typeD;
|
||||
typedef RealD tensor_reduced;
|
||||
typedef RealD scalar_object;
|
||||
typedef ComplexD Complexified;
|
||||
typedef RealD Realified;
|
||||
typedef RealD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<ComplexF> {
|
||||
public:
|
||||
typedef ComplexF scalar_type;
|
||||
typedef ComplexF vector_type;
|
||||
typedef ComplexD vector_typeD;
|
||||
typedef ComplexF tensor_reduced;
|
||||
typedef ComplexF scalar_object;
|
||||
typedef ComplexF Complexified;
|
||||
typedef RealF Realified;
|
||||
typedef ComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<ComplexD> {
|
||||
public:
|
||||
typedef ComplexD scalar_type;
|
||||
typedef ComplexD vector_type;
|
||||
typedef ComplexD vector_typeD;
|
||||
typedef ComplexD tensor_reduced;
|
||||
typedef ComplexD scalar_object;
|
||||
typedef ComplexD Complexified;
|
||||
typedef RealD Realified;
|
||||
typedef ComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<Integer> {
|
||||
public:
|
||||
typedef Integer scalar_type;
|
||||
typedef Integer vector_type;
|
||||
typedef Integer vector_typeD;
|
||||
typedef Integer tensor_reduced;
|
||||
typedef Integer scalar_object;
|
||||
typedef void Complexified;
|
||||
typedef void Realified;
|
||||
typedef void DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
|
||||
template<> class GridTypeMapper<vRealF> {
|
||||
public:
|
||||
typedef RealF scalar_type;
|
||||
typedef vRealF vector_type;
|
||||
typedef vRealD vector_typeD;
|
||||
typedef vRealF tensor_reduced;
|
||||
typedef RealF scalar_object;
|
||||
typedef vComplexF Complexified;
|
||||
typedef vRealF Realified;
|
||||
typedef vRealD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vRealD> {
|
||||
public:
|
||||
typedef RealD scalar_type;
|
||||
typedef vRealD vector_type;
|
||||
typedef vRealD vector_typeD;
|
||||
typedef vRealD tensor_reduced;
|
||||
typedef RealD scalar_object;
|
||||
typedef vComplexD Complexified;
|
||||
typedef vRealD Realified;
|
||||
typedef vRealD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vComplexH> {
|
||||
public:
|
||||
typedef ComplexF scalar_type;
|
||||
typedef vComplexH vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
typedef vComplexH tensor_reduced;
|
||||
typedef ComplexF scalar_object;
|
||||
typedef vComplexH Complexified;
|
||||
typedef vRealH Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vComplexF> {
|
||||
public:
|
||||
typedef ComplexF scalar_type;
|
||||
typedef vComplexF vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
typedef vComplexF tensor_reduced;
|
||||
typedef ComplexF scalar_object;
|
||||
typedef vComplexF Complexified;
|
||||
typedef vRealF Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vComplexD> {
|
||||
public:
|
||||
typedef ComplexD scalar_type;
|
||||
typedef vComplexD vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
typedef vComplexD tensor_reduced;
|
||||
typedef ComplexD scalar_object;
|
||||
typedef vComplexD Complexified;
|
||||
typedef vRealD Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<> class GridTypeMapper<vInteger> {
|
||||
public:
|
||||
typedef Integer scalar_type;
|
||||
typedef vInteger vector_type;
|
||||
typedef vInteger vector_typeD;
|
||||
typedef vInteger tensor_reduced;
|
||||
typedef Integer scalar_object;
|
||||
typedef void Complexified;
|
||||
typedef void Realified;
|
||||
typedef void DoublePrecision;
|
||||
enum { TensorLevel = 0 };
|
||||
};
|
||||
template<typename T> struct GridTypeMapper {};
|
||||
|
||||
// First some of my own traits
|
||||
template<typename T> struct isGridTensor {
|
||||
static const bool value = true;
|
||||
static const bool notvalue = false;
|
||||
};
|
||||
template<> struct isGridTensor<int > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<RealD > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<RealF > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<ComplexD > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<ComplexF > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<Integer > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vRealD > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vRealF > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vComplexD > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vComplexF > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct isGridTensor<vInteger > {
|
||||
static const bool value = false;
|
||||
static const bool notvalue = true;
|
||||
};
|
||||
template<> struct GridTypeMapper<RealF> : public GridTypeMapper_Base {
|
||||
typedef RealF scalar_type;
|
||||
typedef RealF vector_type;
|
||||
typedef RealD vector_typeD;
|
||||
typedef RealF tensor_reduced ;
|
||||
typedef RealF scalar_object;
|
||||
typedef ComplexF Complexified;
|
||||
typedef RealF Realified;
|
||||
typedef RealD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<RealD> : public GridTypeMapper_Base {
|
||||
typedef RealD scalar_type;
|
||||
typedef RealD vector_type;
|
||||
typedef RealD vector_typeD;
|
||||
typedef RealD tensor_reduced;
|
||||
typedef RealD scalar_object;
|
||||
typedef ComplexD Complexified;
|
||||
typedef RealD Realified;
|
||||
typedef RealD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<ComplexF> : public GridTypeMapper_Base {
|
||||
typedef ComplexF scalar_type;
|
||||
typedef ComplexF vector_type;
|
||||
typedef ComplexD vector_typeD;
|
||||
typedef ComplexF tensor_reduced;
|
||||
typedef ComplexF scalar_object;
|
||||
typedef ComplexF Complexified;
|
||||
typedef RealF Realified;
|
||||
typedef ComplexD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<ComplexD> : public GridTypeMapper_Base {
|
||||
typedef ComplexD scalar_type;
|
||||
typedef ComplexD vector_type;
|
||||
typedef ComplexD vector_typeD;
|
||||
typedef ComplexD tensor_reduced;
|
||||
typedef ComplexD scalar_object;
|
||||
typedef ComplexD Complexified;
|
||||
typedef RealD Realified;
|
||||
typedef ComplexD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<Integer> : public GridTypeMapper_Base {
|
||||
typedef Integer scalar_type;
|
||||
typedef Integer vector_type;
|
||||
typedef Integer vector_typeD;
|
||||
typedef Integer tensor_reduced;
|
||||
typedef Integer scalar_object;
|
||||
typedef void Complexified;
|
||||
typedef void Realified;
|
||||
typedef void DoublePrecision;
|
||||
};
|
||||
|
||||
// Match the index
|
||||
template<typename T,int Level> struct matchGridTensorIndex {
|
||||
static const bool value = (Level==T::TensorLevel);
|
||||
static const bool notvalue = (Level!=T::TensorLevel);
|
||||
};
|
||||
// What is the vtype
|
||||
template<typename T> struct isComplex {
|
||||
static const bool value = false;
|
||||
};
|
||||
template<> struct isComplex<ComplexF> {
|
||||
static const bool value = true;
|
||||
};
|
||||
template<> struct isComplex<ComplexD> {
|
||||
static const bool value = true;
|
||||
};
|
||||
template<> struct GridTypeMapper<vRealF> : public GridTypeMapper_Base {
|
||||
typedef RealF scalar_type;
|
||||
typedef vRealF vector_type;
|
||||
typedef vRealD vector_typeD;
|
||||
typedef vRealF tensor_reduced;
|
||||
typedef RealF scalar_object;
|
||||
typedef vComplexF Complexified;
|
||||
typedef vRealF Realified;
|
||||
typedef vRealD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<vRealD> : public GridTypeMapper_Base {
|
||||
typedef RealD scalar_type;
|
||||
typedef vRealD vector_type;
|
||||
typedef vRealD vector_typeD;
|
||||
typedef vRealD tensor_reduced;
|
||||
typedef RealD scalar_object;
|
||||
typedef vComplexD Complexified;
|
||||
typedef vRealD Realified;
|
||||
typedef vRealD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<vRealH> : public GridTypeMapper_Base {
|
||||
// Fixme this is incomplete until Grid supports fp16 or bfp16 arithmetic types
|
||||
typedef RealF scalar_type;
|
||||
typedef vRealH vector_type;
|
||||
typedef vRealD vector_typeD;
|
||||
typedef vRealH tensor_reduced;
|
||||
typedef RealF scalar_object;
|
||||
typedef vComplexH Complexified;
|
||||
typedef vRealH Realified;
|
||||
typedef vRealD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<vComplexH> : public GridTypeMapper_Base {
|
||||
// Fixme this is incomplete until Grid supports fp16 or bfp16 arithmetic types
|
||||
typedef ComplexF scalar_type;
|
||||
typedef vComplexH vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
typedef vComplexH tensor_reduced;
|
||||
typedef ComplexF scalar_object;
|
||||
typedef vComplexH Complexified;
|
||||
typedef vRealH Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<vComplexF> : public GridTypeMapper_Base {
|
||||
typedef ComplexF scalar_type;
|
||||
typedef vComplexF vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
typedef vComplexF tensor_reduced;
|
||||
typedef ComplexF scalar_object;
|
||||
typedef vComplexF Complexified;
|
||||
typedef vRealF Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<vComplexD> : public GridTypeMapper_Base {
|
||||
typedef ComplexD scalar_type;
|
||||
typedef vComplexD vector_type;
|
||||
typedef vComplexD vector_typeD;
|
||||
typedef vComplexD tensor_reduced;
|
||||
typedef ComplexD scalar_object;
|
||||
typedef vComplexD Complexified;
|
||||
typedef vRealD Realified;
|
||||
typedef vComplexD DoublePrecision;
|
||||
};
|
||||
template<> struct GridTypeMapper<vInteger> : public GridTypeMapper_Base {
|
||||
typedef Integer scalar_type;
|
||||
typedef vInteger vector_type;
|
||||
typedef vInteger vector_typeD;
|
||||
typedef vInteger tensor_reduced;
|
||||
typedef Integer scalar_object;
|
||||
typedef void Complexified;
|
||||
typedef void Realified;
|
||||
typedef void DoublePrecision;
|
||||
};
|
||||
|
||||
//Get the SIMD vector type from a Grid tensor or Lattice<Tensor>
|
||||
template<typename T>
|
||||
struct getVectorType{
|
||||
typedef T type;
|
||||
};
|
||||
#define GridTypeMapper_RepeatedTypes \
|
||||
using BaseTraits = GridTypeMapper<T>; \
|
||||
using scalar_type = typename BaseTraits::scalar_type; \
|
||||
using vector_type = typename BaseTraits::vector_type; \
|
||||
using vector_typeD = typename BaseTraits::vector_typeD; \
|
||||
static constexpr int TensorLevel = BaseTraits::TensorLevel + 1
|
||||
|
||||
template<typename T> struct GridTypeMapper<iScalar<T>> {
|
||||
GridTypeMapper_RepeatedTypes;
|
||||
using tensor_reduced = iScalar<typename BaseTraits::tensor_reduced>;
|
||||
using scalar_object = iScalar<typename BaseTraits::scalar_object>;
|
||||
using Complexified = iScalar<typename BaseTraits::Complexified>;
|
||||
using Realified = iScalar<typename BaseTraits::Realified>;
|
||||
using DoublePrecision = iScalar<typename BaseTraits::DoublePrecision>;
|
||||
static constexpr int Rank = BaseTraits::Rank + 1;
|
||||
static constexpr std::size_t count = BaseTraits::count;
|
||||
static constexpr int Dimension(int dim) {
|
||||
return ( dim == 0 ) ? 1 : BaseTraits::Dimension(dim - 1); }
|
||||
};
|
||||
|
||||
template<typename T, int N> struct GridTypeMapper<iVector<T, N>> {
|
||||
GridTypeMapper_RepeatedTypes;
|
||||
using tensor_reduced = iScalar<typename BaseTraits::tensor_reduced>;
|
||||
using scalar_object = iVector<typename BaseTraits::scalar_object, N>;
|
||||
using Complexified = iVector<typename BaseTraits::Complexified, N>;
|
||||
using Realified = iVector<typename BaseTraits::Realified, N>;
|
||||
using DoublePrecision = iVector<typename BaseTraits::DoublePrecision, N>;
|
||||
static constexpr int Rank = BaseTraits::Rank + 1;
|
||||
static constexpr std::size_t count = BaseTraits::count * N;
|
||||
static constexpr int Dimension(int dim) {
|
||||
return ( dim == 0 ) ? N : BaseTraits::Dimension(dim - 1); }
|
||||
};
|
||||
|
||||
template<typename T, int N> struct GridTypeMapper<iMatrix<T, N>> {
|
||||
GridTypeMapper_RepeatedTypes;
|
||||
using tensor_reduced = iScalar<typename BaseTraits::tensor_reduced>;
|
||||
using scalar_object = iMatrix<typename BaseTraits::scalar_object, N>;
|
||||
using Complexified = iMatrix<typename BaseTraits::Complexified, N>;
|
||||
using Realified = iMatrix<typename BaseTraits::Realified, N>;
|
||||
using DoublePrecision = iMatrix<typename BaseTraits::DoublePrecision, N>;
|
||||
static constexpr int Rank = BaseTraits::Rank + 2;
|
||||
static constexpr std::size_t count = BaseTraits::count * N * N;
|
||||
static constexpr int Dimension(int dim) {
|
||||
return ( dim == 0 || dim == 1 ) ? N : BaseTraits::Dimension(dim - 2); }
|
||||
};
|
||||
|
||||
// Match the index
|
||||
template<typename T,int Level> struct matchGridTensorIndex {
|
||||
static const bool value = (Level==T::TensorLevel);
|
||||
static const bool notvalue = (Level!=T::TensorLevel);
|
||||
};
|
||||
// What is the vtype
|
||||
template<typename T> struct isComplex {
|
||||
static const bool value = false;
|
||||
};
|
||||
template<> struct isComplex<ComplexF> {
|
||||
static const bool value = true;
|
||||
};
|
||||
template<> struct isComplex<ComplexD> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
//Get the SIMD vector type from a Grid tensor or Lattice<Tensor>
|
||||
template<typename T>
|
||||
struct getVectorType{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
//Query if a tensor or Lattice<Tensor> is SIMD vector or scalar
|
||||
template<typename T>
|
||||
class isSIMDvectorized{
|
||||
template<typename U>
|
||||
static typename std::enable_if<
|
||||
!std::is_same< typename GridTypeMapper<typename getVectorType<U>::type>::scalar_type,
|
||||
typename GridTypeMapper<typename getVectorType<U>::type>::vector_type>::value,
|
||||
char>::type test(void *);
|
||||
//Query whether a tensor or Lattice<Tensor> is SIMD vector or scalar
|
||||
template<typename T, typename V=void> struct isSIMDvectorized : public std::false_type {};
|
||||
template<typename U> struct isSIMDvectorized<U, typename std::enable_if< !std::is_same<
|
||||
typename GridTypeMapper<typename getVectorType<U>::type>::scalar_type,
|
||||
typename GridTypeMapper<typename getVectorType<U>::type>::vector_type>::value, void>::type>
|
||||
: public std::true_type {};
|
||||
|
||||
template<typename U> static double test(...);
|
||||
|
||||
public:
|
||||
enum {value = sizeof(test<T>(0)) == sizeof(char) };
|
||||
};
|
||||
|
||||
//Get the precision of a Lattice, tensor or scalar type in units of sizeof(float)
|
||||
template<typename T>
|
||||
class getPrecision{
|
||||
public:
|
||||
//get the vector_obj (i.e. a grid Tensor) if its a Lattice<vobj>, do nothing otherwise (i.e. if fundamental or grid Tensor)
|
||||
typedef typename getVectorType<T>::type vector_obj;
|
||||
typedef typename GridTypeMapper<vector_obj>::scalar_type scalar_type; //get the associated scalar type. Works on fundamental and tensor types
|
||||
typedef typename GridTypeMapper<scalar_type>::Realified real_scalar_type; //remove any std::complex wrapper, should get us to the fundamental type
|
||||
|
||||
enum { value = sizeof(real_scalar_type)/sizeof(float) };
|
||||
};
|
||||
|
||||
NAMESPACE_END(Grid);
|
||||
//Get the precision of a Lattice, tensor or scalar type in units of sizeof(float)
|
||||
template<typename T>
|
||||
class getPrecision{
|
||||
public:
|
||||
//get the vector_obj (i.e. a grid Tensor) if its a Lattice<vobj>, do nothing otherwise (i.e. if fundamental or grid Tensor)
|
||||
typedef typename getVectorType<T>::type vector_obj;
|
||||
typedef typename GridTypeMapper<vector_obj>::scalar_type scalar_type; //get the associated scalar type. Works on fundamental and tensor types
|
||||
typedef typename GridTypeMapper<scalar_type>::Realified real_scalar_type; //remove any std::complex wrapper, should get us to the fundamental type
|
||||
|
||||
enum { value = sizeof(real_scalar_type)/sizeof(float) };
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -272,6 +272,11 @@ void GridBanner(void)
|
||||
std::cout << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"<<std::endl;
|
||||
std::cout << "GNU General Public License for more details."<<std::endl;
|
||||
printHash();
|
||||
#ifdef GRID_BUILD_REF
|
||||
#define _GRID_BUILD_STR(x) #x
|
||||
#define GRID_BUILD_STR(x) _GRID_BUILD_STR(x)
|
||||
std::cout << "Build " << GRID_BUILD_STR(GRID_BUILD_REF) << std::endl;
|
||||
#endif
|
||||
std::cout << std::endl;
|
||||
printed=1;
|
||||
}
|
||||
@ -419,7 +424,6 @@ void Grid_init(int *argc,char ***argv)
|
||||
MemoryProfiler::stats = &dbgMemStats;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////
|
||||
// Logging
|
||||
////////////////////////////////////
|
||||
|
6
HMC/Makefile.am
Normal file
6
HMC/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
||||
SUBDIRS = .
|
||||
|
||||
include Make.inc
|
||||
|
||||
|
||||
|
198
HMC/Mobius2p1f.cc
Normal file
198
HMC/Mobius2p1f.cc
Normal file
@ -0,0 +1,198 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./tests/Test_hmc_EODWFRatio.cc
|
||||
|
||||
Copyright (C) 2015-2016
|
||||
|
||||
Author: Peter Boyle <pabobyle@ph.ed.ac.uk>
|
||||
Author: Guido Cossu <guido.cossu@ed.ac.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution
|
||||
directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#include <Grid/Grid.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
using namespace Grid;
|
||||
using namespace Grid::QCD;
|
||||
|
||||
Grid_init(&argc, &argv);
|
||||
int threads = GridThread::GetThreads();
|
||||
// here make a routine to print all the relevant information on the run
|
||||
std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl;
|
||||
|
||||
// Typedefs to simplify notation
|
||||
typedef WilsonImplR FermionImplPolicy;
|
||||
typedef MobiusFermionR FermionAction;
|
||||
typedef typename FermionAction::FermionField FermionField;
|
||||
|
||||
typedef Grid::XmlReader Serialiser;
|
||||
|
||||
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
IntegratorParameters MD;
|
||||
// typedef GenericHMCRunner<LeapFrog> HMCWrapper;
|
||||
// MD.name = std::string("Leap Frog");
|
||||
// typedef GenericHMCRunner<ForceGradient> HMCWrapper;
|
||||
// MD.name = std::string("Force Gradient");
|
||||
typedef GenericHMCRunner<MinimumNorm2> HMCWrapper;
|
||||
MD.name = std::string("MinimumNorm2");
|
||||
MD.MDsteps = 20;
|
||||
MD.trajL = 1.0;
|
||||
|
||||
HMCparameters HMCparams;
|
||||
HMCparams.StartTrajectory = 0;
|
||||
HMCparams.Trajectories = 200;
|
||||
HMCparams.NoMetropolisUntil= 20;
|
||||
// "[HotStart, ColdStart, TepidStart, CheckpointStart]\n";
|
||||
HMCparams.StartingType =std::string("ColdStart");
|
||||
HMCparams.MD = MD;
|
||||
HMCWrapper TheHMC(HMCparams);
|
||||
|
||||
// Grid from the command line arguments --grid and --mpi
|
||||
TheHMC.Resources.AddFourDimGrid("gauge"); // use default simd lanes decomposition
|
||||
|
||||
CheckpointerParameters CPparams;
|
||||
CPparams.config_prefix = "ckpoint_EODWF_lat";
|
||||
CPparams.rng_prefix = "ckpoint_EODWF_rng";
|
||||
CPparams.saveInterval = 10;
|
||||
CPparams.format = "IEEE64BIG";
|
||||
TheHMC.Resources.LoadNerscCheckpointer(CPparams);
|
||||
|
||||
RNGModuleParameters RNGpar;
|
||||
RNGpar.serial_seeds = "1 2 3 4 5";
|
||||
RNGpar.parallel_seeds = "6 7 8 9 10";
|
||||
TheHMC.Resources.SetRNGSeeds(RNGpar);
|
||||
|
||||
// Construct observables
|
||||
// here there is too much indirection
|
||||
typedef PlaquetteMod<HMCWrapper::ImplPolicy> PlaqObs;
|
||||
TheHMC.Resources.AddObservable<PlaqObs>();
|
||||
//////////////////////////////////////////////
|
||||
|
||||
const int Ls = 16;
|
||||
Real beta = 2.13;
|
||||
Real light_mass = 0.01;
|
||||
Real strange_mass = 0.04;
|
||||
Real pv_mass = 1.0;
|
||||
RealD M5 = 1.8;
|
||||
RealD b = 1.0; // Scale factor two
|
||||
RealD c = 0.0;
|
||||
|
||||
OneFlavourRationalParams OFRp;
|
||||
OFRp.lo = 1.0e-2;
|
||||
OFRp.hi = 64;
|
||||
OFRp.MaxIter = 10000;
|
||||
OFRp.tolerance= 1.0e-10;
|
||||
OFRp.degree = 14;
|
||||
OFRp.precision= 40;
|
||||
|
||||
std::vector<Real> hasenbusch({ 0.1 });
|
||||
|
||||
auto GridPtr = TheHMC.Resources.GetCartesian();
|
||||
auto GridRBPtr = TheHMC.Resources.GetRBCartesian();
|
||||
auto FGrid = SpaceTimeGrid::makeFiveDimGrid(Ls,GridPtr);
|
||||
auto FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,GridPtr);
|
||||
|
||||
IwasakiGaugeActionR GaugeAction(beta);
|
||||
|
||||
// temporarily need a gauge field
|
||||
LatticeGaugeField U(GridPtr);
|
||||
|
||||
// These lines are unecessary if BC are all periodic
|
||||
std::vector<Complex> boundary = {1,1,1,-1};
|
||||
FermionAction::ImplParams Params(boundary);
|
||||
|
||||
double StoppingCondition = 1e-10;
|
||||
double MaxCGIterations = 30000;
|
||||
ConjugateGradient<FermionField> CG(StoppingCondition,MaxCGIterations);
|
||||
|
||||
////////////////////////////////////
|
||||
// Collect actions
|
||||
////////////////////////////////////
|
||||
ActionLevel<HMCWrapper::Field> Level1(1);
|
||||
ActionLevel<HMCWrapper::Field> Level2(4);
|
||||
|
||||
////////////////////////////////////
|
||||
// Strange action
|
||||
////////////////////////////////////
|
||||
|
||||
// FermionAction StrangeOp(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_mass,M5,b,c, Params);
|
||||
// DomainWallEOFAFermionR Strange_Op_L(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, shift_L, pm, M5);
|
||||
// DomainWallEOFAFermionR Strange_Op_R(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, shift_R, pm, M5);
|
||||
// ExactOneFlavourRatioPseudoFermionAction EOFA(Strange_Op_L,Strange_Op_R,CG,ofp, false);
|
||||
|
||||
FermionAction StrangeOp (U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,strange_mass,M5,b,c, Params);
|
||||
FermionAction StrangePauliVillarsOp(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,pv_mass, M5,b,c, Params);
|
||||
|
||||
// OneFlavourEvenOddRatioRationalPseudoFermionAction<FermionImplPolicy> StrangePseudoFermion(StrangePauliVillarsOp,StrangeOp,OFRp);
|
||||
OneFlavourRatioRationalPseudoFermionAction<FermionImplPolicy> StrangePseudoFermion(StrangePauliVillarsOp,StrangeOp,OFRp);
|
||||
// TwoFlavourRationalTesterPseudoFermionAction<FermionImplPolicy> StrangePseudoFermion1F(StrangeOp,OFRp);
|
||||
// TwoFlavourPseudoFermionAction<FermionImplPolicy> StrangePseudoFermion2F(StrangeOp,CG,CG);
|
||||
// Level1.push_back(&StrangePseudoFermion2F);
|
||||
// Level1.push_back(&StrangePseudoFermion);
|
||||
|
||||
////////////////////////////////////
|
||||
// up down action
|
||||
////////////////////////////////////
|
||||
std::vector<Real> light_den;
|
||||
std::vector<Real> light_num;
|
||||
|
||||
int n_hasenbusch = hasenbusch.size();
|
||||
light_den.push_back(light_mass);
|
||||
for(int h=0;h<n_hasenbusch;h++){
|
||||
light_den.push_back(hasenbusch[h]);
|
||||
light_num.push_back(hasenbusch[h]);
|
||||
}
|
||||
light_num.push_back(pv_mass);
|
||||
|
||||
std::vector<FermionAction *> Numerators;
|
||||
std::vector<FermionAction *> Denominators;
|
||||
std::vector<TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy> *> Quotients;
|
||||
|
||||
for(int h=0;h<n_hasenbusch+1;h++){
|
||||
std::cout << GridLogMessage << " 2f quotient Action "<< light_num[h] << " / " << light_den[h]<< std::endl;
|
||||
Numerators.push_back (new FermionAction(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_num[h],M5,b,c, Params));
|
||||
Denominators.push_back(new FermionAction(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_den[h],M5,b,c, Params));
|
||||
Quotients.push_back (new TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy>(*Numerators[h],*Denominators[h],CG,CG));
|
||||
}
|
||||
|
||||
for(int h=0;h<n_hasenbusch+1;h++){
|
||||
Level1.push_back(Quotients[h]);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Gauge action
|
||||
/////////////////////////////////////////////////////////////
|
||||
Level2.push_back(&GaugeAction);
|
||||
TheHMC.TheAction.push_back(Level1);
|
||||
TheHMC.TheAction.push_back(Level2);
|
||||
std::cout << GridLogMessage << " Action complete "<< std::endl;
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// HMC parameters are serialisable
|
||||
|
||||
std::cout << GridLogMessage << " Running the HMC "<< std::endl;
|
||||
TheHMC.Run(); // no smearing
|
||||
|
||||
Grid_finalize();
|
||||
} // main
|
||||
|
||||
|
||||
|
449
HMC/Mobius2p1fEOFA.cc
Normal file
449
HMC/Mobius2p1fEOFA.cc
Normal file
@ -0,0 +1,449 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file:
|
||||
|
||||
Copyright (C) 2015-2016
|
||||
|
||||
Author: Peter Boyle <pabobyle@ph.ed.ac.uk>
|
||||
Author: Guido Cossu
|
||||
Author: David Murphy
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution
|
||||
directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#include <Grid/Grid.h>
|
||||
|
||||
#define MIXED_PRECISION
|
||||
|
||||
namespace Grid{
|
||||
namespace QCD{
|
||||
|
||||
/*
|
||||
* Need a plan for gauge field update for mixed precision in HMC (2x speed up)
|
||||
* -- Store the single prec action operator.
|
||||
* -- Clone the gauge field from the operator function argument.
|
||||
* -- Build the mixed precision operator dynamically from the passed operator and single prec clone.
|
||||
*/
|
||||
|
||||
template<class FermionOperatorD, class FermionOperatorF, class SchurOperatorD, class SchurOperatorF>
|
||||
class MixedPrecisionConjugateGradientOperatorFunction : public OperatorFunction<typename FermionOperatorD::FermionField> {
|
||||
public:
|
||||
typedef typename FermionOperatorD::FermionField FieldD;
|
||||
typedef typename FermionOperatorF::FermionField FieldF;
|
||||
|
||||
RealD Tolerance;
|
||||
RealD InnerTolerance; //Initial tolerance for inner CG. Defaults to Tolerance but can be changed
|
||||
Integer MaxInnerIterations;
|
||||
Integer MaxOuterIterations;
|
||||
GridBase* SinglePrecGrid4; //Grid for single-precision fields
|
||||
GridBase* SinglePrecGrid5; //Grid for single-precision fields
|
||||
RealD OuterLoopNormMult; //Stop the outer loop and move to a final double prec solve when the residual is OuterLoopNormMult * Tolerance
|
||||
|
||||
FermionOperatorF &FermOpF;
|
||||
FermionOperatorD &FermOpD;;
|
||||
SchurOperatorF &LinOpF;
|
||||
SchurOperatorD &LinOpD;
|
||||
|
||||
Integer TotalInnerIterations; //Number of inner CG iterations
|
||||
Integer TotalOuterIterations; //Number of restarts
|
||||
Integer TotalFinalStepIterations; //Number of CG iterations in final patch-up step
|
||||
|
||||
MixedPrecisionConjugateGradientOperatorFunction(RealD tol,
|
||||
Integer maxinnerit,
|
||||
Integer maxouterit,
|
||||
GridBase* _sp_grid4,
|
||||
GridBase* _sp_grid5,
|
||||
FermionOperatorF &_FermOpF,
|
||||
FermionOperatorD &_FermOpD,
|
||||
SchurOperatorF &_LinOpF,
|
||||
SchurOperatorD &_LinOpD):
|
||||
LinOpF(_LinOpF),
|
||||
LinOpD(_LinOpD),
|
||||
FermOpF(_FermOpF),
|
||||
FermOpD(_FermOpD),
|
||||
Tolerance(tol),
|
||||
InnerTolerance(tol),
|
||||
MaxInnerIterations(maxinnerit),
|
||||
MaxOuterIterations(maxouterit),
|
||||
SinglePrecGrid4(_sp_grid4),
|
||||
SinglePrecGrid5(_sp_grid5),
|
||||
OuterLoopNormMult(100.)
|
||||
{
|
||||
/* Debugging instances of objects; references are stored
|
||||
std::cout << GridLogMessage << " Mixed precision CG wrapper LinOpF " <<std::hex<< &LinOpF<<std::dec <<std::endl;
|
||||
std::cout << GridLogMessage << " Mixed precision CG wrapper LinOpD " <<std::hex<< &LinOpD<<std::dec <<std::endl;
|
||||
std::cout << GridLogMessage << " Mixed precision CG wrapper FermOpF " <<std::hex<< &FermOpF<<std::dec <<std::endl;
|
||||
std::cout << GridLogMessage << " Mixed precision CG wrapper FermOpD " <<std::hex<< &FermOpD<<std::dec <<std::endl;
|
||||
*/
|
||||
};
|
||||
|
||||
void operator()(LinearOperatorBase<FieldD> &LinOpU, const FieldD &src, FieldD &psi) {
|
||||
|
||||
std::cout << GridLogMessage << " Mixed precision CG wrapper operator() "<<std::endl;
|
||||
|
||||
SchurOperatorD * SchurOpU = static_cast<SchurOperatorD *>(&LinOpU);
|
||||
|
||||
// std::cout << GridLogMessage << " Mixed precision CG wrapper operator() FermOpU " <<std::hex<< &(SchurOpU->_Mat)<<std::dec <<std::endl;
|
||||
// std::cout << GridLogMessage << " Mixed precision CG wrapper operator() FermOpD " <<std::hex<< &(LinOpD._Mat) <<std::dec <<std::endl;
|
||||
// Assumption made in code to extract gauge field
|
||||
// We could avoid storing LinopD reference alltogether ?
|
||||
assert(&(SchurOpU->_Mat)==&(LinOpD._Mat));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Must snarf a single precision copy of the gauge field in Linop_d argument
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef typename FermionOperatorF::GaugeField GaugeFieldF;
|
||||
typedef typename FermionOperatorF::GaugeLinkField GaugeLinkFieldF;
|
||||
typedef typename FermionOperatorD::GaugeField GaugeFieldD;
|
||||
typedef typename FermionOperatorD::GaugeLinkField GaugeLinkFieldD;
|
||||
|
||||
GridBase * GridPtrF = SinglePrecGrid4;
|
||||
GridBase * GridPtrD = FermOpD.Umu._grid;
|
||||
GaugeFieldF U_f (GridPtrF);
|
||||
GaugeLinkFieldF Umu_f(GridPtrF);
|
||||
// std::cout << " Dim gauge field "<<GridPtrF->Nd()<<std::endl; // 4d
|
||||
// std::cout << " Dim gauge field "<<GridPtrD->Nd()<<std::endl; // 4d
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Moving this to a Clone method of fermion operator would allow to duplicate the
|
||||
// physics parameters and decrease gauge field copies
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
GaugeLinkFieldD Umu_d(GridPtrD);
|
||||
for(int mu=0;mu<Nd*2;mu++){
|
||||
Umu_d = PeekIndex<LorentzIndex>(FermOpD.Umu, mu);
|
||||
precisionChange(Umu_f,Umu_d);
|
||||
PokeIndex<LorentzIndex>(FermOpF.Umu, Umu_f, mu);
|
||||
}
|
||||
pickCheckerboard(Even,FermOpF.UmuEven,FermOpF.Umu);
|
||||
pickCheckerboard(Odd ,FermOpF.UmuOdd ,FermOpF.Umu);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Could test to make sure that LinOpF and LinOpD agree to single prec?
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
GridBase *Fgrid = psi._grid;
|
||||
FieldD tmp2(Fgrid);
|
||||
FieldD tmp1(Fgrid);
|
||||
LinOpU.Op(src,tmp1);
|
||||
LinOpD.Op(src,tmp2);
|
||||
std::cout << " Double gauge field "<< norm2(FermOpD.Umu)<<std::endl;
|
||||
std::cout << " Single gauge field "<< norm2(FermOpF.Umu)<<std::endl;
|
||||
std::cout << " Test of operators "<<norm2(tmp1)<<std::endl;
|
||||
std::cout << " Test of operators "<<norm2(tmp2)<<std::endl;
|
||||
tmp1=tmp1-tmp2;
|
||||
std::cout << " Test of operators diff "<<norm2(tmp1)<<std::endl;
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Make a mixed precision conjugate gradient
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
MixedPrecisionConjugateGradient<FieldD,FieldF> MPCG(Tolerance,MaxInnerIterations,MaxOuterIterations,SinglePrecGrid5,LinOpF,LinOpD);
|
||||
std::cout << GridLogMessage << "Calling mixed precision Conjugate Gradient" <<std::endl;
|
||||
MPCG(src,psi);
|
||||
}
|
||||
};
|
||||
}};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
using namespace Grid;
|
||||
using namespace Grid::QCD;
|
||||
|
||||
Grid_init(&argc, &argv);
|
||||
int threads = GridThread::GetThreads();
|
||||
// here make a routine to print all the relevant information on the run
|
||||
std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl;
|
||||
|
||||
// Typedefs to simplify notation
|
||||
typedef WilsonImplR FermionImplPolicy;
|
||||
typedef MobiusFermionR FermionAction;
|
||||
typedef MobiusFermionF FermionActionF;
|
||||
typedef MobiusEOFAFermionR FermionEOFAAction;
|
||||
typedef MobiusEOFAFermionF FermionEOFAActionF;
|
||||
typedef typename FermionAction::FermionField FermionField;
|
||||
typedef typename FermionActionF::FermionField FermionFieldF;
|
||||
|
||||
typedef Grid::XmlReader Serialiser;
|
||||
|
||||
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
IntegratorParameters MD;
|
||||
// typedef GenericHMCRunner<LeapFrog> HMCWrapper;
|
||||
// MD.name = std::string("Leap Frog");
|
||||
typedef GenericHMCRunner<ForceGradient> HMCWrapper;
|
||||
MD.name = std::string("Force Gradient");
|
||||
// typedef GenericHMCRunner<MinimumNorm2> HMCWrapper;
|
||||
// MD.name = std::string("MinimumNorm2");
|
||||
MD.MDsteps = 6;
|
||||
MD.trajL = 1.0;
|
||||
|
||||
HMCparameters HMCparams;
|
||||
HMCparams.StartTrajectory = 590;
|
||||
HMCparams.Trajectories = 1000;
|
||||
HMCparams.NoMetropolisUntil= 0;
|
||||
// "[HotStart, ColdStart, TepidStart, CheckpointStart]\n";
|
||||
// HMCparams.StartingType =std::string("ColdStart");
|
||||
HMCparams.StartingType =std::string("CheckpointStart");
|
||||
HMCparams.MD = MD;
|
||||
HMCWrapper TheHMC(HMCparams);
|
||||
|
||||
// Grid from the command line arguments --grid and --mpi
|
||||
TheHMC.Resources.AddFourDimGrid("gauge"); // use default simd lanes decomposition
|
||||
|
||||
CheckpointerParameters CPparams;
|
||||
CPparams.config_prefix = "ckpoint_EODWF_lat";
|
||||
CPparams.rng_prefix = "ckpoint_EODWF_rng";
|
||||
CPparams.saveInterval = 10;
|
||||
CPparams.format = "IEEE64BIG";
|
||||
TheHMC.Resources.LoadNerscCheckpointer(CPparams);
|
||||
|
||||
RNGModuleParameters RNGpar;
|
||||
RNGpar.serial_seeds = "1 2 3 4 5";
|
||||
RNGpar.parallel_seeds = "6 7 8 9 10";
|
||||
TheHMC.Resources.SetRNGSeeds(RNGpar);
|
||||
|
||||
// Construct observables
|
||||
// here there is too much indirection
|
||||
typedef PlaquetteMod<HMCWrapper::ImplPolicy> PlaqObs;
|
||||
TheHMC.Resources.AddObservable<PlaqObs>();
|
||||
//////////////////////////////////////////////
|
||||
|
||||
const int Ls = 16;
|
||||
Real beta = 2.13;
|
||||
Real light_mass = 0.01;
|
||||
Real strange_mass = 0.04;
|
||||
Real pv_mass = 1.0;
|
||||
RealD M5 = 1.8;
|
||||
RealD b = 1.0;
|
||||
RealD c = 0.0;
|
||||
|
||||
std::vector<Real> hasenbusch({ 0.1, 0.3, 0.6 });
|
||||
|
||||
auto GridPtr = TheHMC.Resources.GetCartesian();
|
||||
auto GridRBPtr = TheHMC.Resources.GetRBCartesian();
|
||||
auto FGrid = SpaceTimeGrid::makeFiveDimGrid(Ls,GridPtr);
|
||||
auto FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,GridPtr);
|
||||
|
||||
std::vector<int> latt = GridDefaultLatt();
|
||||
std::vector<int> mpi = GridDefaultMpi();
|
||||
std::vector<int> simdF = GridDefaultSimd(Nd,vComplexF::Nsimd());
|
||||
std::vector<int> simdD = GridDefaultSimd(Nd,vComplexD::Nsimd());
|
||||
auto GridPtrF = SpaceTimeGrid::makeFourDimGrid(latt,simdF,mpi);
|
||||
auto GridRBPtrF = SpaceTimeGrid::makeFourDimRedBlackGrid(GridPtrF);
|
||||
auto FGridF = SpaceTimeGrid::makeFiveDimGrid(Ls,GridPtrF);
|
||||
auto FrbGridF = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,GridPtrF);
|
||||
|
||||
IwasakiGaugeActionR GaugeAction(beta);
|
||||
|
||||
// temporarily need a gauge field
|
||||
LatticeGaugeField U(GridPtr);
|
||||
LatticeGaugeFieldF UF(GridPtrF);
|
||||
|
||||
// These lines are unecessary if BC are all periodic
|
||||
std::vector<Complex> boundary = {1,1,1,-1};
|
||||
FermionAction::ImplParams Params(boundary);
|
||||
FermionActionF::ImplParams ParamsF(boundary);
|
||||
|
||||
double ActionStoppingCondition = 1e-10;
|
||||
double DerivativeStoppingCondition = 1e-6;
|
||||
double MaxCGIterations = 30000;
|
||||
|
||||
////////////////////////////////////
|
||||
// Collect actions
|
||||
////////////////////////////////////
|
||||
ActionLevel<HMCWrapper::Field> Level1(1);
|
||||
ActionLevel<HMCWrapper::Field> Level2(8);
|
||||
|
||||
////////////////////////////////////
|
||||
// Strange action
|
||||
////////////////////////////////////
|
||||
typedef SchurDiagMooeeOperator<FermionActionF,FermionFieldF> LinearOperatorF;
|
||||
typedef SchurDiagMooeeOperator<FermionAction ,FermionField > LinearOperatorD;
|
||||
typedef SchurDiagMooeeOperator<FermionEOFAActionF,FermionFieldF> LinearOperatorEOFAF;
|
||||
typedef SchurDiagMooeeOperator<FermionEOFAAction ,FermionField > LinearOperatorEOFAD;
|
||||
|
||||
typedef MixedPrecisionConjugateGradientOperatorFunction<MobiusFermionD,MobiusFermionF,LinearOperatorD,LinearOperatorF> MxPCG;
|
||||
typedef MixedPrecisionConjugateGradientOperatorFunction<MobiusEOFAFermionD,MobiusEOFAFermionF,LinearOperatorEOFAD,LinearOperatorEOFAF> MxPCG_EOFA;
|
||||
|
||||
// DJM: setup for EOFA ratio (Mobius)
|
||||
OneFlavourRationalParams OFRp;
|
||||
OFRp.lo = 0.1;
|
||||
OFRp.hi = 25.0;
|
||||
OFRp.MaxIter = 10000;
|
||||
OFRp.tolerance= 1.0e-9;
|
||||
OFRp.degree = 14;
|
||||
OFRp.precision= 50;
|
||||
|
||||
|
||||
MobiusEOFAFermionR Strange_Op_L (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , strange_mass, strange_mass, pv_mass, 0.0, -1, M5, b, c);
|
||||
MobiusEOFAFermionF Strange_Op_LF(UF, *FGridF, *FrbGridF, *GridPtrF, *GridRBPtrF, strange_mass, strange_mass, pv_mass, 0.0, -1, M5, b, c);
|
||||
MobiusEOFAFermionR Strange_Op_R (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , pv_mass, strange_mass, pv_mass, -1.0, 1, M5, b, c);
|
||||
MobiusEOFAFermionF Strange_Op_RF(UF, *FGridF, *FrbGridF, *GridPtrF, *GridRBPtrF, pv_mass, strange_mass, pv_mass, -1.0, 1, M5, b, c);
|
||||
|
||||
ConjugateGradient<FermionField> ActionCG(ActionStoppingCondition,MaxCGIterations);
|
||||
ConjugateGradient<FermionField> DerivativeCG(DerivativeStoppingCondition,MaxCGIterations);
|
||||
#ifdef MIXED_PRECISION
|
||||
const int MX_inner = 1000;
|
||||
// Mixed precision EOFA
|
||||
LinearOperatorEOFAD Strange_LinOp_L (Strange_Op_L);
|
||||
LinearOperatorEOFAD Strange_LinOp_R (Strange_Op_R);
|
||||
LinearOperatorEOFAF Strange_LinOp_LF(Strange_Op_LF);
|
||||
LinearOperatorEOFAF Strange_LinOp_RF(Strange_Op_RF);
|
||||
|
||||
MxPCG_EOFA ActionCGL(ActionStoppingCondition,
|
||||
MX_inner,
|
||||
MaxCGIterations,
|
||||
GridPtrF,
|
||||
FrbGridF,
|
||||
Strange_Op_LF,Strange_Op_L,
|
||||
Strange_LinOp_LF,Strange_LinOp_L);
|
||||
|
||||
MxPCG_EOFA DerivativeCGL(DerivativeStoppingCondition,
|
||||
MX_inner,
|
||||
MaxCGIterations,
|
||||
GridPtrF,
|
||||
FrbGridF,
|
||||
Strange_Op_LF,Strange_Op_L,
|
||||
Strange_LinOp_LF,Strange_LinOp_L);
|
||||
|
||||
MxPCG_EOFA ActionCGR(ActionStoppingCondition,
|
||||
MX_inner,
|
||||
MaxCGIterations,
|
||||
GridPtrF,
|
||||
FrbGridF,
|
||||
Strange_Op_RF,Strange_Op_R,
|
||||
Strange_LinOp_RF,Strange_LinOp_R);
|
||||
|
||||
MxPCG_EOFA DerivativeCGR(DerivativeStoppingCondition,
|
||||
MX_inner,
|
||||
MaxCGIterations,
|
||||
GridPtrF,
|
||||
FrbGridF,
|
||||
Strange_Op_RF,Strange_Op_R,
|
||||
Strange_LinOp_RF,Strange_LinOp_R);
|
||||
|
||||
ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy>
|
||||
EOFA(Strange_Op_L, Strange_Op_R,
|
||||
ActionCG,
|
||||
ActionCGL, ActionCGR,
|
||||
DerivativeCGL, DerivativeCGR,
|
||||
OFRp, true);
|
||||
#else
|
||||
ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy>
|
||||
EOFA(Strange_Op_L, Strange_Op_R,
|
||||
ActionCG, ActionCG,
|
||||
DerivativeCG, DerivativeCG,
|
||||
OFRp, true);
|
||||
#endif
|
||||
Level1.push_back(&EOFA);
|
||||
|
||||
////////////////////////////////////
|
||||
// up down action
|
||||
////////////////////////////////////
|
||||
std::vector<Real> light_den;
|
||||
std::vector<Real> light_num;
|
||||
|
||||
int n_hasenbusch = hasenbusch.size();
|
||||
light_den.push_back(light_mass);
|
||||
for(int h=0;h<n_hasenbusch;h++){
|
||||
light_den.push_back(hasenbusch[h]);
|
||||
light_num.push_back(hasenbusch[h]);
|
||||
}
|
||||
light_num.push_back(pv_mass);
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Forced to replicate the MxPCG and DenominatorsF etc.. because
|
||||
// there is no convenient way to "Clone" physics params from double op
|
||||
// into single op for any operator pair.
|
||||
// Same issue prevents using MxPCG in the Heatbath step
|
||||
//////////////////////////////////////////////////////////////
|
||||
std::vector<FermionAction *> Numerators;
|
||||
std::vector<FermionAction *> Denominators;
|
||||
std::vector<TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy> *> Quotients;
|
||||
std::vector<MxPCG *> ActionMPCG;
|
||||
std::vector<MxPCG *> MPCG;
|
||||
std::vector<FermionActionF *> DenominatorsF;
|
||||
std::vector<LinearOperatorD *> LinOpD;
|
||||
std::vector<LinearOperatorF *> LinOpF;
|
||||
|
||||
for(int h=0;h<n_hasenbusch+1;h++){
|
||||
|
||||
std::cout << GridLogMessage << " 2f quotient Action "<< light_num[h] << " / " << light_den[h]<< std::endl;
|
||||
|
||||
Numerators.push_back (new FermionAction(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_num[h],M5,b,c, Params));
|
||||
Denominators.push_back(new FermionAction(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_den[h],M5,b,c, Params));
|
||||
|
||||
#ifdef MIXED_PRECISION
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Mixed precision CG for 2f force
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DenominatorsF.push_back(new FermionActionF(UF,*FGridF,*FrbGridF,*GridPtrF,*GridRBPtrF,light_den[h],M5,b,c, ParamsF));
|
||||
LinOpD.push_back(new LinearOperatorD(*Denominators[h]));
|
||||
LinOpF.push_back(new LinearOperatorF(*DenominatorsF[h]));
|
||||
|
||||
MPCG.push_back(new MxPCG(DerivativeStoppingCondition,
|
||||
MX_inner,
|
||||
MaxCGIterations,
|
||||
GridPtrF,
|
||||
FrbGridF,
|
||||
*DenominatorsF[h],*Denominators[h],
|
||||
*LinOpF[h], *LinOpD[h]) );
|
||||
|
||||
ActionMPCG.push_back(new MxPCG(ActionStoppingCondition,
|
||||
MX_inner,
|
||||
MaxCGIterations,
|
||||
GridPtrF,
|
||||
FrbGridF,
|
||||
*DenominatorsF[h],*Denominators[h],
|
||||
*LinOpF[h], *LinOpD[h]) );
|
||||
|
||||
// Heatbath not mixed yet. As inverts numerators not so important as raised mass.
|
||||
Quotients.push_back (new TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy>(*Numerators[h],*Denominators[h],*MPCG[h],*ActionMPCG[h],ActionCG));
|
||||
#else
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Standard CG for 2f force
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
Quotients.push_back (new TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy>(*Numerators[h],*Denominators[h],DerivativeCG,ActionCG));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
for(int h=0;h<n_hasenbusch+1;h++){
|
||||
Level1.push_back(Quotients[h]);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Gauge action
|
||||
/////////////////////////////////////////////////////////////
|
||||
Level2.push_back(&GaugeAction);
|
||||
TheHMC.TheAction.push_back(Level1);
|
||||
TheHMC.TheAction.push_back(Level2);
|
||||
std::cout << GridLogMessage << " Action complete "<< std::endl;
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// HMC parameters are serialisable
|
||||
|
||||
std::cout << GridLogMessage << " Running the HMC "<< std::endl;
|
||||
TheHMC.Run(); // no smearing
|
||||
|
||||
Grid_finalize();
|
||||
} // main
|
||||
|
||||
|
||||
|
198
HMC/Mobius2p1fRHMC.cc
Normal file
198
HMC/Mobius2p1fRHMC.cc
Normal file
@ -0,0 +1,198 @@
|
||||
/*************************************************************************************
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: ./tests/Test_hmc_EODWFRatio.cc
|
||||
|
||||
Copyright (C) 2015-2016
|
||||
|
||||
Author: Peter Boyle <pabobyle@ph.ed.ac.uk>
|
||||
Author: Guido Cossu <guido.cossu@ed.ac.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
See the full license in the file "LICENSE" in the top level distribution
|
||||
directory
|
||||
*************************************************************************************/
|
||||
/* END LEGAL */
|
||||
#include <Grid/Grid.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
using namespace Grid;
|
||||
using namespace Grid::QCD;
|
||||
|
||||
Grid_init(&argc, &argv);
|
||||
int threads = GridThread::GetThreads();
|
||||
// here make a routine to print all the relevant information on the run
|
||||
std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl;
|
||||
|
||||
// Typedefs to simplify notation
|
||||
typedef WilsonImplR FermionImplPolicy;
|
||||
typedef MobiusFermionR FermionAction;
|
||||
typedef typename FermionAction::FermionField FermionField;
|
||||
|
||||
typedef Grid::XmlReader Serialiser;
|
||||
|
||||
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
IntegratorParameters MD;
|
||||
// typedef GenericHMCRunner<LeapFrog> HMCWrapper;
|
||||
// MD.name = std::string("Leap Frog");
|
||||
// typedef GenericHMCRunner<ForceGradient> HMCWrapper;
|
||||
// MD.name = std::string("Force Gradient");
|
||||
typedef GenericHMCRunner<MinimumNorm2> HMCWrapper;
|
||||
MD.name = std::string("MinimumNorm2");
|
||||
MD.MDsteps = 20;
|
||||
MD.trajL = 1.0;
|
||||
|
||||
HMCparameters HMCparams;
|
||||
HMCparams.StartTrajectory = 30;
|
||||
HMCparams.Trajectories = 200;
|
||||
HMCparams.NoMetropolisUntil= 0;
|
||||
// "[HotStart, ColdStart, TepidStart, CheckpointStart]\n";
|
||||
// HMCparams.StartingType =std::string("ColdStart");
|
||||
HMCparams.StartingType =std::string("CheckpointStart");
|
||||
HMCparams.MD = MD;
|
||||
HMCWrapper TheHMC(HMCparams);
|
||||
|
||||
// Grid from the command line arguments --grid and --mpi
|
||||
TheHMC.Resources.AddFourDimGrid("gauge"); // use default simd lanes decomposition
|
||||
|
||||
CheckpointerParameters CPparams;
|
||||
CPparams.config_prefix = "ckpoint_EODWF_lat";
|
||||
CPparams.rng_prefix = "ckpoint_EODWF_rng";
|
||||
CPparams.saveInterval = 10;
|
||||
CPparams.format = "IEEE64BIG";
|
||||
TheHMC.Resources.LoadNerscCheckpointer(CPparams);
|
||||
|
||||
RNGModuleParameters RNGpar;
|
||||
RNGpar.serial_seeds = "1 2 3 4 5";
|
||||
RNGpar.parallel_seeds = "6 7 8 9 10";
|
||||
TheHMC.Resources.SetRNGSeeds(RNGpar);
|
||||
|
||||
// Construct observables
|
||||
// here there is too much indirection
|
||||
typedef PlaquetteMod<HMCWrapper::ImplPolicy> PlaqObs;
|
||||
TheHMC.Resources.AddObservable<PlaqObs>();
|
||||
//////////////////////////////////////////////
|
||||
|
||||
const int Ls = 16;
|
||||
Real beta = 2.13;
|
||||
Real light_mass = 0.01;
|
||||
Real strange_mass = 0.04;
|
||||
Real pv_mass = 1.0;
|
||||
RealD M5 = 1.8;
|
||||
RealD b = 1.0;
|
||||
RealD c = 0.0;
|
||||
|
||||
// FIXME:
|
||||
// Same in MC and MD
|
||||
// Need to mix precision too
|
||||
OneFlavourRationalParams OFRp;
|
||||
OFRp.lo = 4.0e-3;
|
||||
OFRp.hi = 30.0;
|
||||
OFRp.MaxIter = 10000;
|
||||
OFRp.tolerance= 1.0e-10;
|
||||
OFRp.degree = 16;
|
||||
OFRp.precision= 50;
|
||||
|
||||
std::vector<Real> hasenbusch({ 0.1 });
|
||||
|
||||
auto GridPtr = TheHMC.Resources.GetCartesian();
|
||||
auto GridRBPtr = TheHMC.Resources.GetRBCartesian();
|
||||
auto FGrid = SpaceTimeGrid::makeFiveDimGrid(Ls,GridPtr);
|
||||
auto FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,GridPtr);
|
||||
|
||||
IwasakiGaugeActionR GaugeAction(beta);
|
||||
|
||||
// temporarily need a gauge field
|
||||
LatticeGaugeField U(GridPtr);
|
||||
|
||||
// These lines are unecessary if BC are all periodic
|
||||
std::vector<Complex> boundary = {1,1,1,-1};
|
||||
FermionAction::ImplParams Params(boundary);
|
||||
|
||||
double StoppingCondition = 1e-10;
|
||||
double MaxCGIterations = 30000;
|
||||
ConjugateGradient<FermionField> CG(StoppingCondition,MaxCGIterations);
|
||||
|
||||
////////////////////////////////////
|
||||
// Collect actions
|
||||
////////////////////////////////////
|
||||
ActionLevel<HMCWrapper::Field> Level1(1);
|
||||
ActionLevel<HMCWrapper::Field> Level2(4);
|
||||
|
||||
////////////////////////////////////
|
||||
// Strange action
|
||||
////////////////////////////////////
|
||||
|
||||
// FermionAction StrangeOp(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_mass,M5,b,c, Params);
|
||||
// DomainWallEOFAFermionR Strange_Op_L(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, shift_L, pm, M5);
|
||||
// DomainWallEOFAFermionR Strange_Op_R(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, shift_R, pm, M5);
|
||||
// ExactOneFlavourRatioPseudoFermionAction EOFA(Strange_Op_L,Strange_Op_R,CG,ofp, false);
|
||||
|
||||
FermionAction StrangeOp (U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,strange_mass,M5,b,c, Params);
|
||||
FermionAction StrangePauliVillarsOp(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,pv_mass, M5,b,c, Params);
|
||||
|
||||
OneFlavourEvenOddRatioRationalPseudoFermionAction<FermionImplPolicy> StrangePseudoFermion(StrangePauliVillarsOp,StrangeOp,OFRp);
|
||||
Level1.push_back(&StrangePseudoFermion);
|
||||
|
||||
////////////////////////////////////
|
||||
// up down action
|
||||
////////////////////////////////////
|
||||
std::vector<Real> light_den;
|
||||
std::vector<Real> light_num;
|
||||
|
||||
int n_hasenbusch = hasenbusch.size();
|
||||
light_den.push_back(light_mass);
|
||||
for(int h=0;h<n_hasenbusch;h++){
|
||||
light_den.push_back(hasenbusch[h]);
|
||||
light_num.push_back(hasenbusch[h]);
|
||||
}
|
||||
light_num.push_back(pv_mass);
|
||||
|
||||
std::vector<FermionAction *> Numerators;
|
||||
std::vector<FermionAction *> Denominators;
|
||||
std::vector<TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy> *> Quotients;
|
||||
|
||||
for(int h=0;h<n_hasenbusch+1;h++){
|
||||
std::cout << GridLogMessage << " 2f quotient Action "<< light_num[h] << " / " << light_den[h]<< std::endl;
|
||||
Numerators.push_back (new FermionAction(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_num[h],M5,b,c, Params));
|
||||
Denominators.push_back(new FermionAction(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_den[h],M5,b,c, Params));
|
||||
Quotients.push_back (new TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy>(*Numerators[h],*Denominators[h],CG,CG));
|
||||
}
|
||||
|
||||
for(int h=0;h<n_hasenbusch+1;h++){
|
||||
Level1.push_back(Quotients[h]);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Gauge action
|
||||
/////////////////////////////////////////////////////////////
|
||||
Level2.push_back(&GaugeAction);
|
||||
TheHMC.TheAction.push_back(Level1);
|
||||
TheHMC.TheAction.push_back(Level2);
|
||||
std::cout << GridLogMessage << " Action complete "<< std::endl;
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// HMC parameters are serialisable
|
||||
|
||||
std::cout << GridLogMessage << " Running the HMC "<< std::endl;
|
||||
TheHMC.Run(); // no smearing
|
||||
|
||||
Grid_finalize();
|
||||
} // main
|
||||
|
||||
|
||||
|
109
HMC/README
Normal file
109
HMC/README
Normal file
@ -0,0 +1,109 @@
|
||||
********************************************************************
|
||||
TODO:
|
||||
********************************************************************
|
||||
|
||||
i) Got mixed precision in 2f and EOFA force and action solves.
|
||||
But need mixed precision in the heatbath solve. Best for Fermop to have a "clone" method, to
|
||||
reduce the number of solver and action objects. Needed ideally for the EOFA heatbath.
|
||||
15% perhaps
|
||||
Combine with 2x trajectory length?
|
||||
|
||||
ii) Rational on EOFA HB -- relax order
|
||||
-- Test the approx as per David email
|
||||
|
||||
Resume / roll.sh
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
- 16^3 Currently 10 traj per hour
|
||||
|
||||
- EOFA use a different derivative solver from action solver
|
||||
- EOFA fix Davids hack to the SchurRedBlack guessing
|
||||
|
||||
*** Reduce precision/tolerance in EOFA with second CG param. (10% speed up)
|
||||
*** Force gradient - reduced precision solve for the gradient (4/3x speedup)
|
||||
|
||||
|
||||
*** Need a plan for gauge field update for mixed precision in HMC (2x speed up)
|
||||
-- Store the single prec action operator.
|
||||
-- Clone the gauge field from the operator function argument.
|
||||
-- Build the mixed precision operator dynamically from the passed operator and single prec clone.
|
||||
|
||||
*** Mixed precision CG into EOFA portion
|
||||
*** Further reduce precision in forces to 10^-6 ?
|
||||
|
||||
*** Overall: a 3x or so is still possible => 500s -> 160s and 20 traj per hour on 16^3.
|
||||
|
||||
- Use mixed precision CG in HMC
|
||||
- SchurRedBlack.h: stop use of operator function; use LinearOperator or similar instead.
|
||||
- Or make an OperatorFunction for mixed precision as a wrapper
|
||||
|
||||
********************************************************************
|
||||
* Signed off 2+1f HMC with Hasenbush and strange RHMC 16^3 x 32 DWF Ls=16 Plaquette 0.5883 ish
|
||||
* Signed off 2+1f HMC with Hasenbush and strange EOFA 16^3 x 32 DWF Ls=16 Plaquette 0.5883 ish
|
||||
* Wilson plaquette cross checked against CPS and literature GwilsonFnone
|
||||
********************************************************************
|
||||
|
||||
********************************************************************
|
||||
* RHMC: Timesteps & eigenranges matched from previous CPS 16^3 x 32 runs:
|
||||
********************************************************************
|
||||
|
||||
****
|
||||
Strange (m=0.04) has eigenspan
|
||||
****
|
||||
16^3 done as 1+1+1 with separate PV's.
|
||||
/dirac1/archive/QCDOC/host/QCDDWF/DWF/2+1f/16nt32/IWASAKI/b2.13/ls16/M1_8/ms0.04/mu0.01/rhmc_multitimescale/evol5/work
|
||||
****
|
||||
2+1f 16^3 - [ 4e^-4, 2.42 ] for strange
|
||||
|
||||
****
|
||||
24^3 done as 1+1+1 at strange, and single quotient https://arxiv.org/pdf/0804.0473.pdf Eq 83,
|
||||
****
|
||||
double lambda_low = 4.0000000000000002e-04 <- strange
|
||||
double lambda_low = 1.0000000000000000e-02 <- pauli villars
|
||||
And high = 2.5
|
||||
|
||||
Array bsn_mass[3] = {
|
||||
double bsn_mass[0] = 1.0000000000000000e+00
|
||||
double bsn_mass[1] = 1.0000000000000000e+00
|
||||
double bsn_mass[2] = 1.0000000000000000e+00
|
||||
}
|
||||
Array frm_mass[3] = {
|
||||
double frm_mass[0] = 4.0000000000000001e-02
|
||||
double frm_mass[1] = 4.0000000000000001e-02
|
||||
double frm_mass[2] = 4.0000000000000001e-02
|
||||
}
|
||||
|
||||
***
|
||||
32^3
|
||||
/dirac1/archive/QCDOC/host/QCDDWF/DWF/2+1f/32nt64/IWASAKI/b2.25/ls16/M1_8/ms0.03/mu0.004/evol6/work
|
||||
***
|
||||
Similar det scheme
|
||||
double lambda_low = 4.0000000000000002e-04
|
||||
double lambda_low = 1.0000000000000000e-02
|
||||
|
||||
Array bsn_mass[3] = {
|
||||
double bsn_mass[0] = 1.0000000000000000e+00
|
||||
double bsn_mass[1] = 1.0000000000000000e+00
|
||||
double bsn_mass[2] = 1.0000000000000000e+00
|
||||
}
|
||||
Array frm_mass[3] = {
|
||||
double frm_mass[0] = 3.0000000000000002e-02
|
||||
double frm_mass[1] = 3.0000000000000002e-02
|
||||
double frm_mass[2] = 3.0000000000000002e-02
|
||||
}
|
||||
|
||||
********************************************************************
|
||||
* Grid: Power method bounds check
|
||||
********************************************************************
|
||||
- Finding largest eigenvalue approx 25 not 2.5
|
||||
- Conventions:
|
||||
|
||||
Grid MpcDagMpc based on:
|
||||
|
||||
(Moo-Moe Mee^-1 Meo)^dag(Moo-Moe Mee^-1 Meo)
|
||||
|
||||
- with Moo = 5-M5 = 3.2
|
||||
- CPS use(d) Moo = 1
|
||||
- Eigenrange in Grid is 3.2^2 rescaled so factor of 10 accounted for
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/A2AMatrix.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/A2AVectors.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: fionnoh <fionnoh@gmail.com>
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Application.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
@ -31,7 +31,7 @@ See the full license in the file "LICENSE" in the top level distribution directo
|
||||
#include <Hadrons/Modules.hpp>
|
||||
|
||||
using namespace Grid;
|
||||
|
||||
using namespace QCD;
|
||||
using namespace Hadrons;
|
||||
|
||||
#define BIG_SEP "================"
|
||||
@ -48,28 +48,32 @@ Application::Application(void)
|
||||
{
|
||||
initLogger();
|
||||
auto dim = GridDefaultLatt(), mpi = GridDefaultMpi(), loc(dim);
|
||||
locVol_ = 1;
|
||||
for (unsigned int d = 0; d < dim.size(); ++d)
|
||||
|
||||
if (dim.size())
|
||||
{
|
||||
loc[d] /= mpi[d];
|
||||
locVol_ *= loc[d];
|
||||
locVol_ = 1;
|
||||
for (unsigned int d = 0; d < dim.size(); ++d)
|
||||
{
|
||||
loc[d] /= mpi[d];
|
||||
locVol_ *= loc[d];
|
||||
}
|
||||
LOG(Message) << "====== HADRONS APPLICATION INITIALISATION ======" << std::endl;
|
||||
LOG(Message) << "** Dimensions" << std::endl;
|
||||
LOG(Message) << "Global lattice: " << dim << std::endl;
|
||||
LOG(Message) << "MPI partition : " << mpi << std::endl;
|
||||
LOG(Message) << "Local lattice : " << loc << std::endl;
|
||||
LOG(Message) << std::endl;
|
||||
LOG(Message) << "** Default parameters (and associated C macros)" << std::endl;
|
||||
LOG(Message) << "ASCII output precision : " << MACOUT(DEFAULT_ASCII_PREC) << std::endl;
|
||||
LOG(Message) << "Fermion implementation : " << MACOUTS(FIMPLBASE) << std::endl;
|
||||
LOG(Message) << "z-Fermion implementation: " << MACOUTS(ZFIMPLBASE) << std::endl;
|
||||
LOG(Message) << "Scalar implementation : " << MACOUTS(SIMPLBASE) << std::endl;
|
||||
LOG(Message) << "Gauge implementation : " << MACOUTS(GIMPLBASE) << std::endl;
|
||||
LOG(Message) << "Eigenvector base size : "
|
||||
<< MACOUT(HADRONS_DEFAULT_LANCZOS_NBASIS) << std::endl;
|
||||
LOG(Message) << "Schur decomposition : " << MACOUTS(HADRONS_DEFAULT_SCHUR) << std::endl;
|
||||
LOG(Message) << std::endl;
|
||||
}
|
||||
LOG(Message) << "====== HADRONS APPLICATION INITIALISATION ======" << std::endl;
|
||||
LOG(Message) << "** Dimensions" << std::endl;
|
||||
LOG(Message) << "Global lattice: " << dim << std::endl;
|
||||
LOG(Message) << "MPI partition : " << mpi << std::endl;
|
||||
LOG(Message) << "Local lattice : " << loc << std::endl;
|
||||
LOG(Message) << std::endl;
|
||||
LOG(Message) << "** Default parameters (and associated C macros)" << std::endl;
|
||||
LOG(Message) << "ASCII output precision : " << MACOUT(DEFAULT_ASCII_PREC) << std::endl;
|
||||
LOG(Message) << "Fermion implementation : " << MACOUTS(FIMPLBASE) << std::endl;
|
||||
LOG(Message) << "z-Fermion implementation: " << MACOUTS(ZFIMPLBASE) << std::endl;
|
||||
LOG(Message) << "Scalar implementation : " << MACOUTS(SIMPLBASE) << std::endl;
|
||||
LOG(Message) << "Gauge implementation : " << MACOUTS(GIMPLBASE) << std::endl;
|
||||
LOG(Message) << "Eigenvector base size : "
|
||||
<< MACOUT(HADRONS_DEFAULT_LANCZOS_NBASIS) << std::endl;
|
||||
LOG(Message) << "Schur decomposition : " << MACOUTS(HADRONS_DEFAULT_SCHUR) << std::endl;
|
||||
LOG(Message) << std::endl;
|
||||
}
|
||||
|
||||
Application::Application(const Application::GlobalPar &par)
|
||||
@ -114,7 +118,22 @@ void Application::run(void)
|
||||
vm().setRunId(getPar().runId);
|
||||
vm().printContent();
|
||||
env().printContent();
|
||||
schedule();
|
||||
if (getPar().saveSchedule or getPar().scheduleFile.empty())
|
||||
{
|
||||
schedule();
|
||||
if (getPar().saveSchedule)
|
||||
{
|
||||
std::string filename;
|
||||
|
||||
filename = (getPar().scheduleFile.empty()) ?
|
||||
"hadrons.sched" : getPar().scheduleFile;
|
||||
saveSchedule(filename);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
loadSchedule(getPar().scheduleFile);
|
||||
}
|
||||
printSchedule();
|
||||
if (!getPar().graphFile.empty())
|
||||
{
|
||||
@ -161,29 +180,30 @@ void Application::parseParameterFile(const std::string parameterFileName)
|
||||
pop(reader);
|
||||
}
|
||||
|
||||
void Application::saveParameterFile(const std::string parameterFileName)
|
||||
void Application::saveParameterFile(const std::string parameterFileName, unsigned int prec)
|
||||
{
|
||||
LOG(Message) << "Saving application to '" << parameterFileName << "'..." << std::endl;
|
||||
if (env().getGrid()->IsBoss())
|
||||
{
|
||||
XmlWriter writer(parameterFileName);
|
||||
ObjectId id;
|
||||
const unsigned int nMod = vm().getNModule();
|
||||
|
||||
write(writer, "parameters", getPar());
|
||||
push(writer, "modules");
|
||||
for (unsigned int i = 0; i < nMod; ++i)
|
||||
{
|
||||
push(writer, "module");
|
||||
id.name = vm().getModuleName(i);
|
||||
id.type = vm().getModule(i)->getRegisteredName();
|
||||
write(writer, "id", id);
|
||||
vm().getModule(i)->saveParameters(writer, "options");
|
||||
XmlWriter writer(parameterFileName);
|
||||
writer.setPrecision(prec);
|
||||
ObjectId id;
|
||||
const unsigned int nMod = vm().getNModule();
|
||||
|
||||
write(writer, "parameters", getPar());
|
||||
push(writer, "modules");
|
||||
for (unsigned int i = 0; i < nMod; ++i)
|
||||
{
|
||||
push(writer, "module");
|
||||
id.name = vm().getModuleName(i);
|
||||
id.type = vm().getModule(i)->getRegisteredName();
|
||||
write(writer, "id", id);
|
||||
vm().getModule(i)->saveParameters(writer, "options");
|
||||
pop(writer);
|
||||
}
|
||||
pop(writer);
|
||||
pop(writer);
|
||||
}
|
||||
pop(writer);
|
||||
pop(writer);
|
||||
}
|
||||
}
|
||||
|
||||
// schedule computation ////////////////////////////////////////////////////////
|
||||
@ -202,20 +222,20 @@ void Application::saveSchedule(const std::string filename)
|
||||
<< std::endl;
|
||||
if (env().getGrid()->IsBoss())
|
||||
{
|
||||
TextWriter writer(filename);
|
||||
std::vector<std::string> program;
|
||||
|
||||
if (!scheduled_)
|
||||
{
|
||||
TextWriter writer(filename);
|
||||
std::vector<std::string> program;
|
||||
|
||||
if (!scheduled_)
|
||||
{
|
||||
HADRONS_ERROR(Definition, "Computation not scheduled");
|
||||
}
|
||||
}
|
||||
|
||||
for (auto address: program_)
|
||||
{
|
||||
program.push_back(vm().getModuleName(address));
|
||||
for (auto address: program_)
|
||||
{
|
||||
program.push_back(vm().getModuleName(address));
|
||||
}
|
||||
write(writer, "schedule", program);
|
||||
}
|
||||
write(writer, "schedule", program);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::loadSchedule(const std::string filename)
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Application.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
@ -57,6 +57,8 @@ public:
|
||||
VirtualMachine::GeneticPar, genetic,
|
||||
std::string, runId,
|
||||
std::string, graphFile,
|
||||
std::string, scheduleFile,
|
||||
bool, saveSchedule,
|
||||
int, parallelWriteMaxRetry);
|
||||
GlobalPar(void): parallelWriteMaxRetry{-1} {}
|
||||
};
|
||||
@ -79,7 +81,7 @@ public:
|
||||
void run(void);
|
||||
// XML parameter file I/O
|
||||
void parseParameterFile(const std::string parameterFileName);
|
||||
void saveParameterFile(const std::string parameterFileName);
|
||||
void saveParameterFile(const std::string parameterFileName, unsigned int prec=15);
|
||||
// schedule computation
|
||||
void schedule(void);
|
||||
void saveSchedule(const std::string filename);
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MScalar/ScalarVP.cc
|
||||
Source file: Hadrons/Archive/Modules/ScalarVP.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: James Harrison <jch1g10@soton.ac.uk>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MScalar/ScalarVP.hpp
|
||||
Source file: Hadrons/Archive/Modules/ScalarVP.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: James Harrison <jch1g10@soton.ac.uk>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MUtilities/TestSeqConserved.cc
|
||||
Source file: Hadrons/Archive/Modules/TestSeqConserved.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MUtilities/TestSeqConserved.hpp
|
||||
Source file: Hadrons/Archive/Modules/TestSeqConserved.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MUtilities/TestSeqGamma.cc
|
||||
Source file: Hadrons/Archive/Modules/TestSeqGamma.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MUtilities/TestSeqGamma.hpp
|
||||
Source file: Hadrons/Archive/Modules/TestSeqGamma.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MScalar/VPCounterTerms.cc
|
||||
Source file: Hadrons/Archive/Modules/VPCounterTerms.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: James Harrison <jch1g10@soton.ac.uk>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MScalar/VPCounterTerms.hpp
|
||||
Source file: Hadrons/Archive/Modules/VPCounterTerms.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: James Harrison <jch1g10@soton.ac.uk>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WardIdentity.cc
|
||||
Source file: Hadrons/Archive/Modules/WardIdentity.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WardIdentity.hpp
|
||||
Source file: Hadrons/Archive/Modules/WardIdentity.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WeakHamiltonian.hpp
|
||||
Source file: Hadrons/Archive/Modules/WeakHamiltonian.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WeakHamiltonianEye.cc
|
||||
Source file: Hadrons/Archive/Modules/WeakHamiltonianEye.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WeakHamiltonianEye.hpp
|
||||
Source file: Hadrons/Archive/Modules/WeakHamiltonianEye.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WeakHamiltonianNonEye.cc
|
||||
Source file: Hadrons/Archive/Modules/WeakHamiltonianNonEye.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WeakHamiltonianNonEye.hpp
|
||||
Source file: Hadrons/Archive/Modules/WeakHamiltonianNonEye.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WeakNeutral4ptDisc.cc
|
||||
Source file: Hadrons/Archive/Modules/WeakNeutral4ptDisc.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -2,9 +2,9 @@
|
||||
|
||||
Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Modules/MContraction/WeakNeutral4ptDisc.hpp
|
||||
Source file: Hadrons/Archive/Modules/WeakNeutral4ptDisc.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
@ -4,10 +4,11 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/DilutedNoise.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Vera Guelpers <Vera.Guelpers@ed.ac.uk>
|
||||
Author: Vera Guelpers <vmg1n14@soton.ac.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/DiskVector.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
@ -395,12 +395,26 @@ void DiskVectorBase<T>::cacheInsert(const unsigned int i, const T &obj) const
|
||||
auto &freeInd = *freePtr_;
|
||||
auto &loads = *loadsPtr_;
|
||||
|
||||
evict();
|
||||
index[i] = freeInd.top();
|
||||
freeInd.pop();
|
||||
cache[index.at(i)] = obj;
|
||||
loads.push_back(i);
|
||||
modified[index.at(i)] = false;
|
||||
// cache miss, evict and store
|
||||
if (index.find(i) == index.end())
|
||||
{
|
||||
evict();
|
||||
index[i] = freeInd.top();
|
||||
freeInd.pop();
|
||||
cache[index.at(i)] = obj;
|
||||
loads.push_back(i);
|
||||
modified[index.at(i)] = false;
|
||||
}
|
||||
// cache hit, modify current value
|
||||
else
|
||||
{
|
||||
auto pos = std::find(loads.begin(), loads.end(), i);
|
||||
|
||||
cache[index.at(i)] = obj;
|
||||
modified[index.at(i)] = true;
|
||||
loads.erase(pos);
|
||||
loads.push_back(i);
|
||||
}
|
||||
|
||||
#ifdef DV_DEBUG
|
||||
std::string msg;
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/EigenPack.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
@ -308,7 +308,9 @@ template <typename FineF, typename CoarseF,
|
||||
class CoarseEigenPack: public EigenPack<FineF, FineFIo>
|
||||
{
|
||||
public:
|
||||
typedef CoarseF CoarseField;
|
||||
typedef CoarseF CoarseField;
|
||||
typedef CoarseFIo CoarseFieldIo;
|
||||
public:
|
||||
std::vector<CoarseF> evecCoarse;
|
||||
std::vector<RealD> evalCoarse;
|
||||
public:
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Environment.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
@ -45,13 +45,11 @@ Environment::Environment(void)
|
||||
{
|
||||
dim_ = GridDefaultLatt().toVector();
|
||||
nd_ = dim_.size();
|
||||
createGrid<vComplex>(1);
|
||||
vol_ = 1.;
|
||||
for (auto d: dim_)
|
||||
{
|
||||
vol_ *= d;
|
||||
}
|
||||
rng4d_.reset(new GridParallelRNG(getGrid()));
|
||||
}
|
||||
|
||||
// grids ///////////////////////////////////////////////////////////////////////
|
||||
@ -76,8 +74,13 @@ double Environment::getVolume(void) const
|
||||
}
|
||||
|
||||
// random number generator /////////////////////////////////////////////////////
|
||||
GridParallelRNG * Environment::get4dRng(void) const
|
||||
GridParallelRNG * Environment::get4dRng(void)
|
||||
{
|
||||
if (rng4d_ == nullptr)
|
||||
{
|
||||
rng4d_.reset(new GridParallelRNG(getGrid()));
|
||||
}
|
||||
|
||||
return rng4d_.get();
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Environment.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
@ -113,7 +113,7 @@ public:
|
||||
unsigned int getNd(void) const;
|
||||
double getVolume(void) const;
|
||||
// random number generator
|
||||
GridParallelRNG * get4dRng(void) const;
|
||||
GridParallelRNG * get4dRng(void);
|
||||
// general memory management
|
||||
void addObject(const std::string name,
|
||||
const int moduleAddress = -1);
|
||||
@ -182,7 +182,7 @@ private:
|
||||
std::map<CoarseGridKey, GridPt> gridCoarse5d_;
|
||||
unsigned int nd_;
|
||||
// random number generator
|
||||
RngPt rng4d_;
|
||||
RngPt rng4d_{nullptr};
|
||||
// object store
|
||||
std::vector<ObjInfo> object_;
|
||||
std::map<std::string, unsigned int> objectAddress_;
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Exceptions.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Exceptions.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Factory.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/GeneticScheduler.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Global.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Global.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
Author: Lanny91 <andrew.lawson@gmail.com>
|
||||
@ -44,6 +44,8 @@ See the full license in the file "LICENSE" in the top level distribution directo
|
||||
#define DEFAULT_ASCII_PREC 16
|
||||
#endif
|
||||
|
||||
#define ARG(...) __VA_ARGS__
|
||||
|
||||
/* the 'using Grid::operator<<;' statement prevents a very nasty compilation
|
||||
* error with GCC 5 (clang & GCC 6 compile fine without it).
|
||||
*/
|
||||
@ -100,15 +102,17 @@ BEGIN_HADRONS_NAMESPACE
|
||||
typedef typename Impl::Field ScalarField##suffix;\
|
||||
typedef typename Impl::PropagatorField PropagatorField##suffix;\
|
||||
typedef typename Impl::SitePropagator::scalar_object SitePropagator##suffix;\
|
||||
typedef std::vector<SitePropagator##suffix> SlicedPropagator##suffix;
|
||||
typedef typename Impl::ComplexField ComplexField##suffix;\
|
||||
typedef std::vector<SitePropagator##suffix> SlicedPropagator##suffix;\
|
||||
typedef std::vector<typename ComplexField##suffix::vector_object::scalar_object> SlicedComplex##suffix;
|
||||
|
||||
#define FERM_TYPE_ALIASES(FImpl, suffix)\
|
||||
BASIC_TYPE_ALIASES(FImpl, suffix);\
|
||||
typedef FermionOperator<FImpl> FMat##suffix;\
|
||||
typedef typename FImpl::FermionField FermionField##suffix;\
|
||||
typedef typename FImpl::GaugeField GaugeField##suffix;\
|
||||
typedef typename FImpl::DoubledGaugeField DoubledGaugeField##suffix;\
|
||||
typedef typename FImpl::ComplexField ComplexField##suffix;
|
||||
typedef FermionOperator<FImpl> FMat##suffix;\
|
||||
typedef typename FImpl::FermionField FermionField##suffix;\
|
||||
typedef typename FImpl::GaugeField GaugeField##suffix;\
|
||||
typedef typename FImpl::DoubledGaugeField DoubledGaugeField##suffix;\
|
||||
typedef Lattice<iSpinMatrix<typename FImpl::Simd>> SpinMatrixField##suffix;
|
||||
|
||||
#define GAUGE_TYPE_ALIASES(GImpl, suffix)\
|
||||
typedef typename GImpl::GaugeField GaugeField##suffix;
|
||||
@ -262,6 +266,15 @@ void tokenReplace(std::string &str, const std::string token,
|
||||
}
|
||||
}
|
||||
|
||||
// generic correlator class
|
||||
template <typename Metadata, typename Scalar = Complex>
|
||||
struct Correlator: Serializable
|
||||
{
|
||||
GRID_SERIALIZABLE_CLASS_MEMBERS(ARG(Correlator<Metadata, Scalar>),
|
||||
Metadata, info,
|
||||
std::vector<Complex>, corr);
|
||||
};
|
||||
|
||||
END_HADRONS_NAMESPACE
|
||||
|
||||
#include <Hadrons/Exceptions.hpp>
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Graph.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Module.cc
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/Module.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
@ -65,7 +65,6 @@ static ns##mod##ModuleRegistrar ns##mod##ModuleRegistrarInstance;
|
||||
extern template class base;\
|
||||
MODULE_REGISTER(mod, ARG(base), ns);
|
||||
|
||||
#define ARG(...) __VA_ARGS__
|
||||
#define HADRONS_MACRO_REDIRECT_12(arg1, arg2, macro, ...) macro
|
||||
#define HADRONS_MACRO_REDIRECT_23(arg1, arg2, arg3, macro, ...) macro
|
||||
|
||||
@ -78,6 +77,15 @@ env().template getGrid<typename latticeType::vector_type>(Ls)
|
||||
#define envGetGrid(...)\
|
||||
HADRONS_MACRO_REDIRECT_12(__VA_ARGS__, envGetGrid5, envGetGrid4)(__VA_ARGS__)
|
||||
|
||||
#define envGetCoarseGrid4(latticeType, blockSize)\
|
||||
env().template getCoarseGrid<typename latticeType::vector_type>(blockSize)
|
||||
|
||||
#define envGetCoarseGrid5(latticeType, blockSize, Ls)\
|
||||
env().template getCoarseGrid<typename latticeType::vector_type>(blockSize, Ls)
|
||||
|
||||
#define envGetCoarseGrid(...)\
|
||||
HADRONS_MACRO_REDIRECT_23(__VA_ARGS__, envGetCoarseGrid5, envGetCoarseGrid4)(__VA_ARGS__)
|
||||
|
||||
#define envGetRbGrid4(latticeType)\
|
||||
env().template getRbGrid<typename latticeType::vector_type>()
|
||||
|
||||
|
@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid
|
||||
|
||||
Source file: Hadrons/ModuleFactory.hpp
|
||||
|
||||
Copyright (C) 2015-2018
|
||||
Copyright (C) 2015-2019
|
||||
|
||||
Author: Antonin Portelli <antonin.portelli@me.com>
|
||||
|
||||
|
@ -1,17 +1,18 @@
|
||||
#include <Hadrons/Modules/MContraction/WeakEye3pt.hpp>
|
||||
#include <Hadrons/Modules/MContraction/Baryon.hpp>
|
||||
#include <Hadrons/Modules/MContraction/A2AAslashField.hpp>
|
||||
#include <Hadrons/Modules/MContraction/A2ALoop.hpp>
|
||||
#include <Hadrons/Modules/MContraction/A2AMesonField.hpp>
|
||||
#include <Hadrons/Modules/MContraction/Meson.hpp>
|
||||
#include <Hadrons/Modules/MContraction/WeakHamiltonian.hpp>
|
||||
#include <Hadrons/Modules/MContraction/WeakHamiltonianNonEye.hpp>
|
||||
#include <Hadrons/Modules/MContraction/DiscLoop.hpp>
|
||||
#include <Hadrons/Modules/MContraction/WeakNeutral4ptDisc.hpp>
|
||||
#include <Hadrons/Modules/MContraction/Gamma3pt.hpp>
|
||||
#include <Hadrons/Modules/MContraction/WardIdentity.hpp>
|
||||
#include <Hadrons/Modules/MContraction/WeakHamiltonianEye.hpp>
|
||||
#include <Hadrons/Modules/MContraction/WeakMesonDecayKl2.hpp>
|
||||
#include <Hadrons/Modules/MContraction/WeakNonEye3pt.hpp>
|
||||
#include <Hadrons/Modules/MFermion/FreeProp.hpp>
|
||||
#include <Hadrons/Modules/MFermion/GaugeProp.hpp>
|
||||
#include <Hadrons/Modules/MFermion/EMLepton.hpp>
|
||||
#include <Hadrons/Modules/MSource/SeqGamma.hpp>
|
||||
#include <Hadrons/Modules/MSource/SeqAslash.hpp>
|
||||
#include <Hadrons/Modules/MSource/Point.hpp>
|
||||
#include <Hadrons/Modules/MSource/Wall.hpp>
|
||||
#include <Hadrons/Modules/MSource/Z2.hpp>
|
||||
@ -21,28 +22,23 @@
|
||||
#include <Hadrons/Modules/MSink/Point.hpp>
|
||||
#include <Hadrons/Modules/MSolver/MixedPrecisionRBPrecCG.hpp>
|
||||
#include <Hadrons/Modules/MSolver/LocalCoherenceLanczos.hpp>
|
||||
#include <Hadrons/Modules/MSolver/A2AAslashVectors.hpp>
|
||||
#include <Hadrons/Modules/MSolver/Guesser.hpp>
|
||||
#include <Hadrons/Modules/MSolver/RBPrecCG.hpp>
|
||||
#include <Hadrons/Modules/MSolver/A2AVectors.hpp>
|
||||
#include <Hadrons/Modules/MSolver/A2AAslashVectors.hpp>
|
||||
#include <Hadrons/Modules/MGauge/UnitEm.hpp>
|
||||
#include <Hadrons/Modules/MGauge/StoutSmearing.hpp>
|
||||
#include <Hadrons/Modules/MGauge/Unit.hpp>
|
||||
#include <Hadrons/Modules/MGauge/Electrify.hpp>
|
||||
#include <Hadrons/Modules/MGauge/Random.hpp>
|
||||
#include <Hadrons/Modules/MGauge/GaugeFix.hpp>
|
||||
#include <Hadrons/Modules/MGauge/FundtoHirep.hpp>
|
||||
#include <Hadrons/Modules/MGauge/StochEm.hpp>
|
||||
#include <Hadrons/Modules/MGauge/Electrify.hpp>
|
||||
#include <Hadrons/Modules/MNoise/TimeDilutedSpinColorDiagonal.hpp>
|
||||
#include <Hadrons/Modules/MNoise/FullVolumeSpinColorDiagonal.hpp>
|
||||
#include <Hadrons/Modules/MUtilities/PrecisionCast.hpp>
|
||||
#include <Hadrons/Modules/MUtilities/RandomVectors.hpp>
|
||||
#include <Hadrons/Modules/MUtilities/TestSeqGamma.hpp>
|
||||
#include <Hadrons/Modules/MUtilities/TestSeqConserved.hpp>
|
||||
#include <Hadrons/Modules/MLoop/NoiseLoop.hpp>
|
||||
#include <Hadrons/Modules/MScalar/FreeProp.hpp>
|
||||
#include <Hadrons/Modules/MScalar/VPCounterTerms.hpp>
|
||||
#include <Hadrons/Modules/MScalar/ScalarVP.hpp>
|
||||
#include <Hadrons/Modules/MScalar/Scalar.hpp>
|
||||
#include <Hadrons/Modules/MScalar/ChargedProp.hpp>
|
||||
#include <Hadrons/Modules/MNPR/Bilinear.hpp>
|
||||
@ -56,7 +52,6 @@
|
||||
#include <Hadrons/Modules/MAction/ScaledDWF.hpp>
|
||||
#include <Hadrons/Modules/MScalarSUN/StochFreeField.hpp>
|
||||
#include <Hadrons/Modules/MScalarSUN/TwoPointNPR.hpp>
|
||||
#include <Hadrons/Modules/MScalarSUN/ShiftProbe.hpp>
|
||||
#include <Hadrons/Modules/MScalarSUN/Div.hpp>
|
||||
#include <Hadrons/Modules/MScalarSUN/TrMag.hpp>
|
||||
#include <Hadrons/Modules/MScalarSUN/EMT.hpp>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user