29#ifndef QCD_PSEUDOFERMION_GENERAL_EVEN_ODD_RATIONAL_RATIO_H
30#define QCD_PSEUDOFERMION_GENERAL_EVEN_ODD_RATIONAL_RATIO_H
85 std::cout<<
GridLogMessage <<
"Generating degree "<< approx_degree<<
" approximation for x^(1/" << inv_pow <<
")"<<std::endl;
87 if(error > CG_tolerance)
88 std::cout<<
GridLogMessage <<
"WARNING: Remez approximation has a larger error " << error <<
" than the CG tolerance " << CG_tolerance <<
"! Try increasing the number of poles" << std::endl;
90 approx.
Init(remez, CG_tolerance,
false);
91 approx_inv.
Init(remez, CG_tolerance,
true);
103 msCG(schurOp,in, out);
108 msCG(schurOp,in, out_elems, out);
119 void SetTolerances(std::vector<RealD> action_tolerance,std::vector<RealD> md_tolerance)
122 assert( md_tolerance.size()==
ApproxPowerMD.tolerances.size());
174 PhiOdd (_NumOp.FermionRedBlackGrid()),
175 PhiEven(_NumOp.FermionRedBlackGrid()),
190 std::cout<<
GridLogMessage <<
"Using same rational approximations for MD as for action evaluation" << std::endl;
210 virtual std::string
action_name(){
return "GeneralEvenOddRatioRationalPseudoFermionAction";}
213 std::stringstream sstream;
223 return sstream.str();
231 FermionField eta(
NumOp.FermionGrid());
237 RealD scale = std::sqrt(0.5);
244 void refresh(
const GaugeField &
U,
const FermionField &eta) {
255 FermionField etaOdd (
NumOp.FermionRedBlackGrid());
256 FermionField etaEven(
NumOp.FermionRedBlackGrid());
257 FermionField tmp(
NumOp.FermionRedBlackGrid());
272 assert(
NumOp.ConstEE() == 1);
273 assert(
DenOp.ConstEE() == 1);
292 FermionField X(
NumOp.FermionRedBlackGrid());
293 FermionField Y(
NumOp.FermionRedBlackGrid());
300 std::cout<<
GridLogMessage <<
action_name() <<
" compute action: doing (M^dag M)^{-1/" << 2*
param.inv_pow <<
"} ( (V^dag V)^{1/" << 2*
param.inv_pow <<
"} Phi)" << std::endl;
305 auto grid =
NumOp.FermionGrid();
307 grid->Broadcast(0,r);
309 if (
param.BoundsCheckFreq != 0 && (r %
param.BoundsCheckFreq)==0 ) {
311 FermionField gauss(
NumOp.FermionRedBlackGrid());
358 virtual void deriv(
const GaugeField &
U,GaugeField & dSdU) {
363 std::vector<FermionField> MpvPhi_k (n_pv,
NumOp.FermionRedBlackGrid());
364 std::vector<FermionField> MpvMfMpvPhi_k(n_pv,
NumOp.FermionRedBlackGrid());
365 std::vector<FermionField> MfMpvPhi_k (n_f ,
NumOp.FermionRedBlackGrid());
367 FermionField MpvPhi(
NumOp.FermionRedBlackGrid());
368 FermionField MfMpvPhi(
NumOp.FermionRedBlackGrid());
369 FermionField MpvMfMpvPhi(
NumOp.FermionRedBlackGrid());
370 FermionField Y(
NumOp.FermionRedBlackGrid());
372 GaugeField tmp(
NumOp.GaugeGrid());
382 std::cout<<
GridLogMessage <<
action_name() <<
" deriv: doing (V^dag V)^{1/" << 2*
param.inv_pow <<
"} ( (M^dag M)^{-1/" <<
param.inv_pow <<
"} (V^dag V)^{1/" << 2*
param.inv_pow <<
"} Phi)" << std::endl;
403 for(
int k=0;k<n_f;k++){
405 MdagM.
Mpc(MfMpvPhi_k[k],Y);
406 MdagM.
MpcDagDeriv(tmp , MfMpvPhi_k[k], Y ); dSdU=dSdU+ak*tmp;
407 MdagM.
MpcDeriv(tmp , Y, MfMpvPhi_k[k] ); dSdU=dSdU+ak*tmp;
413 for(
int k=0;k<n_pv;k++){
417 VdagV.
Mpc(MpvPhi_k[k],Y);
418 VdagV.
MpcDagDeriv(tmp,MpvMfMpvPhi_k[k],Y); dSdU=dSdU+ak*tmp;
419 VdagV.
MpcDeriv (tmp,Y,MpvMfMpvPhi_k[k]); dSdU=dSdU+ak*tmp;
421 VdagV.
Mpc(MpvMfMpvPhi_k[k],Y);
422 VdagV.
MpcDeriv (tmp,Y, MpvPhi_k[k]); dSdU=dSdU+ak*tmp;
423 VdagV.
MpcDagDeriv(tmp,MpvPhi_k[k], Y); dSdU=dSdU+ak*tmp;
void InversePowerBoundsCheck(int inv_pow, int MaxIter, double tol, LinearOperatorBase< Field > &HermOp, Field &GaussNoise, MultiShiftFunction &ApproxNegPow)
void HighBoundCheck(LinearOperatorBase< Field > &HermOp, Field &Phi, RealD hi)
RealD norm2(const Lattice< vobj > &arg)
void gaussian(GridParallelRNG &rng, Lattice< vobj > &l)
void pickCheckerboard(int cb, Lattice< vobj > &half, const Lattice< vobj > &full)
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
#define NAMESPACE_BEGIN(A)
static INTERNAL_PRECISION U
Base class for all actions.
double generateApprox(int num_degree, int den_degree, unsigned long power_num, unsigned long power_den, int a_len, double *a_param, int *a_pow)
void refresh(const GaugeField &U, const FermionField &eta)
virtual std::string LogParameters()
Print the parameters of the action.
RationalActionParams Params
void SetTolerances(std::vector< RealD > action_tolerance, std::vector< RealD > md_tolerance)
FermionOperator< Impl > & NumOp
MultiShiftFunction ApproxPowerAction
MultiShiftFunction ApproxPowerMD
MultiShiftFunction ApproxNegHalfPowerMD
MultiShiftFunction ApproxNegPowerAction
virtual std::string action_name()
Report the name of the action.
virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionField &in, FermionField &out)
MultiShiftFunction ApproxHalfPowerAction
virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionField &in, std::vector< FermionField > &out_elems, FermionField &out)
virtual void ImportGauge(const GaugeField &U)
const FermionField & getPhiOdd() const
GeneralEvenOddRatioRationalPseudoFermionAction(FermionOperator< Impl > &_NumOp, FermionOperator< Impl > &_DenOp, const Params &p)
virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG &pRNG)
Refresh pseudofermion fields.
virtual RealD Sinitial(const GaugeField &U)
Get the action at the start of the trajectory.
virtual void deriv(const GaugeField &U, GaugeField &dSdU)
static constexpr bool Denominator
FermionOperator< Impl > & DenOp
MultiShiftFunction ApproxNegHalfPowerAction
static constexpr bool Numerator
MultiShiftFunction ApproxNegPowerMD
static void generateApprox(MultiShiftFunction &approx, MultiShiftFunction &approx_inv, int inv_pow, int approx_degree, double CG_tolerance, AlgRemez &remez)
MultiShiftFunction ApproxHalfPowerMD
virtual RealD S(const GaugeField &U)
Evaluate this action with the given gauge field.
void Init(AlgRemez &remez, double tol, bool inverse)
virtual void Mpc(const Field &in, Field &out)
void MpcDagDeriv(GaugeField &Force, const FermionField &U, const FermionField &V)
void MpcDeriv(GaugeField &Force, const FermionField &U, const FermionField &V)