mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-04 05:54:32 +00:00 
			
		
		
		
	Small change in the HMC interface.
Example of multiple levels in the WilsonFermion hmc test. Merge remote-tracking branch 'upstream/master' Conflicts: lib/qcd/hmc/HMC.h lib/qcd/hmc/integrators/Integrator.h lib/qcd/hmc/integrators/Integrator_algorithm.h tests/Test_simd.cc
This commit is contained in:
		@@ -7,14 +7,30 @@ template<class GaugeField>
 | 
			
		||||
class Action { 
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  virtual void  init(const GaugeField &U, GridParallelRNG& pRNG) = 0;
 | 
			
		||||
  virtual RealD S(const GaugeField &U)                           = 0;  // evaluate the action
 | 
			
		||||
  virtual void  deriv(const GaugeField &U,GaugeField & dSdU )    = 0;  // evaluate the action derivative
 | 
			
		||||
  //virtual void  refresh(const GaugeField & ) {}                ; 
 | 
			
		||||
  virtual void  init (const GaugeField &U, GridParallelRNG& pRNG) = 0;  // 
 | 
			
		||||
  virtual RealD S    (const GaugeField &U)                        = 0;  // evaluate the action
 | 
			
		||||
  virtual void  deriv(const GaugeField &U,GaugeField & dSdU )     = 0;  // evaluate the action derivative
 | 
			
		||||
  virtual void  refresh(const GaugeField & ) {};                        // Default to no-op for actions with no internal fields
 | 
			
		||||
  // Boundary conditions?
 | 
			
		||||
  // Heatbath?
 | 
			
		||||
  virtual ~Action() {};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Could derive PseudoFermion action with a PF field, FermionField, and a Grid; implement refresh
 | 
			
		||||
template<class GaugeField, class FermionField>
 | 
			
		||||
class PseudoFermionAction : public Action<GaugeField> {
 | 
			
		||||
 public:
 | 
			
		||||
  FermionField Phi;
 | 
			
		||||
  GridParallelRNG &pRNG;
 | 
			
		||||
  GridBase &Grid;
 | 
			
		||||
 | 
			
		||||
  PseudoFermionAction(GridBase &_Grid,GridParallelRNG &_pRNG) : Grid(_Grid), Phi(&_Grid), pRNG(_pRNG) {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  virtual void refresh(const GaugeField &gauge) {
 | 
			
		||||
    gaussian(Phi,pRNG);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
}}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -79,4 +79,10 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
#include <qcd/action/fermion/g5HermitianLinop.h>
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////
 | 
			
		||||
// Pseudo fermion combinations
 | 
			
		||||
////////////////////////////////////////
 | 
			
		||||
#include <qcd/action/pseudofermion/TwoFlavour.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -10,12 +10,12 @@ namespace Grid {
 | 
			
		||||
    void ContinuedFractionFermion5D::SetCoefficientsZolotarev(RealD zolo_hi,Approx::zolotarev_data *zdata)
 | 
			
		||||
    {
 | 
			
		||||
      // How to check Ls matches??
 | 
			
		||||
      //      std::cout << Ls << " Ls"<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->n  << " - n"<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->da << " -da "<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->db << " -db"<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->dn << " -dn"<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->dd << " -dd"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << Ls << " Ls"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->n  << " - n"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->da << " -da "<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->db << " -db"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->dn << " -dn"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->dd << " -dd"<<std::endl;
 | 
			
		||||
 | 
			
		||||
      assert(zdata->db==Ls);// Beta has Ls coeffs
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +55,7 @@ namespace Grid {
 | 
			
		||||
	See[s] = Aee[s] - 1.0/See[s-1];
 | 
			
		||||
      }
 | 
			
		||||
      for(int s=0;s<Ls;s++){
 | 
			
		||||
	std::cout <<"s = "<<s<<" Beta "<<Beta[s]<<" Aee "<<Aee[s] <<" See "<<See[s] <<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage <<"s = "<<s<<" Beta "<<Beta[s]<<" Aee "<<Aee[s] <<" See "<<See[s] <<std::endl;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ namespace Grid {
 | 
			
		||||
	Approx::zolotarev_data *zdata = Approx::higham(eps,this->Ls);// eps is ignored for higham
 | 
			
		||||
	assert(zdata->n==this->Ls);
 | 
			
		||||
	
 | 
			
		||||
	std::cout << "DomainWallFermion with Ls="<<Ls<<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << "DomainWallFermion with Ls="<<Ls<<std::endl;
 | 
			
		||||
	// Call base setter
 | 
			
		||||
	this->CayleyFermion5D::SetCoefficientsTanh(zdata,1.0,0.0);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,10 +39,27 @@ namespace Grid {
 | 
			
		||||
      virtual void Dhop  (const FermionField &in, FermionField &out,int dag)=0;
 | 
			
		||||
      virtual void DhopOE(const FermionField &in, FermionField &out,int dag)=0;
 | 
			
		||||
      virtual void DhopEO(const FermionField &in, FermionField &out,int dag)=0;
 | 
			
		||||
      virtual void DhopDir(const FermionField &in, FermionField &out,int dir,int disp)=0; // implemented by WilsonFermion and WilsonFermion5D
 | 
			
		||||
 | 
			
		||||
      virtual void  Mdiag(const FermionField &in, FermionField &out) { Mooee(in,out);};   // Same as Mooee applied to both CB's
 | 
			
		||||
      virtual void  Mdir (const FermionField &in, FermionField &out,int dir,int disp)=0;   // case by case Wilson, Clover, Cayley, ContFrac, PartFrac
 | 
			
		||||
      virtual void  DhopDir(const FermionField &in, FermionField &out,int dir,int disp)=0; // implemented by WilsonFermion and WilsonFermion5D
 | 
			
		||||
      // force terms; five routines; default to Dhop on diagonal
 | 
			
		||||
      virtual void MDeriv  (LatticeGaugeField &mat,const FermionField &U,const FermionField &V,int dag){DhopDeriv(mat,U,V,dag);};
 | 
			
		||||
      virtual void MoeDeriv(LatticeGaugeField &mat,const FermionField &U,const FermionField &V,int dag){DhopDerivOE(mat,U,V,dag);};
 | 
			
		||||
      virtual void MeoDeriv(LatticeGaugeField &mat,const FermionField &U,const FermionField &V,int dag){DhopDerivEO(mat,U,V,dag);};
 | 
			
		||||
      virtual void MooDeriv(LatticeGaugeField &mat,const FermionField &U,const FermionField &V,int dag){mat=zero;};
 | 
			
		||||
      virtual void MeeDeriv(LatticeGaugeField &mat,const FermionField &U,const FermionField &V,int dag){mat=zero;};
 | 
			
		||||
 | 
			
		||||
      virtual void DhopDeriv  (LatticeGaugeField &mat,const FermionField &U,const FermionField &V,int dag)=0;
 | 
			
		||||
      virtual void DhopDerivEO(LatticeGaugeField &mat,const FermionField &U,const FermionField &V,int dag)=0;
 | 
			
		||||
      virtual void DhopDerivOE(LatticeGaugeField &mat,const FermionField &U,const FermionField &V,int dag)=0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      virtual void  Mdiag  (const FermionField &in, FermionField &out) { Mooee(in,out);};   // Same as Mooee applied to both CB's
 | 
			
		||||
      virtual void  Mdir   (const FermionField &in, FermionField &out,int dir,int disp)=0;   // case by case Wilson, Clover, Cayley, ContFrac, PartFrac
 | 
			
		||||
 | 
			
		||||
      ///////////////////////////////////////////////
 | 
			
		||||
      // Updates gauge field during HMC
 | 
			
		||||
      ///////////////////////////////////////////////
 | 
			
		||||
      virtual void ImportGauge(const GaugeField & _U);
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ namespace Grid {
 | 
			
		||||
      {
 | 
			
		||||
	RealD eps = 1.0;
 | 
			
		||||
 | 
			
		||||
	std::cout << "MobiusFermion (b="<<b<<",c="<<c<<") with Ls= "<<Ls<<" Tanh approx"<<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << "MobiusFermion (b="<<b<<",c="<<c<<") with Ls= "<<Ls<<" Tanh approx"<<std::endl;
 | 
			
		||||
	Approx::zolotarev_data *zdata = Approx::higham(eps,this->Ls);// eps is ignored for higham
 | 
			
		||||
	assert(zdata->n==this->Ls);
 | 
			
		||||
	
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ namespace Grid {
 | 
			
		||||
	Approx::zolotarev_data *zdata = Approx::zolotarev(eps,this->Ls,0);
 | 
			
		||||
	assert(zdata->n==this->Ls);
 | 
			
		||||
 | 
			
		||||
	std::cout << "MobiusZolotarevFermion (b="<<b<<",c="<<c<<") with Ls= "<<Ls<<" Zolotarev range ["<<lo<<","<<hi<<"]"<<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << "MobiusZolotarevFermion (b="<<b<<",c="<<c<<") with Ls= "<<Ls<<" Zolotarev range ["<<lo<<","<<hi<<"]"<<std::endl;
 | 
			
		||||
	
 | 
			
		||||
	// Call base setter
 | 
			
		||||
	this->CayleyFermion5D::SetCoefficientsZolotarev(hi,zdata,b,c);
 | 
			
		||||
 
 | 
			
		||||
@@ -260,12 +260,12 @@ namespace Grid {
 | 
			
		||||
    void  PartialFractionFermion5D::SetCoefficientsZolotarev(RealD zolo_hi,Approx::zolotarev_data *zdata){
 | 
			
		||||
 | 
			
		||||
      // check on degree matching
 | 
			
		||||
      //      std::cout << Ls << " Ls"<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->n  << " - n"<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->da << " -da "<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->db << " -db"<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->dn << " -dn"<<std::endl;
 | 
			
		||||
      //      std::cout << zdata->dd << " -dd"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << Ls << " Ls"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->n  << " - n"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->da << " -da "<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->db << " -db"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->dn << " -dn"<<std::endl;
 | 
			
		||||
      //      std::cout<<GridLogMessage << zdata->dd << " -dd"<<std::endl;
 | 
			
		||||
      assert(Ls == (2*zdata->da -1) );
 | 
			
		||||
 | 
			
		||||
      // Part frac
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,10 @@ WilsonFermion::WilsonFermion(LatticeGaugeField &_Umu,
 | 
			
		||||
{
 | 
			
		||||
  // Allocate the required comms buffer
 | 
			
		||||
  comm_buf.resize(Stencil._unified_buffer_size); // this is always big enough to contain EO
 | 
			
		||||
  ImportGauge(_Umu);
 | 
			
		||||
}
 | 
			
		||||
void WilsonFermion::ImportGauge(const LatticeGaugeField &_Umu)
 | 
			
		||||
{
 | 
			
		||||
  DoubleStore(Umu,_Umu);
 | 
			
		||||
  pickCheckerboard(Even,UmuEven,Umu);
 | 
			
		||||
  pickCheckerboard(Odd ,UmuOdd,Umu);
 | 
			
		||||
@@ -98,7 +102,9 @@ void WilsonFermion::Mdir (const LatticeFermion &in, LatticeFermion &out,int dir,
 | 
			
		||||
  DhopDir(in,out,dir,disp);
 | 
			
		||||
}
 | 
			
		||||
void WilsonFermion::DhopDir(const LatticeFermion &in, LatticeFermion &out,int dir,int disp){
 | 
			
		||||
 | 
			
		||||
  WilsonCompressor compressor(DaggerNo);
 | 
			
		||||
 | 
			
		||||
  Stencil.HaloExchange<vSpinColourVector,vHalfSpinColourVector,WilsonCompressor>(in,comm_buf,compressor);
 | 
			
		||||
  
 | 
			
		||||
  assert( (disp==1)||(disp==-1) );
 | 
			
		||||
@@ -109,9 +115,22 @@ void WilsonFermion::DhopDir(const LatticeFermion &in, LatticeFermion &out,int di
 | 
			
		||||
 | 
			
		||||
PARALLEL_FOR_LOOP
 | 
			
		||||
  for(int sss=0;sss<in._grid->oSites();sss++){
 | 
			
		||||
    DiracOptDhopDir(Stencil,Umu,comm_buf,sss,sss,in,out,dirdisp);
 | 
			
		||||
    DiracOptDhopDir(Stencil,Umu,comm_buf,sss,sss,in,out,dirdisp,dirdisp);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
};
 | 
			
		||||
void WilsonFermion::DhopDirDisp(const LatticeFermion &in, LatticeFermion &out,int dirdisp,int gamma,int dag)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  WilsonCompressor compressor(dag);
 | 
			
		||||
 | 
			
		||||
  Stencil.HaloExchange<vSpinColourVector,vHalfSpinColourVector,WilsonCompressor>(in,comm_buf,compressor);
 | 
			
		||||
 | 
			
		||||
PARALLEL_FOR_LOOP
 | 
			
		||||
  for(int sss=0;sss<in._grid->oSites();sss++){
 | 
			
		||||
    DiracOptDhopDir(Stencil,Umu,comm_buf,sss,sss,in,out,dirdisp,gamma);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void WilsonFermion::DhopInternal(CartesianStencil & st,LatticeDoubledGaugeField & U,
 | 
			
		||||
@@ -177,6 +196,77 @@ void WilsonFermion::Dhop(const LatticeFermion &in, LatticeFermion &out,int dag)
 | 
			
		||||
  DhopInternal(Stencil,Umu,in,out,dag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WilsonFermion::DerivInternal(CartesianStencil & st,LatticeDoubledGaugeField & U,
 | 
			
		||||
				  LatticeGaugeField &mat,const LatticeFermion &A,const LatticeFermion &B,int dag)
 | 
			
		||||
{
 | 
			
		||||
  assert((dag==DaggerNo) ||(dag==DaggerYes));
 | 
			
		||||
 | 
			
		||||
  WilsonCompressor compressor(dag);
 | 
			
		||||
 | 
			
		||||
  LatticeColourMatrix tmp(B._grid);
 | 
			
		||||
  LatticeFermion Btilde(B._grid);
 | 
			
		||||
 | 
			
		||||
  st.HaloExchange<vSpinColourVector,vHalfSpinColourVector,WilsonCompressor>(B,comm_buf,compressor);
 | 
			
		||||
  
 | 
			
		||||
  for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // Flip gamma (1+g)<->(1-g) if dag
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    int gamma = mu;
 | 
			
		||||
    if ( dag ) gamma+= Nd;
 | 
			
		||||
 | 
			
		||||
    ////////////////////////
 | 
			
		||||
    // Call the single hop
 | 
			
		||||
    ////////////////////////
 | 
			
		||||
PARALLEL_FOR_LOOP
 | 
			
		||||
    for(int sss=0;sss<B._grid->oSites();sss++){
 | 
			
		||||
      DiracOptDhopDir(st,U,comm_buf,sss,sss,B,Btilde,mu,gamma);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////////////////////////
 | 
			
		||||
    // spin trace outer product
 | 
			
		||||
    //////////////////////////////////////////////////
 | 
			
		||||
    tmp = TraceIndex<SpinIndex>(outerProduct(Btilde,A)); 
 | 
			
		||||
    PokeIndex<LorentzIndex>(mat,tmp,mu);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
void WilsonFermion::DhopDeriv(LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag)
 | 
			
		||||
{
 | 
			
		||||
  conformable(U._grid,_grid);  
 | 
			
		||||
  conformable(U._grid,V._grid);
 | 
			
		||||
  conformable(U._grid,mat._grid);
 | 
			
		||||
 | 
			
		||||
  mat.checkerboard = U.checkerboard;
 | 
			
		||||
 | 
			
		||||
  DerivInternal(Stencil,Umu,mat,U,V,dag);
 | 
			
		||||
}
 | 
			
		||||
void WilsonFermion::DhopDerivOE(LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag)
 | 
			
		||||
{
 | 
			
		||||
  conformable(U._grid,_cbgrid);  
 | 
			
		||||
  conformable(U._grid,V._grid);
 | 
			
		||||
  conformable(U._grid,mat._grid);
 | 
			
		||||
 | 
			
		||||
  assert(V.checkerboard==Even);
 | 
			
		||||
  assert(U.checkerboard==Odd);
 | 
			
		||||
  mat.checkerboard = Odd;
 | 
			
		||||
 | 
			
		||||
  DerivInternal(StencilEven,UmuOdd,mat,U,V,dag);
 | 
			
		||||
}
 | 
			
		||||
void WilsonFermion::DhopDerivEO(LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag)
 | 
			
		||||
{
 | 
			
		||||
  conformable(U._grid,_cbgrid);  
 | 
			
		||||
  conformable(U._grid,V._grid);
 | 
			
		||||
  conformable(U._grid,mat._grid);
 | 
			
		||||
 | 
			
		||||
  assert(V.checkerboard==Odd);
 | 
			
		||||
  assert(U.checkerboard==Even);
 | 
			
		||||
  mat.checkerboard = Even;
 | 
			
		||||
 | 
			
		||||
  DerivInternal(StencilOdd,UmuEven,mat,U,V,dag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,11 +24,95 @@ namespace Grid {
 | 
			
		||||
      // half checkerboard operaions
 | 
			
		||||
      void   Meooe       (const LatticeFermion &in, LatticeFermion &out);
 | 
			
		||||
      void   MeooeDag    (const LatticeFermion &in, LatticeFermion &out);
 | 
			
		||||
 | 
			
		||||
      virtual void   Mooee       (const LatticeFermion &in, LatticeFermion &out); // remain virtual so we 
 | 
			
		||||
      virtual void   MooeeDag    (const LatticeFermion &in, LatticeFermion &out); // can derive Clover
 | 
			
		||||
      virtual void   MooeeInv    (const LatticeFermion &in, LatticeFermion &out); // from Wilson base
 | 
			
		||||
      virtual void   MooeeInvDag (const LatticeFermion &in, LatticeFermion &out);
 | 
			
		||||
 | 
			
		||||
      ////////////////////////
 | 
			
		||||
      // 
 | 
			
		||||
      // Force term: d/dtau S = 0
 | 
			
		||||
      //
 | 
			
		||||
      // It is simplest to consider the two flavour force term 
 | 
			
		||||
      // 
 | 
			
		||||
      //       S[U,phi] = phidag (MdagM)^-1 phi
 | 
			
		||||
      //
 | 
			
		||||
      // But simplify even this to
 | 
			
		||||
      //
 | 
			
		||||
      //       S[U,phi] = phidag MdagM phi
 | 
			
		||||
      //
 | 
			
		||||
      // (other options exist depending on nature of action fragment.)
 | 
			
		||||
      // 
 | 
			
		||||
      // Require momentum be traceless anti-hermitian to move within group manifold [ P = i P^a T^a ]
 | 
			
		||||
      //
 | 
			
		||||
      // Define the HMC hamiltonian
 | 
			
		||||
      //
 | 
			
		||||
      //       H = 1/2 Tr P^2 + S(U,phi)
 | 
			
		||||
      // 
 | 
			
		||||
      // .
 | 
			
		||||
      // U =  P U    (lorentz & color indices multiplied)
 | 
			
		||||
      //
 | 
			
		||||
      // Hence
 | 
			
		||||
      //
 | 
			
		||||
      // .c    c  c       c
 | 
			
		||||
      // U =  U  P   = - U  P        (c == dagger)
 | 
			
		||||
      //
 | 
			
		||||
      // So, taking some liberty with implicit indices
 | 
			
		||||
      //                  .      .          .c      c
 | 
			
		||||
      // dH/dt = 0 = Tr P P +Tr[ U  dS/dU + U  dS/dU  ]
 | 
			
		||||
      //
 | 
			
		||||
      //                .                          c      c
 | 
			
		||||
      //           = Tr P P + i Tr[  P U dS/dU  - U   P dS/dU  ]
 | 
			
		||||
      //
 | 
			
		||||
      //                   .                        c  c
 | 
			
		||||
      //           = Tr P (P + i ( U dS/dU - P dS/dU  U ]
 | 
			
		||||
      //
 | 
			
		||||
      //              .                        c  c
 | 
			
		||||
      //           => P  = -i [ U dS/dU - dS/dU  U ]      generates HMC EoM
 | 
			
		||||
      //
 | 
			
		||||
      // Simple case work this out using S = phi^dag MdagM phi for wilson:
 | 
			
		||||
      //                               c       c
 | 
			
		||||
      // dSdt     = dU_xdt  dSdUx  + dUxdt dSdUx
 | 
			
		||||
      //          
 | 
			
		||||
      //         = Tr i P U_x [ (\phi^\dag)_x (1+g) (M \phi)_x+\mu   +(\phi^\dag M^\dag)_x (1-g) \phi_{x+\mu} ]
 | 
			
		||||
      //                 c
 | 
			
		||||
      //            - i U_x P [ (\phi^\dag)_x+mu (1-g) (M \phi)_x    +(\phi^\dag M^\dag)_(x+\mu) (1+g) \phi_{x} ]
 | 
			
		||||
      //
 | 
			
		||||
      //         = i [(\phi^\dag)_x      ]_j P_jk  [U_x(1+g) (M \phi)_x+\mu]_k        (1)
 | 
			
		||||
      //         + i [(\phi^\dagM^\dag)_x]_j P_jk  [U_x(1-g) (\phi)_x+\mu]_k          (2)
 | 
			
		||||
      //         - i [(\phi^\dag)_x+mu (1-g) U^dag_x]_j P_jk  [(M \phi)_xk            (3)
 | 
			
		||||
      //         - i [(\phi^\dagM^\dag)_x+mu (1+g) U^dag_x]_j P_jk  [ \phi]_xk        (4)
 | 
			
		||||
      //
 | 
			
		||||
      // Observe that (1)* = (4)
 | 
			
		||||
      //              (2)* = (3)
 | 
			
		||||
      //
 | 
			
		||||
      // Write as    .
 | 
			
		||||
      //             P_{kj}  = - i (  [U_x(1+g) (M \phi)_x+\mu] (x) [(\phi^\dag)_x] + [U_x(1-g) (\phi)_x+\mu] (x) [(\phi^\dagM^\dag)_x] - h.c )
 | 
			
		||||
      //
 | 
			
		||||
      // where (x) denotes outer product in colour and spins are traced.
 | 
			
		||||
      //
 | 
			
		||||
      // Need only evaluate (1) and (2)  [Chroma] or (2) and (4) [IroIro] and take the 
 | 
			
		||||
      // traceless anti hermitian part (of term in brackets w/o the "i")
 | 
			
		||||
      // 
 | 
			
		||||
      // Generalisation to S=phi^dag (MdagM)^{-1} phi is simple:
 | 
			
		||||
      //
 | 
			
		||||
      // For more complicated DWF etc... apply product rule in differentiation
 | 
			
		||||
      //
 | 
			
		||||
      ////////////////////////
 | 
			
		||||
      void DhopDeriv  (LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag);
 | 
			
		||||
      void DhopDerivEO(LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag);
 | 
			
		||||
      void DhopDerivOE(LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag);
 | 
			
		||||
 | 
			
		||||
      // Extra support internal
 | 
			
		||||
      void DerivInternal(CartesianStencil & st,
 | 
			
		||||
			 LatticeDoubledGaugeField & U,
 | 
			
		||||
			 LatticeGaugeField &mat,
 | 
			
		||||
			 const LatticeFermion &A,
 | 
			
		||||
			 const LatticeFermion &B,
 | 
			
		||||
			 int dag);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      // non-hermitian hopping term; half cb or both
 | 
			
		||||
      void Dhop  (const LatticeFermion &in, LatticeFermion &out,int dag);
 | 
			
		||||
      void DhopOE(const LatticeFermion &in, LatticeFermion &out,int dag);
 | 
			
		||||
@@ -37,6 +121,7 @@ namespace Grid {
 | 
			
		||||
      // Multigrid assistance
 | 
			
		||||
      void   Mdir (const LatticeFermion &in, LatticeFermion &out,int dir,int disp);
 | 
			
		||||
      void DhopDir(const LatticeFermion &in, LatticeFermion &out,int dir,int disp);
 | 
			
		||||
      void DhopDirDisp(const LatticeFermion &in, LatticeFermion &out,int dirdisp,int gamma,int dag);
 | 
			
		||||
 | 
			
		||||
      ///////////////////////////////////////////////////////////////
 | 
			
		||||
      // Extra methods added by derived
 | 
			
		||||
@@ -51,6 +136,7 @@ namespace Grid {
 | 
			
		||||
      WilsonFermion(LatticeGaugeField &_Umu,GridCartesian &Fgrid,GridRedBlackCartesian &Hgrid,RealD _mass);
 | 
			
		||||
 | 
			
		||||
      // DoubleStore
 | 
			
		||||
      virtual void ImportGauge(const LatticeGaugeField &_Umu);
 | 
			
		||||
      void DoubleStore(LatticeDoubledGaugeField &Uds,const LatticeGaugeField &Umu);
 | 
			
		||||
 | 
			
		||||
      ///////////////////////////////////////////////////////////////
 | 
			
		||||
@@ -59,7 +145,8 @@ namespace Grid {
 | 
			
		||||
      static int HandOptDslash; // these are a temporary hack
 | 
			
		||||
      static int MortonOrder;
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
      //    protected:
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
      RealD                        mass;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,10 @@ namespace QCD {
 | 
			
		||||
 | 
			
		||||
  // Allocate the required comms buffer
 | 
			
		||||
  comm_buf.resize(Stencil._unified_buffer_size); // this is always big enough to contain EO
 | 
			
		||||
  
 | 
			
		||||
  ImportGauge(_Umu);
 | 
			
		||||
}  
 | 
			
		||||
void WilsonFermion5D::ImportGauge(const LatticeGaugeField &_Umu)
 | 
			
		||||
{
 | 
			
		||||
  DoubleStore(Umu,_Umu);
 | 
			
		||||
  pickCheckerboard(Even,UmuEven,Umu);
 | 
			
		||||
  pickCheckerboard(Odd ,UmuOdd,Umu);
 | 
			
		||||
@@ -100,19 +103,111 @@ void WilsonFermion5D::DhopDir(const LatticeFermion &in, LatticeFermion &out,int
 | 
			
		||||
  assert(dirdisp<=7);
 | 
			
		||||
  assert(dirdisp>=0);
 | 
			
		||||
 | 
			
		||||
//PARALLEL_FOR_LOOP
 | 
			
		||||
PARALLEL_FOR_LOOP
 | 
			
		||||
  for(int ss=0;ss<Umu._grid->oSites();ss++){
 | 
			
		||||
    for(int s=0;s<Ls;s++){
 | 
			
		||||
      int sU=ss;
 | 
			
		||||
      int sF = s+Ls*sU; 
 | 
			
		||||
      DiracOptDhopDir(Stencil,Umu,comm_buf,sF,sU,in,out,dirdisp);
 | 
			
		||||
      DiracOptDhopDir(Stencil,Umu,comm_buf,sF,sU,in,out,dirdisp,dirdisp);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void WilsonFermion5D::DerivInternal(CartesianStencil & st,
 | 
			
		||||
				    LatticeDoubledGaugeField & U,
 | 
			
		||||
				    LatticeGaugeField &mat,
 | 
			
		||||
				    const LatticeFermion &A,
 | 
			
		||||
				    const LatticeFermion &B,
 | 
			
		||||
				    int dag)
 | 
			
		||||
{
 | 
			
		||||
  assert((dag==DaggerNo) ||(dag==DaggerYes));
 | 
			
		||||
 | 
			
		||||
  WilsonCompressor compressor(dag);
 | 
			
		||||
  
 | 
			
		||||
  LatticeColourMatrix tmp(B._grid);
 | 
			
		||||
  LatticeFermion Btilde(B._grid);
 | 
			
		||||
 | 
			
		||||
  st.HaloExchange<vSpinColourVector,vHalfSpinColourVector,WilsonCompressor>(B,comm_buf,compressor);
 | 
			
		||||
  
 | 
			
		||||
  for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // Flip gamma if dag
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    int gamma = mu;
 | 
			
		||||
    if ( dag ) gamma+= Nd;
 | 
			
		||||
 | 
			
		||||
    ////////////////////////
 | 
			
		||||
    // Call the single hop
 | 
			
		||||
    ////////////////////////
 | 
			
		||||
PARALLEL_FOR_LOOP
 | 
			
		||||
    for(int sss=0;sss<B._grid->oSites();sss++){
 | 
			
		||||
      for(int s=0;s<Ls;s++){
 | 
			
		||||
	int sU=sss;
 | 
			
		||||
	int sF = s+Ls*sU;
 | 
			
		||||
	DiracOptDhopDir(st,U,comm_buf,sF,sU,B,Btilde,mu,gamma);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ////////////////////////////
 | 
			
		||||
    // spin trace outer product
 | 
			
		||||
    ////////////////////////////
 | 
			
		||||
// FIXME : need to sum over fifth direction.
 | 
			
		||||
    tmp = TraceIndex<SpinIndex>(outerProduct(Btilde,A)); // ordering here
 | 
			
		||||
    PokeIndex<LorentzIndex>(mat,tmp,mu);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WilsonFermion5D::DhopDeriv(      LatticeGaugeField &mat,
 | 
			
		||||
				const LatticeFermion &A,
 | 
			
		||||
				const LatticeFermion &B,
 | 
			
		||||
				int dag)
 | 
			
		||||
{
 | 
			
		||||
  conformable(A._grid,FermionGrid());  
 | 
			
		||||
  conformable(A._grid,B._grid);
 | 
			
		||||
  conformable(GaugeGrid(),mat._grid);
 | 
			
		||||
 | 
			
		||||
  mat.checkerboard = A.checkerboard;
 | 
			
		||||
 | 
			
		||||
  DerivInternal(Stencil,Umu,mat,A,B,dag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WilsonFermion5D::DhopDerivEO(LatticeGaugeField &mat,
 | 
			
		||||
				  const LatticeFermion &A,
 | 
			
		||||
				  const LatticeFermion &B,
 | 
			
		||||
				  int dag)
 | 
			
		||||
{
 | 
			
		||||
  conformable(A._grid,FermionRedBlackGrid());
 | 
			
		||||
  conformable(GaugeRedBlackGrid(),mat._grid);
 | 
			
		||||
  conformable(A._grid,B._grid);
 | 
			
		||||
 | 
			
		||||
  assert(B.checkerboard==Odd);
 | 
			
		||||
  assert(A.checkerboard==Even);
 | 
			
		||||
  mat.checkerboard = Even;
 | 
			
		||||
 | 
			
		||||
  DerivInternal(StencilOdd,UmuEven,mat,A,B,dag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WilsonFermion5D::DhopDerivOE(LatticeGaugeField &mat,
 | 
			
		||||
				  const LatticeFermion &A,
 | 
			
		||||
				  const LatticeFermion &B,
 | 
			
		||||
				  int dag)
 | 
			
		||||
{
 | 
			
		||||
  conformable(A._grid,FermionRedBlackGrid());
 | 
			
		||||
  conformable(GaugeRedBlackGrid(),mat._grid);
 | 
			
		||||
  conformable(A._grid,B._grid);
 | 
			
		||||
 | 
			
		||||
  assert(B.checkerboard==Even);
 | 
			
		||||
  assert(A.checkerboard==Odd);
 | 
			
		||||
  mat.checkerboard = Odd;
 | 
			
		||||
 | 
			
		||||
  DerivInternal(StencilEven,UmuOdd,mat,A,B,dag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WilsonFermion5D::DhopInternal(CartesianStencil & st, LebesgueOrder &lo,
 | 
			
		||||
				   LatticeDoubledGaugeField & U,
 | 
			
		||||
			   const LatticeFermion &in, LatticeFermion &out,int dag)
 | 
			
		||||
				   const LatticeFermion &in, LatticeFermion &out,int dag)
 | 
			
		||||
{
 | 
			
		||||
  //  assert((dag==DaggerNo) ||(dag==DaggerYes));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -44,12 +44,18 @@ namespace Grid {
 | 
			
		||||
 | 
			
		||||
      // half checkerboard operations; leave unimplemented as abstract for now
 | 
			
		||||
      virtual void   Meooe       (const LatticeFermion &in, LatticeFermion &out){assert(0);};
 | 
			
		||||
      virtual void   MeooeDag    (const LatticeFermion &in, LatticeFermion &out){assert(0);};
 | 
			
		||||
      virtual void   Mooee       (const LatticeFermion &in, LatticeFermion &out){assert(0);};
 | 
			
		||||
      virtual void   MooeeDag    (const LatticeFermion &in, LatticeFermion &out){assert(0);};
 | 
			
		||||
      virtual void   MooeeInv    (const LatticeFermion &in, LatticeFermion &out){assert(0);};
 | 
			
		||||
 | 
			
		||||
      virtual void   MeooeDag    (const LatticeFermion &in, LatticeFermion &out){assert(0);};
 | 
			
		||||
      virtual void   MooeeDag    (const LatticeFermion &in, LatticeFermion &out){assert(0);};
 | 
			
		||||
      virtual void   MooeeInvDag (const LatticeFermion &in, LatticeFermion &out){assert(0);};
 | 
			
		||||
 | 
			
		||||
      // These can be overridden by fancy 5d chiral actions
 | 
			
		||||
      virtual void DhopDeriv  (LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag);
 | 
			
		||||
      virtual void DhopDerivEO(LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag);
 | 
			
		||||
      virtual void DhopDerivOE(LatticeGaugeField &mat,const LatticeFermion &U,const LatticeFermion &V,int dag);
 | 
			
		||||
 | 
			
		||||
      // Implement hopping term non-hermitian hopping term; half cb or both
 | 
			
		||||
      // Implement s-diagonal DW
 | 
			
		||||
      void DW    (const LatticeFermion &in, LatticeFermion &out,int dag);
 | 
			
		||||
@@ -64,6 +70,14 @@ namespace Grid {
 | 
			
		||||
      ///////////////////////////////////////////////////////////////
 | 
			
		||||
      // New methods added 
 | 
			
		||||
      ///////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
      void DerivInternal(CartesianStencil & st,
 | 
			
		||||
			 LatticeDoubledGaugeField & U,
 | 
			
		||||
			 LatticeGaugeField &mat,
 | 
			
		||||
			 const LatticeFermion &A,
 | 
			
		||||
			 const LatticeFermion &B,
 | 
			
		||||
			 int dag);
 | 
			
		||||
 | 
			
		||||
      void DhopInternal(CartesianStencil & st,
 | 
			
		||||
			LebesgueOrder &lo,
 | 
			
		||||
			LatticeDoubledGaugeField &U,
 | 
			
		||||
@@ -80,6 +94,7 @@ namespace Grid {
 | 
			
		||||
			  double _M5);
 | 
			
		||||
 | 
			
		||||
      // DoubleStore
 | 
			
		||||
      virtual void ImportGauge(const LatticeGaugeField &_Umu);
 | 
			
		||||
      void DoubleStore(LatticeDoubledGaugeField &Uds,const LatticeGaugeField &Umu);
 | 
			
		||||
 | 
			
		||||
      ///////////////////////////////////////////////////////////////
 | 
			
		||||
 
 | 
			
		||||
@@ -294,8 +294,8 @@ void DiracOptDhopSiteDag(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
			std::vector<vHalfSpinColourVector,alignedAllocator<vHalfSpinColourVector> >  &buf,
 | 
			
		||||
		       int sF,int sU,const LatticeFermion &in, LatticeFermion &out,int dirdisp)
 | 
			
		||||
		     std::vector<vHalfSpinColourVector,alignedAllocator<vHalfSpinColourVector> >  &buf,
 | 
			
		||||
		     int sF,int sU,const LatticeFermion &in, LatticeFermion &out,int dir,int gamma)
 | 
			
		||||
{
 | 
			
		||||
    vHalfSpinColourVector  tmp;    
 | 
			
		||||
    vHalfSpinColourVector  chi;    
 | 
			
		||||
@@ -304,13 +304,13 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
    int offset,local,perm, ptype;
 | 
			
		||||
    int ss=sF;
 | 
			
		||||
    
 | 
			
		||||
    offset = st._offsets [dirdisp][ss];
 | 
			
		||||
    local  = st._is_local[dirdisp][ss];
 | 
			
		||||
    perm   = st._permute[dirdisp][ss];
 | 
			
		||||
    ptype  = st._permute_type[dirdisp];
 | 
			
		||||
    offset = st._offsets [dir][ss];
 | 
			
		||||
    local  = st._is_local[dir][ss];
 | 
			
		||||
    perm   = st._permute[dir][ss];
 | 
			
		||||
    ptype  = st._permute_type[dir];
 | 
			
		||||
 | 
			
		||||
    // Xp
 | 
			
		||||
    if(dirdisp==Xp){
 | 
			
		||||
    if(gamma==Xp){
 | 
			
		||||
      if ( local && perm ) {
 | 
			
		||||
	spProjXp(tmp,in._odata[offset]);
 | 
			
		||||
	permute(chi,tmp,ptype);
 | 
			
		||||
@@ -319,12 +319,12 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
      } else { 
 | 
			
		||||
	chi=buf[offset];
 | 
			
		||||
      }
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](Xp),&chi());
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](dir),&chi());
 | 
			
		||||
      spReconXp(result,Uchi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Yp
 | 
			
		||||
    if ( dirdisp==Yp ){
 | 
			
		||||
    if ( gamma==Yp ){
 | 
			
		||||
      if ( local && perm ) {
 | 
			
		||||
	spProjYp(tmp,in._odata[offset]);
 | 
			
		||||
	permute(chi,tmp,ptype);
 | 
			
		||||
@@ -333,12 +333,12 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
      } else { 
 | 
			
		||||
	chi=buf[offset];
 | 
			
		||||
      }
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](Yp),&chi());
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](dir),&chi());
 | 
			
		||||
      spReconYp(result,Uchi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Zp
 | 
			
		||||
    if ( dirdisp ==Zp ){
 | 
			
		||||
    if ( gamma ==Zp ){
 | 
			
		||||
      if ( local && perm ) {
 | 
			
		||||
	spProjZp(tmp,in._odata[offset]);
 | 
			
		||||
	permute(chi,tmp,ptype);
 | 
			
		||||
@@ -347,12 +347,12 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
      } else { 
 | 
			
		||||
	chi=buf[offset];
 | 
			
		||||
      }
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](Zp),&chi());
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](dir),&chi());
 | 
			
		||||
      spReconZp(result,Uchi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Tp
 | 
			
		||||
    if ( dirdisp ==Tp ){
 | 
			
		||||
    if ( gamma ==Tp ){
 | 
			
		||||
      if ( local && perm ) {
 | 
			
		||||
	spProjTp(tmp,in._odata[offset]);
 | 
			
		||||
	permute(chi,tmp,ptype);
 | 
			
		||||
@@ -361,12 +361,12 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
      } else { 
 | 
			
		||||
	chi=buf[offset];
 | 
			
		||||
      }
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](Tp),&chi());
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](dir),&chi());
 | 
			
		||||
      spReconTp(result,Uchi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Xm
 | 
			
		||||
    if ( dirdisp==Xm ){
 | 
			
		||||
    if ( gamma==Xm ){
 | 
			
		||||
      if ( local && perm ) {
 | 
			
		||||
	spProjXm(tmp,in._odata[offset]);
 | 
			
		||||
	permute(chi,tmp,ptype);
 | 
			
		||||
@@ -375,12 +375,12 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
      } else { 
 | 
			
		||||
	chi=buf[offset];
 | 
			
		||||
      }
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](Xm),&chi());
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](dir),&chi());
 | 
			
		||||
      spReconXm(result,Uchi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Ym
 | 
			
		||||
    if ( dirdisp == Ym ){
 | 
			
		||||
    if ( gamma == Ym ){
 | 
			
		||||
      if ( local && perm ) {
 | 
			
		||||
	spProjYm(tmp,in._odata[offset]);
 | 
			
		||||
	permute(chi,tmp,ptype);
 | 
			
		||||
@@ -389,12 +389,12 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
      } else { 
 | 
			
		||||
	chi=buf[offset];
 | 
			
		||||
      }
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](Ym),&chi());
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](dir),&chi());
 | 
			
		||||
      spReconYm(result,Uchi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Zm
 | 
			
		||||
    if ( dirdisp == Zm ){
 | 
			
		||||
    if ( gamma == Zm ){
 | 
			
		||||
      if ( local && perm ) {
 | 
			
		||||
	spProjZm(tmp,in._odata[offset]);
 | 
			
		||||
	permute(chi,tmp,ptype);
 | 
			
		||||
@@ -403,12 +403,12 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
      } else { 
 | 
			
		||||
	chi=buf[offset];
 | 
			
		||||
      }
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](Zm),&chi());
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](dir),&chi());
 | 
			
		||||
      spReconZm(result,Uchi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Tm
 | 
			
		||||
    if ( dirdisp==Tm ) {
 | 
			
		||||
    if ( gamma==Tm ) {
 | 
			
		||||
      if ( local && perm ) {
 | 
			
		||||
	spProjTm(tmp,in._odata[offset]);
 | 
			
		||||
	permute(chi,tmp,ptype);
 | 
			
		||||
@@ -417,7 +417,7 @@ void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
      } else { 
 | 
			
		||||
	chi=buf[offset];
 | 
			
		||||
      }
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](Tm),&chi());
 | 
			
		||||
      mult(&Uchi(),&U._odata[sU](dir),&chi());
 | 
			
		||||
      spReconTm(result,Uchi);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ namespace Grid {
 | 
			
		||||
			       int sF,int sU,const LatticeFermion &in, LatticeFermion &out);
 | 
			
		||||
      void DiracOptDhopDir(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
			   std::vector<vHalfSpinColourVector,alignedAllocator<vHalfSpinColourVector> >  &buf,
 | 
			
		||||
			   int sF,int sU,const LatticeFermion &in, LatticeFermion &out,int dirdisp);
 | 
			
		||||
			   int sF,int sU,const LatticeFermion &in, LatticeFermion &out,int dirdisp,int gamma);
 | 
			
		||||
      
 | 
			
		||||
      //  };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -360,11 +360,11 @@ void DiracOptHandDhopSite(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
    MULT_2SPIN(Xp);
 | 
			
		||||
  }
 | 
			
		||||
  XP_RECON;
 | 
			
		||||
  //  std::cout << "XP_RECON"<<std::endl;
 | 
			
		||||
  //  std::cout << result_00 <<" "<<result_01 <<" "<<result_02 <<std::endl;
 | 
			
		||||
  //  std::cout << result_10 <<" "<<result_11 <<" "<<result_12 <<std::endl;
 | 
			
		||||
  //  std::cout << result_20 <<" "<<result_21 <<" "<<result_22 <<std::endl;
 | 
			
		||||
  //  std::cout << result_30 <<" "<<result_31 <<" "<<result_32 <<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << "XP_RECON"<<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << result_00 <<" "<<result_01 <<" "<<result_02 <<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << result_10 <<" "<<result_11 <<" "<<result_12 <<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << result_20 <<" "<<result_21 <<" "<<result_22 <<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << result_30 <<" "<<result_31 <<" "<<result_32 <<std::endl;
 | 
			
		||||
 | 
			
		||||
  // Yp
 | 
			
		||||
  offset = st._offsets [Yp][ss];
 | 
			
		||||
@@ -446,11 +446,11 @@ void DiracOptHandDhopSite(CartesianStencil &st,LatticeDoubledGaugeField &U,
 | 
			
		||||
    MULT_2SPIN(Xm);
 | 
			
		||||
  }
 | 
			
		||||
  XM_RECON_ACCUM;
 | 
			
		||||
  //  std::cout << "XM_RECON_ACCUM"<<std::endl;
 | 
			
		||||
  //  std::cout << result_00 <<" "<<result_01 <<" "<<result_02 <<std::endl;
 | 
			
		||||
  //  std::cout << result_10 <<" "<<result_11 <<" "<<result_12 <<std::endl;
 | 
			
		||||
  //  std::cout << result_20 <<" "<<result_21 <<" "<<result_22 <<std::endl;
 | 
			
		||||
  //  std::cout << result_30 <<" "<<result_31 <<" "<<result_32 <<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << "XM_RECON_ACCUM"<<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << result_00 <<" "<<result_01 <<" "<<result_02 <<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << result_10 <<" "<<result_11 <<" "<<result_12 <<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << result_20 <<" "<<result_21 <<" "<<result_22 <<std::endl;
 | 
			
		||||
  //  std::cout<<GridLogMessage << result_30 <<" "<<result_31 <<" "<<result_32 <<std::endl;
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  // Ym
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,11 @@ namespace Grid{
 | 
			
		||||
      
 | 
			
		||||
      virtual RealD S(const GaugeField &U) {
 | 
			
		||||
	RealD plaq = WilsonLoops<MatrixField,GaugeField>::avgPlaquette(U);
 | 
			
		||||
	std::cout << "Plaq : "<<plaq << "\n";
 | 
			
		||||
	double vol = U._grid->gSites();
 | 
			
		||||
	return beta*(1.0 -plaq)*(Nd*(Nd-1.0))*vol*0.5;
 | 
			
		||||
	std::cout<<GridLogMessage << "Plaq : "<<plaq << "\n";
 | 
			
		||||
	RealD vol = U._grid->gSites();
 | 
			
		||||
	RealD action=beta*(1.0 -plaq)*(Nd*(Nd-1.0))*vol*0.5;
 | 
			
		||||
	std::cout << GridLogMessage << "WilsonGauge action "<<action<<std::endl;
 | 
			
		||||
	return action;
 | 
			
		||||
      };
 | 
			
		||||
      virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
 | 
			
		||||
	//not optimal implementation FIXME
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										209
									
								
								lib/qcd/action/pseudofermion/TwoFlavour.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								lib/qcd/action/pseudofermion/TwoFlavour.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,209 @@
 | 
			
		||||
#ifndef QCD_PSEUDOFERMION_TWO_FLAVOUR_H
 | 
			
		||||
#define QCD_PSEUDOFERMION_TWO_FLAVOUR_H
 | 
			
		||||
 | 
			
		||||
namespace Grid{
 | 
			
		||||
  namespace QCD{
 | 
			
		||||
 | 
			
		||||
    // Placeholder comments:
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////
 | 
			
		||||
    // Two flavour ratio
 | 
			
		||||
    ///////////////////////////////////////
 | 
			
		||||
    // S = phi^dag V (Mdag M)^-1 V^dag  phi
 | 
			
		||||
    // dS/du = phi^dag dV (Mdag M)^-1 V^dag  phi
 | 
			
		||||
    //       - phi^dag V (Mdag M)^-1 [ Mdag dM + dMdag M ]  (Mdag M)^-1 V^dag  phi
 | 
			
		||||
    //       + phi^dag V (Mdag M)^-1 dV^dag  phi
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////
 | 
			
		||||
    // One flavour rational
 | 
			
		||||
    ///////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    // S_f = chi^dag *  N(M^dag*M)/D(M^dag*M) * chi
 | 
			
		||||
    //
 | 
			
		||||
    // Here, M is some operator 
 | 
			
		||||
    // N and D makeup the rat. poly 
 | 
			
		||||
    //
 | 
			
		||||
    // Need
 | 
			
		||||
    // dS_f/dU = chi^dag   P/Q d[N/D]  P/Q  chi
 | 
			
		||||
    //
 | 
			
		||||
    // Here N/D \sim R_{-1/2} ~ (M^dagM)^{-1/2}
 | 
			
		||||
    //
 | 
			
		||||
    // N/D is expressed as partial fraction expansion:
 | 
			
		||||
    //
 | 
			
		||||
    //           a0 + \sum_k ak/(M^dagM + bk)
 | 
			
		||||
    //
 | 
			
		||||
    // d[N/D] is then
 | 
			
		||||
    //
 | 
			
		||||
    //          \sum_k -ak [M^dagM+bk]^{-1}  [ dM^dag M + M^dag dM ] [M^dag M + bk]^{-1}
 | 
			
		||||
    //
 | 
			
		||||
    // Need
 | 
			
		||||
    //
 | 
			
		||||
    //       Mf Phi_k = [MdagM+bk]^{-1} Phi
 | 
			
		||||
    //       Mf Phi   = \sum_k ak [MdagM+bk]^{-1} Phi
 | 
			
		||||
    //
 | 
			
		||||
    // With these building blocks
 | 
			
		||||
    //
 | 
			
		||||
    //       dS/dU =  \sum_k -ak Mf Phi_k^dag      [ dM^dag M + M^dag dM ] Mf Phi_k
 | 
			
		||||
    //        S    = innerprodReal(Phi,Mf Phi);
 | 
			
		||||
    
 | 
			
		||||
    ///////////////////////////////////////
 | 
			
		||||
    // One flavour rational ratio
 | 
			
		||||
    ///////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    // S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi
 | 
			
		||||
    //
 | 
			
		||||
    // Here, M is some 5D operator and V is the Pauli-Villars field
 | 
			
		||||
    // N and D makeup the rat. poly of the M term and P and & makeup the rat.poly of the denom term
 | 
			
		||||
    //
 | 
			
		||||
    // Need
 | 
			
		||||
    // dS_f/dU =  chi^dag d[P/Q]  N/D   P/Q  chi
 | 
			
		||||
    //         +  chi^dag   P/Q d[N/D]  P/Q  chi
 | 
			
		||||
    //         +  chi^dag   P/Q   N/D d[P/Q] chi
 | 
			
		||||
    //
 | 
			
		||||
    // Here P/Q \sim R_{1/4}  ~ (V^dagV)^{1/4}
 | 
			
		||||
    // Here N/D \sim R_{-1/2} ~ (M^dagM)^{-1/2}
 | 
			
		||||
    //
 | 
			
		||||
    // P/Q is expressed as partial fraction expansion:
 | 
			
		||||
    //
 | 
			
		||||
    //           a0 + \sum_k ak/(V^dagV + bk)
 | 
			
		||||
    //
 | 
			
		||||
    // d[P/Q] is then
 | 
			
		||||
    //
 | 
			
		||||
    //          \sum_k -ak [V^dagV+bk]^{-1}  [ dV^dag V + V^dag dV ] [V^dag V + bk]^{-1}
 | 
			
		||||
    //
 | 
			
		||||
    // and similar for N/D.
 | 
			
		||||
    // 
 | 
			
		||||
    // Need
 | 
			
		||||
    //       MpvPhi_k   = [Vdag V + bk]^{-1} chi
 | 
			
		||||
    //
 | 
			
		||||
    //       MpvPhi     = {a0 +  \sum_k ak [Vdag V + bk]^{-1} }chi
 | 
			
		||||
    //
 | 
			
		||||
    //       MfMpvPhi_k = [MdagM+bk]^{-1} MpvPhi
 | 
			
		||||
    //      
 | 
			
		||||
    //       MfMpvPhi   = {a0 +  \sum_k ak [Mdag M + bk]^{-1} } MpvPhi
 | 
			
		||||
    //
 | 
			
		||||
    //       MpvMfMpvPhi_k = [Vdag V + bk]^{-1} MfMpvchi
 | 
			
		||||
    //
 | 
			
		||||
    // With these building blocks
 | 
			
		||||
    //
 | 
			
		||||
    //       dS/dU =  
 | 
			
		||||
    //                 \sum_k -ak MpvPhi_k^dag        [ dV^dag V + V^dag dV ] MpvMfMpvPhi_k           <- deriv on P left
 | 
			
		||||
    //             +   \sum_k -ak MpvMfMpvPhi_k^\dag  [ dV^dag V + V^dag dV ] MpvPhi_k
 | 
			
		||||
    //             +   \sum_k -ak MfMpvPhi_k^dag      [ dM^dag M + M^dag dM ] MfMpvPhi_k
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // Two flavour pseudofermion action for any dop
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    template<class GaugeField,class MatrixField,class FermionField>
 | 
			
		||||
      class TwoFlavourPseudoFermionAction : public Action<GaugeField> {
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
      
 | 
			
		||||
      FermionOperator<FermionField,GaugeField> & FermOp;// the basic operator
 | 
			
		||||
 | 
			
		||||
      OperatorFunction<FermionField> &DerivativeSolver;
 | 
			
		||||
 | 
			
		||||
      OperatorFunction<FermionField> &ActionSolver;
 | 
			
		||||
 | 
			
		||||
      GridBase &Grid;
 | 
			
		||||
 | 
			
		||||
      FermionField Phi; // the pseudo fermion field for this trajectory
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      /////////////////////////////////////////////////
 | 
			
		||||
      // Pass in required objects.
 | 
			
		||||
      /////////////////////////////////////////////////
 | 
			
		||||
    TwoFlavourPseudoFermionAction(FermionOperator<FermionField,GaugeField>  &Op, 
 | 
			
		||||
				  OperatorFunction<FermionField> & DS,
 | 
			
		||||
				  OperatorFunction<FermionField> & AS,
 | 
			
		||||
				  GridBase &_Grid
 | 
			
		||||
				  ) : FermOp(Op), DerivativeSolver(DS), ActionSolver(AS), Phi(&_Grid), Grid(_Grid) {
 | 
			
		||||
      };
 | 
			
		||||
      
 | 
			
		||||
      //////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
      // Push the gauge field in to the dops. Assume any BC's and smearing already applied
 | 
			
		||||
      //////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
      virtual void init(const GaugeField &U, GridParallelRNG& pRNG) {
 | 
			
		||||
 | 
			
		||||
	// P(phi) = e^{- phi^dag (MdagM)^-1 phi}
 | 
			
		||||
	// Phi = Mdag eta 
 | 
			
		||||
	// P(eta) = e^{- eta^dag eta}
 | 
			
		||||
	//
 | 
			
		||||
	// e^{x^2/2 sig^2} => sig^2 = 0.5.
 | 
			
		||||
	// 
 | 
			
		||||
	// So eta should be of width sig = 1/sqrt(2).
 | 
			
		||||
	// and must multiply by 0.707....
 | 
			
		||||
	//
 | 
			
		||||
	// Chroma has this scale factor: two_flavor_monomial_w.h
 | 
			
		||||
	// IroIro: does not use this scale. It is absorbed by a change of vars
 | 
			
		||||
	//         in the Phi integral, and thus is only an irrelevant prefactor for the partition function.
 | 
			
		||||
	//
 | 
			
		||||
	RealD scale = std::sqrt(0.5);
 | 
			
		||||
	FermionField eta(&Grid);
 | 
			
		||||
 | 
			
		||||
	gaussian(pRNG,eta);
 | 
			
		||||
 | 
			
		||||
	FermOp.Mdag(eta,Phi);
 | 
			
		||||
 | 
			
		||||
	Phi=Phi*scale;
 | 
			
		||||
	
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      //////////////////////////////////////////////////////
 | 
			
		||||
      // S = phi^dag (Mdag M)^-1 phi
 | 
			
		||||
      //////////////////////////////////////////////////////
 | 
			
		||||
      virtual RealD S(const GaugeField &U) {
 | 
			
		||||
 | 
			
		||||
	FermOp.ImportGauge(U);
 | 
			
		||||
 | 
			
		||||
	FermionField X(&Grid);
 | 
			
		||||
	FermionField Y(&Grid);
 | 
			
		||||
	
 | 
			
		||||
	MdagMLinearOperator<FermionOperator<FermionField,GaugeField> ,FermionField> MdagMOp(FermOp);
 | 
			
		||||
	X=zero;
 | 
			
		||||
	ActionSolver(MdagMOp,Phi,X);
 | 
			
		||||
	MdagMOp.Op(X,Y);
 | 
			
		||||
 | 
			
		||||
	RealD action = norm2(Y);
 | 
			
		||||
	std::cout << GridLogMessage << "Pseudofermion action "<<action<<std::endl;
 | 
			
		||||
	return action;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      //////////////////////////////////////////////////////
 | 
			
		||||
      // dS/du = - phi^dag  (Mdag M)^-1 [ Mdag dM + dMdag M ]  (Mdag M)^-1 phi
 | 
			
		||||
      //       = - phi^dag M^-1 dM (MdagM)^-1 phi -  phi^dag (MdagM)^-1 dMdag dM (Mdag)^-1 phi 
 | 
			
		||||
      //
 | 
			
		||||
      //       = - Ydag dM X  - Xdag dMdag Y
 | 
			
		||||
      //
 | 
			
		||||
      //////////////////////////////////////////////////////
 | 
			
		||||
      virtual void deriv(const GaugeField &U,GaugeField & dSdU) {
 | 
			
		||||
 | 
			
		||||
	FermOp.ImportGauge(U);
 | 
			
		||||
 | 
			
		||||
	FermionField X(&Grid);
 | 
			
		||||
	FermionField Y(&Grid);
 | 
			
		||||
	GaugeField   tmp(&Grid);
 | 
			
		||||
 | 
			
		||||
	MdagMLinearOperator<FermionOperator<FermionField,GaugeField> ,FermionField> MdagMOp(FermOp);
 | 
			
		||||
 | 
			
		||||
	X=zero;
 | 
			
		||||
	DerivativeSolver(MdagMOp,Phi,X);
 | 
			
		||||
	MdagMOp.Op(X,Y);
 | 
			
		||||
 | 
			
		||||
	// Our conventions really make this UdSdU; We do not differentiate wrt Udag here.
 | 
			
		||||
	// So must take dSdU - adj(dSdU) and left multiply by mom to get dS/dt.
 | 
			
		||||
 | 
			
		||||
	FermOp.MDeriv(tmp , Y, X,DaggerNo );  dSdU=tmp;
 | 
			
		||||
	FermOp.MDeriv(tmp , X, Y,DaggerYes);  dSdU=dSdU+tmp;
 | 
			
		||||
	
 | 
			
		||||
	dSdU = Ta(dSdU);
 | 
			
		||||
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user