/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/qcd/action/fermion/FermionOperatorImpl.h Copyright (C) 2015 Author: Peter Boyle Author: Peter Boyle Author: Peter Boyle Author: paboyle This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. See the full license in the file "LICENSE" in the top level distribution directory *************************************************************************************/ /* END LEGAL */ #ifndef GRID_QCD_FERMION_OPERATOR_IMPL_H #define GRID_QCD_FERMION_OPERATOR_IMPL_H namespace Grid { namespace QCD { ////////////////////////////////////////////// // Template parameter class constructs to package // externally control Fermion implementations // in orthogonal directions // // Ultimately need Impl to always define types where XXX is opaque // // typedef typename XXX Simd; // typedef typename XXX GaugeLinkField; // typedef typename XXX GaugeField; // typedef typename XXX GaugeActField; // typedef typename XXX FermionField; // typedef typename XXX PropagatorField; // typedef typename XXX DoubledGaugeField; // typedef typename XXX SiteSpinor; // typedef typename XXX SitePropagator; // typedef typename XXX SiteHalfSpinor; // typedef typename XXX Compressor; // // and Methods: // void ImportGauge(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu) // void DoubleStore(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu) // void multLink(SiteHalfSpinor &phi,const SiteDoubledGaugeField &U,const SiteHalfSpinor &chi,int mu,StencilEntry *SE,StencilImpl &St) // void InsertForce4D(GaugeField &mat,const FermionField &Btilde,const FermionField &A,int mu) // void InsertForce5D(GaugeField &mat,const FermionField &Btilde,const FermionField &A,int mu) // // // To acquire the typedefs from "Base" (either a base class or template param) use: // // INHERIT_GIMPL_TYPES(Base) // INHERIT_FIMPL_TYPES(Base) // INHERIT_IMPL_TYPES(Base) // // The Fermion operators will do the following: // // struct MyOpParams { // RealD mass; // }; // // // template // class MyOp : public { // public: // // INHERIT_ALL_IMPL_TYPES(Impl); // // MyOp(MyOpParams Myparm, ImplParams &ImplParam) : Impl(ImplParam) // { // // }; // // } ////////////////////////////////////////////// template struct SamePrecisionMapper { typedef T HigherPrecVector ; typedef T LowerPrecVector ; }; template struct LowerPrecisionMapper { }; template <> struct LowerPrecisionMapper { typedef vRealF HigherPrecVector ; typedef vRealH LowerPrecVector ; }; template <> struct LowerPrecisionMapper { typedef vRealD HigherPrecVector ; typedef vRealF LowerPrecVector ; }; template <> struct LowerPrecisionMapper { typedef vComplexF HigherPrecVector ; typedef vComplexH LowerPrecVector ; }; template <> struct LowerPrecisionMapper { typedef vComplexD HigherPrecVector ; typedef vComplexF LowerPrecVector ; }; struct CoeffReal { public: typedef RealD _Coeff_t; static const int Nhcs = 2; template using PrecisionMapper = SamePrecisionMapper; }; struct CoeffRealHalfComms { public: typedef RealD _Coeff_t; static const int Nhcs = 1; template using PrecisionMapper = LowerPrecisionMapper; }; struct CoeffComplex { public: typedef ComplexD _Coeff_t; static const int Nhcs = 2; template using PrecisionMapper = SamePrecisionMapper; }; struct CoeffComplexHalfComms { public: typedef ComplexD _Coeff_t; static const int Nhcs = 1; template using PrecisionMapper = LowerPrecisionMapper; }; //////////////////////////////////////////////////////////////////////// // Implementation dependent fermion types //////////////////////////////////////////////////////////////////////// #define INHERIT_FIMPL_TYPES(Impl)\ typedef typename Impl::FermionField FermionField; \ typedef typename Impl::PropagatorField PropagatorField; \ typedef typename Impl::DoubledGaugeField DoubledGaugeField; \ typedef typename Impl::SiteSpinor SiteSpinor; \ typedef typename Impl::SitePropagator SitePropagator; \ typedef typename Impl::SiteHalfSpinor SiteHalfSpinor; \ typedef typename Impl::Compressor Compressor; \ typedef typename Impl::StencilImpl StencilImpl; \ typedef typename Impl::ImplParams ImplParams; \ typedef typename Impl::Coeff_t Coeff_t; \ #define INHERIT_IMPL_TYPES(Base) \ INHERIT_GIMPL_TYPES(Base) \ INHERIT_FIMPL_TYPES(Base) ///////////////////////////////////////////////////////////////////////////// // Single flavour four spinors with colour index ///////////////////////////////////////////////////////////////////////////// template class WilsonImpl : public PeriodicGaugeImpl > { public: static const int Dimension = Representation::Dimension; static const bool isFundamental = Representation::isFundamental; static const bool LsVectorised=false; static const int Nhcs = Options::Nhcs; typedef PeriodicGaugeImpl > Gimpl; INHERIT_GIMPL_TYPES(Gimpl); //Necessary? constexpr bool is_fundamental() const{return Dimension == Nc ? 1 : 0;} typedef typename Options::_Coeff_t Coeff_t; typedef typename Options::template PrecisionMapper::LowerPrecVector SimdL; template using iImplSpinor = iScalar, Ns> >; template using iImplPropagator = iScalar, Ns> >; template using iImplHalfSpinor = iScalar, Nhs> >; template using iImplHalfCommSpinor = iScalar, Nhcs> >; template using iImplDoubledGaugeField = iVector >, Nds>; typedef iImplSpinor SiteSpinor; typedef iImplPropagator SitePropagator; typedef iImplHalfSpinor SiteHalfSpinor; typedef iImplHalfCommSpinor SiteHalfCommSpinor; typedef iImplDoubledGaugeField SiteDoubledGaugeField; typedef Lattice FermionField; typedef Lattice PropagatorField; typedef Lattice DoubledGaugeField; typedef WilsonCompressor Compressor; typedef WilsonImplParams ImplParams; typedef WilsonStencil StencilImpl; ImplParams Params; WilsonImpl(const ImplParams &p = ImplParams()) : Params(p){ assert(Params.boundary_phases.size() == Nd); }; bool overlapCommsCompute(void) { return Params.overlapCommsCompute; }; inline void multLink(SiteHalfSpinor &phi, const SiteDoubledGaugeField &U, const SiteHalfSpinor &chi, int mu, StencilEntry *SE, StencilImpl &St) { mult(&phi(), &U(mu), &chi()); } inline void multLinkProp(SitePropagator &phi, const SiteDoubledGaugeField &U, const SitePropagator &chi, int mu) { mult(&phi(), &U(mu), &chi()); } template inline void loadLinkElement(Simd ®, ref &memory) { reg = memory; } inline void DoubleStore(GridBase *GaugeGrid, DoubledGaugeField &Uds, const GaugeField &Umu) { typedef typename Simd::scalar_type scalar_type; conformable(Uds._grid, GaugeGrid); conformable(Umu._grid, GaugeGrid); GaugeLinkField U(GaugeGrid); GaugeLinkField tmp(GaugeGrid); Lattice > coor(GaugeGrid); for (int mu = 0; mu < Nd; mu++) { auto pha = Params.boundary_phases[mu]; scalar_type phase( real(pha),imag(pha) ); int Lmu = GaugeGrid->GlobalDimensions()[mu] - 1; LatticeCoordinate(coor, mu); U = PeekIndex(Umu, mu); tmp = where(coor == Lmu, phase * U, U); PokeIndex(Uds, tmp, mu); U = adj(Cshift(U, mu, -1)); U = where(coor == 0, conjugate(phase) * U, U); PokeIndex(Uds, U, mu + 4); } } inline void InsertForce4D(GaugeField &mat, FermionField &Btilde, FermionField &A,int mu){ GaugeLinkField link(mat._grid); link = TraceIndex(outerProduct(Btilde,A)); PokeIndex(mat,link,mu); } inline void outerProductImpl(PropagatorField &mat, const FermionField &B, const FermionField &A){ mat = outerProduct(B,A); } inline void TraceSpinImpl(GaugeLinkField &mat, PropagatorField&P) { mat = TraceIndex(P); } inline void extractLinkField(std::vector &mat, DoubledGaugeField &Uds){ for (int mu = 0; mu < Nd; mu++) mat[mu] = PeekIndex(Uds, mu); } inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã,int mu){ int Ls=Btilde._grid->_fdimensions[0]; GaugeLinkField tmp(mat._grid); tmp = zero; parallel_for(int sss=0;sssoSites();sss++){ int sU=sss; for(int s=0;s(outerProduct(Btilde[sF],Atilde[sF])); // ordering here } } PokeIndex(mat,tmp,mu); } }; //////////////////////////////////////////////////////////////////////////////////// // Single flavour four spinors with colour index, 5d redblack //////////////////////////////////////////////////////////////////////////////////// template class DomainWallVec5dImpl : public PeriodicGaugeImpl< GaugeImplTypes< S,Representation::Dimension> > { public: typedef PeriodicGaugeImpl > Gimpl; INHERIT_GIMPL_TYPES(Gimpl); static const int Dimension = Representation::Dimension; static const bool isFundamental = Representation::isFundamental; static const bool LsVectorised=true; static const int Nhcs = Options::Nhcs; typedef typename Options::_Coeff_t Coeff_t; typedef typename Options::template PrecisionMapper::LowerPrecVector SimdL; template using iImplSpinor = iScalar, Ns> >; template using iImplPropagator = iScalar, Ns> >; template using iImplHalfSpinor = iScalar, Nhs> >; template using iImplHalfCommSpinor = iScalar, Nhcs> >; template using iImplDoubledGaugeField = iVector >, Nds>; template using iImplGaugeField = iVector >, Nd>; template using iImplGaugeLink = iScalar > >; typedef iImplSpinor SiteSpinor; typedef iImplPropagator SitePropagator; typedef iImplHalfSpinor SiteHalfSpinor; typedef iImplHalfCommSpinor SiteHalfCommSpinor; typedef Lattice FermionField; typedef Lattice PropagatorField; ///////////////////////////////////////////////// // Make the doubled gauge field a *scalar* ///////////////////////////////////////////////// typedef iImplDoubledGaugeField SiteDoubledGaugeField; // This is a scalar typedef iImplGaugeField SiteScalarGaugeField; // scalar typedef iImplGaugeLink SiteScalarGaugeLink; // scalar typedef Lattice DoubledGaugeField; typedef WilsonCompressor Compressor; typedef WilsonImplParams ImplParams; typedef WilsonStencil StencilImpl; ImplParams Params; DomainWallVec5dImpl(const ImplParams &p = ImplParams()) : Params(p){}; bool overlapCommsCompute(void) { return false; }; template inline void loadLinkElement(Simd ®, ref &memory) { vsplat(reg, memory); } inline void multLink(SiteHalfSpinor &phi, const SiteDoubledGaugeField &U, const SiteHalfSpinor &chi, int mu, StencilEntry *SE, StencilImpl &St) { SiteGaugeLink UU; for (int i = 0; i < Dimension; i++) { for (int j = 0; j < Dimension; j++) { vsplat(UU()()(i, j), U(mu)()(i, j)); } } mult(&phi(), &UU(), &chi()); } inline void multLinkProp(SitePropagator &phi, const SiteDoubledGaugeField &U, const SitePropagator &chi, int mu) { SiteGaugeLink UU; for (int i = 0; i < Dimension; i++) { for (int j = 0; j < Dimension; j++) { vsplat(UU()()(i, j), U(mu)()(i, j)); } } mult(&phi(), &UU(), &chi()); } inline void DoubleStore(GridBase *GaugeGrid, DoubledGaugeField &Uds,const GaugeField &Umu) { SiteScalarGaugeField ScalarUmu; SiteDoubledGaugeField ScalarUds; GaugeLinkField U(Umu._grid); GaugeField Uadj(Umu._grid); for (int mu = 0; mu < Nd; mu++) { U = PeekIndex(Umu, mu); U = adj(Cshift(U, mu, -1)); PokeIndex(Uadj, U, mu); } for (int lidx = 0; lidx < GaugeGrid->lSites(); lidx++) { std::vector lcoor; GaugeGrid->LocalIndexToLocalCoor(lidx, lcoor); peekLocalSite(ScalarUmu, Umu, lcoor); for (int mu = 0; mu < 4; mu++) ScalarUds(mu) = ScalarUmu(mu); peekLocalSite(ScalarUmu, Uadj, lcoor); for (int mu = 0; mu < 4; mu++) ScalarUds(mu + 4) = ScalarUmu(mu); pokeLocalSite(ScalarUds, Uds, lcoor); } } inline void InsertForce4D(GaugeField &mat, FermionField &Btilde,FermionField &A, int mu) { assert(0); } inline void outerProductImpl(PropagatorField &mat, const FermionField &Btilde, const FermionField &A){ assert(0); } inline void TraceSpinImpl(GaugeLinkField &mat, PropagatorField&P) { assert(0); } inline void extractLinkField(std::vector &mat, DoubledGaugeField &Uds){ assert(0); } inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã, int mu) { assert(0); // Following lines to be revised after Peter's addition of half prec // missing put lane... /* typedef decltype(traceIndex(outerProduct(Btilde[0], Atilde[0]))) result_type; unsigned int LLs = Btilde._grid->_rdimensions[0]; conformable(Atilde._grid,Btilde._grid); GridBase* grid = mat._grid; GridBase* Bgrid = Btilde._grid; unsigned int dimU = grid->Nd(); unsigned int dimF = Bgrid->Nd(); GaugeLinkField tmp(grid); tmp = zero; // FIXME // Current implementation works, thread safe, probably suboptimal // Passing through the local coordinate for grid transformation // the force grid is in general very different from the Ls vectorized grid PARALLEL_FOR_LOOP for (int so = 0; so < grid->oSites(); so++) { std::vector vres(Bgrid->Nsimd()); std::vector ocoor; grid->oCoorFromOindex(ocoor,so); for (int si = 0; si < tmp._grid->iSites(); si++){ typename result_type::scalar_object scalar_object; scalar_object = zero; std::vector local_coor; std::vector icoor; grid->iCoorFromIindex(icoor,si); grid->InOutCoorToLocalCoor(ocoor, icoor, local_coor); for (int s = 0; s < LLs; s++) { std::vector slocal_coor(dimF); slocal_coor[0] = s; for (int s4d = 1; s4d< dimF; s4d++) slocal_coor[s4d] = local_coor[s4d-1]; int sF = Bgrid->oIndexReduced(slocal_coor); assert(sF < Bgrid->oSites()); extract(traceIndex(outerProduct(Btilde[sF], Atilde[sF])), vres); // sum across the 5d dimension for (auto v : vres) scalar_object += v; } tmp._odata[so].putlane(scalar_object, si); } } PokeIndex(mat, tmp, mu); */ } }; //////////////////////////////////////////////////////////////////////////////////////// // Flavour doubled spinors; is Gparity the only? what about C*? //////////////////////////////////////////////////////////////////////////////////////// template class GparityWilsonImpl : public ConjugateGaugeImpl > { public: static const int Dimension = Representation::Dimension; static const bool isFundamental = Representation::isFundamental; static const int Nhcs = Options::Nhcs; static const bool LsVectorised=false; typedef ConjugateGaugeImpl< GaugeImplTypes > Gimpl; INHERIT_GIMPL_TYPES(Gimpl); typedef typename Options::_Coeff_t Coeff_t; typedef typename Options::template PrecisionMapper::LowerPrecVector SimdL; template using iImplSpinor = iVector, Ns>, Ngp>; template using iImplPropagator = iVector, Ns>, Ngp>; template using iImplHalfSpinor = iVector, Nhs>, Ngp>; template using iImplHalfCommSpinor = iVector, Nhcs>, Ngp>; template using iImplDoubledGaugeField = iVector >, Nds>, Ngp>; typedef iImplSpinor SiteSpinor; typedef iImplPropagator SitePropagator; typedef iImplHalfSpinor SiteHalfSpinor; typedef iImplHalfCommSpinor SiteHalfCommSpinor; typedef iImplDoubledGaugeField SiteDoubledGaugeField; typedef Lattice FermionField; typedef Lattice PropagatorField; typedef Lattice DoubledGaugeField; typedef WilsonCompressor Compressor; typedef WilsonStencil StencilImpl; typedef GparityWilsonImplParams ImplParams; ImplParams Params; GparityWilsonImpl(const ImplParams &p = ImplParams()) : Params(p){}; bool overlapCommsCompute(void) { return Params.overlapCommsCompute; }; // provide the multiply by link that is differentiated between Gparity (with // flavour index) and non-Gparity inline void multLink(SiteHalfSpinor &phi, const SiteDoubledGaugeField &U, const SiteHalfSpinor &chi, int mu, StencilEntry *SE, StencilImpl &St) { typedef SiteHalfSpinor vobj; typedef typename SiteHalfSpinor::scalar_object sobj; vobj vtmp; sobj stmp; GridBase *grid = St._grid; const int Nsimd = grid->Nsimd(); int direction = St._directions[mu]; int distance = St._distances[mu]; int ptype = St._permute_type[mu]; int sl = St._grid->_simd_layout[direction]; // Fixme X.Y.Z.T hardcode in stencil int mmu = mu % Nd; // assert our assumptions assert((distance == 1) || (distance == -1)); // nearest neighbour stencil hard code assert((sl == 1) || (sl == 2)); std::vector icoor; if ( SE->_around_the_world && Params.twists[mmu] ) { if ( sl == 2 ) { std::vector vals(Nsimd); extract(chi,vals); for(int s=0;siCoorFromIindex(icoor,s); assert((icoor[direction]==0)||(icoor[direction]==1)); int permute_lane; if ( distance == 1) { permute_lane = icoor[direction]?1:0; } else { permute_lane = icoor[direction]?0:1; } if ( permute_lane ) { stmp(0) = vals[s](1); stmp(1) = vals[s](0); vals[s] = stmp; } } merge(vtmp,vals); } else { vtmp(0) = chi(1); vtmp(1) = chi(0); } mult(&phi(0),&U(0)(mu),&vtmp(0)); mult(&phi(1),&U(1)(mu),&vtmp(1)); } else { mult(&phi(0),&U(0)(mu),&chi(0)); mult(&phi(1),&U(1)(mu),&chi(1)); } } // Fixme: Gparity prop * link inline void multLinkProp(SitePropagator &phi, const SiteDoubledGaugeField &U, const SitePropagator &chi, int mu) { assert(0); } template inline void loadLinkElement(Simd ®, ref &memory) { reg = memory; } inline void DoubleStore(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu) { conformable(Uds._grid,GaugeGrid); conformable(Umu._grid,GaugeGrid); GaugeLinkField Utmp (GaugeGrid); GaugeLinkField U (GaugeGrid); GaugeLinkField Uconj(GaugeGrid); Lattice > coor(GaugeGrid); for(int mu=0;mu(Umu,mu); Uconj = conjugate(U); // This phase could come from a simple bc 1,1,-1,1 .. int neglink = GaugeGrid->GlobalDimensions()[mu]-1; if ( Params.twists[mu] ) { Uconj = where(coor==neglink,-Uconj,Uconj); } parallel_for(auto ss=U.begin();ss(outerProduct(Btilde, A)); parallel_for(auto ss = tmp.begin(); ss < tmp.end(); ss++) { link[ss]() = tmp[ss](0, 0) + conjugate(tmp[ss](1, 1)); } PokeIndex(mat, link, mu); return; } inline void outerProductImpl(PropagatorField &mat, const FermionField &Btilde, const FermionField &A){ //mat = outerProduct(Btilde, A); assert(0); } inline void TraceSpinImpl(GaugeLinkField &mat, PropagatorField&P) { assert(0); /* auto tmp = TraceIndex(P); parallel_for(auto ss = tmp.begin(); ss < tmp.end(); ss++) { mat[ss]() = tmp[ss](0, 0) + conjugate(tmp[ss](1, 1)); } */ } inline void extractLinkField(std::vector &mat, DoubledGaugeField &Uds){ assert(0); } inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã, int mu) { int Ls = Btilde._grid->_fdimensions[0]; GaugeLinkField tmp(mat._grid); tmp = zero; parallel_for(int ss = 0; ss < tmp._grid->oSites(); ss++) { for (int s = 0; s < Ls; s++) { int sF = s + Ls * ss; auto ttmp = traceIndex(outerProduct(Btilde[sF], Atilde[sF])); tmp[ss]() = tmp[ss]() + ttmp(0, 0) + conjugate(ttmp(1, 1)); } } PokeIndex(mat, tmp, mu); return; } }; ///////////////////////////////////////////////////////////////////////////// // Single flavour one component spinors with colour index ///////////////////////////////////////////////////////////////////////////// template class StaggeredImpl : public PeriodicGaugeImpl > { public: typedef RealD _Coeff_t ; static const int Dimension = Representation::Dimension; static const bool isFundamental = Representation::isFundamental; static const bool LsVectorised=false; typedef PeriodicGaugeImpl > Gimpl; //Necessary? constexpr bool is_fundamental() const{return Dimension == Nc ? 1 : 0;} typedef _Coeff_t Coeff_t; INHERIT_GIMPL_TYPES(Gimpl); template using iImplSpinor = iScalar > >; template using iImplHalfSpinor = iScalar > >; template using iImplDoubledGaugeField = iVector >, Nds>; template using iImplPropagator = iScalar > >; typedef iImplSpinor SiteSpinor; typedef iImplHalfSpinor SiteHalfSpinor; typedef iImplDoubledGaugeField SiteDoubledGaugeField; typedef iImplPropagator SitePropagator; typedef Lattice FermionField; typedef Lattice DoubledGaugeField; typedef Lattice PropagatorField; typedef SimpleCompressor Compressor; typedef StaggeredImplParams ImplParams; typedef CartesianStencil StencilImpl; ImplParams Params; StaggeredImpl(const ImplParams &p = ImplParams()) : Params(p){}; inline void multLink(SiteSpinor &phi, const SiteDoubledGaugeField &U, const SiteSpinor &chi, int mu){ mult(&phi(), &U(mu), &chi()); } inline void multLinkAdd(SiteSpinor &phi, const SiteDoubledGaugeField &U, const SiteSpinor &chi, int mu){ mac(&phi(), &U(mu), &chi()); } template inline void loadLinkElement(Simd ®, ref &memory) { reg = memory; } inline void DoubleStore(GridBase *GaugeGrid, DoubledGaugeField &UUUds, // for Naik term DoubledGaugeField &Uds, const GaugeField &Uthin, const GaugeField &Ufat) { conformable(Uds._grid, GaugeGrid); conformable(Uthin._grid, GaugeGrid); conformable(Ufat._grid, GaugeGrid); GaugeLinkField U(GaugeGrid); GaugeLinkField UU(GaugeGrid); GaugeLinkField UUU(GaugeGrid); GaugeLinkField Udag(GaugeGrid); GaugeLinkField UUUdag(GaugeGrid); for (int mu = 0; mu < Nd; mu++) { // Staggered Phase. Lattice > coor(GaugeGrid); Lattice > x(GaugeGrid); LatticeCoordinate(x,0); Lattice > y(GaugeGrid); LatticeCoordinate(y,1); Lattice > z(GaugeGrid); LatticeCoordinate(z,2); Lattice > t(GaugeGrid); LatticeCoordinate(t,3); Lattice > lin_z(GaugeGrid); lin_z=x+y; Lattice > lin_t(GaugeGrid); lin_t=x+y+z; ComplexField phases(GaugeGrid); phases=1.0; if ( mu == 1 ) phases = where( mod(x ,2)==(Integer)0, phases,-phases); if ( mu == 2 ) phases = where( mod(lin_z,2)==(Integer)0, phases,-phases); if ( mu == 3 ) phases = where( mod(lin_t,2)==(Integer)0, phases,-phases); // 1 hop based on fat links U = PeekIndex(Ufat, mu); Udag = adj( Cshift(U, mu, -1)); U = U *phases; Udag = Udag *phases; PokeIndex(Uds, U, mu); PokeIndex(Uds, Udag, mu + 4); // 3 hop based on thin links. Crazy huh ? U = PeekIndex(Uthin, mu); UU = Gimpl::CovShiftForward(U,mu,U); UUU= Gimpl::CovShiftForward(U,mu,UU); UUUdag = adj( Cshift(UUU, mu, -3)); UUU = UUU *phases; UUUdag = UUUdag *phases; PokeIndex(UUUds, UUU, mu); PokeIndex(UUUds, UUUdag, mu+4); } } inline void InsertForce4D(GaugeField &mat, FermionField &Btilde, FermionField &A,int mu){ GaugeLinkField link(mat._grid); link = TraceIndex(outerProduct(Btilde,A)); PokeIndex(mat,link,mu); } inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã,int mu){ assert (0); // Must never hit } }; ///////////////////////////////////////////////////////////////////////////// // Single flavour one component spinors with colour index. 5d vec ///////////////////////////////////////////////////////////////////////////// template class StaggeredVec5dImpl : public PeriodicGaugeImpl > { public: static const int Dimension = Representation::Dimension; static const bool isFundamental = Representation::isFundamental; static const bool LsVectorised=true; typedef RealD Coeff_t ; typedef PeriodicGaugeImpl > Gimpl; //Necessary? constexpr bool is_fundamental() const{return Dimension == Nc ? 1 : 0;} INHERIT_GIMPL_TYPES(Gimpl); template using iImplSpinor = iScalar > >; template using iImplHalfSpinor = iScalar > >; template using iImplDoubledGaugeField = iVector >, Nds>; template using iImplGaugeField = iVector >, Nd>; template using iImplGaugeLink = iScalar > >; template using iImplPropagator = iScalar > >; // Make the doubled gauge field a *scalar* typedef iImplDoubledGaugeField SiteDoubledGaugeField; // This is a scalar typedef iImplGaugeField SiteScalarGaugeField; // scalar typedef iImplGaugeLink SiteScalarGaugeLink; // scalar typedef iImplPropagator SitePropagator; typedef Lattice DoubledGaugeField; typedef Lattice PropagatorField; typedef iImplSpinor SiteSpinor; typedef iImplHalfSpinor SiteHalfSpinor; typedef Lattice FermionField; typedef SimpleCompressor Compressor; typedef StaggeredImplParams ImplParams; typedef CartesianStencil StencilImpl; ImplParams Params; StaggeredVec5dImpl(const ImplParams &p = ImplParams()) : Params(p){}; template inline void loadLinkElement(Simd ®, ref &memory) { vsplat(reg, memory); } inline void multLink(SiteHalfSpinor &phi, const SiteDoubledGaugeField &U, const SiteHalfSpinor &chi, int mu) { SiteGaugeLink UU; for (int i = 0; i < Dimension; i++) { for (int j = 0; j < Dimension; j++) { vsplat(UU()()(i, j), U(mu)()(i, j)); } } mult(&phi(), &UU(), &chi()); } inline void multLinkAdd(SiteHalfSpinor &phi, const SiteDoubledGaugeField &U, const SiteHalfSpinor &chi, int mu) { SiteGaugeLink UU; for (int i = 0; i < Dimension; i++) { for (int j = 0; j < Dimension; j++) { vsplat(UU()()(i, j), U(mu)()(i, j)); } } mac(&phi(), &UU(), &chi()); } inline void DoubleStore(GridBase *GaugeGrid, DoubledGaugeField &UUUds, // for Naik term DoubledGaugeField &Uds, const GaugeField &Uthin, const GaugeField &Ufat) { GridBase * InputGrid = Uthin._grid; conformable(InputGrid,Ufat._grid); GaugeLinkField U(InputGrid); GaugeLinkField UU(InputGrid); GaugeLinkField UUU(InputGrid); GaugeLinkField Udag(InputGrid); GaugeLinkField UUUdag(InputGrid); for (int mu = 0; mu < Nd; mu++) { // Staggered Phase. Lattice > coor(InputGrid); Lattice > x(InputGrid); LatticeCoordinate(x,0); Lattice > y(InputGrid); LatticeCoordinate(y,1); Lattice > z(InputGrid); LatticeCoordinate(z,2); Lattice > t(InputGrid); LatticeCoordinate(t,3); Lattice > lin_z(InputGrid); lin_z=x+y; Lattice > lin_t(InputGrid); lin_t=x+y+z; ComplexField phases(InputGrid); phases=1.0; if ( mu == 1 ) phases = where( mod(x ,2)==(Integer)0, phases,-phases); if ( mu == 2 ) phases = where( mod(lin_z,2)==(Integer)0, phases,-phases); if ( mu == 3 ) phases = where( mod(lin_t,2)==(Integer)0, phases,-phases); // 1 hop based on fat links U = PeekIndex(Ufat, mu); Udag = adj( Cshift(U, mu, -1)); U = U *phases; Udag = Udag *phases; for (int lidx = 0; lidx < GaugeGrid->lSites(); lidx++) { SiteScalarGaugeLink ScalarU; SiteDoubledGaugeField ScalarUds; std::vector lcoor; GaugeGrid->LocalIndexToLocalCoor(lidx, lcoor); peekLocalSite(ScalarUds, Uds, lcoor); peekLocalSite(ScalarU, U, lcoor); ScalarUds(mu) = ScalarU(); peekLocalSite(ScalarU, Udag, lcoor); ScalarUds(mu + 4) = ScalarU(); pokeLocalSite(ScalarUds, Uds, lcoor); } // 3 hop based on thin links. Crazy huh ? U = PeekIndex(Uthin, mu); UU = Gimpl::CovShiftForward(U,mu,U); UUU= Gimpl::CovShiftForward(U,mu,UU); UUUdag = adj( Cshift(UUU, mu, -3)); UUU = UUU *phases; UUUdag = UUUdag *phases; for (int lidx = 0; lidx < GaugeGrid->lSites(); lidx++) { SiteScalarGaugeLink ScalarU; SiteDoubledGaugeField ScalarUds; std::vector lcoor; GaugeGrid->LocalIndexToLocalCoor(lidx, lcoor); peekLocalSite(ScalarUds, UUUds, lcoor); peekLocalSite(ScalarU, UUU, lcoor); ScalarUds(mu) = ScalarU(); peekLocalSite(ScalarU, UUUdag, lcoor); ScalarUds(mu + 4) = ScalarU(); pokeLocalSite(ScalarUds, UUUds, lcoor); } } } inline void InsertForce4D(GaugeField &mat, FermionField &Btilde, FermionField &A,int mu){ assert(0); } inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã,int mu){ assert (0); } }; typedef WilsonImpl WilsonImplR; // Real.. whichever prec typedef WilsonImpl WilsonImplF; // Float typedef WilsonImpl WilsonImplD; // Double typedef WilsonImpl WilsonImplRL; // Real.. whichever prec typedef WilsonImpl WilsonImplFH; // Float typedef WilsonImpl WilsonImplDF; // Double typedef WilsonImpl ZWilsonImplR; // Real.. whichever prec typedef WilsonImpl ZWilsonImplF; // Float typedef WilsonImpl ZWilsonImplD; // Double typedef WilsonImpl ZWilsonImplRL; // Real.. whichever prec typedef WilsonImpl ZWilsonImplFH; // Float typedef WilsonImpl ZWilsonImplDF; // Double typedef WilsonImpl WilsonAdjImplR; // Real.. whichever prec typedef WilsonImpl WilsonAdjImplF; // Float typedef WilsonImpl WilsonAdjImplD; // Double typedef WilsonImpl WilsonTwoIndexSymmetricImplR; // Real.. whichever prec typedef WilsonImpl WilsonTwoIndexSymmetricImplF; // Float typedef WilsonImpl WilsonTwoIndexSymmetricImplD; // Double typedef WilsonImpl WilsonTwoIndexAntiSymmetricImplR; // Real.. whichever prec typedef WilsonImpl WilsonTwoIndexAntiSymmetricImplF; // Float typedef WilsonImpl WilsonTwoIndexAntiSymmetricImplD; // Double typedef DomainWallVec5dImpl DomainWallVec5dImplR; // Real.. whichever prec typedef DomainWallVec5dImpl DomainWallVec5dImplF; // Float typedef DomainWallVec5dImpl DomainWallVec5dImplD; // Double typedef DomainWallVec5dImpl DomainWallVec5dImplRL; // Real.. whichever prec typedef DomainWallVec5dImpl DomainWallVec5dImplFH; // Float typedef DomainWallVec5dImpl DomainWallVec5dImplDF; // Double typedef DomainWallVec5dImpl ZDomainWallVec5dImplR; // Real.. whichever prec typedef DomainWallVec5dImpl ZDomainWallVec5dImplF; // Float typedef DomainWallVec5dImpl ZDomainWallVec5dImplD; // Double typedef DomainWallVec5dImpl ZDomainWallVec5dImplRL; // Real.. whichever prec typedef DomainWallVec5dImpl ZDomainWallVec5dImplFH; // Float typedef DomainWallVec5dImpl ZDomainWallVec5dImplDF; // Double typedef GparityWilsonImpl GparityWilsonImplR; // Real.. whichever prec typedef GparityWilsonImpl GparityWilsonImplF; // Float typedef GparityWilsonImpl GparityWilsonImplD; // Double typedef GparityWilsonImpl GparityWilsonImplRL; // Real.. whichever prec typedef GparityWilsonImpl GparityWilsonImplFH; // Float typedef GparityWilsonImpl GparityWilsonImplDF; // Double typedef StaggeredImpl StaggeredImplR; // Real.. whichever prec typedef StaggeredImpl StaggeredImplF; // Float typedef StaggeredImpl StaggeredImplD; // Double typedef StaggeredVec5dImpl StaggeredVec5dImplR; // Real.. whichever prec typedef StaggeredVec5dImpl StaggeredVec5dImplF; // Float typedef StaggeredVec5dImpl StaggeredVec5dImplD; // Double }} #endif