mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-10-31 12:04:33 +00:00 
			
		
		
		
	
							
								
								
									
										240
									
								
								Grid/qcd/action/fermion/CompactWilsonCloverFermion.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								Grid/qcd/action/fermion/CompactWilsonCloverFermion.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,240 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/CompactWilsonCloverFermion.h | ||||
|  | ||||
|     Copyright (C) 2020 - 2022 | ||||
|  | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|     Author: Nils Meyer <nils.meyer@ur.de> | ||||
|  | ||||
|     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 | ||||
|  | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverTypes.h> | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| // see Grid/qcd/action/fermion/WilsonCloverFermion.h for description | ||||
| // | ||||
| // Modifications done here: | ||||
| // | ||||
| // Original: clover term = 12x12 matrix per site | ||||
| // | ||||
| // But: Only two diagonal 6x6 hermitian blocks are non-zero (also true for original, verified by running) | ||||
| // Sufficient to store/transfer only the real parts of the diagonal and one triangular part | ||||
| // 2 * (6 + 15 * 2) = 72 real or 36 complex words to be stored/transfered | ||||
| // | ||||
| // Here: Above but diagonal as complex numbers, i.e., need to store/transfer | ||||
| // 2 * (6 * 2 + 15 * 2) = 84 real or 42 complex words | ||||
| // | ||||
| // Words per site and improvement compared to original (combined with the input and output spinors): | ||||
| // | ||||
| // - Original: 2*12 + 12*12 = 168 words -> 1.00 x less | ||||
| // - Minimal:  2*12 + 36    =  60 words -> 2.80 x less | ||||
| // - Here:     2*12 + 42    =  66 words -> 2.55 x less | ||||
| // | ||||
| // These improvements directly translate to wall-clock time | ||||
| // | ||||
| // Data layout: | ||||
| // | ||||
| // - diagonal and triangle part as separate lattice fields, | ||||
| //   this was faster than as 1 combined field on all tested machines | ||||
| // - diagonal: as expected | ||||
| // - triangle: store upper right triangle in row major order | ||||
| // - graphical: | ||||
| //        0  1  2  3  4 | ||||
| //           5  6  7  8 | ||||
| //              9 10 11 = upper right triangle indices | ||||
| //                12 13 | ||||
| //                   14 | ||||
| //     0 | ||||
| //        1 | ||||
| //           2 | ||||
| //              3       = diagonal indices | ||||
| //                 4 | ||||
| //                    5 | ||||
| //     0 | ||||
| //     1  5 | ||||
| //     2  6  9          = lower left triangle indices | ||||
| //     3  7 10 12 | ||||
| //     4  8 11 13 14 | ||||
| // | ||||
| // Impact on total memory consumption: | ||||
| // - Original: (2 * 1 + 8 * 1/2) 12x12 matrices = 6 12x12 matrices = 864 complex words per site | ||||
| // - Here:     (2 * 1 + 4 * 1/2) diagonal parts = 4 diagonal parts =  24 complex words per site | ||||
| //           + (2 * 1 + 4 * 1/2) triangle parts = 4 triangle parts =  60 complex words per site | ||||
| //                                                                 =  84 complex words per site | ||||
|  | ||||
| template<class Impl> | ||||
| class CompactWilsonCloverFermion : public WilsonFermion<Impl>, | ||||
|                                    public WilsonCloverHelpers<Impl>, | ||||
|                                    public CompactWilsonCloverHelpers<Impl> { | ||||
|   ///////////////////////////////////////////// | ||||
|   // Sizes | ||||
|   ///////////////////////////////////////////// | ||||
|  | ||||
| public: | ||||
|  | ||||
|   INHERIT_COMPACT_CLOVER_SIZES(Impl); | ||||
|  | ||||
|   ///////////////////////////////////////////// | ||||
|   // Type definitions | ||||
|   ///////////////////////////////////////////// | ||||
|  | ||||
| public: | ||||
|  | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|   INHERIT_CLOVER_TYPES(Impl); | ||||
|   INHERIT_COMPACT_CLOVER_TYPES(Impl); | ||||
|  | ||||
|   typedef WilsonFermion<Impl>              WilsonBase; | ||||
|   typedef WilsonCloverHelpers<Impl>        Helpers; | ||||
|   typedef CompactWilsonCloverHelpers<Impl> CompactHelpers; | ||||
|  | ||||
|   ///////////////////////////////////////////// | ||||
|   // Constructors | ||||
|   ///////////////////////////////////////////// | ||||
|  | ||||
| public: | ||||
|  | ||||
|   CompactWilsonCloverFermion(GaugeField& _Umu, | ||||
| 			    GridCartesian& Fgrid, | ||||
| 			    GridRedBlackCartesian& Hgrid, | ||||
| 			    const RealD _mass, | ||||
| 			    const RealD _csw_r = 0.0, | ||||
| 			    const RealD _csw_t = 0.0, | ||||
| 			    const RealD _cF = 1.0, | ||||
| 			    const WilsonAnisotropyCoefficients& clover_anisotropy = WilsonAnisotropyCoefficients(), | ||||
| 			    const ImplParams& impl_p = ImplParams()); | ||||
|  | ||||
|   ///////////////////////////////////////////// | ||||
|   // Member functions (implementing interface) | ||||
|   ///////////////////////////////////////////// | ||||
|  | ||||
| public: | ||||
|  | ||||
|   virtual void Instantiatable() {}; | ||||
|   int          ConstEE()     override { return 0; }; | ||||
|   int          isTrivialEE() override { return 0; }; | ||||
|  | ||||
|   void Dhop(const FermionField& in, FermionField& out, int dag) override; | ||||
|  | ||||
|   void DhopOE(const FermionField& in, FermionField& out, int dag) override; | ||||
|  | ||||
|   void DhopEO(const FermionField& in, FermionField& out, int dag) override; | ||||
|  | ||||
|   void DhopDir(const FermionField& in, FermionField& out, int dir, int disp) override; | ||||
|  | ||||
|   void DhopDirAll(const FermionField& in, std::vector<FermionField>& out) /* override */; | ||||
|  | ||||
|   void M(const FermionField& in, FermionField& out) override; | ||||
|  | ||||
|   void Mdag(const FermionField& in, FermionField& out) override; | ||||
|  | ||||
|   void Meooe(const FermionField& in, FermionField& out) override; | ||||
|  | ||||
|   void MeooeDag(const FermionField& in, FermionField& out) override; | ||||
|  | ||||
|   void Mooee(const FermionField& in, FermionField& out) override; | ||||
|  | ||||
|   void MooeeDag(const FermionField& in, FermionField& out) override; | ||||
|  | ||||
|   void MooeeInv(const FermionField& in, FermionField& out) override; | ||||
|  | ||||
|   void MooeeInvDag(const FermionField& in, FermionField& out) override; | ||||
|  | ||||
|   void Mdir(const FermionField& in, FermionField& out, int dir, int disp) override; | ||||
|  | ||||
|   void MdirAll(const FermionField& in, std::vector<FermionField>& out) override; | ||||
|  | ||||
|   void MDeriv(GaugeField& force, const FermionField& X, const FermionField& Y, int dag) override; | ||||
|  | ||||
|   void MooDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) override; | ||||
|  | ||||
|   void MeeDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) override; | ||||
|  | ||||
|   ///////////////////////////////////////////// | ||||
|   // Member functions (internals) | ||||
|   ///////////////////////////////////////////// | ||||
|  | ||||
|   void MooeeInternal(const FermionField&        in, | ||||
|                      FermionField&              out, | ||||
|                      const CloverDiagonalField& diagonal, | ||||
|                      const CloverTriangleField& triangle); | ||||
|  | ||||
|   ///////////////////////////////////////////// | ||||
|   // Helpers | ||||
|   ///////////////////////////////////////////// | ||||
|  | ||||
|   void ImportGauge(const GaugeField& _Umu) override; | ||||
|  | ||||
|   ///////////////////////////////////////////// | ||||
|   // Helpers | ||||
|   ///////////////////////////////////////////// | ||||
|  | ||||
| private: | ||||
|  | ||||
|   template<class Field> | ||||
|   const MaskField* getCorrectMaskField(const Field &in) const { | ||||
|     if(in.Grid()->_isCheckerBoarded) { | ||||
|       if(in.Checkerboard() == Odd) { | ||||
|         return &this->BoundaryMaskOdd; | ||||
|       } else { | ||||
|         return &this->BoundaryMaskEven; | ||||
|       } | ||||
|     } else { | ||||
|       return &this->BoundaryMask; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<class Field> | ||||
|   void ApplyBoundaryMask(Field& f) { | ||||
|     const MaskField* m = getCorrectMaskField(f); assert(m != nullptr); | ||||
|     assert(m != nullptr); | ||||
|     CompactHelpers::ApplyBoundaryMask(f, *m); | ||||
|   } | ||||
|  | ||||
|   ///////////////////////////////////////////// | ||||
|   // Member Data | ||||
|   ///////////////////////////////////////////// | ||||
|  | ||||
| public: | ||||
|  | ||||
|   RealD csw_r; | ||||
|   RealD csw_t; | ||||
|   RealD cF; | ||||
|  | ||||
|   bool open_boundaries; | ||||
|  | ||||
|   CloverDiagonalField Diagonal,    DiagonalEven,    DiagonalOdd; | ||||
|   CloverDiagonalField DiagonalInv, DiagonalInvEven, DiagonalInvOdd; | ||||
|  | ||||
|   CloverTriangleField Triangle,    TriangleEven,    TriangleOdd; | ||||
|   CloverTriangleField TriangleInv, TriangleInvEven, TriangleInvOdd; | ||||
|  | ||||
|   FermionField Tmp; | ||||
|  | ||||
|   MaskField BoundaryMask, BoundaryMaskEven, BoundaryMaskOdd; | ||||
| }; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -53,6 +53,7 @@ NAMESPACE_CHECK(Wilson); | ||||
| #include <Grid/qcd/action/fermion/WilsonTMFermion.h>       // 4d wilson like | ||||
| NAMESPACE_CHECK(WilsonTM); | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverFermion.h> // 4d wilson clover fermions | ||||
| #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> // 4d compact wilson clover fermions | ||||
| NAMESPACE_CHECK(WilsonClover); | ||||
| #include <Grid/qcd/action/fermion/WilsonFermion5D.h>     // 5d base used by all 5d overlap types | ||||
| NAMESPACE_CHECK(Wilson5D); | ||||
| @@ -153,6 +154,23 @@ typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplR> WilsonCloverTwoInd | ||||
| typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplF> WilsonCloverTwoIndexAntiSymmetricFermionF; | ||||
| typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplD> WilsonCloverTwoIndexAntiSymmetricFermionD; | ||||
|  | ||||
| // Compact Clover fermions | ||||
| typedef CompactWilsonCloverFermion<WilsonImplR> CompactWilsonCloverFermionR; | ||||
| typedef CompactWilsonCloverFermion<WilsonImplF> CompactWilsonCloverFermionF; | ||||
| typedef CompactWilsonCloverFermion<WilsonImplD> CompactWilsonCloverFermionD; | ||||
|  | ||||
| typedef CompactWilsonCloverFermion<WilsonAdjImplR> CompactWilsonCloverAdjFermionR; | ||||
| typedef CompactWilsonCloverFermion<WilsonAdjImplF> CompactWilsonCloverAdjFermionF; | ||||
| typedef CompactWilsonCloverFermion<WilsonAdjImplD> CompactWilsonCloverAdjFermionD; | ||||
|  | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplR> CompactWilsonCloverTwoIndexSymmetricFermionR; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplF> CompactWilsonCloverTwoIndexSymmetricFermionF; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplD> CompactWilsonCloverTwoIndexSymmetricFermionD; | ||||
|  | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplR> CompactWilsonCloverTwoIndexAntiSymmetricFermionR; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplF> CompactWilsonCloverTwoIndexAntiSymmetricFermionF; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplD> CompactWilsonCloverTwoIndexAntiSymmetricFermionD; | ||||
|  | ||||
| // Domain Wall fermions | ||||
| typedef DomainWallFermion<WilsonImplR> DomainWallFermionR; | ||||
| typedef DomainWallFermion<WilsonImplF> DomainWallFermionF; | ||||
|   | ||||
| @@ -4,10 +4,11 @@ | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/WilsonCloverFermion.h | ||||
|  | ||||
|     Copyright (C) 2017 | ||||
|     Copyright (C) 2017 - 2022 | ||||
|  | ||||
|     Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||
|     Author: David Preti <> | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|  | ||||
|     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 | ||||
| @@ -29,7 +30,8 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverTypes.h> | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| @@ -50,18 +52,15 @@ NAMESPACE_BEGIN(Grid); | ||||
| ////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| template <class Impl> | ||||
| class WilsonCloverFermion : public WilsonFermion<Impl> | ||||
| class WilsonCloverFermion : public WilsonFermion<Impl>, | ||||
|                             public WilsonCloverHelpers<Impl> | ||||
| { | ||||
| public: | ||||
|   // Types definitions | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|   template <typename vtype> | ||||
|   using iImplClover = iScalar<iMatrix<iMatrix<vtype, Impl::Dimension>, Ns>>; | ||||
|   typedef iImplClover<Simd> SiteCloverType; | ||||
|   typedef Lattice<SiteCloverType> CloverFieldType; | ||||
|   INHERIT_CLOVER_TYPES(Impl); | ||||
|  | ||||
| public: | ||||
|   typedef WilsonFermion<Impl> WilsonBase; | ||||
|   typedef WilsonFermion<Impl>       WilsonBase; | ||||
|   typedef WilsonCloverHelpers<Impl> Helpers; | ||||
|  | ||||
|   virtual int    ConstEE(void)     { return 0; }; | ||||
|   virtual void Instantiatable(void){}; | ||||
| @@ -72,42 +71,7 @@ public: | ||||
|                       const RealD _csw_r = 0.0, | ||||
|                       const RealD _csw_t = 0.0, | ||||
|                       const WilsonAnisotropyCoefficients &clover_anisotropy = WilsonAnisotropyCoefficients(), | ||||
|                       const ImplParams &impl_p = ImplParams()) : WilsonFermion<Impl>(_Umu, | ||||
|                                                                                      Fgrid, | ||||
|                                                                                      Hgrid, | ||||
|                                                                                      _mass, impl_p, clover_anisotropy), | ||||
|                                                                  CloverTerm(&Fgrid), | ||||
|                                                                  CloverTermInv(&Fgrid), | ||||
|                                                                  CloverTermEven(&Hgrid), | ||||
|                                                                  CloverTermOdd(&Hgrid), | ||||
|                                                                  CloverTermInvEven(&Hgrid), | ||||
|                                                                  CloverTermInvOdd(&Hgrid), | ||||
|                                                                  CloverTermDagEven(&Hgrid), | ||||
|                                                                  CloverTermDagOdd(&Hgrid), | ||||
|                                                                  CloverTermInvDagEven(&Hgrid), | ||||
|                                                                  CloverTermInvDagOdd(&Hgrid) | ||||
|   { | ||||
|     assert(Nd == 4); // require 4 dimensions | ||||
|  | ||||
|     if (clover_anisotropy.isAnisotropic) | ||||
|     { | ||||
|       csw_r = _csw_r * 0.5 / clover_anisotropy.xi_0; | ||||
|       diag_mass = _mass + 1.0 + (Nd - 1) * (clover_anisotropy.nu / clover_anisotropy.xi_0); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       csw_r = _csw_r * 0.5; | ||||
|       diag_mass = 4.0 + _mass; | ||||
|     } | ||||
|     csw_t = _csw_t * 0.5; | ||||
|  | ||||
|     if (csw_r == 0) | ||||
|       std::cout << GridLogWarning << "Initializing WilsonCloverFermion with csw_r = 0" << std::endl; | ||||
|     if (csw_t == 0) | ||||
|       std::cout << GridLogWarning << "Initializing WilsonCloverFermion with csw_t = 0" << std::endl; | ||||
|  | ||||
|     ImportGauge(_Umu); | ||||
|   } | ||||
|                       const ImplParams &impl_p = ImplParams()); | ||||
|  | ||||
|   virtual void M(const FermionField &in, FermionField &out); | ||||
|   virtual void Mdag(const FermionField &in, FermionField &out); | ||||
| @@ -124,250 +88,21 @@ public: | ||||
|   void ImportGauge(const GaugeField &_Umu); | ||||
|  | ||||
|   // Derivative parts unpreconditioned pseudofermions | ||||
|   void MDeriv(GaugeField &force, const FermionField &X, const FermionField &Y, int dag) | ||||
|   { | ||||
|     conformable(X.Grid(), Y.Grid()); | ||||
|     conformable(X.Grid(), force.Grid()); | ||||
|     GaugeLinkField force_mu(force.Grid()), lambda(force.Grid()); | ||||
|     GaugeField clover_force(force.Grid()); | ||||
|     PropagatorField Lambda(force.Grid()); | ||||
|   void MDeriv(GaugeField &force, const FermionField &X, const FermionField &Y, int dag); | ||||
|  | ||||
|     // Guido: Here we are hitting some performance issues: | ||||
|     // need to extract the components of the DoubledGaugeField | ||||
|     // for each call | ||||
|     // Possible solution | ||||
|     // Create a vector object to store them? (cons: wasting space) | ||||
|     std::vector<GaugeLinkField> U(Nd, this->Umu.Grid()); | ||||
|  | ||||
|     Impl::extractLinkField(U, this->Umu); | ||||
|  | ||||
|     force = Zero(); | ||||
|     // Derivative of the Wilson hopping term | ||||
|     this->DhopDeriv(force, X, Y, dag); | ||||
|  | ||||
|     /////////////////////////////////////////////////////////// | ||||
|     // Clover term derivative | ||||
|     /////////////////////////////////////////////////////////// | ||||
|     Impl::outerProductImpl(Lambda, X, Y); | ||||
|     //std::cout << "Lambda:" << Lambda << std::endl; | ||||
|  | ||||
|     Gamma::Algebra sigma[] = { | ||||
|         Gamma::Algebra::SigmaXY, | ||||
|         Gamma::Algebra::SigmaXZ, | ||||
|         Gamma::Algebra::SigmaXT, | ||||
|         Gamma::Algebra::MinusSigmaXY, | ||||
|         Gamma::Algebra::SigmaYZ, | ||||
|         Gamma::Algebra::SigmaYT, | ||||
|         Gamma::Algebra::MinusSigmaXZ, | ||||
|         Gamma::Algebra::MinusSigmaYZ, | ||||
|         Gamma::Algebra::SigmaZT, | ||||
|         Gamma::Algebra::MinusSigmaXT, | ||||
|         Gamma::Algebra::MinusSigmaYT, | ||||
|         Gamma::Algebra::MinusSigmaZT}; | ||||
|  | ||||
|     /* | ||||
|       sigma_{\mu \nu}= | ||||
|       | 0         sigma[0]  sigma[1]  sigma[2] | | ||||
|       | sigma[3]    0       sigma[4]  sigma[5] | | ||||
|       | sigma[6]  sigma[7]     0      sigma[8] | | ||||
|       | sigma[9]  sigma[10] sigma[11]   0      | | ||||
|     */ | ||||
|  | ||||
|     int count = 0; | ||||
|     clover_force = Zero(); | ||||
|     for (int mu = 0; mu < 4; mu++) | ||||
|     { | ||||
|       force_mu = Zero(); | ||||
|       for (int nu = 0; nu < 4; nu++) | ||||
|       { | ||||
|         if (mu == nu) | ||||
|         continue; | ||||
|          | ||||
|         RealD factor; | ||||
|         if (nu == 4 || mu == 4) | ||||
|         { | ||||
|           factor = 2.0 * csw_t; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|           factor = 2.0 * csw_r; | ||||
|         } | ||||
|         PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked | ||||
|         Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok | ||||
|         force_mu -= factor*Cmunu(U, lambda, mu, nu);                   // checked | ||||
|         count++; | ||||
|       } | ||||
|  | ||||
|       pokeLorentz(clover_force, U[mu] * force_mu, mu); | ||||
|     } | ||||
|     //clover_force *= csw; | ||||
|     force += clover_force; | ||||
|   } | ||||
|  | ||||
|   // Computing C_{\mu \nu}(x) as in Eq.(B.39) in Zbigniew Sroczynski's PhD thesis | ||||
|   GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) | ||||
|   { | ||||
|     conformable(lambda.Grid(), U[0].Grid()); | ||||
|     GaugeLinkField out(lambda.Grid()), tmp(lambda.Grid()); | ||||
|     // insertion in upper staple | ||||
|     // please check redundancy of shift operations | ||||
|  | ||||
|     // C1+ | ||||
|     tmp = lambda * U[nu]; | ||||
|     out = Impl::ShiftStaple(Impl::CovShiftForward(tmp, nu, Impl::CovShiftBackward(U[mu], mu, Impl::CovShiftIdentityBackward(U[nu], nu))), mu); | ||||
|  | ||||
|     // C2+ | ||||
|     tmp = U[mu] * Impl::ShiftStaple(adj(lambda), mu); | ||||
|     out += Impl::ShiftStaple(Impl::CovShiftForward(U[nu], nu, Impl::CovShiftBackward(tmp, mu, Impl::CovShiftIdentityBackward(U[nu], nu))), mu); | ||||
|  | ||||
|     // C3+ | ||||
|     tmp = U[nu] * Impl::ShiftStaple(adj(lambda), nu); | ||||
|     out += Impl::ShiftStaple(Impl::CovShiftForward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, Impl::CovShiftIdentityBackward(tmp, nu))), mu); | ||||
|  | ||||
|     // C4+ | ||||
|     out += Impl::ShiftStaple(Impl::CovShiftForward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, Impl::CovShiftIdentityBackward(U[nu], nu))), mu) * lambda; | ||||
|  | ||||
|     // insertion in lower staple | ||||
|     // C1- | ||||
|     out -= Impl::ShiftStaple(lambda, mu) * Impl::ShiftStaple(Impl::CovShiftBackward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, U[nu])), mu); | ||||
|  | ||||
|     // C2- | ||||
|     tmp = adj(lambda) * U[nu]; | ||||
|     out -= Impl::ShiftStaple(Impl::CovShiftBackward(tmp, nu, Impl::CovShiftBackward(U[mu], mu, U[nu])), mu); | ||||
|  | ||||
|     // C3- | ||||
|     tmp = lambda * U[nu]; | ||||
|     out -= Impl::ShiftStaple(Impl::CovShiftBackward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, tmp)), mu); | ||||
|  | ||||
|     // C4- | ||||
|     out -= Impl::ShiftStaple(Impl::CovShiftBackward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, U[nu])), mu) * lambda; | ||||
|  | ||||
|     return out; | ||||
|   } | ||||
|  | ||||
| protected: | ||||
| public: | ||||
|   // here fixing the 4 dimensions, make it more general? | ||||
|  | ||||
|   RealD csw_r;                                               // Clover coefficient - spatial | ||||
|   RealD csw_t;                                               // Clover coefficient - temporal | ||||
|   RealD diag_mass;                                           // Mass term | ||||
|   CloverFieldType CloverTerm, CloverTermInv;                 // Clover term | ||||
|   CloverFieldType CloverTermEven, CloverTermOdd;             // Clover term EO | ||||
|   CloverFieldType CloverTermInvEven, CloverTermInvOdd;       // Clover term Inv EO | ||||
|   CloverFieldType CloverTermDagEven, CloverTermDagOdd;       // Clover term Dag EO | ||||
|   CloverFieldType CloverTermInvDagEven, CloverTermInvDagOdd; // Clover term Inv Dag EO | ||||
|  | ||||
|  public: | ||||
|   // eventually these can be compressed into 6x6 blocks instead of the 12x12 | ||||
|   // using the DeGrand-Rossi basis for the gamma matrices | ||||
|   CloverFieldType fillCloverYZ(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverFieldType T(F.Grid()); | ||||
|     T = Zero(); | ||||
|     autoView(T_v,T,AcceleratorWrite); | ||||
|     autoView(F_v,F,AcceleratorRead); | ||||
|     accelerator_for(i, CloverTerm.Grid()->oSites(),1, | ||||
|     { | ||||
|       T_v[i]()(0, 1) = timesMinusI(F_v[i]()()); | ||||
|       T_v[i]()(1, 0) = timesMinusI(F_v[i]()()); | ||||
|       T_v[i]()(2, 3) = timesMinusI(F_v[i]()()); | ||||
|       T_v[i]()(3, 2) = timesMinusI(F_v[i]()()); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   CloverFieldType fillCloverXZ(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverFieldType T(F.Grid()); | ||||
|     T = Zero(); | ||||
|      | ||||
|     autoView(T_v, T,AcceleratorWrite); | ||||
|     autoView(F_v, F,AcceleratorRead); | ||||
|     accelerator_for(i, CloverTerm.Grid()->oSites(),1, | ||||
|     { | ||||
|       T_v[i]()(0, 1) = -F_v[i]()(); | ||||
|       T_v[i]()(1, 0) = F_v[i]()(); | ||||
|       T_v[i]()(2, 3) = -F_v[i]()(); | ||||
|       T_v[i]()(3, 2) = F_v[i]()(); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   CloverFieldType fillCloverXY(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverFieldType T(F.Grid()); | ||||
|     T = Zero(); | ||||
|  | ||||
|     autoView(T_v,T,AcceleratorWrite); | ||||
|     autoView(F_v,F,AcceleratorRead); | ||||
|     accelerator_for(i, CloverTerm.Grid()->oSites(),1, | ||||
|     { | ||||
|       T_v[i]()(0, 0) = timesMinusI(F_v[i]()()); | ||||
|       T_v[i]()(1, 1) = timesI(F_v[i]()()); | ||||
|       T_v[i]()(2, 2) = timesMinusI(F_v[i]()()); | ||||
|       T_v[i]()(3, 3) = timesI(F_v[i]()()); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   CloverFieldType fillCloverXT(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverFieldType T(F.Grid()); | ||||
|     T = Zero(); | ||||
|  | ||||
|     autoView( T_v , T, AcceleratorWrite); | ||||
|     autoView( F_v , F, AcceleratorRead); | ||||
|     accelerator_for(i, CloverTerm.Grid()->oSites(),1, | ||||
|     { | ||||
|       T_v[i]()(0, 1) = timesI(F_v[i]()()); | ||||
|       T_v[i]()(1, 0) = timesI(F_v[i]()()); | ||||
|       T_v[i]()(2, 3) = timesMinusI(F_v[i]()()); | ||||
|       T_v[i]()(3, 2) = timesMinusI(F_v[i]()()); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   CloverFieldType fillCloverYT(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverFieldType T(F.Grid()); | ||||
|     T = Zero(); | ||||
|      | ||||
|     autoView( T_v ,T,AcceleratorWrite); | ||||
|     autoView( F_v ,F,AcceleratorRead); | ||||
|     accelerator_for(i, CloverTerm.Grid()->oSites(),1, | ||||
|     { | ||||
|       T_v[i]()(0, 1) = -(F_v[i]()()); | ||||
|       T_v[i]()(1, 0) = (F_v[i]()()); | ||||
|       T_v[i]()(2, 3) = (F_v[i]()()); | ||||
|       T_v[i]()(3, 2) = -(F_v[i]()()); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   CloverFieldType fillCloverZT(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverFieldType T(F.Grid()); | ||||
|  | ||||
|     T = Zero(); | ||||
|  | ||||
|     autoView( T_v , T,AcceleratorWrite); | ||||
|     autoView( F_v , F,AcceleratorRead); | ||||
|     accelerator_for(i, CloverTerm.Grid()->oSites(),1, | ||||
|     { | ||||
|       T_v[i]()(0, 0) = timesI(F_v[i]()()); | ||||
|       T_v[i]()(1, 1) = timesMinusI(F_v[i]()()); | ||||
|       T_v[i]()(2, 2) = timesMinusI(F_v[i]()()); | ||||
|       T_v[i]()(3, 3) = timesI(F_v[i]()()); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|   CloverField CloverTerm, CloverTermInv;                     // Clover term | ||||
|   CloverField CloverTermEven, CloverTermOdd;                 // Clover term EO | ||||
|   CloverField CloverTermInvEven, CloverTermInvOdd;           // Clover term Inv EO | ||||
|   CloverField CloverTermDagEven, CloverTermDagOdd;           // Clover term Dag EO | ||||
|   CloverField CloverTermInvDagEven, CloverTermInvDagOdd;     // Clover term Inv Dag EO | ||||
| }; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										761
									
								
								Grid/qcd/action/fermion/WilsonCloverHelpers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										761
									
								
								Grid/qcd/action/fermion/WilsonCloverHelpers.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,761 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/WilsonCloverHelpers.h | ||||
|  | ||||
|     Copyright (C) 2021 - 2022 | ||||
|  | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|  | ||||
|     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 | ||||
|  | ||||
| // Helper routines that implement common clover functionality | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| template<class Impl> class WilsonCloverHelpers { | ||||
| public: | ||||
|  | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|   INHERIT_CLOVER_TYPES(Impl); | ||||
|  | ||||
|   // Computing C_{\mu \nu}(x) as in Eq.(B.39) in Zbigniew Sroczynski's PhD thesis | ||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) | ||||
|   { | ||||
|     conformable(lambda.Grid(), U[0].Grid()); | ||||
|     GaugeLinkField out(lambda.Grid()), tmp(lambda.Grid()); | ||||
|     // insertion in upper staple | ||||
|     // please check redundancy of shift operations | ||||
|  | ||||
|     // C1+ | ||||
|     tmp = lambda * U[nu]; | ||||
|     out = Impl::ShiftStaple(Impl::CovShiftForward(tmp, nu, Impl::CovShiftBackward(U[mu], mu, Impl::CovShiftIdentityBackward(U[nu], nu))), mu); | ||||
|  | ||||
|     // C2+ | ||||
|     tmp = U[mu] * Impl::ShiftStaple(adj(lambda), mu); | ||||
|     out += Impl::ShiftStaple(Impl::CovShiftForward(U[nu], nu, Impl::CovShiftBackward(tmp, mu, Impl::CovShiftIdentityBackward(U[nu], nu))), mu); | ||||
|  | ||||
|     // C3+ | ||||
|     tmp = U[nu] * Impl::ShiftStaple(adj(lambda), nu); | ||||
|     out += Impl::ShiftStaple(Impl::CovShiftForward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, Impl::CovShiftIdentityBackward(tmp, nu))), mu); | ||||
|  | ||||
|     // C4+ | ||||
|     out += Impl::ShiftStaple(Impl::CovShiftForward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, Impl::CovShiftIdentityBackward(U[nu], nu))), mu) * lambda; | ||||
|  | ||||
|     // insertion in lower staple | ||||
|     // C1- | ||||
|     out -= Impl::ShiftStaple(lambda, mu) * Impl::ShiftStaple(Impl::CovShiftBackward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, U[nu])), mu); | ||||
|  | ||||
|     // C2- | ||||
|     tmp = adj(lambda) * U[nu]; | ||||
|     out -= Impl::ShiftStaple(Impl::CovShiftBackward(tmp, nu, Impl::CovShiftBackward(U[mu], mu, U[nu])), mu); | ||||
|  | ||||
|     // C3- | ||||
|     tmp = lambda * U[nu]; | ||||
|     out -= Impl::ShiftStaple(Impl::CovShiftBackward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, tmp)), mu); | ||||
|  | ||||
|     // C4- | ||||
|     out -= Impl::ShiftStaple(Impl::CovShiftBackward(U[nu], nu, Impl::CovShiftBackward(U[mu], mu, U[nu])), mu) * lambda; | ||||
|  | ||||
|     return out; | ||||
|   } | ||||
|  | ||||
|   static CloverField fillCloverYZ(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverField T(F.Grid()); | ||||
|     T = Zero(); | ||||
|     autoView(T_v,T,AcceleratorWrite); | ||||
|     autoView(F_v,F,AcceleratorRead); | ||||
|     accelerator_for(i, T.Grid()->oSites(),CloverField::vector_type::Nsimd(), | ||||
|     { | ||||
|       coalescedWrite(T_v[i]()(0, 1), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(1, 0), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(2, 3), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(3, 2), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   static CloverField fillCloverXZ(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverField T(F.Grid()); | ||||
|     T = Zero(); | ||||
|      | ||||
|     autoView(T_v, T,AcceleratorWrite); | ||||
|     autoView(F_v, F,AcceleratorRead); | ||||
|     accelerator_for(i, T.Grid()->oSites(),CloverField::vector_type::Nsimd(), | ||||
|     { | ||||
|       coalescedWrite(T_v[i]()(0, 1), coalescedRead(-F_v[i]()())); | ||||
|       coalescedWrite(T_v[i]()(1, 0), coalescedRead(F_v[i]()())); | ||||
|       coalescedWrite(T_v[i]()(2, 3), coalescedRead(-F_v[i]()())); | ||||
|       coalescedWrite(T_v[i]()(3, 2), coalescedRead(F_v[i]()())); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   static CloverField fillCloverXY(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverField T(F.Grid()); | ||||
|     T = Zero(); | ||||
|  | ||||
|     autoView(T_v,T,AcceleratorWrite); | ||||
|     autoView(F_v,F,AcceleratorRead); | ||||
|     accelerator_for(i, T.Grid()->oSites(),CloverField::vector_type::Nsimd(), | ||||
|     { | ||||
|       coalescedWrite(T_v[i]()(0, 0), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(1, 1), coalescedRead(timesI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(2, 2), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(3, 3), coalescedRead(timesI(F_v[i]()()))); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   static CloverField fillCloverXT(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverField T(F.Grid()); | ||||
|     T = Zero(); | ||||
|  | ||||
|     autoView( T_v , T, AcceleratorWrite); | ||||
|     autoView( F_v , F, AcceleratorRead); | ||||
|     accelerator_for(i, T.Grid()->oSites(),CloverField::vector_type::Nsimd(), | ||||
|     { | ||||
|       coalescedWrite(T_v[i]()(0, 1), coalescedRead(timesI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(1, 0), coalescedRead(timesI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(2, 3), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(3, 2), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   static CloverField fillCloverYT(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverField T(F.Grid()); | ||||
|     T = Zero(); | ||||
|      | ||||
|     autoView( T_v ,T,AcceleratorWrite); | ||||
|     autoView( F_v ,F,AcceleratorRead); | ||||
|     accelerator_for(i, T.Grid()->oSites(),CloverField::vector_type::Nsimd(), | ||||
|     { | ||||
|       coalescedWrite(T_v[i]()(0, 1), coalescedRead(-(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(1, 0), coalescedRead((F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(2, 3), coalescedRead((F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(3, 2), coalescedRead(-(F_v[i]()()))); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   static CloverField fillCloverZT(const GaugeLinkField &F) | ||||
|   { | ||||
|     CloverField T(F.Grid()); | ||||
|  | ||||
|     T = Zero(); | ||||
|  | ||||
|     autoView( T_v , T,AcceleratorWrite); | ||||
|     autoView( F_v , F,AcceleratorRead); | ||||
|     accelerator_for(i, T.Grid()->oSites(),CloverField::vector_type::Nsimd(), | ||||
|     { | ||||
|       coalescedWrite(T_v[i]()(0, 0), coalescedRead(timesI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(1, 1), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(2, 2), coalescedRead(timesMinusI(F_v[i]()()))); | ||||
|       coalescedWrite(T_v[i]()(3, 3), coalescedRead(timesI(F_v[i]()()))); | ||||
|     }); | ||||
|  | ||||
|     return T; | ||||
|   } | ||||
|  | ||||
|   template<class _Spinor> | ||||
|   static accelerator_inline void multClover(_Spinor& phi, const SiteClover& C, const _Spinor& chi) { | ||||
|     auto CC = coalescedRead(C); | ||||
|     mult(&phi, &CC, &chi); | ||||
|   } | ||||
|  | ||||
|   template<class _SpinorField> | ||||
|   inline void multCloverField(_SpinorField& out, const CloverField& C, const _SpinorField& phi) { | ||||
|     const int Nsimd = SiteSpinor::Nsimd(); | ||||
|     autoView(out_v, out, AcceleratorWrite); | ||||
|     autoView(phi_v, phi, AcceleratorRead); | ||||
|     autoView(C_v,   C,   AcceleratorRead); | ||||
|     typedef decltype(coalescedRead(out_v[0])) calcSpinor; | ||||
|     accelerator_for(sss,out.Grid()->oSites(),Nsimd,{ | ||||
|       calcSpinor tmp; | ||||
|       multClover(tmp,C_v[sss],phi_v(sss)); | ||||
|       coalescedWrite(out_v[sss],tmp); | ||||
|     }); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| template<class Impl> class CompactWilsonCloverHelpers { | ||||
| public: | ||||
|  | ||||
|   INHERIT_COMPACT_CLOVER_SIZES(Impl); | ||||
|  | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|   INHERIT_CLOVER_TYPES(Impl); | ||||
|   INHERIT_COMPACT_CLOVER_TYPES(Impl); | ||||
|  | ||||
|   #if 0 | ||||
|   static accelerator_inline typename SiteCloverTriangle::vector_type triangle_elem(const SiteCloverTriangle& triangle, int block, int i, int j) { | ||||
|     assert(i != j); | ||||
|     if(i < j) { | ||||
|       return triangle()(block)(triangle_index(i, j)); | ||||
|     } else { // i > j | ||||
|       return conjugate(triangle()(block)(triangle_index(i, j))); | ||||
|     } | ||||
|   } | ||||
|   #else | ||||
|   template<typename vobj> | ||||
|   static accelerator_inline vobj triangle_elem(const iImplCloverTriangle<vobj>& triangle, int block, int i, int j) { | ||||
|     assert(i != j); | ||||
|     if(i < j) { | ||||
|       return triangle()(block)(triangle_index(i, j)); | ||||
|     } else { // i > j | ||||
|       return conjugate(triangle()(block)(triangle_index(i, j))); | ||||
|     } | ||||
|   } | ||||
|   #endif | ||||
|  | ||||
|   static accelerator_inline int triangle_index(int i, int j) { | ||||
|     if(i == j) | ||||
|       return 0; | ||||
|     else if(i < j) | ||||
|       return Nred * (Nred - 1) / 2 - (Nred - i) * (Nred - i - 1) / 2 + j - i - 1; | ||||
|     else // i > j | ||||
|       return Nred * (Nred - 1) / 2 - (Nred - j) * (Nred - j - 1) / 2 + i - j - 1; | ||||
|   } | ||||
|  | ||||
|   static void MooeeKernel_gpu(int                        Nsite, | ||||
|                               int                        Ls, | ||||
|                               const FermionField&        in, | ||||
|                               FermionField&              out, | ||||
|                               const CloverDiagonalField& diagonal, | ||||
|                               const CloverTriangleField& triangle) { | ||||
|     autoView(diagonal_v, diagonal, AcceleratorRead); | ||||
|     autoView(triangle_v, triangle, AcceleratorRead); | ||||
|     autoView(in_v,       in,       AcceleratorRead); | ||||
|     autoView(out_v,      out,      AcceleratorWrite); | ||||
|  | ||||
|     typedef decltype(coalescedRead(out_v[0])) CalcSpinor; | ||||
|  | ||||
|     const uint64_t NN = Nsite * Ls; | ||||
|  | ||||
|     accelerator_for(ss, NN, Simd::Nsimd(), { | ||||
|       int sF = ss; | ||||
|       int sU = ss/Ls; | ||||
|       CalcSpinor res; | ||||
|       CalcSpinor in_t = in_v(sF); | ||||
|       auto diagonal_t = diagonal_v(sU); | ||||
|       auto triangle_t = triangle_v(sU); | ||||
|       for(int block=0; block<Nhs; block++) { | ||||
|         int s_start = block*Nhs; | ||||
|         for(int i=0; i<Nred; i++) { | ||||
|           int si = s_start + i/Nc, ci = i%Nc; | ||||
|           res()(si)(ci) = diagonal_t()(block)(i) * in_t()(si)(ci); | ||||
|           for(int j=0; j<Nred; j++) { | ||||
|             if (j == i) continue; | ||||
|             int sj = s_start + j/Nc, cj = j%Nc; | ||||
|             res()(si)(ci) = res()(si)(ci) + triangle_elem(triangle_t, block, i, j) * in_t()(sj)(cj); | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|       coalescedWrite(out_v[sF], res); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   static void MooeeKernel_cpu(int                        Nsite, | ||||
|                               int                        Ls, | ||||
|                               const FermionField&        in, | ||||
|                               FermionField&              out, | ||||
|                               const CloverDiagonalField& diagonal, | ||||
|                               const CloverTriangleField& triangle) { | ||||
|     autoView(diagonal_v, diagonal, CpuRead); | ||||
|     autoView(triangle_v, triangle, CpuRead); | ||||
|     autoView(in_v,       in,       CpuRead); | ||||
|     autoView(out_v,      out,      CpuWrite); | ||||
|  | ||||
|     typedef SiteSpinor CalcSpinor; | ||||
|  | ||||
| #if defined(A64FX) || defined(A64FXFIXEDSIZE) | ||||
| #define PREFETCH_CLOVER(BASE) {                                     \ | ||||
|     uint64_t base;                                                  \ | ||||
|     int pf_dist_L1 = 1;                                             \ | ||||
|     int pf_dist_L2 = -5; /* -> penalty -> disable */                \ | ||||
|                                                                     \ | ||||
|     if ((pf_dist_L1 >= 0) && (sU + pf_dist_L1 < Nsite)) {           \ | ||||
|       base = (uint64_t)&diag_t()(pf_dist_L1+BASE)(0);               \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base +    0), SV_PLDL1STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base +  256), SV_PLDL1STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base +  512), SV_PLDL1STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base +  768), SV_PLDL1STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base + 1024), SV_PLDL1STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base + 1280), SV_PLDL1STRM); \ | ||||
|     }                                                               \ | ||||
|                                                                     \ | ||||
|     if ((pf_dist_L2 >= 0) && (sU + pf_dist_L2 < Nsite)) {           \ | ||||
|       base = (uint64_t)&diag_t()(pf_dist_L2+BASE)(0);               \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base +    0), SV_PLDL2STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base +  256), SV_PLDL2STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base +  512), SV_PLDL2STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base +  768), SV_PLDL2STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base + 1024), SV_PLDL2STRM); \ | ||||
|       svprfd(svptrue_b64(), (int64_t*)(base + 1280), SV_PLDL2STRM); \ | ||||
|     }                                                               \ | ||||
|   } | ||||
| // TODO: Implement/generalize this for other architectures | ||||
| // I played around a bit on KNL (see below) but didn't bring anything | ||||
| // #elif defined(AVX512) | ||||
| // #define PREFETCH_CLOVER(BASE) {                              \ | ||||
| //     uint64_t base;                                           \ | ||||
| //     int pf_dist_L1 = 1;                                      \ | ||||
| //     int pf_dist_L2 = +4;                                     \ | ||||
| //                                                              \ | ||||
| //     if ((pf_dist_L1 >= 0) && (sU + pf_dist_L1 < Nsite)) {    \ | ||||
| //       base = (uint64_t)&diag_t()(pf_dist_L1+BASE)(0);        \ | ||||
| //       _mm_prefetch((const char*)(base +    0), _MM_HINT_T0); \ | ||||
| //       _mm_prefetch((const char*)(base +   64), _MM_HINT_T0); \ | ||||
| //       _mm_prefetch((const char*)(base +  128), _MM_HINT_T0); \ | ||||
| //       _mm_prefetch((const char*)(base +  192), _MM_HINT_T0); \ | ||||
| //       _mm_prefetch((const char*)(base +  256), _MM_HINT_T0); \ | ||||
| //       _mm_prefetch((const char*)(base +  320), _MM_HINT_T0); \ | ||||
| //     }                                                        \ | ||||
| //                                                              \ | ||||
| //     if ((pf_dist_L2 >= 0) && (sU + pf_dist_L2 < Nsite)) {    \ | ||||
| //       base = (uint64_t)&diag_t()(pf_dist_L2+BASE)(0);        \ | ||||
| //       _mm_prefetch((const char*)(base +    0), _MM_HINT_T1); \ | ||||
| //       _mm_prefetch((const char*)(base +   64), _MM_HINT_T1); \ | ||||
| //       _mm_prefetch((const char*)(base +  128), _MM_HINT_T1); \ | ||||
| //       _mm_prefetch((const char*)(base +  192), _MM_HINT_T1); \ | ||||
| //       _mm_prefetch((const char*)(base +  256), _MM_HINT_T1); \ | ||||
| //       _mm_prefetch((const char*)(base +  320), _MM_HINT_T1); \ | ||||
| //     }                                                        \ | ||||
| //   } | ||||
| #else | ||||
| #define PREFETCH_CLOVER(BASE) | ||||
| #endif | ||||
|  | ||||
|     const uint64_t NN = Nsite * Ls; | ||||
|  | ||||
|     thread_for(ss, NN, { | ||||
|       int sF = ss; | ||||
|       int sU = ss/Ls; | ||||
|       CalcSpinor res; | ||||
|       CalcSpinor in_t = in_v[sF]; | ||||
|       auto diag_t     = diagonal_v[sU]; // "diag" instead of "diagonal" here to make code below easier to read | ||||
|       auto triangle_t = triangle_v[sU]; | ||||
|  | ||||
|       // upper half | ||||
|       PREFETCH_CLOVER(0); | ||||
|  | ||||
|       auto in_cc_0_0 = conjugate(in_t()(0)(0)); // Nils: reduces number | ||||
|       auto in_cc_0_1 = conjugate(in_t()(0)(1)); // of conjugates from | ||||
|       auto in_cc_0_2 = conjugate(in_t()(0)(2)); // 30 to 20 | ||||
|       auto in_cc_1_0 = conjugate(in_t()(1)(0)); | ||||
|       auto in_cc_1_1 = conjugate(in_t()(1)(1)); | ||||
|  | ||||
|       res()(0)(0) =               diag_t()(0)( 0) * in_t()(0)(0) | ||||
|                   +           triangle_t()(0)( 0) * in_t()(0)(1) | ||||
|                   +           triangle_t()(0)( 1) * in_t()(0)(2) | ||||
|                   +           triangle_t()(0)( 2) * in_t()(1)(0) | ||||
|                   +           triangle_t()(0)( 3) * in_t()(1)(1) | ||||
|                   +           triangle_t()(0)( 4) * in_t()(1)(2); | ||||
|  | ||||
|       res()(0)(1) =           triangle_t()(0)( 0) * in_cc_0_0; | ||||
|       res()(0)(1) =               diag_t()(0)( 1) * in_t()(0)(1) | ||||
|                   +           triangle_t()(0)( 5) * in_t()(0)(2) | ||||
|                   +           triangle_t()(0)( 6) * in_t()(1)(0) | ||||
|                   +           triangle_t()(0)( 7) * in_t()(1)(1) | ||||
|                   +           triangle_t()(0)( 8) * in_t()(1)(2) | ||||
|                   + conjugate(       res()(0)( 1)); | ||||
|  | ||||
|       res()(0)(2) =           triangle_t()(0)( 1) * in_cc_0_0 | ||||
|                   +           triangle_t()(0)( 5) * in_cc_0_1; | ||||
|       res()(0)(2) =               diag_t()(0)( 2) * in_t()(0)(2) | ||||
|                   +           triangle_t()(0)( 9) * in_t()(1)(0) | ||||
|                   +           triangle_t()(0)(10) * in_t()(1)(1) | ||||
|                   +           triangle_t()(0)(11) * in_t()(1)(2) | ||||
|                   + conjugate(       res()(0)( 2)); | ||||
|  | ||||
|       res()(1)(0) =           triangle_t()(0)( 2) * in_cc_0_0 | ||||
|                   +           triangle_t()(0)( 6) * in_cc_0_1 | ||||
|                   +           triangle_t()(0)( 9) * in_cc_0_2; | ||||
|       res()(1)(0) =               diag_t()(0)( 3) * in_t()(1)(0) | ||||
|                   +           triangle_t()(0)(12) * in_t()(1)(1) | ||||
|                   +           triangle_t()(0)(13) * in_t()(1)(2) | ||||
|                   + conjugate(       res()(1)( 0)); | ||||
|  | ||||
|       res()(1)(1) =           triangle_t()(0)( 3) * in_cc_0_0 | ||||
|                   +           triangle_t()(0)( 7) * in_cc_0_1 | ||||
|                   +           triangle_t()(0)(10) * in_cc_0_2 | ||||
|                   +           triangle_t()(0)(12) * in_cc_1_0; | ||||
|       res()(1)(1) =               diag_t()(0)( 4) * in_t()(1)(1) | ||||
|                   +           triangle_t()(0)(14) * in_t()(1)(2) | ||||
|                   + conjugate(       res()(1)( 1)); | ||||
|  | ||||
|       res()(1)(2) =           triangle_t()(0)( 4) * in_cc_0_0 | ||||
|                   +           triangle_t()(0)( 8) * in_cc_0_1 | ||||
|                   +           triangle_t()(0)(11) * in_cc_0_2 | ||||
|                   +           triangle_t()(0)(13) * in_cc_1_0 | ||||
|                   +           triangle_t()(0)(14) * in_cc_1_1; | ||||
|       res()(1)(2) =               diag_t()(0)( 5) * in_t()(1)(2) | ||||
|                   + conjugate(       res()(1)( 2)); | ||||
|  | ||||
|       vstream(out_v[sF]()(0)(0), res()(0)(0)); | ||||
|       vstream(out_v[sF]()(0)(1), res()(0)(1)); | ||||
|       vstream(out_v[sF]()(0)(2), res()(0)(2)); | ||||
|       vstream(out_v[sF]()(1)(0), res()(1)(0)); | ||||
|       vstream(out_v[sF]()(1)(1), res()(1)(1)); | ||||
|       vstream(out_v[sF]()(1)(2), res()(1)(2)); | ||||
|  | ||||
|       // lower half | ||||
|       PREFETCH_CLOVER(1); | ||||
|  | ||||
|       auto in_cc_2_0 = conjugate(in_t()(2)(0)); | ||||
|       auto in_cc_2_1 = conjugate(in_t()(2)(1)); | ||||
|       auto in_cc_2_2 = conjugate(in_t()(2)(2)); | ||||
|       auto in_cc_3_0 = conjugate(in_t()(3)(0)); | ||||
|       auto in_cc_3_1 = conjugate(in_t()(3)(1)); | ||||
|  | ||||
|       res()(2)(0) =               diag_t()(1)( 0) * in_t()(2)(0) | ||||
|                   +           triangle_t()(1)( 0) * in_t()(2)(1) | ||||
|                   +           triangle_t()(1)( 1) * in_t()(2)(2) | ||||
|                   +           triangle_t()(1)( 2) * in_t()(3)(0) | ||||
|                   +           triangle_t()(1)( 3) * in_t()(3)(1) | ||||
|                   +           triangle_t()(1)( 4) * in_t()(3)(2); | ||||
|  | ||||
|       res()(2)(1) =           triangle_t()(1)( 0) * in_cc_2_0; | ||||
|       res()(2)(1) =               diag_t()(1)( 1) * in_t()(2)(1) | ||||
|                   +           triangle_t()(1)( 5) * in_t()(2)(2) | ||||
|                   +           triangle_t()(1)( 6) * in_t()(3)(0) | ||||
|                   +           triangle_t()(1)( 7) * in_t()(3)(1) | ||||
|                   +           triangle_t()(1)( 8) * in_t()(3)(2) | ||||
|                   + conjugate(       res()(2)( 1)); | ||||
|  | ||||
|       res()(2)(2) =           triangle_t()(1)( 1) * in_cc_2_0 | ||||
|                   +           triangle_t()(1)( 5) * in_cc_2_1; | ||||
|       res()(2)(2) =               diag_t()(1)( 2) * in_t()(2)(2) | ||||
|                   +           triangle_t()(1)( 9) * in_t()(3)(0) | ||||
|                   +           triangle_t()(1)(10) * in_t()(3)(1) | ||||
|                   +           triangle_t()(1)(11) * in_t()(3)(2) | ||||
|                   + conjugate(       res()(2)( 2)); | ||||
|  | ||||
|       res()(3)(0) =           triangle_t()(1)( 2) * in_cc_2_0 | ||||
|                   +           triangle_t()(1)( 6) * in_cc_2_1 | ||||
|                   +           triangle_t()(1)( 9) * in_cc_2_2; | ||||
|       res()(3)(0) =               diag_t()(1)( 3) * in_t()(3)(0) | ||||
|                   +           triangle_t()(1)(12) * in_t()(3)(1) | ||||
|                   +           triangle_t()(1)(13) * in_t()(3)(2) | ||||
|                   + conjugate(       res()(3)( 0)); | ||||
|  | ||||
|       res()(3)(1) =           triangle_t()(1)( 3) * in_cc_2_0 | ||||
|                   +           triangle_t()(1)( 7) * in_cc_2_1 | ||||
|                   +           triangle_t()(1)(10) * in_cc_2_2 | ||||
|                   +           triangle_t()(1)(12) * in_cc_3_0; | ||||
|       res()(3)(1) =               diag_t()(1)( 4) * in_t()(3)(1) | ||||
|                   +           triangle_t()(1)(14) * in_t()(3)(2) | ||||
|                   + conjugate(       res()(3)( 1)); | ||||
|  | ||||
|       res()(3)(2) =           triangle_t()(1)( 4) * in_cc_2_0 | ||||
|                   +           triangle_t()(1)( 8) * in_cc_2_1 | ||||
|                   +           triangle_t()(1)(11) * in_cc_2_2 | ||||
|                   +           triangle_t()(1)(13) * in_cc_3_0 | ||||
|                   +           triangle_t()(1)(14) * in_cc_3_1; | ||||
|       res()(3)(2) =               diag_t()(1)( 5) * in_t()(3)(2) | ||||
|                   + conjugate(       res()(3)( 2)); | ||||
|  | ||||
|       vstream(out_v[sF]()(2)(0), res()(2)(0)); | ||||
|       vstream(out_v[sF]()(2)(1), res()(2)(1)); | ||||
|       vstream(out_v[sF]()(2)(2), res()(2)(2)); | ||||
|       vstream(out_v[sF]()(3)(0), res()(3)(0)); | ||||
|       vstream(out_v[sF]()(3)(1), res()(3)(1)); | ||||
|       vstream(out_v[sF]()(3)(2), res()(3)(2)); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   static void MooeeKernel(int                        Nsite, | ||||
|                           int                        Ls, | ||||
|                           const FermionField&        in, | ||||
|                           FermionField&              out, | ||||
|                           const CloverDiagonalField& diagonal, | ||||
|                           const CloverTriangleField& triangle) { | ||||
| #if defined(GRID_CUDA) || defined(GRID_HIP) | ||||
|     MooeeKernel_gpu(Nsite, Ls, in, out, diagonal, triangle); | ||||
| #else | ||||
|     MooeeKernel_cpu(Nsite, Ls, in, out, diagonal, triangle); | ||||
| #endif | ||||
|   } | ||||
|  | ||||
|   static void Invert(const CloverDiagonalField& diagonal, | ||||
|                      const CloverTriangleField& triangle, | ||||
|                      CloverDiagonalField&       diagonalInv, | ||||
|                      CloverTriangleField&       triangleInv) { | ||||
|     conformable(diagonal, diagonalInv); | ||||
|     conformable(triangle, triangleInv); | ||||
|     conformable(diagonal, triangle); | ||||
|  | ||||
|     diagonalInv.Checkerboard() = diagonal.Checkerboard(); | ||||
|     triangleInv.Checkerboard() = triangle.Checkerboard(); | ||||
|  | ||||
|     GridBase* grid = diagonal.Grid(); | ||||
|  | ||||
|     long lsites = grid->lSites(); | ||||
|  | ||||
|     typedef typename SiteCloverDiagonal::scalar_object scalar_object_diagonal; | ||||
|     typedef typename SiteCloverTriangle::scalar_object scalar_object_triangle; | ||||
|  | ||||
|     autoView(diagonal_v,  diagonal,  CpuRead); | ||||
|     autoView(triangle_v,  triangle,  CpuRead); | ||||
|     autoView(diagonalInv_v, diagonalInv, CpuWrite); | ||||
|     autoView(triangleInv_v, triangleInv, CpuWrite); | ||||
|  | ||||
|     thread_for(site, lsites, { // NOTE: Not on GPU because of Eigen & (peek/poke)LocalSite | ||||
|       Eigen::MatrixXcd clover_inv_eigen = Eigen::MatrixXcd::Zero(Ns*Nc, Ns*Nc); | ||||
|       Eigen::MatrixXcd clover_eigen = Eigen::MatrixXcd::Zero(Ns*Nc, Ns*Nc); | ||||
|  | ||||
|       scalar_object_diagonal diagonal_tmp     = Zero(); | ||||
|       scalar_object_diagonal diagonal_inv_tmp = Zero(); | ||||
|       scalar_object_triangle triangle_tmp     = Zero(); | ||||
|       scalar_object_triangle triangle_inv_tmp = Zero(); | ||||
|  | ||||
|       Coordinate lcoor; | ||||
|       grid->LocalIndexToLocalCoor(site, lcoor); | ||||
|  | ||||
|       peekLocalSite(diagonal_tmp, diagonal_v, lcoor); | ||||
|       peekLocalSite(triangle_tmp, triangle_v, lcoor); | ||||
|  | ||||
|       // TODO: can we save time here by inverting the two 6x6 hermitian matrices separately? | ||||
|       for (long s_row=0;s_row<Ns;s_row++) { | ||||
|         for (long s_col=0;s_col<Ns;s_col++) { | ||||
|           if(abs(s_row - s_col) > 1 || s_row + s_col == 3) continue; | ||||
|           int block       = s_row / Nhs; | ||||
|           int s_row_block = s_row % Nhs; | ||||
|           int s_col_block = s_col % Nhs; | ||||
|           for (long c_row=0;c_row<Nc;c_row++) { | ||||
|             for (long c_col=0;c_col<Nc;c_col++) { | ||||
|               int i = s_row_block * Nc + c_row; | ||||
|               int j = s_col_block * Nc + c_col; | ||||
|               if(i == j) | ||||
|                 clover_eigen(s_row*Nc+c_row, s_col*Nc+c_col) = static_cast<ComplexD>(TensorRemove(diagonal_tmp()(block)(i))); | ||||
|               else | ||||
|                 clover_eigen(s_row*Nc+c_row, s_col*Nc+c_col) = static_cast<ComplexD>(TensorRemove(triangle_elem(triangle_tmp, block, i, j))); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       clover_inv_eigen = clover_eigen.inverse(); | ||||
|  | ||||
|       for (long s_row=0;s_row<Ns;s_row++) { | ||||
|         for (long s_col=0;s_col<Ns;s_col++) { | ||||
|           if(abs(s_row - s_col) > 1 || s_row + s_col == 3) continue; | ||||
|           int block       = s_row / Nhs; | ||||
|           int s_row_block = s_row % Nhs; | ||||
|           int s_col_block = s_col % Nhs; | ||||
|           for (long c_row=0;c_row<Nc;c_row++) { | ||||
|             for (long c_col=0;c_col<Nc;c_col++) { | ||||
|               int i = s_row_block * Nc + c_row; | ||||
|               int j = s_col_block * Nc + c_col; | ||||
|               if(i == j) | ||||
|                 diagonal_inv_tmp()(block)(i) = clover_inv_eigen(s_row*Nc+c_row, s_col*Nc+c_col); | ||||
|               else if(i < j) | ||||
|                 triangle_inv_tmp()(block)(triangle_index(i, j)) = clover_inv_eigen(s_row*Nc+c_row, s_col*Nc+c_col); | ||||
|               else | ||||
|                 continue; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       pokeLocalSite(diagonal_inv_tmp, diagonalInv_v, lcoor); | ||||
|       pokeLocalSite(triangle_inv_tmp, triangleInv_v, lcoor); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   static void ConvertLayout(const CloverField&   full, | ||||
|                             CloverDiagonalField& diagonal, | ||||
|                             CloverTriangleField& triangle) { | ||||
|     conformable(full, diagonal); | ||||
|     conformable(full, triangle); | ||||
|  | ||||
|     diagonal.Checkerboard() = full.Checkerboard(); | ||||
|     triangle.Checkerboard() = full.Checkerboard(); | ||||
|  | ||||
|     autoView(full_v,     full,     AcceleratorRead); | ||||
|     autoView(diagonal_v, diagonal, AcceleratorWrite); | ||||
|     autoView(triangle_v, triangle, AcceleratorWrite); | ||||
|  | ||||
|     // NOTE: this function cannot be 'private' since nvcc forbids this for kernels | ||||
|     accelerator_for(ss, full.Grid()->oSites(), 1, { | ||||
|       for(int s_row = 0; s_row < Ns; s_row++) { | ||||
|         for(int s_col = 0; s_col < Ns; s_col++) { | ||||
|           if(abs(s_row - s_col) > 1 || s_row + s_col == 3) continue; | ||||
|           int block       = s_row / Nhs; | ||||
|           int s_row_block = s_row % Nhs; | ||||
|           int s_col_block = s_col % Nhs; | ||||
|           for(int c_row = 0; c_row < Nc; c_row++) { | ||||
|             for(int c_col = 0; c_col < Nc; c_col++) { | ||||
|               int i = s_row_block * Nc + c_row; | ||||
|               int j = s_col_block * Nc + c_col; | ||||
|               if(i == j) | ||||
|                 diagonal_v[ss]()(block)(i) = full_v[ss]()(s_row, s_col)(c_row, c_col); | ||||
|               else if(i < j) | ||||
|                 triangle_v[ss]()(block)(triangle_index(i, j)) = full_v[ss]()(s_row, s_col)(c_row, c_col); | ||||
|               else | ||||
|                 continue; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   static void ConvertLayout(const CloverDiagonalField& diagonal, | ||||
|                             const CloverTriangleField& triangle, | ||||
|                             CloverField&               full) { | ||||
|     conformable(full, diagonal); | ||||
|     conformable(full, triangle); | ||||
|  | ||||
|     full.Checkerboard() = diagonal.Checkerboard(); | ||||
|  | ||||
|     full = Zero(); | ||||
|  | ||||
|     autoView(diagonal_v, diagonal, AcceleratorRead); | ||||
|     autoView(triangle_v, triangle, AcceleratorRead); | ||||
|     autoView(full_v,     full,     AcceleratorWrite); | ||||
|  | ||||
|     // NOTE: this function cannot be 'private' since nvcc forbids this for kernels | ||||
|     accelerator_for(ss, full.Grid()->oSites(), 1, { | ||||
|       for(int s_row = 0; s_row < Ns; s_row++) { | ||||
|         for(int s_col = 0; s_col < Ns; s_col++) { | ||||
|           if(abs(s_row - s_col) > 1 || s_row + s_col == 3) continue; | ||||
|           int block       = s_row / Nhs; | ||||
|           int s_row_block = s_row % Nhs; | ||||
|           int s_col_block = s_col % Nhs; | ||||
|           for(int c_row = 0; c_row < Nc; c_row++) { | ||||
|             for(int c_col = 0; c_col < Nc; c_col++) { | ||||
|               int i = s_row_block * Nc + c_row; | ||||
|               int j = s_col_block * Nc + c_col; | ||||
|               if(i == j) | ||||
|                 full_v[ss]()(s_row, s_col)(c_row, c_col) = diagonal_v[ss]()(block)(i); | ||||
|               else | ||||
|                 full_v[ss]()(s_row, s_col)(c_row, c_col) = triangle_elem(triangle_v[ss], block, i, j); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   static void ModifyBoundaries(CloverDiagonalField& diagonal, CloverTriangleField& triangle, RealD csw_t, RealD cF, RealD diag_mass) { | ||||
|     // Checks/grid | ||||
|     double t0 = usecond(); | ||||
|     conformable(diagonal, triangle); | ||||
|     GridBase* grid = diagonal.Grid(); | ||||
|  | ||||
|     // Determine the boundary coordinates/sites | ||||
|     double t1 = usecond(); | ||||
|     int t_dir = Nd - 1; | ||||
|     Lattice<iScalar<vInteger>> t_coor(grid); | ||||
|     LatticeCoordinate(t_coor, t_dir); | ||||
|     int T = grid->GlobalDimensions()[t_dir]; | ||||
|  | ||||
|     // Set off-diagonal parts at boundary to zero -- OK | ||||
|     double t2 = usecond(); | ||||
|     CloverTriangleField zeroTriangle(grid); | ||||
|     zeroTriangle.Checkerboard() = triangle.Checkerboard(); | ||||
|     zeroTriangle = Zero(); | ||||
|     triangle = where(t_coor == 0,   zeroTriangle, triangle); | ||||
|     triangle = where(t_coor == T-1, zeroTriangle, triangle); | ||||
|  | ||||
|     // Set diagonal to unity (scaled correctly) -- OK | ||||
|     double t3 = usecond(); | ||||
|     CloverDiagonalField tmp(grid); | ||||
|     tmp.Checkerboard() = diagonal.Checkerboard(); | ||||
|     tmp                = -1.0 * csw_t + diag_mass; | ||||
|     diagonal           = where(t_coor == 0,   tmp, diagonal); | ||||
|     diagonal           = where(t_coor == T-1, tmp, diagonal); | ||||
|  | ||||
|     // Correct values next to boundary | ||||
|     double t4 = usecond(); | ||||
|     if(cF != 1.0) { | ||||
|       tmp = cF - 1.0; | ||||
|       tmp += diagonal; | ||||
|       diagonal = where(t_coor == 1,   tmp, diagonal); | ||||
|       diagonal = where(t_coor == T-2, tmp, diagonal); | ||||
|     } | ||||
|  | ||||
|     // Report timings | ||||
|     double t5 = usecond(); | ||||
| #if 0 | ||||
|     std::cout << GridLogMessage << "CompactWilsonCloverHelpers::ModifyBoundaries timings:" | ||||
|               << " checks = "          << (t1 - t0) / 1e6 | ||||
|               << ", coordinate = "     << (t2 - t1) / 1e6 | ||||
|               << ", off-diag zero = "  << (t3 - t2) / 1e6 | ||||
|               << ", diagonal unity = " << (t4 - t3) / 1e6 | ||||
|               << ", near-boundary = "  << (t5 - t4) / 1e6 | ||||
|               << ", total = "          << (t5 - t0) / 1e6 | ||||
|               << std::endl; | ||||
| #endif | ||||
|   } | ||||
|  | ||||
|   template<class Field, class Mask> | ||||
|   static strong_inline void ApplyBoundaryMask(Field& f, const Mask& m) { | ||||
|     conformable(f, m); | ||||
|     auto grid  = f.Grid(); | ||||
|     const uint32_t Nsite = grid->oSites(); | ||||
|     const uint32_t Nsimd = grid->Nsimd(); | ||||
|     autoView(f_v, f, AcceleratorWrite); | ||||
|     autoView(m_v, m, AcceleratorRead); | ||||
|     // NOTE: this function cannot be 'private' since nvcc forbids this for kernels | ||||
|     accelerator_for(ss, Nsite, Nsimd, { | ||||
|       coalescedWrite(f_v[ss], m_v(ss) * f_v(ss)); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   template<class MaskField> | ||||
|   static void SetupMasks(MaskField& full, MaskField& even, MaskField& odd) { | ||||
|     assert(even.Grid()->_isCheckerBoarded && even.Checkerboard() == Even); | ||||
|     assert(odd.Grid()->_isCheckerBoarded  && odd.Checkerboard()  == Odd); | ||||
|     assert(!full.Grid()->_isCheckerBoarded); | ||||
|  | ||||
|     GridBase* grid = full.Grid(); | ||||
|     int t_dir = Nd-1; | ||||
|     Lattice<iScalar<vInteger>> t_coor(grid); | ||||
|     LatticeCoordinate(t_coor, t_dir); | ||||
|     int T = grid->GlobalDimensions()[t_dir]; | ||||
|  | ||||
|     MaskField zeroMask(grid); zeroMask = Zero(); | ||||
|     full = 1.0; | ||||
|     full = where(t_coor == 0,   zeroMask, full); | ||||
|     full = where(t_coor == T-1, zeroMask, full); | ||||
|  | ||||
|     pickCheckerboard(Even, even, full); | ||||
|     pickCheckerboard(Odd,  odd,  full); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
							
								
								
									
										92
									
								
								Grid/qcd/action/fermion/WilsonCloverTypes.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								Grid/qcd/action/fermion/WilsonCloverTypes.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/WilsonCloverTypes.h | ||||
|  | ||||
|     Copyright (C) 2021 - 2022 | ||||
|  | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|  | ||||
|     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 Impl> | ||||
| class WilsonCloverTypes { | ||||
| public: | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|   template <typename vtype> using iImplClover = iScalar<iMatrix<iMatrix<vtype, Impl::Dimension>, Ns>>; | ||||
|  | ||||
|   typedef iImplClover<Simd> SiteClover; | ||||
|  | ||||
|   typedef Lattice<SiteClover> CloverField; | ||||
| }; | ||||
|  | ||||
| template<class Impl> | ||||
| class CompactWilsonCloverTypes { | ||||
| public: | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|   static_assert(Nd == 4 && Nc == 3 && Ns == 4 && Impl::Dimension == 3, "Wrong dimensions"); | ||||
|  | ||||
|   static constexpr int Nred      = Nc * Nhs;        // 6 | ||||
|   static constexpr int Nblock    = Nhs;             // 2 | ||||
|   static constexpr int Ndiagonal = Nred;            // 6 | ||||
|   static constexpr int Ntriangle = (Nred - 1) * Nc; // 15 | ||||
|  | ||||
|   template<typename vtype> using iImplCloverDiagonal = iScalar<iVector<iVector<vtype, Ndiagonal>, Nblock>>; | ||||
|   template<typename vtype> using iImplCloverTriangle = iScalar<iVector<iVector<vtype, Ntriangle>, Nblock>>; | ||||
|  | ||||
|   typedef iImplCloverDiagonal<Simd> SiteCloverDiagonal; | ||||
|   typedef iImplCloverTriangle<Simd> SiteCloverTriangle; | ||||
|   typedef iSinglet<Simd>            SiteMask; | ||||
|  | ||||
|   typedef Lattice<SiteCloverDiagonal> CloverDiagonalField; | ||||
|   typedef Lattice<SiteCloverTriangle> CloverTriangleField; | ||||
|   typedef Lattice<SiteMask>           MaskField; | ||||
| }; | ||||
|  | ||||
| #define INHERIT_CLOVER_TYPES(Impl)                                 \ | ||||
|   typedef typename WilsonCloverTypes<Impl>::SiteClover SiteClover; \ | ||||
|   typedef typename WilsonCloverTypes<Impl>::CloverField CloverField; | ||||
|  | ||||
| #define INHERIT_COMPACT_CLOVER_TYPES(Impl) \ | ||||
|   typedef typename CompactWilsonCloverTypes<Impl>::SiteCloverDiagonal  SiteCloverDiagonal; \ | ||||
|   typedef typename CompactWilsonCloverTypes<Impl>::SiteCloverTriangle  SiteCloverTriangle; \ | ||||
|   typedef typename CompactWilsonCloverTypes<Impl>::SiteMask            SiteMask; \ | ||||
|   typedef typename CompactWilsonCloverTypes<Impl>::CloverDiagonalField CloverDiagonalField; \ | ||||
|   typedef typename CompactWilsonCloverTypes<Impl>::CloverTriangleField CloverTriangleField; \ | ||||
|   typedef typename CompactWilsonCloverTypes<Impl>::MaskField           MaskField; \ | ||||
|   /* ugly duplication but needed inside functionality classes */ \ | ||||
|   template<typename vtype> using iImplCloverDiagonal = \ | ||||
|     iScalar<iVector<iVector<vtype, CompactWilsonCloverTypes<Impl>::Ndiagonal>, CompactWilsonCloverTypes<Impl>::Nblock>>; \ | ||||
|   template<typename vtype> using iImplCloverTriangle = \ | ||||
|     iScalar<iVector<iVector<vtype, CompactWilsonCloverTypes<Impl>::Ntriangle>, CompactWilsonCloverTypes<Impl>::Nblock>>; | ||||
|  | ||||
| #define INHERIT_COMPACT_CLOVER_SIZES(Impl)                                    \ | ||||
|   static constexpr int Nred      = CompactWilsonCloverTypes<Impl>::Nred;      \ | ||||
|   static constexpr int Nblock    = CompactWilsonCloverTypes<Impl>::Nblock;    \ | ||||
|   static constexpr int Ndiagonal = CompactWilsonCloverTypes<Impl>::Ndiagonal; \ | ||||
|   static constexpr int Ntriangle = CompactWilsonCloverTypes<Impl>::Ntriangle; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -834,6 +834,7 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
|  | ||||
| #if (!defined(GRID_HIP)) | ||||
|   int tshift = (mu == Nd-1) ? 1 : 0; | ||||
|   unsigned int LLt    = GridDefaultLatt()[Tp]; | ||||
|   //////////////////////////////////////////////// | ||||
|   // GENERAL CAYLEY CASE | ||||
|   //////////////////////////////////////////////// | ||||
| @@ -886,7 +887,7 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
|   } | ||||
|  | ||||
|   std::vector<RealD> G_s(Ls,1.0); | ||||
|   RealD sign = 1; // sign flip for vector/tadpole | ||||
|   RealD sign = 1.0; // sign flip for vector/tadpole | ||||
|   if ( curr_type == Current::Axial ) { | ||||
|     for(int s=0;s<Ls/2;s++){ | ||||
|       G_s[s] = -1.0; | ||||
| @@ -896,7 +897,7 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
|     auto b=this->_b; | ||||
|     auto c=this->_c; | ||||
|     if ( b == 1 && c == 0 ) { | ||||
|       sign = -1;     | ||||
|       sign = -1.0;     | ||||
|     } | ||||
|     else { | ||||
|       std::cerr << "Error: Tadpole implementation currently unavailable for non-Shamir actions." << std::endl; | ||||
| @@ -940,7 +941,13 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
|     tmp    = Cshift(tmp,mu,-1); | ||||
|     Impl::multLinkField(Utmp,this->Umu,tmp,mu+Nd); // Adjoint link | ||||
|     tmp = -G_s[s]*( Utmp + gmu*Utmp ); | ||||
|     tmp    = where((lcoor>=tmin+tshift),tmp,zz); // Mask the time  | ||||
|     // Mask the time | ||||
|     if (tmax == LLt - 1 && tshift == 1){ // quick fix to include timeslice 0 if tmax + tshift is over the last timeslice | ||||
|       unsigned int t0 = 0; | ||||
|       tmp    = where(((lcoor==t0) || (lcoor>=tmin+tshift)),tmp,zz); | ||||
|     } else { | ||||
|       tmp    = where((lcoor>=tmin+tshift),tmp,zz); | ||||
|     } | ||||
|     L_Q   += where((lcoor<=tmax+tshift),tmp,zz); // Position of current complicated | ||||
|  | ||||
|     InsertSlice(L_Q, q_out, s , 0); | ||||
|   | ||||
| @@ -0,0 +1,363 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/CompactWilsonCloverFermionImplementation.h | ||||
|  | ||||
|     Copyright (C) 2017 - 2022 | ||||
|  | ||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|  | ||||
|     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 <Grid/Grid.h> | ||||
| #include <Grid/qcd/spin/Dirac.h> | ||||
| #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
| template<class Impl> | ||||
| CompactWilsonCloverFermion<Impl>::CompactWilsonCloverFermion(GaugeField& _Umu, | ||||
|                                                              GridCartesian& Fgrid, | ||||
|                                                              GridRedBlackCartesian& Hgrid, | ||||
|                                                              const RealD _mass, | ||||
|                                                              const RealD _csw_r, | ||||
|                                                              const RealD _csw_t, | ||||
|                                                              const RealD _cF, | ||||
|                                                              const WilsonAnisotropyCoefficients& clover_anisotropy, | ||||
|                                                              const ImplParams& impl_p) | ||||
|   : WilsonBase(_Umu, Fgrid, Hgrid, _mass, impl_p, clover_anisotropy) | ||||
|   , csw_r(_csw_r) | ||||
|   , csw_t(_csw_t) | ||||
|   , cF(_cF) | ||||
|   , open_boundaries(impl_p.boundary_phases[Nd-1] == 0.0) | ||||
|   , Diagonal(&Fgrid),        Triangle(&Fgrid) | ||||
|   , DiagonalEven(&Hgrid),    TriangleEven(&Hgrid) | ||||
|   , DiagonalOdd(&Hgrid),     TriangleOdd(&Hgrid) | ||||
|   , DiagonalInv(&Fgrid),     TriangleInv(&Fgrid) | ||||
|   , DiagonalInvEven(&Hgrid), TriangleInvEven(&Hgrid) | ||||
|   , DiagonalInvOdd(&Hgrid),  TriangleInvOdd(&Hgrid) | ||||
|   , Tmp(&Fgrid) | ||||
|   , BoundaryMask(&Fgrid) | ||||
|   , BoundaryMaskEven(&Hgrid), BoundaryMaskOdd(&Hgrid) | ||||
| { | ||||
|   csw_r *= 0.5; | ||||
|   csw_t *= 0.5; | ||||
|   if (clover_anisotropy.isAnisotropic) | ||||
|     csw_r /= clover_anisotropy.xi_0; | ||||
|  | ||||
|   ImportGauge(_Umu); | ||||
|   if (open_boundaries) | ||||
|     CompactHelpers::SetupMasks(this->BoundaryMask, this->BoundaryMaskEven, this->BoundaryMaskOdd); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Dhop(const FermionField& in, FermionField& out, int dag) { | ||||
|   WilsonBase::Dhop(in, out, dag); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::DhopOE(const FermionField& in, FermionField& out, int dag) { | ||||
|   WilsonBase::DhopOE(in, out, dag); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::DhopEO(const FermionField& in, FermionField& out, int dag) { | ||||
|   WilsonBase::DhopEO(in, out, dag); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::DhopDir(const FermionField& in, FermionField& out, int dir, int disp) { | ||||
|   WilsonBase::DhopDir(in, out, dir, disp); | ||||
|   if(this->open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::DhopDirAll(const FermionField& in, std::vector<FermionField>& out) { | ||||
|   WilsonBase::DhopDirAll(in, out); | ||||
|   if(this->open_boundaries) { | ||||
|     for(auto& o : out) ApplyBoundaryMask(o); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::M(const FermionField& in, FermionField& out) { | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   WilsonBase::Dhop(in, out, DaggerNo); // call base to save applying bc | ||||
|   Mooee(in, Tmp); | ||||
|   axpy(out, 1.0, out, Tmp); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Mdag(const FermionField& in, FermionField& out) { | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   WilsonBase::Dhop(in, out, DaggerYes);  // call base to save applying bc | ||||
|   MooeeDag(in, Tmp); | ||||
|   axpy(out, 1.0, out, Tmp); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Meooe(const FermionField& in, FermionField& out) { | ||||
|   WilsonBase::Meooe(in, out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MeooeDag(const FermionField& in, FermionField& out) { | ||||
|   WilsonBase::MeooeDag(in, out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Mooee(const FermionField& in, FermionField& out) { | ||||
|   if(in.Grid()->_isCheckerBoarded) { | ||||
|     if(in.Checkerboard() == Odd) { | ||||
|       MooeeInternal(in, out, DiagonalOdd, TriangleOdd); | ||||
|     } else { | ||||
|       MooeeInternal(in, out, DiagonalEven, TriangleEven); | ||||
|     } | ||||
|   } else { | ||||
|     MooeeInternal(in, out, Diagonal, Triangle); | ||||
|   } | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooeeDag(const FermionField& in, FermionField& out) { | ||||
|   Mooee(in, out); // blocks are hermitian | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooeeInv(const FermionField& in, FermionField& out) { | ||||
|   if(in.Grid()->_isCheckerBoarded) { | ||||
|     if(in.Checkerboard() == Odd) { | ||||
|       MooeeInternal(in, out, DiagonalInvOdd, TriangleInvOdd); | ||||
|     } else { | ||||
|       MooeeInternal(in, out, DiagonalInvEven, TriangleInvEven); | ||||
|     } | ||||
|   } else { | ||||
|     MooeeInternal(in, out, DiagonalInv, TriangleInv); | ||||
|   } | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooeeInvDag(const FermionField& in, FermionField& out) { | ||||
|   MooeeInv(in, out); // blocks are hermitian | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Mdir(const FermionField& in, FermionField& out, int dir, int disp) { | ||||
|   DhopDir(in, out, dir, disp); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MdirAll(const FermionField& in, std::vector<FermionField>& out) { | ||||
|   DhopDirAll(in, out); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MDeriv(GaugeField& force, const FermionField& X, const FermionField& Y, int dag) { | ||||
|   assert(!open_boundaries); // TODO check for changes required for open bc | ||||
|  | ||||
|   // NOTE: code copied from original clover term | ||||
|   conformable(X.Grid(), Y.Grid()); | ||||
|   conformable(X.Grid(), force.Grid()); | ||||
|   GaugeLinkField force_mu(force.Grid()), lambda(force.Grid()); | ||||
|   GaugeField clover_force(force.Grid()); | ||||
|   PropagatorField Lambda(force.Grid()); | ||||
|  | ||||
|   // Guido: Here we are hitting some performance issues: | ||||
|   // need to extract the components of the DoubledGaugeField | ||||
|   // for each call | ||||
|   // Possible solution | ||||
|   // Create a vector object to store them? (cons: wasting space) | ||||
|   std::vector<GaugeLinkField> U(Nd, this->Umu.Grid()); | ||||
|  | ||||
|   Impl::extractLinkField(U, this->Umu); | ||||
|  | ||||
|   force = Zero(); | ||||
|   // Derivative of the Wilson hopping term | ||||
|   this->DhopDeriv(force, X, Y, dag); | ||||
|  | ||||
|   /////////////////////////////////////////////////////////// | ||||
|   // Clover term derivative | ||||
|   /////////////////////////////////////////////////////////// | ||||
|   Impl::outerProductImpl(Lambda, X, Y); | ||||
|   //std::cout << "Lambda:" << Lambda << std::endl; | ||||
|  | ||||
|   Gamma::Algebra sigma[] = { | ||||
|       Gamma::Algebra::SigmaXY, | ||||
|       Gamma::Algebra::SigmaXZ, | ||||
|       Gamma::Algebra::SigmaXT, | ||||
|       Gamma::Algebra::MinusSigmaXY, | ||||
|       Gamma::Algebra::SigmaYZ, | ||||
|       Gamma::Algebra::SigmaYT, | ||||
|       Gamma::Algebra::MinusSigmaXZ, | ||||
|       Gamma::Algebra::MinusSigmaYZ, | ||||
|       Gamma::Algebra::SigmaZT, | ||||
|       Gamma::Algebra::MinusSigmaXT, | ||||
|       Gamma::Algebra::MinusSigmaYT, | ||||
|       Gamma::Algebra::MinusSigmaZT}; | ||||
|  | ||||
|   /* | ||||
|     sigma_{\mu \nu}= | ||||
|     | 0         sigma[0]  sigma[1]  sigma[2] | | ||||
|     | sigma[3]    0       sigma[4]  sigma[5] | | ||||
|     | sigma[6]  sigma[7]     0      sigma[8] | | ||||
|     | sigma[9]  sigma[10] sigma[11]   0      | | ||||
|   */ | ||||
|  | ||||
|   int count = 0; | ||||
|   clover_force = Zero(); | ||||
|   for (int mu = 0; mu < 4; mu++) | ||||
|   { | ||||
|     force_mu = Zero(); | ||||
|     for (int nu = 0; nu < 4; nu++) | ||||
|     { | ||||
|       if (mu == nu) | ||||
|         continue; | ||||
|  | ||||
|       RealD factor; | ||||
|       if (nu == 4 || mu == 4) | ||||
|       { | ||||
|         factor = 2.0 * csw_t; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         factor = 2.0 * csw_r; | ||||
|       } | ||||
|       PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked | ||||
|       Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok | ||||
|       force_mu -= factor*Helpers::Cmunu(U, lambda, mu, nu);   // checked | ||||
|       count++; | ||||
|     } | ||||
|  | ||||
|     pokeLorentz(clover_force, U[mu] * force_mu, mu); | ||||
|   } | ||||
|   //clover_force *= csw; | ||||
|   force += clover_force; | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | ||||
|   assert(0); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MeeDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | ||||
|   assert(0); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooeeInternal(const FermionField&        in, | ||||
|                     FermionField&              out, | ||||
|                     const CloverDiagonalField& diagonal, | ||||
|                     const CloverTriangleField& triangle) { | ||||
|   assert(in.Checkerboard() == Odd || in.Checkerboard() == Even); | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   conformable(in, out); | ||||
|   conformable(in, diagonal); | ||||
|   conformable(in, triangle); | ||||
|  | ||||
|   CompactHelpers::MooeeKernel(diagonal.oSites(), 1, in, out, diagonal, triangle); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::ImportGauge(const GaugeField& _Umu) { | ||||
|   // NOTE: parts copied from original implementation | ||||
|  | ||||
|   // Import gauge into base class | ||||
|   double t0 = usecond(); | ||||
|   WilsonBase::ImportGauge(_Umu); // NOTE: called here and in wilson constructor -> performed twice, but can't avoid that | ||||
|  | ||||
|   // Initialize temporary variables | ||||
|   double t1 = usecond(); | ||||
|   conformable(_Umu.Grid(), this->GaugeGrid()); | ||||
|   GridBase* grid = _Umu.Grid(); | ||||
|   typename Impl::GaugeLinkField Bx(grid), By(grid), Bz(grid), Ex(grid), Ey(grid), Ez(grid); | ||||
|   CloverField TmpOriginal(grid); | ||||
|  | ||||
|   // Compute the field strength terms mu>nu | ||||
|   double t2 = usecond(); | ||||
|   WilsonLoops<Impl>::FieldStrength(Bx, _Umu, Zdir, Ydir); | ||||
|   WilsonLoops<Impl>::FieldStrength(By, _Umu, Zdir, Xdir); | ||||
|   WilsonLoops<Impl>::FieldStrength(Bz, _Umu, Ydir, Xdir); | ||||
|   WilsonLoops<Impl>::FieldStrength(Ex, _Umu, Tdir, Xdir); | ||||
|   WilsonLoops<Impl>::FieldStrength(Ey, _Umu, Tdir, Ydir); | ||||
|   WilsonLoops<Impl>::FieldStrength(Ez, _Umu, Tdir, Zdir); | ||||
|  | ||||
|   // Compute the Clover Operator acting on Colour and Spin | ||||
|   // multiply here by the clover coefficients for the anisotropy | ||||
|   double t3 = usecond(); | ||||
|   TmpOriginal  = Helpers::fillCloverYZ(Bx) * csw_r; | ||||
|   TmpOriginal += Helpers::fillCloverXZ(By) * csw_r; | ||||
|   TmpOriginal += Helpers::fillCloverXY(Bz) * csw_r; | ||||
|   TmpOriginal += Helpers::fillCloverXT(Ex) * csw_t; | ||||
|   TmpOriginal += Helpers::fillCloverYT(Ey) * csw_t; | ||||
|   TmpOriginal += Helpers::fillCloverZT(Ez) * csw_t; | ||||
|   TmpOriginal += this->diag_mass; | ||||
|  | ||||
|   // Convert the data layout of the clover term | ||||
|   double t4 = usecond(); | ||||
|   CompactHelpers::ConvertLayout(TmpOriginal, Diagonal, Triangle); | ||||
|  | ||||
|   // Possible modify the boundary values | ||||
|   double t5 = usecond(); | ||||
|   if(open_boundaries) CompactHelpers::ModifyBoundaries(Diagonal, Triangle, csw_t, cF, this->diag_mass); | ||||
|  | ||||
|   // Invert the clover term in the improved layout | ||||
|   double t6 = usecond(); | ||||
|   CompactHelpers::Invert(Diagonal, Triangle, DiagonalInv, TriangleInv); | ||||
|  | ||||
|   // Fill the remaining clover fields | ||||
|   double t7 = usecond(); | ||||
|   pickCheckerboard(Even, DiagonalEven,    Diagonal); | ||||
|   pickCheckerboard(Even, TriangleEven,    Triangle); | ||||
|   pickCheckerboard(Odd,  DiagonalOdd,     Diagonal); | ||||
|   pickCheckerboard(Odd,  TriangleOdd,     Triangle); | ||||
|   pickCheckerboard(Even, DiagonalInvEven, DiagonalInv); | ||||
|   pickCheckerboard(Even, TriangleInvEven, TriangleInv); | ||||
|   pickCheckerboard(Odd,  DiagonalInvOdd,  DiagonalInv); | ||||
|   pickCheckerboard(Odd,  TriangleInvOdd,  TriangleInv); | ||||
|  | ||||
|   // Report timings | ||||
|   double t8 = usecond(); | ||||
| #if 0 | ||||
|   std::cout << GridLogMessage << "CompactWilsonCloverFermion::ImportGauge timings:" | ||||
|             << " WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 | ||||
|             << ", allocations = "               << (t2 - t1) / 1e6 | ||||
|             << ", field strength = "            << (t3 - t2) / 1e6 | ||||
|             << ", fill clover = "               << (t4 - t3) / 1e6 | ||||
|             << ", convert = "                   << (t5 - t4) / 1e6 | ||||
|             << ", boundaries = "                << (t6 - t5) / 1e6 | ||||
|             << ", inversions = "                << (t7 - t6) / 1e6 | ||||
|             << ", pick cbs = "                  << (t8 - t7) / 1e6 | ||||
|             << ", total = "                     << (t8 - t0) / 1e6 | ||||
|             << std::endl; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -2,12 +2,13 @@ | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/WilsonCloverFermion.cc | ||||
|     Source file: ./lib/qcd/action/fermion/WilsonCloverFermionImplementation.h | ||||
|  | ||||
|     Copyright (C) 2017 | ||||
|     Copyright (C) 2017 - 2022 | ||||
|  | ||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|  | ||||
|     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 | ||||
| @@ -33,6 +34,45 @@ | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| template<class Impl> | ||||
| WilsonCloverFermion<Impl>::WilsonCloverFermion(GaugeField&                         _Umu, | ||||
|                                                GridCartesian&                      Fgrid, | ||||
|                                                GridRedBlackCartesian&              Hgrid, | ||||
|                                                const RealD                         _mass, | ||||
|                                                const RealD                         _csw_r, | ||||
|                                                const RealD                         _csw_t, | ||||
|                                                const WilsonAnisotropyCoefficients& clover_anisotropy, | ||||
|                                                const ImplParams&                   impl_p) | ||||
|   : WilsonFermion<Impl>(_Umu, Fgrid, Hgrid, _mass, impl_p, clover_anisotropy) | ||||
|   , CloverTerm(&Fgrid) | ||||
|   , CloverTermInv(&Fgrid) | ||||
|   , CloverTermEven(&Hgrid) | ||||
|   , CloverTermOdd(&Hgrid) | ||||
|   , CloverTermInvEven(&Hgrid) | ||||
|   , CloverTermInvOdd(&Hgrid) | ||||
|   , CloverTermDagEven(&Hgrid) | ||||
|   , CloverTermDagOdd(&Hgrid) | ||||
|   , CloverTermInvDagEven(&Hgrid) | ||||
|   , CloverTermInvDagOdd(&Hgrid) { | ||||
|   assert(Nd == 4); // require 4 dimensions | ||||
|  | ||||
|   if(clover_anisotropy.isAnisotropic) { | ||||
|     csw_r     = _csw_r * 0.5 / clover_anisotropy.xi_0; | ||||
|     diag_mass = _mass + 1.0 + (Nd - 1) * (clover_anisotropy.nu / clover_anisotropy.xi_0); | ||||
|   } else { | ||||
|     csw_r     = _csw_r * 0.5; | ||||
|     diag_mass = 4.0 + _mass; | ||||
|   } | ||||
|   csw_t = _csw_t * 0.5; | ||||
|  | ||||
|   if(csw_r == 0) | ||||
|     std::cout << GridLogWarning << "Initializing WilsonCloverFermion with csw_r = 0" << std::endl; | ||||
|   if(csw_t == 0) | ||||
|     std::cout << GridLogWarning << "Initializing WilsonCloverFermion with csw_t = 0" << std::endl; | ||||
|  | ||||
|   ImportGauge(_Umu); | ||||
| } | ||||
|  | ||||
| // *NOT* EO | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::M(const FermionField &in, FermionField &out) | ||||
| @@ -67,10 +107,13 @@ void WilsonCloverFermion<Impl>::Mdag(const FermionField &in, FermionField &out) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::ImportGauge(const GaugeField &_Umu) | ||||
| { | ||||
|   double t0 = usecond(); | ||||
|   WilsonFermion<Impl>::ImportGauge(_Umu); | ||||
|   double t1 = usecond(); | ||||
|   GridBase *grid = _Umu.Grid(); | ||||
|   typename Impl::GaugeLinkField Bx(grid), By(grid), Bz(grid), Ex(grid), Ey(grid), Ez(grid); | ||||
|  | ||||
|   double t2 = usecond(); | ||||
|   // Compute the field strength terms mu>nu | ||||
|   WilsonLoops<Impl>::FieldStrength(Bx, _Umu, Zdir, Ydir); | ||||
|   WilsonLoops<Impl>::FieldStrength(By, _Umu, Zdir, Xdir); | ||||
| @@ -79,19 +122,22 @@ void WilsonCloverFermion<Impl>::ImportGauge(const GaugeField &_Umu) | ||||
|   WilsonLoops<Impl>::FieldStrength(Ey, _Umu, Tdir, Ydir); | ||||
|   WilsonLoops<Impl>::FieldStrength(Ez, _Umu, Tdir, Zdir); | ||||
|  | ||||
|   double t3 = usecond(); | ||||
|   // Compute the Clover Operator acting on Colour and Spin | ||||
|   // multiply here by the clover coefficients for the anisotropy | ||||
|   CloverTerm  = fillCloverYZ(Bx) * csw_r; | ||||
|   CloverTerm += fillCloverXZ(By) * csw_r; | ||||
|   CloverTerm += fillCloverXY(Bz) * csw_r; | ||||
|   CloverTerm += fillCloverXT(Ex) * csw_t; | ||||
|   CloverTerm += fillCloverYT(Ey) * csw_t; | ||||
|   CloverTerm += fillCloverZT(Ez) * csw_t; | ||||
|   CloverTerm  = Helpers::fillCloverYZ(Bx) * csw_r; | ||||
|   CloverTerm += Helpers::fillCloverXZ(By) * csw_r; | ||||
|   CloverTerm += Helpers::fillCloverXY(Bz) * csw_r; | ||||
|   CloverTerm += Helpers::fillCloverXT(Ex) * csw_t; | ||||
|   CloverTerm += Helpers::fillCloverYT(Ey) * csw_t; | ||||
|   CloverTerm += Helpers::fillCloverZT(Ez) * csw_t; | ||||
|   CloverTerm += diag_mass; | ||||
|  | ||||
|   double t4 = usecond(); | ||||
|   int lvol = _Umu.Grid()->lSites(); | ||||
|   int DimRep = Impl::Dimension; | ||||
|  | ||||
|   double t5 = usecond(); | ||||
|   { | ||||
|     autoView(CTv,CloverTerm,CpuRead); | ||||
|     autoView(CTIv,CloverTermInv,CpuWrite); | ||||
| @@ -100,7 +146,7 @@ void WilsonCloverFermion<Impl>::ImportGauge(const GaugeField &_Umu) | ||||
|       grid->LocalIndexToLocalCoor(site, lcoor); | ||||
|       Eigen::MatrixXcd EigenCloverOp = Eigen::MatrixXcd::Zero(Ns * DimRep, Ns * DimRep); | ||||
|       Eigen::MatrixXcd EigenInvCloverOp = Eigen::MatrixXcd::Zero(Ns * DimRep, Ns * DimRep); | ||||
|       typename SiteCloverType::scalar_object Qx = Zero(), Qxinv = Zero(); | ||||
|       typename SiteClover::scalar_object Qx = Zero(), Qxinv = Zero(); | ||||
|       peekLocalSite(Qx, CTv, lcoor); | ||||
|       //if (csw!=0){ | ||||
|       for (int j = 0; j < Ns; j++) | ||||
| @@ -125,6 +171,7 @@ void WilsonCloverFermion<Impl>::ImportGauge(const GaugeField &_Umu) | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   double t6 = usecond(); | ||||
|   // Separate the even and odd parts | ||||
|   pickCheckerboard(Even, CloverTermEven, CloverTerm); | ||||
|   pickCheckerboard(Odd, CloverTermOdd, CloverTerm); | ||||
| @@ -137,6 +184,20 @@ void WilsonCloverFermion<Impl>::ImportGauge(const GaugeField &_Umu) | ||||
|  | ||||
|   pickCheckerboard(Even, CloverTermInvDagEven, adj(CloverTermInv)); | ||||
|   pickCheckerboard(Odd, CloverTermInvDagOdd, adj(CloverTermInv)); | ||||
|   double t7 = usecond(); | ||||
|  | ||||
| #if 0 | ||||
|   std::cout << GridLogMessage << "WilsonCloverFermion::ImportGauge timings:" | ||||
|             << " WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 | ||||
|             << ", allocations = "               << (t2 - t1) / 1e6 | ||||
|             << ", field strength = "            << (t3 - t2) / 1e6 | ||||
|             << ", fill clover = "               << (t4 - t3) / 1e6 | ||||
|             << ", misc = "                      << (t5 - t4) / 1e6 | ||||
|             << ", inversions = "                << (t6 - t5) / 1e6 | ||||
|             << ", pick cbs = "                  << (t7 - t6) / 1e6 | ||||
|             << ", total = "                     << (t7 - t0) / 1e6 | ||||
|             << std::endl; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template <class Impl> | ||||
| @@ -167,7 +228,7 @@ template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MooeeInternal(const FermionField &in, FermionField &out, int dag, int inv) | ||||
| { | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   CloverFieldType *Clover; | ||||
|   CloverField *Clover; | ||||
|   assert(in.Checkerboard() == Odd || in.Checkerboard() == Even); | ||||
|  | ||||
|   if (dag) | ||||
| @@ -182,12 +243,12 @@ void WilsonCloverFermion<Impl>::MooeeInternal(const FermionField &in, FermionFie | ||||
|       { | ||||
|         Clover = (inv) ? &CloverTermInvDagEven : &CloverTermDagEven; | ||||
|       } | ||||
|       out = *Clover * in; | ||||
|       Helpers::multCloverField(out, *Clover, in); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       Clover = (inv) ? &CloverTermInv : &CloverTerm; | ||||
|       out = adj(*Clover) * in; | ||||
|       Helpers::multCloverField(out, *Clover, in); // don't bother with adj, hermitian anyway | ||||
|     } | ||||
|   } | ||||
|   else | ||||
| @@ -205,18 +266,98 @@ void WilsonCloverFermion<Impl>::MooeeInternal(const FermionField &in, FermionFie | ||||
|         //  std::cout << "Calling clover term Even" << std::endl; | ||||
|         Clover = (inv) ? &CloverTermInvEven : &CloverTermEven; | ||||
|       } | ||||
|       out = *Clover * in; | ||||
|       Helpers::multCloverField(out, *Clover, in); | ||||
|       //  std::cout << GridLogMessage << "*Clover.Checkerboard() "  << (*Clover).Checkerboard() << std::endl; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       Clover = (inv) ? &CloverTermInv : &CloverTerm; | ||||
|       out = *Clover * in; | ||||
|       Helpers::multCloverField(out, *Clover, in); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } // MooeeInternal | ||||
|  | ||||
| // Derivative parts unpreconditioned pseudofermions | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MDeriv(GaugeField &force, const FermionField &X, const FermionField &Y, int dag) | ||||
| { | ||||
|   conformable(X.Grid(), Y.Grid()); | ||||
|   conformable(X.Grid(), force.Grid()); | ||||
|   GaugeLinkField force_mu(force.Grid()), lambda(force.Grid()); | ||||
|   GaugeField clover_force(force.Grid()); | ||||
|   PropagatorField Lambda(force.Grid()); | ||||
|  | ||||
|   // Guido: Here we are hitting some performance issues: | ||||
|   // need to extract the components of the DoubledGaugeField | ||||
|   // for each call | ||||
|   // Possible solution | ||||
|   // Create a vector object to store them? (cons: wasting space) | ||||
|   std::vector<GaugeLinkField> U(Nd, this->Umu.Grid()); | ||||
|  | ||||
|   Impl::extractLinkField(U, this->Umu); | ||||
|  | ||||
|   force = Zero(); | ||||
|   // Derivative of the Wilson hopping term | ||||
|   this->DhopDeriv(force, X, Y, dag); | ||||
|  | ||||
|   /////////////////////////////////////////////////////////// | ||||
|   // Clover term derivative | ||||
|   /////////////////////////////////////////////////////////// | ||||
|   Impl::outerProductImpl(Lambda, X, Y); | ||||
|   //std::cout << "Lambda:" << Lambda << std::endl; | ||||
|  | ||||
|   Gamma::Algebra sigma[] = { | ||||
|       Gamma::Algebra::SigmaXY, | ||||
|       Gamma::Algebra::SigmaXZ, | ||||
|       Gamma::Algebra::SigmaXT, | ||||
|       Gamma::Algebra::MinusSigmaXY, | ||||
|       Gamma::Algebra::SigmaYZ, | ||||
|       Gamma::Algebra::SigmaYT, | ||||
|       Gamma::Algebra::MinusSigmaXZ, | ||||
|       Gamma::Algebra::MinusSigmaYZ, | ||||
|       Gamma::Algebra::SigmaZT, | ||||
|       Gamma::Algebra::MinusSigmaXT, | ||||
|       Gamma::Algebra::MinusSigmaYT, | ||||
|       Gamma::Algebra::MinusSigmaZT}; | ||||
|  | ||||
|   /* | ||||
|     sigma_{\mu \nu}= | ||||
|     | 0         sigma[0]  sigma[1]  sigma[2] | | ||||
|     | sigma[3]    0       sigma[4]  sigma[5] | | ||||
|     | sigma[6]  sigma[7]     0      sigma[8] | | ||||
|     | sigma[9]  sigma[10] sigma[11]   0      | | ||||
|   */ | ||||
|  | ||||
|   int count = 0; | ||||
|   clover_force = Zero(); | ||||
|   for (int mu = 0; mu < 4; mu++) | ||||
|   { | ||||
|     force_mu = Zero(); | ||||
|     for (int nu = 0; nu < 4; nu++) | ||||
|     { | ||||
|       if (mu == nu) | ||||
|       continue; | ||||
|  | ||||
|       RealD factor; | ||||
|       if (nu == 4 || mu == 4) | ||||
|       { | ||||
|         factor = 2.0 * csw_t; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         factor = 2.0 * csw_r; | ||||
|       } | ||||
|       PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked | ||||
|       Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok | ||||
|       force_mu -= factor*Helpers::Cmunu(U, lambda, mu, nu);                   // checked | ||||
|       count++; | ||||
|     } | ||||
|  | ||||
|     pokeLorentz(clover_force, U[mu] * force_mu, mu); | ||||
|   } | ||||
|   //clover_force *= csw; | ||||
|   force += clover_force; | ||||
| } | ||||
|  | ||||
| // Derivative parts | ||||
| template <class Impl> | ||||
|   | ||||
| @@ -77,23 +77,23 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| #define REGISTER | ||||
|  | ||||
| #ifdef GRID_SIMT | ||||
| #define LOAD_CHIMU(ptype)		\ | ||||
| #define LOAD_CHIMU(Ptype)		\ | ||||
|   {const SiteSpinor & ref (in[offset]);	\ | ||||
|     Chimu_00=coalescedReadPermute<ptype>(ref()(0)(0),perm,lane);	\ | ||||
|     Chimu_01=coalescedReadPermute<ptype>(ref()(0)(1),perm,lane);		\ | ||||
|     Chimu_02=coalescedReadPermute<ptype>(ref()(0)(2),perm,lane);		\ | ||||
|     Chimu_10=coalescedReadPermute<ptype>(ref()(1)(0),perm,lane);		\ | ||||
|     Chimu_11=coalescedReadPermute<ptype>(ref()(1)(1),perm,lane);		\ | ||||
|     Chimu_12=coalescedReadPermute<ptype>(ref()(1)(2),perm,lane);		\ | ||||
|     Chimu_20=coalescedReadPermute<ptype>(ref()(2)(0),perm,lane);		\ | ||||
|     Chimu_21=coalescedReadPermute<ptype>(ref()(2)(1),perm,lane);		\ | ||||
|     Chimu_22=coalescedReadPermute<ptype>(ref()(2)(2),perm,lane);		\ | ||||
|     Chimu_30=coalescedReadPermute<ptype>(ref()(3)(0),perm,lane);		\ | ||||
|     Chimu_31=coalescedReadPermute<ptype>(ref()(3)(1),perm,lane);		\ | ||||
|     Chimu_32=coalescedReadPermute<ptype>(ref()(3)(2),perm,lane);	} | ||||
|     Chimu_00=coalescedReadPermute<Ptype>(ref()(0)(0),perm,lane);	\ | ||||
|     Chimu_01=coalescedReadPermute<Ptype>(ref()(0)(1),perm,lane);		\ | ||||
|     Chimu_02=coalescedReadPermute<Ptype>(ref()(0)(2),perm,lane);		\ | ||||
|     Chimu_10=coalescedReadPermute<Ptype>(ref()(1)(0),perm,lane);		\ | ||||
|     Chimu_11=coalescedReadPermute<Ptype>(ref()(1)(1),perm,lane);		\ | ||||
|     Chimu_12=coalescedReadPermute<Ptype>(ref()(1)(2),perm,lane);		\ | ||||
|     Chimu_20=coalescedReadPermute<Ptype>(ref()(2)(0),perm,lane);		\ | ||||
|     Chimu_21=coalescedReadPermute<Ptype>(ref()(2)(1),perm,lane);		\ | ||||
|     Chimu_22=coalescedReadPermute<Ptype>(ref()(2)(2),perm,lane);		\ | ||||
|     Chimu_30=coalescedReadPermute<Ptype>(ref()(3)(0),perm,lane);		\ | ||||
|     Chimu_31=coalescedReadPermute<Ptype>(ref()(3)(1),perm,lane);		\ | ||||
|     Chimu_32=coalescedReadPermute<Ptype>(ref()(3)(2),perm,lane);	} | ||||
| #define PERMUTE_DIR(dir) ; | ||||
| #else | ||||
| #define LOAD_CHIMU(ptype)		\ | ||||
| #define LOAD_CHIMU(Ptype)		\ | ||||
|   {const SiteSpinor & ref (in[offset]);	\ | ||||
|     Chimu_00=ref()(0)(0);\ | ||||
|     Chimu_01=ref()(0)(1);\ | ||||
| @@ -109,12 +109,12 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|     Chimu_32=ref()(3)(2);} | ||||
|  | ||||
| #define PERMUTE_DIR(dir)			\ | ||||
|   permute##dir(Chi_00,Chi_00);	\ | ||||
|       permute##dir(Chi_01,Chi_01);\ | ||||
|       permute##dir(Chi_02,Chi_02);\ | ||||
|       permute##dir(Chi_10,Chi_10);	\ | ||||
|       permute##dir(Chi_11,Chi_11);\ | ||||
|       permute##dir(Chi_12,Chi_12); | ||||
|   permute##dir(Chi_00,Chi_00);			\ | ||||
|   permute##dir(Chi_01,Chi_01);			\ | ||||
|   permute##dir(Chi_02,Chi_02);			\ | ||||
|   permute##dir(Chi_10,Chi_10);			\ | ||||
|   permute##dir(Chi_11,Chi_11);			\ | ||||
|   permute##dir(Chi_12,Chi_12); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @@ -371,88 +371,91 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|   result_32-= UChi_12; | ||||
|  | ||||
| #define HAND_STENCIL_LEGB(PROJ,PERM,DIR,RECON)	\ | ||||
|   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||
|   offset = SE->_offset;				\ | ||||
|   local  = SE->_is_local;			\ | ||||
|   perm   = SE->_permute;			\ | ||||
|   if ( local ) {				\ | ||||
|     LOAD_CHIMU(PERM);				\ | ||||
|     PROJ;					\ | ||||
|     if ( perm) {				\ | ||||
|       PERMUTE_DIR(PERM);			\ | ||||
|     }						\ | ||||
|   } else {					\ | ||||
|     LOAD_CHI;					\ | ||||
|   }						\ | ||||
|   acceleratorSynchronise();			\ | ||||
|   MULT_2SPIN(DIR);				\ | ||||
|   RECON;					 | ||||
|   {int ptype;					\ | ||||
|    SE=st.GetEntry(ptype,DIR,ss);		\ | ||||
|    auto offset = SE->_offset;			\ | ||||
|    auto local  = SE->_is_local;			\ | ||||
|    auto perm   = SE->_permute;			\ | ||||
|    if ( local ) {				\ | ||||
|      LOAD_CHIMU(PERM);				\ | ||||
|      PROJ;					\ | ||||
|      if ( perm) {				\ | ||||
|        PERMUTE_DIR(PERM);			\ | ||||
|      }						\ | ||||
|    } else {					\ | ||||
|      LOAD_CHI;					\ | ||||
|    }						\ | ||||
|    acceleratorSynchronise();			\ | ||||
|    MULT_2SPIN(DIR);				\ | ||||
|    RECON;					} | ||||
|  | ||||
| #define HAND_STENCIL_LEG(PROJ,PERM,DIR,RECON)	\ | ||||
|   SE=&st_p[DIR+8*ss];				\ | ||||
|   ptype=st_perm[DIR];				\ | ||||
|   offset = SE->_offset;				\ | ||||
|   local  = SE->_is_local;			\ | ||||
|   perm   = SE->_permute;			\ | ||||
|   if ( local ) {				\ | ||||
|     LOAD_CHIMU(PERM);				\ | ||||
|     PROJ;					\ | ||||
|     if ( perm) {				\ | ||||
|       PERMUTE_DIR(PERM);			\ | ||||
|     }						\ | ||||
|   } else {					\ | ||||
|     LOAD_CHI;					\ | ||||
|   }						\ | ||||
|   acceleratorSynchronise();			\ | ||||
|   MULT_2SPIN(DIR);				\ | ||||
|   RECON;					 | ||||
| #define HAND_STENCIL_LEG(PROJ,PERM,DIR,RECON)		\ | ||||
|   { SE=&st_p[DIR+8*ss];						\ | ||||
|   auto ptype=st_perm[DIR];					\ | ||||
|   auto offset = SE->_offset;					\ | ||||
|   auto local  = SE->_is_local;					\ | ||||
|   auto perm   = SE->_permute;					\ | ||||
|   if ( local ) {						\ | ||||
|     LOAD_CHIMU(PERM);						\ | ||||
|     PROJ;							\ | ||||
|     if ( perm) {						\ | ||||
|       PERMUTE_DIR(PERM);					\ | ||||
|     }								\ | ||||
|   } else {							\ | ||||
|     LOAD_CHI;							\ | ||||
|   }								\ | ||||
|   acceleratorSynchronise();					\ | ||||
|   MULT_2SPIN(DIR);						\ | ||||
|   RECON;					} | ||||
|  | ||||
| #define HAND_STENCIL_LEGA(PROJ,PERM,DIR,RECON)				\ | ||||
|   SE=&st_p[DIR+8*ss];							\ | ||||
|   ptype=st_perm[DIR];							\ | ||||
|  /*SE=st.GetEntry(ptype,DIR,ss);*/					\ | ||||
|   offset = SE->_offset;				\ | ||||
|   perm   = SE->_permute;			\ | ||||
|   LOAD_CHIMU(PERM);				\ | ||||
|   PROJ;						\ | ||||
|   MULT_2SPIN(DIR);				\ | ||||
|   RECON;					 | ||||
|   { SE=&st_p[DIR+8*ss];							\ | ||||
|     auto ptype=st_perm[DIR];						\ | ||||
|     /*SE=st.GetEntry(ptype,DIR,ss);*/					\ | ||||
|     auto offset = SE->_offset;						\ | ||||
|     auto perm   = SE->_permute;						\ | ||||
|     LOAD_CHIMU(PERM);							\ | ||||
|     PROJ;								\ | ||||
|     MULT_2SPIN(DIR);							\ | ||||
|     RECON;					} | ||||
|  | ||||
| #define HAND_STENCIL_LEG_INT(PROJ,PERM,DIR,RECON)	\ | ||||
|   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||
|   offset = SE->_offset;				\ | ||||
|   local  = SE->_is_local;			\ | ||||
|   perm   = SE->_permute;			\ | ||||
|   if ( local ) {				\ | ||||
|     LOAD_CHIMU(PERM);				\ | ||||
|     PROJ;					\ | ||||
|     if ( perm) {				\ | ||||
|       PERMUTE_DIR(PERM);			\ | ||||
|     }						\ | ||||
|   } else if ( st.same_node[DIR] ) {		\ | ||||
|     LOAD_CHI;					\ | ||||
|   }						\ | ||||
|   acceleratorSynchronise();			\ | ||||
|   if (local || st.same_node[DIR] ) {		\ | ||||
|     MULT_2SPIN(DIR);				\ | ||||
|     RECON;					\ | ||||
|   }						\ | ||||
|   acceleratorSynchronise();			 | ||||
|   { int ptype;						\ | ||||
|   SE=st.GetEntry(ptype,DIR,ss);				\ | ||||
|   auto offset = SE->_offset;					\ | ||||
|   auto local  = SE->_is_local;					\ | ||||
|   auto perm   = SE->_permute;					\ | ||||
|   if ( local ) {						\ | ||||
|     LOAD_CHIMU(PERM);						\ | ||||
|     PROJ;							\ | ||||
|     if ( perm) {						\ | ||||
|       PERMUTE_DIR(PERM);					\ | ||||
|     }								\ | ||||
|   } else if ( st.same_node[DIR] ) {				\ | ||||
|     LOAD_CHI;							\ | ||||
|   }								\ | ||||
|   acceleratorSynchronise();					\ | ||||
|   if (local || st.same_node[DIR] ) {				\ | ||||
|     MULT_2SPIN(DIR);						\ | ||||
|     RECON;							\ | ||||
|   }								\ | ||||
|   acceleratorSynchronise();			} | ||||
|  | ||||
| #define HAND_STENCIL_LEG_EXT(PROJ,PERM,DIR,RECON)	\ | ||||
|   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||
|   offset = SE->_offset;				\ | ||||
|   if((!SE->_is_local)&&(!st.same_node[DIR]) ) {	\ | ||||
|     LOAD_CHI;					\ | ||||
|     MULT_2SPIN(DIR);				\ | ||||
|     RECON;					\ | ||||
|     nmu++;					\ | ||||
|   }						\ | ||||
|   acceleratorSynchronise();			 | ||||
|   { int ptype;						\ | ||||
|   SE=st.GetEntry(ptype,DIR,ss);				\ | ||||
|   auto offset = SE->_offset;				\ | ||||
|   if((!SE->_is_local)&&(!st.same_node[DIR]) ) {		\ | ||||
|     LOAD_CHI;						\ | ||||
|     MULT_2SPIN(DIR);					\ | ||||
|     RECON;						\ | ||||
|     nmu++;						\ | ||||
|   }							\ | ||||
|   acceleratorSynchronise();			} | ||||
|  | ||||
| #define HAND_RESULT(ss)				\ | ||||
|   {						\ | ||||
|     SiteSpinor & ref (out[ss]);			\ | ||||
| #define HAND_RESULT(ss)					\ | ||||
|   {							\ | ||||
|     SiteSpinor & ref (out[ss]);				\ | ||||
|     coalescedWrite(ref()(0)(0),result_00,lane);		\ | ||||
|     coalescedWrite(ref()(0)(1),result_01,lane);		\ | ||||
|     coalescedWrite(ref()(0)(2),result_02,lane);		\ | ||||
| @@ -563,7 +566,6 @@ WilsonKernels<Impl>::HandDhopSiteSycl(StencilVector st_perm,StencilEntry *st_p, | ||||
|  | ||||
|   HAND_DECLARATIONS(Simt); | ||||
|  | ||||
|   int offset,local,perm, ptype; | ||||
|   StencilEntry *SE; | ||||
|   HAND_STENCIL_LEG(XM_PROJ,3,Xp,XM_RECON); | ||||
|   HAND_STENCIL_LEG(YM_PROJ,2,Yp,YM_RECON_ACCUM); | ||||
| @@ -593,9 +595,7 @@ WilsonKernels<Impl>::HandDhopSite(StencilView &st, DoubledGaugeFieldView &U,Site | ||||
|  | ||||
|   HAND_DECLARATIONS(Simt); | ||||
|  | ||||
|   int offset,local,perm, ptype; | ||||
|   StencilEntry *SE; | ||||
|  | ||||
|   HAND_STENCIL_LEG(XM_PROJ,3,Xp,XM_RECON); | ||||
|   HAND_STENCIL_LEG(YM_PROJ,2,Yp,YM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(ZM_PROJ,1,Zp,ZM_RECON_ACCUM); | ||||
| @@ -623,8 +623,6 @@ void WilsonKernels<Impl>::HandDhopSiteDag(StencilView &st,DoubledGaugeFieldView | ||||
|   HAND_DECLARATIONS(Simt); | ||||
|  | ||||
|   StencilEntry *SE; | ||||
|   int offset,local,perm, ptype; | ||||
|    | ||||
|   HAND_STENCIL_LEG(XP_PROJ,3,Xp,XP_RECON); | ||||
|   HAND_STENCIL_LEG(YP_PROJ,2,Yp,YP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(ZP_PROJ,1,Zp,ZP_RECON_ACCUM); | ||||
| @@ -640,8 +638,8 @@ template<class Impl>  accelerator_inline void | ||||
| WilsonKernels<Impl>::HandDhopSiteInt(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor  *buf, | ||||
| 					  int ss,int sU,const FermionFieldView &in, FermionFieldView &out) | ||||
| { | ||||
|   auto st_p = st._entries_p;						 | ||||
|   auto st_perm = st._permute_type;					 | ||||
|   //  auto st_p = st._entries_p;						 | ||||
|   //  auto st_perm = st._permute_type;					 | ||||
| // T==0, Z==1, Y==2, Z==3 expect 1,2,2,2 simd layout etc... | ||||
|   typedef typename Simd::scalar_type S; | ||||
|   typedef typename Simd::vector_type V; | ||||
| @@ -652,7 +650,6 @@ WilsonKernels<Impl>::HandDhopSiteInt(StencilView &st,DoubledGaugeFieldView &U,Si | ||||
|  | ||||
|   HAND_DECLARATIONS(Simt); | ||||
|  | ||||
|   int offset,local,perm, ptype; | ||||
|   StencilEntry *SE; | ||||
|   ZERO_RESULT; | ||||
|   HAND_STENCIL_LEG_INT(XM_PROJ,3,Xp,XM_RECON_ACCUM); | ||||
| @@ -670,8 +667,8 @@ template<class Impl> accelerator_inline | ||||
| void WilsonKernels<Impl>::HandDhopSiteDagInt(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor *buf, | ||||
| 						  int ss,int sU,const FermionFieldView &in, FermionFieldView &out) | ||||
| { | ||||
|   auto st_p = st._entries_p;						 | ||||
|   auto st_perm = st._permute_type;					 | ||||
|   //  auto st_p = st._entries_p;						 | ||||
|   //  auto st_perm = st._permute_type;					 | ||||
|   typedef typename Simd::scalar_type S; | ||||
|   typedef typename Simd::vector_type V; | ||||
|   typedef decltype( coalescedRead( in[0]()(0)(0) )) Simt; | ||||
| @@ -682,7 +679,6 @@ void WilsonKernels<Impl>::HandDhopSiteDagInt(StencilView &st,DoubledGaugeFieldVi | ||||
|   HAND_DECLARATIONS(Simt); | ||||
|  | ||||
|   StencilEntry *SE; | ||||
|   int offset,local,perm, ptype; | ||||
|   ZERO_RESULT; | ||||
|   HAND_STENCIL_LEG_INT(XP_PROJ,3,Xp,XP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(YP_PROJ,2,Yp,YP_RECON_ACCUM); | ||||
| @@ -699,8 +695,8 @@ template<class Impl>  accelerator_inline void | ||||
| WilsonKernels<Impl>::HandDhopSiteExt(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor  *buf, | ||||
| 					  int ss,int sU,const FermionFieldView &in, FermionFieldView &out) | ||||
| { | ||||
|   auto st_p = st._entries_p;						 | ||||
|   auto st_perm = st._permute_type;					 | ||||
|   //  auto st_p = st._entries_p;						 | ||||
|   //  auto st_perm = st._permute_type;					 | ||||
| // T==0, Z==1, Y==2, Z==3 expect 1,2,2,2 simd layout etc... | ||||
|   typedef typename Simd::scalar_type S; | ||||
|   typedef typename Simd::vector_type V; | ||||
| @@ -711,7 +707,7 @@ WilsonKernels<Impl>::HandDhopSiteExt(StencilView &st,DoubledGaugeFieldView &U,Si | ||||
|  | ||||
|   HAND_DECLARATIONS(Simt); | ||||
|  | ||||
|   int offset, ptype; | ||||
|   //  int offset, ptype; | ||||
|   StencilEntry *SE; | ||||
|   int nmu=0; | ||||
|   ZERO_RESULT; | ||||
| @@ -730,8 +726,8 @@ template<class Impl>  accelerator_inline | ||||
| void WilsonKernels<Impl>::HandDhopSiteDagExt(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor *buf, | ||||
| 						  int ss,int sU,const FermionFieldView &in, FermionFieldView &out) | ||||
| { | ||||
|   auto st_p = st._entries_p;						 | ||||
|   auto st_perm = st._permute_type;					 | ||||
|   //  auto st_p = st._entries_p;						 | ||||
|   //  auto st_perm = st._permute_type;					 | ||||
|   typedef typename Simd::scalar_type S; | ||||
|   typedef typename Simd::vector_type V; | ||||
|   typedef decltype( coalescedRead( in[0]()(0)(0) )) Simt; | ||||
| @@ -742,7 +738,7 @@ void WilsonKernels<Impl>::HandDhopSiteDagExt(StencilView &st,DoubledGaugeFieldVi | ||||
|   HAND_DECLARATIONS(Simt); | ||||
|  | ||||
|   StencilEntry *SE; | ||||
|   int offset, ptype; | ||||
|   //  int offset, ptype; | ||||
|   int nmu=0; | ||||
|   ZERO_RESULT; | ||||
|   HAND_STENCIL_LEG_EXT(XP_PROJ,3,Xp,XP_RECON_ACCUM); | ||||
|   | ||||
| @@ -0,0 +1,41 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/ qcd/action/fermion/instantiation/CompactWilsonCloverFermionInstantiation.cc.master | ||||
|  | ||||
|     Copyright (C) 2017 - 2022 | ||||
|  | ||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|  | ||||
|     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 <Grid/Grid.h> | ||||
| #include <Grid/qcd/spin/Dirac.h> | ||||
| #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/CompactWilsonCloverFermionImplementation.h> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class CompactWilsonCloverFermion<IMPLEMENTATION>;  | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -0,0 +1 @@ | ||||
| ../CompactWilsonCloverFermionInstantiation.cc.master | ||||
| @@ -0,0 +1 @@ | ||||
| ../CompactWilsonCloverFermionInstantiation.cc.master | ||||
| @@ -40,7 +40,7 @@ EOF | ||||
|  | ||||
| done | ||||
|  | ||||
| CC_LIST="WilsonCloverFermionInstantiation WilsonFermionInstantiation WilsonKernelsInstantiation WilsonTMFermionInstantiation" | ||||
| CC_LIST="WilsonCloverFermionInstantiation CompactWilsonCloverFermionInstantiation WilsonFermionInstantiation WilsonKernelsInstantiation WilsonTMFermionInstantiation" | ||||
|  | ||||
| for impl in $WILSON_IMPL_LIST | ||||
| do | ||||
|   | ||||
| @@ -78,6 +78,8 @@ public: | ||||
|   typedef Lattice<SiteLink>    LinkField;  | ||||
|   typedef Lattice<SiteField>   Field; | ||||
|  | ||||
|   typedef SU<Nrepresentation> Group; | ||||
|  | ||||
|   // Guido: we can probably separate the types from the HMC functions | ||||
|   // this will create 2 kind of implementations | ||||
|   // probably confusing the users | ||||
| @@ -118,7 +120,7 @@ public: | ||||
|     LinkField Pmu(P.Grid()); | ||||
|     Pmu = Zero(); | ||||
|     for (int mu = 0; mu < Nd; mu++) { | ||||
|       SU<Nrepresentation>::GaussianFundamentalLieAlgebraMatrix(pRNG, Pmu); | ||||
|       Group::GaussianFundamentalLieAlgebraMatrix(pRNG, Pmu); | ||||
|       RealD scale = ::sqrt(HMC_MOMENTUM_DENOMINATOR) ; | ||||
|       Pmu = Pmu*scale; | ||||
|       PokeIndex<LorentzIndex>(P, Pmu, mu); | ||||
| @@ -159,15 +161,15 @@ public: | ||||
|   } | ||||
|  | ||||
|   static inline void HotConfiguration(GridParallelRNG &pRNG, Field &U) { | ||||
|     SU<Nc>::HotConfiguration(pRNG, U); | ||||
|     Group::HotConfiguration(pRNG, U); | ||||
|   } | ||||
|  | ||||
|   static inline void TepidConfiguration(GridParallelRNG &pRNG, Field &U) { | ||||
|     SU<Nc>::TepidConfiguration(pRNG, U); | ||||
|     Group::TepidConfiguration(pRNG, U); | ||||
|   } | ||||
|  | ||||
|   static inline void ColdConfiguration(GridParallelRNG &pRNG, Field &U) { | ||||
|     SU<Nc>::ColdConfiguration(pRNG, U); | ||||
|     Group::ColdConfiguration(pRNG, U); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,61 +1,63 @@ | ||||
| Using HMC in Grid version 0.5.1 | ||||
| # Using HMC in Grid | ||||
|  | ||||
| These are the instructions to use the Generalised HMC on Grid version 0.5.1. | ||||
| Disclaimer: GRID is still under active development so any information here can be changed in future releases. | ||||
| These are the instructions to use the Generalised HMC on Grid as of commit `749b802`. | ||||
| Disclaimer: Grid is still under active development so any information here can be changed in future releases. | ||||
|  | ||||
|  | ||||
| Command line options | ||||
| =================== | ||||
| (relevant file GenericHMCrunner.h) | ||||
| ## Command line options | ||||
|  | ||||
| (relevant file `GenericHMCrunner.h`) | ||||
| The initial configuration can be changed at the command line using  | ||||
| --StartType <your choice> | ||||
| valid choices, one among these | ||||
| HotStart, ColdStart, TepidStart, CheckpointStart | ||||
| default: HotStart | ||||
| `--StartingType STARTING_TYPE`, where `STARTING_TYPE` is one of | ||||
| `HotStart`, `ColdStart`, `TepidStart`, and `CheckpointStart`. | ||||
| Default: `--StartingType HotStart` | ||||
|  | ||||
| example | ||||
| ./My_hmc_exec  --StartType HotStart | ||||
| Example: | ||||
| ``` | ||||
| ./My_hmc_exec  --StartingType HotStart | ||||
| ``` | ||||
|  | ||||
| The CheckpointStart option uses the prefix for the configurations and rng seed files defined in your executable and the initial configuration is specified by | ||||
| --StartTrajectory <integer> | ||||
| default: 0 | ||||
| The `CheckpointStart` option uses the prefix for the configurations and rng seed files defined in your executable and the initial configuration is specified by | ||||
| `--StartingTrajectory STARTING_TRAJECTORY`, where `STARTING_TRAJECTORY` is an integer. | ||||
| Default: `--StartingTrajectory 0` | ||||
|  | ||||
| The number of trajectories for a specific run are specified at command line by | ||||
| --Trajectories <integer> | ||||
| default: 1 | ||||
| `--Trajectories TRAJECTORIES`, where `TRAJECTORIES` is an integer. | ||||
| Default: `--Trajectories 1` | ||||
|  | ||||
| The number of thermalization steps (i.e. steps when the Metropolis acceptance check is turned off) is specified by | ||||
| --Thermalizations <integer> | ||||
| default: 10 | ||||
|  | ||||
| `--Thermalizations THERMALIZATIONS`, where `THERMALIZATIONS` is an integer. | ||||
| Default: `--Thermalizations 10` | ||||
|  | ||||
| Any other parameter is defined in the source for the executable. | ||||
|  | ||||
| HMC controls | ||||
| =========== | ||||
| ## HMC controls | ||||
|  | ||||
| The lines  | ||||
|  | ||||
| ``` | ||||
|   std::vector<int> SerSeed({1, 2, 3, 4, 5}); | ||||
|   std::vector<int> ParSeed({6, 7, 8, 9, 10}); | ||||
| ``` | ||||
|  | ||||
| define the seeds for the serial and the parallel RNG. | ||||
|  | ||||
| The line  | ||||
|  | ||||
| ``` | ||||
|   TheHMC.MDparameters.set(20, 1.0);// MDsteps, traj length | ||||
| ``` | ||||
|  | ||||
| declares the number of molecular dynamics steps and the total trajectory length. | ||||
|  | ||||
|  | ||||
| Actions | ||||
| ====== | ||||
| ## Actions | ||||
|  | ||||
| Action names are defined in the file | ||||
| lib/qcd/Actions.h | ||||
| Action names are defined in the directory `Grid/qcd/action`. | ||||
|  | ||||
| Gauge actions list: | ||||
| Gauge actions list (from `Grid/qcd/action/gauge/Gauge.h`): | ||||
|  | ||||
| ``` | ||||
| WilsonGaugeActionR; | ||||
| WilsonGaugeActionF; | ||||
| WilsonGaugeActionD; | ||||
| @@ -68,8 +70,9 @@ IwasakiGaugeActionD; | ||||
| SymanzikGaugeActionR; | ||||
| SymanzikGaugeActionF; | ||||
| SymanzikGaugeActionD; | ||||
| ``` | ||||
|  | ||||
|  | ||||
| ``` | ||||
| ConjugateWilsonGaugeActionR; | ||||
| ConjugateWilsonGaugeActionF; | ||||
| ConjugateWilsonGaugeActionD; | ||||
| @@ -82,26 +85,23 @@ ConjugateIwasakiGaugeActionD; | ||||
| ConjugateSymanzikGaugeActionR; | ||||
| ConjugateSymanzikGaugeActionF; | ||||
| ConjugateSymanzikGaugeActionD; | ||||
| ``` | ||||
|  | ||||
| Each of these action accepts one single parameter at creation time (beta). | ||||
| Example for creating a Symanzik action with beta=4.0 | ||||
|  | ||||
| ``` | ||||
|   SymanzikGaugeActionR(4.0) | ||||
| ``` | ||||
|  | ||||
| Scalar actions list (from `Grid/qcd/action/scalar/Scalar.h`): | ||||
|  | ||||
| ``` | ||||
| ScalarActionR; | ||||
| ScalarActionF; | ||||
| ScalarActionD; | ||||
| ``` | ||||
|  | ||||
|  | ||||
| each of these action accept one single parameter at creation time (beta). | ||||
| Example for creating a Symanzik action with beta=4.0 | ||||
|  | ||||
| 	SymanzikGaugeActionR(4.0) | ||||
|  | ||||
| The suffixes R,F,D in the action names refer to the Real | ||||
| (the precision is defined at compile time by the --enable-precision flag in the configure), | ||||
| Float and Double, that force the precision of the action to be 32, 64 bit respectively. | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| The suffixes `R`, `F`, `D` in the action names refer to the `Real` | ||||
| (the precision is defined at compile time by the `--enable-precision` flag in the configure), | ||||
| `Float` and `Double`, that force the precision of the action to be 32, 64 bit respectively. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user