From 9751d52192993b9682c90b2364b71efddcd0161f Mon Sep 17 00:00:00 2001 From: Henry Monge Date: Tue, 27 Aug 2024 11:33:45 -0400 Subject: [PATCH 1/2] Unprec exp-clover forces added --- .../ferm/fermacts/fermacts_aggregate_w.cc | 2 + .../ferm/linop/exp_clover_term_base_w.h | 6 +- .../ferm/linop/exp_clover_term_qdp_w.h | 359 +++++++++++++++++- .../ferm/linop/unprec_exp_clover_linop_w.cc | 5 + 4 files changed, 364 insertions(+), 8 deletions(-) diff --git a/lib/actions/ferm/fermacts/fermacts_aggregate_w.cc b/lib/actions/ferm/fermacts/fermacts_aggregate_w.cc index 5b008c052f..07aa26d87b 100644 --- a/lib/actions/ferm/fermacts/fermacts_aggregate_w.cc +++ b/lib/actions/ferm/fermacts/fermacts_aggregate_w.cc @@ -6,6 +6,7 @@ #include "actions/ferm/fermacts/fermacts_aggregate_w.h" #include "actions/ferm/fermacts/unprec_clover_fermact_w.h" +#include "actions/ferm/fermacts/unprec_exp_clover_fermact_w.h" #include "actions/ferm/fermacts/unprec_wilson_fermact_w.h" #include "actions/ferm/fermacts/unprec_parwilson_fermact_w.h" #include "actions/ferm/fermacts/unprec_graphene_fermact_w.h" @@ -102,6 +103,7 @@ namespace Chroma success &= EvenOddPrecCloverFermActEnv::registerAll(); success &= SymEvenOddPrecCloverFermActEnv::registerAll(); success &= UnprecCloverFermActEnv::registerAll(); + success &= UnprecExpCloverFermActEnv::registerAll(); success &= EvenOddPrecCloverOrbifoldFermActEnv::registerAll(); success &= EvenOddPrecSLICFermActEnv::registerAll(); success &= EvenOddPrecSLRCFermActEnv::registerAll(); diff --git a/lib/actions/ferm/linop/exp_clover_term_base_w.h b/lib/actions/ferm/linop/exp_clover_term_base_w.h index 397624265b..07b3f908de 100644 --- a/lib/actions/ferm/linop/exp_clover_term_base_w.h +++ b/lib/actions/ferm/linop/exp_clover_term_base_w.h @@ -8,7 +8,7 @@ #include "chroma_config.h" #include "linearop.h" - +#include "actions/ferm/linop/clover_term_base_w.h" namespace Chroma { @@ -19,9 +19,7 @@ namespace Chroma */ template - class ExpCloverTermBase : public DslashLinearOperator, - multi1d > + class ExpCloverTermBase : public CloverTermBase< T, U> { public: //! No real need for cleanup here diff --git a/lib/actions/ferm/linop/exp_clover_term_qdp_w.h b/lib/actions/ferm/linop/exp_clover_term_qdp_w.h index b16c545a0b..f2b8cd2ae3 100644 --- a/lib/actions/ferm/linop/exp_clover_term_qdp_w.h +++ b/lib/actions/ferm/linop/exp_clover_term_qdp_w.h @@ -309,6 +309,10 @@ namespace Chroma #endif #if 1 + //Set the highest power of A^n for the exp sum. This allows for N_exp_default < 5 to compare with clover + int pow_max=5; + if (N_exp_default <5) + pow_max=N_exp_default; // Accumulate exponential from only A RComplex tmp[12]; @@ -320,7 +324,7 @@ namespace Chroma } // Main loop: chi = psi + q[i]/q[i-1] A chi - for (int pow = 5; pow > 0; --pow) + for (int pow = pow_max; pow > 0; --pow) { siteApplicationBlock(tmp, tri_in.A, cchi); for (int cspin = 0; cspin < 6; cspin++) @@ -399,6 +403,23 @@ namespace Chroma #endif } + //Apply coefficient to site + template + inline void siteApplicationCoeff(RComplex* __restrict__ cchi, const ExpClovTriang& tri_in, + int pow_i,int pow_j, + const RComplex* const __restrict__ ppsi) + { + + // Top block + for (int cspin = 0; cspin < 6; cspin++) + cchi[cspin] = tri_in.C[0][pow_i][pow_j] * ppsi[cspin]; + + // Second Block + for (int cspin = 6; cspin < 12; cspin++) + cchi[cspin] = tri_in.C[1][pow_i][pow_j]* ppsi[cspin]; + } + + template inline void siteApplicationPower(RComplex* __restrict__ cchi, const ExpClovTriang& tri_in, @@ -501,17 +522,73 @@ namespace Chroma * \param cb Checkerboard of OUTPUT std::vector (Read) */ + //! Take deriv of D^power + /*! + * \param chi left std::vector on cb (Read) + * \param psi right std::vector on 1-cb (Read) + * \param isign D'^dag or D' ( MINUS | PLUS ) resp. (Read) + * \param cb Checkerboard of chi std::vector (Read) + * + * \return Computes \f$chi^\dag * \dot(D} * psi\f$ + */ + //! Take deriv of D + /*! + * \param chi left std::vector (Read) + * \param psi right std::vector (Read) + * \param isign D'^dag or D' ( MINUS | PLUS ) resp. (Read) + * + * \return Computes \f$chi^\dag * \dot(D} * psi\f$ + */ + void deriv(multi1d& ds_u, + const T& chi, const T& psi, + enum PlusMinus isign) const;//{ExpCloverTermBase::deriv(ds_u,chi,psi,isign);} + + void deriv(multi1d& ds_u, + const T& chi, const T& psi, + enum PlusMinus isign, int cb) const; + + //! Take deriv of D + /*! + * \param chi left vectors (Read) + * \param psi right vectors (Read) + * \param isign D'^dag or D' ( MINUS | PLUS ) resp. (Read) + * \param cb Checkerboard of chi std::vector (Read) + * + * \return Computes \f$chi^\dag * \dot(D} * psi\f$ + */ + void derivMultipole(multi1d& ds_u, + const multi1d& chi, const multi1d& psi, + enum PlusMinus isign) const; + + //! Take deriv of D + /*! + * \param chi left vectors on cb (Read) + * \param psi right vectors on cb (Read) + * \param isign D'^dag or D' ( MINUS | PLUS ) resp. (Read) + * \param cb Checkerboard of chi std::vector (Read) + * + * \return Computes \f$chi^\dag * \dot(D} * psi\f$ + */ + + void derivMultipole(multi1d& ds_u, + const multi1d& chi, const multi1d& psi, + enum PlusMinus isign, int cb) const; + + void fillRefDiag(Real diag); // Reference exponential using old fashioned taylor expansion void applyRef(T& chi, const T& psi, enum PlusMinus isign, int N = N_exp) const; - // Appl;y a power of a matrix from A^0 to A^5 + // Apply a power of a matrix from A^0 to A^5 void applyPowerSite(T& chi, const T& psi, enum PlusMinus isign, int site, int power = 1) const; - // Appl;y a power of a matrix from A^0 to A^5 + // Apply a power of a matrix from A^0 to A^5 void applyPower(T& chi, const T& psi, enum PlusMinus isign, int cb, int power = 1) const; + // Apply coefficients to powers of a matrix A + void applyCoeff(T& chi, const T& psi, enum PlusMinus isign,int cb, int pow_i, int pow_j) const; + // Apply exponential operator void apply(T& chi, const T& psi, enum PlusMinus isign, int cb) const override; @@ -1021,6 +1098,169 @@ namespace Chroma #endif } + //! Take deriv of D + /*! + * \param chi left std::vector (Read) + * \param psi right std::vector (Read) + * \param isign D'^dag or D' ( MINUS | PLUS ) resp. (Read) + * + * \return Computes \f$\chi^\dag * \dot(D} * \psi\f$ + */ + template + void QDPExpCloverTermT::deriv(multi1d& ds_u, + const T& chi, const T& psi, + enum PlusMinus isign) const + { + START_CODE(); + + // base deriv resizes. + // Even even checkerboard + deriv(ds_u, chi, psi, isign,0); + + // Odd Odd checkerboard + multi1d ds_tmp; + deriv(ds_tmp, chi, psi, isign,1); + + ds_u += ds_tmp; + + END_CODE(); + } + + //! Take deriv of D + /*! + * \param chi left std::vector on cb (Read) + * \param psi right std::vector on 1-cb (Read) + * \param isign D'^dag or D' ( MINUS | PLUS ) resp. (Read) + * \param cb Checkerboard of chi std::vector (Read) + * + * \return Computes \f$\chi^\dag * \dot(D} * \psi\f$ + */ + + template + void QDPExpCloverTermT::deriv(multi1d& ds_u, + const T& chi, const T& psi, + enum PlusMinus isign, int cb) const + { + START_CODE(); + + // Do I still need to do this? + if( ds_u.size() != Nd ) { + ds_u.resize(Nd); + } + + ds_u = zero; + multi1d ds_u_tmp; + ds_u_tmp.resize(Nd); + + // Get the links + //const multi1d& u = getU(); + + T ppsi= zero; + T cchi= zero; + T f_chi= zero; + f_chi=chi; + + // The exp derivative is computed as + // A'+AA'/2+A'A/2+A'AA/6+AA'A/6+AAA'/6 = Sum A^i A' A^j + // applyCoeff multiplies the chi by the exponential term factor + // and the factors from using the Caley Hamilton for A^n, for n>5 + + for(int i=0;i<=5;i++){ + for(int j=0;j<=5;j++){ + (*this).applyCoeff(f_chi, chi, isign,cb,i,j); + (*this).applyPower(ppsi, psi, PLUS, cb, j); + (*this).applyPower(cchi, f_chi, PLUS, cb,i); + + CloverTermBase::deriv(ds_u_tmp,cchi,ppsi,isign,cb); + + for(int i=0;i + void QDPExpCloverTermT::derivMultipole(multi1d& ds_u, + const multi1d& chi, const multi1d& psi, + enum PlusMinus isign) const + { + START_CODE(); + + // base deriv resizes. + // Even even checkerboard + derivMultipole(ds_u, chi, psi, isign,0); + + // Odd Odd checkerboard + multi1d ds_tmp; + derivMultipole(ds_tmp, chi, psi, isign,1); + + ds_u += ds_tmp; + + END_CODE(); + } + + template + void QDPExpCloverTermT::derivMultipole(multi1d& ds_u, + const multi1d& chi, const multi1d& psi, + enum PlusMinus isign, int cb) const + { + START_CODE(); + + + // Do I still need to do this? + if( ds_u.size() != Nd ) { + ds_u.resize(Nd); + } + + ds_u = zero; + multi1d ds_u_tmp; + ds_u_tmp.resize(Nd); + + // Get the links + //const multi1d& u = getU(); + + multi1d ppsi,cchi,f_chi; + + f_chi.resize(chi.size()); + cchi.resize(chi.size()); + ppsi.resize(chi.size()); + + for(int i=0;i5 + + for(int i=0;i<=5;i++){ + for(int j=0;j<=5;j++){ + for(int k=0;k::derivMultipole(ds_u_tmp,cchi,ppsi,isign,cb); + + for(int i=0;i(sign * tab[block][row][i] / (REALT)(fact)); } } - } + + //HMC: adding the calculation of the C_ij + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < 6; j++) + { + tri[site].C[block][i][j] = RScalar(tab[block][0][i])*RScalar(tab[block][0][j]); + } + } + + fact = 1; + unsigned long fact_row = 1; + + for (unsigned int row = 0; row <= N_exp; ++row) + { + if (row!=0) + fact_row *= (unsigned long)(row); + fact=fact_row*(unsigned long)(row+1); + for(unsigned int col = 0; col <= N_exp-row; ++col) + { + if(row!=0 || col!=0) //row=0, col=0 computed above + { + + //This is the factor on the exp = c_n x^n, for the derivative of the n-term x^row x'x^col + //the factor is row+col+1,where row+col=n-1 + if( col !=0) + fact *= (unsigned long)(row+col+1); + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < 6; j++) + { + tri[site].C[block][i][j] += RScalar(tab[block][col][j])*RScalar(tab[block][row][i] / (REALT)(fact)); + } + } + } + } + } + + }//for block ends // Assemble te exponential from the q-s and powers of A. // siteExponentiate(tri[site]); @@ -1409,6 +1687,18 @@ namespace Chroma int power = 1; }; + template + struct ApplyDerivCoeffArgs { + typedef typename WordType::Type_t REALT; + T& chi; + const T& psi; + const ExpClovTriang* tri; + int cb; + int pow_i = 1; + int pow_j = 1; + }; + + template void applySitePowerLoop(int lo, int hi, int MyId, ApplyPowerArgs* arg) { @@ -1452,6 +1742,43 @@ namespace Chroma int cb; }; + template + void applySiteCoeffLoop(int lo, int hi, int MyId, ApplyDerivCoeffArgs* arg) + { +#ifndef QDP_IS_QDPJIT + // This is essentially the body of the previous "Apply" + // but now the args are handed in through user arg struct... + + START_CODE(); + + typedef typename WordType::Type_t REALT; + // Unwrap the args... + T& chi = arg->chi; + const T& psi = arg->psi; + const ExpClovTriang* tri = arg->tri; + int cb = arg->cb; + int pow_i = arg->pow_i; + int pow_j = arg->pow_j; + const int n = 2 * Nc; + + for (int ssite = lo; ssite < hi; ++ssite) + { + + int site = rb[cb].siteTable()[ssite]; + + RComplex* cchi = (RComplex*)&(chi.elem(site).elem(0).elem(0)); + + const RComplex* const ppsi = + (const RComplex* const) & (psi.elem(site).elem(0).elem(0)); + + siteApplicationCoeff(cchi, tri[site], pow_i,pow_j, ppsi); + } + END_CODE(); +#endif + } // Function + + + template void applySiteLoop(int lo, int hi, int MyId, ApplyArgs* arg) { @@ -1546,6 +1873,30 @@ namespace Chroma #endif } + template + void QDPExpCloverTermT::applyCoeff(T& chi, const T& psi, enum PlusMinus isign,int cb, int pow_i, int pow_j) const + { +#ifndef QDP_IS_QDPJIT + START_CODE(); + + if (Ns != 4) + { + QDPIO::cerr << __func__ << ": CloverTerm::apply requires Ns==4" << std::endl; + QDP_abort(1); + } + + QDPExpCloverEnv::ApplyDerivCoeffArgs arg = {chi, psi, tri, cb, pow_i, pow_j}; + int num_sites = rb[cb].siteTable().size(); + + // The dispatch function is at the end of the file + // ought to work for non-threaded targets too... + dispatch_to_threads(num_sites, arg, QDPExpCloverEnv::applySiteCoeffLoop); + (*this).getFermBC().modifyF(chi, QDP::rb[cb]); + + END_CODE(); +#endif + } + template void QDPExpCloverTermT::apply(T& chi, const T& psi, enum PlusMinus isign, int cb) const diff --git a/lib/actions/ferm/linop/unprec_exp_clover_linop_w.cc b/lib/actions/ferm/linop/unprec_exp_clover_linop_w.cc index 77e8fdda57..4ccc9f6c45 100644 --- a/lib/actions/ferm/linop/unprec_exp_clover_linop_w.cc +++ b/lib/actions/ferm/linop/unprec_exp_clover_linop_w.cc @@ -58,6 +58,11 @@ namespace Chroma A.deriv(ds_u, chi, psi, isign); + for (int mu = 0; mu < Nd; mu++) + { + ds_u[mu] *= (Real(Nd) + param.Mass); + } + multi1d ds_tmp(Nd); ds_tmp = zero; From 496703f3f1bf5e003d1f78158cddbcec17cf419e Mon Sep 17 00:00:00 2001 From: Henry Monge Date: Wed, 23 Oct 2024 09:05:51 -0400 Subject: [PATCH 2/2] Added eoprec_exp-clover --- lib/CMakeLists.txt | 18 +- .../fermacts/eoprec_exp_clover_fermact_w.cc | 91 +++++ .../fermacts/eoprec_exp_clover_fermact_w.h | 83 +++++ .../ferm/fermacts/fermacts_aggregate_w.cc | 2 + .../ferm/linop/eoprec_exp_clover_linop_w.cc | 351 ++++++++++++++++++ .../ferm/linop/eoprec_exp_clover_linop_w.h | 141 +++++++ .../ferm/linop/exp_clover_term_base_w.h | 4 +- 7 files changed, 682 insertions(+), 8 deletions(-) create mode 100644 lib/actions/ferm/fermacts/eoprec_exp_clover_fermact_w.cc create mode 100644 lib/actions/ferm/fermacts/eoprec_exp_clover_fermact_w.h create mode 100644 lib/actions/ferm/linop/eoprec_exp_clover_linop_w.cc create mode 100644 lib/actions/ferm/linop/eoprec_exp_clover_linop_w.h diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 10924b2507..1264512209 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -549,10 +549,11 @@ list(APPEND ChromaLIB_HEADERS actions/ferm/fermacts/fermact_factory_w.h actions/ferm/fermacts/clover_fermact_params_w.h actions/ferm/fermacts/eoprec_clover_fermact_w.h + actions/ferm/fermacts/eoprec_exp_clover_fermact_w.h actions/ferm/fermacts/seoprec_clover_fermact_w.h actions/ferm/fermacts/eoprec_clover_orbifold_fermact_w.h actions/ferm/fermacts/unprec_clover_fermact_w.h - actions/ferm/fermacts/unprec_exp_clover_fermact_w.h + actions/ferm/fermacts/unprec_exp_clover_fermact_w.h actions/ferm/fermacts/nef_fermact_params_w.h actions/ferm/fermacts/eoprec_slic_fermact_w.h actions/ferm/fermacts/eoprec_slrc_fermact_w.h @@ -654,19 +655,20 @@ list(APPEND ChromaLIB_HEADERS actions/ferm/linop/lwldslash_base_3d_w.h actions/ferm/linop/lwldslash_3d_qdp_w.h actions/ferm/linop/clover_term_w.h - actions/ferm/linop/clov_triang_qdp_w.h + actions/ferm/linop/clov_triang_qdp_w.h actions/ferm/linop/clover_term_base_w.h actions/ferm/linop/exp_clover_term_base_w.h actions/ferm/linop/clover_term_qdp_w.h - actions/ferm/linop/exp_clover_term_w.h + actions/ferm/linop/exp_clover_term_w.h actions/ferm/linop/exp_clover_term_qdp_w.h actions/ferm/linop/eoprec_clover_linop_w.h + actions/ferm/linop/eoprec_exp_clover_linop_w.h actions/ferm/linop/seoprec_clover_linop_w.h actions/ferm/linop/shifted_linop_w.h actions/ferm/linop/eoprec_clover_dumb_linop_w.h actions/ferm/linop/eoprec_clover_orbifold_linop_w.h actions/ferm/linop/unprec_clover_linop_w.h - actions/ferm/linop/unprec_exp_clover_linop_w.h + actions/ferm/linop/unprec_exp_clover_linop_w.h actions/ferm/linop/eoprec_clover_extfield_linop_w.h actions/ferm/linop/eoprec_dwflike_linop_base_array_w.h actions/ferm/linop/eoprec_dwf_linop_array_w.h @@ -1469,10 +1471,11 @@ target_sources(chromalib PRIVATE actions/ferm/fermacts/eoprec_ovext_fermact_array_w.cc actions/ferm/fermacts/clover_fermact_params_w.cc actions/ferm/fermacts/eoprec_clover_fermact_w.cc + actions/ferm/fermacts/eoprec_exp_clover_fermact_w.cc actions/ferm/fermacts/seoprec_clover_fermact_w.cc actions/ferm/fermacts/eoprec_clover_orbifold_fermact_w.cc actions/ferm/fermacts/unprec_clover_fermact_w.cc - actions/ferm/fermacts/unprec_exp_clover_fermact_w.cc + actions/ferm/fermacts/unprec_exp_clover_fermact_w.cc actions/ferm/fermacts/nef_fermact_params_w.cc actions/ferm/fermacts/eoprec_slic_fermact_w.cc actions/ferm/fermacts/eoprec_slrc_fermact_w.cc @@ -1565,12 +1568,13 @@ target_sources(chromalib PRIVATE actions/ferm/linop/unprec_wilson_linop_w.cc actions/ferm/linop/clover_term_base_w.cc actions/ferm/linop/clover_term_qdp_w.cc - actions/ferm/linop/eoprec_clover_linop_w.cc + actions/ferm/linop/eoprec_clover_linop_w.cc + actions/ferm/linop/eoprec_exp_clover_linop_w.cc actions/ferm/linop/seoprec_clover_linop_w.cc actions/ferm/linop/eoprec_clover_dumb_linop_w.cc actions/ferm/linop/eoprec_clover_orbifold_linop_w.cc actions/ferm/linop/unprec_clover_linop_w.cc - actions/ferm/linop/unprec_exp_clover_linop_w.cc + actions/ferm/linop/unprec_exp_clover_linop_w.cc actions/ferm/linop/eoprec_clover_extfield_linop_w.cc actions/ferm/linop/eoprec_slic_linop_w.cc actions/ferm/linop/eoprec_slrc_linop_w.cc diff --git a/lib/actions/ferm/fermacts/eoprec_exp_clover_fermact_w.cc b/lib/actions/ferm/fermacts/eoprec_exp_clover_fermact_w.cc new file mode 100644 index 0000000000..acc79f4fec --- /dev/null +++ b/lib/actions/ferm/fermacts/eoprec_exp_clover_fermact_w.cc @@ -0,0 +1,91 @@ +/*! \file + * \brief Even-odd preconditioned ExpClover fermion action + */ + +#include "chromabase.h" +#include "actions/ferm/fermacts/fermact_factory_w.h" + +#include "actions/ferm/linop/eoprec_exp_clover_linop_w.h" +#include "actions/ferm/fermacts/eoprec_exp_clover_fermact_w.h" +#include "actions/ferm/invert/syssolver_linop_factory.h" + +//#include "actions/ferm/fermacts/fermact_factory_w.h" +#include "actions/ferm/fermstates/ferm_createstate_reader_w.h" + +namespace Chroma +{ + + //! Hooks to register the class with the fermact factory + namespace EvenOddPrecExpCloverFermActEnv + { + //! Callback function + WilsonTypeFermAct, + multi1d >* createFermAct4D(XMLReader& xml_in, + const std::string& path) + { + return new EvenOddPrecExpCloverFermAct(CreateFermStateEnv::reader(xml_in, path), + CloverFermActParams(xml_in, path)); + } + + //! Callback function + /*! Differs in return type */ + FermionAction, + multi1d >* createFermAct(XMLReader& xml_in, + const std::string& path) + { + return createFermAct4D(xml_in, path); + } + + //! Name to be used + const std::string name = "EXP_CLOVER"; + + //! Local registration flag + static bool registered = false; + + //! Register all the factories + bool registerAll() + { + bool success = true; + if (! registered) + { + success &= Chroma::TheFermionActionFactory::Instance().registerObject(name, createFermAct); + success &= Chroma::TheWilsonTypeFermActFactory::Instance().registerObject(name, createFermAct4D); + registered = true; + } + return success; + } + } + + //! Produce a linear operator for this action + /*! + * The operator acts on the odd subset + * + * \param state gauge field (Read) + */ + EvenOddPrecLogDetLinearOperator, + multi1d >* + EvenOddPrecExpCloverFermAct::linOp(Handle< FermState > state) const + { + return new EvenOddPrecExpCloverLinOp(state,param); + } + + //! Return a linear operator solver for this action to solve M*psi=chi + Projector* + EvenOddPrecExpCloverFermAct::projector(Handle< FermState > state, + const GroupXML_t& projParam) const + { + std::istringstream is(projParam.xml); + XMLReader paramtop(is); + + return TheLinOpFermProjectorFactory::Instance().createObject(projParam.id, + paramtop, + projParam.path, + state, + linOp(state)); + } + +} + diff --git a/lib/actions/ferm/fermacts/eoprec_exp_clover_fermact_w.h b/lib/actions/ferm/fermacts/eoprec_exp_clover_fermact_w.h new file mode 100644 index 0000000000..7758b3dbfe --- /dev/null +++ b/lib/actions/ferm/fermacts/eoprec_exp_clover_fermact_w.h @@ -0,0 +1,83 @@ +// -*- C++ -*- +/*! \file + * \brief Even-odd preconditioned ExpClover fermion action + */ + +#ifndef __prec_exp_clover_fermact_w_h__ +#define __prec_exp_clover_fermact_w_h__ + +#include "eoprec_logdet_wilstype_fermact_w.h" +#include "actions/ferm/linop/lgherm_w.h" +#include "actions/ferm/fermacts/clover_fermact_params_w.h" + +namespace Chroma +{ + //! Name and registration + /*! \ingroup fermacts */ + namespace EvenOddPrecExpCloverFermActEnv + { + extern const std::string name; + bool registerAll(); + } + + + //! Even-odd preconditioned ExpClover fermion action + /*! \ingroup fermacts + * + * Even-odd preconditioned exponentiated clover fermion action. + * Only defined on odd subset. + */ + + class EvenOddPrecExpCloverFermAct : public EvenOddPrecLogDetWilsonTypeFermAct, multi1d > + { + public: + // Typedefs to save typing + typedef LatticeFermion T; + typedef multi1d P; + typedef multi1d Q; + + //! Partial constructor + EvenOddPrecExpCloverFermAct() {} + + //! General FermState + EvenOddPrecExpCloverFermAct(Handle< CreateFermState > cfs_, + const CloverFermActParams& param_) : + cfs(cfs_), param(param_) {} + + //! Copy constructor + EvenOddPrecExpCloverFermAct(const EvenOddPrecExpCloverFermAct& a) : + cfs(a.cfs), param(a.param) {} + + //! Produce a linear operator for this action + EvenOddPrecLogDetLinearOperator* linOp(Handle< FermState > state) const; + + //! Produce the gamma_5 hermitian operator H_w + LinearOperator* hermitianLinOp(Handle< FermState > state) const + { + return new lgherm(linOp(state)); + } + + //! Return a projector after this action + Projector* projector(Handle< FermState > state, + const GroupXML_t& projParam) const override; + + //! Destructor is automatic + ~EvenOddPrecExpCloverFermAct() {} + + protected: + //! Return the fermion BC object for this action + const CreateFermState& getCreateState() const {return *cfs;} + + //! Assignment + void operator=(const EvenOddPrecExpCloverFermAct& a) {} + + private: + Handle< CreateFermState > cfs; + CloverFermActParams param; + }; + +} // End Namespace Chroma + + +#endif diff --git a/lib/actions/ferm/fermacts/fermacts_aggregate_w.cc b/lib/actions/ferm/fermacts/fermacts_aggregate_w.cc index 07aa26d87b..e8e98a7a8f 100644 --- a/lib/actions/ferm/fermacts/fermacts_aggregate_w.cc +++ b/lib/actions/ferm/fermacts/fermacts_aggregate_w.cc @@ -15,6 +15,7 @@ #include "actions/ferm/fermacts/unprec_w12_fermact_w.h" #include "actions/ferm/fermacts/eoprec_clover_fermact_w.h" +#include "actions/ferm/fermacts/eoprec_exp_clover_fermact_w.h" #include "actions/ferm/fermacts/eoprec_clover_orbifold_fermact_w.h" #include "actions/ferm/fermacts/eoprec_clover_extfield_fermact_w.h" #include "actions/ferm/fermacts/eoprec_wilson_fermact_w.h" @@ -101,6 +102,7 @@ namespace Chroma success &= UnprecParWilsonFermActEnv::registerAll(); success &= EvenOddPrecCloverFermActEnv::registerAll(); + success &= EvenOddPrecExpCloverFermActEnv::registerAll(); success &= SymEvenOddPrecCloverFermActEnv::registerAll(); success &= UnprecCloverFermActEnv::registerAll(); success &= UnprecExpCloverFermActEnv::registerAll(); diff --git a/lib/actions/ferm/linop/eoprec_exp_clover_linop_w.cc b/lib/actions/ferm/linop/eoprec_exp_clover_linop_w.cc new file mode 100644 index 0000000000..06debcf087 --- /dev/null +++ b/lib/actions/ferm/linop/eoprec_exp_clover_linop_w.cc @@ -0,0 +1,351 @@ +/*! \file + * \brief Even-odd preconditioned exponentiated clover linear operator + */ + +#include "actions/ferm/linop/eoprec_exp_clover_linop_w.h" + + + +namespace Chroma +{ + + using namespace QDP::Hints; + + //! Creation routine with Anisotropy + /*! + * \param u_ gauge field (Read) + * \param param_ fermion kappa (Read) + */ + void EvenOddPrecExpCloverLinOp::create(Handle< FermState > fs, + const CloverFermActParams& param_) + { + START_CODE(); + // QDPIO::cout << __PRETTY_FUNCTION__ << ": enter" << std::endl; + + QDPIO::cout << "Using even-odd preconditioned exponetiated clover\n"; + + param = param_; + + clov.create(fs, param); + + invclov.create(fs,param,clov); // make a copy + invclov.choles(0); // invert the cb=0 part + + D.create(fs, param.anisoParam); + + clov_deriv_time = 0; + clov_apply_time = 0; + + moveToFastMemoryHint(tmp1); + moveToFastMemoryHint(tmp2); + + // QDPIO::cout << __PRETTY_FUNCTION__ << ": exit" << std::endl; + END_CODE(); + } + + //! Apply the the odd-odd block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::oddOddLinOp(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + + swatch.reset(); swatch.start(); + clov.apply(chi, psi, isign, 1); + chi *= (Real(Nd) + param.Mass); + + swatch.stop(); + clov_apply_time += swatch.getTimeInSeconds(); + + END_CODE(); + } + + + //! Apply the the even-even block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::evenEvenLinOp(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + + // Nuke for testing + swatch.reset(); swatch.start(); + clov.apply(chi, psi, isign, 0); + chi *= (Real(Nd) + param.Mass); + + swatch.stop(); + clov_apply_time += swatch.getTimeInSeconds(); + + END_CODE(); + } + + //! Apply the inverse of the even-even block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::evenEvenInvLinOp(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + + swatch.reset(); swatch.start(); + + clov.applyInv(chi, psi, isign, 0); + chi /= (Real(Nd) + param.Mass); + + swatch.stop(); + clov_apply_time += swatch.getTimeInSeconds(); + + END_CODE(); + } + + + //! Apply even-odd linop component + /*! + * The operator acts on the entire even sublattice + * + * \param chi Pseudofermion field (Write) + * \param psi Pseudofermion field (Read) + * \param isign Flag ( PLUS | MINUS ) (Read) + */ + void + EvenOddPrecExpCloverLinOp::evenOddLinOp(LatticeFermion& chi, + const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + + Real mhalf = -0.5; + + D.apply(chi, psi, isign, 0); + chi[rb[0]] *= mhalf; + + END_CODE(); + } + + //! Apply odd-even linop component + /*! + * The operator acts on the entire odd sublattice + * + * \param chi Pseudofermion field (Write) + * \param psi Pseudofermion field (Read) + * \param isign Flag ( PLUS | MINUS ) (Read) + */ + void + EvenOddPrecExpCloverLinOp::oddEvenLinOp(LatticeFermion& chi, + const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + + Real mhalf = -0.5; + + D.apply(chi, psi, isign, 1); + chi[rb[1]] *= mhalf; + + END_CODE(); + } + + + //! Apply even-odd preconditioned ExpClover fermion linear operator + /*! + * \param chi Pseudofermion field (Write) + * \param psi Pseudofermion field (Read) + * \param isign Flag ( PLUS | MINUS ) (Read) + */ + void EvenOddPrecExpCloverLinOp::operator()(LatticeFermion & chi, + const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + + Real mquarter = -0.25; + + // tmp1_o = D_oe A^(-1)_ee D_eo psi_o + D.apply(tmp1, psi, isign, 0); + + swatch.reset(); swatch.start(); + clov.applyInv(tmp2, tmp1, isign, 0); + tmp2 /= (Real(Nd) + param.Mass); + + swatch.stop(); + clov_apply_time += swatch.getTimeInSeconds(); + + D.apply(tmp1, tmp2, isign, 1); + + // chi_o = A_oo psi_o - tmp1_o + swatch.reset(); swatch.start(); + clov.apply(chi, psi, isign, 1); + chi *= (Real(Nd) + param.Mass); + + swatch.stop(); + clov_apply_time += swatch.getTimeInSeconds(); + + chi[rb[1]] += mquarter*tmp1; + + // Twisted Term? + if( param.twisted_m_usedP ){ + // tmp1 = i mu gamma_5 tmp1 + tmp1[rb[1]] = (Gamma(15) * timesI(psi)); + + if( isign == PLUS ) { + chi[rb[1]] += param.twisted_m * tmp1; + } + else { + chi[rb[1]] -= param.twisted_m * tmp1; + } + } + + END_CODE(); + } + + + //! Apply the even-even block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::derivEvenEvenLinOp(multi1d& ds_u, + const LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + + swatch.reset(); swatch.start(); + clov.deriv(ds_u, chi, psi, isign, 0); + for (int mu = 0; mu < Nd; mu++) + { + ds_u[mu] *= (Real(Nd) + param.Mass); + } + + swatch.stop(); + clov_deriv_time += swatch.getTimeInSeconds(); + + END_CODE(); + } + + //! Apply the even-even block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::derivEvenEvenLinOpMP(multi1d& ds_u, + const multi1d& chi, const multi1d& psi, + enum PlusMinus isign) const + { + START_CODE(); + + swatch.reset(); swatch.start(); + clov.derivMultipole(ds_u, chi, psi, isign, 0); + + for (int mu = 0; mu < Nd; mu++) + { + ds_u[mu] *= (Real(Nd) + param.Mass); + } + + swatch.stop(); + clov_deriv_time += swatch.getTimeInSeconds(); + + END_CODE(); + } + + //! Apply the even-even block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::derivLogDetEvenEvenLinOp(multi1d& ds_u, + enum PlusMinus isign) const + { + START_CODE(); + + //invclov.derivTrLn(ds_u, isign, 0); + // Testing Odd Odd Term - get nothing from even even term + clov.derivTrLn(ds_u, isign, 0); + for (int mu = 0; mu < Nd; mu++) + { + ds_u[mu] *= (Real(Nd) + param.Mass); + } + + + END_CODE(); + } + + //! Apply the the even-odd block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::derivEvenOddLinOp(multi1d& ds_u, + const LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + ds_u.resize(Nd); + D.deriv(ds_u, chi, psi, isign, 0); + for(int mu=0; mu < Nd; mu++) { + ds_u[mu] *= Real(-0.5); + } + END_CODE(); + } + + //! Apply the the odd-even block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::derivOddEvenLinOp(multi1d& ds_u, + const LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + ds_u.resize(Nd); + + D.deriv(ds_u, chi, psi, isign, 1); + for(int mu=0; mu < Nd; mu++) { + ds_u[mu] *= Real(-0.5); + } + END_CODE(); + } + + // Inherit this + //! Apply the the odd-odd block onto a source std::vector + void + EvenOddPrecExpCloverLinOp::derivOddOddLinOp(multi1d& ds_u, + const LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const + { + START_CODE(); + + swatch.reset(); swatch.start(); + clov.deriv(ds_u, chi, psi, isign, 1); + for (int mu = 0; mu < Nd; mu++) + { + ds_u[mu] *= (Real(Nd) + param.Mass); + } + + swatch.stop(); + clov_deriv_time += swatch.getTimeInSeconds(); + + END_CODE(); + } + + void + EvenOddPrecExpCloverLinOp::derivOddOddLinOpMP(multi1d& ds_u, + const multi1d& chi, const multi1d& psi, + enum PlusMinus isign) const + { + START_CODE(); + + swatch.reset(); swatch.start(); + clov.derivMultipole(ds_u, chi, psi, isign, 1); + for (int mu = 0; mu < Nd; mu++) + { + ds_u[mu] *= (Real(Nd) + param.Mass); + } + + swatch.stop(); + clov_deriv_time += swatch.getTimeInSeconds(); + + END_CODE(); + } + + //! Return flops performed by the operator() + unsigned long EvenOddPrecExpCloverLinOp::nFlops() const + { + unsigned long cbsite_flops = 2*D.nFlops()+2*clov.nFlops()+4*Nc*Ns; + if( param.twisted_m_usedP ) { + cbsite_flops += 4*Nc*Ns; // a + mu*b : a = chi, b = g_5 I psi + } + return cbsite_flops*(Layout::sitesOnNode()/2); + } + + //! Get the log det of the even even part + // BUt for now, return zero for testing. + Double EvenOddPrecExpCloverLinOp::logDetEvenEvenLinOp(void) const { + return invclov.cholesDet(0); + } +} // End Namespace Chroma diff --git a/lib/actions/ferm/linop/eoprec_exp_clover_linop_w.h b/lib/actions/ferm/linop/eoprec_exp_clover_linop_w.h new file mode 100644 index 0000000000..f4789d34d4 --- /dev/null +++ b/lib/actions/ferm/linop/eoprec_exp_clover_linop_w.h @@ -0,0 +1,141 @@ +// -*- C++ -*- +/*! \file + * \brief Even-odd preconditioned ExpClover fermion linear operator + */ + +#ifndef __prec_exp_clover_linop_w_h__ +#define __prec_exp_clover_linop_w_h__ + +#include "state.h" +#include "fermbc.h" +#include "eoprec_logdet_linop.h" +#include "actions/ferm/fermacts/clover_fermact_params_w.h" +#include "actions/ferm/linop/dslash_w.h" +#include "actions/ferm/linop/exp_clover_term_w.h" + + +namespace Chroma +{ + //! Even-odd preconditioned ExpClover-Dirac operator + /*! + * \ingroup linop + * + * This routine is specific to Wilson fermions! + * + * The kernel for ExpClover fermions is + * + * M = A + (d+M) - (1/2) D' + */ + class EvenOddPrecExpCloverLinOp : public EvenOddPrecLogDetLinearOperator, multi1d > + { + public: + // Typedefs to save typing + typedef LatticeFermion T; + typedef multi1d P; + typedef multi1d Q; + + //! Partial constructor + EvenOddPrecExpCloverLinOp() {} + + //! Full constructor + EvenOddPrecExpCloverLinOp(Handle< FermState > fs, + const CloverFermActParams& param_) + { + create(fs,param_); + } + + //! Destructor is automatic + ~EvenOddPrecExpCloverLinOp() { + QDPIO::cout << "EXP_CLOV_LINOP: Time spent in clov deriv (total) = " << clov_deriv_time << std::endl; + QDPIO::cout << "EXP_CLOV_LINOP: Time spent in clov apply/invapply (total) = " << clov_apply_time << std::endl; + + } + + //! Return the fermion BC object for this linear operator + const FermBC& getFermBC() const {return D.getFermBC();} + + //! Creation routine + void create(Handle< FermState > fs, + const CloverFermActParams& param_); + + //! Apply the the even-even block onto a source std::vector + void evenEvenLinOp(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + //! Apply the inverse of the even-even block onto a source std::vector + void evenEvenInvLinOp(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + //! Apply the the even-odd block onto a source std::vector + void evenOddLinOp(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + //! Apply the the odd-even block onto a source std::vector + void oddEvenLinOp(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + //! Apply the the odd-odd block onto a source std::vector + void oddOddLinOp(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + // Override inherited one with a few more funkies + void operator()(LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + //! Apply the even-even block onto a source std::vector + void derivEvenEvenLinOp(multi1d& ds_u, + const LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + //! Apply the even-even block onto a source std::vector + void derivEvenEvenLinOpMP(multi1d& ds_u, + const multi1d& chi, const multi1d& psi, + enum PlusMinus isign) const; + + void derivLogDetEvenEvenLinOp(multi1d& ds_u, + enum PlusMinus isign) const; + + //! Apply the the even-odd block onto a source std::vector + void derivEvenOddLinOp(multi1d& ds_u, + const LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + //! Apply the the odd-even block onto a source std::vector + void derivOddEvenLinOp(multi1d& ds_u, + const LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + //! Apply the the odd-odd block onto a source std::vector + void derivOddOddLinOp(multi1d& ds_u, + const LatticeFermion& chi, const LatticeFermion& psi, + enum PlusMinus isign) const; + + void derivOddOddLinOpMP(multi1d& ds_u, + const multi1d& chi, const multi1d& psi, + enum PlusMinus isign) const; + + //! Return flops performed by the operator() + unsigned long nFlops() const; + + //! Get the log det of the even even part + Double logDetEvenEvenLinOp(void) const; + + private: + mutable LatticeFermion tmp1; + mutable LatticeFermion tmp2; + CloverFermActParams param; + WilsonDslash D; + ExpCloverTerm clov; + ExpCloverTerm invclov; // uggh, only needed for evenEvenLinOp + mutable double clov_apply_time; + mutable double clov_deriv_time; + mutable StopWatch swatch; + }; + + + +} // End Namespace Chroma + + +#endif diff --git a/lib/actions/ferm/linop/exp_clover_term_base_w.h b/lib/actions/ferm/linop/exp_clover_term_base_w.h index 07b3f908de..dcf80cccbb 100644 --- a/lib/actions/ferm/linop/exp_clover_term_base_w.h +++ b/lib/actions/ferm/linop/exp_clover_term_base_w.h @@ -845,7 +845,9 @@ namespace Chroma // Get weight*Tr_spin gamma_mu gamma_nu A^{-1} piece triacntr(sigma_XY_dag, mu_nu_index, cb); - sigma_XY_dag[rb[cb]] *= factor; + //sigma_XY_dag[rb[cb]] *= factor; + + sigma_XY_dag[rb[cb]] *= factor*0; // These will be overwritten so no need to initialize to zero U ds_tmp_mu;