mirror of
https://github.com/paboyle/Grid.git
synced 2025-04-09 21:50:45 +01:00
Added Laplacian metric, Gauge OpenBC
This commit is contained in:
parent
6d0c2de399
commit
515ff6bf62
@ -460,6 +460,53 @@ class NonHermitianSchurDiagTwoOperator : public NonHermitianSchurOperatorBase<Fi
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class Matrix,class Field>
|
||||||
|
class QuadLinearOperator : public LinearOperatorBase<Field> {
|
||||||
|
Matrix &_Mat;
|
||||||
|
public:
|
||||||
|
RealD a0,a1,a2;
|
||||||
|
QuadLinearOperator(Matrix &Mat): _Mat(Mat),a0(0.),a1(0.),a2(1.) {};
|
||||||
|
QuadLinearOperator(Matrix &Mat, RealD _a0,RealD _a1,RealD _a2): _Mat(Mat),a0(_a0),a1(_a1),a2(_a2) {};
|
||||||
|
// Support for coarsening to a multigrid
|
||||||
|
void OpDiag (const Field &in, Field &out) {
|
||||||
|
assert(0);
|
||||||
|
_Mat.Mdiag(in,out);
|
||||||
|
}
|
||||||
|
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
||||||
|
assert(0);
|
||||||
|
_Mat.Mdir(in,out,dir,disp);
|
||||||
|
}
|
||||||
|
void OpDirAll (const Field &in, std::vector<Field> &out){
|
||||||
|
assert(0);
|
||||||
|
_Mat.MdirAll(in,out);
|
||||||
|
}
|
||||||
|
void HermOp (const Field &in, Field &out){
|
||||||
|
// _Mat.M(in,out);
|
||||||
|
Field tmp1(in.Grid());
|
||||||
|
// Linop.HermOpAndNorm(psi, mmp, d, b);
|
||||||
|
_Mat.M(in,tmp1);
|
||||||
|
_Mat.M(tmp1,out);
|
||||||
|
out *= a2;
|
||||||
|
axpy(out, a1, tmp1, out);
|
||||||
|
axpy(out, a0, in, out);
|
||||||
|
// d=real(innerProduct(psi,mmp));
|
||||||
|
// b=norm2(mmp);
|
||||||
|
}
|
||||||
|
void AdjOp (const Field &in, Field &out){
|
||||||
|
assert(0);
|
||||||
|
_Mat.M(in,out);
|
||||||
|
}
|
||||||
|
void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){
|
||||||
|
HermOp(in,out);
|
||||||
|
ComplexD dot= innerProduct(in,out); n1=real(dot);
|
||||||
|
n2=norm2(out);
|
||||||
|
}
|
||||||
|
void Op(const Field &in, Field &out){
|
||||||
|
assert(0);
|
||||||
|
_Mat.M(in,out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Left handed Moo^-1 ; (Moo - Moe Mee^-1 Meo) psi = eta --> ( 1 - Moo^-1 Moe Mee^-1 Meo ) psi = Moo^-1 eta
|
// 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
|
// 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
|
||||||
|
@ -36,11 +36,12 @@ NAMESPACE_BEGIN(Grid);
|
|||||||
// Abstract base class.
|
// Abstract base class.
|
||||||
// Takes a matrix (Mat), a source (phi), and a vector of Fields (chi)
|
// Takes a matrix (Mat), a source (phi), and a vector of Fields (chi)
|
||||||
// and returns a forecasted solution to the system D*psi = phi (psi).
|
// and returns a forecasted solution to the system D*psi = phi (psi).
|
||||||
template<class Matrix, class Field>
|
// Changing to operator
|
||||||
|
template<class LinearOperatorBase, class Field>
|
||||||
class Forecast
|
class Forecast
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& chi) = 0;
|
virtual Field operator()(LinearOperatorBase &Mat, const Field& phi, const std::vector<Field>& chi) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implementation of Brower et al.'s chronological inverter (arXiv:hep-lat/9509012),
|
// Implementation of Brower et al.'s chronological inverter (arXiv:hep-lat/9509012),
|
||||||
@ -54,13 +55,13 @@ public:
|
|||||||
Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& prev_solns)
|
Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& prev_solns)
|
||||||
{
|
{
|
||||||
int degree = prev_solns.size();
|
int degree = prev_solns.size();
|
||||||
|
std::cout << GridLogMessage << "ChronoForecast: degree= " << degree << std::endl;
|
||||||
Field chi(phi); // forecasted solution
|
Field chi(phi); // forecasted solution
|
||||||
|
|
||||||
// Trivial cases
|
// Trivial cases
|
||||||
if(degree == 0){ chi = Zero(); return chi; }
|
if(degree == 0){ chi = Zero(); return chi; }
|
||||||
else if(degree == 1){ return prev_solns[0]; }
|
else if(degree == 1){ return prev_solns[0]; }
|
||||||
|
|
||||||
// RealD dot;
|
|
||||||
ComplexD xp;
|
ComplexD xp;
|
||||||
Field r(phi); // residual
|
Field r(phi); // residual
|
||||||
Field Mv(phi);
|
Field Mv(phi);
|
||||||
@ -83,8 +84,9 @@ public:
|
|||||||
// Perform sparse matrix multiplication and construct rhs
|
// Perform sparse matrix multiplication and construct rhs
|
||||||
for(int i=0; i<degree; i++){
|
for(int i=0; i<degree; i++){
|
||||||
b[i] = innerProduct(v[i],phi);
|
b[i] = innerProduct(v[i],phi);
|
||||||
Mat.M(v[i],Mv);
|
// Mat.M(v[i],Mv);
|
||||||
Mat.Mdag(Mv,MdagMv[i]);
|
// Mat.Mdag(Mv,MdagMv[i]);
|
||||||
|
Mat.HermOp(v[i],MdagMv[i]);
|
||||||
G[i][i] = innerProduct(v[i],MdagMv[i]);
|
G[i][i] = innerProduct(v[i],MdagMv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ NAMESPACE_CHECK(Scalar);
|
|||||||
#include <Grid/qcd/utils/Metric.h>
|
#include <Grid/qcd/utils/Metric.h>
|
||||||
NAMESPACE_CHECK(Metric);
|
NAMESPACE_CHECK(Metric);
|
||||||
#include <Grid/qcd/utils/CovariantLaplacian.h>
|
#include <Grid/qcd/utils/CovariantLaplacian.h>
|
||||||
|
#include <Grid/qcd/utils/CovariantLaplacianRat.h>
|
||||||
NAMESPACE_CHECK(CovariantLaplacian);
|
NAMESPACE_CHECK(CovariantLaplacian);
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,6 +65,19 @@ struct WilsonImplParams {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GaugeImplParams {
|
||||||
|
// bool overlapCommsCompute;
|
||||||
|
// AcceleratorVector<Real,Nd> twist_n_2pi_L;
|
||||||
|
AcceleratorVector<Complex,Nd> boundary_phases;
|
||||||
|
GaugeImplParams() {
|
||||||
|
boundary_phases.resize(Nd, 1.0);
|
||||||
|
// twist_n_2pi_L.resize(Nd, 0.0);
|
||||||
|
};
|
||||||
|
GaugeImplParams(const AcceleratorVector<Complex,Nd> phi) : boundary_phases(phi) {
|
||||||
|
// twist_n_2pi_L.resize(Nd, 0.0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct StaggeredImplParams {
|
struct StaggeredImplParams {
|
||||||
Coordinate dirichlet; // Blocksize of dirichlet BCs
|
Coordinate dirichlet; // Blocksize of dirichlet BCs
|
||||||
int partialDirichlet;
|
int partialDirichlet;
|
||||||
|
@ -42,9 +42,13 @@ template <class Gimpl>
|
|||||||
class WilsonGaugeAction : public Action<typename Gimpl::GaugeField> {
|
class WilsonGaugeAction : public Action<typename Gimpl::GaugeField> {
|
||||||
public:
|
public:
|
||||||
INHERIT_GIMPL_TYPES(Gimpl);
|
INHERIT_GIMPL_TYPES(Gimpl);
|
||||||
|
typedef GaugeImplParams ImplParams;
|
||||||
|
ImplParams Params;
|
||||||
|
|
||||||
/////////////////////////// constructors
|
/////////////////////////// constructors
|
||||||
explicit WilsonGaugeAction(RealD beta_):beta(beta_){};
|
explicit WilsonGaugeAction(RealD beta_,
|
||||||
|
const ImplParams &p = ImplParams()
|
||||||
|
):beta(beta_),Params(p){};
|
||||||
|
|
||||||
virtual std::string action_name() {return "WilsonGaugeAction";}
|
virtual std::string action_name() {return "WilsonGaugeAction";}
|
||||||
|
|
||||||
@ -56,14 +60,53 @@ public:
|
|||||||
|
|
||||||
virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG &pRNG){}; // noop as no pseudoferms
|
virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG &pRNG){}; // noop as no pseudoferms
|
||||||
|
|
||||||
|
// Umu<->U maximally confusing
|
||||||
|
virtual void boundary(const GaugeField &Umu, GaugeField &Ub){
|
||||||
|
typedef typename Simd::scalar_type scalar_type;
|
||||||
|
assert(Params.boundary_phases.size() == Nd);
|
||||||
|
GridBase *GaugeGrid=Umu.Grid();
|
||||||
|
GaugeLinkField U(GaugeGrid);
|
||||||
|
GaugeLinkField tmp(GaugeGrid);
|
||||||
|
|
||||||
|
Lattice<iScalar<vInteger> > coor(GaugeGrid);
|
||||||
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
|
////////// boundary phase /////////////
|
||||||
|
auto pha = Params.boundary_phases[mu];
|
||||||
|
scalar_type phase( real(pha),imag(pha) );
|
||||||
|
std::cout<< GridLogMessage << "[WilsonGaugeAction] boundary "<<mu<<" "<<phase<< std::endl;
|
||||||
|
|
||||||
|
int L = GaugeGrid->GlobalDimensions()[mu];
|
||||||
|
int Lmu = L - 1;
|
||||||
|
|
||||||
|
LatticeCoordinate(coor, mu);
|
||||||
|
|
||||||
|
U = PeekIndex<LorentzIndex>(Umu, mu);
|
||||||
|
tmp = where(coor == Lmu, phase * U, U);
|
||||||
|
PokeIndex<LorentzIndex>(Ub, tmp, mu);
|
||||||
|
// PokeIndex<LorentzIndex>(Ub, U, mu);
|
||||||
|
// PokeIndex<LorentzIndex>(Umu, tmp, mu);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
virtual RealD S(const GaugeField &U) {
|
virtual RealD S(const GaugeField &U) {
|
||||||
RealD plaq = WilsonLoops<Gimpl>::avgPlaquette(U);
|
GaugeField Ub(U.Grid());
|
||||||
RealD vol = U.Grid()->gSites();
|
this->boundary(U,Ub);
|
||||||
|
static RealD lastG=0.;
|
||||||
|
RealD plaq = WilsonLoops<Gimpl>::avgPlaquette(Ub);
|
||||||
|
RealD vol = Ub.Grid()->gSites();
|
||||||
RealD action = beta * (1.0 - plaq) * (Nd * (Nd - 1.0)) * vol * 0.5;
|
RealD action = beta * (1.0 - plaq) * (Nd * (Nd - 1.0)) * vol * 0.5;
|
||||||
|
std::cout << GridLogMessage << "[WilsonGaugeAction] dH: " << action-lastG << std::endl;
|
||||||
|
RealD plaq_o = WilsonLoops<Gimpl>::avgPlaquette(U);
|
||||||
|
RealD action_o = beta * (1.0 - plaq_o) * (Nd * (Nd - 1.0)) * vol * 0.5;
|
||||||
|
std::cout << GridLogMessage << "[WilsonGaugeAction] U: " << action_o <<" Ub: "<< action << std::endl;
|
||||||
|
lastG=action;
|
||||||
return action;
|
return action;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void deriv(const GaugeField &U, GaugeField &dSdU) {
|
virtual void deriv(const GaugeField &U, GaugeField &dSdU) {
|
||||||
|
GaugeField Ub(U.Grid());
|
||||||
|
this->boundary(U,Ub);
|
||||||
// not optimal implementation FIXME
|
// not optimal implementation FIXME
|
||||||
// extend Ta to include Lorentz indexes
|
// extend Ta to include Lorentz indexes
|
||||||
|
|
||||||
@ -73,10 +116,9 @@ public:
|
|||||||
GaugeLinkField dSdU_mu(U.Grid());
|
GaugeLinkField dSdU_mu(U.Grid());
|
||||||
for (int mu = 0; mu < Nd; mu++) {
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
|
|
||||||
Umu = PeekIndex<LorentzIndex>(U, mu);
|
Umu = PeekIndex<LorentzIndex>(Ub, mu);
|
||||||
|
|
||||||
// Staple in direction mu
|
// Staple in direction mu
|
||||||
WilsonLoops<Gimpl>::Staple(dSdU_mu, U, mu);
|
WilsonLoops<Gimpl>::Staple(dSdU_mu, Ub, mu);
|
||||||
dSdU_mu = Ta(Umu * dSdU_mu) * factor;
|
dSdU_mu = Ta(Umu * dSdU_mu) * factor;
|
||||||
|
|
||||||
PokeIndex<LorentzIndex>(dSdU, dSdU_mu, mu);
|
PokeIndex<LorentzIndex>(dSdU, dSdU_mu, mu);
|
||||||
|
@ -178,7 +178,10 @@ NAMESPACE_BEGIN(Grid);
|
|||||||
// Use chronological inverter to forecast solutions across poles
|
// Use chronological inverter to forecast solutions across poles
|
||||||
std::vector<FermionField> prev_solns;
|
std::vector<FermionField> prev_solns;
|
||||||
if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); }
|
if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); }
|
||||||
ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast;
|
MdagMLinearOperator<AbstractEOFAFermion<Impl> ,FermionField> MdagML(Lop);
|
||||||
|
MdagMLinearOperator<AbstractEOFAFermion<Impl> ,FermionField> MdagMR(Rop);
|
||||||
|
// ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast;
|
||||||
|
ChronoForecast<MdagMLinearOperator<AbstractEOFAFermion<Impl>, FermionField> , FermionField> Forecast;
|
||||||
|
|
||||||
// \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta
|
// \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta
|
||||||
RealD N(PowerNegHalf.norm);
|
RealD N(PowerNegHalf.norm);
|
||||||
@ -198,7 +201,7 @@ NAMESPACE_BEGIN(Grid);
|
|||||||
heatbathRefreshShiftCoefficients(0, -gamma_l);
|
heatbathRefreshShiftCoefficients(0, -gamma_l);
|
||||||
if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles
|
if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles
|
||||||
Lop.Mdag(CG_src, Forecast_src);
|
Lop.Mdag(CG_src, Forecast_src);
|
||||||
CG_soln = Forecast(Lop, Forecast_src, prev_solns);
|
CG_soln = Forecast(MdagML, Forecast_src, prev_solns);
|
||||||
SolverHBL(Lop, CG_src, CG_soln);
|
SolverHBL(Lop, CG_src, CG_soln);
|
||||||
prev_solns.push_back(CG_soln);
|
prev_solns.push_back(CG_soln);
|
||||||
} else {
|
} else {
|
||||||
@ -225,7 +228,7 @@ NAMESPACE_BEGIN(Grid);
|
|||||||
heatbathRefreshShiftCoefficients(1, -gamma_l*PowerNegHalf.poles[k]);
|
heatbathRefreshShiftCoefficients(1, -gamma_l*PowerNegHalf.poles[k]);
|
||||||
if(use_heatbath_forecasting){
|
if(use_heatbath_forecasting){
|
||||||
Rop.Mdag(CG_src, Forecast_src);
|
Rop.Mdag(CG_src, Forecast_src);
|
||||||
CG_soln = Forecast(Rop, Forecast_src, prev_solns);
|
CG_soln = Forecast(MdagMR, Forecast_src, prev_solns);
|
||||||
SolverHBR(Rop, CG_src, CG_soln);
|
SolverHBR(Rop, CG_src, CG_soln);
|
||||||
prev_solns.push_back(CG_soln);
|
prev_solns.push_back(CG_soln);
|
||||||
} else {
|
} else {
|
||||||
|
@ -121,12 +121,19 @@ public:
|
|||||||
|
|
||||||
template <class SmearingPolicy>
|
template <class SmearingPolicy>
|
||||||
void Run(SmearingPolicy &S) {
|
void Run(SmearingPolicy &S) {
|
||||||
Runner(S);
|
TrivialMetric<typename Implementation::Field> Mtr;
|
||||||
|
Runner(S,Mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SmearingPolicy, class Metric>
|
||||||
|
void Run(SmearingPolicy &S, Metric &Mtr) {
|
||||||
|
Runner(S,Mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run(){
|
void Run(){
|
||||||
NoSmearing<Implementation> S;
|
NoSmearing<Implementation> S;
|
||||||
Runner(S);
|
TrivialMetric<typename Implementation::Field> Mtr;
|
||||||
|
Runner(S,Mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Use the checkpointer to initialize the RNGs and the gauge field, writing the resulting gauge field into U.
|
//Use the checkpointer to initialize the RNGs and the gauge field, writing the resulting gauge field into U.
|
||||||
@ -176,15 +183,15 @@ public:
|
|||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class SmearingPolicy>
|
template <class SmearingPolicy, class Metric>
|
||||||
void Runner(SmearingPolicy &Smearing) {
|
void Runner(SmearingPolicy &Smearing, Metric &Mtr) {
|
||||||
auto UGrid = Resources.GetCartesian();
|
auto UGrid = Resources.GetCartesian();
|
||||||
Field U(UGrid);
|
Field U(UGrid);
|
||||||
|
|
||||||
initializeGaugeFieldAndRNGs(U);
|
initializeGaugeFieldAndRNGs(U);
|
||||||
|
|
||||||
typedef IntegratorType<SmearingPolicy> TheIntegrator;
|
typedef IntegratorType<SmearingPolicy> TheIntegrator;
|
||||||
TheIntegrator MDynamics(UGrid, Parameters.MD, TheAction, Smearing);
|
TheIntegrator MDynamics(UGrid, Parameters.MD, TheAction, Smearing,Mtr);
|
||||||
|
|
||||||
// Sets the momentum filter
|
// Sets the momentum filter
|
||||||
MDynamics.setMomentumFilter(*(Resources.GetMomentumFilter()));
|
MDynamics.setMomentumFilter(*(Resources.GetMomentumFilter()));
|
||||||
|
@ -55,6 +55,8 @@ struct HMCparameters: Serializable {
|
|||||||
Integer, NoMetropolisUntil,
|
Integer, NoMetropolisUntil,
|
||||||
bool, PerformRandomShift, /* @brief Randomly shift the gauge configuration at the start of a trajectory */
|
bool, PerformRandomShift, /* @brief Randomly shift the gauge configuration at the start of a trajectory */
|
||||||
std::string, StartingType,
|
std::string, StartingType,
|
||||||
|
Integer, SW,
|
||||||
|
RealD, Kappa,
|
||||||
IntegratorParameters, MD)
|
IntegratorParameters, MD)
|
||||||
|
|
||||||
HMCparameters() {
|
HMCparameters() {
|
||||||
|
@ -9,6 +9,7 @@ Copyright (C) 2015
|
|||||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
||||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
||||||
Author: Guido Cossu <cossu@post.kek.jp>
|
Author: Guido Cossu <cossu@post.kek.jp>
|
||||||
|
Author: Chulwoo Jung <chulwoo@bnl.gov>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -41,10 +42,19 @@ public:
|
|||||||
GRID_SERIALIZABLE_CLASS_MEMBERS(IntegratorParameters,
|
GRID_SERIALIZABLE_CLASS_MEMBERS(IntegratorParameters,
|
||||||
std::string, name, // name of the integrator
|
std::string, name, // name of the integrator
|
||||||
unsigned int, MDsteps, // number of outer steps
|
unsigned int, MDsteps, // number of outer steps
|
||||||
|
RealD, RMHMCTol,
|
||||||
|
RealD, RMHMCCGTol,
|
||||||
|
RealD, lambda0,
|
||||||
|
RealD, lambda1,
|
||||||
|
RealD, lambda2,
|
||||||
RealD, trajL) // trajectory length
|
RealD, trajL) // trajectory length
|
||||||
|
|
||||||
IntegratorParameters(int MDsteps_ = 10, RealD trajL_ = 1.0)
|
IntegratorParameters(int MDsteps_ = 10, RealD trajL_ = 1.0)
|
||||||
: MDsteps(MDsteps_),
|
: MDsteps(MDsteps_),
|
||||||
|
lambda0(0.1931833275037836),
|
||||||
|
lambda1(0.1931833275037836),
|
||||||
|
lambda2(0.1931833275037836),
|
||||||
|
RMHMCTol(1e-8),RMHMCCGTol(1e-8),
|
||||||
trajL(trajL_) {};
|
trajL(trajL_) {};
|
||||||
|
|
||||||
template <class ReaderClass, typename std::enable_if<isReader<ReaderClass>::value, int >::type = 0 >
|
template <class ReaderClass, typename std::enable_if<isReader<ReaderClass>::value, int >::type = 0 >
|
||||||
@ -75,7 +85,8 @@ public:
|
|||||||
double t_U; // Track time passing on each level and for U and for P
|
double t_U; // Track time passing on each level and for U and for P
|
||||||
std::vector<double> t_P;
|
std::vector<double> t_P;
|
||||||
|
|
||||||
MomentaField P;
|
// MomentaField P;
|
||||||
|
GeneralisedMomenta<FieldImplementation > P;
|
||||||
SmearingPolicy& Smearer;
|
SmearingPolicy& Smearer;
|
||||||
RepresentationPolicy Representations;
|
RepresentationPolicy Representations;
|
||||||
IntegratorParameters Params;
|
IntegratorParameters Params;
|
||||||
@ -96,7 +107,16 @@ public:
|
|||||||
void update_P(Field& U, int level, double ep)
|
void update_P(Field& U, int level, double ep)
|
||||||
{
|
{
|
||||||
t_P[level] += ep;
|
t_P[level] += ep;
|
||||||
update_P(P, U, level, ep);
|
update_P(P.Mom, U, level, ep);
|
||||||
|
|
||||||
|
std::cout << GridLogIntegrator << "[" << level << "] P " << " dt " << ep << " : t_P " << t_P[level] << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_P2(Field& U, int level, double ep)
|
||||||
|
{
|
||||||
|
t_P[level] += ep;
|
||||||
|
update_P2(P.Mom, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,62 +139,167 @@ public:
|
|||||||
}
|
}
|
||||||
} update_P_hireps{};
|
} update_P_hireps{};
|
||||||
|
|
||||||
|
|
||||||
void update_P(MomentaField& Mom, Field& U, int level, double ep) {
|
void update_P(MomentaField& Mom, Field& U, int level, double ep) {
|
||||||
// input U actually not used in the fundamental case
|
// input U actually not used in the fundamental case
|
||||||
// Fundamental updates, include smearing
|
// Fundamental updates, include smearing
|
||||||
|
|
||||||
for (int a = 0; a < as[level].actions.size(); ++a) {
|
for (int a = 0; a < as[level].actions.size(); ++a) {
|
||||||
|
|
||||||
double start_full = usecond();
|
double start_full = usecond();
|
||||||
Field force(U.Grid());
|
Field force(U.Grid());
|
||||||
conformable(U.Grid(), Mom.Grid());
|
conformable(U.Grid(), Mom.Grid());
|
||||||
|
|
||||||
|
Field& Us = Smearer.get_U(as[level].actions.at(a)->is_smeared);
|
||||||
double start_force = usecond();
|
double start_force = usecond();
|
||||||
|
as[level].actions.at(a)->deriv(Us, force); // deriv should NOT include Ta
|
||||||
|
|
||||||
as[level].actions.at(a)->deriv_timer_start();
|
std::cout << GridLogIntegrator << "Smearing (on/off): " << as[level].actions.at(a)->is_smeared << std::endl;
|
||||||
as[level].actions.at(a)->deriv(Smearer, force); // deriv should NOT include Ta
|
if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force);
|
||||||
as[level].actions.at(a)->deriv_timer_stop();
|
|
||||||
|
|
||||||
auto name = as[level].actions.at(a)->action_name();
|
|
||||||
|
|
||||||
force = FieldImplementation::projectForce(force); // Ta for gauge fields
|
force = FieldImplementation::projectForce(force); // Ta for gauge fields
|
||||||
double end_force = usecond();
|
double end_force = usecond();
|
||||||
|
Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites());
|
||||||
MomFilter->applyFilter(force);
|
std::cout << GridLogIntegrator << "["<<level<<"]["<<a<<"] Force average: " << force_abs << std::endl;
|
||||||
|
|
||||||
std::cout << GridLogIntegrator << " update_P : Level [" << level <<"]["<<a <<"] "<<name<<" dt "<<ep<< std::endl;
|
|
||||||
|
|
||||||
Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites()); //average per-site norm. nb. norm2(latt) = \sum_x norm2(latt[x])
|
|
||||||
Real impulse_abs = force_abs * ep * HMC_MOMENTUM_DENOMINATOR;
|
|
||||||
|
|
||||||
Real force_max = std::sqrt(maxLocalNorm2(force));
|
|
||||||
Real impulse_max = force_max * ep * HMC_MOMENTUM_DENOMINATOR;
|
|
||||||
|
|
||||||
as[level].actions.at(a)->deriv_log(force_abs,force_max,impulse_abs,impulse_max);
|
|
||||||
|
|
||||||
std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] dt : " << ep <<" "<<name<<std::endl;
|
|
||||||
std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] Force average: " << force_abs <<" "<<name<<std::endl;
|
|
||||||
std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] Force max : " << force_max <<" "<<name<<std::endl;
|
|
||||||
std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] Fdt average : " << impulse_abs <<" "<<name<<std::endl;
|
|
||||||
std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] Fdt max : " << impulse_max <<" "<<name<<std::endl;
|
|
||||||
|
|
||||||
Mom -= force * ep* HMC_MOMENTUM_DENOMINATOR;;
|
Mom -= force * ep* HMC_MOMENTUM_DENOMINATOR;;
|
||||||
double end_full = usecond();
|
double end_full = usecond();
|
||||||
double time_full = (end_full - start_full) / 1e3;
|
double time_full = (end_full - start_full) / 1e3;
|
||||||
double time_force = (end_force - start_force) / 1e3;
|
double time_force = (end_force - start_force) / 1e3;
|
||||||
std::cout << GridLogMessage << "["<<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
|
// Force from the other representations
|
||||||
as[level].apply(update_P_hireps, Representations, Mom, U, ep);
|
as[level].apply(update_P_hireps, Representations, Mom, U, ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_P2(MomentaField& Mom, Field& U, int level, double ep) {
|
||||||
|
// input U actually not used in the fundamental case
|
||||||
|
// Fundamental updates, include smearing
|
||||||
|
|
||||||
|
std::cout << GridLogIntegrator << "U before update_P2: " << std::sqrt(norm2(U)) << std::endl;
|
||||||
|
// Generalised momenta
|
||||||
|
// Derivative of the kinetic term must be computed before
|
||||||
|
// Mom is the momenta and gets updated by the
|
||||||
|
// actions derivatives
|
||||||
|
MomentaField MomDer(P.Mom.Grid());
|
||||||
|
P.M.ImportGauge(U);
|
||||||
|
P.DerivativeU(P.Mom, MomDer);
|
||||||
|
std::cout << GridLogIntegrator << "MomDer update_P2: " << std::sqrt(norm2(MomDer)) << std::endl;
|
||||||
|
// Mom -= MomDer * ep;
|
||||||
|
Mom -= MomDer * ep * HMC_MOMENTUM_DENOMINATOR;
|
||||||
|
std::cout << GridLogIntegrator << "Mom update_P2: " << std::sqrt(norm2(Mom)) << std::endl;
|
||||||
|
|
||||||
|
// Auxiliary fields
|
||||||
|
P.update_auxiliary_momenta(ep*0.5 );
|
||||||
|
P.AuxiliaryFieldsDerivative(MomDer);
|
||||||
|
std::cout << GridLogIntegrator << "MomDer(Aux) update_P2: " << std::sqrt(norm2(Mom)) << std::endl;
|
||||||
|
// Mom -= MomDer * ep;
|
||||||
|
Mom -= MomDer * ep * HMC_MOMENTUM_DENOMINATOR;
|
||||||
|
P.update_auxiliary_momenta(ep*0.5 );
|
||||||
|
|
||||||
|
for (int a = 0; a < as[level].actions.size(); ++a) {
|
||||||
|
double start_full = usecond();
|
||||||
|
Field force(U.Grid());
|
||||||
|
conformable(U.Grid(), Mom.Grid());
|
||||||
|
|
||||||
|
Field& Us = Smearer.get_U(as[level].actions.at(a)->is_smeared);
|
||||||
|
double start_force = usecond();
|
||||||
|
as[level].actions.at(a)->deriv(Us, force); // deriv should NOT include Ta
|
||||||
|
|
||||||
|
std::cout << GridLogIntegrator << "Smearing (on/off): " << as[level].actions.at(a)->is_smeared << std::endl;
|
||||||
|
if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force);
|
||||||
|
force = FieldImplementation::projectForce(force); // Ta for gauge fields
|
||||||
|
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* 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 << 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 implicit_update_P(Field& U, int level, double ep, bool intermediate = false) {
|
||||||
|
t_P[level] += ep;
|
||||||
|
|
||||||
|
std::cout << GridLogIntegrator << "[" << level << "] P "
|
||||||
|
<< " dt " << ep << " : t_P " << t_P[level] << std::endl;
|
||||||
|
std::cout << GridLogIntegrator << "U before implicit_update_P: " << std::sqrt(norm2(U)) << std::endl;
|
||||||
|
// Fundamental updates, include smearing
|
||||||
|
MomentaField Msum(P.Mom.Grid());
|
||||||
|
Msum = Zero();
|
||||||
|
for (int a = 0; a < as[level].actions.size(); ++a) {
|
||||||
|
// Compute the force terms for the lagrangian part
|
||||||
|
// We need to compute the derivative of the actions
|
||||||
|
// only once
|
||||||
|
Field force(U.Grid());
|
||||||
|
conformable(U.Grid(), P.Mom.Grid());
|
||||||
|
Field& Us = Smearer.get_U(as[level].actions.at(a)->is_smeared);
|
||||||
|
as[level].actions.at(a)->deriv(Us, force); // deriv should NOT include Ta
|
||||||
|
|
||||||
|
std::cout << GridLogIntegrator << "Smearing (on/off): " << as[level].actions.at(a)->is_smeared << std::endl;
|
||||||
|
if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force);
|
||||||
|
force = FieldImplementation::projectForce(force); // Ta for gauge fields
|
||||||
|
Real force_abs = std::sqrt(norm2(force) / U.Grid()->gSites());
|
||||||
|
std::cout << GridLogIntegrator << "|Force| site average: " << force_abs
|
||||||
|
<< std::endl;
|
||||||
|
Msum += force;
|
||||||
|
}
|
||||||
|
|
||||||
|
MomentaField NewMom = P.Mom;
|
||||||
|
MomentaField OldMom = P.Mom;
|
||||||
|
double threshold = Params.RMHMCTol;
|
||||||
|
P.M.ImportGauge(U);
|
||||||
|
MomentaField MomDer(P.Mom.Grid());
|
||||||
|
MomentaField MomDer1(P.Mom.Grid());
|
||||||
|
MomentaField AuxDer(P.Mom.Grid());
|
||||||
|
MomDer1 = Zero();
|
||||||
|
MomentaField diff(P.Mom.Grid());
|
||||||
|
double factor = 2.0;
|
||||||
|
if (intermediate){
|
||||||
|
P.DerivativeU(P.Mom, MomDer1);
|
||||||
|
factor = 1.0;
|
||||||
|
}
|
||||||
|
// std::cout << GridLogIntegrator << "MomDer1 implicit_update_P: " << std::sqrt(norm2(MomDer1)) << std::endl;
|
||||||
|
|
||||||
|
// Auxiliary fields
|
||||||
|
P.update_auxiliary_momenta(ep*0.5 );
|
||||||
|
P.AuxiliaryFieldsDerivative(AuxDer);
|
||||||
|
Msum += AuxDer;
|
||||||
|
|
||||||
|
|
||||||
|
// Here run recursively
|
||||||
|
int counter = 1;
|
||||||
|
RealD RelativeError;
|
||||||
|
do {
|
||||||
|
std::cout << GridLogIntegrator << "UpdateP implicit step "<< counter << std::endl;
|
||||||
|
|
||||||
|
// Compute the derivative of the kinetic term
|
||||||
|
// with respect to the gauge field
|
||||||
|
P.DerivativeU(NewMom, MomDer);
|
||||||
|
Real force_abs = std::sqrt(norm2(MomDer) / U.Grid()->gSites());
|
||||||
|
std::cout << GridLogIntegrator << "|Force| laplacian site average: " << force_abs
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
NewMom = P.Mom - ep* 0.5 * HMC_MOMENTUM_DENOMINATOR * (2.0*Msum + factor*MomDer + MomDer1);// simplify
|
||||||
|
diff = NewMom - OldMom;
|
||||||
|
counter++;
|
||||||
|
RelativeError = std::sqrt(norm2(diff))/std::sqrt(norm2(NewMom));
|
||||||
|
std::cout << GridLogIntegrator << "UpdateP RelativeError: " << RelativeError << std::endl;
|
||||||
|
OldMom = NewMom;
|
||||||
|
} while (RelativeError > threshold);
|
||||||
|
|
||||||
|
P.Mom = NewMom;
|
||||||
|
std::cout << GridLogIntegrator << "NewMom implicit_update_P: " << std::sqrt(norm2(NewMom)) << std::endl;
|
||||||
|
|
||||||
|
// update the auxiliary fields momenta
|
||||||
|
P.update_auxiliary_momenta(ep*0.5 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_U(Field& U, double ep)
|
void update_U(Field& U, double ep)
|
||||||
{
|
{
|
||||||
update_U(P, U, ep);
|
update_U(P.Mom, U, ep);
|
||||||
|
|
||||||
t_U += ep;
|
t_U += ep;
|
||||||
int fl = levels - 1;
|
int fl = levels - 1;
|
||||||
@ -183,12 +308,8 @@ public:
|
|||||||
|
|
||||||
void update_U(MomentaField& Mom, Field& U, double ep)
|
void update_U(MomentaField& Mom, Field& U, double ep)
|
||||||
{
|
{
|
||||||
MomentaField MomFiltered(Mom.Grid());
|
|
||||||
MomFiltered = Mom;
|
|
||||||
MomFilter->applyFilter(MomFiltered);
|
|
||||||
|
|
||||||
// exponential of Mom*U in the gauge fields case
|
// exponential of Mom*U in the gauge fields case
|
||||||
FieldImplementation::update_field(MomFiltered, U, ep);
|
FieldImplementation::update_field(Mom, U, ep);
|
||||||
|
|
||||||
// Update the smeared fields, can be implemented as observer
|
// Update the smeared fields, can be implemented as observer
|
||||||
Smearer.set_Field(U);
|
Smearer.set_Field(U);
|
||||||
@ -197,15 +318,70 @@ public:
|
|||||||
Representations.update(U); // void functions if fundamental representation
|
Representations.update(U); // void functions if fundamental representation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void implicit_update_U(Field&U, double ep, double ep1 ){
|
||||||
|
double ep2=ep-ep1;
|
||||||
|
t_U += ep;
|
||||||
|
int fl = levels - 1;
|
||||||
|
std::cout << GridLogIntegrator << " " << "[" << fl << "] U " << " dt " << ep << " : t_U " << t_U << std::endl;
|
||||||
|
std::cout << GridLogIntegrator << "U before implicit_update_U: " << std::sqrt(norm2(U)) << std::endl;
|
||||||
|
|
||||||
|
MomentaField Mom1(P.Mom.Grid());
|
||||||
|
MomentaField Mom2(P.Mom.Grid());
|
||||||
|
RealD RelativeError;
|
||||||
|
Field diff(U.Grid());
|
||||||
|
Real threshold = Params.RMHMCTol;
|
||||||
|
int counter = 1;
|
||||||
|
int MaxCounter = 100;
|
||||||
|
|
||||||
|
Field OldU = U;
|
||||||
|
Field NewU = U;
|
||||||
|
|
||||||
|
P.M.ImportGauge(U);
|
||||||
|
P.DerivativeP(Mom1); // first term in the derivative
|
||||||
|
std::cout << GridLogIntegrator << "implicit_update_U: Mom1: " << std::sqrt(norm2(Mom1)) << std::endl;
|
||||||
|
|
||||||
|
P.update_auxiliary_fields(ep1);
|
||||||
|
|
||||||
|
|
||||||
|
MomentaField sum=Mom1;
|
||||||
|
do {
|
||||||
|
std::cout << GridLogIntegrator << "UpdateU implicit step "<< counter << std::endl;
|
||||||
|
|
||||||
|
P.DerivativeP(Mom2); // second term in the derivative, on the updated U
|
||||||
|
std::cout << GridLogIntegrator << "implicit_update_U: Mom1: " << std::sqrt(norm2(Mom1)) << std::endl;
|
||||||
|
sum = (Mom1*ep1 + Mom2*ep2);
|
||||||
|
|
||||||
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
|
auto Umu = PeekIndex<LorentzIndex>(U, mu);
|
||||||
|
auto Pmu = PeekIndex<LorentzIndex>(sum, mu);
|
||||||
|
Umu = expMat(Pmu, 1, 12) * Umu;
|
||||||
|
PokeIndex<LorentzIndex>(NewU, ProjectOnGroup(Umu), mu);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff = NewU - OldU;
|
||||||
|
RelativeError = std::sqrt(norm2(diff))/std::sqrt(norm2(NewU));
|
||||||
|
std::cout << GridLogIntegrator << "UpdateU RelativeError: " << RelativeError << std::endl;
|
||||||
|
|
||||||
|
P.M.ImportGauge(NewU);
|
||||||
|
OldU = NewU; // some redundancy to be eliminated
|
||||||
|
counter++;
|
||||||
|
} while (RelativeError > threshold && counter < MaxCounter);
|
||||||
|
|
||||||
|
U = NewU;
|
||||||
|
std::cout << GridLogIntegrator << "NewU implicit_update_U: " << std::sqrt(norm2(U)) << std::endl;
|
||||||
|
P.update_auxiliary_fields(ep2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void step(Field& U, int level, int first, int last) = 0;
|
virtual void step(Field& U, int level, int first, int last) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Integrator(GridBase* grid, IntegratorParameters Par,
|
Integrator(GridBase* grid, IntegratorParameters Par,
|
||||||
ActionSet<Field, RepresentationPolicy>& Aset,
|
ActionSet<Field, RepresentationPolicy>& Aset,
|
||||||
SmearingPolicy& Sm)
|
SmearingPolicy& Sm, Metric<MomentaField>& M)
|
||||||
: Params(Par),
|
: Params(Par),
|
||||||
as(Aset),
|
as(Aset),
|
||||||
P(grid),
|
P(grid, M),
|
||||||
levels(Aset.size()),
|
levels(Aset.size()),
|
||||||
Smearer(Sm),
|
Smearer(Sm),
|
||||||
Representations(grid)
|
Representations(grid)
|
||||||
@ -324,7 +500,8 @@ public:
|
|||||||
|
|
||||||
void reverse_momenta()
|
void reverse_momenta()
|
||||||
{
|
{
|
||||||
P *= -1.0;
|
P.Mom *= -1.0;
|
||||||
|
P.AuxMom *= -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be used by the actionlevel class to iterate
|
// to be used by the actionlevel class to iterate
|
||||||
@ -343,11 +520,11 @@ public:
|
|||||||
// Initialization of momenta and actions
|
// Initialization of momenta and actions
|
||||||
void refresh(Field& U, GridSerialRNG & sRNG, GridParallelRNG& pRNG)
|
void refresh(Field& U, GridSerialRNG & sRNG, GridParallelRNG& pRNG)
|
||||||
{
|
{
|
||||||
assert(P.Grid() == U.Grid());
|
assert(P.Mom.Grid() == U.Grid());
|
||||||
std::cout << GridLogIntegrator << "Integrator refresh" << std::endl;
|
std::cout << GridLogIntegrator << "Integrator refresh" << std::endl;
|
||||||
|
|
||||||
std::cout << GridLogIntegrator << "Generating momentum" << std::endl;
|
std::cout << GridLogIntegrator << "Generating momentum" << std::endl;
|
||||||
FieldImplementation::generate_momenta(P, sRNG, pRNG);
|
FieldImplementation::generate_momenta(P.Mom, sRNG, pRNG);
|
||||||
|
|
||||||
// Update the smeared fields, can be implemented as observer
|
// Update the smeared fields, can be implemented as observer
|
||||||
// necessary to keep the fields updated even after a reject
|
// necessary to keep the fields updated even after a reject
|
||||||
@ -402,7 +579,7 @@ public:
|
|||||||
|
|
||||||
std::cout << GridLogIntegrator << "Integrator action\n";
|
std::cout << GridLogIntegrator << "Integrator action\n";
|
||||||
|
|
||||||
RealD H = - FieldImplementation::FieldSquareNorm(P)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
|
RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
|
||||||
|
|
||||||
RealD Hterm;
|
RealD Hterm;
|
||||||
|
|
||||||
@ -446,7 +623,7 @@ public:
|
|||||||
|
|
||||||
std::cout << GridLogIntegrator << "Integrator initial action\n";
|
std::cout << GridLogIntegrator << "Integrator initial action\n";
|
||||||
|
|
||||||
RealD H = - FieldImplementation::FieldSquareNorm(P)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
|
RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
|
||||||
|
|
||||||
RealD Hterm;
|
RealD Hterm;
|
||||||
|
|
||||||
|
@ -102,8 +102,8 @@ public:
|
|||||||
|
|
||||||
std::string integrator_name(){return "LeapFrog";}
|
std::string integrator_name(){return "LeapFrog";}
|
||||||
|
|
||||||
LeapFrog(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
|
LeapFrog(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
|
||||||
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm){};
|
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm,M){};
|
||||||
|
|
||||||
void step(Field& U, int level, int _first, int _last) {
|
void step(Field& U, int level, int _first, int _last) {
|
||||||
int fl = this->as.size() - 1;
|
int fl = this->as.size() - 1;
|
||||||
@ -146,8 +146,8 @@ public:
|
|||||||
typedef FieldImplementation_ FieldImplementation;
|
typedef FieldImplementation_ FieldImplementation;
|
||||||
INHERIT_FIELD_TYPES(FieldImplementation);
|
INHERIT_FIELD_TYPES(FieldImplementation);
|
||||||
|
|
||||||
MinimumNorm2(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
|
MinimumNorm2(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
|
||||||
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm){};
|
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm,M){};
|
||||||
|
|
||||||
std::string integrator_name(){return "MininumNorm2";}
|
std::string integrator_name(){return "MininumNorm2";}
|
||||||
|
|
||||||
@ -210,9 +210,9 @@ public:
|
|||||||
// Looks like dH scales as dt^4. tested wilson/wilson 2 level.
|
// Looks like dH scales as dt^4. tested wilson/wilson 2 level.
|
||||||
ForceGradient(GridBase* grid, IntegratorParameters Par,
|
ForceGradient(GridBase* grid, IntegratorParameters Par,
|
||||||
ActionSet<Field, RepresentationPolicy>& Aset,
|
ActionSet<Field, RepresentationPolicy>& Aset,
|
||||||
SmearingPolicy& Sm)
|
SmearingPolicy& Sm, Metric<Field>& M)
|
||||||
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
|
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
|
||||||
grid, Par, Aset, Sm){};
|
grid, Par, Aset, Sm,M){};
|
||||||
|
|
||||||
std::string integrator_name(){return "ForceGradient";}
|
std::string integrator_name(){return "ForceGradient";}
|
||||||
|
|
||||||
@ -275,6 +275,184 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Riemannian Manifold HMC
|
||||||
|
// Girolami et al
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// correct
|
||||||
|
template <class FieldImplementation, class SmearingPolicy,
|
||||||
|
class RepresentationPolicy =
|
||||||
|
Representations<FundamentalRepresentation> >
|
||||||
|
class ImplicitLeapFrog : public Integrator<FieldImplementation, SmearingPolicy,
|
||||||
|
RepresentationPolicy> {
|
||||||
|
public:
|
||||||
|
typedef ImplicitLeapFrog<FieldImplementation, SmearingPolicy, RepresentationPolicy>
|
||||||
|
Algorithm;
|
||||||
|
INHERIT_FIELD_TYPES(FieldImplementation);
|
||||||
|
|
||||||
|
// Riemannian manifold metric operator
|
||||||
|
// Hermitian operator Fisher
|
||||||
|
|
||||||
|
std::string integrator_name(){return "ImplicitLeapFrog";}
|
||||||
|
|
||||||
|
ImplicitLeapFrog(GridBase* grid, IntegratorParameters Par,
|
||||||
|
ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
|
||||||
|
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
|
||||||
|
grid, Par, Aset, Sm, M){};
|
||||||
|
|
||||||
|
void step(Field& U, int level, int _first, int _last) {
|
||||||
|
int fl = this->as.size() - 1;
|
||||||
|
// level : current level
|
||||||
|
// fl : final level
|
||||||
|
// eps : current step size
|
||||||
|
|
||||||
|
// Get current level step size
|
||||||
|
RealD eps = this->Params.trajL/this->Params.MDsteps;
|
||||||
|
for (int l = 0; l <= level; ++l) eps /= this->as[l].multiplier;
|
||||||
|
|
||||||
|
int multiplier = this->as[level].multiplier;
|
||||||
|
for (int e = 0; e < multiplier; ++e) {
|
||||||
|
int first_step = _first && (e == 0);
|
||||||
|
int last_step = _last && (e == multiplier - 1);
|
||||||
|
|
||||||
|
if (first_step) { // initial half step
|
||||||
|
this->implicit_update_P(U, level, eps / 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level == fl) { // lowest level
|
||||||
|
this->implicit_update_U(U, eps,eps/2.);
|
||||||
|
} else { // recursive function call
|
||||||
|
this->step(U, level + 1, first_step, last_step);
|
||||||
|
}
|
||||||
|
|
||||||
|
//int mm = last_step ? 1 : 2;
|
||||||
|
if (last_step){
|
||||||
|
this->update_P2(U, level, eps / 2.0);
|
||||||
|
} else {
|
||||||
|
this->implicit_update_P(U, level, eps, true);// works intermediate step
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class FieldImplementation, class SmearingPolicy,
|
||||||
|
class RepresentationPolicy =
|
||||||
|
Representations<FundamentalRepresentation> >
|
||||||
|
class ImplicitMinimumNorm2 : public Integrator<FieldImplementation, SmearingPolicy,
|
||||||
|
RepresentationPolicy> {
|
||||||
|
private:
|
||||||
|
// const RealD lambda = 0.1931833275037836;
|
||||||
|
|
||||||
|
public:
|
||||||
|
INHERIT_FIELD_TYPES(FieldImplementation);
|
||||||
|
|
||||||
|
ImplicitMinimumNorm2(GridBase* grid, IntegratorParameters Par,
|
||||||
|
ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
|
||||||
|
: Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
|
||||||
|
grid, Par, Aset, Sm, M){};
|
||||||
|
|
||||||
|
std::string integrator_name(){return "ImplicitMininumNorm2";}
|
||||||
|
|
||||||
|
void step(Field& U, int level, int _first, int _last) {
|
||||||
|
// level : current level
|
||||||
|
// fl : final level
|
||||||
|
// eps : current step size
|
||||||
|
|
||||||
|
int fl = this->as.size() - 1;
|
||||||
|
// assert(Params.lambda.size()>level);
|
||||||
|
// RealD lambda= Params.lambda[level];
|
||||||
|
assert(level<3);
|
||||||
|
RealD lambda= this->Params.lambda0;
|
||||||
|
if (level>0) lambda= this->Params.lambda1;
|
||||||
|
if (level>1) lambda= this->Params.lambda2;
|
||||||
|
std::cout << GridLogMessage << "level: "<<level<< "lambda: "<<lambda<<std::endl;
|
||||||
|
|
||||||
|
if(level<fl){
|
||||||
|
|
||||||
|
RealD eps = this->Params.trajL/this->Params.MDsteps * 2.0;
|
||||||
|
for (int l = 0; l <= level; ++l) eps /= 2.0 * this->as[l].multiplier;
|
||||||
|
|
||||||
|
// Nesting: 2xupdate_U of size eps/2
|
||||||
|
// Next level is eps/2/multiplier
|
||||||
|
|
||||||
|
int multiplier = this->as[level].multiplier;
|
||||||
|
for (int e = 0; e < multiplier; ++e) { // steps per step
|
||||||
|
|
||||||
|
int first_step = _first && (e == 0);
|
||||||
|
int last_step = _last && (e == multiplier - 1);
|
||||||
|
|
||||||
|
if (first_step) { // initial half step
|
||||||
|
this->update_P(U, level, lambda * eps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level == fl) { // lowest level
|
||||||
|
this->update_U(U, 0.5 * eps);
|
||||||
|
} else { // recursive function call
|
||||||
|
this->step(U, level + 1, first_step, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->update_P(U, level, (1.0 - 2.0 * lambda) * eps);
|
||||||
|
|
||||||
|
if (level == fl) { // lowest level
|
||||||
|
this->update_U(U, 0.5 * eps);
|
||||||
|
} else { // recursive function call
|
||||||
|
this->step(U, level + 1, 0, last_step);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm = (last_step) ? 1 : 2;
|
||||||
|
this->update_P(U, level, lambda * eps * mm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // last level
|
||||||
|
RealD eps = this->Params.trajL/this->Params.MDsteps * 2.0;
|
||||||
|
for (int l = 0; l <= level; ++l) eps /= 2.0 * this->as[l].multiplier;
|
||||||
|
|
||||||
|
// Nesting: 2xupdate_U of size eps/2
|
||||||
|
// Next level is eps/2/multiplier
|
||||||
|
|
||||||
|
int multiplier = this->as[level].multiplier;
|
||||||
|
for (int e = 0; e < multiplier; ++e) { // steps per step
|
||||||
|
|
||||||
|
int first_step = _first && (e == 0);
|
||||||
|
int last_step = _last && (e == multiplier - 1);
|
||||||
|
|
||||||
|
if (first_step) { // initial half step
|
||||||
|
this->implicit_update_P(U, level, lambda * eps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level == fl) { // lowest level
|
||||||
|
this->implicit_update_U(U, 0.5 * eps,lambda*eps);
|
||||||
|
} else { // recursive function call
|
||||||
|
this->step(U, level + 1, first_step, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->implicit_update_P(U, level, (1.0 - 2.0 * lambda) * eps, true);
|
||||||
|
|
||||||
|
if (level == fl) { // lowest level
|
||||||
|
this->implicit_update_U(U, 0.5 * eps, (0.5-lambda)*eps);
|
||||||
|
} else { // recursive function call
|
||||||
|
this->step(U, level + 1, 0, last_step);
|
||||||
|
}
|
||||||
|
|
||||||
|
//int mm = (last_step) ? 1 : 2;
|
||||||
|
//this->update_P(U, level, lambda * eps * mm);
|
||||||
|
|
||||||
|
if (last_step) {
|
||||||
|
this->update_P2(U, level, eps * lambda);
|
||||||
|
} else {
|
||||||
|
this->implicit_update_P(U, level, lambda * eps*2.0, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
NAMESPACE_END(Grid);
|
NAMESPACE_END(Grid);
|
||||||
|
|
||||||
#endif // INTEGRATOR_INCLUDED
|
#endif // INTEGRATOR_INCLUDED
|
||||||
|
@ -54,7 +54,133 @@ struct LaplacianParams : Serializable {
|
|||||||
precision(precision){};
|
precision(precision){};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LEG_LOAD(Dir) \
|
||||||
|
SE = st.GetEntry(ptype, Dir, ss); \
|
||||||
|
if (SE->_is_local ) { \
|
||||||
|
int perm= SE->_permute; \
|
||||||
|
chi = coalescedReadPermute(in[SE->_offset],ptype,perm,lane); \
|
||||||
|
} else { \
|
||||||
|
chi = coalescedRead(buf[SE->_offset],lane); \
|
||||||
|
} \
|
||||||
|
acceleratorSynchronise();
|
||||||
|
|
||||||
|
const std::vector<int> directions4D ({Xdir,Ydir,Zdir,Tdir,Xdir,Ydir,Zdir,Tdir});
|
||||||
|
const std::vector<int> displacements4D({1,1,1,1,-1,-1,-1,-1});
|
||||||
|
|
||||||
|
template<class Gimpl,class Field> class CovariantAdjointLaplacianStencil : public SparseMatrixBase<Field>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
INHERIT_GIMPL_TYPES(Gimpl);
|
||||||
|
// RealD kappa;
|
||||||
|
|
||||||
|
typedef typename Field::vector_object siteObject;
|
||||||
|
|
||||||
|
template <typename vtype> using iImplDoubledGaugeField = iVector<iScalar<iMatrix<vtype, Nc> >, Nds>;
|
||||||
|
typedef iImplDoubledGaugeField<Simd> SiteDoubledGaugeField;
|
||||||
|
typedef Lattice<SiteDoubledGaugeField> DoubledGaugeField;
|
||||||
|
typedef CartesianStencil<siteObject, siteObject, DefaultImplParams> StencilImpl;
|
||||||
|
|
||||||
|
GridBase *grid;
|
||||||
|
StencilImpl Stencil;
|
||||||
|
SimpleCompressor<siteObject> Compressor;
|
||||||
|
DoubledGaugeField Uds;
|
||||||
|
|
||||||
|
CovariantAdjointLaplacianStencil( GridBase *_grid)
|
||||||
|
: grid(_grid),
|
||||||
|
Stencil (grid,8,Even,directions4D,displacements4D),
|
||||||
|
Uds(grid){}
|
||||||
|
|
||||||
|
CovariantAdjointLaplacianStencil(GaugeField &Umu)
|
||||||
|
:
|
||||||
|
grid(Umu.Grid()),
|
||||||
|
Stencil (grid,8,Even,directions4D,displacements4D),
|
||||||
|
Uds(grid)
|
||||||
|
{ GaugeImport(Umu); }
|
||||||
|
|
||||||
|
void GaugeImport (const GaugeField &Umu)
|
||||||
|
{
|
||||||
|
assert(grid == Umu.Grid());
|
||||||
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
|
auto U = PeekIndex<LorentzIndex>(Umu, mu);
|
||||||
|
PokeIndex<LorentzIndex>(Uds, U, mu );
|
||||||
|
U = adj(Cshift(U, mu, -1));
|
||||||
|
PokeIndex<LorentzIndex>(Uds, U, mu + 4);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual GridBase *Grid(void) { return grid; };
|
||||||
|
|
||||||
|
virtual void M (const Field &_in, Field &_out)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
// Halo exchange for this geometry of stencil
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
Stencil.HaloExchange(_in, Compressor);
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
// Arithmetic expressions
|
||||||
|
///////////////////////////////////
|
||||||
|
auto st = Stencil.View(AcceleratorRead);
|
||||||
|
auto buf = st.CommBuf();
|
||||||
|
|
||||||
|
autoView( in , _in , AcceleratorRead);
|
||||||
|
autoView( out , _out , AcceleratorWrite);
|
||||||
|
autoView( U , Uds , AcceleratorRead);
|
||||||
|
|
||||||
|
typedef typename Field::vector_object vobj;
|
||||||
|
typedef decltype(coalescedRead(in[0])) calcObj;
|
||||||
|
typedef decltype(coalescedRead(U[0](0))) calcLink;
|
||||||
|
|
||||||
|
const int Nsimd = vobj::Nsimd();
|
||||||
|
const uint64_t NN = grid->oSites();
|
||||||
|
|
||||||
|
accelerator_for( ss, NN, Nsimd, {
|
||||||
|
|
||||||
|
StencilEntry *SE;
|
||||||
|
|
||||||
|
const int lane=acceleratorSIMTlane(Nsimd);
|
||||||
|
|
||||||
|
calcObj chi;
|
||||||
|
calcObj res;
|
||||||
|
calcObj Uchi;
|
||||||
|
calcObj Utmp;
|
||||||
|
calcObj Utmp2;
|
||||||
|
calcLink UU;
|
||||||
|
calcLink Udag;
|
||||||
|
int ptype;
|
||||||
|
|
||||||
|
res = coalescedRead(in[ss])*(-8.0);
|
||||||
|
|
||||||
|
#define LEG_LOAD_MULT(leg,polarisation) \
|
||||||
|
UU = coalescedRead(U[ss](polarisation)); \
|
||||||
|
Udag = adj(UU); \
|
||||||
|
LEG_LOAD(leg); \
|
||||||
|
mult(&Utmp(), &UU, &chi()); \
|
||||||
|
Utmp2 = adj(Utmp); \
|
||||||
|
mult(&Utmp(), &UU, &Utmp2()); \
|
||||||
|
Uchi = adj(Utmp); \
|
||||||
|
res = res + Uchi;
|
||||||
|
|
||||||
|
LEG_LOAD_MULT(0,Xp);
|
||||||
|
LEG_LOAD_MULT(1,Yp);
|
||||||
|
LEG_LOAD_MULT(2,Zp);
|
||||||
|
LEG_LOAD_MULT(3,Tp);
|
||||||
|
LEG_LOAD_MULT(4,Xm);
|
||||||
|
LEG_LOAD_MULT(5,Ym);
|
||||||
|
LEG_LOAD_MULT(6,Zm);
|
||||||
|
LEG_LOAD_MULT(7,Tm);
|
||||||
|
|
||||||
|
coalescedWrite(out[ss], res,lane);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
virtual void Mdag (const Field &in, Field &out) { M(in,out);}; // Laplacian is hermitian
|
||||||
|
virtual void Mdiag (const Field &in, Field &out) {assert(0);}; // Unimplemented need only for multigrid
|
||||||
|
virtual void Mdir (const Field &in, Field &out,int dir, int disp){assert(0);}; // Unimplemented need only for multigrid
|
||||||
|
virtual void MdirAll (const Field &in, std::vector<Field> &out) {assert(0);}; // Unimplemented need only for multigrid
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef LEG_LOAD_MULT
|
||||||
|
#undef LEG_LOAD
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Laplacian operator L on adjoint fields
|
// Laplacian operator L on adjoint fields
|
||||||
@ -76,29 +202,40 @@ class LaplacianAdjointField: public Metric<typename Impl::Field> {
|
|||||||
LaplacianParams param;
|
LaplacianParams param;
|
||||||
MultiShiftFunction PowerHalf;
|
MultiShiftFunction PowerHalf;
|
||||||
MultiShiftFunction PowerInvHalf;
|
MultiShiftFunction PowerInvHalf;
|
||||||
|
//template<class Gimpl,class Field> class CovariantAdjointLaplacianStencil : public SparseMatrixBase<Field>
|
||||||
|
CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField> LapStencil;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
INHERIT_GIMPL_TYPES(Impl);
|
INHERIT_GIMPL_TYPES(Impl);
|
||||||
|
|
||||||
LaplacianAdjointField(GridBase* grid, OperatorFunction<GaugeField>& S, LaplacianParams& p, const RealD k = 1.0)
|
LaplacianAdjointField(GridBase* grid, OperatorFunction<GaugeField>& S, LaplacianParams& p, const RealD k = 1.0, bool if_remez=true)
|
||||||
: U(Nd, grid), Solver(S), param(p), kappa(k){
|
: U(Nd, grid), Solver(S), param(p), kappa(k)
|
||||||
|
,LapStencil(grid){
|
||||||
AlgRemez remez(param.lo,param.hi,param.precision);
|
AlgRemez remez(param.lo,param.hi,param.precision);
|
||||||
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
||||||
|
if(if_remez){
|
||||||
remez.generateApprox(param.degree,1,2);
|
remez.generateApprox(param.degree,1,2);
|
||||||
PowerHalf.Init(remez,param.tolerance,false);
|
PowerHalf.Init(remez,param.tolerance,false);
|
||||||
PowerInvHalf.Init(remez,param.tolerance,true);
|
PowerInvHalf.Init(remez,param.tolerance,true);
|
||||||
|
}
|
||||||
|
this->triv=0;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
LaplacianAdjointField(){this->triv=0; printf("triv=%d\n",this->Trivial());}
|
||||||
void Mdir(const GaugeField&, GaugeField&, int, int){ assert(0);}
|
void Mdir(const GaugeField&, GaugeField&, int, int){ assert(0);}
|
||||||
void MdirAll(const GaugeField&, std::vector<GaugeField> &){ assert(0);}
|
void MdirAll(const GaugeField&, std::vector<GaugeField> &){ assert(0);}
|
||||||
void Mdiag(const GaugeField&, GaugeField&){ assert(0);}
|
void Mdiag(const GaugeField&, GaugeField&){ assert(0);}
|
||||||
|
|
||||||
void ImportGauge(const GaugeField& _U) {
|
void ImportGauge(const GaugeField& _U) {
|
||||||
|
RealD total=0.;
|
||||||
for (int mu = 0; mu < Nd; mu++) {
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
U[mu] = PeekIndex<LorentzIndex>(_U, mu);
|
U[mu] = PeekIndex<LorentzIndex>(_U, mu);
|
||||||
|
total += norm2(U[mu]);
|
||||||
}
|
}
|
||||||
|
LapStencil.GaugeImport (_U);
|
||||||
|
|
||||||
|
std::cout << GridLogDebug <<"ImportGauge:norm2(U _U) = "<<total<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void M(const GaugeField& in, GaugeField& out) {
|
void M(const GaugeField& in, GaugeField& out) {
|
||||||
@ -106,10 +243,12 @@ public:
|
|||||||
// test
|
// test
|
||||||
//GaugeField herm = in + adj(in);
|
//GaugeField herm = in + adj(in);
|
||||||
//std::cout << "AHermiticity: " << norm2(herm) << std::endl;
|
//std::cout << "AHermiticity: " << norm2(herm) << std::endl;
|
||||||
|
// std::cout << GridLogDebug <<"M:Kappa = "<<kappa<<std::endl;
|
||||||
|
|
||||||
|
GaugeLinkField sum(in.Grid());
|
||||||
|
#if 0
|
||||||
GaugeLinkField tmp(in.Grid());
|
GaugeLinkField tmp(in.Grid());
|
||||||
GaugeLinkField tmp2(in.Grid());
|
GaugeLinkField tmp2(in.Grid());
|
||||||
GaugeLinkField sum(in.Grid());
|
|
||||||
|
|
||||||
for (int nu = 0; nu < Nd; nu++) {
|
for (int nu = 0; nu < Nd; nu++) {
|
||||||
sum = Zero();
|
sum = Zero();
|
||||||
@ -123,10 +262,69 @@ public:
|
|||||||
out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum;
|
out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum;
|
||||||
PokeIndex<LorentzIndex>(out, out_nu, nu);
|
PokeIndex<LorentzIndex>(out, out_nu, nu);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
for (int nu = 0; nu < Nd; nu++) {
|
||||||
|
GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu);
|
||||||
|
GaugeLinkField out_nu(out.Grid());
|
||||||
|
LapStencil.M(in_nu,sum);
|
||||||
|
out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum;
|
||||||
|
PokeIndex<LorentzIndex>(out, out_nu, nu);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// std::cout << GridLogDebug <<"M:norm2(out) = "<<norm2(out)<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void Quad(const GaugeField& in, GaugeField& out,RealD a0,RealD a1,RealD a2) {
|
||||||
|
|
||||||
|
GaugeLinkField tmp(in.Grid());
|
||||||
|
GaugeLinkField tmp2(in.Grid());
|
||||||
|
#if 0
|
||||||
|
std::vector<GaugeLinkField> sum(in.Grid(),Nd);
|
||||||
|
std::vector<GaugeLinkField> sum2(in.Grid(),Nd);
|
||||||
|
std::vector<GaugeLinkField> in_nu(in.Grid(),Nd);
|
||||||
|
std::vector<GaugeLinkField> out_nu(in.Grid(),Nd);
|
||||||
|
|
||||||
|
for (int nu = 0; nu < Nd; nu++) {
|
||||||
|
sum[nu] = Zero();
|
||||||
|
in_nu[nu] = PeekIndex<LorentzIndex>(in, nu);
|
||||||
|
out_nu[nu] = a0*in_nu[nu];
|
||||||
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
|
tmp = U[mu] * Cshift(in_nu[nu], mu, +1) * adj(U[mu]);
|
||||||
|
tmp2 = adj(U[mu]) * in_nu[nu] * U[mu];
|
||||||
|
sum[nu] += tmp + Cshift(tmp2, mu, -1) - 2.0 * in_nu;
|
||||||
|
}
|
||||||
|
out_nu[nu] += a1* 1. / (double(4 * Nd)) * sum[nu];
|
||||||
|
sum2[nu] = Zero();
|
||||||
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
|
tmp = U[mu] * Cshift(sum[nu], mu, +1) * adj(U[mu]);
|
||||||
|
tmp2 = adj(U[mu]) * in_nu * U[mu];
|
||||||
|
sum2[nu] += tmp + Cshift(tmp2, mu, -1) - 2.0 * in_nu;
|
||||||
|
}
|
||||||
|
out_nu[nu] += a2* ( 1. / (double(4 * Nd)))^2 * sum[nu];
|
||||||
|
PokeIndex<LorentzIndex>(out, out_nu[nu], nu);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
for (int nu = 0; nu < Nd; nu++) {
|
||||||
|
GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu);
|
||||||
|
GaugeLinkField out_nu(out.Grid());
|
||||||
|
GaugeLinkField sum(out.Grid());
|
||||||
|
GaugeLinkField sum2(out.Grid());
|
||||||
|
out_nu=a0*in_nu;
|
||||||
|
LapStencil.M(in_nu,sum);
|
||||||
|
out_nu += a1* 1. / (double(4 * Nd)) * sum;
|
||||||
|
LapStencil.M(sum,sum2);
|
||||||
|
out_nu += a2* ( 1. / (double(4 * Nd)))^2 * sum2;
|
||||||
|
// out_nu += (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum;
|
||||||
|
PokeIndex<LorentzIndex>(out, out_nu, nu);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void MDeriv(const GaugeField& in, GaugeField& der) {
|
void MDeriv(const GaugeField& in, GaugeField& der) {
|
||||||
// in is anti-hermitian
|
// in is anti-hermitian
|
||||||
|
// std::cout << GridLogDebug <<"MDeriv:Kappa = "<<kappa<<std::endl;
|
||||||
RealD factor = -kappa / (double(4 * Nd));
|
RealD factor = -kappa / (double(4 * Nd));
|
||||||
|
|
||||||
for (int mu = 0; mu < Nd; mu++){
|
for (int mu = 0; mu < Nd; mu++){
|
||||||
@ -140,6 +338,7 @@ public:
|
|||||||
// adjoint in the last multiplication
|
// adjoint in the last multiplication
|
||||||
PokeIndex<LorentzIndex>(der, -2.0 * factor * der_mu, mu);
|
PokeIndex<LorentzIndex>(der, -2.0 * factor * der_mu, mu);
|
||||||
}
|
}
|
||||||
|
std::cout << GridLogDebug <<"MDeriv: Kappa= "<< kappa << " norm2(der) = "<<norm2(der)<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// separating this temporarily
|
// separating this temporarily
|
||||||
@ -159,11 +358,22 @@ public:
|
|||||||
}
|
}
|
||||||
PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
|
PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
|
||||||
}
|
}
|
||||||
|
std::cout << GridLogDebug <<"MDeriv: Kappa= "<< kappa << " norm2(der) = "<<norm2(der)<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Minv(const GaugeField& in, GaugeField& inverted){
|
void Minv(const GaugeField& in, GaugeField& inverted){
|
||||||
HermitianLinearOperator<LaplacianAdjointField<Impl>,GaugeField> HermOp(*this);
|
HermitianLinearOperator<LaplacianAdjointField<Impl>,GaugeField> HermOp(*this);
|
||||||
Solver(HermOp, in, inverted);
|
Solver(HermOp, in, inverted);
|
||||||
|
std::cout << GridLogDebug <<"Minv:norm2(inverted) = "<<norm2(inverted)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MinvDeriv(const GaugeField& in, GaugeField& der) {
|
||||||
|
GaugeField X(in.Grid());
|
||||||
|
Minv(in,X);
|
||||||
|
MDeriv(X,der);
|
||||||
|
der *=-1.0;
|
||||||
|
std::cout << GridLogDebug <<"MinvDeriv:norm2(der) = "<<norm2(der)<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSquareRoot(GaugeField& P){
|
void MSquareRoot(GaugeField& P){
|
||||||
@ -172,6 +382,7 @@ public:
|
|||||||
ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerHalf);
|
ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerHalf);
|
||||||
msCG(HermOp,P,Gp);
|
msCG(HermOp,P,Gp);
|
||||||
P = Gp;
|
P = Gp;
|
||||||
|
std::cout << GridLogDebug <<"MSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MInvSquareRoot(GaugeField& P){
|
void MInvSquareRoot(GaugeField& P){
|
||||||
@ -180,6 +391,7 @@ public:
|
|||||||
ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerInvHalf);
|
ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerInvHalf);
|
||||||
msCG(HermOp,P,Gp);
|
msCG(HermOp,P,Gp);
|
||||||
P = Gp;
|
P = Gp;
|
||||||
|
std::cout << GridLogDebug <<"MInvSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
352
Grid/qcd/utils/CovariantLaplacianRat.h
Normal file
352
Grid/qcd/utils/CovariantLaplacianRat.h
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
/*************************************************************************************
|
||||||
|
|
||||||
|
Grid physics library, www.github.com/paboyle/Grid
|
||||||
|
|
||||||
|
Source file: ./lib/qcd/action/scalar/CovariantLaplacianRat.h
|
||||||
|
|
||||||
|
Copyright (C) 2021
|
||||||
|
|
||||||
|
Author: Chulwoo Jung <chulwoo@bnl.gov>
|
||||||
|
|
||||||
|
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 */
|
||||||
|
#pragma once
|
||||||
|
#undef MIXED_CG
|
||||||
|
//enable/disable push_back
|
||||||
|
#undef USE_CHRONO
|
||||||
|
|
||||||
|
//#include <roctracer/roctx.h>
|
||||||
|
|
||||||
|
NAMESPACE_BEGIN(Grid);
|
||||||
|
|
||||||
|
struct LaplacianRatParams {
|
||||||
|
|
||||||
|
RealD offset;
|
||||||
|
int order;
|
||||||
|
std::vector<RealD> a0;
|
||||||
|
std::vector<RealD> a1;
|
||||||
|
std::vector<RealD> b0;
|
||||||
|
std::vector<RealD> b1;
|
||||||
|
RealD b2; //for debugging
|
||||||
|
int MaxIter;
|
||||||
|
RealD tolerance;
|
||||||
|
int precision;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
LaplacianRatParams(int ord = 1,
|
||||||
|
int maxit = 1000,
|
||||||
|
RealD tol = 1.0e-8,
|
||||||
|
int precision = 64)
|
||||||
|
: offset(1.), order(ord),b2(1.),
|
||||||
|
MaxIter(maxit),
|
||||||
|
tolerance(tol),
|
||||||
|
precision(precision){
|
||||||
|
a0.resize(ord,0.);
|
||||||
|
a1.resize(ord,0.);
|
||||||
|
b0.resize(ord,0.);
|
||||||
|
b1.resize(ord,0.);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Laplacian operator L on adjoint fields
|
||||||
|
//
|
||||||
|
// phi: adjoint field
|
||||||
|
// L: D_mu^dag D_mu
|
||||||
|
//
|
||||||
|
// L phi(x) = Sum_mu [ U_mu(x)phi(x+mu)U_mu(x)^dag +
|
||||||
|
// U_mu(x-mu)^dag phi(x-mu)U_mu(x-mu)
|
||||||
|
// -2phi(x)]
|
||||||
|
//
|
||||||
|
// Operator designed to be encapsulated by
|
||||||
|
// an HermitianLinearOperator<.. , ..>
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class Impl, class ImplF>
|
||||||
|
class LaplacianAdjointRat: public Metric<typename Impl::Field> {
|
||||||
|
OperatorFunction<typename Impl::Field> &Solver;
|
||||||
|
LaplacianRatParams Gparam;
|
||||||
|
LaplacianRatParams Mparam;
|
||||||
|
GridBase *grid;
|
||||||
|
GridBase *grid_f;
|
||||||
|
CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField> LapStencil;
|
||||||
|
public:
|
||||||
|
INHERIT_GIMPL_TYPES(Impl);
|
||||||
|
typedef typename ImplF::Field GaugeFieldF;
|
||||||
|
GaugeField Usav;
|
||||||
|
GaugeFieldF UsavF;
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solnsM;
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solnsMinv;
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solnsMDeriv;
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solnsMinvDeriv;
|
||||||
|
|
||||||
|
LaplacianAdjointRat(GridBase* _grid, GridBase* _grid_f, OperatorFunction<GaugeField>& S, LaplacianRatParams& gpar, LaplacianRatParams& mpar)
|
||||||
|
: grid(_grid),grid_f(_grid_f), LapStencil(grid), U(Nd, _grid), Solver(S), Gparam(gpar), Mparam(mpar),Usav(_grid), UsavF(_grid_f),
|
||||||
|
prev_solnsM(4),prev_solnsMinv(4),prev_solnsMDeriv(4),prev_solnsMinvDeriv(4) {
|
||||||
|
// std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
|
||||||
|
this->triv=0;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
LaplacianAdjointRat(){this->triv=0; printf("triv=%d\n",this->Trivial());}
|
||||||
|
void Mdir(const GaugeField&, GaugeField&, int, int){ assert(0);}
|
||||||
|
void MdirAll(const GaugeField&, std::vector<GaugeField> &){ assert(0);}
|
||||||
|
void Mdiag(const GaugeField&, GaugeField&){ assert(0);}
|
||||||
|
|
||||||
|
void ImportGauge(const GaugeField& _U) {
|
||||||
|
RealD total=0.;
|
||||||
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
|
U[mu] = PeekIndex<LorentzIndex>(_U, mu);
|
||||||
|
total += norm2(U[mu]);
|
||||||
|
}
|
||||||
|
Usav = _U;
|
||||||
|
precisionChange(UsavF,Usav);
|
||||||
|
std::cout <<GridLogDebug << "ImportGauge:norm2(_U) = "<<" "<<total<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MDerivLink(const GaugeLinkField& left, const GaugeLinkField& right,
|
||||||
|
GaugeField& der) {
|
||||||
|
RealD factor = -1. / (double(4 * Nd));
|
||||||
|
|
||||||
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
|
GaugeLinkField der_mu(der.Grid());
|
||||||
|
der_mu = Zero();
|
||||||
|
// for (int nu = 0; nu < Nd; nu++) {
|
||||||
|
// GaugeLinkField left_nu = PeekIndex<LorentzIndex>(left, nu);
|
||||||
|
// GaugeLinkField right_nu = PeekIndex<LorentzIndex>(right, nu);
|
||||||
|
der_mu += U[mu] * Cshift(left, mu, 1) * adj(U[mu]) * right;
|
||||||
|
der_mu += U[mu] * Cshift(right, mu, 1) * adj(U[mu]) * left;
|
||||||
|
// }
|
||||||
|
PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
|
||||||
|
}
|
||||||
|
std::cout << GridLogDebug <<"MDerivLink: norm2(der) = "<<norm2(der)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MDerivInt(LaplacianRatParams &par, const GaugeField& left, const GaugeField& right,
|
||||||
|
GaugeField& der , std::vector< std::vector<GaugeLinkField> >& prev_solns ) {
|
||||||
|
|
||||||
|
// get rid of this please
|
||||||
|
RealD fac = - 1. / (double(4 * Nd)) ;
|
||||||
|
RealD coef=0.5;
|
||||||
|
LapStencil.GaugeImport(Usav);
|
||||||
|
|
||||||
|
|
||||||
|
for (int nu=0;nu<Nd;nu++){
|
||||||
|
GaugeLinkField right_nu = PeekIndex<LorentzIndex>(right, nu);
|
||||||
|
GaugeLinkField left_nu = PeekIndex<LorentzIndex>(left, nu);
|
||||||
|
GaugeLinkField LMinvMom(left.Grid());
|
||||||
|
|
||||||
|
GaugeLinkField GMom(left.Grid());
|
||||||
|
GaugeLinkField LMinvGMom(left.Grid());
|
||||||
|
|
||||||
|
GaugeLinkField AGMom(left.Grid());
|
||||||
|
GaugeLinkField MinvAGMom(left.Grid());
|
||||||
|
GaugeLinkField LMinvAGMom(left.Grid());
|
||||||
|
|
||||||
|
GaugeLinkField AMinvMom(left.Grid());
|
||||||
|
GaugeLinkField LMinvAMom(left.Grid());
|
||||||
|
GaugeLinkField temp(left.Grid());
|
||||||
|
GaugeLinkField temp2(left.Grid());
|
||||||
|
|
||||||
|
std::vector<GaugeLinkField> MinvMom(par.order,left.Grid());
|
||||||
|
|
||||||
|
GaugeLinkField MinvGMom(left.Grid());
|
||||||
|
GaugeLinkField Gtemp(left.Grid());
|
||||||
|
GaugeLinkField Gtemp2(left.Grid());
|
||||||
|
|
||||||
|
|
||||||
|
ConjugateGradient<GaugeLinkField> CG(par.tolerance,10000,false);
|
||||||
|
// ConjugateGradient<GaugeFieldF> CG_f(par.tolerance,10000,false);
|
||||||
|
LaplacianParams LapPar(0.0001, 1.0, 10000, 1e-8, 12, 64);
|
||||||
|
|
||||||
|
ChronoForecast< QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,GaugeLinkField>,GaugeLinkField> , GaugeLinkField> Forecast;
|
||||||
|
|
||||||
|
GMom = par.offset * right_nu;
|
||||||
|
|
||||||
|
for(int i =0;i<par.order;i++){
|
||||||
|
QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField>,GaugeLinkField> QuadOp(LapStencil,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
|
||||||
|
#if USE_CHRONO
|
||||||
|
MinvMom[i] = Forecast(QuadOp, right_nu, prev_solns[nu]);
|
||||||
|
#endif
|
||||||
|
#ifndef MIXED_CG
|
||||||
|
CG(QuadOp,right_nu,MinvMom[i]);
|
||||||
|
#else
|
||||||
|
QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeLinkFieldF> QuadOpF(LaplacianF,par.b0[i],par.b1[i],par.b2);
|
||||||
|
MixedPrecisionConjugateGradient<GaugeField,GaugeFieldF> MixedCG(par.tolerance,10000,10000,grid_f,QuadOpF,QuadOp);
|
||||||
|
MixedCG.InnerTolerance=par.tolerance;
|
||||||
|
MixedCG(right_nu,MinvMom[i]);
|
||||||
|
#endif
|
||||||
|
#if USE_CHRONO
|
||||||
|
prev_solns[nu].push_back(MinvMom[i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GMom += par.a0[i]*MinvMom[i];
|
||||||
|
LapStencil.M(MinvMom[i],Gtemp2);
|
||||||
|
GMom += par.a1[i]*fac*Gtemp2;
|
||||||
|
}
|
||||||
|
for(int i =0;i<par.order;i++){
|
||||||
|
QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField>,GaugeLinkField> QuadOp(LapStencil,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
|
||||||
|
|
||||||
|
MinvGMom = Forecast(QuadOp, GMom, prev_solns[nu]);
|
||||||
|
#ifndef MIXED_CG
|
||||||
|
CG(QuadOp,GMom,MinvGMom);
|
||||||
|
LapStencil.M(MinvGMom, Gtemp2); LMinvGMom=fac*Gtemp2;
|
||||||
|
CG(QuadOp,right_nu,MinvMom[i]);
|
||||||
|
#else
|
||||||
|
QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeLinkFieldF> QuadOpF(LaplacianF,par.b0[i],par.b1[i],par.b2);
|
||||||
|
MixedPrecisionConjugateGradient<GaugeField,GaugeFieldF> MixedCG(par.tolerance,10000,10000,grid_f,QuadOpF,QuadOp);
|
||||||
|
MixedCG.InnerTolerance=par.tolerance;
|
||||||
|
MixedCG(GMom,MinvGMom);
|
||||||
|
Laplacian.M(MinvGMom, LMinvGMom);
|
||||||
|
MixedCG(right_nu,MinvMom[i]);
|
||||||
|
#endif
|
||||||
|
#if USE_CHRONO
|
||||||
|
prev_solns[nu].push_back(MinvGMom);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LapStencil.M(MinvMom[i], Gtemp2); LMinvMom=fac*Gtemp2;
|
||||||
|
AMinvMom = par.a1[i]*LMinvMom;
|
||||||
|
AMinvMom += par.a0[i]*MinvMom[i];
|
||||||
|
|
||||||
|
LapStencil.M(AMinvMom, Gtemp2); LMinvAMom=fac*Gtemp2;
|
||||||
|
LapStencil.M(MinvGMom, Gtemp2); temp=fac*Gtemp2;
|
||||||
|
MinvAGMom = par.a1[i]*temp;
|
||||||
|
MinvAGMom += par.a0[i]*MinvGMom;
|
||||||
|
LapStencil.M(MinvAGMom, Gtemp2); LMinvAGMom=fac*Gtemp2;
|
||||||
|
|
||||||
|
|
||||||
|
GaugeField tempDer(left.Grid());
|
||||||
|
std::cout<<GridLogMessage << "force contraction "<< i <<std::endl;
|
||||||
|
// roctxRangePushA("RMHMC force contraction");
|
||||||
|
MDerivLink(GMom,MinvMom[i],tempDer); der += coef*2*par.a1[i]*tempDer;
|
||||||
|
MDerivLink(left_nu,MinvGMom,tempDer); der += coef*2*par.a1[i]*tempDer;
|
||||||
|
MDerivLink(LMinvAGMom,MinvMom[i],tempDer); der += coef*-2.*par.b2*tempDer;
|
||||||
|
MDerivLink(LMinvAMom,MinvGMom,tempDer); der += coef*-2.*par.b2*tempDer;
|
||||||
|
MDerivLink(MinvAGMom,LMinvMom,tempDer); der += coef*-2.*par.b2*tempDer;
|
||||||
|
MDerivLink(AMinvMom,LMinvGMom,tempDer); der += coef*-2.*par.b2*tempDer;
|
||||||
|
MDerivLink(MinvAGMom,MinvMom[i],tempDer); der += coef*-2.*par.b1[i]*tempDer;
|
||||||
|
MDerivLink(AMinvMom,MinvGMom,tempDer); der += coef*-2.*par.b1[i]*tempDer;
|
||||||
|
std::cout<<GridLogMessage << "coef = force contraction "<< i << "done "<< coef <<std::endl;
|
||||||
|
// roctxRangePop();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit(-42);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MDeriv(const GaugeField& in, GaugeField& der) {
|
||||||
|
MDeriv(in,in, der);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MDeriv(const GaugeField& left, const GaugeField& right,
|
||||||
|
GaugeField& der) {
|
||||||
|
|
||||||
|
der=Zero();
|
||||||
|
MDerivInt(Mparam, left, right, der,prev_solnsMDeriv );
|
||||||
|
std::cout <<GridLogDebug << "MDeriv:norm2(der) = "<<norm2(der)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinvDeriv(const GaugeField& in, GaugeField& der) {
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solns(4);
|
||||||
|
der=Zero();
|
||||||
|
MDerivInt(Gparam, in, in, der,prev_solnsMinvDeriv);
|
||||||
|
std::cout <<GridLogDebug << "MinvDeriv:norm2(der) = "<<norm2(der)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MSquareRootInt(LaplacianRatParams &par, GaugeField& P, std::vector< std::vector<GaugeLinkField> > & prev_solns ){
|
||||||
|
|
||||||
|
RealD fac = -1. / (double(4 * Nd));
|
||||||
|
LapStencil.GaugeImport(Usav);
|
||||||
|
for(int nu=0; nu<Nd;nu++){
|
||||||
|
GaugeLinkField P_nu = PeekIndex<LorentzIndex>(P, nu);
|
||||||
|
GaugeLinkField Gp(P.Grid());
|
||||||
|
Gp = par.offset * P_nu;
|
||||||
|
ConjugateGradient<GaugeLinkField> CG(par.tolerance,10000);
|
||||||
|
// ConjugateGradient<GaugeLinkFieldF> CG_f(1.0e-8,10000);
|
||||||
|
|
||||||
|
ChronoForecast< QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField>,GaugeLinkField> , GaugeLinkField> Forecast;
|
||||||
|
|
||||||
|
GaugeLinkField Gtemp(P.Grid());
|
||||||
|
GaugeLinkField Gtemp2(P.Grid());
|
||||||
|
|
||||||
|
|
||||||
|
for(int i =0;i<par.order;i++){
|
||||||
|
QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField>,GaugeLinkField> QuadOp(LapStencil,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
|
||||||
|
|
||||||
|
Gtemp = Forecast(QuadOp, P_nu, prev_solns[nu]);
|
||||||
|
#ifndef MIXED_CG
|
||||||
|
CG(QuadOp,P_nu,Gtemp);
|
||||||
|
#else
|
||||||
|
QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeFieldF> QuadOpF(LaplacianF,par.b0[i],par.b1[i],par.b2);
|
||||||
|
MixedPrecisionConjugateGradient<GaugeField,GaugeFieldF> MixedCG(par.tolerance,10000,10000,grid_f,QuadOpF,QuadOp);
|
||||||
|
MixedCG.InnerTolerance=par.tolerance;
|
||||||
|
MixedCG(P,Gtemp[i]);
|
||||||
|
#endif
|
||||||
|
#if USE_CHRONO
|
||||||
|
prev_solns[nu].push_back(Gtemp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Gp += par.a0[i]*Gtemp;
|
||||||
|
LapStencil.M(Gtemp,Gtemp2);
|
||||||
|
Gp += par.a1[i]*fac*Gtemp2;
|
||||||
|
}
|
||||||
|
PokeIndex<LorentzIndex>(P, Gp, nu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MSquareRoot(GaugeField& P){
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solns(4);
|
||||||
|
MSquareRootInt(Mparam,P,prev_solns);
|
||||||
|
std::cout <<GridLogDebug << "MSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MInvSquareRoot(GaugeField& P){
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solns(4);
|
||||||
|
MSquareRootInt(Gparam,P,prev_solns);
|
||||||
|
std::cout <<GridLogDebug << "MInvSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M(const GaugeField& in, GaugeField& out) {
|
||||||
|
out = in;
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solns(4);
|
||||||
|
MSquareRootInt(Mparam,out,prev_solns);
|
||||||
|
MSquareRootInt(Mparam,out,prev_solns);
|
||||||
|
std::cout <<GridLogDebug << "M:norm2(out) = "<<norm2(out)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Minv(const GaugeField& in, GaugeField& inverted){
|
||||||
|
inverted = in;
|
||||||
|
std::vector< std::vector<GaugeLinkField> > prev_solns(4);
|
||||||
|
MSquareRootInt(Gparam,inverted,prev_solns);
|
||||||
|
MSquareRootInt(Gparam,inverted,prev_solns);
|
||||||
|
std::cout <<GridLogDebug << "Minv:norm2(inverted) = "<<norm2(inverted)<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<GaugeLinkField> U;
|
||||||
|
};
|
||||||
|
#undef MIXED_CG
|
||||||
|
|
||||||
|
NAMESPACE_END(Grid);
|
@ -7,6 +7,7 @@ Source file: ./lib/qcd/hmc/integrators/Integrator.h
|
|||||||
Copyright (C) 2015
|
Copyright (C) 2015
|
||||||
|
|
||||||
Author: Guido Cossu <guido.cossu@ed.ac.uk>
|
Author: Guido Cossu <guido.cossu@ed.ac.uk>
|
||||||
|
Author: Chulwoo Jung <chulwoo@bnl.gov>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -33,7 +34,12 @@ NAMESPACE_BEGIN(Grid);
|
|||||||
|
|
||||||
template <typename Field>
|
template <typename Field>
|
||||||
class Metric{
|
class Metric{
|
||||||
|
protected:
|
||||||
|
int triv;
|
||||||
public:
|
public:
|
||||||
|
Metric(){this->triv=1;}
|
||||||
|
int Trivial(){ return triv;}
|
||||||
|
//printf("Metric::Trivial=%d\n",triv); ;
|
||||||
virtual void ImportGauge(const Field&) = 0;
|
virtual void ImportGauge(const Field&) = 0;
|
||||||
virtual void M(const Field&, Field&) = 0;
|
virtual void M(const Field&, Field&) = 0;
|
||||||
virtual void Minv(const Field&, Field&) = 0;
|
virtual void Minv(const Field&, Field&) = 0;
|
||||||
@ -41,6 +47,8 @@ public:
|
|||||||
virtual void MInvSquareRoot(Field&) = 0;
|
virtual void MInvSquareRoot(Field&) = 0;
|
||||||
virtual void MDeriv(const Field&, Field&) = 0;
|
virtual void MDeriv(const Field&, Field&) = 0;
|
||||||
virtual void MDeriv(const Field&, const Field&, Field&) = 0;
|
virtual void MDeriv(const Field&, const Field&, Field&) = 0;
|
||||||
|
virtual void MinvDeriv(const Field&, Field&) = 0;
|
||||||
|
// virtual void MinvDeriv(const Field&, const Field&, Field&) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -48,23 +56,36 @@ public:
|
|||||||
template <typename Field>
|
template <typename Field>
|
||||||
class TrivialMetric : public Metric<Field>{
|
class TrivialMetric : public Metric<Field>{
|
||||||
public:
|
public:
|
||||||
|
// TrivialMetric(){this->triv=1;printf("TrivialMetric::triv=%d\n",this->Trivial());}
|
||||||
virtual void ImportGauge(const Field&){};
|
virtual void ImportGauge(const Field&){};
|
||||||
virtual void M(const Field& in, Field& out){
|
virtual void M(const Field& in, Field& out){
|
||||||
|
// printf("M:norm=%0.15e\n",norm2(in));
|
||||||
|
std::cout << GridLogIntegrator << " M:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
|
||||||
out = in;
|
out = in;
|
||||||
}
|
}
|
||||||
virtual void Minv(const Field& in, Field& out){
|
virtual void Minv(const Field& in, Field& out){
|
||||||
|
std::cout << GridLogIntegrator << " Minv:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
|
||||||
out = in;
|
out = in;
|
||||||
}
|
}
|
||||||
virtual void MSquareRoot(Field& P){
|
virtual void MSquareRoot(Field& P){
|
||||||
|
std::cout << GridLogIntegrator << " MSquareRoot:norm(P)= " << std::sqrt(norm2(P)) << std::endl;
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
virtual void MInvSquareRoot(Field& P){
|
virtual void MInvSquareRoot(Field& P){
|
||||||
|
std::cout << GridLogIntegrator << " MInvSquareRoot:norm(P)= " << std::sqrt(norm2(P)) << std::endl;
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
virtual void MDeriv(const Field& in, Field& out){
|
virtual void MDeriv(const Field& in, Field& out){
|
||||||
|
std::cout << GridLogIntegrator << " MDeriv:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
|
||||||
|
out = Zero();
|
||||||
|
}
|
||||||
|
virtual void MinvDeriv(const Field& in, Field& out){
|
||||||
|
std::cout << GridLogIntegrator << " MinvDeriv:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
|
||||||
out = Zero();
|
out = Zero();
|
||||||
}
|
}
|
||||||
virtual void MDeriv(const Field& left, const Field& right, Field& out){
|
virtual void MDeriv(const Field& left, const Field& right, Field& out){
|
||||||
|
std::cout << GridLogIntegrator << " MDeriv:norm(left)= " << std::sqrt(norm2(left)) << std::endl;
|
||||||
|
std::cout << GridLogIntegrator << " MDeriv:norm(right)= " << std::sqrt(norm2(right)) << std::endl;
|
||||||
out = Zero();
|
out = Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,14 +122,15 @@ public:
|
|||||||
// Generate gaussian momenta
|
// Generate gaussian momenta
|
||||||
Implementation::generate_momenta(Mom, sRNG, pRNG);
|
Implementation::generate_momenta(Mom, sRNG, pRNG);
|
||||||
// Modify the distribution with the metric
|
// Modify the distribution with the metric
|
||||||
|
// if(M.Trivial()) return;
|
||||||
M.MSquareRoot(Mom);
|
M.MSquareRoot(Mom);
|
||||||
|
|
||||||
if (1) {
|
if (1) {
|
||||||
// Auxiliary momenta
|
// Auxiliary momenta
|
||||||
// do nothing if trivial, so hide in the metric
|
// do nothing if trivial, so hide in the metric
|
||||||
MomentaField AuxMomTemp(Mom.Grid());
|
MomentaField AuxMomTemp(Mom.Grid());
|
||||||
Implementation::generate_momenta(AuxMom, sRNG, pRNG);
|
Implementation::generate_momenta(AuxMom, sRNG,pRNG);
|
||||||
Implementation::generate_momenta(AuxField, sRNG, pRNG);
|
Implementation::generate_momenta(AuxField, sRNG,pRNG);
|
||||||
// Modify the distribution with the metric
|
// Modify the distribution with the metric
|
||||||
// Aux^dag M Aux
|
// Aux^dag M Aux
|
||||||
M.MInvSquareRoot(AuxMom); // AuxMom = M^{-1/2} AuxMomTemp
|
M.MInvSquareRoot(AuxMom); // AuxMom = M^{-1/2} AuxMomTemp
|
||||||
@ -117,11 +139,12 @@ public:
|
|||||||
|
|
||||||
// Correct
|
// Correct
|
||||||
RealD MomentaAction(){
|
RealD MomentaAction(){
|
||||||
|
static RealD Saux=0.,Smom=0.;
|
||||||
MomentaField inv(Mom.Grid());
|
MomentaField inv(Mom.Grid());
|
||||||
inv = Zero();
|
inv = Zero();
|
||||||
M.Minv(Mom, inv);
|
M.Minv(Mom, inv);
|
||||||
LatticeComplex Hloc(Mom.Grid());
|
LatticeComplex Hloc(Mom.Grid()); Hloc = Zero();
|
||||||
Hloc = Zero();
|
LatticeComplex Hloc2(Mom.Grid()); Hloc2 = Zero();
|
||||||
for (int mu = 0; mu < Nd; mu++) {
|
for (int mu = 0; mu < Nd; mu++) {
|
||||||
// This is not very general
|
// This is not very general
|
||||||
// hide in the metric
|
// hide in the metric
|
||||||
@ -129,8 +152,15 @@ public:
|
|||||||
auto inv_mu = PeekIndex<LorentzIndex>(inv, mu);
|
auto inv_mu = PeekIndex<LorentzIndex>(inv, mu);
|
||||||
Hloc += trace(Mom_mu * inv_mu);
|
Hloc += trace(Mom_mu * inv_mu);
|
||||||
}
|
}
|
||||||
|
auto Htmp1 = TensorRemove(sum(Hloc));
|
||||||
|
std::cout << GridLogMessage << "S:dSmom = " << Htmp1.real()-Smom << "\n";
|
||||||
|
Smom=Htmp1.real()/HMC_MOMENTUM_DENOMINATOR;
|
||||||
|
|
||||||
|
|
||||||
if (1) {
|
|
||||||
|
|
||||||
|
// if(!M.Trivial())
|
||||||
|
{
|
||||||
// Auxiliary Fields
|
// Auxiliary Fields
|
||||||
// hide in the metric
|
// hide in the metric
|
||||||
M.M(AuxMom, inv);
|
M.M(AuxMom, inv);
|
||||||
@ -140,13 +170,18 @@ public:
|
|||||||
auto inv_mu = PeekIndex<LorentzIndex>(inv, mu);
|
auto inv_mu = PeekIndex<LorentzIndex>(inv, mu);
|
||||||
auto am_mu = PeekIndex<LorentzIndex>(AuxMom, mu);
|
auto am_mu = PeekIndex<LorentzIndex>(AuxMom, mu);
|
||||||
auto af_mu = PeekIndex<LorentzIndex>(AuxField, mu);
|
auto af_mu = PeekIndex<LorentzIndex>(AuxField, mu);
|
||||||
Hloc += trace(am_mu * inv_mu);// p M p
|
Hloc += trace(am_mu * inv_mu);
|
||||||
Hloc += trace(af_mu * af_mu);
|
Hloc2 += trace(af_mu * af_mu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto Htmp2 = TensorRemove(sum(Hloc))-Htmp1;
|
||||||
|
std::cout << GridLogMessage << "S:dSaux = " << Htmp2.real()-Saux << "\n";
|
||||||
|
Saux=Htmp2.real();
|
||||||
|
|
||||||
auto Hsum = TensorRemove(sum(Hloc));
|
auto Hsum = TensorRemove(sum(Hloc))/HMC_MOMENTUM_DENOMINATOR;
|
||||||
return Hsum.real();
|
auto Hsum2 = TensorRemove(sum(Hloc2));
|
||||||
|
std::cout << GridLogIntegrator << "MomentaAction: " << Hsum.real()+Hsum2.real() << std::endl;
|
||||||
|
return Hsum.real()+Hsum2.real();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Correct
|
// Correct
|
||||||
@ -157,15 +192,17 @@ public:
|
|||||||
MomentaField MDer(in.Grid());
|
MomentaField MDer(in.Grid());
|
||||||
MomentaField X(in.Grid());
|
MomentaField X(in.Grid());
|
||||||
X = Zero();
|
X = Zero();
|
||||||
M.Minv(in, X); // X = G in
|
M.MinvDeriv(in, MDer); // MDer = U * dS/dU
|
||||||
M.MDeriv(X, MDer); // MDer = U * dS/dU
|
der = -1.0* Implementation::projectForce(MDer); // Ta if gauge fields
|
||||||
der = Implementation::projectForce(MDer); // Ta if gauge fields
|
// std::cout << GridLogIntegrator << " DerivativeU: norm(in)= " << std::sqrt(norm2(in)) << std::endl;
|
||||||
|
// std::cout << GridLogIntegrator << " DerivativeU: norm(der)= " << std::sqrt(norm2(der)) << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuxiliaryFieldsDerivative(MomentaField& der){
|
void AuxiliaryFieldsDerivative(MomentaField& der){
|
||||||
der = Zero();
|
der = Zero();
|
||||||
if (1){
|
// if(!M.Trivial())
|
||||||
|
{
|
||||||
// Auxiliary fields
|
// Auxiliary fields
|
||||||
MomentaField der_temp(der.Grid());
|
MomentaField der_temp(der.Grid());
|
||||||
MomentaField X(der.Grid());
|
MomentaField X(der.Grid());
|
||||||
@ -173,6 +210,7 @@ public:
|
|||||||
//M.M(AuxMom, X); // X = M Aux
|
//M.M(AuxMom, X); // X = M Aux
|
||||||
// Two derivative terms
|
// Two derivative terms
|
||||||
// the Mderiv need separation of left and right terms
|
// the Mderiv need separation of left and right terms
|
||||||
|
std::cout << GridLogIntegrator << " AuxiliaryFieldsDerivative:norm(AuxMom)= " << std::sqrt(norm2(AuxMom)) << std::endl;
|
||||||
M.MDeriv(AuxMom, der);
|
M.MDeriv(AuxMom, der);
|
||||||
|
|
||||||
|
|
||||||
@ -180,6 +218,7 @@ public:
|
|||||||
//M.MDeriv(X, AuxMom, der_temp); der += der_temp;
|
//M.MDeriv(X, AuxMom, der_temp); der += der_temp;
|
||||||
|
|
||||||
der = -1.0*Implementation::projectForce(der);
|
der = -1.0*Implementation::projectForce(der);
|
||||||
|
std::cout << GridLogIntegrator << " AuxiliaryFieldsDerivative:norm(der)= " << std::sqrt(norm2(der)) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,22 +228,27 @@ public:
|
|||||||
// is the projection necessary here?
|
// is the projection necessary here?
|
||||||
// no for fields in the algebra
|
// no for fields in the algebra
|
||||||
der = Implementation::projectForce(der);
|
der = Implementation::projectForce(der);
|
||||||
|
std::cout << GridLogIntegrator << " DerivativeP:norm(der)= " << std::sqrt(norm2(der)) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_auxiliary_momenta(RealD ep){
|
void update_auxiliary_momenta(RealD ep){
|
||||||
if(1){
|
// if(!M.Trivial())
|
||||||
AuxMom -= ep * AuxField;
|
{
|
||||||
|
AuxMom -= ep * AuxField * HMC_MOMENTUM_DENOMINATOR;
|
||||||
|
std::cout << GridLogIntegrator << "AuxMom update_auxiliary_fields: " << std::sqrt(norm2(AuxMom)) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_auxiliary_fields(RealD ep){
|
void update_auxiliary_fields(RealD ep){
|
||||||
if (1) {
|
// if(!M.Trivial())
|
||||||
|
{
|
||||||
MomentaField tmp(AuxMom.Grid());
|
MomentaField tmp(AuxMom.Grid());
|
||||||
MomentaField tmp2(AuxMom.Grid());
|
MomentaField tmp2(AuxMom.Grid());
|
||||||
M.M(AuxMom, tmp);
|
M.M(AuxMom, tmp);
|
||||||
// M.M(tmp, tmp2);
|
// M.M(tmp, tmp2);
|
||||||
AuxField += ep * tmp; // M^2 AuxMom
|
AuxField += ep * tmp; // M^2 AuxMom
|
||||||
// factor of 2?
|
// factor of 2?
|
||||||
|
std::cout << GridLogIntegrator << "AuxField update_auxiliary_fields: " << std::sqrt(norm2(AuxField)) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
572
HMC/Mobius2p1p1fEOFA_4Gev.cc
Normal file
572
HMC/Mobius2p1p1fEOFA_4Gev.cc
Normal file
@ -0,0 +1,572 @@
|
|||||||
|
/*************************************************************************************
|
||||||
|
|
||||||
|
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
|
||||||
|
Author: Chulwoo Jung <chulwoo@bnl.gov>
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
#ifdef GRID_DEFAULT_PRECISION_DOUBLE
|
||||||
|
#define MIXED_PRECISION
|
||||||
|
#endif
|
||||||
|
// second level EOFA
|
||||||
|
#undef EOFA_H
|
||||||
|
#define USE_OBC
|
||||||
|
#undef DO_IMPLICIT
|
||||||
|
|
||||||
|
NAMESPACE_BEGIN(Grid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
using OperatorFunction<FieldD>::operator();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NAMESPACE_END(Grid);
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
using namespace Grid;
|
||||||
|
|
||||||
|
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 MobiusFermionD FermionAction;
|
||||||
|
typedef MobiusFermionF FermionActionF;
|
||||||
|
typedef MobiusEOFAFermionD FermionEOFAAction;
|
||||||
|
typedef MobiusEOFAFermionF FermionEOFAActionF;
|
||||||
|
typedef typename FermionAction::FermionField FermionField;
|
||||||
|
typedef typename FermionActionF::FermionField FermionFieldF;
|
||||||
|
|
||||||
|
typedef Grid::XmlReader Serialiser;
|
||||||
|
|
||||||
|
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
|
|
||||||
|
HMCparameters HMCparams;
|
||||||
|
#if 1
|
||||||
|
{
|
||||||
|
XmlReader HMCrd("HMCparameters.xml");
|
||||||
|
read(HMCrd,"HMCparameters",HMCparams);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
// HMCparameters HMCparams;
|
||||||
|
// "[HotStart, ColdStart, TepidStart, CheckpointStart]\n";
|
||||||
|
// HMCparams.StartingType =std::string("ColdStart");
|
||||||
|
HMCparams.StartingType =std::string("CheckpointStart");
|
||||||
|
HMCparams.StartTrajectory =7;
|
||||||
|
HMCparams.SW =4;
|
||||||
|
HMCparams.Trajectories =1000;
|
||||||
|
HMCparams.NoMetropolisUntil=0;
|
||||||
|
HMCparams.MD.name =std::string("Force Gradient");
|
||||||
|
HMCparams.MD.MDsteps = 10;
|
||||||
|
HMCparams.MD.trajL = 1.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// typedef GenericHMCRunner<LeapFrog> HMCWrapper;
|
||||||
|
// typedef GenericHMCRunner<ImplicitLeapFrog> HMCWrapper;
|
||||||
|
#ifdef DO_IMPLICIT
|
||||||
|
typedef GenericHMCRunner<ImplicitMinimumNorm2> HMCWrapper;
|
||||||
|
HMCparams.MD.name =std::string("ImplicitMinimumNorm2");
|
||||||
|
#else
|
||||||
|
typedef GenericHMCRunner<ForceGradient> HMCWrapper;
|
||||||
|
// typedef GenericHMCRunner<MinimumNorm2> HMCWrapper;
|
||||||
|
HMCparams.MD.name =std::string("ForceGradient");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::cout << GridLogMessage<< HMCparams <<std::endl;
|
||||||
|
HMCWrapper TheHMC(HMCparams);
|
||||||
|
TheHMC.ReadCommandLine(argc, argv);
|
||||||
|
{
|
||||||
|
XmlWriter HMCwr("HMCparameters.xml.out");
|
||||||
|
write(HMCwr,"HMCparameters",TheHMC.Parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grid from the command line arguments --grid and --mpi
|
||||||
|
TheHMC.Resources.AddFourDimGrid("gauge"); // use default simd lanes decomposition
|
||||||
|
|
||||||
|
CheckpointerParameters CPparams;
|
||||||
|
CPparams.config_prefix = "ckpoint_lat";
|
||||||
|
CPparams.rng_prefix = "ckpoint_rng";
|
||||||
|
CPparams.saveInterval = 1;
|
||||||
|
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 = 12;
|
||||||
|
Real beta = 5.983;
|
||||||
|
std::cout << GridLogMessage << " beta "<< beta << std::endl;
|
||||||
|
Real light_mass = 0.00049;
|
||||||
|
Real strange_mass = 0.0158;
|
||||||
|
Real charm_mass = 0.191;
|
||||||
|
Real pv_mass = 1.0;
|
||||||
|
RealD M5 = 1.4;
|
||||||
|
RealD b = 2.0;
|
||||||
|
RealD c = 1.0;
|
||||||
|
|
||||||
|
// Copied from paper
|
||||||
|
// std::vector<Real> hasenbusch({ 0.045 }); // Paper values from F1 incorrect run
|
||||||
|
std::vector<Real> hasenbusch({ 0.0038, 0.0145, 0.045, 0.108 , 0.25, 0.51 }); // Paper values from F1 incorrect run
|
||||||
|
std::vector<Real> hasenbusch2({ 0.4 }); // Paper values from F1 incorrect run
|
||||||
|
|
||||||
|
// RealD eofa_mass=0.05 ;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//Bad choices with large dH. Equalising force L2 norm was not wise.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//std::vector<Real> hasenbusch({ 0.03, 0.2, 0.3, 0.5, 0.8 });
|
||||||
|
|
||||||
|
auto GridPtr = TheHMC.Resources.GetCartesian();
|
||||||
|
auto GridRBPtr = TheHMC.Resources.GetRBCartesian();
|
||||||
|
auto FGrid = SpaceTimeGrid::makeFiveDimGrid(Ls,GridPtr);
|
||||||
|
auto FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,GridPtr);
|
||||||
|
|
||||||
|
Coordinate latt = GridDefaultLatt();
|
||||||
|
Coordinate mpi = GridDefaultMpi();
|
||||||
|
Coordinate simdF = GridDefaultSimd(Nd,vComplexF::Nsimd());
|
||||||
|
Coordinate 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);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef USE_OBC
|
||||||
|
// IwasakiGaugeActionR GaugeAction(beta);
|
||||||
|
WilsonGaugeActionR GaugeAction(beta);
|
||||||
|
#else
|
||||||
|
std::vector<Complex> boundaryG = {1,1,1,0};
|
||||||
|
WilsonGaugeActionR::ImplParams ParamsG(boundaryG);
|
||||||
|
WilsonGaugeActionR GaugeAction(beta,ParamsG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// temporarily need a gauge field
|
||||||
|
LatticeGaugeField U(GridPtr);
|
||||||
|
LatticeGaugeFieldF UF(GridPtrF);
|
||||||
|
|
||||||
|
// These lines are unecessary if BC are all periodic
|
||||||
|
#ifndef USE_OBC
|
||||||
|
std::vector<Complex> boundary = {1,1,1,-1};
|
||||||
|
#else
|
||||||
|
std::vector<Complex> boundary = {1,1,1,0};
|
||||||
|
#endif
|
||||||
|
FermionAction::ImplParams Params(boundary);
|
||||||
|
FermionActionF::ImplParams ParamsF(boundary);
|
||||||
|
|
||||||
|
double ActionStoppingCondition = 1e-8;
|
||||||
|
double DerivativeStoppingCondition = 1e-6;
|
||||||
|
double MaxCGIterations = 30000;
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
// Collect actions
|
||||||
|
////////////////////////////////////
|
||||||
|
ActionLevel<HMCWrapper::Field> Level1(1);
|
||||||
|
ActionLevel<HMCWrapper::Field> Level2(HMCparams.SW);
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
// 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.99; // How do I know this on F1?
|
||||||
|
OFRp.hi = 20;
|
||||||
|
OFRp.MaxIter = 100000;
|
||||||
|
OFRp.tolerance= 1.0e-12;
|
||||||
|
OFRp.degree = 12;
|
||||||
|
OFRp.precision= 50;
|
||||||
|
|
||||||
|
|
||||||
|
MobiusEOFAFermionD Strange_Op_L (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , strange_mass, strange_mass, charm_mass, 0.0, -1, M5, b, c);
|
||||||
|
MobiusEOFAFermionF Strange_Op_LF(UF, *FGridF, *FrbGridF, *GridPtrF, *GridRBPtrF, strange_mass, strange_mass, charm_mass, 0.0, -1, M5, b, c);
|
||||||
|
MobiusEOFAFermionD Strange_Op_R (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , charm_mass, strange_mass, charm_mass, -1.0, 1, M5, b, c);
|
||||||
|
MobiusEOFAFermionF Strange_Op_RF(UF, *FGridF, *FrbGridF, *GridPtrF, *GridRBPtrF, charm_mass, strange_mass, charm_mass, -1.0, 1, M5, b, c);
|
||||||
|
|
||||||
|
#ifdef EOFA_H
|
||||||
|
MobiusEOFAFermionD Strange2_Op_L (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , eofa_mass, eofa_mass, charm_mass , 0.0, -1, M5, b, c);
|
||||||
|
MobiusEOFAFermionF Strange2_Op_LF(UF, *FGridF, *FrbGridF, *GridPtrF, *GridRBPtrF, eofa_mass, eofa_mass, charm_mass , 0.0, -1, M5, b, c);
|
||||||
|
MobiusEOFAFermionD Strange2_Op_R (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , charm_mass , eofa_mass, charm_mass , -1.0, 1, M5, b, c);
|
||||||
|
MobiusEOFAFermionF Strange2_Op_RF(UF, *FGridF, *FrbGridF, *GridPtrF, *GridRBPtrF, charm_mass , eofa_mass, charm_mass , -1.0, 1, M5, b, c);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ConjugateGradient<FermionField> ActionCG(ActionStoppingCondition,MaxCGIterations);
|
||||||
|
ConjugateGradient<FermionField> DerivativeCG(DerivativeStoppingCondition,MaxCGIterations);
|
||||||
|
#ifdef MIXED_PRECISION
|
||||||
|
const int MX_inner = 5000;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
#ifdef EOFA_H
|
||||||
|
// Mixed precision EOFA
|
||||||
|
LinearOperatorEOFAD Strange2_LinOp_L (Strange2_Op_L);
|
||||||
|
LinearOperatorEOFAD Strange2_LinOp_R (Strange2_Op_R);
|
||||||
|
LinearOperatorEOFAF Strange2_LinOp_LF(Strange2_Op_LF);
|
||||||
|
LinearOperatorEOFAF Strange2_LinOp_RF(Strange2_Op_RF);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MxPCG_EOFA ActionCGL(ActionStoppingCondition,
|
||||||
|
MX_inner,
|
||||||
|
MaxCGIterations,
|
||||||
|
GridPtrF,
|
||||||
|
FrbGridF,
|
||||||
|
Strange_Op_LF,Strange_Op_L,
|
||||||
|
Strange_LinOp_LF,Strange_LinOp_L);
|
||||||
|
|
||||||
|
#ifdef EOFA_H
|
||||||
|
MxPCG_EOFA ActionCGL2(ActionStoppingCondition,
|
||||||
|
MX_inner,
|
||||||
|
MaxCGIterations,
|
||||||
|
GridPtrF,
|
||||||
|
FrbGridF,
|
||||||
|
Strange2_Op_LF,Strange2_Op_L,
|
||||||
|
Strange2_LinOp_LF,Strange2_LinOp_L);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MxPCG_EOFA DerivativeCGL(DerivativeStoppingCondition,
|
||||||
|
MX_inner,
|
||||||
|
MaxCGIterations,
|
||||||
|
GridPtrF,
|
||||||
|
FrbGridF,
|
||||||
|
Strange_Op_LF,Strange_Op_L,
|
||||||
|
Strange_LinOp_LF,Strange_LinOp_L);
|
||||||
|
|
||||||
|
#ifdef EOFA_H
|
||||||
|
MxPCG_EOFA DerivativeCGL2(DerivativeStoppingCondition,
|
||||||
|
MX_inner,
|
||||||
|
MaxCGIterations,
|
||||||
|
GridPtrF,
|
||||||
|
FrbGridF,
|
||||||
|
Strange2_Op_LF,Strange2_Op_L,
|
||||||
|
Strange2_LinOp_LF,Strange2_LinOp_L);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MxPCG_EOFA ActionCGR(ActionStoppingCondition,
|
||||||
|
MX_inner,
|
||||||
|
MaxCGIterations,
|
||||||
|
GridPtrF,
|
||||||
|
FrbGridF,
|
||||||
|
Strange_Op_RF,Strange_Op_R,
|
||||||
|
Strange_LinOp_RF,Strange_LinOp_R);
|
||||||
|
|
||||||
|
#ifdef EOFA_H
|
||||||
|
MxPCG_EOFA ActionCGR2(ActionStoppingCondition,
|
||||||
|
MX_inner,
|
||||||
|
MaxCGIterations,
|
||||||
|
GridPtrF,
|
||||||
|
FrbGridF,
|
||||||
|
Strange2_Op_RF,Strange2_Op_R,
|
||||||
|
Strange2_LinOp_RF,Strange2_LinOp_R);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MxPCG_EOFA DerivativeCGR(DerivativeStoppingCondition,
|
||||||
|
MX_inner,
|
||||||
|
MaxCGIterations,
|
||||||
|
GridPtrF,
|
||||||
|
FrbGridF,
|
||||||
|
Strange_Op_RF,Strange_Op_R,
|
||||||
|
Strange_LinOp_RF,Strange_LinOp_R);
|
||||||
|
|
||||||
|
#ifdef EOFA_H
|
||||||
|
MxPCG_EOFA DerivativeCGR2(DerivativeStoppingCondition,
|
||||||
|
MX_inner,
|
||||||
|
MaxCGIterations,
|
||||||
|
GridPtrF,
|
||||||
|
FrbGridF,
|
||||||
|
Strange2_Op_RF,Strange2_Op_R,
|
||||||
|
Strange2_LinOp_RF,Strange2_LinOp_R);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy>
|
||||||
|
EOFA(Strange_Op_L, Strange_Op_R,
|
||||||
|
ActionCG,
|
||||||
|
ActionCGL, ActionCGR,
|
||||||
|
DerivativeCGL, DerivativeCGR,
|
||||||
|
OFRp, true);
|
||||||
|
|
||||||
|
#ifdef EOFA_H
|
||||||
|
ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy>
|
||||||
|
EOFA2(Strange2_Op_L, Strange2_Op_R,
|
||||||
|
ActionCG,
|
||||||
|
ActionCGL2, ActionCGR2,
|
||||||
|
DerivativeCGL2, DerivativeCGR2,
|
||||||
|
OFRp, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Level1.push_back(&EOFA);
|
||||||
|
#ifdef EOFA_H
|
||||||
|
Level1.push_back(&EOFA2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy>
|
||||||
|
EOFA(Strange_Op_L, Strange_Op_R,
|
||||||
|
ActionCG,
|
||||||
|
ActionCG, ActionCG,
|
||||||
|
ActionCG, ActionCG,
|
||||||
|
// DerivativeCG, DerivativeCG,
|
||||||
|
OFRp, true);
|
||||||
|
Level1.push_back(&EOFA);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
int n_hasenbusch2 = hasenbusch2.size();
|
||||||
|
light_den.push_back(charm_mass);
|
||||||
|
for(int h=0;h<n_hasenbusch2;h++){
|
||||||
|
light_den.push_back(hasenbusch2[h]);
|
||||||
|
light_num.push_back(hasenbusch2[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<light_den.size();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
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
double DerivativeStoppingConditionLoose = 1e-10;
|
||||||
|
|
||||||
|
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]));
|
||||||
|
|
||||||
|
double conv = DerivativeStoppingCondition;
|
||||||
|
if (h<3) conv= DerivativeStoppingConditionLoose; // Relax on first two hasenbusch factors
|
||||||
|
MPCG.push_back(new MxPCG(conv,
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user