/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/qcd/action/fermion/CayleyFermion5D.cc 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 */ #include #include namespace Grid { namespace QCD { template CayleyFermion5D::CayleyFermion5D(GaugeField &_Umu, GridCartesian &FiveDimGrid, GridRedBlackCartesian &FiveDimRedBlackGrid, GridCartesian &FourDimGrid, GridRedBlackCartesian &FourDimRedBlackGrid, RealD _mass,RealD _M5,const ImplParams &p) : WilsonFermion5D(_Umu, FiveDimGrid, FiveDimRedBlackGrid, FourDimGrid, FourDimRedBlackGrid,_M5,p), mass(_mass) { } template void CayleyFermion5D::Meooe5D (const FermionField &psi, FermionField &Din) { // Assemble Din int Ls=this->Ls; for(int s=0;s void CayleyFermion5D::MeooeDag5D (const FermionField &psi, FermionField &Din) { int Ls=this->Ls; for(int s=0;s RealD CayleyFermion5D::M (const FermionField &psi, FermionField &chi) { int Ls=this->Ls; FermionField Din(psi._grid); // Assemble Din Meooe5D(psi,Din); this->DW(Din,chi,DaggerNo); // ((b D_W + D_w hop terms +1) on s-diag axpby(chi,1.0,1.0,chi,psi); // Call Mooee?? for(int s=0;s RealD CayleyFermion5D::Mdag (const FermionField &psi, FermionField &chi) { // Under adjoint //D1+ D1- P- -> D1+^dag P+ D2-^dag //D2- P+ D2+ P-D1-^dag D2+dag FermionField Din(psi._grid); // Apply Dw this->DW(psi,Din,DaggerYes); MeooeDag5D(Din,chi); int Ls=this->Ls; for(int s=0;s void CayleyFermion5D::Meooe (const FermionField &psi, FermionField &chi) { int Ls=this->Ls; FermionField tmp(psi._grid); // Assemble the 5d matrix Meooe5D(psi,tmp); // Apply 4d dslash if ( psi.checkerboard == Odd ) { this->DhopEO(tmp,chi,DaggerNo); } else { this->DhopOE(tmp,chi,DaggerNo); } } template void CayleyFermion5D::MeooeDag (const FermionField &psi, FermionField &chi) { FermionField tmp(psi._grid); // Apply 4d dslash if ( psi.checkerboard == Odd ) { this->DhopEO(psi,tmp,DaggerYes); } else { this->DhopOE(psi,tmp,DaggerYes); } MeooeDag5D(tmp,chi); } template void CayleyFermion5D::Mooee (const FermionField &psi, FermionField &chi) { int Ls=this->Ls; for (int s=0;sMooeeDenseInternal(psi,temp,DaggerNo,InverseNo); temp = temp - chi; std::cout << "Difference between dense and normal "<< norm2(temp) < void CayleyFermion5D::Mdir (const FermionField &psi, FermionField &chi,int dir,int disp){ int Ls=this->Ls; FermionField tmp(psi._grid); // Assemble the 5d matrix for(int s=0;sDhopDir(tmp,chi,dir,disp); } template void CayleyFermion5D::MooeeDag (const FermionField &psi, FermionField &chi) { int Ls=this->Ls; for (int s=0;sMooeeDenseInternal(psi,temp,DaggerYes,InverseNo); temp = temp - chi; std::cout << "Difference between dense and normal "<< norm2(temp) < void CayleyFermion5D::MooeeInv (const FermionField &psi, FermionField &chi) { FermionField temp(psi._grid); this->MooeeLDUInv(psi,chi); this->MooeeDenseInv(psi,temp); temp = temp - chi; std::cout << "Difference between dense and normal "<< norm2(temp) < void CayleyFermion5D::MooeeInvDag (const FermionField &psi, FermionField &chi) { FermionField temp(psi._grid); this->MooeeLDUInvDag(psi,chi); this->MooeeDenseInvDag(psi,temp); temp = temp - chi; std::cout << "Difference between dense and normal "<< norm2(temp) < void CayleyFermion5D::MooeeDenseInvDag (const FermionField &psi, FermionField &chi) { this->MooeeDenseInternal(psi,chi,DaggerYes,InverseYes); } template void CayleyFermion5D::MooeeDenseInv(const FermionField &psi, FermionField &chi) { this->MooeeDenseInternal(psi,chi,DaggerNo,InverseYes); } template void CayleyFermion5D::MooeeDenseInternal(const FermionField &psi, FermionField &chi,int dag, int inv) { int Ls=this->Ls; int LLs = psi._grid->_rdimensions[0]; int vol = psi._grid->oSites()/LLs; chi.checkerboard=psi.checkerboard; assert(Ls==LLs); Eigen::MatrixXd Pplus = Eigen::MatrixXd::Zero(Ls,Ls); Eigen::MatrixXd Pminus = Eigen::MatrixXd::Zero(Ls,Ls); for(int s=0;s void CayleyFermion5D::MooeeLDUInv (const FermionField &psi, FermionField &chi) { chi.checkerboard=psi.checkerboard; int Ls=this->Ls; // Apply (L^{\prime})^{-1} axpby_ssp (chi,1.0,psi, 0.0,psi,0,0); // chi[0]=psi[0] for (int s=1;s=0;s--){ axpby_ssp_pminus (chi,1.0,chi,-uee[s],chi,s,s+1); // chi[Ls] } } template void CayleyFermion5D::MooeeLDUInvDag (const FermionField &psi, FermionField &chi) { chi.checkerboard=psi.checkerboard; int Ls=this->Ls; // Apply (U^{\prime})^{-dagger} axpby_ssp (chi,1.0,psi, 0.0,psi,0,0); // chi[0]=psi[0] for (int s=1;s=0;s--){ axpby_ssp_pplus (chi,1.0,chi,-lee[s],chi,s,s+1); // chi[Ls] } } // force terms; five routines; default to Dhop on diagonal template void CayleyFermion5D::MDeriv (GaugeField &mat,const FermionField &U,const FermionField &V,int dag) { FermionField Din(V._grid); if ( dag == DaggerNo ) { // U d/du [D_w D5] V = U d/du DW D5 V Meooe5D(V,Din); this->DhopDeriv(mat,U,Din,dag); } else { // U d/du [D_w D5]^dag V = U D5^dag d/du DW^dag Y // implicit adj on U in call Meooe5D(U,Din); this->DhopDeriv(mat,Din,V,dag); } }; template void CayleyFermion5D::MoeDeriv(GaugeField &mat,const FermionField &U,const FermionField &V,int dag) { FermionField Din(V._grid); if ( dag == DaggerNo ) { // U d/du [D_w D5] V = U d/du DW D5 V Meooe5D(V,Din); this->DhopDerivOE(mat,U,Din,dag); } else { // U d/du [D_w D5]^dag V = U D5^dag d/du DW^dag Y // implicit adj on U in call Meooe5D(U,Din); this->DhopDerivOE(mat,Din,V,dag); } }; template void CayleyFermion5D::MeoDeriv(GaugeField &mat,const FermionField &U,const FermionField &V,int dag) { FermionField Din(V._grid); if ( dag == DaggerNo ) { // U d/du [D_w D5] V = U d/du DW D5 V Meooe5D(V,Din); this->DhopDerivEO(mat,U,Din,dag); } else { // U d/du [D_w D5]^dag V = U D5^dag d/du DW^dag Y // implicit adj on U in call Meooe5D(U,Din); this->DhopDerivEO(mat,Din,V,dag); } }; // Tanh template void CayleyFermion5D::SetCoefficientsTanh(Approx::zolotarev_data *zdata,RealD b,RealD c) { SetCoefficientsZolotarev(1.0,zdata,b,c); } //Zolo template void CayleyFermion5D::SetCoefficientsZolotarev(RealD zolo_hi,Approx::zolotarev_data *zdata,RealD b,RealD c) { int Ls=this->Ls; /////////////////////////////////////////////////////////// // The Cayley coeffs (unprec) /////////////////////////////////////////////////////////// omega.resize(Ls); bs.resize(Ls); cs.resize(Ls); as.resize(Ls); // // Ts = ( [bs+cs]Dw )^-1 ( (bs+cs) Dw ) // -(g5 ------- -1 ) ( g5 --------- + 1 ) // ( {2+(bs-cs)Dw} ) ( 2+(bs-cs) Dw ) // // bs = 1/2( (1/omega_s + 1)*b + (1/omega - 1)*c ) = 1/2( 1/omega(b+c) + (b-c) ) // cs = 1/2( (1/omega_s - 1)*b + (1/omega + 1)*c ) = 1/2( 1/omega(b+c) - (b-c) ) // // bs+cs = 0.5*( 1/omega(b+c) + (b-c) + 1/omega(b+c) - (b-c) ) = 1/omega(b+c) // bs-cs = 0.5*( 1/omega(b+c) + (b-c) - 1/omega(b+c) + (b-c) ) = b-c // // So // // Ts = ( [b+c]Dw/omega_s )^-1 ( (b+c) Dw /omega_s ) // -(g5 ------- -1 ) ( g5 --------- + 1 ) // ( {2+(b-c)Dw} ) ( 2+(b-c) Dw ) // // Ts = ( [b+c]Dw )^-1 ( (b+c) Dw ) // -(g5 ------- -omega_s) ( g5 --------- + omega_s ) // ( {2+(b-c)Dw} ) ( 2+(b-c) Dw ) // double bpc = b+c; double bmc = b-c; for(int i=0; i < Ls; i++){ as[i] = 1.0; omega[i] = ((double)zdata->gamma[i])*zolo_hi; //NB reciprocal relative to Chroma NEF code bs[i] = 0.5*(bpc/omega[i] + bmc); cs[i] = 0.5*(bpc/omega[i] - bmc); } //////////////////////////////////////////////////////// // Constants for the preconditioned matrix Cayley form //////////////////////////////////////////////////////// bee.resize(Ls); cee.resize(Ls); beo.resize(Ls); ceo.resize(Ls); for(int i=0;iM5) +1.0); cee[i]=as[i]*(1.0-cs[i]*(4.0-this->M5)); beo[i]=as[i]*bs[i]; ceo[i]=-as[i]*cs[i]; } aee.resize(Ls); aeo.resize(Ls); for(int i=0;i