mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-04 05:54:32 +00:00 
			
		
		
		
	Compare commits
	
		
			11 Commits
		
	
	
		
			c4b9f71357
			...
			rmhmc_merg
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					cfa0576ffd | ||
| 
						 | 
					fe98e9f555 | ||
| 
						 | 
					948d16fb06 | ||
| 
						 | 
					58fbcaa399 | ||
| 
						 | 
					9ad6836b0f | ||
| 
						 | 
					026eb8a695 | ||
| 
						 | 
					076580c232 | ||
| 
						 | 
					7af6022a2a | ||
| 
						 | 
					982a60536c | ||
| 
						 | 
					dc36d272ce | ||
| 
						 | 
					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
 | 
			
		||||
// 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.
 | 
			
		||||
// 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).
 | 
			
		||||
template<class Matrix, class Field>
 | 
			
		||||
// Changing to operator
 | 
			
		||||
template<class LinearOperatorBase, class Field>
 | 
			
		||||
class Forecast
 | 
			
		||||
{
 | 
			
		||||
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),
 | 
			
		||||
@@ -54,13 +55,13 @@ public:
 | 
			
		||||
  Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& prev_solns)
 | 
			
		||||
  {
 | 
			
		||||
    int degree = prev_solns.size();
 | 
			
		||||
    std::cout << GridLogMessage << "ChronoForecast: degree= " << degree << std::endl;
 | 
			
		||||
    Field chi(phi); // forecasted solution
 | 
			
		||||
 | 
			
		||||
    // Trivial cases
 | 
			
		||||
    if(degree == 0){ chi = Zero(); return chi; }
 | 
			
		||||
    else if(degree == 1){ return prev_solns[0]; }
 | 
			
		||||
 | 
			
		||||
    //    RealD dot;
 | 
			
		||||
    ComplexD xp;
 | 
			
		||||
    Field r(phi); // residual
 | 
			
		||||
    Field Mv(phi);
 | 
			
		||||
@@ -83,8 +84,9 @@ public:
 | 
			
		||||
    // Perform sparse matrix multiplication and construct rhs
 | 
			
		||||
    for(int i=0; i<degree; i++){
 | 
			
		||||
      b[i] = innerProduct(v[i],phi);
 | 
			
		||||
      Mat.M(v[i],Mv);
 | 
			
		||||
      Mat.Mdag(Mv,MdagMv[i]);
 | 
			
		||||
//      Mat.M(v[i],Mv);
 | 
			
		||||
//      Mat.Mdag(Mv,MdagMv[i]);
 | 
			
		||||
      Mat.HermOp(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>
 | 
			
		||||
NAMESPACE_CHECK(Metric);
 | 
			
		||||
#include <Grid/qcd/utils/CovariantLaplacian.h>
 | 
			
		||||
#include <Grid/qcd/utils/CovariantLaplacianRat.h>
 | 
			
		||||
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 {
 | 
			
		||||
  Coordinate dirichlet; // Blocksize of dirichlet BCs
 | 
			
		||||
  int  partialDirichlet;
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ directory
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
#define CPS_MD_TIME
 | 
			
		||||
#undef CPS_MD_TIME
 | 
			
		||||
 | 
			
		||||
#ifdef CPS_MD_TIME
 | 
			
		||||
#define HMC_MOMENTUM_DENOMINATOR (2.0)
 | 
			
		||||
 
 | 
			
		||||
@@ -42,9 +42,13 @@ template <class Gimpl>
 | 
			
		||||
class WilsonGaugeAction : public Action<typename Gimpl::GaugeField> {
 | 
			
		||||
public:  
 | 
			
		||||
  INHERIT_GIMPL_TYPES(Gimpl);
 | 
			
		||||
  typedef GaugeImplParams ImplParams;
 | 
			
		||||
  ImplParams Params;
 | 
			
		||||
 | 
			
		||||
  /////////////////////////// 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";}
 | 
			
		||||
 | 
			
		||||
@@ -56,14 +60,53 @@ public:
 | 
			
		||||
 | 
			
		||||
  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<< GridLogIterative << "[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) {
 | 
			
		||||
    RealD plaq = WilsonLoops<Gimpl>::avgPlaquette(U);
 | 
			
		||||
    RealD vol = U.Grid()->gSites();
 | 
			
		||||
    GaugeField Ub(U.Grid());
 | 
			
		||||
    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;
 | 
			
		||||
    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;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  virtual void deriv(const GaugeField &U, GaugeField &dSdU) {
 | 
			
		||||
    GaugeField Ub(U.Grid());
 | 
			
		||||
    this->boundary(U,Ub);
 | 
			
		||||
    // not optimal implementation FIXME
 | 
			
		||||
    // extend Ta to include Lorentz indexes
 | 
			
		||||
 | 
			
		||||
@@ -73,10 +116,9 @@ public:
 | 
			
		||||
    GaugeLinkField dSdU_mu(U.Grid());
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
 | 
			
		||||
      Umu = PeekIndex<LorentzIndex>(U, mu);
 | 
			
		||||
      
 | 
			
		||||
      Umu = PeekIndex<LorentzIndex>(Ub, 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;
 | 
			
		||||
      
 | 
			
		||||
      PokeIndex<LorentzIndex>(dSdU, dSdU_mu, mu);
 | 
			
		||||
 
 | 
			
		||||
@@ -178,7 +178,10 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
        // Use chronological inverter to forecast solutions across poles
 | 
			
		||||
        std::vector<FermionField> prev_solns;
 | 
			
		||||
        if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); }
 | 
			
		||||
        ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast;
 | 
			
		||||
	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
 | 
			
		||||
        RealD N(PowerNegHalf.norm);
 | 
			
		||||
@@ -198,7 +201,7 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
          heatbathRefreshShiftCoefficients(0, -gamma_l);
 | 
			
		||||
          if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles
 | 
			
		||||
            Lop.Mdag(CG_src, Forecast_src);
 | 
			
		||||
            CG_soln = Forecast(Lop, Forecast_src, prev_solns);
 | 
			
		||||
            CG_soln = Forecast(MdagML, Forecast_src, prev_solns);
 | 
			
		||||
            SolverHBL(Lop, CG_src, CG_soln);
 | 
			
		||||
            prev_solns.push_back(CG_soln);
 | 
			
		||||
          } else {
 | 
			
		||||
@@ -225,7 +228,7 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
	  heatbathRefreshShiftCoefficients(1, -gamma_l*PowerNegHalf.poles[k]);
 | 
			
		||||
          if(use_heatbath_forecasting){
 | 
			
		||||
            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);
 | 
			
		||||
            prev_solns.push_back(CG_soln);
 | 
			
		||||
          } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define CPS_MD_TIME 
 | 
			
		||||
#undef CPS_MD_TIME 
 | 
			
		||||
 | 
			
		||||
#ifdef CPS_MD_TIME
 | 
			
		||||
#define HMC_MOMENTUM_DENOMINATOR (2.0)
 | 
			
		||||
 
 | 
			
		||||
@@ -121,12 +121,19 @@ public:
 | 
			
		||||
 | 
			
		||||
  template <class SmearingPolicy>
 | 
			
		||||
  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(){
 | 
			
		||||
    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.
 | 
			
		||||
@@ -176,15 +183,15 @@ public:
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  template <class SmearingPolicy>
 | 
			
		||||
  void Runner(SmearingPolicy &Smearing) {
 | 
			
		||||
  template <class SmearingPolicy, class Metric>
 | 
			
		||||
  void Runner(SmearingPolicy &Smearing, Metric &Mtr) {
 | 
			
		||||
    auto UGrid = Resources.GetCartesian();
 | 
			
		||||
    Field U(UGrid);
 | 
			
		||||
 | 
			
		||||
    initializeGaugeFieldAndRNGs(U);
 | 
			
		||||
 | 
			
		||||
    typedef IntegratorType<SmearingPolicy> TheIntegrator;
 | 
			
		||||
    TheIntegrator MDynamics(UGrid, Parameters.MD, TheAction, Smearing);
 | 
			
		||||
    TheIntegrator MDynamics(UGrid, Parameters.MD, TheAction, Smearing,Mtr);
 | 
			
		||||
 | 
			
		||||
    // Sets the momentum filter
 | 
			
		||||
    MDynamics.setMomentumFilter(*(Resources.GetMomentumFilter()));
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,8 @@ struct HMCparameters: Serializable {
 | 
			
		||||
                                  Integer, NoMetropolisUntil,
 | 
			
		||||
				  bool, PerformRandomShift, /* @brief Randomly shift the gauge configuration at the start of a trajectory */
 | 
			
		||||
                                  std::string, StartingType,
 | 
			
		||||
				  Integer, SW,
 | 
			
		||||
                                  RealD, Kappa,
 | 
			
		||||
                                  IntegratorParameters, MD)
 | 
			
		||||
 | 
			
		||||
  HMCparameters() {
 | 
			
		||||
@@ -110,6 +112,8 @@ private:
 | 
			
		||||
  IntegratorType &TheIntegrator;
 | 
			
		||||
  ObsListType Observables;
 | 
			
		||||
 | 
			
		||||
  int traj_num;
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////////
 | 
			
		||||
  // Metropolis step
 | 
			
		||||
  /////////////////////////////////////////////////////////
 | 
			
		||||
@@ -200,14 +204,14 @@ private:
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "--------------------------------------------------\n";
 | 
			
		||||
    std::cout << GridLogMessage << " Molecular Dynamics evolution ";
 | 
			
		||||
    TheIntegrator.integrate(U);
 | 
			
		||||
    TheIntegrator.integrate(U,traj_num);
 | 
			
		||||
    std::cout << GridLogMessage << "--------------------------------------------------\n";
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // updated state action
 | 
			
		||||
    //////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    std::cout << GridLogMessage << "--------------------------------------------------\n";
 | 
			
		||||
    std::cout << GridLogMessage << "Compute final action";
 | 
			
		||||
    std::cout << GridLogMessage << "Compute final action" <<std::endl;
 | 
			
		||||
    RealD H1 = TheIntegrator.S(U);  
 | 
			
		||||
    std::cout << GridLogMessage << "--------------------------------------------------\n";
 | 
			
		||||
 | 
			
		||||
@@ -242,7 +246,7 @@ public:
 | 
			
		||||
  HybridMonteCarlo(HMCparameters _Pams, IntegratorType &_Int,
 | 
			
		||||
                   GridSerialRNG &_sRNG, GridParallelRNG &_pRNG, 
 | 
			
		||||
                   ObsListType _Obs, Field &_U)
 | 
			
		||||
    : Params(_Pams), TheIntegrator(_Int), sRNG(_sRNG), pRNG(_pRNG), Observables(_Obs), Ucur(_U) {}
 | 
			
		||||
    : Params(_Pams), TheIntegrator(_Int), sRNG(_sRNG), pRNG(_pRNG), Observables(_Obs), Ucur(_U),traj_num(0) {}
 | 
			
		||||
  ~HybridMonteCarlo(){};
 | 
			
		||||
 | 
			
		||||
  void evolve(void) {
 | 
			
		||||
@@ -257,9 +261,10 @@ public:
 | 
			
		||||
    unsigned int FinalTrajectory = Params.Trajectories + Params.NoMetropolisUntil + Params.StartTrajectory;
 | 
			
		||||
 | 
			
		||||
    for (int traj = Params.StartTrajectory; traj < FinalTrajectory; ++traj) {
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
      std::cout << GridLogHMC << "-- # Trajectory = " << traj << "\n";
 | 
			
		||||
 | 
			
		||||
      traj_num=traj;
 | 
			
		||||
      if (traj < Params.StartTrajectory + Params.NoMetropolisUntil) {
 | 
			
		||||
      	std::cout << GridLogHMC << "-- Thermalization" << std::endl;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ Copyright (C) 2015
 | 
			
		||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
 | 
			
		||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
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
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -33,6 +34,7 @@ directory
 | 
			
		||||
#define INTEGRATOR_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <Grid/parallelIO/NerscIO.h>
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
@@ -41,10 +43,19 @@ public:
 | 
			
		||||
  GRID_SERIALIZABLE_CLASS_MEMBERS(IntegratorParameters,
 | 
			
		||||
				  std::string, name,      // name of the integrator
 | 
			
		||||
				  unsigned int, MDsteps,  // number of outer steps
 | 
			
		||||
				  RealD, RMHMCTol,
 | 
			
		||||
                                  RealD, RMHMCCGTol,
 | 
			
		||||
                                  RealD, lambda0,
 | 
			
		||||
                                  RealD, lambda1,
 | 
			
		||||
                                  RealD, lambda2,
 | 
			
		||||
				  RealD, trajL)           // trajectory length
 | 
			
		||||
 | 
			
		||||
  IntegratorParameters(int MDsteps_ = 10, RealD trajL_ = 1.0)
 | 
			
		||||
  : MDsteps(MDsteps_),
 | 
			
		||||
   lambda0(0.1931833275037836),
 | 
			
		||||
   lambda1(0.1931833275037836),
 | 
			
		||||
   lambda2(0.1931833275037836),
 | 
			
		||||
   RMHMCTol(1e-8),RMHMCCGTol(1e-8),
 | 
			
		||||
    trajL(trajL_) {};
 | 
			
		||||
 | 
			
		||||
  template <class ReaderClass, typename std::enable_if<isReader<ReaderClass>::value, int >::type = 0 >
 | 
			
		||||
@@ -75,11 +86,14 @@ public:
 | 
			
		||||
  double t_U;  // Track time passing on each level and for U and for P
 | 
			
		||||
  std::vector<double> t_P;  
 | 
			
		||||
 | 
			
		||||
  MomentaField P;
 | 
			
		||||
//  MomentaField P;
 | 
			
		||||
  GeneralisedMomenta<FieldImplementation > P;
 | 
			
		||||
  SmearingPolicy& Smearer;
 | 
			
		||||
  RepresentationPolicy Representations;
 | 
			
		||||
  IntegratorParameters Params;
 | 
			
		||||
 | 
			
		||||
  RealD Saux,Smom,Sg;
 | 
			
		||||
 | 
			
		||||
  //Filters allow the user to manipulate the conjugate momentum, for example to freeze links in DDHMC
 | 
			
		||||
  //It is applied whenever the momentum is updated / refreshed
 | 
			
		||||
  //The default filter does nothing
 | 
			
		||||
@@ -96,7 +110,16 @@ public:
 | 
			
		||||
  void update_P(Field& U, int level, double 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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -119,62 +142,174 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
  } update_P_hireps{};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
  void update_P(MomentaField& Mom, Field& U, int level, double ep) {
 | 
			
		||||
    // input U actually not used in the fundamental case
 | 
			
		||||
    // Fundamental updates, include smearing
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
      as[level].actions.at(a)->deriv_timer_start();
 | 
			
		||||
      as[level].actions.at(a)->deriv(Smearer, force);  // deriv should NOT include Ta
 | 
			
		||||
      as[level].actions.at(a)->deriv_timer_stop();
 | 
			
		||||
 | 
			
		||||
      auto name = as[level].actions.at(a)->action_name();
 | 
			
		||||
 | 
			
		||||
      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();
 | 
			
		||||
      
 | 
			
		||||
      MomFilter->applyFilter(force);
 | 
			
		||||
 | 
			
		||||
      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;
 | 
			
		||||
 | 
			
		||||
      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 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, double ep1, bool intermediate = false) {
 | 
			
		||||
    t_P[level] += ep;
 | 
			
		||||
 | 
			
		||||
    double ep2= ep-ep1;
 | 
			
		||||
 | 
			
		||||
    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(ep1);
 | 
			
		||||
    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
 | 
			
		||||
      NewMom = P.Mom -  HMC_MOMENTUM_DENOMINATOR * (ep*Msum + ep1* factor*MomDer + ep2* 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(ep2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void implicit_update_P(Field& U, int level, double ep, bool intermediate = false) {
 | 
			
		||||
      implicit_update_P( U, level, ep, ep*0.5, intermediate ); 
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void update_U(Field& U, double ep) 
 | 
			
		||||
  {
 | 
			
		||||
    update_U(P, U, ep);
 | 
			
		||||
    update_U(P.Mom, U, ep);
 | 
			
		||||
 | 
			
		||||
    t_U += ep;
 | 
			
		||||
    int fl = levels - 1;
 | 
			
		||||
@@ -183,12 +318,8 @@ public:
 | 
			
		||||
  
 | 
			
		||||
  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
 | 
			
		||||
    FieldImplementation::update_field(MomFiltered, U, ep);
 | 
			
		||||
    FieldImplementation::update_field(Mom, U, ep);
 | 
			
		||||
 | 
			
		||||
    // Update the smeared fields, can be implemented as observer
 | 
			
		||||
    Smearer.set_Field(U);
 | 
			
		||||
@@ -197,18 +328,74 @@ public:
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  Integrator(GridBase* grid, IntegratorParameters Par,
 | 
			
		||||
             ActionSet<Field, RepresentationPolicy>& Aset,
 | 
			
		||||
             SmearingPolicy& Sm)
 | 
			
		||||
             SmearingPolicy& Sm, Metric<MomentaField>& M)
 | 
			
		||||
    : Params(Par),
 | 
			
		||||
      as(Aset),
 | 
			
		||||
      P(grid),
 | 
			
		||||
      P(grid, M),
 | 
			
		||||
      levels(Aset.size()),
 | 
			
		||||
      Smearer(Sm),
 | 
			
		||||
      Representations(grid) 
 | 
			
		||||
      Representations(grid),
 | 
			
		||||
      Saux(0.),Smom(0.),Sg(0.)
 | 
			
		||||
  {
 | 
			
		||||
    t_P.resize(levels, 0.0);
 | 
			
		||||
    t_U = 0.0;
 | 
			
		||||
@@ -324,7 +511,8 @@ public:
 | 
			
		||||
 | 
			
		||||
  void reverse_momenta()
 | 
			
		||||
  {
 | 
			
		||||
    P *= -1.0;
 | 
			
		||||
    P.Mom *= -1.0;
 | 
			
		||||
    P.AuxMom *= -1.0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // to be used by the actionlevel class to iterate
 | 
			
		||||
@@ -343,11 +531,14 @@ public:
 | 
			
		||||
  // Initialization of momenta and actions
 | 
			
		||||
  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 << "Generating momentum" << std::endl;
 | 
			
		||||
    FieldImplementation::generate_momenta(P, sRNG, pRNG);
 | 
			
		||||
//    FieldImplementation::generate_momenta(P.Mom, sRNG, pRNG);
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    P.MomentaDistribution(sRNG,pRNG);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Update the smeared fields, can be implemented as observer
 | 
			
		||||
    // necessary to keep the fields updated even after a reject
 | 
			
		||||
@@ -402,9 +593,22 @@ public:
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
//    static RealD Saux=0.,Smom=0.,Sg=0.;
 | 
			
		||||
 | 
			
		||||
    RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
    std::cout << GridLogMessage << "S:FieldSquareNorm H_p = " << H << "\n";
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSField = " << H-Smom << "\n";
 | 
			
		||||
    Smom=H;
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    RealD Hterm = - P.MomentaAction();
 | 
			
		||||
    std::cout << GridLogMessage << "S:Momentum action H_p = " << Hterm << "\n";
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSMom = " << Hterm-Saux << "\n";
 | 
			
		||||
    Saux=Hterm;
 | 
			
		||||
    H = Hterm;
 | 
			
		||||
 | 
			
		||||
    RealD Hterm;
 | 
			
		||||
 | 
			
		||||
    // Actions
 | 
			
		||||
    for (int level = 0; level < as.size(); ++level) {
 | 
			
		||||
@@ -446,9 +650,18 @@ public:
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogIntegrator << "Integrator initial action\n";
 | 
			
		||||
 | 
			
		||||
    RealD H = - FieldImplementation::FieldSquareNorm(P)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
 | 
			
		||||
    RealD Hterm;
 | 
			
		||||
//    RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
//    RealD Hterm;
 | 
			
		||||
    RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
    std::cout << GridLogMessage << "S:FieldSquareNorm H_p = " << H << "\n";
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSField = " << H-Smom << "\n";
 | 
			
		||||
    Smom=H;
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    RealD Hterm = - P.MomentaAction();
 | 
			
		||||
    std::cout << GridLogMessage << "S:Momentum action H_p = " << Hterm << "\n";
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSMom = " << Hterm-Saux << "\n";
 | 
			
		||||
    Saux=Hterm;
 | 
			
		||||
    H = Hterm;
 | 
			
		||||
 | 
			
		||||
    // Actions
 | 
			
		||||
    for (int level = 0; level < as.size(); ++level) {
 | 
			
		||||
@@ -471,7 +684,7 @@ public:
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  void integrate(Field& U) 
 | 
			
		||||
  void integrate(Field& U, int traj=-1 ) 
 | 
			
		||||
  {
 | 
			
		||||
    // reset the clocks
 | 
			
		||||
    t_U = 0;
 | 
			
		||||
@@ -483,6 +696,12 @@ public:
 | 
			
		||||
      int first_step = (stp == 0);
 | 
			
		||||
      int last_step = (stp == Params.MDsteps - 1);
 | 
			
		||||
      this->step(U, 0, first_step, last_step);
 | 
			
		||||
      if (traj>=0){
 | 
			
		||||
        std::string file("./config."+std::to_string(traj)+"_"+std::to_string(stp+1) );
 | 
			
		||||
        int precision32 = 0;
 | 
			
		||||
        int tworow      = 0;
 | 
			
		||||
        NerscIO::writeConfiguration(U,file,tworow,precision32);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check the clocks all match on all levels
 | 
			
		||||
@@ -492,7 +711,6 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FieldImplementation::Project(U);
 | 
			
		||||
 | 
			
		||||
    // and that we indeed got to the end of the trajectory
 | 
			
		||||
    assert(fabs(t_U - Params.trajL) < 1.0e-6);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -102,8 +102,8 @@ public:
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "LeapFrog";}
 | 
			
		||||
 | 
			
		||||
  LeapFrog(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm){};
 | 
			
		||||
  LeapFrog(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, 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;
 | 
			
		||||
@@ -140,14 +140,14 @@ template <class FieldImplementation_, class SmearingPolicy, class Representation
 | 
			
		||||
class MinimumNorm2 : public Integrator<FieldImplementation_, SmearingPolicy, RepresentationPolicy> 
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
  const RealD lambda = 0.1931833275037836;
 | 
			
		||||
//  const RealD lambda = 0.1931833275037836;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  typedef FieldImplementation_ FieldImplementation;
 | 
			
		||||
  INHERIT_FIELD_TYPES(FieldImplementation);
 | 
			
		||||
 | 
			
		||||
  MinimumNorm2(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm){};
 | 
			
		||||
  MinimumNorm2(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm,M){};
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "MininumNorm2";}
 | 
			
		||||
 | 
			
		||||
@@ -155,6 +155,11 @@ public:
 | 
			
		||||
    // level  : current level
 | 
			
		||||
    // fl     : final level
 | 
			
		||||
    // eps    : current step size
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    int fl = this->as.size() - 1;
 | 
			
		||||
 | 
			
		||||
@@ -210,9 +215,9 @@ public:
 | 
			
		||||
  // Looks like dH scales as dt^4. tested wilson/wilson 2 level.
 | 
			
		||||
  ForceGradient(GridBase* grid, IntegratorParameters Par,
 | 
			
		||||
                ActionSet<Field, RepresentationPolicy>& Aset,
 | 
			
		||||
                SmearingPolicy& Sm)
 | 
			
		||||
                SmearingPolicy& Sm, Metric<Field>& M)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
 | 
			
		||||
									    grid, Par, Aset, Sm){};
 | 
			
		||||
									    grid, Par, Aset, Sm,M){};
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "ForceGradient";}
 | 
			
		||||
  
 | 
			
		||||
@@ -275,6 +280,255 @@ 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);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        this->step(U, level + 1, first_step, 0);
 | 
			
		||||
 | 
			
		||||
      this->update_P(U, level, (1.0 - 2.0 * lambda) * eps);
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this->implicit_update_U(U, 0.5 * eps,lambda*eps);
 | 
			
		||||
 | 
			
		||||
      this->implicit_update_P(U, level, (1.0 - 2.0 * lambda) * eps, true);
 | 
			
		||||
 | 
			
		||||
      this->implicit_update_U(U, 0.5 * eps, (0.5-lambda)*eps);
 | 
			
		||||
 | 
			
		||||
      if (last_step) {
 | 
			
		||||
        this->update_P2(U, level, eps * lambda);
 | 
			
		||||
      } else {
 | 
			
		||||
        this->implicit_update_P(U, level, lambda * eps*2.0, true);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class FieldImplementation, class SmearingPolicy,
 | 
			
		||||
          class RepresentationPolicy =
 | 
			
		||||
              Representations<FundamentalRepresentation> >
 | 
			
		||||
class ImplicitCampostrini : public Integrator<FieldImplementation, SmearingPolicy,
 | 
			
		||||
                                       RepresentationPolicy> {
 | 
			
		||||
 private:
 | 
			
		||||
//  const RealD lambda = 0.1931833275037836;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  INHERIT_FIELD_TYPES(FieldImplementation);
 | 
			
		||||
 | 
			
		||||
  ImplicitCampostrini(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 "ImplicitCampostrini";}
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
    
 | 
			
		||||
    RealD sigma=pow(2.0,1./3.);
 | 
			
		||||
 | 
			
		||||
  if(level<fl){
 | 
			
		||||
//Still Omelyan. Needs to change step() to accept variable stepsize
 | 
			
		||||
    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);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        this->step(U, level + 1, first_step, 0);
 | 
			
		||||
 | 
			
		||||
      this->update_P(U, level, (1.0 - 2.0 * lambda) * eps);
 | 
			
		||||
 | 
			
		||||
        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 dt = this->Params.trajL/this->Params.MDsteps * 2.0;
 | 
			
		||||
    for (int l = 0; l <= level; ++l) dt /= 2.0 * this->as[l].multiplier;
 | 
			
		||||
 | 
			
		||||
    RealD epsilon = dt/(2.0 - sigma);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
      // initial half step
 | 
			
		||||
      if (first_step) {  this->implicit_update_P(U, level, epsilon*0.5); }
 | 
			
		||||
      this->implicit_update_U(U, epsilon,epsilon*0.5);
 | 
			
		||||
      this->implicit_update_P(U, level, (1.0 - sigma) * epsilon *0.5, epsilon*0.5, true);
 | 
			
		||||
      this->implicit_update_U(U, -epsilon*sigma, -epsilon*sigma*0.5);
 | 
			
		||||
      this->implicit_update_P(U, level, (1.0 - sigma) * epsilon *0.5, -epsilon*sigma*0.5, true);
 | 
			
		||||
      this->implicit_update_U(U, epsilon,epsilon*0.5);
 | 
			
		||||
      if (last_step) { this->update_P2(U, level, epsilon*0.5 ); } 
 | 
			
		||||
      else
 | 
			
		||||
      this->implicit_update_P(U, level, epsilon,epsilon*0.5);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
#endif  // INTEGRATOR_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,361 @@ struct LaplacianParams : Serializable {
 | 
			
		||||
      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; };
 | 
			
		||||
//broken
 | 
			
		||||
#if 0
 | 
			
		||||
  virtual void  MDeriv(const Field &_left, Field &_right,Field &_der, int mu)
 | 
			
		||||
  {
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    // Halo exchange for this geometry of stencil
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    Stencil.HaloExchange(_lef, Compressor);
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
    // Arithmetic expressions
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
    autoView( st     , Stencil    , AcceleratorRead);
 | 
			
		||||
    auto buf = st.CommBuf();
 | 
			
		||||
 | 
			
		||||
    autoView( in     , _left    , AcceleratorRead);
 | 
			
		||||
    autoView( right    , _right   , AcceleratorRead);
 | 
			
		||||
    autoView( der    , _der   , AcceleratorWrite);
 | 
			
		||||
    autoView( U     , Uds    , AcceleratorRead);
 | 
			
		||||
 | 
			
		||||
    typedef typename Field::vector_object        vobj;
 | 
			
		||||
    typedef decltype(coalescedRead(left[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 phi;
 | 
			
		||||
	calcObj res;
 | 
			
		||||
	calcObj Uchi;
 | 
			
		||||
	calcObj Utmp;
 | 
			
		||||
	calcObj Utmp2;
 | 
			
		||||
	calcLink UU;
 | 
			
		||||
	calcLink Udag;
 | 
			
		||||
	int ptype;
 | 
			
		||||
 | 
			
		||||
	res                 = coalescedRead(def[ss]);
 | 
			
		||||
	phi                 = coalescedRead(right[ss]);
 | 
			
		||||
 | 
			
		||||
#define LEG_LOAD_MULT_LINK(leg,polarisation)			\
 | 
			
		||||
	UU = coalescedRead(U[ss](polarisation));	\
 | 
			
		||||
	Udag = adj(UU);					\
 | 
			
		||||
	LEG_LOAD(leg);					\
 | 
			
		||||
	mult(&Utmp(), &UU, &chi());			\
 | 
			
		||||
	Utmp2 = adj(Utmp);				\
 | 
			
		||||
	mult(&Utmp(), &UU, &Utmp2());			\
 | 
			
		||||
	Utmp2 = adj(Utmp);				\
 | 
			
		||||
	mult(&Uchi(), &phi(), &Utmp2());			\
 | 
			
		||||
	res = res + Uchi;
 | 
			
		||||
	
 | 
			
		||||
	LEG_LOAD_MULT_LINK(0,Xp);
 | 
			
		||||
	LEG_LOAD_MULT_LINK(1,Yp);
 | 
			
		||||
	LEG_LOAD_MULT_LINK(2,Zp);
 | 
			
		||||
	LEG_LOAD_MULT_LINK(3,Tp);
 | 
			
		||||
 | 
			
		||||
	coalescedWrite(der[ss], res,lane);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  virtual void  Morig(const Field &_in, Field &_out)
 | 
			
		||||
  {
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    // Halo exchange for this geometry of stencil
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    Stencil.HaloExchange(_in, Compressor);
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
    // Arithmetic expressions
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
//    auto st = Stencil.View(AcceleratorRead);
 | 
			
		||||
    autoView( st     , Stencil    , 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  Mnew (const Field &_in, Field &_out)
 | 
			
		||||
  {
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    // Halo exchange for this geometry of stencil
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
//    Stencil.HaloExchange(_in, Compressor);
 | 
			
		||||
      std::vector<std::vector<CommsRequest_t> > requests;
 | 
			
		||||
      Stencil.Prepare();
 | 
			
		||||
  {
 | 
			
		||||
    GRID_TRACE("Laplace Gather");
 | 
			
		||||
    Stencil.HaloGather(_in,Compressor);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  tracePush("Laplace Communication");
 | 
			
		||||
  Stencil.CommunicateBegin(requests);
 | 
			
		||||
  {
 | 
			
		||||
    GRID_TRACE("MergeSHM");
 | 
			
		||||
    Stencil.CommsMergeSHM(Compressor);
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
    // Arithmetic expressions
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
//    auto st = Stencil.View(AcceleratorRead);
 | 
			
		||||
    autoView( st     , Stencil    , 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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        SE = st.GetEntry(ptype, 0, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(0,Xp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 1, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(1,Yp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 2, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(2,Zp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 3, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(3,Tp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 4, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(4,Xm);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 5, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(5,Ym);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 6, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(6,Zm);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 7, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(7,Tm);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	coalescedWrite(out[ss], res,lane);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    Stencil.CommunicateComplete(requests);
 | 
			
		||||
  tracePop("Communication");
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    GRID_TRACE("Merge");
 | 
			
		||||
    Stencil.CommsMerge(Compressor);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
	res                 = coalescedRead(out[ss]);
 | 
			
		||||
 | 
			
		||||
        SE = st.GetEntry(ptype, 0, ss);				 
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(0,Xp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 1, ss);				 
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(1,Yp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 2, ss);				 
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(2,Zp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 3, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(3,Tp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 4, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(4,Xm);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 5, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(5,Ym);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 6, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(6,Zm);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 7, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(7,Tm);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	coalescedWrite(out[ss], res,lane);
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  virtual void  M(const Field &in, Field &out) {Mnew(in,out);};
 | 
			
		||||
  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_MULT_LINK
 | 
			
		||||
#undef LEG_LOAD
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////
 | 
			
		||||
// Laplacian operator L on adjoint fields
 | 
			
		||||
@@ -76,29 +430,40 @@ class LaplacianAdjointField: public Metric<typename Impl::Field> {
 | 
			
		||||
  LaplacianParams param;
 | 
			
		||||
  MultiShiftFunction PowerHalf;    
 | 
			
		||||
  MultiShiftFunction PowerInvHalf;    
 | 
			
		||||
//template<class Gimpl,class Field> class CovariantAdjointLaplacianStencil : public SparseMatrixBase<Field>
 | 
			
		||||
  CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField> LapStencil;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  INHERIT_GIMPL_TYPES(Impl);
 | 
			
		||||
 | 
			
		||||
  LaplacianAdjointField(GridBase* grid, OperatorFunction<GaugeField>& S, LaplacianParams& p, const RealD k = 1.0)
 | 
			
		||||
    : U(Nd, grid), Solver(S), param(p), kappa(k){
 | 
			
		||||
  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)
 | 
			
		||||
	,LapStencil(grid){
 | 
			
		||||
    AlgRemez remez(param.lo,param.hi,param.precision);
 | 
			
		||||
    std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
 | 
			
		||||
    if(if_remez){
 | 
			
		||||
    remez.generateApprox(param.degree,1,2);
 | 
			
		||||
    PowerHalf.Init(remez,param.tolerance,false);
 | 
			
		||||
    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 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]);
 | 
			
		||||
    }
 | 
			
		||||
    LapStencil.GaugeImport (_U);
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogDebug <<"ImportGauge:norm2(U _U) = "<<total<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void M(const GaugeField& in, GaugeField& out) {
 | 
			
		||||
@@ -106,10 +471,12 @@ public:
 | 
			
		||||
    // test
 | 
			
		||||
    //GaugeField herm = in + adj(in);
 | 
			
		||||
    //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 tmp2(in.Grid());
 | 
			
		||||
    GaugeLinkField sum(in.Grid());
 | 
			
		||||
 | 
			
		||||
    for (int nu = 0; nu < Nd; nu++) {
 | 
			
		||||
      sum = Zero();
 | 
			
		||||
@@ -123,10 +490,22 @@ public:
 | 
			
		||||
      out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum;
 | 
			
		||||
      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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  void MDeriv(const GaugeField& in, GaugeField& der) {
 | 
			
		||||
    // in is anti-hermitian
 | 
			
		||||
//    std::cout << GridLogDebug <<"MDeriv:Kappa = "<<kappa<<std::endl;
 | 
			
		||||
    RealD factor = -kappa / (double(4 * Nd));
 | 
			
		||||
    
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++){
 | 
			
		||||
@@ -140,6 +519,7 @@ public:
 | 
			
		||||
      // adjoint in the last multiplication
 | 
			
		||||
      PokeIndex<LorentzIndex>(der,  -2.0 * factor * der_mu, mu);
 | 
			
		||||
    } 
 | 
			
		||||
    std::cout << GridLogDebug <<"MDeriv: Kappa= "<< kappa << " norm2(der) = "<<norm2(der)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // separating this temporarily
 | 
			
		||||
@@ -159,11 +539,22 @@ public:
 | 
			
		||||
      }
 | 
			
		||||
      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){
 | 
			
		||||
    HermitianLinearOperator<LaplacianAdjointField<Impl>,GaugeField> HermOp(*this);
 | 
			
		||||
    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){
 | 
			
		||||
@@ -172,6 +563,7 @@ public:
 | 
			
		||||
    ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerHalf);
 | 
			
		||||
    msCG(HermOp,P,Gp);
 | 
			
		||||
    P = Gp; 
 | 
			
		||||
    std::cout << GridLogDebug <<"MSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MInvSquareRoot(GaugeField& P){
 | 
			
		||||
@@ -180,6 +572,7 @@ public:
 | 
			
		||||
    ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerInvHalf);
 | 
			
		||||
    msCG(HermOp,P,Gp);
 | 
			
		||||
    P = Gp; 
 | 
			
		||||
    std::cout << GridLogDebug <<"MInvSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										403
									
								
								Grid/qcd/utils/CovariantLaplacianRat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										403
									
								
								Grid/qcd/utils/CovariantLaplacianRat.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,403 @@
 | 
			
		||||
/*************************************************************************************
 | 
			
		||||
 | 
			
		||||
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 
 | 
			
		||||
#define 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;
 | 
			
		||||
  CovariantAdjointLaplacianStencil<ImplF,typename ImplF::LinkField> LapStencilF;
 | 
			
		||||
public:
 | 
			
		||||
  INHERIT_GIMPL_TYPES(Impl);
 | 
			
		||||
//   typedef typename GImpl::LinkField GaugeLinkField; \
 | 
			
		||||
//  typedef typename GImpl::Field GaugeField;         
 | 
			
		||||
  typedef typename ImplF::Field GaugeFieldF;
 | 
			
		||||
  typedef typename ImplF::LinkField GaugeLinkFieldF; \
 | 
			
		||||
  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), LapStencilF(_grid_f), 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) {
 | 
			
		||||
    std::cout<<GridLogMessage << "MDerivLink start "<< std::endl;
 | 
			
		||||
    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;
 | 
			
		||||
    std::cout<<GridLogMessage << "MDerivLink end "<< std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MDerivLink(const GaugeLinkField& left, const GaugeLinkField& right,
 | 
			
		||||
              std::vector<GaugeLinkField> & der) {
 | 
			
		||||
//    std::cout<<GridLogMessage << "MDerivLink "<< std::endl;
 | 
			
		||||
    RealD factor = -1. / (double(4 * Nd));
 | 
			
		||||
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      GaugeLinkField der_mu(left.Grid());
 | 
			
		||||
      der_mu = Zero();
 | 
			
		||||
        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);
 | 
			
		||||
      der[mu] = -factor*der_mu;
 | 
			
		||||
//      std::cout << GridLogDebug <<"MDerivLink:  norm2(der) = "<<norm2(der[mu])<<std::endl;
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
//    std::cout<<GridLogMessage << "MDerivLink end "<< 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
 | 
			
		||||
    std::cout<<GridLogMessage << "LaplaceStart " <<std::endl;
 | 
			
		||||
    RealD fac =  - 1. / (double(4 * Nd)) ;
 | 
			
		||||
    RealD coef=0.5;
 | 
			
		||||
    LapStencil.GaugeImport(Usav);
 | 
			
		||||
    LapStencilF.GaugeImport(UsavF);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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<CovariantAdjointLaplacianStencil<ImplF,typename ImplF::LinkField>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
    //    QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],par.b1[i],par.b2);
 | 
			
		||||
        MixedPrecisionConjugateGradient<GaugeLinkField,GaugeLinkFieldF> 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<CovariantAdjointLaplacianStencil<ImplF,typename ImplF::LinkField>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
    //    QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],par.b1[i],par.b2);
 | 
			
		||||
        MixedPrecisionConjugateGradient<GaugeLinkField,GaugeLinkFieldF> MixedCG(par.tolerance,10000,10000,grid_f,QuadOpF,QuadOp);
 | 
			
		||||
        MixedCG.InnerTolerance=par.tolerance;
 | 
			
		||||
        MixedCG(GMom,MinvGMom);
 | 
			
		||||
        LapStencil.M(MinvGMom, Gtemp2); LMinvGMom=fac*Gtemp2;
 | 
			
		||||
    //    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::vector<GaugeLinkField> DerLink(Nd,left.Grid());
 | 
			
		||||
        std::vector<GaugeLinkField> tempDerLink(Nd,left.Grid());
 | 
			
		||||
 | 
			
		||||
        std::cout<<GridLogMessage << "force contraction "<< i <<std::endl;
 | 
			
		||||
    //    roctxRangePushA("RMHMC force contraction");
 | 
			
		||||
 #if 0
 | 
			
		||||
        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;
 | 
			
		||||
#else
 | 
			
		||||
	for (int mu=0;mu<Nd;mu++) DerLink[mu]=Zero();
 | 
			
		||||
        MDerivLink(GMom,MinvMom[i],tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*2*par.a1[i]*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(left_nu,MinvGMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*2*par.a1[i]*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(LMinvAGMom,MinvMom[i],tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b2*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(LMinvAMom,MinvGMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b2*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(MinvAGMom,LMinvMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b2*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(AMinvMom,LMinvGMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b2*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(MinvAGMom,MinvMom[i],tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b1[i]*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(AMinvMom,MinvGMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b1[i]*tempDerLink[mu];
 | 
			
		||||
//      PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
 | 
			
		||||
        for (int mu=0;mu<Nd;mu++) PokeIndex<LorentzIndex>(tempDer, tempDerLink[mu], mu);
 | 
			
		||||
 | 
			
		||||
	der += tempDer;
 | 
			
		||||
#endif
 | 
			
		||||
        std::cout<<GridLogMessage << "coef =  force contraction "<< i << "done "<< coef <<std::endl;
 | 
			
		||||
    //    roctxRangePop();
 | 
			
		||||
    
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<GridLogMessage << "LaplaceEnd " <<std::endl;
 | 
			
		||||
//  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 ){
 | 
			
		||||
 | 
			
		||||
    std::cout<<GridLogMessage << "LaplaceStart " <<std::endl;
 | 
			
		||||
    RealD fac = -1. / (double(4 * Nd));
 | 
			
		||||
    LapStencil.GaugeImport(Usav);
 | 
			
		||||
    LapStencilF.GaugeImport(UsavF);
 | 
			
		||||
    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<CovariantAdjointLaplacianStencil<ImplF,typename ImplF::LinkField>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
    //    QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeFieldF> QuadOpF(LapStencilF,par.b0[i],par.b1[i],par.b2);
 | 
			
		||||
        MixedPrecisionConjugateGradient<GaugeLinkField,GaugeLinkFieldF> MixedCG(par.tolerance,10000,10000,grid_f,QuadOpF,QuadOp);
 | 
			
		||||
        MixedCG.InnerTolerance=par.tolerance;
 | 
			
		||||
        MixedCG(P_nu,Gtemp);
 | 
			
		||||
    #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);
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<GridLogMessage << "LaplaceEnd " <<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -33,7 +34,12 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
template <typename Field> 
 | 
			
		||||
class Metric{
 | 
			
		||||
protected:
 | 
			
		||||
  int triv;
 | 
			
		||||
public:
 | 
			
		||||
  Metric(){this->triv=1;}
 | 
			
		||||
  int Trivial(){ return triv;}
 | 
			
		||||
//printf("Metric::Trivial=%d\n",triv); ;
 | 
			
		||||
  virtual void ImportGauge(const Field&)   = 0;
 | 
			
		||||
  virtual void M(const Field&, Field&)     = 0;
 | 
			
		||||
  virtual void Minv(const Field&, Field&)  = 0;
 | 
			
		||||
@@ -41,6 +47,8 @@ public:
 | 
			
		||||
  virtual void MInvSquareRoot(Field&) = 0;
 | 
			
		||||
  virtual void MDeriv(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>
 | 
			
		||||
class TrivialMetric : public Metric<Field>{
 | 
			
		||||
public:
 | 
			
		||||
//  TrivialMetric(){this->triv=1;printf("TrivialMetric::triv=%d\n",this->Trivial());}
 | 
			
		||||
  virtual void ImportGauge(const Field&){};
 | 
			
		||||
  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;
 | 
			
		||||
  }
 | 
			
		||||
  virtual void Minv(const Field& in, Field& out){
 | 
			
		||||
    std::cout << GridLogIntegrator << " Minv:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
 | 
			
		||||
    out = in;
 | 
			
		||||
  }
 | 
			
		||||
  virtual void MSquareRoot(Field& P){
 | 
			
		||||
    std::cout << GridLogIntegrator << " MSquareRoot:norm(P)= " << std::sqrt(norm2(P)) << std::endl;
 | 
			
		||||
    // do nothing
 | 
			
		||||
  }
 | 
			
		||||
  virtual void MInvSquareRoot(Field& P){
 | 
			
		||||
    std::cout << GridLogIntegrator << " MInvSquareRoot:norm(P)= " << std::sqrt(norm2(P)) << std::endl;
 | 
			
		||||
    // do nothing
 | 
			
		||||
  }
 | 
			
		||||
  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();
 | 
			
		||||
  }
 | 
			
		||||
  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();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -101,14 +122,15 @@ public:
 | 
			
		||||
    // Generate gaussian momenta
 | 
			
		||||
    Implementation::generate_momenta(Mom, sRNG, pRNG);
 | 
			
		||||
    // Modify the distribution with the metric
 | 
			
		||||
//    if(M.Trivial()) return;
 | 
			
		||||
    M.MSquareRoot(Mom);
 | 
			
		||||
 | 
			
		||||
    if (1) {
 | 
			
		||||
      // Auxiliary momenta
 | 
			
		||||
      // do nothing if trivial, so hide in the metric
 | 
			
		||||
      MomentaField AuxMomTemp(Mom.Grid());
 | 
			
		||||
      Implementation::generate_momenta(AuxMom, sRNG, pRNG);
 | 
			
		||||
      Implementation::generate_momenta(AuxField, sRNG, pRNG);
 | 
			
		||||
      Implementation::generate_momenta(AuxMom, sRNG,pRNG);
 | 
			
		||||
      Implementation::generate_momenta(AuxField, sRNG,pRNG);
 | 
			
		||||
      // Modify the distribution with the metric
 | 
			
		||||
      // Aux^dag M Aux
 | 
			
		||||
      M.MInvSquareRoot(AuxMom);  // AuxMom = M^{-1/2} AuxMomTemp
 | 
			
		||||
@@ -117,11 +139,12 @@ public:
 | 
			
		||||
 | 
			
		||||
  // Correct
 | 
			
		||||
  RealD MomentaAction(){
 | 
			
		||||
    static RealD Saux=0.,Smom=0.;
 | 
			
		||||
    MomentaField inv(Mom.Grid());
 | 
			
		||||
    inv = Zero();
 | 
			
		||||
    M.Minv(Mom, inv);
 | 
			
		||||
    LatticeComplex Hloc(Mom.Grid());
 | 
			
		||||
    Hloc = Zero();
 | 
			
		||||
    LatticeComplex Hloc(Mom.Grid()); Hloc = Zero();
 | 
			
		||||
    LatticeComplex Hloc2(Mom.Grid()); Hloc2 = Zero();
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      // This is not very general
 | 
			
		||||
      // hide in the metric
 | 
			
		||||
@@ -129,8 +152,15 @@ public:
 | 
			
		||||
      auto inv_mu = PeekIndex<LorentzIndex>(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
 | 
			
		||||
      // hide in the metric
 | 
			
		||||
      M.M(AuxMom, inv);
 | 
			
		||||
@@ -140,13 +170,18 @@ public:
 | 
			
		||||
        auto inv_mu = PeekIndex<LorentzIndex>(inv, mu);
 | 
			
		||||
        auto am_mu = PeekIndex<LorentzIndex>(AuxMom, mu);
 | 
			
		||||
        auto af_mu = PeekIndex<LorentzIndex>(AuxField, mu);
 | 
			
		||||
        Hloc += trace(am_mu * inv_mu);// p M p
 | 
			
		||||
        Hloc += trace(af_mu * af_mu);
 | 
			
		||||
        Hloc += trace(am_mu * inv_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));
 | 
			
		||||
    return Hsum.real();
 | 
			
		||||
    auto Hsum = TensorRemove(sum(Hloc))/HMC_MOMENTUM_DENOMINATOR;
 | 
			
		||||
    auto Hsum2 = TensorRemove(sum(Hloc2));
 | 
			
		||||
    std::cout << GridLogIntegrator << "MomentaAction: " <<  Hsum.real()+Hsum2.real() << std::endl;
 | 
			
		||||
    return Hsum.real()+Hsum2.real();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Correct
 | 
			
		||||
@@ -157,15 +192,17 @@ public:
 | 
			
		||||
    MomentaField MDer(in.Grid());
 | 
			
		||||
    MomentaField X(in.Grid());
 | 
			
		||||
    X = Zero();
 | 
			
		||||
    M.Minv(in, X);  // X = G in
 | 
			
		||||
    M.MDeriv(X, MDer);  // MDer = U * dS/dU
 | 
			
		||||
    der = Implementation::projectForce(MDer);  // Ta if gauge fields
 | 
			
		||||
    M.MinvDeriv(in, MDer);  // MDer = U * dS/dU
 | 
			
		||||
    der = -1.0* 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){
 | 
			
		||||
    der = Zero();
 | 
			
		||||
    if (1){
 | 
			
		||||
//    if(!M.Trivial()) 
 | 
			
		||||
    {
 | 
			
		||||
      // Auxiliary fields
 | 
			
		||||
      MomentaField der_temp(der.Grid());
 | 
			
		||||
      MomentaField X(der.Grid());
 | 
			
		||||
@@ -173,6 +210,7 @@ public:
 | 
			
		||||
      //M.M(AuxMom, X); // X = M Aux
 | 
			
		||||
      // Two derivative 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); 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -180,6 +218,7 @@ public:
 | 
			
		||||
      //M.MDeriv(X, AuxMom, der_temp); der += der_temp;
 | 
			
		||||
 | 
			
		||||
      der = -1.0*Implementation::projectForce(der);
 | 
			
		||||
      std::cout << GridLogIntegrator << " AuxiliaryFieldsDerivative:norm(der)= " << std::sqrt(norm2(der)) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -189,22 +228,28 @@ public:
 | 
			
		||||
    // is the projection necessary here?
 | 
			
		||||
    // no for fields in the algebra
 | 
			
		||||
    der = Implementation::projectForce(der); 
 | 
			
		||||
    std::cout << GridLogIntegrator << " DerivativeP:norm(der)= " << std::sqrt(norm2(der)) << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void update_auxiliary_momenta(RealD ep){
 | 
			
		||||
    if(1){
 | 
			
		||||
      AuxMom -= ep * AuxField;
 | 
			
		||||
      std::cout << GridLogIntegrator << "AuxMom update_auxiliary_fields: " << std::sqrt(norm2(AuxMom)) << std::endl;
 | 
			
		||||
      std::cout << GridLogIntegrator << "AuxField update_auxiliary_fields: " << std::sqrt(norm2(AuxField)) << std::endl;
 | 
			
		||||
    {
 | 
			
		||||
      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){
 | 
			
		||||
    if (1) {
 | 
			
		||||
//    if(!M.Trivial()) 
 | 
			
		||||
    {
 | 
			
		||||
      MomentaField tmp(AuxMom.Grid());
 | 
			
		||||
      MomentaField tmp2(AuxMom.Grid());
 | 
			
		||||
      M.M(AuxMom, tmp);
 | 
			
		||||
      // M.M(tmp, tmp2);
 | 
			
		||||
      AuxField += ep * tmp;  // M^2 AuxMom
 | 
			
		||||
      // factor of 2?
 | 
			
		||||
      std::cout << GridLogIntegrator << "AuxField update_auxiliary_fields: " << std::sqrt(norm2(AuxField)) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										637
									
								
								HMC/Mobius2p1p1fEOFA_4Gev.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										637
									
								
								HMC/Mobius2p1p1fEOFA_4Gev.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,637 @@
 | 
			
		||||
/*************************************************************************************
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
#undef USE_OBC
 | 
			
		||||
#define 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
 | 
			
		||||
 | 
			
		||||
#ifdef DO_IMPLICIT
 | 
			
		||||
//    typedef GenericHMCRunner<ImplicitLeapFrog> HMCWrapper; 
 | 
			
		||||
  typedef GenericHMCRunner<ImplicitMinimumNorm2> HMCWrapper; 
 | 
			
		||||
  HMCparams.MD.name          =std::string("ImplicitMinimumNorm2");
 | 
			
		||||
#else
 | 
			
		||||
//  typedef GenericHMCRunner<LeapFrog> HMCWrapper; 
 | 
			
		||||
  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 UGrid_f    = SpaceTimeGrid::makeFourDimGrid(latt,simdF,mpi);
 | 
			
		||||
  auto GridRBPtrF = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid_f);
 | 
			
		||||
  auto FGridF     = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid_f);
 | 
			
		||||
  auto FrbGridF   = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,UGrid_f);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#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(UGrid_f);
 | 
			
		||||
 | 
			
		||||
  // 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-8;
 | 
			
		||||
  double MaxCGIterations =  100000;
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // 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, *UGrid_f, *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, *UGrid_f, *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, *UGrid_f, *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, *UGrid_f, *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 = 50000;
 | 
			
		||||
 | 
			
		||||
  // 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,
 | 
			
		||||
		       UGrid_f,
 | 
			
		||||
		       FrbGridF,
 | 
			
		||||
		       Strange_Op_LF,Strange_Op_L,
 | 
			
		||||
		       Strange_LinOp_LF,Strange_LinOp_L);
 | 
			
		||||
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MxPCG_EOFA ActionCGL2(ActionStoppingCondition,
 | 
			
		||||
		       MX_inner,
 | 
			
		||||
		       MaxCGIterations,
 | 
			
		||||
		       UGrid_f,
 | 
			
		||||
		       FrbGridF,
 | 
			
		||||
		       Strange2_Op_LF,Strange2_Op_L,
 | 
			
		||||
		       Strange2_LinOp_LF,Strange2_LinOp_L);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  MxPCG_EOFA DerivativeCGL(DerivativeStoppingCondition,
 | 
			
		||||
			   MX_inner,
 | 
			
		||||
			   MaxCGIterations,
 | 
			
		||||
			   UGrid_f,
 | 
			
		||||
			   FrbGridF,
 | 
			
		||||
			   Strange_Op_LF,Strange_Op_L,
 | 
			
		||||
			   Strange_LinOp_LF,Strange_LinOp_L);
 | 
			
		||||
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MxPCG_EOFA DerivativeCGL2(DerivativeStoppingCondition,
 | 
			
		||||
			   MX_inner,
 | 
			
		||||
			   MaxCGIterations,
 | 
			
		||||
			   UGrid_f,
 | 
			
		||||
			   FrbGridF,
 | 
			
		||||
			   Strange2_Op_LF,Strange2_Op_L,
 | 
			
		||||
			   Strange2_LinOp_LF,Strange2_LinOp_L);
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
  MxPCG_EOFA ActionCGR(ActionStoppingCondition,
 | 
			
		||||
		       MX_inner,
 | 
			
		||||
		       MaxCGIterations,
 | 
			
		||||
		       UGrid_f,
 | 
			
		||||
		       FrbGridF,
 | 
			
		||||
		       Strange_Op_RF,Strange_Op_R,
 | 
			
		||||
		       Strange_LinOp_RF,Strange_LinOp_R);
 | 
			
		||||
  
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MxPCG_EOFA ActionCGR2(ActionStoppingCondition,
 | 
			
		||||
		       MX_inner,
 | 
			
		||||
		       MaxCGIterations,
 | 
			
		||||
		       UGrid_f,
 | 
			
		||||
		       FrbGridF,
 | 
			
		||||
		       Strange2_Op_RF,Strange2_Op_R,
 | 
			
		||||
		       Strange2_LinOp_RF,Strange2_LinOp_R);
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
  MxPCG_EOFA DerivativeCGR(DerivativeStoppingCondition,
 | 
			
		||||
			   MX_inner,
 | 
			
		||||
			   MaxCGIterations,
 | 
			
		||||
			   UGrid_f,
 | 
			
		||||
			   FrbGridF,
 | 
			
		||||
			   Strange_Op_RF,Strange_Op_R,
 | 
			
		||||
			   Strange_LinOp_RF,Strange_LinOp_R);
 | 
			
		||||
  
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MxPCG_EOFA DerivativeCGR2(DerivativeStoppingCondition,
 | 
			
		||||
			   MX_inner,
 | 
			
		||||
			   MaxCGIterations,
 | 
			
		||||
			   UGrid_f,
 | 
			
		||||
			   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-8;
 | 
			
		||||
 | 
			
		||||
    DenominatorsF.push_back(new FermionActionF(UF,*FGridF,*FrbGridF,*UGrid_f,*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,
 | 
			
		||||
			     UGrid_f,
 | 
			
		||||
			     FrbGridF,
 | 
			
		||||
			     *DenominatorsF[h],*Denominators[h],
 | 
			
		||||
			     *LinOpF[h], *LinOpD[h]) );
 | 
			
		||||
 | 
			
		||||
    ActionMPCG.push_back(new MxPCG(ActionStoppingCondition,
 | 
			
		||||
				   MX_inner,
 | 
			
		||||
				   MaxCGIterations,
 | 
			
		||||
				   UGrid_f,
 | 
			
		||||
				   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
 | 
			
		||||
 | 
			
		||||
  NoSmearing<HMCWrapper::ImplPolicy> S;
 | 
			
		||||
#ifndef DO_IMPLICIT
 | 
			
		||||
  TrivialMetric<HMCWrapper::ImplPolicy::Field> Mtr;
 | 
			
		||||
#else
 | 
			
		||||
    LaplacianRatParams gpar(2),mpar(2);
 | 
			
		||||
    gpar.offset = 1.;
 | 
			
		||||
    gpar.a0[0] = 500.;
 | 
			
		||||
    gpar.a1[0] = 0.;
 | 
			
		||||
    gpar.b0[0] = 0.25;
 | 
			
		||||
    gpar.b1[0] = 1.;
 | 
			
		||||
    gpar.a0[1] = -500.;
 | 
			
		||||
    gpar.a1[1] = 0.;
 | 
			
		||||
    gpar.b0[1] = 0.36;
 | 
			
		||||
    gpar.b1[1] = 1.2;
 | 
			
		||||
    gpar.b2=1.;
 | 
			
		||||
 | 
			
		||||
    mpar.offset = 1.;
 | 
			
		||||
    mpar.a0[0] =  -0.850891906532;
 | 
			
		||||
    mpar.a1[0] = -1.54707654538;
 | 
			
		||||
    mpar. b0[0] = 2.85557166137;
 | 
			
		||||
    mpar. b1[0] = 5.74194794773;
 | 
			
		||||
    mpar.a0[1] = -13.5120056831218384729709214298;
 | 
			
		||||
    mpar.a1[1] = 1.54707654538396877086370295729;
 | 
			
		||||
    mpar.b0[1] = 19.2921090880640520026645390317;
 | 
			
		||||
    mpar.b1[1] = -3.54194794773029020262811172870;
 | 
			
		||||
    mpar.b2=1.;
 | 
			
		||||
    for(int i=0;i<2;i++){
 | 
			
		||||
       gpar.a1[i] *=16.;
 | 
			
		||||
       gpar.b1[i] *=16.;
 | 
			
		||||
       mpar.a1[i] *=16.;
 | 
			
		||||
       mpar.b1[i] *=16.;
 | 
			
		||||
    }
 | 
			
		||||
    gpar.b2 *= 16.*16.;
 | 
			
		||||
    mpar.b2 *= 16.*16.;
 | 
			
		||||
 | 
			
		||||
    ConjugateGradient<LatticeGaugeField> CG(1.0e-8,10000);
 | 
			
		||||
    LaplacianParams LapPar(0.0001, 1.0, 10000, 1e-8, 12, 64);
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "LaplacianRat " << std::endl;
 | 
			
		||||
    gpar.tolerance=HMCparams.MD.RMHMCCGTol;
 | 
			
		||||
    mpar.tolerance=HMCparams.MD.RMHMCCGTol;
 | 
			
		||||
    std::cout << GridLogMessage << "gpar offset= " << gpar.offset <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a0= " << gpar.a0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a1= " << gpar.a1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b0= " << gpar.b0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b1= " << gpar.b1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b2= " << gpar.b2 <<std::endl ;;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "mpar offset= " << mpar.offset <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a0= " << mpar.a0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a1= " << mpar.a1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b0= " << mpar.b0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b1= " << mpar.b1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b2= " << mpar.b2 <<std::endl;
 | 
			
		||||
//  Assumes PeriodicGimplR or D at the moment
 | 
			
		||||
    auto UGrid = TheHMC.Resources.GetCartesian("gauge");
 | 
			
		||||
//    auto UGrid_f   = GridPtrF;
 | 
			
		||||
//  auto GridPtrF   = SpaceTimeGrid::makeFourDimGrid(latt,simdF,mpi);
 | 
			
		||||
//    std::cout << GridLogMessage << " UGrid= " << UGrid <<std::endl;
 | 
			
		||||
//    std::cout << GridLogMessage << " UGrid_f= " << UGrid_f <<std::endl;
 | 
			
		||||
 | 
			
		||||
    LaplacianAdjointRat<HMCWrapper::ImplPolicy, PeriodicGimplF> Mtr(UGrid, UGrid_f ,CG, gpar, mpar);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  std::cout << GridLogMessage << " Running the HMC "<< std::endl;
 | 
			
		||||
  TheHMC.Run(S,Mtr);  // no smearing
 | 
			
		||||
 | 
			
		||||
  Grid_finalize();
 | 
			
		||||
} // main
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -365,9 +365,15 @@ public:
 | 
			
		||||
    GridParallelRNG          RNG5(FGrid);  RNG5.SeedFixedIntegers(seeds5);
 | 
			
		||||
    std::cout << GridLogMessage << "Initialised RNGs" << std::endl;
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
    typedef DomainWallFermionF Action;
 | 
			
		||||
    typedef typename Action::FermionField Fermion;
 | 
			
		||||
    typedef LatticeGaugeFieldF Gauge;
 | 
			
		||||
#else
 | 
			
		||||
    typedef GparityDomainWallFermionF Action;
 | 
			
		||||
    typedef typename Action::FermionField Fermion;
 | 
			
		||||
    typedef LatticeGaugeFieldF Gauge;
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    ///////// Source preparation ////////////
 | 
			
		||||
    Gauge Umu(UGrid);  SU<Nc>::HotConfiguration(RNG4,Umu); 
 | 
			
		||||
@@ -635,6 +641,170 @@ public:
 | 
			
		||||
    std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
    return mflops_best;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static double Laplace(int L)
 | 
			
		||||
  {
 | 
			
		||||
    double mflops;
 | 
			
		||||
    double mflops_best = 0;
 | 
			
		||||
    double mflops_worst= 0;
 | 
			
		||||
    std::vector<double> mflops_all;
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////
 | 
			
		||||
    // Set/Get the layout & grid size
 | 
			
		||||
    ///////////////////////////////////////////////////////
 | 
			
		||||
    int threads = GridThread::GetThreads();
 | 
			
		||||
    Coordinate mpi = GridDefaultMpi(); assert(mpi.size()==4);
 | 
			
		||||
    Coordinate local({L,L,L,L});
 | 
			
		||||
    Coordinate latt4({local[0]*mpi[0],local[1]*mpi[1],local[2]*mpi[2],local[3]*mpi[3]});
 | 
			
		||||
    
 | 
			
		||||
    GridCartesian         * TmpGrid   = SpaceTimeGrid::makeFourDimGrid(latt4,
 | 
			
		||||
								       GridDefaultSimd(Nd,vComplex::Nsimd()),
 | 
			
		||||
								       GridDefaultMpi());
 | 
			
		||||
    uint64_t NP = TmpGrid->RankCount();
 | 
			
		||||
    uint64_t NN = TmpGrid->NodeCount();
 | 
			
		||||
    NN_global=NN;
 | 
			
		||||
    uint64_t SHM=NP/NN;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    ///////// Welcome message ////////////
 | 
			
		||||
    std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "Benchmark Laplace on "<<L<<"^4 local volume "<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* Global volume  : "<<GridCmdVectorIntToString(latt4)<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* ranks          : "<<NP  <<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* nodes          : "<<NN  <<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* ranks/node     : "<<SHM <<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* ranks geom     : "<<GridCmdVectorIntToString(mpi)<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* Using "<<threads<<" threads"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
 | 
			
		||||
    ///////// Lattice Init ////////////
 | 
			
		||||
    GridCartesian         * FGrid   = SpaceTimeGrid::makeFourDimGrid(latt4, GridDefaultSimd(Nd,vComplexF::Nsimd()),GridDefaultMpi());
 | 
			
		||||
    GridRedBlackCartesian * FrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(FGrid);
 | 
			
		||||
    
 | 
			
		||||
    ///////// RNG Init ////////////
 | 
			
		||||
    std::vector<int> seeds4({1,2,3,4});
 | 
			
		||||
    GridParallelRNG          RNG4(FGrid);  RNG4.SeedFixedIntegers(seeds4);
 | 
			
		||||
    std::cout << GridLogMessage << "Initialised RNGs" << std::endl;
 | 
			
		||||
 | 
			
		||||
    RealD mass=0.1;
 | 
			
		||||
    RealD c1=9.0/8.0;
 | 
			
		||||
    RealD c2=-1.0/24.0;
 | 
			
		||||
    RealD u0=1.0;
 | 
			
		||||
 | 
			
		||||
//    typedef ImprovedStaggeredFermionF Action;
 | 
			
		||||
//    typedef typename Action::FermionField Fermion; 
 | 
			
		||||
    typedef LatticeGaugeFieldF Gauge;
 | 
			
		||||
    
 | 
			
		||||
    Gauge Umu(FGrid);  SU<Nc>::HotConfiguration(RNG4,Umu); 
 | 
			
		||||
 | 
			
		||||
//    typename Action::ImplParams params;
 | 
			
		||||
//    Action Ds(Umu,Umu,*FGrid,*FrbGrid,mass,c1,c2,u0,params);
 | 
			
		||||
 | 
			
		||||
//  PeriodicGimplF
 | 
			
		||||
    typedef typename PeriodicGimplF::LinkField GaugeLinkFieldF;
 | 
			
		||||
 | 
			
		||||
    ///////// Source preparation ////////////
 | 
			
		||||
    GaugeLinkFieldF src   (FGrid); random(RNG4,src);
 | 
			
		||||
//    GaugeLinkFieldF src_e (FrbGrid);
 | 
			
		||||
//    GaugeLinkFieldF src_o (FrbGrid);
 | 
			
		||||
//    GaugeLinkFieldF r_e   (FrbGrid);
 | 
			
		||||
//    GaugeLinkFieldF r_o   (FrbGrid);
 | 
			
		||||
    GaugeLinkFieldF r_eo  (FGrid);
 | 
			
		||||
  
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
 //     pickCheckerboard(Even,src_e,src);
 | 
			
		||||
 //     pickCheckerboard(Odd,src_o,src);
 | 
			
		||||
    
 | 
			
		||||
      const int num_cases = 1;
 | 
			
		||||
      std::string fmt("G/O/C  ");
 | 
			
		||||
      
 | 
			
		||||
      controls Cases [] = {
 | 
			
		||||
	{  StaggeredKernelsStatic::OptGeneric   ,  StaggeredKernelsStatic::CommsAndCompute  ,CartesianCommunicator::CommunicatorPolicyConcurrent  },
 | 
			
		||||
      }; 
 | 
			
		||||
 | 
			
		||||
      for(int c=0;c<num_cases;c++) {
 | 
			
		||||
        CovariantAdjointLaplacianStencil<PeriodicGimplF,typename PeriodicGimplF::LinkField> LapStencilF(FGrid);
 | 
			
		||||
        QuadLinearOperator<CovariantAdjointLaplacianStencil<PeriodicGimplF,typename PeriodicGimplF::LinkField>,PeriodicGimplF::LinkField> QuadOpF(LapStencilF,c2,c1,1.);
 | 
			
		||||
        LapStencilF.GaugeImport(Umu);
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	StaggeredKernelsStatic::Comms = Cases[c].CommsOverlap;
 | 
			
		||||
	StaggeredKernelsStatic::Opt   = Cases[c].Opt;
 | 
			
		||||
	CartesianCommunicator::SetCommunicatorPolicy(Cases[c].CommsAsynch);
 | 
			
		||||
      
 | 
			
		||||
	std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
	if ( StaggeredKernelsStatic::Opt == StaggeredKernelsStatic::OptGeneric   ) std::cout << GridLogMessage<< "* Using Stencil Nc Laplace" <<std::endl;
 | 
			
		||||
	if ( StaggeredKernelsStatic::Comms == StaggeredKernelsStatic::CommsAndCompute ) std::cout << GridLogMessage<< "* Using Overlapped Comms/Compute" <<std::endl;
 | 
			
		||||
	if ( StaggeredKernelsStatic::Comms == StaggeredKernelsStatic::CommsThenCompute) std::cout << GridLogMessage<< "* Using sequential Comms/Compute" <<std::endl;
 | 
			
		||||
	std::cout << GridLogMessage<< "* SINGLE precision "<<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
	
 | 
			
		||||
	int nwarm = 10;
 | 
			
		||||
	double t0=usecond();
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
	for(int i=0;i<nwarm;i++){
 | 
			
		||||
//	  Ds.DhopEO(src_o,r_e,DaggerNo);
 | 
			
		||||
          QuadOpF.HermOp(src,r_eo);
 | 
			
		||||
	}
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
	double t1=usecond();
 | 
			
		||||
	uint64_t ncall = 500;
 | 
			
		||||
 | 
			
		||||
	FGrid->Broadcast(0,&ncall,sizeof(ncall));
 | 
			
		||||
 | 
			
		||||
	//	std::cout << GridLogMessage << " Estimate " << ncall << " calls per second"<<std::endl;
 | 
			
		||||
 | 
			
		||||
	time_statistics timestat;
 | 
			
		||||
	std::vector<double> t_time(ncall);
 | 
			
		||||
	for(uint64_t i=0;i<ncall;i++){
 | 
			
		||||
	  t0=usecond();
 | 
			
		||||
//	  Ds.DhopEO(src_o,r_e,DaggerNo);
 | 
			
		||||
          QuadOpF.HermOp(src,r_eo);
 | 
			
		||||
	  t1=usecond();
 | 
			
		||||
	  t_time[i] = t1-t0;
 | 
			
		||||
	}
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
	
 | 
			
		||||
	double volume=1;  for(int mu=0;mu<Nd;mu++) volume=volume*latt4[mu];
 | 
			
		||||
//	double flops=(1146.0*volume)/2;
 | 
			
		||||
	double flops=(2*2*8*216.0*volume);
 | 
			
		||||
	double mf_hi, mf_lo, mf_err;
 | 
			
		||||
	
 | 
			
		||||
	timestat.statistics(t_time);
 | 
			
		||||
	mf_hi = flops/timestat.min;
 | 
			
		||||
	mf_lo = flops/timestat.max;
 | 
			
		||||
	mf_err= flops/timestat.min * timestat.err/timestat.mean;
 | 
			
		||||
 | 
			
		||||
	mflops = flops/timestat.mean;
 | 
			
		||||
	mflops_all.push_back(mflops);
 | 
			
		||||
	if ( mflops_best == 0   ) mflops_best = mflops;
 | 
			
		||||
	if ( mflops_worst== 0   ) mflops_worst= mflops;
 | 
			
		||||
	if ( mflops>mflops_best ) mflops_best = mflops;
 | 
			
		||||
	if ( mflops<mflops_worst) mflops_worst= mflops;
 | 
			
		||||
	
 | 
			
		||||
	std::cout<<GridLogMessage << std::fixed << std::setprecision(1)<<"Quad mflop/s =   "<< mflops << " ("<<mf_err<<") " << mf_lo<<"-"<<mf_hi <<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << std::fixed << std::setprecision(1)<<"Quad mflop/s per rank   "<< mflops/NP<<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << std::fixed << std::setprecision(1)<<"Quad mflop/s per node   "<< mflops/NN<<std::endl;
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
      
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
      std::cout<<GridLogMessage << L<<"^4  Quad Best  mflop/s        =   "<< mflops_best << " ; " << mflops_best/NN<<" per node " <<std::endl;
 | 
			
		||||
      std::cout<<GridLogMessage << L<<"^4  Quad Worst mflop/s        =   "<< mflops_worst<< " ; " << mflops_worst/NN<<" per node " <<std::endl;
 | 
			
		||||
      std::cout<<GridLogMessage <<fmt << std::endl;
 | 
			
		||||
      std::cout<<GridLogMessage ;
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
 | 
			
		||||
      for(int i=0;i<mflops_all.size();i++){
 | 
			
		||||
	std::cout<<mflops_all[i]/NN<<" ; " ;
 | 
			
		||||
      }
 | 
			
		||||
      std::cout<<std::endl;
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
    return mflops_best;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -662,6 +832,7 @@ int main (int argc, char ** argv)
 | 
			
		||||
  std::vector<double> wilson;
 | 
			
		||||
  std::vector<double> dwf4;
 | 
			
		||||
  std::vector<double> staggered;
 | 
			
		||||
  std::vector<double> lap;
 | 
			
		||||
 | 
			
		||||
  int Ls=1;
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
@@ -688,12 +859,20 @@ int main (int argc, char ** argv)
 | 
			
		||||
    staggered.push_back(result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << " Laplace QuadOp 4D " <<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
  for(int l=0;l<L_list.size();l++){
 | 
			
		||||
    double result = Benchmark::Laplace(L_list[l]) ;
 | 
			
		||||
    lap.push_back(result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << " Summary table Ls="<<Ls <<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << "L \t\t Wilson \t\t DWF4 \t\t Staggered" <<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << "L \t\t Wilson \t\t DWF4 \t\t Staggered \t\t Quad Laplace" <<std::endl;
 | 
			
		||||
  for(int l=0;l<L_list.size();l++){
 | 
			
		||||
    std::cout<<GridLogMessage << L_list[l] <<" \t\t "<< wilson[l]<<" \t\t "<<dwf4[l] << " \t\t "<< staggered[l]<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << L_list[l] <<" \t\t "<< wilson[l]<<" \t\t "<<dwf4[l] << " \t\t "<< staggered[l]<< " \t\t "<< lap[l]<< std::endl;
 | 
			
		||||
  }
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -83,8 +83,15 @@ int main(int argc, char **argv)
 | 
			
		||||
  // need wrappers of the fermionic classes 
 | 
			
		||||
  // that have a complex construction
 | 
			
		||||
  // standard
 | 
			
		||||
  RealD beta = 5.6 ;
 | 
			
		||||
  RealD beta = 6.6 ; 
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  WilsonGaugeActionR Waction(beta);
 | 
			
		||||
#else
 | 
			
		||||
  std::vector<Complex> boundaryG = {1,1,1,0};
 | 
			
		||||
  WilsonGaugeActionR::ImplParams ParamsG(boundaryG);
 | 
			
		||||
  WilsonGaugeActionR Waction(beta,ParamsG);
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
  ActionLevel<HMCWrapper::Field> Level1(1);
 | 
			
		||||
  Level1.push_back(&Waction);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										238
									
								
								tests/hmc/Test_hmc_WilsonGauge_Implicit.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								tests/hmc/Test_hmc_WilsonGauge_Implicit.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,238 @@
 | 
			
		||||
/*************************************************************************************
 | 
			
		||||
 | 
			
		||||
Grid physics library, www.github.com/paboyle/Grid
 | 
			
		||||
 | 
			
		||||
Source file: ./tests/Test_hmc_WilsonFermionGauge.cc
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2015
 | 
			
		||||
 | 
			
		||||
Author: Peter Boyle <pabobyle@ph.ed.ac.uk>
 | 
			
		||||
Author: neo <cossu@post.kek.jp>
 | 
			
		||||
Author: Guido Cossu <guido.cossu@ed.ac.uk>
 | 
			
		||||
 | 
			
		||||
This program is free software; you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License along
 | 
			
		||||
with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 | 
			
		||||
See the full license in the file "LICENSE" in the top level distribution
 | 
			
		||||
directory
 | 
			
		||||
*************************************************************************************/
 | 
			
		||||
/*  END LEGAL */
 | 
			
		||||
#include <Grid/Grid.h>
 | 
			
		||||
 | 
			
		||||
#undef USE_OBC
 | 
			
		||||
#define DO_IMPLICIT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) 
 | 
			
		||||
{
 | 
			
		||||
  using namespace Grid;
 | 
			
		||||
 | 
			
		||||
  Grid_init(&argc, &argv);
 | 
			
		||||
  GridLogLayout();
 | 
			
		||||
  
 | 
			
		||||
  std::string arg;
 | 
			
		||||
 
 | 
			
		||||
  HMCparameters HMCparams;
 | 
			
		||||
#if 1
 | 
			
		||||
  {
 | 
			
		||||
    XmlReader  HMCrd("HMCparameters.xml");
 | 
			
		||||
    read(HMCrd,"HMCparameters",HMCparams);
 | 
			
		||||
  }
 | 
			
		||||
#else
 | 
			
		||||
//IntegratorParameters MD;
 | 
			
		||||
  std::vector<int> steps(0);
 | 
			
		||||
  if( GridCmdOptionExists(argv,argv+argc,"--MDsteps") ){
 | 
			
		||||
    arg= GridCmdOptionPayload(argv,argv+argc,"--MDsteps");
 | 
			
		||||
    GridCmdOptionIntVector(arg,steps);
 | 
			
		||||
    assert(steps.size()==1);
 | 
			
		||||
  }
 | 
			
		||||
  MD.trajL   = 0.001*std::sqrt(2.);
 | 
			
		||||
  MD.MDsteps = 1;
 | 
			
		||||
  if (steps.size()>0) MD.MDsteps = steps[0];
 | 
			
		||||
  if( GridCmdOptionExists(argv,argv+argc,"--trajL") ){
 | 
			
		||||
    arg= GridCmdOptionPayload(argv,argv+argc,"--trajL");
 | 
			
		||||
    std::vector<int> traj(0);
 | 
			
		||||
    GridCmdOptionIntVector(arg,traj);
 | 
			
		||||
    assert(traj.size()==1);
 | 
			
		||||
    MD.trajL *= double(traj[0]);
 | 
			
		||||
  }
 | 
			
		||||
  MD.RMHMCTol=1e-8;
 | 
			
		||||
  MD.RMHMCCGTol=1e-8;
 | 
			
		||||
  std::cout << "RMHMCTol= "<<  MD.RMHMCTol<<" RMHMCCGTol= "<<MD.RMHMCCGTol<<std::endl;
 | 
			
		||||
 | 
			
		||||
  HMCparameters HMCparams;
 | 
			
		||||
  HMCparams.StartTrajectory  = 0;
 | 
			
		||||
  HMCparams.Trajectories     = 1;
 | 
			
		||||
  HMCparams.NoMetropolisUntil=  100;
 | 
			
		||||
  // "[HotStart, ColdStart, TepidStart, CheckpointStart]\n";
 | 
			
		||||
  HMCparams.StartingType     =std::string("ColdStart");
 | 
			
		||||
  HMCparams.Kappa=0.01; //checking against trivial. Pathetic.
 | 
			
		||||
  HMCparams.MD = MD;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   // Typedefs to simplify notation
 | 
			
		||||
#ifdef DO_IMPLICIT
 | 
			
		||||
  typedef GenericHMCRunner<ImplicitMinimumNorm2> HMCWrapper;  // Uses the default minimum norm
 | 
			
		||||
//  typedef GenericHMCRunner<ImplicitCampostrini> HMCWrapper;  // 4th order
 | 
			
		||||
  HMCparams.MD.name    = std::string("ImplicitMinimumNorm2");
 | 
			
		||||
#else
 | 
			
		||||
  typedef GenericHMCRunner<MinimumNorm2> HMCWrapper;  // Uses the default minimum norm
 | 
			
		||||
  HMCparams.MD.name    = std::string("MinimumNorm2");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Possibile to create the module by hand 
 | 
			
		||||
  // hardcoding parameters or using a Reader
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Checkpointer definition
 | 
			
		||||
  CheckpointerParameters CPparams;  
 | 
			
		||||
  CPparams.config_prefix = "ckpoint_lat";
 | 
			
		||||
  CPparams.rng_prefix = "ckpoint_rng";
 | 
			
		||||
  CPparams.saveInterval = 1;
 | 
			
		||||
  CPparams.format = "IEEE64BIG";
 | 
			
		||||
  
 | 
			
		||||
  HMCWrapper TheHMC(HMCparams);
 | 
			
		||||
  // Grid from the command line
 | 
			
		||||
  TheHMC.Resources.AddFourDimGrid("gauge");
 | 
			
		||||
  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;
 | 
			
		||||
  typedef TopologicalChargeMod<HMCWrapper::ImplPolicy> QObs;
 | 
			
		||||
  TheHMC.Resources.AddObservable<PlaqObs>();
 | 
			
		||||
  TopologyObsParameters TopParams;
 | 
			
		||||
  TopParams.interval = 1;
 | 
			
		||||
  TopParams.do_smearing = true;
 | 
			
		||||
//  TopParams.Smearing.steps = 1600;
 | 
			
		||||
//  TopParams.Smearing.step_size = 0.01;
 | 
			
		||||
  TopParams.Smearing.init_step_size = 0.01;
 | 
			
		||||
  TopParams.Smearing.meas_interval = 10;
 | 
			
		||||
  TopParams.Smearing.maxTau = 16.0; 
 | 
			
		||||
//  TheHMC.Resources.AddObservable<QObs>(TopParams);
 | 
			
		||||
  //////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////////////
 | 
			
		||||
  // Collect actions, here use more encapsulation
 | 
			
		||||
  // need wrappers of the fermionic classes 
 | 
			
		||||
  // that have a complex construction
 | 
			
		||||
  // standard
 | 
			
		||||
 | 
			
		||||
  RealD beta = 6.6;
 | 
			
		||||
  std::cout << "Wilson Gauge beta= " <<beta <<std::endl;
 | 
			
		||||
#ifndef USE_OBC
 | 
			
		||||
  WilsonGaugeActionR Waction(beta);
 | 
			
		||||
#else
 | 
			
		||||
  std::vector<Complex> boundaryG = {1,1,1,0};
 | 
			
		||||
  WilsonGaugeActionR::ImplParams ParamsG(boundaryG);
 | 
			
		||||
  WilsonGaugeActionR Waction(beta,ParamsG);
 | 
			
		||||
  std::cout << "boundaryG = " <<boundaryG  <<std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  ActionLevel<HMCWrapper::Field> Level1(1);
 | 
			
		||||
  Level1.push_back(&Waction);
 | 
			
		||||
  TheHMC.TheAction.push_back(Level1);
 | 
			
		||||
 | 
			
		||||
  TheHMC.ReadCommandLine(argc, argv); // these can be parameters from file
 | 
			
		||||
  std::cout << "trajL= " <<TheHMC.Parameters.MD.trajL <<" steps= "<<TheHMC.Parameters.MD.MDsteps << " integrator= "<<TheHMC.Parameters.MD.name<<std::endl;
 | 
			
		||||
 | 
			
		||||
  NoSmearing<HMCWrapper::ImplPolicy> S;
 | 
			
		||||
#ifndef DO_IMPLICIT
 | 
			
		||||
  TrivialMetric<HMCWrapper::ImplPolicy::Field> Mtr;
 | 
			
		||||
#else
 | 
			
		||||
// g_x3_2
 | 
			
		||||
    LaplacianRatParams gpar(2),mpar(2);
 | 
			
		||||
    gpar.offset = 1.;
 | 
			
		||||
    gpar.a0[0] = 500.;
 | 
			
		||||
    gpar.a1[0] = 0.;
 | 
			
		||||
    gpar.b0[0] = 0.25;
 | 
			
		||||
    gpar.b1[0] = 1.;
 | 
			
		||||
    gpar.a0[1] = -500.;
 | 
			
		||||
    gpar.a1[1] = 0.;
 | 
			
		||||
    gpar.b0[1] = 0.36;
 | 
			
		||||
    gpar.b1[1] = 1.2;
 | 
			
		||||
    gpar.b2=1.;
 | 
			
		||||
 | 
			
		||||
    mpar.offset = 1.;
 | 
			
		||||
    mpar.a0[0] =  -0.850891906532;
 | 
			
		||||
    mpar.a1[0] = -1.54707654538;
 | 
			
		||||
    mpar. b0[0] = 2.85557166137;
 | 
			
		||||
    mpar. b1[0] = 5.74194794773;
 | 
			
		||||
    mpar.a0[1] = -13.5120056831218384729709214298;
 | 
			
		||||
    mpar.a1[1] = 1.54707654538396877086370295729;
 | 
			
		||||
    mpar.b0[1] = 19.2921090880640520026645390317;
 | 
			
		||||
    mpar.b1[1] = -3.54194794773029020262811172870;
 | 
			
		||||
    mpar.b2=1.;
 | 
			
		||||
    for(int i=0;i<2;i++){
 | 
			
		||||
       gpar.a1[i] *=16.;
 | 
			
		||||
       gpar.b1[i] *=16.;
 | 
			
		||||
       mpar.a1[i] *=16.;
 | 
			
		||||
       mpar.b1[i] *=16.;
 | 
			
		||||
    }
 | 
			
		||||
    gpar.b2 *= 16.*16.;
 | 
			
		||||
    mpar.b2 *= 16.*16.;
 | 
			
		||||
 | 
			
		||||
    ConjugateGradient<LatticeGaugeField> CG(1.0e-8,10000);
 | 
			
		||||
    LaplacianParams LapPar(0.0001, 1.0, 10000, 1e-8, 12, 64);
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "LaplacianRat " << std::endl;
 | 
			
		||||
 | 
			
		||||
    gpar.tolerance=HMCparams.MD.RMHMCCGTol;
 | 
			
		||||
    mpar.tolerance=HMCparams.MD.RMHMCCGTol;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "gpar offset= " << gpar.offset <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a0= " << gpar.a0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a1= " << gpar.a1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b0= " << gpar.b0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b1= " << gpar.b1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b2= " << gpar.b2 <<std::endl ;;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "mpar offset= " << mpar.offset <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a0= " << mpar.a0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a1= " << mpar.a1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b0= " << mpar.b0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b1= " << mpar.b1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b2= " << mpar.b2 <<std::endl;
 | 
			
		||||
//  Assumes PeriodicGimplR or D at the moment
 | 
			
		||||
    Coordinate latt  = GridDefaultLatt();
 | 
			
		||||
    Coordinate mpi   = GridDefaultMpi();
 | 
			
		||||
    auto UGrid = TheHMC.Resources.GetCartesian("gauge");
 | 
			
		||||
    Coordinate simdF = GridDefaultSimd(Nd,vComplexF::Nsimd());
 | 
			
		||||
    auto UGrid_f   = SpaceTimeGrid::makeFourDimGrid(latt,simdF,mpi);
 | 
			
		||||
    std::cout << GridLogMessage << " UGrid= " << UGrid <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " UGrid_f= " << UGrid_f <<std::endl;
 | 
			
		||||
 | 
			
		||||
    LaplacianAdjointRat<HMCWrapper::ImplPolicy, PeriodicGimplF> Mtr(UGrid, UGrid_f,CG, gpar, mpar);
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
  {
 | 
			
		||||
    XmlWriter HMCwr("HMCparameters.xml.out");
 | 
			
		||||
    write(HMCwr,"HMCparameters",TheHMC.Parameters);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TheHMC.Run(S,Mtr);  // no smearing
 | 
			
		||||
 | 
			
		||||
  Grid_finalize();
 | 
			
		||||
 | 
			
		||||
} // main
 | 
			
		||||
		Reference in New Issue
	
	Block a user