diff --git a/Grid/qcd/action/fermion/GparityWilsonImpl.h b/Grid/qcd/action/fermion/GparityWilsonImpl.h new file mode 100644 index 00000000..1e89a68a --- /dev/null +++ b/Grid/qcd/action/fermion/GparityWilsonImpl.h @@ -0,0 +1,321 @@ +/************************************************************************************* + +Grid physics library, www.github.com/paboyle/Grid + +Source file: ./lib/qcd/action/fermion/FermionOperatorImpl.h + +Copyright (C) 2015 + +Author: Peter Boyle + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +See the full license in the file "LICENSE" in the top level distribution +directory +*************************************************************************************/ + /* END LEGAL */ +#pragma once + +NAMESPACE_BEGIN(Grid); + +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 GparityWilsonImplParams ImplParams; + typedef WilsonCompressor Compressor; + typedef WilsonStencil StencilImpl; + typedef typename StencilImpl::View_type StencilView; + + ImplParams Params; + + GparityWilsonImpl(const ImplParams &p = ImplParams()) : Params(p){}; + + // provide the multiply by link that is differentiated between Gparity (with + // flavour index) and non-Gparity + template + static accelerator_inline void multLink(_Spinor &phi, + const SiteDoubledGaugeField &U, + const _Spinor &chi, + int mu, + StencilEntry *SE, + StencilView &St) + { + int direction = St._directions[mu]; + int distance = St._distances[mu]; + int ptype = St._permute_type[mu]; + int sl = St._simd_layout[direction]; + Coordinate icoor; + +#ifdef __CUDA_ARCH__ + _Spinor tmp; + + const int Nsimd =SiteDoubledGaugeField::Nsimd(); + int s = SIMTlane(Nsimd); + St.iCoorFromIindex(icoor,s); + + int mmu = mu % Nd; + if ( SE->_around_the_world && St.parameters.twists[mmu] ) { + + int permute_lane = (sl==1) + || ((distance== 1)&&(icoor[direction]==1)) + || ((distance==-1)&&(icoor[direction]==0)); + + if ( permute_lane ) { + tmp(0) = chi(1); + tmp(1) = chi(0); + } else { + tmp(0) = chi(0); + tmp(1) = chi(1); + } + + auto UU0=coalescedRead(U(0)(mu)); + auto UU1=coalescedRead(U(1)(mu)); + + mult(&phi(0),&UU0,&tmp(0)); + mult(&phi(1),&UU1,&tmp(1)); + + } else { + + auto UU0=coalescedRead(U(0)(mu)); + auto UU1=coalescedRead(U(1)(mu)); + + mult(&phi(0),&UU0,&chi(0)); + mult(&phi(1),&UU1,&chi(1)); + + } + +#else + typedef _Spinor vobj; + typedef typename SiteHalfSpinor::scalar_object sobj; + typedef typename SiteHalfSpinor::vector_type vector_type; + + vobj vtmp; + sobj stmp; + + const int Nsimd =vector_type::Nsimd(); + + // 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)); + + if ( SE->_around_the_world && St.parameters.twists[mmu] ) { + + if ( sl == 2 ) { + + ExtractBuffer vals(Nsimd); + + extract(chi,vals); + for(int s=0;s + static accelerator_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); + } + + auto U_v = U.View(); + auto Uds_v = Uds.View(); + auto Uconj_v = Uconj.View(); + auto Utmp_v= Utmp.View(); + thread_loop( (auto ss=U_v.begin();ss(outerProduct(Btilde, A)); + auto link_v = link.View(); + auto tmp_v = tmp.View(); + thread_loop((auto ss = tmp_v.begin(); ss < tmp_v.end(); ss++), { + link_v[ss]() = tmp_v[ss](0, 0) + conjugate(tmp_v[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(); + auto tmp_v = tmp.View(); + auto Atilde_v = Atilde.View(); + auto Btilde_v = Btilde.View(); + thread_loop((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_v[sF], Atilde_v[sF])); + tmp_v[ss]() = tmp_v[ss]() + ttmp(0, 0) + conjugate(ttmp(1, 1)); + } + }); + PokeIndex(mat, tmp, mu); + return; + } + +}; + +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 + +NAMESPACE_END(Grid);