/************************************************************************************* 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 DoubledGaugeField; // typedef typename XXX SiteSpinor; // 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) // { // // }; // // } ////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Implementation dependent fermion types //////////////////////////////////////////////////////////////////////// #define INHERIT_FIMPL_TYPES(Impl)\ typedef typename Impl::FermionField FermionField; \ typedef typename Impl::DoubledGaugeField DoubledGaugeField; \ typedef typename Impl::SiteSpinor SiteSpinor; \ typedef typename Impl::SiteHalfSpinor SiteHalfSpinor; \ typedef typename Impl::Compressor Compressor; \ typedef typename Impl::StencilImpl StencilImpl; \ typedef typename Impl::ImplParams ImplParams; #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< GaugeImplTypes< S, Nrepresentation> > { public: const bool LsVectorised=false; typedef PeriodicGaugeImpl< GaugeImplTypes< S,Nrepresentation> > Gimpl; INHERIT_GIMPL_TYPES(Gimpl); template using iImplSpinor = iScalar, Ns> >; template using iImplHalfSpinor = iScalar, Nhs> >; template using iImplDoubledGaugeField = iVector >, Nds >; typedef iImplSpinor SiteSpinor; typedef iImplHalfSpinor SiteHalfSpinor; typedef iImplDoubledGaugeField SiteDoubledGaugeField; typedef Lattice FermionField; typedef Lattice DoubledGaugeField; typedef WilsonCompressor Compressor; typedef WilsonImplParams ImplParams; typedef WilsonStencil StencilImpl; ImplParams Params; WilsonImpl(const ImplParams &p= ImplParams()) : Params(p) {}; 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()); } template inline void loadLinkElement(Simd & reg,ref &memory){ reg = memory; } inline void DoubleStore(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu) { conformable(Uds._grid,GaugeGrid); conformable(Umu._grid,GaugeGrid); GaugeLinkField U(GaugeGrid); for(int mu=0;mu(Umu,mu); PokeIndex(Uds,U,mu); U = adj(Cshift(U,mu,-1)); 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 InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã,int mu){ int Ls=Btilde._grid->_fdimensions[0]; GaugeLinkField tmp(mat._grid); tmp = zero; PARALLEL_FOR_LOOP 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,Nrepresentation> > { public: const bool LsVectorised=true; typedef PeriodicGaugeImpl< GaugeImplTypes< S,Nrepresentation> > Gimpl; INHERIT_GIMPL_TYPES(Gimpl); template using iImplSpinor = iScalar, Ns> >; template using iImplHalfSpinor = iScalar, Nhs> >; template using iImplDoubledGaugeField = iVector >, Nds >; template using iImplGaugeField = iVector >, Nd >; template using iImplGaugeLink = iScalar > >; typedef iImplSpinor SiteSpinor; typedef iImplHalfSpinor SiteHalfSpinor; typedef Lattice FermionField; // 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 & reg,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(Umu,mu); U = adj(Cshift(U,mu,-1)); PokeIndex(Uadj,U,mu); } for(int lidx=0;lidxlSites();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 InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã,int mu){ assert(0); } }; //////////////////////////////////////////////////////////////////////////////////////// // Flavour doubled spinors; is Gparity the only? what about C*? //////////////////////////////////////////////////////////////////////////////////////// template class GparityWilsonImpl : public ConjugateGaugeImpl< GaugeImplTypes >{ public: const bool LsVectorised=false; typedef ConjugateGaugeImpl< GaugeImplTypes > Gimpl; INHERIT_GIMPL_TYPES(Gimpl); template using iImplSpinor = iVector, Ns>, Ngp >; template using iImplHalfSpinor = iVector, Nhs>, Ngp >; template using iImplDoubledGaugeField = iVector >, Nds >, Ngp >; typedef iImplSpinor SiteSpinor; typedef iImplHalfSpinor SiteHalfSpinor; typedef iImplDoubledGaugeField SiteDoubledGaugeField; typedef Lattice FermionField; 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)); } } 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_LOOP for(auto ss=U.begin();ss(outerProduct(Btilde[ss],A[ss])); link[ss]() = ttmp(0,0) + conjugate(ttmp(1,1)) ; } PokeIndex(mat,link,mu); return; } inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã,int mu){ int Ls=Btilde._grid->_fdimensions[0]; GaugeLinkField tmp(mat._grid); tmp = zero; PARALLEL_FOR_LOOP for(int ss=0;ssoSites();ss++){ for(int s=0;s(outerProduct(Btilde[sF],Atilde[sF])); tmp[ss]() = tmp[ss]()+ ttmp(0,0) + conjugate(ttmp(1,1)); } } PokeIndex(mat,tmp,mu); return; } }; typedef WilsonImpl WilsonImplR; // Real.. whichever prec typedef WilsonImpl WilsonImplF; // Float typedef WilsonImpl WilsonImplD; // Double typedef DomainWallVec5dImpl DomainWallVec5dImplR; // Real.. whichever prec typedef DomainWallVec5dImpl DomainWallVec5dImplF; // Float typedef DomainWallVec5dImpl DomainWallVec5dImplD; // Double typedef GparityWilsonImpl GparityWilsonImplR; // Real.. whichever prec typedef GparityWilsonImpl GparityWilsonImplF; // Float typedef GparityWilsonImpl GparityWilsonImplD; // Double } } #endif