mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-10-31 20:14:32 +00:00 
			
		
		
		
	Compare commits
	
		
			84 Commits
		
	
	
		
			release/0.
			...
			feature/gp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 4fefae1745 | ||
|  | 758e2edcad | ||
|  | 1538b15f3b | ||
|  | deac621c2c | ||
|  | ba974960e6 | ||
|  | 6755dc57f8 | ||
|  | aa620ca52c | ||
|  | 2c46c942cc | ||
|  | adeba8059a | ||
|  | c4ac528126 | ||
|  | 551b93ba8e | ||
|  | ddf7540510 | ||
|  | de68d12c3d | ||
|  | 6d26a2a1ad | ||
|  | a1211cdcce | ||
|  | e78acf77ff | ||
|  | f7e9621492 | ||
|  | f14be15f8b | ||
|  | 6a3aaa52ef | ||
|  | 9ba47b4696 | ||
|  | e85af80c39 | ||
|  | 0b91e90dd4 | ||
|  | d184b8c921 | ||
|  | c92e390b08 | ||
|  | 5b36a8af54 | ||
|  | 75a1f85162 | ||
|  | ac4f2d9798 | ||
|  | c3b99de33f | ||
|  | e1a02bb80a | ||
|  | 86f08c6b9a | ||
|  | 9f0271039f | ||
|  | 24df770f74 | ||
|  | 45b6c7effc | ||
|  | 1c70d8c4d9 | ||
|  | f0e9a5299f | ||
|  | f1b8ba45e7 | ||
|  | fe998ab578 | ||
|  | c2ee2b5fd1 | ||
|  | 3b734ee397 | ||
|  | 8637a9512a | ||
|  | 7f6e2ee03e | ||
|  | 7b02acb2bd | ||
|  | 86948c6ea0 | ||
|  | 53d226924a | ||
|  | 80176b1b39 | ||
|  | 29ddafd0fc | ||
|  | 0f08364e4f | ||
|  | a198d59381 | ||
|  | 3a4f5f2324 | ||
|  | 824d84473f | ||
|  | 38964a4076 | ||
|  | 0d9aa87228 | ||
|  | 0e959d9b94 | ||
|  | 752f70cd48 | ||
|  | e0e42873c1 | ||
|  | 0ff3bf6dc5 | ||
|  | 351eab02ae | ||
|  | feee5ccde2 | ||
|  | e0f6a146d8 | ||
|  | daa095c519 | ||
|  | c2676853ca | ||
|  | 6a824033f8 | ||
|  | cee6a37639 | ||
|  | 6cc3ad110c | ||
|  | e6c6f82c52 | ||
|  | d10d0c4e7f | ||
|  | 9c106d625a | ||
|  | 6795bbca31 | ||
|  | d161c2dc35 | ||
|  | 7a06826cf1 | ||
|  | c3712b8e06 | ||
|  | 901ee77b84 | ||
|  | 1b84f59273 | ||
|  | 1fb41a4300 | ||
|  | 287bac946f | ||
|  | 80c14be65e | ||
|  | d7a2a4852d | ||
|  | d185f2eaa7 | ||
|  | 813d4cd900 | ||
|  | 75c6c6b173 | ||
|  | 220ad5e3ee | ||
|  | ba5dc670a5 | ||
|  | a0ca362690 | ||
|  | 249b6e61ec | 
| @@ -34,6 +34,9 @@ directory | |||||||
|  |  | ||||||
| #if defined __GNUC__ && __GNUC__>=6 | #if defined __GNUC__ && __GNUC__>=6 | ||||||
| #pragma GCC diagnostic ignored "-Wignored-attributes" | #pragma GCC diagnostic ignored "-Wignored-attributes" | ||||||
|  | #endif | ||||||
|  | #if defined __GNUC__  | ||||||
|  | #pragma GCC diagnostic ignored "-Wpsabi" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  //disables and intel compiler specific warning (in json.hpp) |  //disables and intel compiler specific warning (in json.hpp) | ||||||
| @@ -44,22 +47,14 @@ directory | |||||||
| #ifdef __NVCC__ | #ifdef __NVCC__ | ||||||
|  //disables nvcc specific warning in json.hpp |  //disables nvcc specific warning in json.hpp | ||||||
| #pragma clang diagnostic ignored "-Wdeprecated-register" | #pragma clang diagnostic ignored "-Wdeprecated-register" | ||||||
|  |  | ||||||
| #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ |  | ||||||
|  //disables nvcc specific warning in json.hpp |  | ||||||
| #pragma nv_diag_suppress unsigned_compare_with_zero |  | ||||||
| #pragma nv_diag_suppress cast_to_qualified_type |  | ||||||
|  //disables nvcc specific warning in many files |  | ||||||
| #pragma nv_diag_suppress esa_on_defaulted_function_ignored |  | ||||||
| #pragma nv_diag_suppress extra_semicolon |  | ||||||
| #else |  | ||||||
|  //disables nvcc specific warning in json.hpp |  | ||||||
| #pragma diag_suppress unsigned_compare_with_zero | #pragma diag_suppress unsigned_compare_with_zero | ||||||
| #pragma diag_suppress cast_to_qualified_type | #pragma diag_suppress cast_to_qualified_type | ||||||
|  |  | ||||||
|  //disables nvcc specific warning in many files |  //disables nvcc specific warning in many files | ||||||
| #pragma diag_suppress esa_on_defaulted_function_ignored | #pragma diag_suppress esa_on_defaulted_function_ignored | ||||||
| #pragma diag_suppress extra_semicolon | #pragma diag_suppress extra_semicolon | ||||||
| #endif |  | ||||||
|  | //Eigen only | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Disable vectorisation in Eigen on the Power8/9 and PowerPC | // Disable vectorisation in Eigen on the Power8/9 and PowerPC | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | |||||||
| #include <Grid/GridCore.h> | #include <Grid/GridCore.h> | ||||||
| #include <Grid/qcd/QCD.h> | #include <Grid/qcd/QCD.h> | ||||||
| #include <Grid/qcd/spin/Spin.h> | #include <Grid/qcd/spin/Spin.h> | ||||||
|  | #include <Grid/qcd/gparity/Gparity.h> | ||||||
| #include <Grid/qcd/utils/Utils.h> | #include <Grid/qcd/utils/Utils.h> | ||||||
| #include <Grid/qcd/representations/Representations.h> | #include <Grid/qcd/representations/Representations.h> | ||||||
| NAMESPACE_CHECK(GridQCDCore); | NAMESPACE_CHECK(GridQCDCore); | ||||||
|   | |||||||
| @@ -16,7 +16,6 @@ | |||||||
| #include <functional> | #include <functional> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <strings.h> |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
| #include <ctime> | #include <ctime> | ||||||
|   | |||||||
| @@ -14,11 +14,7 @@ | |||||||
| /* NVCC save and restore compile environment*/ | /* NVCC save and restore compile environment*/ | ||||||
| #ifdef __NVCC__ | #ifdef __NVCC__ | ||||||
| #pragma push | #pragma push | ||||||
| #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ |  | ||||||
| #pragma nv_diag_suppress code_is_unreachable |  | ||||||
| #else |  | ||||||
| #pragma diag_suppress code_is_unreachable | #pragma diag_suppress code_is_unreachable | ||||||
| #endif |  | ||||||
| #pragma push_macro("__CUDA_ARCH__") | #pragma push_macro("__CUDA_ARCH__") | ||||||
| #pragma push_macro("__NVCC__") | #pragma push_macro("__NVCC__") | ||||||
| #pragma push_macro("__CUDACC__") | #pragma push_macro("__CUDACC__") | ||||||
|   | |||||||
| @@ -54,7 +54,7 @@ NAMESPACE_CHECK(BiCGSTAB); | |||||||
| #include <Grid/algorithms/iterative/SchurRedBlack.h> | #include <Grid/algorithms/iterative/SchurRedBlack.h> | ||||||
| #include <Grid/algorithms/iterative/ConjugateGradientMultiShift.h> | #include <Grid/algorithms/iterative/ConjugateGradientMultiShift.h> | ||||||
| #include <Grid/algorithms/iterative/ConjugateGradientMixedPrec.h> | #include <Grid/algorithms/iterative/ConjugateGradientMixedPrec.h> | ||||||
| #include <Grid/algorithms/iterative/ConjugateGradientMixedPrecBatched.h> | #include <Grid/algorithms/iterative/ConjugateGradientMultiShiftMixedPrec.h> | ||||||
| #include <Grid/algorithms/iterative/BiCGSTABMixedPrec.h> | #include <Grid/algorithms/iterative/BiCGSTABMixedPrec.h> | ||||||
| #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | ||||||
| #include <Grid/algorithms/iterative/ConjugateGradientReliableUpdate.h> | #include <Grid/algorithms/iterative/ConjugateGradientReliableUpdate.h> | ||||||
|   | |||||||
| @@ -262,7 +262,7 @@ public: | |||||||
| 	autoView( Tnp_v , (*Tnp), AcceleratorWrite); | 	autoView( Tnp_v , (*Tnp), AcceleratorWrite); | ||||||
| 	autoView( Tnm_v , (*Tnm), AcceleratorWrite); | 	autoView( Tnm_v , (*Tnm), AcceleratorWrite); | ||||||
| 	const int Nsimd = CComplex::Nsimd(); | 	const int Nsimd = CComplex::Nsimd(); | ||||||
| 	accelerator_for(ss, FineGrid->oSites(), Nsimd, { | 	accelerator_forNB(ss, FineGrid->oSites(), Nsimd, { | ||||||
| 	  coalescedWrite(y_v[ss],xscale*y_v(ss)+mscale*Tn_v(ss)); | 	  coalescedWrite(y_v[ss],xscale*y_v(ss)+mscale*Tn_v(ss)); | ||||||
| 	  coalescedWrite(Tnp_v[ss],2.0*y_v(ss)-Tnm_v(ss)); | 	  coalescedWrite(Tnp_v[ss],2.0*y_v(ss)-Tnm_v(ss)); | ||||||
|         }); |         }); | ||||||
|   | |||||||
| @@ -264,7 +264,7 @@ public: | |||||||
|       auto Tnp_v = Tnp->View(); |       auto Tnp_v = Tnp->View(); | ||||||
|       auto Tnm_v = Tnm->View(); |       auto Tnm_v = Tnm->View(); | ||||||
|       constexpr int Nsimd = vector_type::Nsimd(); |       constexpr int Nsimd = vector_type::Nsimd(); | ||||||
|       accelerator_for(ss, in.Grid()->oSites(), Nsimd, { |       accelerator_forNB(ss, in.Grid()->oSites(), Nsimd, { | ||||||
| 	  coalescedWrite(y_v[ss],xscale*y_v(ss)+mscale*Tn_v(ss)); | 	  coalescedWrite(y_v[ss],xscale*y_v(ss)+mscale*Tn_v(ss)); | ||||||
| 	  coalescedWrite(Tnp_v[ss],2.0*y_v(ss)-Tnm_v(ss)); | 	  coalescedWrite(Tnp_v[ss],2.0*y_v(ss)-Tnm_v(ss)); | ||||||
|       }); |       }); | ||||||
| @@ -292,6 +292,7 @@ public: | |||||||
| template<class Field> | template<class Field> | ||||||
| class ChebyshevLanczos : public Chebyshev<Field> { | class ChebyshevLanczos : public Chebyshev<Field> { | ||||||
| private: | private: | ||||||
|  |  | ||||||
|   std::vector<RealD> Coeffs; |   std::vector<RealD> Coeffs; | ||||||
|   int order; |   int order; | ||||||
|   RealD alpha; |   RealD alpha; | ||||||
|   | |||||||
| @@ -49,6 +49,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
|     Integer TotalInnerIterations; //Number of inner CG iterations |     Integer TotalInnerIterations; //Number of inner CG iterations | ||||||
|     Integer TotalOuterIterations; //Number of restarts |     Integer TotalOuterIterations; //Number of restarts | ||||||
|     Integer TotalFinalStepIterations; //Number of CG iterations in final patch-up step |     Integer TotalFinalStepIterations; //Number of CG iterations in final patch-up step | ||||||
|  |     RealD TrueResidual; | ||||||
|  |  | ||||||
|     //Option to speed up *inner single precision* solves using a LinearFunction that produces a guess |     //Option to speed up *inner single precision* solves using a LinearFunction that produces a guess | ||||||
|     LinearFunction<FieldF> *guesser; |     LinearFunction<FieldF> *guesser; | ||||||
| @@ -68,6 +69,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
|     } |     } | ||||||
|    |    | ||||||
|   void operator() (const FieldD &src_d_in, FieldD &sol_d){ |   void operator() (const FieldD &src_d_in, FieldD &sol_d){ | ||||||
|  |     std::cout << GridLogMessage << "MixedPrecisionConjugateGradient: Starting mixed precision CG with outer tolerance " << Tolerance << " and inner tolerance " << InnerTolerance << std::endl; | ||||||
|     TotalInnerIterations = 0; |     TotalInnerIterations = 0; | ||||||
| 	 | 	 | ||||||
|     GridStopWatch TotalTimer; |     GridStopWatch TotalTimer; | ||||||
| @@ -80,6 +82,11 @@ NAMESPACE_BEGIN(Grid); | |||||||
|     RealD stop = src_norm * Tolerance*Tolerance; |     RealD stop = src_norm * Tolerance*Tolerance; | ||||||
|  |  | ||||||
|     GridBase* DoublePrecGrid = src_d_in.Grid(); |     GridBase* DoublePrecGrid = src_d_in.Grid(); | ||||||
|  |  | ||||||
|  |     //Generate precision change workspaces | ||||||
|  |     precisionChangeWorkspace wk_dp_from_sp(DoublePrecGrid, SinglePrecGrid); | ||||||
|  |     precisionChangeWorkspace wk_sp_from_dp(SinglePrecGrid, DoublePrecGrid); | ||||||
|  |  | ||||||
|     FieldD tmp_d(DoublePrecGrid); |     FieldD tmp_d(DoublePrecGrid); | ||||||
|     tmp_d.Checkerboard() = cb; |     tmp_d.Checkerboard() = cb; | ||||||
|      |      | ||||||
| @@ -97,6 +104,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
|     FieldF sol_f(SinglePrecGrid); |     FieldF sol_f(SinglePrecGrid); | ||||||
|     sol_f.Checkerboard() = cb; |     sol_f.Checkerboard() = cb; | ||||||
|      |      | ||||||
|  |     std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Starting initial inner CG with tolerance " << inner_tol << std::endl; | ||||||
|     ConjugateGradient<FieldF> CG_f(inner_tol, MaxInnerIterations); |     ConjugateGradient<FieldF> CG_f(inner_tol, MaxInnerIterations); | ||||||
|     CG_f.ErrorOnNoConverge = false; |     CG_f.ErrorOnNoConverge = false; | ||||||
|  |  | ||||||
| @@ -120,7 +128,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
|       while(norm * inner_tol * inner_tol < stop) inner_tol *= 2;  // inner_tol = sqrt(stop/norm) ?? |       while(norm * inner_tol * inner_tol < stop) inner_tol *= 2;  // inner_tol = sqrt(stop/norm) ?? | ||||||
|  |  | ||||||
|       PrecChangeTimer.Start(); |       PrecChangeTimer.Start(); | ||||||
|       precisionChange(src_f, src_d); |       precisionChange(src_f, src_d, wk_sp_from_dp); | ||||||
|       PrecChangeTimer.Stop(); |       PrecChangeTimer.Stop(); | ||||||
|        |        | ||||||
|       sol_f = Zero(); |       sol_f = Zero(); | ||||||
| @@ -130,6 +138,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
| 	(*guesser)(src_f, sol_f); | 	(*guesser)(src_f, sol_f); | ||||||
|  |  | ||||||
|       //Inner CG |       //Inner CG | ||||||
|  |       std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Outer iteration " << outer_iter << " starting inner CG with tolerance " << inner_tol << std::endl; | ||||||
|       CG_f.Tolerance = inner_tol; |       CG_f.Tolerance = inner_tol; | ||||||
|       InnerCGtimer.Start(); |       InnerCGtimer.Start(); | ||||||
|       CG_f(Linop_f, src_f, sol_f); |       CG_f(Linop_f, src_f, sol_f); | ||||||
| @@ -138,7 +147,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
|        |        | ||||||
|       //Convert sol back to double and add to double prec solution |       //Convert sol back to double and add to double prec solution | ||||||
|       PrecChangeTimer.Start(); |       PrecChangeTimer.Start(); | ||||||
|       precisionChange(tmp_d, sol_f); |       precisionChange(tmp_d, sol_f, wk_dp_from_sp); | ||||||
|       PrecChangeTimer.Stop(); |       PrecChangeTimer.Stop(); | ||||||
|        |        | ||||||
|       axpy(sol_d, 1.0, tmp_d, sol_d); |       axpy(sol_d, 1.0, tmp_d, sol_d); | ||||||
| @@ -150,6 +159,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
|     ConjugateGradient<FieldD> CG_d(Tolerance, MaxInnerIterations); |     ConjugateGradient<FieldD> CG_d(Tolerance, MaxInnerIterations); | ||||||
|     CG_d(Linop_d, src_d_in, sol_d); |     CG_d(Linop_d, src_d_in, sol_d); | ||||||
|     TotalFinalStepIterations = CG_d.IterationsToComplete; |     TotalFinalStepIterations = CG_d.IterationsToComplete; | ||||||
|  |     TrueResidual = CG_d.TrueResidual; | ||||||
|  |  | ||||||
|     TotalTimer.Stop(); |     TotalTimer.Stop(); | ||||||
|     std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Inner CG iterations " << TotalInnerIterations << " Restarts " << TotalOuterIterations << " Final CG iterations " << TotalFinalStepIterations << std::endl; |     std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Inner CG iterations " << TotalInnerIterations << " Restarts " << TotalOuterIterations << " Final CG iterations " << TotalFinalStepIterations << std::endl; | ||||||
|   | |||||||
| @@ -1,213 +0,0 @@ | |||||||
| /************************************************************************************* |  | ||||||
|  |  | ||||||
|     Grid physics library, www.github.com/paboyle/Grid  |  | ||||||
|  |  | ||||||
|     Source file: ./lib/algorithms/iterative/ConjugateGradientMixedPrecBatched.h |  | ||||||
|  |  | ||||||
|     Copyright (C) 2015 |  | ||||||
|  |  | ||||||
|     Author: Raoul Hodgson <raoul.hodgson@ed.ac.uk> |  | ||||||
|  |  | ||||||
|     This program is free software; you can redistribute it and/or modify |  | ||||||
|     it under the terms of the GNU General Public License as published by |  | ||||||
|     the Free Software Foundation; either version 2 of the License, or |  | ||||||
|     (at your option) any later version. |  | ||||||
|  |  | ||||||
|     This program is distributed in the hope that it will be useful, |  | ||||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|     GNU General Public License for more details. |  | ||||||
|  |  | ||||||
|     You should have received a copy of the GNU General Public License along |  | ||||||
|     with this program; if not, write to the Free Software Foundation, Inc., |  | ||||||
|     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |  | ||||||
|  |  | ||||||
|     See the full license in the file "LICENSE" in the top level distribution directory |  | ||||||
| *************************************************************************************/ |  | ||||||
| /*  END LEGAL */ |  | ||||||
| #ifndef GRID_CONJUGATE_GRADIENT_MIXED_PREC_BATCHED_H |  | ||||||
| #define GRID_CONJUGATE_GRADIENT_MIXED_PREC_BATCHED_H |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); |  | ||||||
|  |  | ||||||
| //Mixed precision restarted defect correction CG |  | ||||||
| template<class FieldD,class FieldF,  |  | ||||||
|   typename std::enable_if< getPrecision<FieldD>::value == 2, int>::type = 0, |  | ||||||
|   typename std::enable_if< getPrecision<FieldF>::value == 1, int>::type = 0>  |  | ||||||
| class MixedPrecisionConjugateGradientBatched : public LinearFunction<FieldD> { |  | ||||||
| public: |  | ||||||
|   using LinearFunction<FieldD>::operator(); |  | ||||||
|   RealD   Tolerance; |  | ||||||
|   RealD   InnerTolerance; //Initial tolerance for inner CG. Defaults to Tolerance but can be changed |  | ||||||
|   Integer MaxInnerIterations; |  | ||||||
|   Integer MaxOuterIterations; |  | ||||||
|   Integer MaxPatchupIterations; |  | ||||||
|   GridBase* SinglePrecGrid; //Grid for single-precision fields |  | ||||||
|   RealD OuterLoopNormMult; //Stop the outer loop and move to a final double prec solve when the residual is OuterLoopNormMult * Tolerance |  | ||||||
|   LinearOperatorBase<FieldF> &Linop_f; |  | ||||||
|   LinearOperatorBase<FieldD> &Linop_d; |  | ||||||
|  |  | ||||||
|   //Option to speed up *inner single precision* solves using a LinearFunction that produces a guess |  | ||||||
|   LinearFunction<FieldF> *guesser; |  | ||||||
|   bool updateResidual; |  | ||||||
|    |  | ||||||
|   MixedPrecisionConjugateGradientBatched(RealD tol,  |  | ||||||
|           Integer maxinnerit,  |  | ||||||
|           Integer maxouterit,  |  | ||||||
|           Integer maxpatchit, |  | ||||||
|           GridBase* _sp_grid,  |  | ||||||
|           LinearOperatorBase<FieldF> &_Linop_f,  |  | ||||||
|           LinearOperatorBase<FieldD> &_Linop_d, |  | ||||||
|           bool _updateResidual=true) : |  | ||||||
|     Linop_f(_Linop_f), Linop_d(_Linop_d), |  | ||||||
|     Tolerance(tol), InnerTolerance(tol), MaxInnerIterations(maxinnerit), MaxOuterIterations(maxouterit), MaxPatchupIterations(maxpatchit), SinglePrecGrid(_sp_grid), |  | ||||||
|     OuterLoopNormMult(100.), guesser(NULL), updateResidual(_updateResidual) { }; |  | ||||||
|  |  | ||||||
|   void useGuesser(LinearFunction<FieldF> &g){ |  | ||||||
|     guesser = &g; |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   void operator() (const FieldD &src_d_in, FieldD &sol_d){ |  | ||||||
|     std::vector<FieldD> srcs_d_in{src_d_in}; |  | ||||||
|     std::vector<FieldD> sols_d{sol_d}; |  | ||||||
|  |  | ||||||
|     (*this)(srcs_d_in,sols_d); |  | ||||||
|  |  | ||||||
|     sol_d = sols_d[0]; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void operator() (const std::vector<FieldD> &src_d_in, std::vector<FieldD> &sol_d){ |  | ||||||
|     assert(src_d_in.size() == sol_d.size()); |  | ||||||
|     int NBatch = src_d_in.size(); |  | ||||||
|  |  | ||||||
|     std::cout << GridLogMessage << "NBatch = " << NBatch << std::endl; |  | ||||||
|  |  | ||||||
|     Integer TotalOuterIterations = 0; //Number of restarts |  | ||||||
|     std::vector<Integer> TotalInnerIterations(NBatch,0);     //Number of inner CG iterations |  | ||||||
|     std::vector<Integer> TotalFinalStepIterations(NBatch,0); //Number of CG iterations in final patch-up step |  | ||||||
|    |  | ||||||
|     GridStopWatch TotalTimer; |  | ||||||
|     TotalTimer.Start(); |  | ||||||
|  |  | ||||||
|     GridStopWatch InnerCGtimer; |  | ||||||
|     GridStopWatch PrecChangeTimer; |  | ||||||
|      |  | ||||||
|     int cb = src_d_in[0].Checkerboard(); |  | ||||||
|      |  | ||||||
|     std::vector<RealD> src_norm; |  | ||||||
|     std::vector<RealD> norm; |  | ||||||
|     std::vector<RealD> stop; |  | ||||||
|      |  | ||||||
|     GridBase* DoublePrecGrid = src_d_in[0].Grid(); |  | ||||||
|     FieldD tmp_d(DoublePrecGrid); |  | ||||||
|     tmp_d.Checkerboard() = cb; |  | ||||||
|      |  | ||||||
|     FieldD tmp2_d(DoublePrecGrid); |  | ||||||
|     tmp2_d.Checkerboard() = cb; |  | ||||||
|  |  | ||||||
|     std::vector<FieldD> src_d; |  | ||||||
|     std::vector<FieldF> src_f; |  | ||||||
|     std::vector<FieldF> sol_f; |  | ||||||
|  |  | ||||||
|     for (int i=0; i<NBatch; i++) { |  | ||||||
|       sol_d[i].Checkerboard() = cb; |  | ||||||
|  |  | ||||||
|       src_norm.push_back(norm2(src_d_in[i])); |  | ||||||
|       norm.push_back(0.); |  | ||||||
|       stop.push_back(src_norm[i] * Tolerance*Tolerance); |  | ||||||
|  |  | ||||||
|       src_d.push_back(src_d_in[i]); //source for next inner iteration, computed from residual during operation |  | ||||||
|  |  | ||||||
|       src_f.push_back(SinglePrecGrid); |  | ||||||
|       src_f[i].Checkerboard() = cb; |  | ||||||
|  |  | ||||||
|       sol_f.push_back(SinglePrecGrid); |  | ||||||
|       sol_f[i].Checkerboard() = cb; |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     RealD inner_tol = InnerTolerance; |  | ||||||
|      |  | ||||||
|     ConjugateGradient<FieldF> CG_f(inner_tol, MaxInnerIterations); |  | ||||||
|     CG_f.ErrorOnNoConverge = false; |  | ||||||
|      |  | ||||||
|     Integer &outer_iter = TotalOuterIterations; //so it will be equal to the final iteration count |  | ||||||
|        |  | ||||||
|     for(outer_iter = 0; outer_iter < MaxOuterIterations; outer_iter++){ |  | ||||||
|       std::cout << GridLogMessage << std::endl; |  | ||||||
|       std::cout << GridLogMessage << "Outer iteration " << outer_iter << std::endl; |  | ||||||
|        |  | ||||||
|       bool allConverged = true; |  | ||||||
|        |  | ||||||
|       for (int i=0; i<NBatch; i++) { |  | ||||||
|         //Compute double precision rsd and also new RHS vector. |  | ||||||
|         Linop_d.HermOp(sol_d[i], tmp_d); |  | ||||||
|         norm[i] = axpy_norm(src_d[i], -1., tmp_d, src_d_in[i]); //src_d is residual vector |  | ||||||
|          |  | ||||||
|         std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Outer iteration " << outer_iter <<" solve " << i << " residual "<< norm[i] << " target "<< stop[i] <<std::endl; |  | ||||||
|  |  | ||||||
|         PrecChangeTimer.Start(); |  | ||||||
|         precisionChange(src_f[i], src_d[i]); |  | ||||||
|         PrecChangeTimer.Stop(); |  | ||||||
|          |  | ||||||
|         sol_f[i] = Zero(); |  | ||||||
|        |  | ||||||
|         if(norm[i] > OuterLoopNormMult * stop[i]) { |  | ||||||
|           allConverged = false; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       if (allConverged) break; |  | ||||||
|  |  | ||||||
|       if (updateResidual) { |  | ||||||
|         RealD normMax = *std::max_element(std::begin(norm), std::end(norm)); |  | ||||||
|         RealD stopMax = *std::max_element(std::begin(stop), std::end(stop)); |  | ||||||
|         while( normMax * inner_tol * inner_tol < stopMax) inner_tol *= 2;  // inner_tol = sqrt(stop/norm) ?? |  | ||||||
|         CG_f.Tolerance = inner_tol; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       //Optionally improve inner solver guess (eg using known eigenvectors) |  | ||||||
|       if(guesser != NULL) { |  | ||||||
|         (*guesser)(src_f, sol_f); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       for (int i=0; i<NBatch; i++) { |  | ||||||
|         //Inner CG |  | ||||||
|         InnerCGtimer.Start(); |  | ||||||
|         CG_f(Linop_f, src_f[i], sol_f[i]); |  | ||||||
|         InnerCGtimer.Stop(); |  | ||||||
|         TotalInnerIterations[i] += CG_f.IterationsToComplete; |  | ||||||
|          |  | ||||||
|         //Convert sol back to double and add to double prec solution |  | ||||||
|         PrecChangeTimer.Start(); |  | ||||||
|         precisionChange(tmp_d, sol_f[i]); |  | ||||||
|         PrecChangeTimer.Stop(); |  | ||||||
|          |  | ||||||
|         axpy(sol_d[i], 1.0, tmp_d, sol_d[i]); |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     //Final trial CG |  | ||||||
|     std::cout << GridLogMessage << std::endl; |  | ||||||
|     std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Starting final patch-up double-precision solve"<<std::endl; |  | ||||||
|      |  | ||||||
|     for (int i=0; i<NBatch; i++) { |  | ||||||
|       ConjugateGradient<FieldD> CG_d(Tolerance, MaxPatchupIterations); |  | ||||||
|       CG_d(Linop_d, src_d_in[i], sol_d[i]); |  | ||||||
|       TotalFinalStepIterations[i] += CG_d.IterationsToComplete; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     TotalTimer.Stop(); |  | ||||||
|  |  | ||||||
|     std::cout << GridLogMessage << std::endl; |  | ||||||
|     for (int i=0; i<NBatch; i++) { |  | ||||||
|       std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: solve " << i << " Inner CG iterations " << TotalInnerIterations[i] << " Restarts " << TotalOuterIterations << " Final CG iterations " << TotalFinalStepIterations[i] << std::endl; |  | ||||||
|     } |  | ||||||
|     std::cout << GridLogMessage << std::endl; |  | ||||||
|     std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Total time " << TotalTimer.Elapsed() << " Precision change " << PrecChangeTimer.Elapsed() << " Inner CG total " << InnerCGtimer.Elapsed() << std::endl; |  | ||||||
|      |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
| @@ -52,7 +52,7 @@ public: | |||||||
|   MultiShiftFunction shifts; |   MultiShiftFunction shifts; | ||||||
|   std::vector<RealD> TrueResidualShift; |   std::vector<RealD> TrueResidualShift; | ||||||
|  |  | ||||||
|   ConjugateGradientMultiShift(Integer maxit,MultiShiftFunction &_shifts) :  |   ConjugateGradientMultiShift(Integer maxit, const MultiShiftFunction &_shifts) :  | ||||||
|     MaxIterations(maxit), |     MaxIterations(maxit), | ||||||
|     shifts(_shifts) |     shifts(_shifts) | ||||||
|   {  |   {  | ||||||
| @@ -183,6 +183,9 @@ public: | |||||||
|       axpby(psi[s],0.,-bs[s]*alpha[s],src,src); |       axpby(psi[s],0.,-bs[s]*alpha[s],src,src); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     std::cout << GridLogIterative << "ConjugateGradientMultiShift: initial rn (|src|^2) =" << rn << " qq (|MdagM src|^2) =" << qq << " d ( dot(src, [MdagM + m_0]src) ) =" << d << " c=" << c << std::endl; | ||||||
|  |      | ||||||
|  |    | ||||||
|   /////////////////////////////////////// |   /////////////////////////////////////// | ||||||
|   // Timers |   // Timers | ||||||
|   /////////////////////////////////////// |   /////////////////////////////////////// | ||||||
|   | |||||||
							
								
								
									
										411
									
								
								Grid/algorithms/iterative/ConjugateGradientMultiShiftMixedPrec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										411
									
								
								Grid/algorithms/iterative/ConjugateGradientMultiShiftMixedPrec.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,411 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  |     Grid physics library, www.github.com/paboyle/Grid  | ||||||
|  |  | ||||||
|  |     Source file: ./lib/algorithms/iterative/ConjugateGradientMultiShift.h | ||||||
|  |  | ||||||
|  |     Copyright (C) 2015 | ||||||
|  |  | ||||||
|  | Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Christopher Kelly <ckelly@bnl.gov> | ||||||
|  |  | ||||||
|  |     This program is free software; you can redistribute it and/or modify | ||||||
|  |     it under the terms of the GNU General Public License as published by | ||||||
|  |     the Free Software Foundation; either version 2 of the License, or | ||||||
|  |     (at your option) any later version. | ||||||
|  |  | ||||||
|  |     This program is distributed in the hope that it will be useful, | ||||||
|  |     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |     GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |     You should have received a copy of the GNU General Public License along | ||||||
|  |     with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|  |     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  |  | ||||||
|  |     See the full license in the file "LICENSE" in the top level distribution directory | ||||||
|  | *************************************************************************************/ | ||||||
|  | /*  END LEGAL */ | ||||||
|  | #ifndef GRID_CONJUGATE_GRADIENT_MULTI_SHIFT_MIXEDPREC_H | ||||||
|  | #define GRID_CONJUGATE_GRADIENT_MULTI_SHIFT_MIXEDPREC_H | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | //CK 2020: A variant of the multi-shift conjugate gradient with the matrix multiplication in single precision.  | ||||||
|  | //The residual is stored in single precision, but the search directions and solution are stored in double precision.  | ||||||
|  | //Every update_freq iterations the residual is corrected in double precision.  | ||||||
|  |      | ||||||
|  | //For safety the a final regular CG is applied to clean up if necessary | ||||||
|  |  | ||||||
|  | //Linop to add shift to input linop, used in cleanup CG | ||||||
|  | namespace ConjugateGradientMultiShiftMixedPrecSupport{ | ||||||
|  | template<typename Field> | ||||||
|  | class ShiftedLinop: public LinearOperatorBase<Field>{ | ||||||
|  | public: | ||||||
|  |   LinearOperatorBase<Field> &linop_base; | ||||||
|  |   RealD shift; | ||||||
|  |  | ||||||
|  |   ShiftedLinop(LinearOperatorBase<Field> &_linop_base, RealD _shift): linop_base(_linop_base), shift(_shift){} | ||||||
|  |  | ||||||
|  |   void OpDiag (const Field &in, Field &out){ assert(0); } | ||||||
|  |   void OpDir  (const Field &in, Field &out,int dir,int disp){ assert(0); } | ||||||
|  |   void OpDirAll  (const Field &in, std::vector<Field> &out){ assert(0); } | ||||||
|  |    | ||||||
|  |   void Op     (const Field &in, Field &out){ assert(0); } | ||||||
|  |   void AdjOp  (const Field &in, Field &out){ assert(0); } | ||||||
|  |  | ||||||
|  |   void HermOp(const Field &in, Field &out){ | ||||||
|  |     linop_base.HermOp(in, out); | ||||||
|  |     axpy(out, shift, in, out); | ||||||
|  |   }     | ||||||
|  |  | ||||||
|  |   void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){ | ||||||
|  |     HermOp(in,out); | ||||||
|  |     ComplexD dot = innerProduct(in,out); | ||||||
|  |     n1=real(dot); | ||||||
|  |     n2=norm2(out); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template<class FieldD, class FieldF, | ||||||
|  | 	 typename std::enable_if< getPrecision<FieldD>::value == 2, int>::type = 0, | ||||||
|  | 	 typename std::enable_if< getPrecision<FieldF>::value == 1, int>::type = 0>  | ||||||
|  | class ConjugateGradientMultiShiftMixedPrec : public OperatorMultiFunction<FieldD>, | ||||||
|  | 					     public OperatorFunction<FieldD> | ||||||
|  | { | ||||||
|  | public:                                                 | ||||||
|  |  | ||||||
|  |   using OperatorFunction<FieldD>::operator(); | ||||||
|  |  | ||||||
|  |   RealD   Tolerance; | ||||||
|  |   Integer MaxIterations; | ||||||
|  |   Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion | ||||||
|  |   std::vector<int> IterationsToCompleteShift;  // Iterations for this shift | ||||||
|  |   int verbose; | ||||||
|  |   MultiShiftFunction shifts; | ||||||
|  |   std::vector<RealD> TrueResidualShift; | ||||||
|  |  | ||||||
|  |   int ReliableUpdateFreq; //number of iterations between reliable updates | ||||||
|  |  | ||||||
|  |   GridBase* SinglePrecGrid; //Grid for single-precision fields | ||||||
|  |   LinearOperatorBase<FieldF> &Linop_f; //single precision | ||||||
|  |  | ||||||
|  |   ConjugateGradientMultiShiftMixedPrec(Integer maxit, const MultiShiftFunction &_shifts, | ||||||
|  | 				       GridBase* _SinglePrecGrid, LinearOperatorBase<FieldF> &_Linop_f, | ||||||
|  | 				       int _ReliableUpdateFreq | ||||||
|  | 				       ) :  | ||||||
|  |     MaxIterations(maxit),  shifts(_shifts), SinglePrecGrid(_SinglePrecGrid), Linop_f(_Linop_f), ReliableUpdateFreq(_ReliableUpdateFreq) | ||||||
|  |   {  | ||||||
|  |     verbose=1; | ||||||
|  |     IterationsToCompleteShift.resize(_shifts.order); | ||||||
|  |     TrueResidualShift.resize(_shifts.order); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void operator() (LinearOperatorBase<FieldD> &Linop, const FieldD &src, FieldD &psi) | ||||||
|  |   { | ||||||
|  |     GridBase *grid = src.Grid(); | ||||||
|  |     int nshift = shifts.order; | ||||||
|  |     std::vector<FieldD> results(nshift,grid); | ||||||
|  |     (*this)(Linop,src,results,psi); | ||||||
|  |   } | ||||||
|  |   void operator() (LinearOperatorBase<FieldD> &Linop, const FieldD &src, std::vector<FieldD> &results, FieldD &psi) | ||||||
|  |   { | ||||||
|  |     int nshift = shifts.order; | ||||||
|  |  | ||||||
|  |     (*this)(Linop,src,results); | ||||||
|  |    | ||||||
|  |     psi = shifts.norm*src; | ||||||
|  |     for(int i=0;i<nshift;i++){ | ||||||
|  |       psi = psi + shifts.residues[i]*results[i]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void operator() (LinearOperatorBase<FieldD> &Linop_d, const FieldD &src_d, std::vector<FieldD> &psi_d) | ||||||
|  |   {  | ||||||
|  |     GridBase *DoublePrecGrid = src_d.Grid(); | ||||||
|  |     precisionChangeWorkspace wk_f_from_d(SinglePrecGrid, DoublePrecGrid); | ||||||
|  |     precisionChangeWorkspace wk_d_from_f(DoublePrecGrid, SinglePrecGrid); | ||||||
|  |  | ||||||
|  |     //////////////////////////////////////////////////////////////////////// | ||||||
|  |     // Convenience references to the info stored in "MultiShiftFunction" | ||||||
|  |     //////////////////////////////////////////////////////////////////////// | ||||||
|  |     int nshift = shifts.order; | ||||||
|  |  | ||||||
|  |     std::vector<RealD> &mass(shifts.poles); // Make references to array in "shifts" | ||||||
|  |     std::vector<RealD> &mresidual(shifts.tolerances); | ||||||
|  |     std::vector<RealD> alpha(nshift,1.0); | ||||||
|  |  | ||||||
|  |     //Double precision search directions | ||||||
|  |     FieldD p_d(DoublePrecGrid); | ||||||
|  |     std::vector<FieldD> ps_d(nshift, DoublePrecGrid);// Search directions (double precision) | ||||||
|  |  | ||||||
|  |     FieldD tmp_d(DoublePrecGrid); | ||||||
|  |     FieldD r_d(DoublePrecGrid); | ||||||
|  |     FieldD mmp_d(DoublePrecGrid); | ||||||
|  |  | ||||||
|  |     assert(psi_d.size()==nshift); | ||||||
|  |     assert(mass.size()==nshift); | ||||||
|  |     assert(mresidual.size()==nshift); | ||||||
|  |    | ||||||
|  |     // dynamic sized arrays on stack; 2d is a pain with vector | ||||||
|  |     RealD  bs[nshift]; | ||||||
|  |     RealD  rsq[nshift]; | ||||||
|  |     RealD  z[nshift][2]; | ||||||
|  |     int     converged[nshift]; | ||||||
|  |    | ||||||
|  |     const int       primary =0; | ||||||
|  |    | ||||||
|  |     //Primary shift fields CG iteration | ||||||
|  |     RealD a,b,c,d; | ||||||
|  |     RealD cp,bp,qq; //prev | ||||||
|  |    | ||||||
|  |     // Matrix mult fields | ||||||
|  |     FieldF r_f(SinglePrecGrid); | ||||||
|  |     FieldF p_f(SinglePrecGrid); | ||||||
|  |     FieldF tmp_f(SinglePrecGrid); | ||||||
|  |     FieldF mmp_f(SinglePrecGrid); | ||||||
|  |     FieldF src_f(SinglePrecGrid); | ||||||
|  |     precisionChange(src_f, src_d, wk_f_from_d); | ||||||
|  |  | ||||||
|  |     // Check lightest mass | ||||||
|  |     for(int s=0;s<nshift;s++){ | ||||||
|  |       assert( mass[s]>= mass[primary] ); | ||||||
|  |       converged[s]=0; | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |     // Wire guess to zero | ||||||
|  |     // Residuals "r" are src | ||||||
|  |     // First search direction "p" is also src | ||||||
|  |     cp = norm2(src_d); | ||||||
|  |  | ||||||
|  |     // Handle trivial case of zero src. | ||||||
|  |     if( cp == 0. ){ | ||||||
|  |       for(int s=0;s<nshift;s++){ | ||||||
|  | 	psi_d[s] = Zero(); | ||||||
|  | 	IterationsToCompleteShift[s] = 1; | ||||||
|  | 	TrueResidualShift[s] = 0.; | ||||||
|  |       } | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     for(int s=0;s<nshift;s++){ | ||||||
|  |       rsq[s] = cp * mresidual[s] * mresidual[s]; | ||||||
|  |       std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec: shift "<< s <<" target resid "<<rsq[s]<<std::endl; | ||||||
|  |       ps_d[s] = src_d; | ||||||
|  |     } | ||||||
|  |     // r and p for primary | ||||||
|  |     r_f=src_f; //residual maintained in single | ||||||
|  |     p_f=src_f; | ||||||
|  |     p_d = src_d; //primary copy --- make this a reference to ps_d to save axpys | ||||||
|  |    | ||||||
|  |     //MdagM+m[0] | ||||||
|  |     Linop_f.HermOpAndNorm(p_f,mmp_f,d,qq); // mmp = MdagM p        d=real(dot(p, mmp)),  qq=norm2(mmp) | ||||||
|  |     axpy(mmp_f,mass[0],p_f,mmp_f); | ||||||
|  |     RealD rn = norm2(p_f); | ||||||
|  |     d += rn*mass[0]; | ||||||
|  |  | ||||||
|  |     b = -cp /d; | ||||||
|  |    | ||||||
|  |     // Set up the various shift variables | ||||||
|  |     int       iz=0; | ||||||
|  |     z[0][1-iz] = 1.0; | ||||||
|  |     z[0][iz]   = 1.0; | ||||||
|  |     bs[0]      = b; | ||||||
|  |     for(int s=1;s<nshift;s++){ | ||||||
|  |       z[s][1-iz] = 1.0; | ||||||
|  |       z[s][iz]   = 1.0/( 1.0 - b*(mass[s]-mass[0])); | ||||||
|  |       bs[s]      = b*z[s][iz];  | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |     // r += b[0] A.p[0] | ||||||
|  |     // c= norm(r) | ||||||
|  |     c=axpy_norm(r_f,b,mmp_f,r_f); | ||||||
|  |    | ||||||
|  |     for(int s=0;s<nshift;s++) { | ||||||
|  |       axpby(psi_d[s],0.,-bs[s]*alpha[s],src_d,src_d); | ||||||
|  |     } | ||||||
|  |    | ||||||
|  |     /////////////////////////////////////// | ||||||
|  |     // Timers | ||||||
|  |     /////////////////////////////////////// | ||||||
|  |     GridStopWatch AXPYTimer, ShiftTimer, QRTimer, MatrixTimer, SolverTimer, PrecChangeTimer, CleanupTimer; | ||||||
|  |  | ||||||
|  |     SolverTimer.Start(); | ||||||
|  |    | ||||||
|  |     // Iteration loop | ||||||
|  |     int k; | ||||||
|  |    | ||||||
|  |     for (k=1;k<=MaxIterations;k++){     | ||||||
|  |       a = c /cp; | ||||||
|  |  | ||||||
|  |       //Update double precision search direction by residual | ||||||
|  |       PrecChangeTimer.Start(); | ||||||
|  |       precisionChange(r_d, r_f, wk_d_from_f); | ||||||
|  |       PrecChangeTimer.Stop(); | ||||||
|  |  | ||||||
|  |       AXPYTimer.Start(); | ||||||
|  |       axpy(p_d,a,p_d,r_d);  | ||||||
|  |  | ||||||
|  |       for(int s=0;s<nshift;s++){ | ||||||
|  | 	if ( ! converged[s] ) {  | ||||||
|  | 	  if (s==0){ | ||||||
|  | 	    axpy(ps_d[s],a,ps_d[s],r_d); | ||||||
|  | 	  } else{ | ||||||
|  | 	    RealD as =a *z[s][iz]*bs[s] /(z[s][1-iz]*b); | ||||||
|  | 	    axpby(ps_d[s],z[s][iz],as,r_d,ps_d[s]); | ||||||
|  | 	  } | ||||||
|  | 	} | ||||||
|  |       } | ||||||
|  |       AXPYTimer.Stop(); | ||||||
|  |  | ||||||
|  |       PrecChangeTimer.Start(); | ||||||
|  |       precisionChange(p_f, p_d, wk_f_from_d); //get back single prec search direction for linop | ||||||
|  |       PrecChangeTimer.Stop(); | ||||||
|  |  | ||||||
|  |       cp=c; | ||||||
|  |       MatrixTimer.Start();   | ||||||
|  |       Linop_f.HermOp(p_f,mmp_f);  | ||||||
|  |       d=real(innerProduct(p_f,mmp_f));     | ||||||
|  |       MatrixTimer.Stop();   | ||||||
|  |  | ||||||
|  |       AXPYTimer.Start(); | ||||||
|  |       axpy(mmp_f,mass[0],p_f,mmp_f); | ||||||
|  |       AXPYTimer.Stop(); | ||||||
|  |       RealD rn = norm2(p_f); | ||||||
|  |       d += rn*mass[0]; | ||||||
|  |      | ||||||
|  |       bp=b; | ||||||
|  |       b=-cp/d; | ||||||
|  |      | ||||||
|  |       // Toggle the recurrence history | ||||||
|  |       bs[0] = b; | ||||||
|  |       iz = 1-iz; | ||||||
|  |       ShiftTimer.Start(); | ||||||
|  |       for(int s=1;s<nshift;s++){ | ||||||
|  | 	if((!converged[s])){ | ||||||
|  | 	  RealD z0 = z[s][1-iz]; | ||||||
|  | 	  RealD z1 = z[s][iz]; | ||||||
|  | 	  z[s][iz] = z0*z1*bp | ||||||
|  | 	    / (b*a*(z1-z0) + z1*bp*(1- (mass[s]-mass[0])*b));  | ||||||
|  | 	  bs[s] = b*z[s][iz]/z0; // NB sign  rel to Mike | ||||||
|  | 	} | ||||||
|  |       } | ||||||
|  |       ShiftTimer.Stop(); | ||||||
|  |  | ||||||
|  |       //Update double precision solutions | ||||||
|  |       AXPYTimer.Start(); | ||||||
|  |       for(int s=0;s<nshift;s++){ | ||||||
|  | 	int ss = s; | ||||||
|  | 	if( (!converged[s]) ) {  | ||||||
|  | 	  axpy(psi_d[ss],-bs[s]*alpha[s],ps_d[s],psi_d[ss]); | ||||||
|  | 	} | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       //Perform reliable update if necessary; otherwise update residual from single-prec mmp | ||||||
|  |       RealD c_f = axpy_norm(r_f,b,mmp_f,r_f); | ||||||
|  |       AXPYTimer.Stop(); | ||||||
|  |  | ||||||
|  |       c = c_f; | ||||||
|  |  | ||||||
|  |       if(k % ReliableUpdateFreq == 0){ | ||||||
|  | 	//Replace r with true residual | ||||||
|  | 	MatrixTimer.Start();   | ||||||
|  | 	Linop_d.HermOp(psi_d[0],mmp_d);  | ||||||
|  | 	MatrixTimer.Stop();   | ||||||
|  |  | ||||||
|  | 	AXPYTimer.Start(); | ||||||
|  | 	axpy(mmp_d,mass[0],psi_d[0],mmp_d); | ||||||
|  |  | ||||||
|  | 	RealD c_d = axpy_norm(r_d, -1.0, mmp_d, src_d); | ||||||
|  | 	AXPYTimer.Stop(); | ||||||
|  |  | ||||||
|  | 	std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec k="<<k<< ", replaced |r|^2 = "<<c_f <<" with |r|^2 = "<<c_d<<std::endl; | ||||||
|  | 	 | ||||||
|  | 	PrecChangeTimer.Start(); | ||||||
|  | 	precisionChange(r_f, r_d, wk_f_from_d); | ||||||
|  | 	PrecChangeTimer.Stop(); | ||||||
|  | 	c = c_d; | ||||||
|  |       } | ||||||
|  |      | ||||||
|  |       // Convergence checks | ||||||
|  |       int all_converged = 1; | ||||||
|  |       for(int s=0;s<nshift;s++){ | ||||||
|  |        | ||||||
|  | 	if ( (!converged[s]) ){ | ||||||
|  | 	  IterationsToCompleteShift[s] = k; | ||||||
|  | 	 | ||||||
|  | 	  RealD css  = c * z[s][iz]* z[s][iz]; | ||||||
|  | 	 | ||||||
|  | 	  if(css<rsq[s]){ | ||||||
|  | 	    if ( ! converged[s] ) | ||||||
|  | 	      std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec k="<<k<<" Shift "<<s<<" has converged"<<std::endl; | ||||||
|  | 	    converged[s]=1; | ||||||
|  | 	  } else { | ||||||
|  | 	    all_converged=0; | ||||||
|  | 	  } | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if ( all_converged ){ | ||||||
|  |  | ||||||
|  | 	SolverTimer.Stop(); | ||||||
|  | 	std::cout<<GridLogMessage<< "ConjugateGradientMultiShiftMixedPrec: All shifts have converged iteration "<<k<<std::endl; | ||||||
|  | 	std::cout<<GridLogMessage<< "ConjugateGradientMultiShiftMixedPrec: Checking solutions"<<std::endl; | ||||||
|  |        | ||||||
|  | 	// Check answers  | ||||||
|  | 	for(int s=0; s < nshift; s++) {  | ||||||
|  | 	  Linop_d.HermOpAndNorm(psi_d[s],mmp_d,d,qq); | ||||||
|  | 	  axpy(tmp_d,mass[s],psi_d[s],mmp_d); | ||||||
|  | 	  axpy(r_d,-alpha[s],src_d,tmp_d); | ||||||
|  | 	  RealD rn = norm2(r_d); | ||||||
|  | 	  RealD cn = norm2(src_d); | ||||||
|  | 	  TrueResidualShift[s] = std::sqrt(rn/cn); | ||||||
|  | 	  std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec: shift["<<s<<"] true residual "<< TrueResidualShift[s] << " target " << mresidual[s] << std::endl; | ||||||
|  |  | ||||||
|  | 	  //If we have not reached the desired tolerance, do a (mixed precision) CG cleanup | ||||||
|  | 	  if(rn >= rsq[s]){ | ||||||
|  | 	    CleanupTimer.Start(); | ||||||
|  | 	    std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec: performing cleanup step for shift " << s << std::endl; | ||||||
|  |  | ||||||
|  | 	    //Setup linear operators for final cleanup | ||||||
|  | 	    ConjugateGradientMultiShiftMixedPrecSupport::ShiftedLinop<FieldD> Linop_shift_d(Linop_d, mass[s]); | ||||||
|  | 	    ConjugateGradientMultiShiftMixedPrecSupport::ShiftedLinop<FieldF> Linop_shift_f(Linop_f, mass[s]); | ||||||
|  | 					        | ||||||
|  | 	    MixedPrecisionConjugateGradient<FieldD,FieldF> cg(mresidual[s], MaxIterations, MaxIterations, SinglePrecGrid, Linop_shift_f, Linop_shift_d);  | ||||||
|  | 	    cg(src_d, psi_d[s]); | ||||||
|  | 	     | ||||||
|  | 	    TrueResidualShift[s] = cg.TrueResidual; | ||||||
|  | 	    CleanupTimer.Stop(); | ||||||
|  | 	  } | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	std::cout << GridLogMessage << "ConjugateGradientMultiShiftMixedPrec: Time Breakdown for body"<<std::endl; | ||||||
|  | 	std::cout << GridLogMessage << "\tSolver    " << SolverTimer.Elapsed()     <<std::endl; | ||||||
|  | 	std::cout << GridLogMessage << "\t\tAXPY    " << AXPYTimer.Elapsed()     <<std::endl; | ||||||
|  | 	std::cout << GridLogMessage << "\t\tMatrix    " << MatrixTimer.Elapsed()     <<std::endl; | ||||||
|  | 	std::cout << GridLogMessage << "\t\tShift    " << ShiftTimer.Elapsed()     <<std::endl; | ||||||
|  | 	std::cout << GridLogMessage << "\t\tPrecision Change " << PrecChangeTimer.Elapsed()     <<std::endl; | ||||||
|  | 	std::cout << GridLogMessage << "\tFinal Cleanup " << CleanupTimer.Elapsed()     <<std::endl; | ||||||
|  | 	std::cout << GridLogMessage << "\tSolver+Cleanup " << SolverTimer.Elapsed() + CleanupTimer.Elapsed() << std::endl; | ||||||
|  |  | ||||||
|  | 	IterationsToComplete = k;	 | ||||||
|  |  | ||||||
|  | 	return; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     | ||||||
|  |     } | ||||||
|  |     // ugly hack | ||||||
|  |     std::cout<<GridLogMessage<<"CG multi shift did not converge"<<std::endl; | ||||||
|  |     //  assert(0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | }; | ||||||
|  | NAMESPACE_END(Grid); | ||||||
|  | #endif | ||||||
| @@ -113,42 +113,6 @@ public: | |||||||
|     blockPromote(guess_coarse,guess,subspace); |     blockPromote(guess_coarse,guess,subspace); | ||||||
|     guess.Checkerboard() = src.Checkerboard(); |     guess.Checkerboard() = src.Checkerboard(); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   void operator()(const std::vector<FineField> &src,std::vector<FineField> &guess) { |  | ||||||
|     int Nevec = (int)evec_coarse.size(); |  | ||||||
|     int Nsrc = (int)src.size(); |  | ||||||
|     // make temp variables |  | ||||||
|     std::vector<CoarseField> src_coarse(Nsrc,evec_coarse[0].Grid()); |  | ||||||
|     std::vector<CoarseField> guess_coarse(Nsrc,evec_coarse[0].Grid());     |  | ||||||
|     //Preporcessing |  | ||||||
|     std::cout << GridLogMessage << "Start BlockProject for loop" << std::endl; |  | ||||||
|     for (int j=0;j<Nsrc;j++) |  | ||||||
|     { |  | ||||||
|     guess_coarse[j] = Zero(); |  | ||||||
|     std::cout << GridLogMessage << "BlockProject iter: " << j << std::endl; |  | ||||||
|     blockProject(src_coarse[j],src[j],subspace); |  | ||||||
|     } |  | ||||||
|     //deflation set up for eigen vector batchsize 1 and source batch size equal number of sources |  | ||||||
|     std::cout << GridLogMessage << "Start ProjectAccum for loop" << std::endl; |  | ||||||
|     for (int i=0;i<Nevec;i++) |  | ||||||
|     { |  | ||||||
|       std::cout << GridLogMessage << "ProjectAccum Nvec: " << i << std::endl; |  | ||||||
|       const CoarseField & tmp = evec_coarse[i]; |  | ||||||
|       for (int j=0;j<Nsrc;j++) |  | ||||||
|       { |  | ||||||
|         axpy(guess_coarse[j],TensorRemove(innerProduct(tmp,src_coarse[j])) / eval_coarse[i],tmp,guess_coarse[j]); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     //postprocessing |  | ||||||
|     std::cout << GridLogMessage << "Start BlockPromote for loop" << std::endl; |  | ||||||
|     for (int j=0;j<Nsrc;j++) |  | ||||||
|     { |  | ||||||
|     std::cout << GridLogMessage << "BlockProject iter: " << j << std::endl; |  | ||||||
|     blockPromote(guess_coarse[j],guess[j],subspace); |  | ||||||
|     guess[j].Checkerboard() = src[j].Checkerboard(); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -44,6 +44,7 @@ public: | |||||||
| 				  int, MinRes);    // Must restart | 				  int, MinRes);    // Must restart | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | //This class is the input parameter class for some testing programs | ||||||
| struct LocalCoherenceLanczosParams : Serializable { | struct LocalCoherenceLanczosParams : Serializable { | ||||||
| public: | public: | ||||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(LocalCoherenceLanczosParams, |   GRID_SERIALIZABLE_CLASS_MEMBERS(LocalCoherenceLanczosParams, | ||||||
| @@ -155,6 +156,7 @@ public: | |||||||
|       _coarse_relax_tol(coarse_relax_tol)   |       _coarse_relax_tol(coarse_relax_tol)   | ||||||
|   {    }; |   {    }; | ||||||
|  |  | ||||||
|  |   //evalMaxApprox: approximation of largest eval of the fine Chebyshev operator (suitably wrapped by block projection) | ||||||
|   int TestConvergence(int j,RealD eresid,CoarseField &B, RealD &eval,RealD evalMaxApprox) |   int TestConvergence(int j,RealD eresid,CoarseField &B, RealD &eval,RealD evalMaxApprox) | ||||||
|   { |   { | ||||||
|     CoarseField v(B); |     CoarseField v(B); | ||||||
| @@ -181,8 +183,16 @@ public: | |||||||
|     if( (vv<eresid*eresid) ) conv = 1; |     if( (vv<eresid*eresid) ) conv = 1; | ||||||
|     return conv; |     return conv; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //This function is called at the end of the coarse grid Lanczos. It promotes the coarse eigenvector 'B' to the fine grid, | ||||||
|  |   //applies a smoother to the result then computes the computes the *fine grid* eigenvalue (output as 'eval'). | ||||||
|  |  | ||||||
|  |   //evalMaxApprox should be the approximation of the largest eval of the fine Hermop. However when this function is called by IRL it actually passes the largest eval of the *Chebyshev* operator (as this is the max approx used for the TestConvergence above) | ||||||
|  |   //As the largest eval of the Chebyshev is typically several orders of magnitude larger this makes the convergence test pass even when it should not. | ||||||
|  |   //We therefore ignore evalMaxApprox here and use a value of 1.0 (note this value is already used by TestCoarse) | ||||||
|   int ReconstructEval(int j,RealD eresid,CoarseField &B, RealD &eval,RealD evalMaxApprox)   |   int ReconstructEval(int j,RealD eresid,CoarseField &B, RealD &eval,RealD evalMaxApprox)   | ||||||
|   { |   { | ||||||
|  |     evalMaxApprox = 1.0; //cf above | ||||||
|     GridBase *FineGrid = _subspace[0].Grid();     |     GridBase *FineGrid = _subspace[0].Grid();     | ||||||
|     int checkerboard   = _subspace[0].Checkerboard(); |     int checkerboard   = _subspace[0].Checkerboard(); | ||||||
|     FineField fB(FineGrid);fB.Checkerboard() =checkerboard; |     FineField fB(FineGrid);fB.Checkerboard() =checkerboard; | ||||||
| @@ -201,13 +211,13 @@ public: | |||||||
|     eval   = vnum/vden; |     eval   = vnum/vden; | ||||||
|     fv -= eval*fB; |     fv -= eval*fB; | ||||||
|     RealD vv = norm2(fv) / ::pow(evalMaxApprox,2.0); |     RealD vv = norm2(fv) / ::pow(evalMaxApprox,2.0); | ||||||
|  |     if ( j > nbasis ) eresid = eresid*_coarse_relax_tol; | ||||||
|      |      | ||||||
|     std::cout.precision(13); |     std::cout.precision(13); | ||||||
|     std::cout<<GridLogIRL  << "[" << std::setw(3)<<j<<"] " |     std::cout<<GridLogIRL  << "[" << std::setw(3)<<j<<"] " | ||||||
| 	     <<"eval = "<<std::setw(25)<< eval << " (" << eval_poly << ")" | 	     <<"eval = "<<std::setw(25)<< eval << " (" << eval_poly << ")" | ||||||
| 	     <<" |H B[i] - eval[i]B[i]|^2 / evalMaxApprox^2 " << std::setw(25) << vv | 	     <<" |H B[i] - eval[i]B[i]|^2 / evalMaxApprox^2 " << std::setw(25) << vv << " target " << eresid*eresid | ||||||
| 	     <<std::endl; | 	     <<std::endl; | ||||||
|     if ( j > nbasis ) eresid = eresid*_coarse_relax_tol; |  | ||||||
|     if( (vv<eresid*eresid) ) return 1; |     if( (vv<eresid*eresid) ) return 1; | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
| @@ -285,6 +295,10 @@ public: | |||||||
|     evals_coarse.resize(0); |     evals_coarse.resize(0); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   //The block inner product is the inner product on the fine grid locally summed over the blocks | ||||||
|  |   //to give a Lattice<Scalar> on the coarse grid. This function orthnormalizes the fine-grid subspace | ||||||
|  |   //vectors under the block inner product. This step must be performed after computing the fine grid | ||||||
|  |   //eigenvectors and before computing the coarse grid eigenvectors.     | ||||||
|   void Orthogonalise(void ) { |   void Orthogonalise(void ) { | ||||||
|     CoarseScalar InnerProd(_CoarseGrid); |     CoarseScalar InnerProd(_CoarseGrid); | ||||||
|     std::cout << GridLogMessage <<" Gramm-Schmidt pass 1"<<std::endl; |     std::cout << GridLogMessage <<" Gramm-Schmidt pass 1"<<std::endl; | ||||||
| @@ -328,6 +342,8 @@ public: | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //While this method serves to check the coarse eigenvectors, it also recomputes the eigenvalues from the smoothed reconstructed eigenvectors | ||||||
|  |   //hence the smoother can be tuned after running the coarse Lanczos by using a different smoother here | ||||||
|   void testCoarse(RealD resid,ChebyParams cheby_smooth,RealD relax)  |   void testCoarse(RealD resid,ChebyParams cheby_smooth,RealD relax)  | ||||||
|   { |   { | ||||||
|     assert(evals_fine.size() == nbasis); |     assert(evals_fine.size() == nbasis); | ||||||
| @@ -376,18 +392,23 @@ public: | |||||||
|     evals_fine.resize(nbasis); |     evals_fine.resize(nbasis); | ||||||
|     subspace.resize(nbasis,_FineGrid); |     subspace.resize(nbasis,_FineGrid); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   //cheby_op: Parameters of the fine grid Chebyshev polynomial used for the Lanczos acceleration | ||||||
|  |   //cheby_smooth: Parameters of a separate Chebyshev polynomial used after the Lanczos has completed to smooth out high frequency noise in the reconstructed fine grid eigenvectors prior to computing the eigenvalue | ||||||
|  |   //relax: Reconstructed eigenvectors (post smoothing) are naturally not as precise as true eigenvectors. This factor acts as a multiplier on the stopping condition when determining whether the results satisfy the user provided stopping condition | ||||||
|   void calcCoarse(ChebyParams cheby_op,ChebyParams cheby_smooth,RealD relax, |   void calcCoarse(ChebyParams cheby_op,ChebyParams cheby_smooth,RealD relax, | ||||||
| 		  int Nstop, int Nk, int Nm,RealD resid,  | 		  int Nstop, int Nk, int Nm,RealD resid,  | ||||||
| 		  RealD MaxIt, RealD betastp, int MinRes) | 		  RealD MaxIt, RealD betastp, int MinRes) | ||||||
|   { |   { | ||||||
|     Chebyshev<FineField>                          Cheby(cheby_op); |     Chebyshev<FineField>                          Cheby(cheby_op); //Chebyshev of fine operator on fine grid | ||||||
|     ProjectedHermOp<Fobj,CComplex,nbasis>         Op(_FineOp,subspace); |     ProjectedHermOp<Fobj,CComplex,nbasis>         Op(_FineOp,subspace); //Fine operator on coarse grid with intermediate fine grid conversion | ||||||
|     ProjectedFunctionHermOp<Fobj,CComplex,nbasis> ChebyOp (Cheby,_FineOp,subspace); |     ProjectedFunctionHermOp<Fobj,CComplex,nbasis> ChebyOp (Cheby,_FineOp,subspace); //Chebyshev of fine operator on coarse grid with intermediate fine grid conversion | ||||||
|     ////////////////////////////////////////////////////////////////////////////////////////////////// |     ////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|     // create a smoother and see if we can get a cheap convergence test and smooth inside the IRL |     // create a smoother and see if we can get a cheap convergence test and smooth inside the IRL | ||||||
|     ////////////////////////////////////////////////////////////////////////////////////////////////// |     ////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|     Chebyshev<FineField>                                           ChebySmooth(cheby_smooth); |     Chebyshev<FineField>                                           ChebySmooth(cheby_smooth); //lower order Chebyshev of fine operator on fine grid used to smooth regenerated eigenvectors | ||||||
|     ImplicitlyRestartedLanczosSmoothedTester<Fobj,CComplex,nbasis> ChebySmoothTester(ChebyOp,ChebySmooth,_FineOp,subspace,relax);  |     ImplicitlyRestartedLanczosSmoothedTester<Fobj,CComplex,nbasis> ChebySmoothTester(ChebyOp,ChebySmooth,_FineOp,subspace,relax);  | ||||||
|  |  | ||||||
|     evals_coarse.resize(Nm); |     evals_coarse.resize(Nm); | ||||||
| @@ -395,6 +416,7 @@ public: | |||||||
|  |  | ||||||
|     CoarseField src(_CoarseGrid);     src=1.0;  |     CoarseField src(_CoarseGrid);     src=1.0;  | ||||||
|  |  | ||||||
|  |     //Note the "tester" here is also responsible for generating the fine grid eigenvalues which are output into the "evals_coarse" array | ||||||
|     ImplicitlyRestartedLanczos<CoarseField> IRL(ChebyOp,ChebyOp,ChebySmoothTester,Nstop,Nk,Nm,resid,MaxIt,betastp,MinRes); |     ImplicitlyRestartedLanczos<CoarseField> IRL(ChebyOp,ChebyOp,ChebySmoothTester,Nstop,Nk,Nm,resid,MaxIt,betastp,MinRes); | ||||||
|     int Nconv=0; |     int Nconv=0; | ||||||
|     IRL.calc(evals_coarse,evec_coarse,src,Nconv,false); |     IRL.calc(evals_coarse,evec_coarse,src,Nconv,false); | ||||||
| @@ -405,6 +427,14 @@ public: | |||||||
|       std::cout << i << " Coarse eval = " << evals_coarse[i]  << std::endl; |       std::cout << i << " Coarse eval = " << evals_coarse[i]  << std::endl; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //Get the fine eigenvector 'i' by reconstruction | ||||||
|  |   void getFineEvecEval(FineField &evec, RealD &eval, const int i) const{ | ||||||
|  |     blockPromote(evec_coarse[i],evec,subspace);   | ||||||
|  |     eval = evals_coarse[i]; | ||||||
|  |   } | ||||||
|  |      | ||||||
|  |      | ||||||
| }; | }; | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|   | |||||||
| @@ -30,6 +30,8 @@ template<class Field> class PowerMethod | |||||||
|       RealD vden = norm2(src_n);  |       RealD vden = norm2(src_n);  | ||||||
|       RealD na = vnum/vden;  |       RealD na = vnum/vden;  | ||||||
|  |  | ||||||
|  |       std::cout << GridLogIterative << "PowerMethod: Current approximation of largest eigenvalue " << na << std::endl; | ||||||
|  |        | ||||||
|       if ( (fabs(evalMaxApprox/na - 1.0) < 0.001) || (i==_MAX_ITER_EST_-1) ) {  |       if ( (fabs(evalMaxApprox/na - 1.0) < 0.001) || (i==_MAX_ITER_EST_-1) ) {  | ||||||
|  	evalMaxApprox = na;  |  	evalMaxApprox = na;  | ||||||
| 	std::cout << GridLogMessage << " Approximation of largest eigenvalue: " << evalMaxApprox << std::endl; | 	std::cout << GridLogMessage << " Approximation of largest eigenvalue: " << evalMaxApprox << std::endl; | ||||||
|   | |||||||
| @@ -4,14 +4,11 @@ NAMESPACE_BEGIN(Grid); | |||||||
|  |  | ||||||
| /*Allocation types, saying which pointer cache should be used*/ | /*Allocation types, saying which pointer cache should be used*/ | ||||||
| #define Cpu      (0) | #define Cpu      (0) | ||||||
| #define CpuHuge  (1) | #define CpuSmall (1) | ||||||
| #define CpuSmall (2) | #define Acc      (2) | ||||||
| #define Acc      (3) | #define AccSmall (3) | ||||||
| #define AccHuge  (4) | #define Shared   (4) | ||||||
| #define AccSmall (5) | #define SharedSmall (5) | ||||||
| #define Shared   (6) |  | ||||||
| #define SharedHuge  (7) |  | ||||||
| #define SharedSmall (8) |  | ||||||
| #undef GRID_MM_VERBOSE  | #undef GRID_MM_VERBOSE  | ||||||
| uint64_t total_shared; | uint64_t total_shared; | ||||||
| uint64_t total_device; | uint64_t total_device; | ||||||
| @@ -38,15 +35,12 @@ void MemoryManager::PrintBytes(void) | |||||||
|    |    | ||||||
| } | } | ||||||
|  |  | ||||||
| uint64_t MemoryManager::DeviceCacheBytes() { return CacheBytes[Acc] + CacheBytes[AccHuge] + CacheBytes[AccSmall]; } |  | ||||||
| uint64_t MemoryManager::HostCacheBytes()   { return CacheBytes[Cpu] + CacheBytes[CpuHuge] + CacheBytes[CpuSmall]; } |  | ||||||
|  |  | ||||||
| ////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////// | ||||||
| // Data tables for recently freed pooiniter caches | // Data tables for recently freed pooiniter caches | ||||||
| ////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////// | ||||||
| MemoryManager::AllocationCacheEntry MemoryManager::Entries[MemoryManager::NallocType][MemoryManager::NallocCacheMax]; | MemoryManager::AllocationCacheEntry MemoryManager::Entries[MemoryManager::NallocType][MemoryManager::NallocCacheMax]; | ||||||
| int MemoryManager::Victim[MemoryManager::NallocType]; | int MemoryManager::Victim[MemoryManager::NallocType]; | ||||||
| int MemoryManager::Ncache[MemoryManager::NallocType] = { 2, 0, 8, 8, 0, 16, 8, 0, 16 }; | int MemoryManager::Ncache[MemoryManager::NallocType] = { 2, 8, 2, 8, 2, 8 }; | ||||||
| uint64_t MemoryManager::CacheBytes[MemoryManager::NallocType]; | uint64_t MemoryManager::CacheBytes[MemoryManager::NallocType]; | ||||||
| ////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////// | ||||||
| // Actual allocation and deallocation utils | // Actual allocation and deallocation utils | ||||||
| @@ -176,16 +170,6 @@ void MemoryManager::Init(void) | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   str= getenv("GRID_ALLOC_NCACHE_HUGE"); |  | ||||||
|   if ( str ) { |  | ||||||
|     Nc = atoi(str); |  | ||||||
|     if ( (Nc>=0) && (Nc < NallocCacheMax)) { |  | ||||||
|       Ncache[CpuHuge]=Nc; |  | ||||||
|       Ncache[AccHuge]=Nc; |  | ||||||
|       Ncache[SharedHuge]=Nc; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   str= getenv("GRID_ALLOC_NCACHE_SMALL"); |   str= getenv("GRID_ALLOC_NCACHE_SMALL"); | ||||||
|   if ( str ) { |   if ( str ) { | ||||||
|     Nc = atoi(str); |     Nc = atoi(str); | ||||||
| @@ -206,9 +190,7 @@ void MemoryManager::InitMessage(void) { | |||||||
|    |    | ||||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() setting up"<<std::endl; |   std::cout << GridLogMessage<< "MemoryManager::Init() setting up"<<std::endl; | ||||||
| #ifdef ALLOCATION_CACHE | #ifdef ALLOCATION_CACHE | ||||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() cache pool for recent host   allocations: SMALL "<<Ncache[CpuSmall]<<" LARGE "<<Ncache[Cpu]<<" HUGE "<<Ncache[CpuHuge]<<std::endl; |   std::cout << GridLogMessage<< "MemoryManager::Init() cache pool for recent allocations: SMALL "<<Ncache[CpuSmall]<<" LARGE "<<Ncache[Cpu]<<std::endl; | ||||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() cache pool for recent device allocations: SMALL "<<Ncache[AccSmall]<<" LARGE "<<Ncache[Acc]<<" Huge "<<Ncache[AccHuge]<<std::endl; |  | ||||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() cache pool for recent shared allocations: SMALL "<<Ncache[SharedSmall]<<" LARGE "<<Ncache[Shared]<<" Huge "<<Ncache[SharedHuge]<<std::endl; |  | ||||||
| #endif | #endif | ||||||
|    |    | ||||||
| #ifdef GRID_UVM | #ifdef GRID_UVM | ||||||
| @@ -240,11 +222,8 @@ void MemoryManager::InitMessage(void) { | |||||||
| void *MemoryManager::Insert(void *ptr,size_t bytes,int type)  | void *MemoryManager::Insert(void *ptr,size_t bytes,int type)  | ||||||
| { | { | ||||||
| #ifdef ALLOCATION_CACHE | #ifdef ALLOCATION_CACHE | ||||||
|   int cache; |   bool small = (bytes < GRID_ALLOC_SMALL_LIMIT); | ||||||
|   if      (bytes < GRID_ALLOC_SMALL_LIMIT) cache = type + 2; |   int cache = type + small; | ||||||
|   else if (bytes >= GRID_ALLOC_HUGE_LIMIT) cache = type + 1; |  | ||||||
|   else                                     cache = type; |  | ||||||
|  |  | ||||||
|   return Insert(ptr,bytes,Entries[cache],Ncache[cache],Victim[cache],CacheBytes[cache]);   |   return Insert(ptr,bytes,Entries[cache],Ncache[cache],Victim[cache],CacheBytes[cache]);   | ||||||
| #else | #else | ||||||
|   return ptr; |   return ptr; | ||||||
| @@ -253,12 +232,11 @@ void *MemoryManager::Insert(void *ptr,size_t bytes,int type) | |||||||
|  |  | ||||||
| void *MemoryManager::Insert(void *ptr,size_t bytes,AllocationCacheEntry *entries,int ncache,int &victim, uint64_t &cacheBytes)  | void *MemoryManager::Insert(void *ptr,size_t bytes,AllocationCacheEntry *entries,int ncache,int &victim, uint64_t &cacheBytes)  | ||||||
| { | { | ||||||
|  |   assert(ncache>0); | ||||||
| #ifdef GRID_OMP | #ifdef GRID_OMP | ||||||
|   assert(omp_in_parallel()==0); |   assert(omp_in_parallel()==0); | ||||||
| #endif  | #endif  | ||||||
|  |  | ||||||
|   if (ncache == 0) return ptr; |  | ||||||
|  |  | ||||||
|   void * ret = NULL; |   void * ret = NULL; | ||||||
|   int v = -1; |   int v = -1; | ||||||
|  |  | ||||||
| @@ -293,11 +271,8 @@ void *MemoryManager::Insert(void *ptr,size_t bytes,AllocationCacheEntry *entries | |||||||
| void *MemoryManager::Lookup(size_t bytes,int type) | void *MemoryManager::Lookup(size_t bytes,int type) | ||||||
| { | { | ||||||
| #ifdef ALLOCATION_CACHE | #ifdef ALLOCATION_CACHE | ||||||
|   int cache; |   bool small = (bytes < GRID_ALLOC_SMALL_LIMIT); | ||||||
|   if      (bytes < GRID_ALLOC_SMALL_LIMIT) cache = type + 2; |   int cache = type+small; | ||||||
|   else if (bytes >= GRID_ALLOC_HUGE_LIMIT) cache = type + 1; |  | ||||||
|   else                                     cache = type; |  | ||||||
|  |  | ||||||
|   return Lookup(bytes,Entries[cache],Ncache[cache],CacheBytes[cache]); |   return Lookup(bytes,Entries[cache],Ncache[cache],CacheBytes[cache]); | ||||||
| #else | #else | ||||||
|   return NULL; |   return NULL; | ||||||
| @@ -306,6 +281,7 @@ void *MemoryManager::Lookup(size_t bytes,int type) | |||||||
|  |  | ||||||
| void *MemoryManager::Lookup(size_t bytes,AllocationCacheEntry *entries,int ncache,uint64_t & cacheBytes)  | void *MemoryManager::Lookup(size_t bytes,AllocationCacheEntry *entries,int ncache,uint64_t & cacheBytes)  | ||||||
| { | { | ||||||
|  |   assert(ncache>0); | ||||||
| #ifdef GRID_OMP | #ifdef GRID_OMP | ||||||
|   assert(omp_in_parallel()==0); |   assert(omp_in_parallel()==0); | ||||||
| #endif  | #endif  | ||||||
|   | |||||||
| @@ -35,12 +35,6 @@ NAMESPACE_BEGIN(Grid); | |||||||
| // Move control to configure.ac and Config.h? | // Move control to configure.ac and Config.h? | ||||||
|  |  | ||||||
| #define GRID_ALLOC_SMALL_LIMIT (4096) | #define GRID_ALLOC_SMALL_LIMIT (4096) | ||||||
| #define GRID_ALLOC_HUGE_LIMIT  (2147483648) |  | ||||||
|  |  | ||||||
| #define STRINGIFY(x) #x |  | ||||||
| #define TOSTRING(x) STRINGIFY(x) |  | ||||||
| #define FILE_LINE __FILE__ ":" TOSTRING(__LINE__) |  | ||||||
| #define AUDIT(a) MemoryManager::Audit(FILE_LINE) |  | ||||||
|  |  | ||||||
| /*Pinning pages is costly*/ | /*Pinning pages is costly*/ | ||||||
| //////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -71,21 +65,6 @@ enum ViewMode { | |||||||
|   CpuWriteDiscard = 0x10 // same for now |   CpuWriteDiscard = 0x10 // same for now | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct MemoryStatus { |  | ||||||
|   uint64_t     DeviceBytes; |  | ||||||
|   uint64_t     DeviceLRUBytes; |  | ||||||
|   uint64_t     DeviceMaxBytes; |  | ||||||
|   uint64_t     HostToDeviceBytes; |  | ||||||
|   uint64_t     DeviceToHostBytes; |  | ||||||
|   uint64_t     HostToDeviceXfer; |  | ||||||
|   uint64_t     DeviceToHostXfer; |  | ||||||
|   uint64_t     DeviceEvictions; |  | ||||||
|   uint64_t     DeviceDestroy; |  | ||||||
|   uint64_t     DeviceAllocCacheBytes; |  | ||||||
|   uint64_t     HostAllocCacheBytes; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class MemoryManager { | class MemoryManager { | ||||||
| private: | private: | ||||||
|  |  | ||||||
| @@ -99,7 +78,7 @@ private: | |||||||
|   } AllocationCacheEntry; |   } AllocationCacheEntry; | ||||||
|  |  | ||||||
|   static const int NallocCacheMax=128;  |   static const int NallocCacheMax=128;  | ||||||
|   static const int NallocType=9; |   static const int NallocType=6; | ||||||
|   static AllocationCacheEntry Entries[NallocType][NallocCacheMax]; |   static AllocationCacheEntry Entries[NallocType][NallocCacheMax]; | ||||||
|   static int Victim[NallocType]; |   static int Victim[NallocType]; | ||||||
|   static int Ncache[NallocType]; |   static int Ncache[NallocType]; | ||||||
| @@ -113,9 +92,8 @@ private: | |||||||
|   static void *Insert(void *ptr,size_t bytes,AllocationCacheEntry *entries,int ncache,int &victim,uint64_t &cbytes) ; |   static void *Insert(void *ptr,size_t bytes,AllocationCacheEntry *entries,int ncache,int &victim,uint64_t &cbytes) ; | ||||||
|   static void *Lookup(size_t bytes,AllocationCacheEntry *entries,int ncache,uint64_t &cbytes) ; |   static void *Lookup(size_t bytes,AllocationCacheEntry *entries,int ncache,uint64_t &cbytes) ; | ||||||
|  |  | ||||||
|  public: |  | ||||||
|   static void PrintBytes(void); |   static void PrintBytes(void); | ||||||
|   static void Audit(std::string s); |  public: | ||||||
|   static void Init(void); |   static void Init(void); | ||||||
|   static void InitMessage(void); |   static void InitMessage(void); | ||||||
|   static void *AcceleratorAllocate(size_t bytes); |   static void *AcceleratorAllocate(size_t bytes); | ||||||
| @@ -135,27 +113,6 @@ private: | |||||||
|   static uint64_t     DeviceToHostBytes; |   static uint64_t     DeviceToHostBytes; | ||||||
|   static uint64_t     HostToDeviceXfer; |   static uint64_t     HostToDeviceXfer; | ||||||
|   static uint64_t     DeviceToHostXfer; |   static uint64_t     DeviceToHostXfer; | ||||||
|   static uint64_t     DeviceEvictions; |  | ||||||
|   static uint64_t     DeviceDestroy; |  | ||||||
|    |  | ||||||
|   static uint64_t     DeviceCacheBytes(); |  | ||||||
|   static uint64_t     HostCacheBytes(); |  | ||||||
|  |  | ||||||
|   static MemoryStatus GetFootprint(void) { |  | ||||||
|     MemoryStatus stat; |  | ||||||
|     stat.DeviceBytes       = DeviceBytes; |  | ||||||
|     stat.DeviceLRUBytes    = DeviceLRUBytes; |  | ||||||
|     stat.DeviceMaxBytes    = DeviceMaxBytes; |  | ||||||
|     stat.HostToDeviceBytes = HostToDeviceBytes; |  | ||||||
|     stat.DeviceToHostBytes = DeviceToHostBytes; |  | ||||||
|     stat.HostToDeviceXfer  = HostToDeviceXfer; |  | ||||||
|     stat.DeviceToHostXfer  = DeviceToHostXfer; |  | ||||||
|     stat.DeviceEvictions   = DeviceEvictions; |  | ||||||
|     stat.DeviceDestroy     = DeviceDestroy; |  | ||||||
|     stat.DeviceAllocCacheBytes = DeviceCacheBytes(); |  | ||||||
|     stat.HostAllocCacheBytes   = HostCacheBytes(); |  | ||||||
|     return stat; |  | ||||||
|   }; |  | ||||||
|   |   | ||||||
|  private: |  private: | ||||||
| #ifndef GRID_UVM | #ifndef GRID_UVM | ||||||
| @@ -213,7 +170,6 @@ private: | |||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   static void Print(void); |   static void Print(void); | ||||||
|   static void PrintAll(void); |  | ||||||
|   static void PrintState( void* CpuPtr); |   static void PrintState( void* CpuPtr); | ||||||
|   static int   isOpen   (void* CpuPtr); |   static int   isOpen   (void* CpuPtr); | ||||||
|   static void  ViewClose(void* CpuPtr,ViewMode mode); |   static void  ViewClose(void* CpuPtr,ViewMode mode); | ||||||
|   | |||||||
| @@ -3,13 +3,8 @@ | |||||||
|  |  | ||||||
| #warning "Using explicit device memory copies" | #warning "Using explicit device memory copies" | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  | //#define dprintf(...) printf ( __VA_ARGS__ ); fflush(stdout); | ||||||
| #define MAXLINE 512 | #define dprintf(...) | ||||||
| static char print_buffer [ MAXLINE ]; |  | ||||||
|  |  | ||||||
| #define mprintf(...) snprintf (print_buffer,MAXLINE, __VA_ARGS__ ); std::cout << GridLogMemory << print_buffer; |  | ||||||
| #define dprintf(...) snprintf (print_buffer,MAXLINE, __VA_ARGS__ ); std::cout << GridLogMemory << print_buffer; |  | ||||||
| //#define dprintf(...)  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////// | ||||||
| @@ -28,8 +23,6 @@ uint64_t  MemoryManager::HostToDeviceBytes; | |||||||
| uint64_t  MemoryManager::DeviceToHostBytes; | uint64_t  MemoryManager::DeviceToHostBytes; | ||||||
| uint64_t  MemoryManager::HostToDeviceXfer; | uint64_t  MemoryManager::HostToDeviceXfer; | ||||||
| uint64_t  MemoryManager::DeviceToHostXfer; | uint64_t  MemoryManager::DeviceToHostXfer; | ||||||
| uint64_t  MemoryManager::DeviceEvictions; |  | ||||||
| uint64_t  MemoryManager::DeviceDestroy; |  | ||||||
|  |  | ||||||
| //////////////////////////////////// | //////////////////////////////////// | ||||||
| // Priority ordering for unlocked entries | // Priority ordering for unlocked entries | ||||||
| @@ -111,17 +104,15 @@ void MemoryManager::AccDiscard(AcceleratorViewEntry &AccCache) | |||||||
|   /////////////////////////////////////////////////////////// |   /////////////////////////////////////////////////////////// | ||||||
|   assert(AccCache.state!=Empty); |   assert(AccCache.state!=Empty); | ||||||
|    |    | ||||||
|   mprintf("MemoryManager: Discard(%lx) %lx\n",(uint64_t)AccCache.CpuPtr,(uint64_t)AccCache.AccPtr);  |    dprintf("MemoryManager: Discard(%llx) %llx\n",(uint64_t)AccCache.CpuPtr,(uint64_t)AccCache.AccPtr);  | ||||||
|   assert(AccCache.accLock==0); |   assert(AccCache.accLock==0); | ||||||
|   assert(AccCache.cpuLock==0); |   assert(AccCache.cpuLock==0); | ||||||
|   assert(AccCache.CpuPtr!=(uint64_t)NULL); |   assert(AccCache.CpuPtr!=(uint64_t)NULL); | ||||||
|   if(AccCache.AccPtr) { |   if(AccCache.AccPtr) { | ||||||
|     AcceleratorFree((void *)AccCache.AccPtr,AccCache.bytes); |     AcceleratorFree((void *)AccCache.AccPtr,AccCache.bytes); | ||||||
|     DeviceDestroy++; |  | ||||||
|     DeviceBytes   -=AccCache.bytes; |     DeviceBytes   -=AccCache.bytes; | ||||||
|     LRUremove(AccCache); |     LRUremove(AccCache); | ||||||
|     AccCache.AccPtr=(uint64_t) NULL; |     dprintf("MemoryManager: Free(%llx) LRU %lld Total %lld\n",(uint64_t)AccCache.AccPtr,DeviceLRUBytes,DeviceBytes);   | ||||||
|     dprintf("MemoryManager: Free(%lx) LRU %ld Total %ld\n",(uint64_t)AccCache.AccPtr,DeviceLRUBytes,DeviceBytes);   |  | ||||||
|   } |   } | ||||||
|   uint64_t CpuPtr = AccCache.CpuPtr; |   uint64_t CpuPtr = AccCache.CpuPtr; | ||||||
|   EntryErase(CpuPtr); |   EntryErase(CpuPtr); | ||||||
| @@ -130,36 +121,26 @@ void MemoryManager::AccDiscard(AcceleratorViewEntry &AccCache) | |||||||
| void MemoryManager::Evict(AcceleratorViewEntry &AccCache) | void MemoryManager::Evict(AcceleratorViewEntry &AccCache) | ||||||
| { | { | ||||||
|   /////////////////////////////////////////////////////////////////////////// |   /////////////////////////////////////////////////////////////////////////// | ||||||
|   // Make CPU consistent, remove from Accelerator, remove from LRU, LEAVE CPU only entry |   // Make CPU consistent, remove from Accelerator, remove entry | ||||||
|   // Cannot be acclocked. If allocated must be in LRU pool. |   // Cannot be locked. If allocated must be in LRU pool. | ||||||
|   // |  | ||||||
|   // Nov 2022... Felix issue: Allocating two CpuPtrs, can have an entry in LRU-q with CPUlock. |  | ||||||
|   //                          and require to evict the AccPtr copy. Eviction was a mistake in CpuViewOpen |  | ||||||
|   //                          but there is a weakness where CpuLock entries are attempted for erase |  | ||||||
|   //                          Take these OUT LRU queue when CPU locked? |  | ||||||
|   //                          Cannot take out the table as cpuLock data is important. |  | ||||||
|   /////////////////////////////////////////////////////////////////////////// |   /////////////////////////////////////////////////////////////////////////// | ||||||
|   assert(AccCache.state!=Empty); |   assert(AccCache.state!=Empty); | ||||||
|    |    | ||||||
|   mprintf("MemoryManager: Evict cpu %lx acc %lx cpuLock %ld accLock %ld\n", |   dprintf("MemoryManager: Evict(%llx) %llx\n",(uint64_t)AccCache.CpuPtr,(uint64_t)AccCache.AccPtr);  | ||||||
| 	  (uint64_t)AccCache.CpuPtr,(uint64_t)AccCache.AccPtr, |   assert(AccCache.accLock==0); | ||||||
| 	  (uint64_t)AccCache.cpuLock,(uint64_t)AccCache.accLock);  |   assert(AccCache.cpuLock==0); | ||||||
|   assert(AccCache.accLock==0); // Cannot evict so logic bomb |  | ||||||
|   assert(AccCache.CpuPtr!=(uint64_t)NULL); |  | ||||||
|   if(AccCache.state==AccDirty) { |   if(AccCache.state==AccDirty) { | ||||||
|     Flush(AccCache); |     Flush(AccCache); | ||||||
|   } |   } | ||||||
|  |   assert(AccCache.CpuPtr!=(uint64_t)NULL); | ||||||
|   if(AccCache.AccPtr) { |   if(AccCache.AccPtr) { | ||||||
|     AcceleratorFree((void *)AccCache.AccPtr,AccCache.bytes); |     AcceleratorFree((void *)AccCache.AccPtr,AccCache.bytes); | ||||||
|     LRUremove(AccCache); |  | ||||||
|     AccCache.AccPtr=(uint64_t)NULL; |  | ||||||
|     AccCache.state=CpuDirty; // CPU primary now |  | ||||||
|     DeviceBytes   -=AccCache.bytes; |     DeviceBytes   -=AccCache.bytes; | ||||||
|     dprintf("MemoryManager: Free(%lx) footprint now %ld \n",(uint64_t)AccCache.AccPtr,DeviceBytes);   |     LRUremove(AccCache); | ||||||
|  |     dprintf("MemoryManager: Free(%llx) footprint now %lld \n",(uint64_t)AccCache.AccPtr,DeviceBytes);   | ||||||
|   } |   } | ||||||
|   //  uint64_t CpuPtr = AccCache.CpuPtr; |   uint64_t CpuPtr = AccCache.CpuPtr; | ||||||
|   DeviceEvictions++; |   EntryErase(CpuPtr); | ||||||
|   //  EntryErase(CpuPtr); |  | ||||||
| } | } | ||||||
| void MemoryManager::Flush(AcceleratorViewEntry &AccCache) | void MemoryManager::Flush(AcceleratorViewEntry &AccCache) | ||||||
| { | { | ||||||
| @@ -169,7 +150,7 @@ void MemoryManager::Flush(AcceleratorViewEntry &AccCache) | |||||||
|   assert(AccCache.AccPtr!=(uint64_t)NULL); |   assert(AccCache.AccPtr!=(uint64_t)NULL); | ||||||
|   assert(AccCache.CpuPtr!=(uint64_t)NULL); |   assert(AccCache.CpuPtr!=(uint64_t)NULL); | ||||||
|   acceleratorCopyFromDevice((void *)AccCache.AccPtr,(void *)AccCache.CpuPtr,AccCache.bytes); |   acceleratorCopyFromDevice((void *)AccCache.AccPtr,(void *)AccCache.CpuPtr,AccCache.bytes); | ||||||
|   mprintf("MemoryManager: Flush  %lx -> %lx\n",(uint64_t)AccCache.AccPtr,(uint64_t)AccCache.CpuPtr); fflush(stdout); |   dprintf("MemoryManager: Flush  %llx -> %llx\n",(uint64_t)AccCache.AccPtr,(uint64_t)AccCache.CpuPtr); fflush(stdout); | ||||||
|   DeviceToHostBytes+=AccCache.bytes; |   DeviceToHostBytes+=AccCache.bytes; | ||||||
|   DeviceToHostXfer++; |   DeviceToHostXfer++; | ||||||
|   AccCache.state=Consistent; |   AccCache.state=Consistent; | ||||||
| @@ -184,7 +165,7 @@ void MemoryManager::Clone(AcceleratorViewEntry &AccCache) | |||||||
|     AccCache.AccPtr=(uint64_t)AcceleratorAllocate(AccCache.bytes); |     AccCache.AccPtr=(uint64_t)AcceleratorAllocate(AccCache.bytes); | ||||||
|     DeviceBytes+=AccCache.bytes; |     DeviceBytes+=AccCache.bytes; | ||||||
|   } |   } | ||||||
|   mprintf("MemoryManager: Clone %lx <- %lx\n",(uint64_t)AccCache.AccPtr,(uint64_t)AccCache.CpuPtr); fflush(stdout); |   dprintf("MemoryManager: Clone %llx <- %llx\n",(uint64_t)AccCache.AccPtr,(uint64_t)AccCache.CpuPtr); fflush(stdout); | ||||||
|   acceleratorCopyToDevice((void *)AccCache.CpuPtr,(void *)AccCache.AccPtr,AccCache.bytes); |   acceleratorCopyToDevice((void *)AccCache.CpuPtr,(void *)AccCache.AccPtr,AccCache.bytes); | ||||||
|   HostToDeviceBytes+=AccCache.bytes; |   HostToDeviceBytes+=AccCache.bytes; | ||||||
|   HostToDeviceXfer++; |   HostToDeviceXfer++; | ||||||
| @@ -210,7 +191,6 @@ void MemoryManager::CpuDiscard(AcceleratorViewEntry &AccCache) | |||||||
| void MemoryManager::ViewClose(void* Ptr,ViewMode mode) | void MemoryManager::ViewClose(void* Ptr,ViewMode mode) | ||||||
| { | { | ||||||
|   if( (mode==AcceleratorRead)||(mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard) ){ |   if( (mode==AcceleratorRead)||(mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard) ){ | ||||||
|     dprintf("AcceleratorViewClose %lx\n",(uint64_t)Ptr); |  | ||||||
|     AcceleratorViewClose((uint64_t)Ptr); |     AcceleratorViewClose((uint64_t)Ptr); | ||||||
|   } else if( (mode==CpuRead)||(mode==CpuWrite)){ |   } else if( (mode==CpuRead)||(mode==CpuWrite)){ | ||||||
|     CpuViewClose((uint64_t)Ptr); |     CpuViewClose((uint64_t)Ptr); | ||||||
| @@ -222,7 +202,6 @@ void *MemoryManager::ViewOpen(void* _CpuPtr,size_t bytes,ViewMode mode,ViewAdvis | |||||||
| { | { | ||||||
|   uint64_t CpuPtr = (uint64_t)_CpuPtr; |   uint64_t CpuPtr = (uint64_t)_CpuPtr; | ||||||
|   if( (mode==AcceleratorRead)||(mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard) ){ |   if( (mode==AcceleratorRead)||(mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard) ){ | ||||||
|     dprintf("AcceleratorViewOpen %lx\n",(uint64_t)CpuPtr); |  | ||||||
|     return (void *) AcceleratorViewOpen(CpuPtr,bytes,mode,hint); |     return (void *) AcceleratorViewOpen(CpuPtr,bytes,mode,hint); | ||||||
|   } else if( (mode==CpuRead)||(mode==CpuWrite)){ |   } else if( (mode==CpuRead)||(mode==CpuWrite)){ | ||||||
|     return (void *)CpuViewOpen(CpuPtr,bytes,mode,hint); |     return (void *)CpuViewOpen(CpuPtr,bytes,mode,hint); | ||||||
| @@ -233,16 +212,13 @@ void *MemoryManager::ViewOpen(void* _CpuPtr,size_t bytes,ViewMode mode,ViewAdvis | |||||||
| } | } | ||||||
| void  MemoryManager::EvictVictims(uint64_t bytes) | void  MemoryManager::EvictVictims(uint64_t bytes) | ||||||
| { | { | ||||||
|   assert(bytes<DeviceMaxBytes); |  | ||||||
|   while(bytes+DeviceLRUBytes > DeviceMaxBytes){ |   while(bytes+DeviceLRUBytes > DeviceMaxBytes){ | ||||||
|     if ( DeviceLRUBytes > 0){ |     if ( DeviceLRUBytes > 0){ | ||||||
|       assert(LRU.size()>0); |       assert(LRU.size()>0); | ||||||
|       uint64_t victim = LRU.back(); // From the LRU |       uint64_t victim = LRU.back(); | ||||||
|       auto AccCacheIterator = EntryLookup(victim); |       auto AccCacheIterator = EntryLookup(victim); | ||||||
|       auto & AccCache = AccCacheIterator->second; |       auto & AccCache = AccCacheIterator->second; | ||||||
|       Evict(AccCache); |       Evict(AccCache); | ||||||
|     } else { |  | ||||||
|       return; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -265,12 +241,11 @@ uint64_t MemoryManager::AcceleratorViewOpen(uint64_t CpuPtr,size_t bytes,ViewMod | |||||||
|   assert(AccCache.cpuLock==0);  // Programming error |   assert(AccCache.cpuLock==0);  // Programming error | ||||||
|  |  | ||||||
|   if(AccCache.state!=Empty) { |   if(AccCache.state!=Empty) { | ||||||
|     dprintf("ViewOpen found entry %lx %lx : %ld %ld accLock %ld\n", |     dprintf("ViewOpen found entry %llx %llx : %lld %lld\n", | ||||||
| 		    (uint64_t)AccCache.CpuPtr, | 		    (uint64_t)AccCache.CpuPtr, | ||||||
| 		    (uint64_t)CpuPtr, | 		    (uint64_t)CpuPtr, | ||||||
| 		    (uint64_t)AccCache.bytes, | 		    (uint64_t)AccCache.bytes, | ||||||
| 	            (uint64_t)bytes, | 		    (uint64_t)bytes); | ||||||
| 		    (uint64_t)AccCache.accLock); |  | ||||||
|     assert(AccCache.CpuPtr == CpuPtr); |     assert(AccCache.CpuPtr == CpuPtr); | ||||||
|     assert(AccCache.bytes  ==bytes); |     assert(AccCache.bytes  ==bytes); | ||||||
|   } |   } | ||||||
| @@ -305,7 +280,6 @@ uint64_t MemoryManager::AcceleratorViewOpen(uint64_t CpuPtr,size_t bytes,ViewMod | |||||||
|       AccCache.state  = Consistent; // Empty + AccRead => Consistent |       AccCache.state  = Consistent; // Empty + AccRead => Consistent | ||||||
|     } |     } | ||||||
|     AccCache.accLock= 1; |     AccCache.accLock= 1; | ||||||
|     dprintf("Copied Empty entry into device accLock= %d\n",AccCache.accLock); |  | ||||||
|   } else if(AccCache.state==CpuDirty ){ |   } else if(AccCache.state==CpuDirty ){ | ||||||
|     if(mode==AcceleratorWriteDiscard) { |     if(mode==AcceleratorWriteDiscard) { | ||||||
|       CpuDiscard(AccCache); |       CpuDiscard(AccCache); | ||||||
| @@ -318,30 +292,28 @@ uint64_t MemoryManager::AcceleratorViewOpen(uint64_t CpuPtr,size_t bytes,ViewMod | |||||||
|       AccCache.state  = Consistent; // CpuDirty + AccRead => Consistent |       AccCache.state  = Consistent; // CpuDirty + AccRead => Consistent | ||||||
|     } |     } | ||||||
|     AccCache.accLock++; |     AccCache.accLock++; | ||||||
|     dprintf("CpuDirty entry into device ++accLock= %d\n",AccCache.accLock); |     dprintf("Copied CpuDirty entry into device accLock %d\n",AccCache.accLock); | ||||||
|   } else if(AccCache.state==Consistent) { |   } else if(AccCache.state==Consistent) { | ||||||
|     if((mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard)) |     if((mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard)) | ||||||
|       AccCache.state  = AccDirty;   // Consistent + AcceleratorWrite=> AccDirty |       AccCache.state  = AccDirty;   // Consistent + AcceleratorWrite=> AccDirty | ||||||
|     else |     else | ||||||
|       AccCache.state  = Consistent; // Consistent + AccRead => Consistent |       AccCache.state  = Consistent; // Consistent + AccRead => Consistent | ||||||
|     AccCache.accLock++; |     AccCache.accLock++; | ||||||
|     dprintf("Consistent entry into device ++accLock= %d\n",AccCache.accLock); |     dprintf("Consistent entry into device accLock %d\n",AccCache.accLock); | ||||||
|   } else if(AccCache.state==AccDirty) { |   } else if(AccCache.state==AccDirty) { | ||||||
|     if((mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard)) |     if((mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard)) | ||||||
|       AccCache.state  = AccDirty; // AccDirty + AcceleratorWrite=> AccDirty |       AccCache.state  = AccDirty; // AccDirty + AcceleratorWrite=> AccDirty | ||||||
|     else |     else | ||||||
|       AccCache.state  = AccDirty; // AccDirty + AccRead => AccDirty |       AccCache.state  = AccDirty; // AccDirty + AccRead => AccDirty | ||||||
|     AccCache.accLock++; |     AccCache.accLock++; | ||||||
|     dprintf("AccDirty entry ++accLock= %d\n",AccCache.accLock); |     dprintf("AccDirty entry into device accLock %d\n",AccCache.accLock); | ||||||
|   } else { |   } else { | ||||||
|     assert(0); |     assert(0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   assert(AccCache.accLock>0); |   // If view is opened on device remove from LRU | ||||||
|   // If view is opened on device must remove from LRU |  | ||||||
|   if(AccCache.LRU_valid==1){ |   if(AccCache.LRU_valid==1){ | ||||||
|     // must possibly remove from LRU as now locked on GPU |     // must possibly remove from LRU as now locked on GPU | ||||||
|     dprintf("AccCache entry removed from LRU \n"); |  | ||||||
|     LRUremove(AccCache); |     LRUremove(AccCache); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -362,12 +334,10 @@ void MemoryManager::AcceleratorViewClose(uint64_t CpuPtr) | |||||||
|   assert(AccCache.accLock>0); |   assert(AccCache.accLock>0); | ||||||
|  |  | ||||||
|   AccCache.accLock--; |   AccCache.accLock--; | ||||||
|  |  | ||||||
|   // Move to LRU queue if not locked and close on device |   // Move to LRU queue if not locked and close on device | ||||||
|   if(AccCache.accLock==0) { |   if(AccCache.accLock==0) { | ||||||
|     dprintf("AccleratorViewClose %lx AccLock decremented to %ld move to LRU queue\n",(uint64_t)CpuPtr,(uint64_t)AccCache.accLock); |  | ||||||
|     LRUinsert(AccCache); |     LRUinsert(AccCache); | ||||||
|   } else { |  | ||||||
|     dprintf("AccleratorViewClose %lx AccLock decremented to %ld\n",(uint64_t)CpuPtr,(uint64_t)AccCache.accLock); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
| void MemoryManager::CpuViewClose(uint64_t CpuPtr) | void MemoryManager::CpuViewClose(uint64_t CpuPtr) | ||||||
| @@ -404,10 +374,9 @@ uint64_t MemoryManager::CpuViewOpen(uint64_t CpuPtr,size_t bytes,ViewMode mode,V | |||||||
|   auto AccCacheIterator = EntryLookup(CpuPtr); |   auto AccCacheIterator = EntryLookup(CpuPtr); | ||||||
|   auto & AccCache = AccCacheIterator->second; |   auto & AccCache = AccCacheIterator->second; | ||||||
|  |  | ||||||
|   // CPU doesn't need to free space |   if (!AccCache.AccPtr) { | ||||||
|   //  if (!AccCache.AccPtr) { |      EvictVictims(bytes); | ||||||
|   //    EvictVictims(bytes); |   } | ||||||
|   //  } |  | ||||||
|  |  | ||||||
|   assert((mode==CpuRead)||(mode==CpuWrite)); |   assert((mode==CpuRead)||(mode==CpuWrite)); | ||||||
|   assert(AccCache.accLock==0);  // Programming error |   assert(AccCache.accLock==0);  // Programming error | ||||||
| @@ -461,28 +430,20 @@ void  MemoryManager::NotifyDeletion(void *_ptr) | |||||||
| void  MemoryManager::Print(void) | void  MemoryManager::Print(void) | ||||||
| { | { | ||||||
|   PrintBytes(); |   PrintBytes(); | ||||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; |   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||||
|   std::cout << GridLogMessage << "Memory Manager                             " << std::endl; |   std::cout << GridLogDebug << "Memory Manager                             " << std::endl; | ||||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; |   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||||
|   std::cout << GridLogMessage << DeviceBytes   << " bytes allocated on device " << std::endl; |   std::cout << GridLogDebug << DeviceBytes   << " bytes allocated on device " << std::endl; | ||||||
|   std::cout << GridLogMessage << DeviceLRUBytes<< " bytes evictable on device " << std::endl; |   std::cout << GridLogDebug << DeviceLRUBytes<< " bytes evictable on device " << std::endl; | ||||||
|   std::cout << GridLogMessage << DeviceMaxBytes<< " bytes max on device       " << std::endl; |   std::cout << GridLogDebug << DeviceMaxBytes<< " bytes max on device       " << std::endl; | ||||||
|   std::cout << GridLogMessage << HostToDeviceXfer << " transfers        to   device " << std::endl; |   std::cout << GridLogDebug << HostToDeviceXfer << " transfers        to   device " << std::endl; | ||||||
|   std::cout << GridLogMessage << DeviceToHostXfer << " transfers        from device " << std::endl; |   std::cout << GridLogDebug << DeviceToHostXfer << " transfers        from device " << std::endl; | ||||||
|   std::cout << GridLogMessage << HostToDeviceBytes<< " bytes transfered to   device " << std::endl; |   std::cout << GridLogDebug << HostToDeviceBytes<< " bytes transfered to   device " << std::endl; | ||||||
|   std::cout << GridLogMessage << DeviceToHostBytes<< " bytes transfered from device " << std::endl; |   std::cout << GridLogDebug << DeviceToHostBytes<< " bytes transfered from device " << std::endl; | ||||||
|   std::cout << GridLogMessage << DeviceEvictions  << " Evictions from device " << std::endl; |   std::cout << GridLogDebug << AccViewTable.size()<< " vectors " << LRU.size()<<" evictable"<< std::endl; | ||||||
|   std::cout << GridLogMessage << DeviceDestroy    << " Destroyed vectors on device " << std::endl; |   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||||
|   std::cout << GridLogMessage << AccViewTable.size()<< " vectors " << LRU.size()<<" evictable"<< std::endl; |   std::cout << GridLogDebug << "CpuAddr\t\tAccAddr\t\tState\t\tcpuLock\taccLock\tLRU_valid "<<std::endl; | ||||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; |   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||||
| } |  | ||||||
| void  MemoryManager::PrintAll(void) |  | ||||||
| { |  | ||||||
|   Print(); |  | ||||||
|   std::cout << GridLogMessage << std::endl; |  | ||||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; |  | ||||||
|   std::cout << GridLogMessage << "CpuAddr\t\tAccAddr\t\tState\t\tcpuLock\taccLock\tLRU_valid "<<std::endl; |  | ||||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; |  | ||||||
|   for(auto it=AccViewTable.begin();it!=AccViewTable.end();it++){ |   for(auto it=AccViewTable.begin();it!=AccViewTable.end();it++){ | ||||||
|     auto &AccCache = it->second; |     auto &AccCache = it->second; | ||||||
|      |      | ||||||
| @@ -492,13 +453,13 @@ void  MemoryManager::PrintAll(void) | |||||||
|     if ( AccCache.state==AccDirty ) str = std::string("AccDirty"); |     if ( AccCache.state==AccDirty ) str = std::string("AccDirty"); | ||||||
|     if ( AccCache.state==Consistent)str = std::string("Consistent"); |     if ( AccCache.state==Consistent)str = std::string("Consistent"); | ||||||
|  |  | ||||||
|     std::cout << GridLogMessage << "0x"<<std::hex<<AccCache.CpuPtr<<std::dec |     std::cout << GridLogDebug << "0x"<<std::hex<<AccCache.CpuPtr<<std::dec | ||||||
| 	      << "\t0x"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str | 	      << "\t0x"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str | ||||||
| 	      << "\t" << AccCache.cpuLock | 	      << "\t" << AccCache.cpuLock | ||||||
| 	      << "\t" << AccCache.accLock | 	      << "\t" << AccCache.accLock | ||||||
| 	      << "\t" << AccCache.LRU_valid<<std::endl; | 	      << "\t" << AccCache.LRU_valid<<std::endl; | ||||||
|   } |   } | ||||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; |   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||||
|  |  | ||||||
| }; | }; | ||||||
| int   MemoryManager::isOpen   (void* _CpuPtr)  | int   MemoryManager::isOpen   (void* _CpuPtr)  | ||||||
| @@ -512,61 +473,6 @@ int   MemoryManager::isOpen   (void* _CpuPtr) | |||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| void MemoryManager::Audit(std::string s) |  | ||||||
| { |  | ||||||
|   uint64_t CpuBytes=0; |  | ||||||
|   uint64_t AccBytes=0; |  | ||||||
|   uint64_t LruBytes1=0; |  | ||||||
|   uint64_t LruBytes2=0; |  | ||||||
|   uint64_t LruCnt=0; |  | ||||||
|   uint64_t LockedBytes=0; |  | ||||||
|    |  | ||||||
|   std::cout << " Memory Manager::Audit() from "<<s<<std::endl; |  | ||||||
|   for(auto it=LRU.begin();it!=LRU.end();it++){ |  | ||||||
|     uint64_t cpuPtr = *it; |  | ||||||
|     assert(EntryPresent(cpuPtr)); |  | ||||||
|     auto AccCacheIterator = EntryLookup(cpuPtr); |  | ||||||
|     auto & AccCache = AccCacheIterator->second; |  | ||||||
|     LruBytes2+=AccCache.bytes; |  | ||||||
|     assert(AccCache.LRU_valid==1); |  | ||||||
|     assert(AccCache.LRU_entry==it); |  | ||||||
|   } |  | ||||||
|   std::cout << " Memory Manager::Audit() LRU queue matches table entries "<<std::endl; |  | ||||||
|   for(auto it=AccViewTable.begin();it!=AccViewTable.end();it++){ |  | ||||||
|     auto &AccCache = it->second; |  | ||||||
|      |  | ||||||
|     std::string str; |  | ||||||
|     if ( AccCache.state==Empty    ) str = std::string("Empty"); |  | ||||||
|     if ( AccCache.state==CpuDirty ) str = std::string("CpuDirty"); |  | ||||||
|     if ( AccCache.state==AccDirty ) str = std::string("AccDirty"); |  | ||||||
|     if ( AccCache.state==Consistent)str = std::string("Consistent"); |  | ||||||
|  |  | ||||||
|     CpuBytes+=AccCache.bytes; |  | ||||||
|     if( AccCache.AccPtr )    AccBytes+=AccCache.bytes; |  | ||||||
|     if( AccCache.LRU_valid ) LruBytes1+=AccCache.bytes; |  | ||||||
|     if( AccCache.LRU_valid ) LruCnt++; |  | ||||||
|      |  | ||||||
|     if ( AccCache.cpuLock || AccCache.accLock ) { |  | ||||||
|       assert(AccCache.LRU_valid==0); |  | ||||||
|       std::cout << GridLogError << s<< "\n\t 0x"<<std::hex<<AccCache.CpuPtr<<std::dec |  | ||||||
| 		<< "\t0x"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str |  | ||||||
| 		<< "\t cpuLock  " << AccCache.cpuLock |  | ||||||
| 		<< "\t accLock  " << AccCache.accLock |  | ||||||
| 		<< "\t LRUvalid " << AccCache.LRU_valid<<std::endl; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     assert( AccCache.cpuLock== 0 ) ; |  | ||||||
|     assert( AccCache.accLock== 0 ) ; |  | ||||||
|   } |  | ||||||
|   std::cout << " Memory Manager::Audit() no locked table entries "<<std::endl; |  | ||||||
|   assert(LruBytes1==LruBytes2); |  | ||||||
|   assert(LruBytes1==DeviceLRUBytes); |  | ||||||
|   std::cout << " Memory Manager::Audit() evictable bytes matches sum over table "<<std::endl; |  | ||||||
|   assert(AccBytes==DeviceBytes); |  | ||||||
|   std::cout << " Memory Manager::Audit() device bytes matches sum over table "<<std::endl; |  | ||||||
|   assert(LruCnt == LRU.size()); |  | ||||||
|   std::cout << " Memory Manager::Audit() LRU entry count matches "<<std::endl; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void MemoryManager::PrintState(void* _CpuPtr) | void MemoryManager::PrintState(void* _CpuPtr) | ||||||
| { | { | ||||||
| @@ -583,8 +489,8 @@ void MemoryManager::PrintState(void* _CpuPtr) | |||||||
|     if ( AccCache.state==EvictNext) str = std::string("EvictNext"); |     if ( AccCache.state==EvictNext) str = std::string("EvictNext"); | ||||||
|  |  | ||||||
|     std::cout << GridLogMessage << "CpuAddr\t\tAccAddr\t\tState\t\tcpuLock\taccLock\tLRU_valid "<<std::endl; |     std::cout << GridLogMessage << "CpuAddr\t\tAccAddr\t\tState\t\tcpuLock\taccLock\tLRU_valid "<<std::endl; | ||||||
|     std::cout << GridLogMessage << "\tx"<<std::hex<<AccCache.CpuPtr<<std::dec |     std::cout << GridLogMessage << "0x"<<std::hex<<AccCache.CpuPtr<<std::dec | ||||||
|     << "\tx"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str |     << "\t0x"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str | ||||||
|     << "\t" << AccCache.cpuLock |     << "\t" << AccCache.cpuLock | ||||||
|     << "\t" << AccCache.accLock |     << "\t" << AccCache.accLock | ||||||
|     << "\t" << AccCache.LRU_valid<<std::endl; |     << "\t" << AccCache.LRU_valid<<std::endl; | ||||||
|   | |||||||
| @@ -12,10 +12,7 @@ uint64_t  MemoryManager::HostToDeviceBytes; | |||||||
| uint64_t  MemoryManager::DeviceToHostBytes; | uint64_t  MemoryManager::DeviceToHostBytes; | ||||||
| uint64_t  MemoryManager::HostToDeviceXfer; | uint64_t  MemoryManager::HostToDeviceXfer; | ||||||
| uint64_t  MemoryManager::DeviceToHostXfer; | uint64_t  MemoryManager::DeviceToHostXfer; | ||||||
| uint64_t  MemoryManager::DeviceEvictions; |  | ||||||
| uint64_t  MemoryManager::DeviceDestroy; |  | ||||||
|  |  | ||||||
| void  MemoryManager::Audit(std::string s){}; |  | ||||||
| void  MemoryManager::ViewClose(void* AccPtr,ViewMode mode){}; | void  MemoryManager::ViewClose(void* AccPtr,ViewMode mode){}; | ||||||
| void *MemoryManager::ViewOpen(void* CpuPtr,size_t bytes,ViewMode mode,ViewAdvise hint){ return CpuPtr; }; | void *MemoryManager::ViewOpen(void* CpuPtr,size_t bytes,ViewMode mode,ViewAdvise hint){ return CpuPtr; }; | ||||||
| int   MemoryManager::isOpen   (void* CpuPtr) { return 0;} | int   MemoryManager::isOpen   (void* CpuPtr) { return 0;} | ||||||
| @@ -24,7 +21,6 @@ void  MemoryManager::PrintState(void* CpuPtr) | |||||||
| std::cout << GridLogMessage << "Host<->Device memory movement not currently managed by Grid." << std::endl; | std::cout << GridLogMessage << "Host<->Device memory movement not currently managed by Grid." << std::endl; | ||||||
| }; | }; | ||||||
| void  MemoryManager::Print(void){}; | void  MemoryManager::Print(void){}; | ||||||
| void  MemoryManager::PrintAll(void){}; |  | ||||||
| void  MemoryManager::NotifyDeletion(void *ptr){}; | void  MemoryManager::NotifyDeletion(void *ptr){}; | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|   | |||||||
| @@ -392,15 +392,17 @@ double CartesianCommunicator::StencilSendToRecvFromBegin(std::vector<CommsReques | |||||||
|     acceleratorCopyDeviceToDeviceAsynch(xmit,shm,bytes); |     acceleratorCopyDeviceToDeviceAsynch(xmit,shm,bytes); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   //  if ( CommunicatorPolicy == CommunicatorPolicySequential ) { |   if ( CommunicatorPolicy == CommunicatorPolicySequential ) { | ||||||
|   //    this->StencilSendToRecvFromComplete(list,dir); |     this->StencilSendToRecvFromComplete(list,dir); | ||||||
|   //  } |   } | ||||||
|  |  | ||||||
|   return off_node_bytes; |   return off_node_bytes; | ||||||
| } | } | ||||||
| void CartesianCommunicator::StencilSendToRecvFromComplete(std::vector<CommsRequest_t> &list,int dir) | void CartesianCommunicator::StencilSendToRecvFromComplete(std::vector<CommsRequest_t> &list,int dir) | ||||||
| { | { | ||||||
|   //   std::cout << "Copy Synchronised\n"<<std::endl; |   //   std::cout << "Copy Synchronised\n"<<std::endl; | ||||||
|  |   acceleratorCopySynchronise(); | ||||||
|  |  | ||||||
|   int nreq=list.size(); |   int nreq=list.size(); | ||||||
|  |  | ||||||
|   if (nreq==0) return; |   if (nreq==0) return; | ||||||
|   | |||||||
| @@ -36,10 +36,9 @@ Author: Christoph Lehner <christoph@lhnr.de> | |||||||
| #ifdef GRID_HIP | #ifdef GRID_HIP | ||||||
| #include <hip/hip_runtime_api.h> | #include <hip/hip_runtime_api.h> | ||||||
| #endif | #endif | ||||||
| #ifdef GRID_SYCL | #ifdef GRID_SYCl | ||||||
| #define GRID_SYCL_LEVEL_ZERO_IPC |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid);  | NAMESPACE_BEGIN(Grid);  | ||||||
| #define header "SharedMemoryMpi: " | #define header "SharedMemoryMpi: " | ||||||
|   | |||||||
| @@ -297,30 +297,6 @@ template<class vobj> void Scatter_plane_merge(Lattice<vobj> &rhs,ExtractPointerA | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| #if (defined(GRID_CUDA) || defined(GRID_HIP)) && defined(ACCELERATOR_CSHIFT) |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| T iDivUp(T a, T b) // Round a / b to nearest higher integer value |  | ||||||
| { return (a % b != 0) ? (a / b + 1) : (a / b); } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| __global__ void populate_Cshift_table(T* vector, T lo, T ro, T e1, T e2, T stride) |  | ||||||
| { |  | ||||||
|     int idx = blockIdx.x*blockDim.x + threadIdx.x; |  | ||||||
|     if (idx >= e1*e2) return; |  | ||||||
|  |  | ||||||
|     int n, b, o; |  | ||||||
|  |  | ||||||
|     n = idx / e2; |  | ||||||
|     b = idx % e2; |  | ||||||
|     o = n*stride + b; |  | ||||||
|  |  | ||||||
|     vector[2*idx + 0] = lo + o; |  | ||||||
|     vector[2*idx + 1] = ro + o; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| ////////////////////////////////////////////////////// | ////////////////////////////////////////////////////// | ||||||
| // local to node block strided copies | // local to node block strided copies | ||||||
| ////////////////////////////////////////////////////// | ////////////////////////////////////////////////////// | ||||||
| @@ -345,20 +321,12 @@ template<class vobj> void Copy_plane(Lattice<vobj>& lhs,const Lattice<vobj> &rhs | |||||||
|   int ent=0; |   int ent=0; | ||||||
|  |  | ||||||
|   if(cbmask == 0x3 ){ |   if(cbmask == 0x3 ){ | ||||||
| #if (defined(GRID_CUDA) || defined(GRID_HIP)) && defined(ACCELERATOR_CSHIFT) |  | ||||||
|     ent = e1*e2; |  | ||||||
|     dim3 blockSize(acceleratorThreads()); |  | ||||||
|     dim3 gridSize(iDivUp((unsigned int)ent, blockSize.x)); |  | ||||||
|     populate_Cshift_table<<<gridSize, blockSize>>>(&Cshift_table[0].first, lo, ro, e1, e2, stride); |  | ||||||
|     accelerator_barrier(); |  | ||||||
| #else |  | ||||||
|     for(int n=0;n<e1;n++){ |     for(int n=0;n<e1;n++){ | ||||||
|       for(int b=0;b<e2;b++){ |       for(int b=0;b<e2;b++){ | ||||||
|         int o =n*stride+b; |         int o =n*stride+b; | ||||||
| 	Cshift_table[ent++] = std::pair<int,int>(lo+o,ro+o); | 	Cshift_table[ent++] = std::pair<int,int>(lo+o,ro+o); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| #endif |  | ||||||
|   } else {  |   } else {  | ||||||
|     for(int n=0;n<e1;n++){ |     for(int n=0;n<e1;n++){ | ||||||
|       for(int b=0;b<e2;b++){ |       for(int b=0;b<e2;b++){ | ||||||
| @@ -409,19 +377,11 @@ template<class vobj> void Copy_plane_permute(Lattice<vobj>& lhs,const Lattice<vo | |||||||
|   int ent=0; |   int ent=0; | ||||||
|  |  | ||||||
|   if ( cbmask == 0x3 ) { |   if ( cbmask == 0x3 ) { | ||||||
| #if (defined(GRID_CUDA) || defined(GRID_HIP)) && defined(ACCELERATOR_CSHIFT) |  | ||||||
|     ent = e1*e2; |  | ||||||
|     dim3 blockSize(acceleratorThreads()); |  | ||||||
|     dim3 gridSize(iDivUp((unsigned int)ent, blockSize.x)); |  | ||||||
|     populate_Cshift_table<<<gridSize, blockSize>>>(&Cshift_table[0].first, lo, ro, e1, e2, stride); |  | ||||||
|     accelerator_barrier(); |  | ||||||
| #else |  | ||||||
|     for(int n=0;n<e1;n++){ |     for(int n=0;n<e1;n++){ | ||||||
|     for(int b=0;b<e2;b++){ |     for(int b=0;b<e2;b++){ | ||||||
|       int o  =n*stride; |       int o  =n*stride; | ||||||
|       Cshift_table[ent++] = std::pair<int,int>(lo+o+b,ro+o+b); |       Cshift_table[ent++] = std::pair<int,int>(lo+o+b,ro+o+b); | ||||||
|     }} |     }} | ||||||
| #endif |  | ||||||
|   } else { |   } else { | ||||||
|     for(int n=0;n<e1;n++){ |     for(int n=0;n<e1;n++){ | ||||||
|     for(int b=0;b<e2;b++){ |     for(int b=0;b<e2;b++){ | ||||||
|   | |||||||
							
								
								
									
										23405
									
								
								Grid/json/json.hpp
									
									
									
									
									
								
							
							
						
						
									
										23405
									
								
								Grid/json/json.hpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -288,8 +288,8 @@ public: | |||||||
|     typename std::enable_if<!std::is_same<robj,vobj>::value,int>::type i=0; |     typename std::enable_if<!std::is_same<robj,vobj>::value,int>::type i=0; | ||||||
|     conformable(*this,r); |     conformable(*this,r); | ||||||
|     this->checkerboard = r.Checkerboard(); |     this->checkerboard = r.Checkerboard(); | ||||||
|     auto him= r.View(AcceleratorRead); |  | ||||||
|     auto me =   View(AcceleratorWriteDiscard); |     auto me =   View(AcceleratorWriteDiscard); | ||||||
|  |     auto him= r.View(AcceleratorRead); | ||||||
|     accelerator_for(ss,me.size(),vobj::Nsimd(),{ |     accelerator_for(ss,me.size(),vobj::Nsimd(),{ | ||||||
|       coalescedWrite(me[ss],him(ss)); |       coalescedWrite(me[ss],him(ss)); | ||||||
|     }); |     }); | ||||||
| @@ -303,8 +303,8 @@ public: | |||||||
|   inline Lattice<vobj> & operator = (const Lattice<vobj> & r){ |   inline Lattice<vobj> & operator = (const Lattice<vobj> & r){ | ||||||
|     this->checkerboard = r.Checkerboard(); |     this->checkerboard = r.Checkerboard(); | ||||||
|     conformable(*this,r); |     conformable(*this,r); | ||||||
|     auto him= r.View(AcceleratorRead); |  | ||||||
|     auto me =   View(AcceleratorWriteDiscard); |     auto me =   View(AcceleratorWriteDiscard); | ||||||
|  |     auto him= r.View(AcceleratorRead); | ||||||
|     accelerator_for(ss,me.size(),vobj::Nsimd(),{ |     accelerator_for(ss,me.size(),vobj::Nsimd(),{ | ||||||
|       coalescedWrite(me[ss],him(ss)); |       coalescedWrite(me[ss],him(ss)); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -29,19 +29,6 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | |||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| template<class vobj> void DumpSliceNorm(std::string s,Lattice<vobj> &f,int mu=-1) |  | ||||||
| { |  | ||||||
|   auto ff = localNorm2(f); |  | ||||||
|   if ( mu==-1 ) mu = f.Grid()->Nd()-1; |  | ||||||
|   typedef typename vobj::tensor_reduced normtype; |  | ||||||
|   typedef typename normtype::scalar_object scalar; |  | ||||||
|   std::vector<scalar> sff; |  | ||||||
|   sliceSum(ff,sff,mu); |  | ||||||
|   for(int t=0;t<sff.size();t++){ |  | ||||||
|     std::cout << s<<" "<<t<<" "<<sff[t]<<std::endl; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template<class vobj> uint32_t crc(Lattice<vobj> & buf) | template<class vobj> uint32_t crc(Lattice<vobj> & buf) | ||||||
| { | { | ||||||
|   autoView( buf_v , buf, CpuRead); |   autoView( buf_v , buf, CpuRead); | ||||||
|   | |||||||
| @@ -28,9 +28,6 @@ Author: Christoph Lehner <christoph@lhnr.de> | |||||||
| #if defined(GRID_CUDA)||defined(GRID_HIP) | #if defined(GRID_CUDA)||defined(GRID_HIP) | ||||||
| #include <Grid/lattice/Lattice_reduction_gpu.h> | #include <Grid/lattice/Lattice_reduction_gpu.h> | ||||||
| #endif | #endif | ||||||
| #if defined(GRID_SYCL) |  | ||||||
| #include <Grid/lattice/Lattice_reduction_sycl.h> |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| @@ -130,7 +127,7 @@ inline Double max(const Double *arg, Integer osites) | |||||||
| template<class vobj> | template<class vobj> | ||||||
| inline typename vobj::scalar_object sum(const vobj *arg, Integer osites) | inline typename vobj::scalar_object sum(const vobj *arg, Integer osites) | ||||||
| { | { | ||||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) | #if defined(GRID_CUDA)||defined(GRID_HIP) | ||||||
|   return sum_gpu(arg,osites); |   return sum_gpu(arg,osites); | ||||||
| #else | #else | ||||||
|   return sum_cpu(arg,osites); |   return sum_cpu(arg,osites); | ||||||
| @@ -139,61 +136,25 @@ inline typename vobj::scalar_object sum(const vobj *arg, Integer osites) | |||||||
| template<class vobj> | template<class vobj> | ||||||
| inline typename vobj::scalar_objectD sumD(const vobj *arg, Integer osites) | inline typename vobj::scalar_objectD sumD(const vobj *arg, Integer osites) | ||||||
| { | { | ||||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) | #if defined(GRID_CUDA)||defined(GRID_HIP) | ||||||
|   return sumD_gpu(arg,osites); |   return sumD_gpu(arg,osites); | ||||||
| #else | #else | ||||||
|   return sumD_cpu(arg,osites); |   return sumD_cpu(arg,osites); | ||||||
| #endif   | #endif   | ||||||
| } | } | ||||||
| template<class vobj> |  | ||||||
| inline typename vobj::scalar_objectD sumD_large(const vobj *arg, Integer osites) |  | ||||||
| { |  | ||||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) |  | ||||||
|   return sumD_gpu_large(arg,osites); |  | ||||||
| #else |  | ||||||
|   return sumD_cpu(arg,osites); |  | ||||||
| #endif   |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template<class vobj> |  | ||||||
| inline typename vobj::scalar_object rankSum(const Lattice<vobj> &arg) |  | ||||||
| { |  | ||||||
|   Integer osites = arg.Grid()->oSites(); |  | ||||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) |  | ||||||
|   autoView( arg_v, arg, AcceleratorRead); |  | ||||||
|   return sum_gpu(&arg_v[0],osites); |  | ||||||
| #else |  | ||||||
|   autoView(arg_v, arg, CpuRead); |  | ||||||
|   return sum_cpu(&arg_v[0],osites); |  | ||||||
| #endif   |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template<class vobj> | template<class vobj> | ||||||
| inline typename vobj::scalar_object sum(const Lattice<vobj> &arg) | inline typename vobj::scalar_object sum(const Lattice<vobj> &arg) | ||||||
| { | { | ||||||
|   auto ssum = rankSum(arg); | #if defined(GRID_CUDA)||defined(GRID_HIP) | ||||||
|   arg.Grid()->GlobalSum(ssum); |  | ||||||
|   return ssum; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template<class vobj> |  | ||||||
| inline typename vobj::scalar_object rankSumLarge(const Lattice<vobj> &arg) |  | ||||||
| { |  | ||||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) |  | ||||||
|   autoView( arg_v, arg, AcceleratorRead); |   autoView( arg_v, arg, AcceleratorRead); | ||||||
|   Integer osites = arg.Grid()->oSites(); |   Integer osites = arg.Grid()->oSites(); | ||||||
|   return sum_gpu_large(&arg_v[0],osites); |   auto ssum= sum_gpu(&arg_v[0],osites); | ||||||
| #else | #else | ||||||
|   autoView(arg_v, arg, CpuRead); |   autoView(arg_v, arg, CpuRead); | ||||||
|   Integer osites = arg.Grid()->oSites(); |   Integer osites = arg.Grid()->oSites(); | ||||||
|   return sum_cpu(&arg_v[0],osites); |   auto ssum= sum_cpu(&arg_v[0],osites); | ||||||
| #endif   | #endif   | ||||||
| } |  | ||||||
|  |  | ||||||
| template<class vobj> |  | ||||||
| inline typename vobj::scalar_object sum_large(const Lattice<vobj> &arg) |  | ||||||
| { |  | ||||||
|   auto ssum = rankSumLarge(arg); |  | ||||||
|   arg.Grid()->GlobalSum(ssum); |   arg.Grid()->GlobalSum(ssum); | ||||||
|   return ssum; |   return ssum; | ||||||
| } | } | ||||||
| @@ -249,10 +210,11 @@ inline ComplexD rankInnerProduct(const Lattice<vobj> &left,const Lattice<vobj> & | |||||||
|   typedef decltype(innerProductD(vobj(),vobj())) inner_t; |   typedef decltype(innerProductD(vobj(),vobj())) inner_t; | ||||||
|   Vector<inner_t> inner_tmp(sites); |   Vector<inner_t> inner_tmp(sites); | ||||||
|   auto inner_tmp_v = &inner_tmp[0]; |   auto inner_tmp_v = &inner_tmp[0]; | ||||||
|  |      | ||||||
|   { |   { | ||||||
|     autoView( left_v , left, AcceleratorRead); |     autoView( left_v , left, AcceleratorRead); | ||||||
|     autoView( right_v,right, AcceleratorRead); |     autoView( right_v,right, AcceleratorRead); | ||||||
|     // This code could read coalesce |  | ||||||
|     // GPU - SIMT lane compliance... |     // GPU - SIMT lane compliance... | ||||||
|     accelerator_for( ss, sites, 1,{ |     accelerator_for( ss, sites, 1,{ | ||||||
| 	auto x_l = left_v[ss]; | 	auto x_l = left_v[ss]; | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ unsigned int nextPow2(Iterator x) { | |||||||
| } | } | ||||||
|  |  | ||||||
| template <class Iterator> | template <class Iterator> | ||||||
| int getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator &threads, Iterator &blocks) { | void getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator &threads, Iterator &blocks) { | ||||||
|    |    | ||||||
|   int device; |   int device; | ||||||
| #ifdef GRID_CUDA | #ifdef GRID_CUDA | ||||||
| @@ -37,13 +37,13 @@ int getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator & | |||||||
|   Iterator sharedMemPerBlock   = gpu_props[device].sharedMemPerBlock; |   Iterator sharedMemPerBlock   = gpu_props[device].sharedMemPerBlock; | ||||||
|   Iterator maxThreadsPerBlock  = gpu_props[device].maxThreadsPerBlock; |   Iterator maxThreadsPerBlock  = gpu_props[device].maxThreadsPerBlock; | ||||||
|   Iterator multiProcessorCount = gpu_props[device].multiProcessorCount; |   Iterator multiProcessorCount = gpu_props[device].multiProcessorCount; | ||||||
|   /*   |    | ||||||
|   std::cout << GridLogDebug << "GPU has:" << std::endl; |   std::cout << GridLogDebug << "GPU has:" << std::endl; | ||||||
|   std::cout << GridLogDebug << "\twarpSize            = " << warpSize << std::endl; |   std::cout << GridLogDebug << "\twarpSize            = " << warpSize << std::endl; | ||||||
|   std::cout << GridLogDebug << "\tsharedMemPerBlock   = " << sharedMemPerBlock << std::endl; |   std::cout << GridLogDebug << "\tsharedMemPerBlock   = " << sharedMemPerBlock << std::endl; | ||||||
|   std::cout << GridLogDebug << "\tmaxThreadsPerBlock  = " << maxThreadsPerBlock << std::endl; |   std::cout << GridLogDebug << "\tmaxThreadsPerBlock  = " << maxThreadsPerBlock << std::endl; | ||||||
|   std::cout << GridLogDebug << "\tmultiProcessorCount = " << multiProcessorCount << std::endl; |   std::cout << GridLogDebug << "\tmultiProcessorCount = " << multiProcessorCount << std::endl; | ||||||
|   */   |    | ||||||
|   if (warpSize != WARP_SIZE) { |   if (warpSize != WARP_SIZE) { | ||||||
|     std::cout << GridLogError << "The warp size of the GPU in use does not match the warp size set when compiling Grid." << std::endl; |     std::cout << GridLogError << "The warp size of the GPU in use does not match the warp size set when compiling Grid." << std::endl; | ||||||
|     exit(EXIT_FAILURE); |     exit(EXIT_FAILURE); | ||||||
| @@ -53,12 +53,12 @@ int getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator & | |||||||
|   threads = warpSize; |   threads = warpSize; | ||||||
|   if ( threads*sizeofsobj > sharedMemPerBlock ) { |   if ( threads*sizeofsobj > sharedMemPerBlock ) { | ||||||
|     std::cout << GridLogError << "The object is too large for the shared memory." << std::endl; |     std::cout << GridLogError << "The object is too large for the shared memory." << std::endl; | ||||||
|     return 0; |     exit(EXIT_FAILURE); | ||||||
|   } |   } | ||||||
|   while( 2*threads*sizeofsobj < sharedMemPerBlock && 2*threads <= maxThreadsPerBlock ) threads *= 2; |   while( 2*threads*sizeofsobj < sharedMemPerBlock && 2*threads <= maxThreadsPerBlock ) threads *= 2; | ||||||
|   // keep all the streaming multiprocessors busy |   // keep all the streaming multiprocessors busy | ||||||
|   blocks = nextPow2(multiProcessorCount); |   blocks = nextPow2(multiProcessorCount); | ||||||
|   return 1; |    | ||||||
| } | } | ||||||
|  |  | ||||||
| template <class sobj, class Iterator> | template <class sobj, class Iterator> | ||||||
| @@ -198,7 +198,7 @@ __global__ void reduceKernel(const vobj *lat, sobj *buffer, Iterator n) { | |||||||
| // Possibly promote to double and sum | // Possibly promote to double and sum | ||||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
| template <class vobj> | template <class vobj> | ||||||
| inline typename vobj::scalar_objectD sumD_gpu_small(const vobj *lat, Integer osites)  | inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites)  | ||||||
| { | { | ||||||
|   typedef typename vobj::scalar_objectD sobj; |   typedef typename vobj::scalar_objectD sobj; | ||||||
|   typedef decltype(lat) Iterator; |   typedef decltype(lat) Iterator; | ||||||
| @@ -207,9 +207,7 @@ inline typename vobj::scalar_objectD sumD_gpu_small(const vobj *lat, Integer osi | |||||||
|   Integer size = osites*nsimd; |   Integer size = osites*nsimd; | ||||||
|  |  | ||||||
|   Integer numThreads, numBlocks; |   Integer numThreads, numBlocks; | ||||||
|   int ok = getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks); |   getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks); | ||||||
|   assert(ok); |  | ||||||
|  |  | ||||||
|   Integer smemSize = numThreads * sizeof(sobj); |   Integer smemSize = numThreads * sizeof(sobj); | ||||||
|  |  | ||||||
|   Vector<sobj> buffer(numBlocks); |   Vector<sobj> buffer(numBlocks); | ||||||
| @@ -220,54 +218,6 @@ inline typename vobj::scalar_objectD sumD_gpu_small(const vobj *lat, Integer osi | |||||||
|   auto result = buffer_v[0]; |   auto result = buffer_v[0]; | ||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_objectD sumD_gpu_large(const vobj *lat, Integer osites) |  | ||||||
| { |  | ||||||
|   typedef typename vobj::vector_type  vector; |  | ||||||
|   typedef typename vobj::scalar_typeD scalarD; |  | ||||||
|   typedef typename vobj::scalar_objectD sobj; |  | ||||||
|   sobj ret; |  | ||||||
|   scalarD *ret_p = (scalarD *)&ret; |  | ||||||
|    |  | ||||||
|   const int words = sizeof(vobj)/sizeof(vector); |  | ||||||
|  |  | ||||||
|   Vector<vector> buffer(osites); |  | ||||||
|   vector *dat = (vector *)lat; |  | ||||||
|   vector *buf = &buffer[0]; |  | ||||||
|   iScalar<vector> *tbuf =(iScalar<vector> *)  &buffer[0]; |  | ||||||
|   for(int w=0;w<words;w++) { |  | ||||||
|  |  | ||||||
|     accelerator_for(ss,osites,1,{ |  | ||||||
| 	buf[ss] = dat[ss*words+w]; |  | ||||||
|       }); |  | ||||||
|        |  | ||||||
|     ret_p[w] = sumD_gpu_small(tbuf,osites); |  | ||||||
|   } |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites) |  | ||||||
| { |  | ||||||
|   typedef typename vobj::vector_type  vector; |  | ||||||
|   typedef typename vobj::scalar_typeD scalarD; |  | ||||||
|   typedef typename vobj::scalar_objectD sobj; |  | ||||||
|   sobj ret; |  | ||||||
|    |  | ||||||
|   Integer nsimd= vobj::Nsimd(); |  | ||||||
|   Integer size = osites*nsimd; |  | ||||||
|   Integer numThreads, numBlocks; |  | ||||||
|   int ok = getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks); |  | ||||||
|    |  | ||||||
|   if ( ok ) { |  | ||||||
|     ret = sumD_gpu_small(lat,osites); |  | ||||||
|   } else { |  | ||||||
|     ret = sumD_gpu_large(lat,osites); |  | ||||||
|   } |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
| // Return as same precision as input performing reduction in double precision though | // Return as same precision as input performing reduction in double precision though | ||||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
| @@ -280,13 +230,6 @@ inline typename vobj::scalar_object sum_gpu(const vobj *lat, Integer osites) | |||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_object sum_gpu_large(const vobj *lat, Integer osites) |  | ||||||
| { |  | ||||||
|   typedef typename vobj::scalar_object sobj; |  | ||||||
|   sobj result; |  | ||||||
|   result = sumD_gpu_large(lat,osites); |  | ||||||
|   return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|   | |||||||
| @@ -1,125 +0,0 @@ | |||||||
| NAMESPACE_BEGIN(Grid); |  | ||||||
|  |  | ||||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
| // Possibly promote to double and sum |  | ||||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
|  |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_objectD sumD_gpu_tensor(const vobj *lat, Integer osites)  |  | ||||||
| { |  | ||||||
|   typedef typename vobj::scalar_object sobj; |  | ||||||
|   typedef typename vobj::scalar_objectD sobjD; |  | ||||||
|   sobj *mysum =(sobj *) malloc_shared(sizeof(sobj),*theGridAccelerator); |  | ||||||
|   sobj identity; zeroit(identity); |  | ||||||
|   sobj ret ;  |  | ||||||
|  |  | ||||||
|   Integer nsimd= vobj::Nsimd(); |  | ||||||
|    |  | ||||||
|   theGridAccelerator->submit([&](cl::sycl::handler &cgh) { |  | ||||||
|      auto Reduction = cl::sycl::reduction(mysum,identity,std::plus<>()); |  | ||||||
|      cgh.parallel_for(cl::sycl::range<1>{osites}, |  | ||||||
| 		      Reduction, |  | ||||||
| 		      [=] (cl::sycl::id<1> item, auto &sum) { |  | ||||||
|       auto osite   = item[0]; |  | ||||||
|       sum +=Reduce(lat[osite]); |  | ||||||
|      }); |  | ||||||
|    }); |  | ||||||
|   theGridAccelerator->wait(); |  | ||||||
|   ret = mysum[0]; |  | ||||||
|   free(mysum,*theGridAccelerator); |  | ||||||
|   sobjD dret; convertType(dret,ret); |  | ||||||
|   return dret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_objectD sumD_gpu_large(const vobj *lat, Integer osites) |  | ||||||
| { |  | ||||||
|   return sumD_gpu_tensor(lat,osites); |  | ||||||
| } |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_objectD sumD_gpu_small(const vobj *lat, Integer osites) |  | ||||||
| { |  | ||||||
|   return sumD_gpu_large(lat,osites); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites) |  | ||||||
| { |  | ||||||
|   return sumD_gpu_large(lat,osites); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
| // Return as same precision as input performing reduction in double precision though |  | ||||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_object sum_gpu(const vobj *lat, Integer osites)  |  | ||||||
| { |  | ||||||
|   typedef typename vobj::scalar_object sobj; |  | ||||||
|   sobj result; |  | ||||||
|   result = sumD_gpu(lat,osites); |  | ||||||
|   return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_object sum_gpu_large(const vobj *lat, Integer osites) |  | ||||||
| { |  | ||||||
|   typedef typename vobj::scalar_object sobj; |  | ||||||
|   sobj result; |  | ||||||
|   result = sumD_gpu_large(lat,osites); |  | ||||||
|   return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| template<class Double> Double svm_reduce(Double *vec,uint64_t L) |  | ||||||
| { |  | ||||||
|   Double sumResult; zeroit(sumResult); |  | ||||||
|   Double *d_sum =(Double *)cl::sycl::malloc_shared(sizeof(Double),*theGridAccelerator); |  | ||||||
|   Double identity;  zeroit(identity); |  | ||||||
|   theGridAccelerator->submit([&](cl::sycl::handler &cgh) { |  | ||||||
|      auto Reduction = cl::sycl::reduction(d_sum,identity,std::plus<>()); |  | ||||||
|      cgh.parallel_for(cl::sycl::range<1>{L}, |  | ||||||
| 		      Reduction, |  | ||||||
| 		      [=] (cl::sycl::id<1> index, auto &sum) { |  | ||||||
| 	 sum +=vec[index]; |  | ||||||
|      }); |  | ||||||
|    }); |  | ||||||
|   theGridAccelerator->wait(); |  | ||||||
|   Double ret = d_sum[0]; |  | ||||||
|   free(d_sum,*theGridAccelerator); |  | ||||||
|   std::cout << " svm_reduce finished "<<L<<" sites sum = " << ret <<std::endl; |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <class vobj> |  | ||||||
| inline typename vobj::scalar_objectD sumD_gpu_repack(const vobj *lat, Integer osites) |  | ||||||
| { |  | ||||||
|   typedef typename vobj::vector_type  vector; |  | ||||||
|   typedef typename vobj::scalar_type  scalar; |  | ||||||
|  |  | ||||||
|   typedef typename vobj::scalar_typeD scalarD; |  | ||||||
|   typedef typename vobj::scalar_objectD sobjD; |  | ||||||
|  |  | ||||||
|   sobjD ret; |  | ||||||
|   scalarD *ret_p = (scalarD *)&ret; |  | ||||||
|    |  | ||||||
|   const int nsimd = vobj::Nsimd(); |  | ||||||
|   const int words = sizeof(vobj)/sizeof(vector); |  | ||||||
|  |  | ||||||
|   Vector<scalar> buffer(osites*nsimd); |  | ||||||
|   scalar *buf = &buffer[0]; |  | ||||||
|   vector *dat = (vector *)lat; |  | ||||||
|  |  | ||||||
|   for(int w=0;w<words;w++) { |  | ||||||
|  |  | ||||||
|     accelerator_for(ss,osites,nsimd,{ |  | ||||||
| 	int lane = acceleratorSIMTlane(nsimd); |  | ||||||
| 	buf[ss*nsimd+lane] = dat[ss*words+w].getlane(lane); |  | ||||||
|     }); |  | ||||||
|     //Precision change at this point is to late to gain precision |  | ||||||
|     ret_p[w] = svm_reduce(buf,nsimd*osites); |  | ||||||
|   } |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
| */ |  | ||||||
| @@ -32,8 +32,9 @@ | |||||||
| #include <random> | #include <random> | ||||||
|  |  | ||||||
| #ifdef RNG_SITMO | #ifdef RNG_SITMO | ||||||
| #include <Grid/sitmo_rng/sitmo_prng_engine.hpp> | #include <Grid/random/sitmo_prng_engine.hpp> | ||||||
| #endif  | #endif  | ||||||
|  | #include <Grid/random/gaussian.h> | ||||||
|  |  | ||||||
| #if defined(RNG_SITMO) | #if defined(RNG_SITMO) | ||||||
| #define RNG_FAST_DISCARD | #define RNG_FAST_DISCARD | ||||||
| @@ -142,8 +143,8 @@ public: | |||||||
|  |  | ||||||
|   std::vector<RngEngine>                             _generators; |   std::vector<RngEngine>                             _generators; | ||||||
|   std::vector<std::uniform_real_distribution<RealD> > _uniform; |   std::vector<std::uniform_real_distribution<RealD> > _uniform; | ||||||
|   std::vector<std::normal_distribution<RealD> >       _gaussian; |   std::vector<Grid::gaussian_distribution<RealD> >       _gaussian; | ||||||
|   std::vector<std::discrete_distribution<int32_t> >   _bernoulli; |   //  std::vector<std::discrete_distribution<int32_t> >   _bernoulli; | ||||||
|   std::vector<std::uniform_int_distribution<uint32_t> > _uid; |   std::vector<std::uniform_int_distribution<uint32_t> > _uid; | ||||||
|  |  | ||||||
|   /////////////////////// |   /////////////////////// | ||||||
| @@ -243,8 +244,8 @@ public: | |||||||
|   GridSerialRNG() : GridRNGbase() { |   GridSerialRNG() : GridRNGbase() { | ||||||
|     _generators.resize(1); |     _generators.resize(1); | ||||||
|     _uniform.resize(1,std::uniform_real_distribution<RealD>{0,1}); |     _uniform.resize(1,std::uniform_real_distribution<RealD>{0,1}); | ||||||
|     _gaussian.resize(1,std::normal_distribution<RealD>(0.0,1.0) ); |     _gaussian.resize(1,gaussian_distribution<RealD>(0.0,1.0) ); | ||||||
|     _bernoulli.resize(1,std::discrete_distribution<int32_t>{1,1}); |     //    _bernoulli.resize(1,std::discrete_distribution<int32_t>{1,1}); | ||||||
|     _uid.resize(1,std::uniform_int_distribution<uint32_t>() ); |     _uid.resize(1,std::uniform_int_distribution<uint32_t>() ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -357,8 +358,8 @@ public: | |||||||
|  |  | ||||||
|     _generators.resize(_vol); |     _generators.resize(_vol); | ||||||
|     _uniform.resize(_vol,std::uniform_real_distribution<RealD>{0,1}); |     _uniform.resize(_vol,std::uniform_real_distribution<RealD>{0,1}); | ||||||
|     _gaussian.resize(_vol,std::normal_distribution<RealD>(0.0,1.0) ); |     _gaussian.resize(_vol,gaussian_distribution<RealD>(0.0,1.0) ); | ||||||
|     _bernoulli.resize(_vol,std::discrete_distribution<int32_t>{1,1}); |     //    _bernoulli.resize(_vol,std::discrete_distribution<int32_t>{1,1}); | ||||||
|     _uid.resize(_vol,std::uniform_int_distribution<uint32_t>() ); |     _uid.resize(_vol,std::uniform_int_distribution<uint32_t>() ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -515,11 +516,11 @@ public: | |||||||
|  |  | ||||||
| template <class vobj> inline void random(GridParallelRNG &rng,Lattice<vobj> &l)   { rng.fill(l,rng._uniform);  } | template <class vobj> inline void random(GridParallelRNG &rng,Lattice<vobj> &l)   { rng.fill(l,rng._uniform);  } | ||||||
| template <class vobj> inline void gaussian(GridParallelRNG &rng,Lattice<vobj> &l) { rng.fill(l,rng._gaussian); } | template <class vobj> inline void gaussian(GridParallelRNG &rng,Lattice<vobj> &l) { rng.fill(l,rng._gaussian); } | ||||||
| template <class vobj> inline void bernoulli(GridParallelRNG &rng,Lattice<vobj> &l){ rng.fill(l,rng._bernoulli);} | //template <class vobj> inline void bernoulli(GridParallelRNG &rng,Lattice<vobj> &l){ rng.fill(l,rng._bernoulli);} | ||||||
|  |  | ||||||
| template <class sobj> inline void random(GridSerialRNG &rng,sobj &l)   { rng.fill(l,rng._uniform  ); } | template <class sobj> inline void random(GridSerialRNG &rng,sobj &l)   { rng.fill(l,rng._uniform  ); } | ||||||
| template <class sobj> inline void gaussian(GridSerialRNG &rng,sobj &l) { rng.fill(l,rng._gaussian ); } | template <class sobj> inline void gaussian(GridSerialRNG &rng,sobj &l) { rng.fill(l,rng._gaussian ); } | ||||||
| template <class sobj> inline void bernoulli(GridSerialRNG &rng,sobj &l){ rng.fill(l,rng._bernoulli); } | //template <class sobj> inline void bernoulli(GridSerialRNG &rng,sobj &l){ rng.fill(l,rng._bernoulli); } | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -288,36 +288,7 @@ inline void blockProject(Lattice<iVector<CComplex,nbasis > > &coarseData, | |||||||
|     blockZAXPY(fineDataRed,ip,Basis[v],fineDataRed);  |     blockZAXPY(fineDataRed,ip,Basis[v],fineDataRed);  | ||||||
|   } |   } | ||||||
| } | } | ||||||
| template<class vobj,class CComplex,int nbasis,class VLattice> |  | ||||||
| inline void batchBlockProject(std::vector<Lattice<iVector<CComplex,nbasis>>> &coarseData, |  | ||||||
|                                const std::vector<Lattice<vobj>> &fineData, |  | ||||||
|                                const VLattice &Basis) |  | ||||||
| { |  | ||||||
|   int NBatch = fineData.size(); |  | ||||||
|   assert(coarseData.size() == NBatch); |  | ||||||
|  |  | ||||||
|   GridBase * fine  = fineData[0].Grid(); |  | ||||||
|   GridBase * coarse= coarseData[0].Grid(); |  | ||||||
|  |  | ||||||
|   Lattice<iScalar<CComplex>> ip(coarse); |  | ||||||
|   std::vector<Lattice<vobj>> fineDataCopy = fineData; |  | ||||||
|  |  | ||||||
|   autoView(ip_, ip, AcceleratorWrite); |  | ||||||
|   for(int v=0;v<nbasis;v++) { |  | ||||||
|     for (int k=0; k<NBatch; k++) { |  | ||||||
|       autoView( coarseData_ , coarseData[k], AcceleratorWrite); |  | ||||||
|       blockInnerProductD(ip,Basis[v],fineDataCopy[k]); // ip = <basis|fine> |  | ||||||
|       accelerator_for( sc, coarse->oSites(), vobj::Nsimd(), { |  | ||||||
|         convertType(coarseData_[sc](v),ip_[sc]); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       // improve numerical stability of projection |  | ||||||
|       // |fine> = |fine> - <basis|fine> |basis> |  | ||||||
|       ip=-ip; |  | ||||||
|       blockZAXPY(fineDataCopy[k],ip,Basis[v],fineDataCopy[k]);  |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template<class vobj,class vobj2,class CComplex> | template<class vobj,class vobj2,class CComplex> | ||||||
|   inline void blockZAXPY(Lattice<vobj> &fineZ, |   inline void blockZAXPY(Lattice<vobj> &fineZ, | ||||||
| @@ -619,26 +590,6 @@ inline void blockPromote(const Lattice<iVector<CComplex,nbasis > > &coarseData, | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| template<class vobj,class CComplex,int nbasis,class VLattice> |  | ||||||
| inline void batchBlockPromote(const std::vector<Lattice<iVector<CComplex,nbasis>>> &coarseData, |  | ||||||
|                                std::vector<Lattice<vobj>> &fineData, |  | ||||||
|                                const VLattice &Basis) |  | ||||||
| { |  | ||||||
|   int NBatch = coarseData.size(); |  | ||||||
|   assert(fineData.size() == NBatch); |  | ||||||
|  |  | ||||||
|   GridBase * fine   = fineData[0].Grid(); |  | ||||||
|   GridBase * coarse = coarseData[0].Grid(); |  | ||||||
|   for (int k=0; k<NBatch; k++) |  | ||||||
|     fineData[k]=Zero(); |  | ||||||
|   for (int i=0;i<nbasis;i++) { |  | ||||||
|     for (int k=0; k<NBatch; k++) { |  | ||||||
|       Lattice<iScalar<CComplex>> ip = PeekIndex<0>(coarseData[k],i); |  | ||||||
|       blockZAXPY(fineData[k],ip,Basis[i],fineData[k]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Useful for precision conversion, or indeed anything where an operator= does a conversion on scalars. | // Useful for precision conversion, or indeed anything where an operator= does a conversion on scalars. | ||||||
| // Simd layouts need not match since we use peek/poke Local | // Simd layouts need not match since we use peek/poke Local | ||||||
| template<class vobj,class vvobj> | template<class vobj,class vvobj> | ||||||
| @@ -904,7 +855,7 @@ void ExtractSliceLocal(Lattice<vobj> &lowDim,const Lattice<vobj> & higherDim,int | |||||||
|  |  | ||||||
|  |  | ||||||
| template<class vobj> | template<class vobj> | ||||||
| void Replicate(Lattice<vobj> &coarse,Lattice<vobj> & fine) | void Replicate(const Lattice<vobj> &coarse,Lattice<vobj> & fine) | ||||||
| { | { | ||||||
|   typedef typename vobj::scalar_object sobj; |   typedef typename vobj::scalar_object sobj; | ||||||
|  |  | ||||||
| @@ -1129,54 +1080,96 @@ vectorizeFromRevLexOrdArray( std::vector<sobj> &in, Lattice<vobj> &out) | |||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| //Convert a Lattice from one precision to another | //The workspace for a precision change operation allowing for the reuse of the mapping to save time on subsequent calls | ||||||
| template<class VobjOut, class VobjIn> | class precisionChangeWorkspace{ | ||||||
| void precisionChange(Lattice<VobjOut> &out, const Lattice<VobjIn> &in) |   std::pair<Integer,Integer>* fmap_device; //device pointer | ||||||
| { | public: | ||||||
|   assert(out.Grid()->Nd() == in.Grid()->Nd()); |   precisionChangeWorkspace(GridBase *out_grid, GridBase *in_grid){ | ||||||
|   for(int d=0;d<out.Grid()->Nd();d++){ |     //Build a map between the sites and lanes of the output field and the input field as we cannot use the Grids on the device | ||||||
|     assert(out.Grid()->FullDimensions()[d] == in.Grid()->FullDimensions()[d]); |     assert(out_grid->Nd() == in_grid->Nd()); | ||||||
|  |     for(int d=0;d<out_grid->Nd();d++){ | ||||||
|  |       assert(out_grid->FullDimensions()[d] == in_grid->FullDimensions()[d]); | ||||||
|     } |     } | ||||||
|   out.Checkerboard() = in.Checkerboard(); |     int Nsimd_out = out_grid->Nsimd(); | ||||||
|   GridBase *in_grid=in.Grid(); |  | ||||||
|   GridBase *out_grid = out.Grid(); |  | ||||||
|  |  | ||||||
|   typedef typename VobjOut::scalar_object SobjOut; |     std::vector<Coordinate> out_icorrs(out_grid->Nsimd()); //reuse these | ||||||
|   typedef typename VobjIn::scalar_object SobjIn; |     for(int lane=0; lane < out_grid->Nsimd(); lane++) | ||||||
|  |       out_grid->iCoorFromIindex(out_icorrs[lane], lane); | ||||||
|    |    | ||||||
|   int ndim = out.Grid()->Nd(); |     std::vector<std::pair<Integer,Integer> > fmap_host(out_grid->lSites()); //lsites = osites*Nsimd | ||||||
|   int out_nsimd = out_grid->Nsimd(); |  | ||||||
|      |  | ||||||
|   std::vector<Coordinate > out_icoor(out_nsimd); |  | ||||||
|        |  | ||||||
|   for(int lane=0; lane < out_nsimd; lane++){ |  | ||||||
|     out_icoor[lane].resize(ndim); |  | ||||||
|     out_grid->iCoorFromIindex(out_icoor[lane], lane); |  | ||||||
|   } |  | ||||||
|          |  | ||||||
|   std::vector<SobjOut> in_slex_conv(in_grid->lSites()); |  | ||||||
|   unvectorizeToLexOrdArray(in_slex_conv, in); |  | ||||||
|      |  | ||||||
|   autoView( out_v , out, CpuWrite); |  | ||||||
|     thread_for(out_oidx,out_grid->oSites(),{ |     thread_for(out_oidx,out_grid->oSites(),{ | ||||||
|     Coordinate out_ocoor(ndim); | 	Coordinate out_ocorr;  | ||||||
|     out_grid->oCoorFromOindex(out_ocoor, out_oidx); | 	out_grid->oCoorFromOindex(out_ocorr, out_oidx); | ||||||
|        |        | ||||||
|     ExtractPointerArray<SobjOut> ptrs(out_nsimd);       | 	Coordinate lcorr; //the local coordinate (common to both in and out as full coordinate) | ||||||
|  | 	for(int out_lane=0; out_lane < Nsimd_out; out_lane++){ | ||||||
|  | 	  out_grid->InOutCoorToLocalCoor(out_ocorr, out_icorrs[out_lane], lcorr); | ||||||
| 	 | 	 | ||||||
|     Coordinate lcoor(out_grid->Nd()); | 	  //int in_oidx = in_grid->oIndex(lcorr), in_lane = in_grid->iIndex(lcorr); | ||||||
|        | 	  //Note oIndex and OcorrFromOindex (and same for iIndex) are not inverse for checkerboarded lattice, the former coordinates being defined on the full lattice and the latter on the reduced lattice | ||||||
|     for(int lane=0; lane < out_nsimd; lane++){ | 	  //Until this is fixed we need to circumvent the problem locally. Here I will use the coordinates defined on the reduced lattice for simplicity | ||||||
|       for(int mu=0;mu<ndim;mu++) | 	  int in_oidx = 0, in_lane = 0; | ||||||
| 	lcoor[mu] = out_ocoor[mu] + out_grid->_rdimensions[mu]*out_icoor[lane][mu]; | 	  for(int d=0;d<in_grid->_ndimension;d++){ | ||||||
| 	 | 	    in_oidx += in_grid->_ostride[d] * ( lcorr[d] % in_grid->_rdimensions[d] ); | ||||||
|       int llex; Lexicographic::IndexFromCoor(lcoor, llex, out_grid->_ldimensions); | 	    in_lane += in_grid->_istride[d] * ( lcorr[d] / in_grid->_rdimensions[d] ); | ||||||
|       ptrs[lane] = &in_slex_conv[llex]; | 	  } | ||||||
|  | 	  fmap_host[out_lane + Nsimd_out*out_oidx] = std::pair<Integer,Integer>( in_oidx, in_lane ); | ||||||
|  | 	} | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |     //Copy the map to the device (if we had a way to tell if an accelerator is in use we could avoid this copy for CPU-only machines) | ||||||
|  |     size_t fmap_bytes = out_grid->lSites() * sizeof(std::pair<Integer,Integer>); | ||||||
|  |     fmap_device = (std::pair<Integer,Integer>*)acceleratorAllocDevice(fmap_bytes); | ||||||
|  |     acceleratorCopyToDevice(fmap_host.data(), fmap_device, fmap_bytes);  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   //Prevent moving or copying | ||||||
|  |   precisionChangeWorkspace(const precisionChangeWorkspace &r) = delete; | ||||||
|  |   precisionChangeWorkspace(precisionChangeWorkspace &&r) = delete; | ||||||
|  |   precisionChangeWorkspace &operator=(const precisionChangeWorkspace &r) = delete; | ||||||
|  |   precisionChangeWorkspace &operator=(precisionChangeWorkspace &&r) = delete; | ||||||
|  |    | ||||||
|  |   std::pair<Integer,Integer> const* getMap() const{ return fmap_device; } | ||||||
|  |  | ||||||
|  |   ~precisionChangeWorkspace(){ | ||||||
|  |     acceleratorFreeDevice(fmap_device); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //Convert a lattice of one precision to another. The input workspace contains the mapping data. | ||||||
|  | template<class VobjOut, class VobjIn> | ||||||
|  | void precisionChange(Lattice<VobjOut> &out, const Lattice<VobjIn> &in, const precisionChangeWorkspace &workspace){ | ||||||
|  |   static_assert( std::is_same<typename VobjOut::DoublePrecision, typename VobjIn::DoublePrecision>::value == 1, "copyLane: tensor types must be the same" ); //if tensor types are same the DoublePrecision type must be the same | ||||||
|  |  | ||||||
|  |   out.Checkerboard() = in.Checkerboard(); | ||||||
|  |   constexpr int Nsimd_out = VobjOut::Nsimd(); | ||||||
|  |  | ||||||
|  |   std::pair<Integer,Integer> const* fmap_device = workspace.getMap(); | ||||||
|  |  | ||||||
|  |   //Do the copy/precision change | ||||||
|  |   autoView( out_v , out, AcceleratorWrite); | ||||||
|  |   autoView( in_v , in, AcceleratorRead); | ||||||
|  |  | ||||||
|  |   accelerator_for(out_oidx, out.Grid()->oSites(), 1,{ | ||||||
|  |       std::pair<Integer,Integer> const* fmap_osite = fmap_device + out_oidx*Nsimd_out; | ||||||
|  |       for(int out_lane=0; out_lane < Nsimd_out; out_lane++){       | ||||||
|  | 	int in_oidx = fmap_osite[out_lane].first; | ||||||
|  | 	int in_lane = fmap_osite[out_lane].second; | ||||||
|  | 	copyLane(out_v[out_oidx], out_lane, in_v[in_oidx], in_lane); | ||||||
|       } |       } | ||||||
|     merge(out_v[out_oidx], ptrs, 0); |  | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | //Convert a Lattice from one precision to another | ||||||
|  | //Generate the workspace in place; if multiple calls with the same mapping are performed, consider pregenerating the workspace and reusing | ||||||
|  | template<class VobjOut, class VobjIn> | ||||||
|  | void precisionChange(Lattice<VobjOut> &out, const Lattice<VobjIn> &in){ | ||||||
|  |   precisionChangeWorkspace workspace(out.Grid(), in.Grid()); | ||||||
|  |   precisionChange(out, in, workspace); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||||
| // Communicate between grids | // Communicate between grids | ||||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -65,38 +65,30 @@ GridLogger GridLogSolver (1, "Solver", GridLogColours, "NORMAL"); | |||||||
| GridLogger GridLogError  (1, "Error" , GridLogColours, "RED"); | GridLogger GridLogError  (1, "Error" , GridLogColours, "RED"); | ||||||
| GridLogger GridLogWarning(1, "Warning", GridLogColours, "YELLOW"); | GridLogger GridLogWarning(1, "Warning", GridLogColours, "YELLOW"); | ||||||
| GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL"); | GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL"); | ||||||
| GridLogger GridLogMemory (1, "Memory", GridLogColours, "NORMAL"); |  | ||||||
| GridLogger GridLogTracing(1, "Tracing", GridLogColours, "NORMAL"); |  | ||||||
| GridLogger GridLogDebug  (1, "Debug", GridLogColours, "PURPLE"); | GridLogger GridLogDebug  (1, "Debug", GridLogColours, "PURPLE"); | ||||||
| GridLogger GridLogPerformance(1, "Performance", GridLogColours, "GREEN"); | GridLogger GridLogPerformance(1, "Performance", GridLogColours, "GREEN"); | ||||||
| GridLogger GridLogDslash     (1, "Dslash", GridLogColours, "BLUE"); |  | ||||||
| GridLogger GridLogIterative  (1, "Iterative", GridLogColours, "BLUE"); | GridLogger GridLogIterative  (1, "Iterative", GridLogColours, "BLUE"); | ||||||
| GridLogger GridLogIntegrator (1, "Integrator", GridLogColours, "BLUE"); | GridLogger GridLogIntegrator (1, "Integrator", GridLogColours, "BLUE"); | ||||||
| GridLogger GridLogHMC (1, "HMC", GridLogColours, "BLUE"); | GridLogger GridLogHMC (1, "HMC", GridLogColours, "BLUE"); | ||||||
|  |  | ||||||
| void GridLogConfigure(std::vector<std::string> &logstreams) { | void GridLogConfigure(std::vector<std::string> &logstreams) { | ||||||
|   GridLogError.Active(1); |   GridLogError.Active(0); | ||||||
|   GridLogWarning.Active(0); |   GridLogWarning.Active(0); | ||||||
|   GridLogMessage.Active(1); // at least the messages should be always on |   GridLogMessage.Active(1); // at least the messages should be always on | ||||||
|   GridLogMemory.Active(0);  |  | ||||||
|   GridLogTracing.Active(0);  |  | ||||||
|   GridLogIterative.Active(0); |   GridLogIterative.Active(0); | ||||||
|   GridLogDebug.Active(0); |   GridLogDebug.Active(0); | ||||||
|   GridLogPerformance.Active(0); |   GridLogPerformance.Active(0); | ||||||
|   GridLogDslash.Active(0); |  | ||||||
|   GridLogIntegrator.Active(1); |   GridLogIntegrator.Active(1); | ||||||
|   GridLogColours.Active(0); |   GridLogColours.Active(0); | ||||||
|   GridLogHMC.Active(1); |   GridLogHMC.Active(1); | ||||||
|  |  | ||||||
|   for (int i = 0; i < logstreams.size(); i++) { |   for (int i = 0; i < logstreams.size(); i++) { | ||||||
|     if (logstreams[i] == std::string("Tracing"))     GridLogTracing.Active(1); |     if (logstreams[i] == std::string("Error"))       GridLogError.Active(1); | ||||||
|     if (logstreams[i] == std::string("Memory"))      GridLogMemory.Active(1); |  | ||||||
|     if (logstreams[i] == std::string("Warning"))     GridLogWarning.Active(1); |     if (logstreams[i] == std::string("Warning"))     GridLogWarning.Active(1); | ||||||
|     if (logstreams[i] == std::string("NoMessage"))   GridLogMessage.Active(0); |     if (logstreams[i] == std::string("NoMessage"))   GridLogMessage.Active(0); | ||||||
|     if (logstreams[i] == std::string("Iterative"))   GridLogIterative.Active(1); |     if (logstreams[i] == std::string("Iterative"))   GridLogIterative.Active(1); | ||||||
|     if (logstreams[i] == std::string("Debug"))       GridLogDebug.Active(1); |     if (logstreams[i] == std::string("Debug"))       GridLogDebug.Active(1); | ||||||
|     if (logstreams[i] == std::string("Performance")) GridLogPerformance.Active(1); |     if (logstreams[i] == std::string("Performance")) GridLogPerformance.Active(1); | ||||||
|     if (logstreams[i] == std::string("Dslash"))      GridLogDslash.Active(1); |  | ||||||
|     if (logstreams[i] == std::string("NoIntegrator"))  GridLogIntegrator.Active(0); |     if (logstreams[i] == std::string("NoIntegrator"))  GridLogIntegrator.Active(0); | ||||||
|     if (logstreams[i] == std::string("NoHMC"))         GridLogHMC.Active(0); |     if (logstreams[i] == std::string("NoHMC"))         GridLogHMC.Active(0); | ||||||
|     if (logstreams[i] == std::string("Colours"))     GridLogColours.Active(1); |     if (logstreams[i] == std::string("Colours"))     GridLogColours.Active(1); | ||||||
|   | |||||||
| @@ -138,8 +138,7 @@ public: | |||||||
|         stream << std::setw(log.topWidth); |         stream << std::setw(log.topWidth); | ||||||
|       } |       } | ||||||
|       stream << log.topName << log.background()<< " : "; |       stream << log.topName << log.background()<< " : "; | ||||||
|       //      stream << log.colour() <<  std::left; |       stream << log.colour() <<  std::left; | ||||||
|       stream <<  std::left; |  | ||||||
|       if (log.chanWidth > 0) |       if (log.chanWidth > 0) | ||||||
|       { |       { | ||||||
|         stream << std::setw(log.chanWidth); |         stream << std::setw(log.chanWidth); | ||||||
| @@ -154,9 +153,9 @@ public: | |||||||
| 	stream << log.evidence() | 	stream << log.evidence() | ||||||
| 	       << now	       << log.background() << " : " ; | 	       << now	       << log.background() << " : " ; | ||||||
|       } |       } | ||||||
|       //      stream << log.colour(); |       stream << log.colour(); | ||||||
|       stream <<  std::right; |  | ||||||
|       stream.flags(f); |       stream.flags(f); | ||||||
|  |  | ||||||
|       return stream; |       return stream; | ||||||
|     } else {  |     } else {  | ||||||
|       return devnull; |       return devnull; | ||||||
| @@ -181,12 +180,9 @@ extern GridLogger GridLogWarning; | |||||||
| extern GridLogger GridLogMessage; | extern GridLogger GridLogMessage; | ||||||
| extern GridLogger GridLogDebug  ; | extern GridLogger GridLogDebug  ; | ||||||
| extern GridLogger GridLogPerformance; | extern GridLogger GridLogPerformance; | ||||||
| extern GridLogger GridLogDslash; |  | ||||||
| extern GridLogger GridLogIterative  ; | extern GridLogger GridLogIterative  ; | ||||||
| extern GridLogger GridLogIntegrator  ; | extern GridLogger GridLogIntegrator  ; | ||||||
| extern GridLogger GridLogHMC; | extern GridLogger GridLogHMC; | ||||||
| extern GridLogger GridLogMemory; |  | ||||||
| extern GridLogger GridLogTracing; |  | ||||||
| extern Colours    GridLogColours; | extern Colours    GridLogColours; | ||||||
|  |  | ||||||
| std::string demangle(const char* name) ; | std::string demangle(const char* name) ; | ||||||
|   | |||||||
| @@ -31,7 +31,6 @@ directory | |||||||
| #include <fstream> | #include <fstream> | ||||||
| #include <iomanip> | #include <iomanip> | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <string> |  | ||||||
| #include <map> | #include <map> | ||||||
|  |  | ||||||
| #include <pwd.h> | #include <pwd.h> | ||||||
| @@ -655,8 +654,7 @@ class IldgWriter : public ScidacWriter { | |||||||
|     // Fill ILDG header data struct |     // Fill ILDG header data struct | ||||||
|     ////////////////////////////////////////////////////// |     ////////////////////////////////////////////////////// | ||||||
|     ildgFormat ildgfmt ; |     ildgFormat ildgfmt ; | ||||||
|     const std::string stNC = std::to_string( Nc ) ; |     ildgfmt.field     = std::string("su3gauge"); | ||||||
|     ildgfmt.field          = std::string("su"+stNC+"gauge"); |  | ||||||
|  |  | ||||||
|     if ( format == std::string("IEEE32BIG") ) {  |     if ( format == std::string("IEEE32BIG") ) {  | ||||||
|       ildgfmt.precision = 32; |       ildgfmt.precision = 32; | ||||||
| @@ -873,8 +871,7 @@ class IldgReader : public GridLimeReader { | |||||||
|     } else {  |     } else {  | ||||||
|  |  | ||||||
|       assert(found_ildgFormat); |       assert(found_ildgFormat); | ||||||
|       const std::string stNC = std::to_string( Nc ) ; |       assert ( ildgFormat_.field == std::string("su3gauge") ); | ||||||
|       assert ( ildgFormat_.field == std::string("su"+stNC+"gauge") ); |  | ||||||
|  |  | ||||||
|       /////////////////////////////////////////////////////////////////////////////////////// |       /////////////////////////////////////////////////////////////////////////////////////// | ||||||
|       // Populate our Grid metadata as best we can |       // Populate our Grid metadata as best we can | ||||||
| @@ -882,7 +879,7 @@ class IldgReader : public GridLimeReader { | |||||||
|  |  | ||||||
|       std::ostringstream vers; vers << ildgFormat_.version; |       std::ostringstream vers; vers << ildgFormat_.version; | ||||||
|       FieldMetaData_.hdr_version = vers.str(); |       FieldMetaData_.hdr_version = vers.str(); | ||||||
|       FieldMetaData_.data_type = std::string("4D_SU"+stNC+"_GAUGE_"+stNC+"x"+stNC); |       FieldMetaData_.data_type = std::string("4D_SU3_GAUGE_3X3"); | ||||||
|  |  | ||||||
|       FieldMetaData_.nd=4; |       FieldMetaData_.nd=4; | ||||||
|       FieldMetaData_.dimension.resize(4); |       FieldMetaData_.dimension.resize(4); | ||||||
|   | |||||||
| @@ -6,8 +6,8 @@ | |||||||
|  |  | ||||||
|     Copyright (C) 2015 |     Copyright (C) 2015 | ||||||
|  |  | ||||||
|  |  | ||||||
|     Author: Peter Boyle <paboyle@ph.ed.ac.uk> |     Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|     Author: Jamie Hudspith <renwick.james.hudspth@gmail.com> |  | ||||||
|  |  | ||||||
|     This program is free software; you can redistribute it and/or modify |     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 |     it under the terms of the GNU General Public License as published by | ||||||
| @@ -203,24 +203,20 @@ template<> inline void PrepareMetaData<vLorentzColourMatrixD>(Lattice<vLorentzCo | |||||||
| ////////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////////// | ||||||
| inline void reconstruct3(LorentzColourMatrix & cm) | inline void reconstruct3(LorentzColourMatrix & cm) | ||||||
| { | { | ||||||
|   assert( Nc < 4 && Nc > 1 ) ; |   const int x=0; | ||||||
|  |   const int y=1; | ||||||
|  |   const int z=2; | ||||||
|   for(int mu=0;mu<Nd;mu++){ |   for(int mu=0;mu<Nd;mu++){ | ||||||
|     #if Nc == 2 |  | ||||||
|       cm(mu)()(1,0) = -adj(cm(mu)()(0,y)) ; |  | ||||||
|       cm(mu)()(1,1) =  adj(cm(mu)()(0,x)) ; |  | ||||||
|     #else |  | ||||||
|       const int x=0 , y=1 , z=2 ; // a little disinenuous labelling |  | ||||||
|     cm(mu)()(2,x) = adj(cm(mu)()(0,y)*cm(mu)()(1,z)-cm(mu)()(0,z)*cm(mu)()(1,y)); //x= yz-zy |     cm(mu)()(2,x) = adj(cm(mu)()(0,y)*cm(mu)()(1,z)-cm(mu)()(0,z)*cm(mu)()(1,y)); //x= yz-zy | ||||||
|     cm(mu)()(2,y) = adj(cm(mu)()(0,z)*cm(mu)()(1,x)-cm(mu)()(0,x)*cm(mu)()(1,z)); //y= zx-xz |     cm(mu)()(2,y) = adj(cm(mu)()(0,z)*cm(mu)()(1,x)-cm(mu)()(0,x)*cm(mu)()(1,z)); //y= zx-xz | ||||||
|     cm(mu)()(2,z) = adj(cm(mu)()(0,x)*cm(mu)()(1,y)-cm(mu)()(0,y)*cm(mu)()(1,x)); //z= xy-yx |     cm(mu)()(2,z) = adj(cm(mu)()(0,x)*cm(mu)()(1,y)-cm(mu)()(0,y)*cm(mu)()(1,x)); //z= xy-yx | ||||||
|     #endif |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||||
| // Some data types for intermediate storage | // Some data types for intermediate storage | ||||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||||
| template<typename vtype> using iLorentzColour2x3 = iVector<iVector<iVector<vtype, Nc>, Nc-1>, Nd >; | template<typename vtype> using iLorentzColour2x3 = iVector<iVector<iVector<vtype, Nc>, 2>, Nd >; | ||||||
|  |  | ||||||
| typedef iLorentzColour2x3<Complex>  LorentzColour2x3; | typedef iLorentzColour2x3<Complex>  LorentzColour2x3; | ||||||
| typedef iLorentzColour2x3<ComplexF> LorentzColour2x3F; | typedef iLorentzColour2x3<ComplexF> LorentzColour2x3F; | ||||||
| @@ -282,6 +278,7 @@ struct GaugeSimpleMunger{ | |||||||
|  |  | ||||||
| template <class fobj, class sobj> | template <class fobj, class sobj> | ||||||
| struct GaugeSimpleUnmunger { | struct GaugeSimpleUnmunger { | ||||||
|  |  | ||||||
|   void operator()(sobj &in, fobj &out) { |   void operator()(sobj &in, fobj &out) { | ||||||
|     for (int mu = 0; mu < Nd; mu++) { |     for (int mu = 0; mu < Nd; mu++) { | ||||||
|       for (int i = 0; i < Nc; i++) { |       for (int i = 0; i < Nc; i++) { | ||||||
| @@ -320,8 +317,8 @@ template<class fobj,class sobj> | |||||||
| struct Gauge3x2munger{ | struct Gauge3x2munger{ | ||||||
|   void operator() (fobj &in,sobj &out){ |   void operator() (fobj &in,sobj &out){ | ||||||
|     for(int mu=0;mu<Nd;mu++){ |     for(int mu=0;mu<Nd;mu++){ | ||||||
|       for(int i=0;i<Nc-1;i++){ |       for(int i=0;i<2;i++){ | ||||||
| 	for(int j=0;j<Nc;j++){ | 	for(int j=0;j<3;j++){ | ||||||
| 	  out(mu)()(i,j) = in(mu)(i)(j); | 	  out(mu)()(i,j) = in(mu)(i)(j); | ||||||
| 	}} | 	}} | ||||||
|     } |     } | ||||||
| @@ -333,8 +330,8 @@ template<class fobj,class sobj> | |||||||
| struct Gauge3x2unmunger{ | struct Gauge3x2unmunger{ | ||||||
|   void operator() (sobj &in,fobj &out){ |   void operator() (sobj &in,fobj &out){ | ||||||
|     for(int mu=0;mu<Nd;mu++){ |     for(int mu=0;mu<Nd;mu++){ | ||||||
|       for(int i=0;i<Nc-1;i++){ |       for(int i=0;i<2;i++){ | ||||||
| 	for(int j=0;j<Nc;j++){ | 	for(int j=0;j<3;j++){ | ||||||
| 	  out(mu)(i)(j) = in(mu)()(i,j); | 	  out(mu)(i)(j) = in(mu)()(i,j); | ||||||
| 	}} | 	}} | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
|     Author: Matt Spraggs <matthew.spraggs@gmail.com> |     Author: Matt Spraggs <matthew.spraggs@gmail.com> | ||||||
|     Author: Peter Boyle <paboyle@ph.ed.ac.uk> |     Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> |     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|     Author: Jamie Hudspith <renwick.james.hudspth@gmail.com> |  | ||||||
|  |  | ||||||
|     This program is free software; you can redistribute it and/or modify |     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 |     it under the terms of the GNU General Public License as published by | ||||||
| @@ -31,8 +30,6 @@ | |||||||
| #ifndef GRID_NERSC_IO_H | #ifndef GRID_NERSC_IO_H | ||||||
| #define GRID_NERSC_IO_H | #define GRID_NERSC_IO_H | ||||||
|  |  | ||||||
| #include <string> |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| using namespace Grid; | using namespace Grid; | ||||||
| @@ -42,9 +39,11 @@ using namespace Grid; | |||||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||||
| class NerscIO : public BinaryIO {  | class NerscIO : public BinaryIO {  | ||||||
| public: | public: | ||||||
|  |  | ||||||
|   typedef Lattice<vLorentzColourMatrixD> GaugeField; |   typedef Lattice<vLorentzColourMatrixD> GaugeField; | ||||||
|  |  | ||||||
|  |   // Enable/disable exiting if the plaquette in the header does not match the value computed (default true) | ||||||
|  |   static bool & exitOnReadPlaquetteMismatch(){ static bool v=true; return v; } | ||||||
|  |  | ||||||
|   static inline void truncate(std::string file){ |   static inline void truncate(std::string file){ | ||||||
|     std::ofstream fout(file,std::ios::out); |     std::ofstream fout(file,std::ios::out); | ||||||
|   } |   } | ||||||
| @@ -148,17 +147,15 @@ public: | |||||||
|  |  | ||||||
|     std::string format(header.floating_point); |     std::string format(header.floating_point); | ||||||
|  |  | ||||||
|     const int ieee32big = (format == std::string("IEEE32BIG")); |     int ieee32big = (format == std::string("IEEE32BIG")); | ||||||
|     const int ieee32    = (format == std::string("IEEE32")); |     int ieee32    = (format == std::string("IEEE32")); | ||||||
|     const int ieee64big = (format == std::string("IEEE64BIG")); |     int ieee64big = (format == std::string("IEEE64BIG")); | ||||||
|     const int ieee64    = (format == std::string("IEEE64") || \ |     int ieee64    = (format == std::string("IEEE64") || format == std::string("IEEE64LITTLE")); | ||||||
| 			   format == std::string("IEEE64LITTLE")); |  | ||||||
|  |  | ||||||
|     uint32_t nersc_csum,scidac_csuma,scidac_csumb; |     uint32_t nersc_csum,scidac_csuma,scidac_csumb; | ||||||
|     // depending on datatype, set up munger; |     // depending on datatype, set up munger; | ||||||
|     // munger is a function of <floating point, Real, data_type> |     // munger is a function of <floating point, Real, data_type> | ||||||
|     const std::string stNC = std::to_string( Nc ) ; |     if ( header.data_type == std::string("4D_SU3_GAUGE") ) { | ||||||
|     if ( header.data_type == std::string("4D_SU"+stNC+"_GAUGE") ) { |  | ||||||
|       if ( ieee32 || ieee32big ) { |       if ( ieee32 || ieee32big ) { | ||||||
| 	BinaryIO::readLatticeObject<vLorentzColourMatrixD, LorentzColour2x3F>  | 	BinaryIO::readLatticeObject<vLorentzColourMatrixD, LorentzColour2x3F>  | ||||||
| 	  (Umu,file,Gauge3x2munger<LorentzColour2x3F,LorentzColourMatrix>(), offset,format, | 	  (Umu,file,Gauge3x2munger<LorentzColour2x3F,LorentzColourMatrix>(), offset,format, | ||||||
| @@ -169,7 +166,7 @@ public: | |||||||
| 	  (Umu,file,Gauge3x2munger<LorentzColour2x3D,LorentzColourMatrix>(),offset,format, | 	  (Umu,file,Gauge3x2munger<LorentzColour2x3D,LorentzColourMatrix>(),offset,format, | ||||||
| 	   nersc_csum,scidac_csuma,scidac_csumb); | 	   nersc_csum,scidac_csuma,scidac_csumb); | ||||||
|       } |       } | ||||||
|     } else if ( header.data_type == std::string("4D_SU"+stNC+"_GAUGE_"+stNC+"x"+stNC) ) { |     } else if ( header.data_type == std::string("4D_SU3_GAUGE_3x3") ) { | ||||||
|       if ( ieee32 || ieee32big ) { |       if ( ieee32 || ieee32big ) { | ||||||
| 	BinaryIO::readLatticeObject<vLorentzColourMatrixD,LorentzColourMatrixF> | 	BinaryIO::readLatticeObject<vLorentzColourMatrixD,LorentzColourMatrixF> | ||||||
| 	  (Umu,file,GaugeSimpleMunger<LorentzColourMatrixF,LorentzColourMatrix>(),offset,format, | 	  (Umu,file,GaugeSimpleMunger<LorentzColourMatrixF,LorentzColourMatrix>(),offset,format, | ||||||
| @@ -203,7 +200,7 @@ public: | |||||||
|       std::cerr << " nersc_csum  " <<std::hex<< nersc_csum << " " << header.checksum<< std::dec<< std::endl; |       std::cerr << " nersc_csum  " <<std::hex<< nersc_csum << " " << header.checksum<< std::dec<< std::endl; | ||||||
|       exit(0); |       exit(0); | ||||||
|     } |     } | ||||||
|     assert(fabs(clone.plaquette -header.plaquette ) < 1.0e-5 ); |     if(exitOnReadPlaquetteMismatch()) assert(fabs(clone.plaquette -header.plaquette ) < 1.0e-5 ); | ||||||
|     assert(fabs(clone.link_trace-header.link_trace) < 1.0e-6 ); |     assert(fabs(clone.link_trace-header.link_trace) < 1.0e-6 ); | ||||||
|     assert(nersc_csum == header.checksum ); |     assert(nersc_csum == header.checksum ); | ||||||
|        |        | ||||||
| @@ -214,29 +211,27 @@ public: | |||||||
|   template<class GaugeStats=PeriodicGaugeStatistics> |   template<class GaugeStats=PeriodicGaugeStatistics> | ||||||
|   static inline void writeConfiguration(Lattice<vLorentzColourMatrixD > &Umu, |   static inline void writeConfiguration(Lattice<vLorentzColourMatrixD > &Umu, | ||||||
| 					std::string file,  | 					std::string file,  | ||||||
| 					std::string ens_label = std::string("DWF"), | 					std::string ens_label = std::string("DWF")) | ||||||
| 					std::string ens_id = std::string("UKQCD"), |  | ||||||
| 					unsigned int sequence_number = 1) |  | ||||||
|   { |   { | ||||||
|     writeConfiguration(Umu,file,0,1,ens_label,ens_id,sequence_number); |     writeConfiguration(Umu,file,0,1,ens_label); | ||||||
|   } |   } | ||||||
|   template<class GaugeStats=PeriodicGaugeStatistics> |   template<class GaugeStats=PeriodicGaugeStatistics> | ||||||
|   static inline void writeConfiguration(Lattice<vLorentzColourMatrixD > &Umu, |   static inline void writeConfiguration(Lattice<vLorentzColourMatrixD > &Umu, | ||||||
| 					std::string file,  | 					std::string file,  | ||||||
| 					int two_row, | 					int two_row, | ||||||
| 					int bits32, | 					int bits32, | ||||||
| 					std::string ens_label = std::string("DWF"), | 					std::string ens_label = std::string("DWF")) | ||||||
| 					std::string ens_id = std::string("UKQCD"), |  | ||||||
| 					unsigned int sequence_number = 1) |  | ||||||
|   { |   { | ||||||
|     typedef vLorentzColourMatrixD vobj; |     typedef vLorentzColourMatrixD vobj; | ||||||
|     typedef typename vobj::scalar_object sobj; |     typedef typename vobj::scalar_object sobj; | ||||||
|  |  | ||||||
|     FieldMetaData header; |     FieldMetaData header; | ||||||
|     header.sequence_number = sequence_number; |     /////////////////////////////////////////// | ||||||
|     header.ensemble_id     = ens_id; |     // Following should become arguments | ||||||
|  |     /////////////////////////////////////////// | ||||||
|  |     header.sequence_number = 1; | ||||||
|  |     header.ensemble_id     = std::string("UKQCD"); | ||||||
|     header.ensemble_label  = ens_label; |     header.ensemble_label  = ens_label; | ||||||
|     header.hdr_version     = "1.0" ; |  | ||||||
|  |  | ||||||
|     typedef LorentzColourMatrixD fobj3D; |     typedef LorentzColourMatrixD fobj3D; | ||||||
|     typedef LorentzColour2x3D    fobj2D; |     typedef LorentzColour2x3D    fobj2D; | ||||||
| @@ -250,14 +245,10 @@ public: | |||||||
|  |  | ||||||
|     uint64_t offset; |     uint64_t offset; | ||||||
|  |  | ||||||
|     // Sod it -- always write NcxNc double |     // Sod it -- always write 3x3 double | ||||||
|     header.floating_point = std::string("IEEE64BIG"); |     header.floating_point = std::string("IEEE64BIG"); | ||||||
|     const std::string stNC = std::to_string( Nc ) ; |     header.data_type      = std::string("4D_SU3_GAUGE_3x3"); | ||||||
|     if( two_row ) { |     GaugeSimpleUnmunger<fobj3D,sobj> munge; | ||||||
|       header.data_type = std::string("4D_SU" + stNC + "_GAUGE" ); |  | ||||||
|     } else { |  | ||||||
|       header.data_type = std::string("4D_SU" + stNC + "_GAUGE_" + stNC + "x" + stNC ); |  | ||||||
|     } |  | ||||||
|     if ( grid->IsBoss() ) {  |     if ( grid->IsBoss() ) {  | ||||||
|       truncate(file); |       truncate(file); | ||||||
|       offset = writeHeader(header,file); |       offset = writeHeader(header,file); | ||||||
| @@ -265,15 +256,8 @@ public: | |||||||
|     grid->Broadcast(0,(void *)&offset,sizeof(offset)); |     grid->Broadcast(0,(void *)&offset,sizeof(offset)); | ||||||
|  |  | ||||||
|     uint32_t nersc_csum,scidac_csuma,scidac_csumb; |     uint32_t nersc_csum,scidac_csuma,scidac_csumb; | ||||||
|     if( two_row ) { |  | ||||||
|       Gauge3x2unmunger<fobj2D,sobj> munge; |  | ||||||
|       BinaryIO::writeLatticeObject<vobj,fobj2D>(Umu,file,munge,offset,header.floating_point, |  | ||||||
| 						nersc_csum,scidac_csuma,scidac_csumb); |  | ||||||
|     } else { |  | ||||||
|       GaugeSimpleUnmunger<fobj3D,sobj> munge; |  | ||||||
|     BinaryIO::writeLatticeObject<vobj,fobj3D>(Umu,file,munge,offset,header.floating_point, |     BinaryIO::writeLatticeObject<vobj,fobj3D>(Umu,file,munge,offset,header.floating_point, | ||||||
| 					      nersc_csum,scidac_csuma,scidac_csumb); | 					      nersc_csum,scidac_csuma,scidac_csumb); | ||||||
|     } |  | ||||||
|     header.checksum = nersc_csum; |     header.checksum = nersc_csum; | ||||||
|     if ( grid->IsBoss() ) {  |     if ( grid->IsBoss() ) {  | ||||||
|       writeHeader(header,file); |       writeHeader(header,file); | ||||||
| @@ -306,6 +290,7 @@ public: | |||||||
|     MachineCharacteristics(header); |     MachineCharacteristics(header); | ||||||
|  |  | ||||||
| 	uint64_t offset; | 	uint64_t offset; | ||||||
|  |    | ||||||
| #ifdef RNG_RANLUX | #ifdef RNG_RANLUX | ||||||
|     header.floating_point = std::string("UINT64"); |     header.floating_point = std::string("UINT64"); | ||||||
|     header.data_type      = std::string("RANLUX48"); |     header.data_type      = std::string("RANLUX48"); | ||||||
|   | |||||||
| @@ -27,12 +27,9 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | |||||||
| /*  END LEGAL */ | /*  END LEGAL */ | ||||||
|  |  | ||||||
| #include <Grid/GridCore.h> | #include <Grid/GridCore.h> | ||||||
|  |  | ||||||
| #include <Grid/perfmon/Timer.h> |  | ||||||
| #include <Grid/perfmon/PerfCount.h> | #include <Grid/perfmon/PerfCount.h> | ||||||
| NAMESPACE_BEGIN(Grid); |  | ||||||
|  |  | ||||||
| GridTimePoint theProgramStart = GridClock::now(); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| #define CacheControl(L,O,R) ((PERF_COUNT_HW_CACHE_##L)|(PERF_COUNT_HW_CACHE_OP_##O<<8)| (PERF_COUNT_HW_CACHE_RESULT_##R<<16)) | #define CacheControl(L,O,R) ((PERF_COUNT_HW_CACHE_##L)|(PERF_COUNT_HW_CACHE_OP_##O<<8)| (PERF_COUNT_HW_CACHE_RESULT_##R<<16)) | ||||||
| #define RawConfig(A,B) (A<<8|B) | #define RawConfig(A,B) (A<<8|B) | ||||||
|   | |||||||
| @@ -30,12 +30,6 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | |||||||
| #ifndef GRID_PERFCOUNT_H | #ifndef GRID_PERFCOUNT_H | ||||||
| #define GRID_PERFCOUNT_H | #define GRID_PERFCOUNT_H | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifndef __SSC_START |  | ||||||
| #define __SSC_START |  | ||||||
| #define __SSC_STOP |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #include <sys/time.h> | #include <sys/time.h> | ||||||
| #include <ctime> | #include <ctime> | ||||||
| #include <chrono> | #include <chrono> | ||||||
| @@ -78,9 +72,17 @@ static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, | |||||||
| inline uint64_t cyclecount(void){  | inline uint64_t cyclecount(void){  | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  | #define __SSC_MARK(mark) __asm__ __volatile__ ("movl %0, %%ebx; .byte 0x64, 0x67, 0x90 " ::"i"(mark):"%ebx") | ||||||
|  | #define __SSC_STOP  __SSC_MARK(0x110) | ||||||
|  | #define __SSC_START __SSC_MARK(0x111) | ||||||
|  |  | ||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
|  | #define __SSC_MARK(mark)  | ||||||
|  | #define __SSC_STOP   | ||||||
|  | #define __SSC_START  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * cycle counters arch dependent |  * cycle counters arch dependent | ||||||
|  */ |  */ | ||||||
|   | |||||||
| @@ -35,8 +35,17 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | |||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid) | NAMESPACE_BEGIN(Grid) | ||||||
|  |  | ||||||
| //typedef  std::chrono::system_clock          GridClock; | // Dress the output; use std::chrono | ||||||
| typedef  std::chrono::high_resolution_clock   GridClock; | // C++11 time facilities better? | ||||||
|  | inline double usecond(void) { | ||||||
|  |   struct timeval tv; | ||||||
|  | #ifdef TIMERS_ON | ||||||
|  |   gettimeofday(&tv,NULL); | ||||||
|  | #endif | ||||||
|  |   return 1.0*tv.tv_usec + 1.0e6*tv.tv_sec; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | typedef  std::chrono::system_clock          GridClock; | ||||||
| typedef  std::chrono::time_point<GridClock> GridTimePoint; | typedef  std::chrono::time_point<GridClock> GridTimePoint; | ||||||
|  |  | ||||||
| typedef  std::chrono::seconds               GridSecs; | typedef  std::chrono::seconds               GridSecs; | ||||||
| @@ -44,15 +53,6 @@ typedef  std::chrono::milliseconds          GridMillisecs; | |||||||
| typedef  std::chrono::microseconds          GridUsecs; | typedef  std::chrono::microseconds          GridUsecs; | ||||||
| typedef  std::chrono::microseconds          GridTime; | typedef  std::chrono::microseconds          GridTime; | ||||||
|  |  | ||||||
| extern GridTimePoint theProgramStart; |  | ||||||
| // Dress the output; use std::chrono |  | ||||||
| // C++11 time facilities better? |  | ||||||
| inline double usecond(void) { |  | ||||||
|   auto usecs = std::chrono::duration_cast<GridUsecs>(GridClock::now()-theProgramStart);  |  | ||||||
|   return 1.0*usecs.count(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| inline std::ostream& operator<< (std::ostream & stream, const GridSecs & time) | inline std::ostream& operator<< (std::ostream & stream, const GridSecs & time) | ||||||
| { | { | ||||||
|   stream << time.count()<<" s"; |   stream << time.count()<<" s"; | ||||||
|   | |||||||
| @@ -1,70 +0,0 @@ | |||||||
| #pragma once |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); |  | ||||||
|  |  | ||||||
| #ifdef GRID_TRACING_NVTX |  | ||||||
| #include <nvToolsExt.h> |  | ||||||
| class GridTracer { |  | ||||||
| public: |  | ||||||
|   GridTracer(const char* name) { |  | ||||||
|     nvtxRangePushA(name); |  | ||||||
|   } |  | ||||||
|   ~GridTracer() { |  | ||||||
|     nvtxRangePop(); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| inline void tracePush(const char *name) { nvtxRangePushA(name); } |  | ||||||
| inline void tracePop(const char *name) { nvtxRangePop(); } |  | ||||||
| inline int  traceStart(const char *name) {  } |  | ||||||
| inline void traceStop(int ID) {  } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef GRID_TRACING_ROCTX |  | ||||||
| #include <roctracer/roctx.h> |  | ||||||
| class GridTracer { |  | ||||||
|  public: |  | ||||||
|   GridTracer(const char* name) { |  | ||||||
|     roctxRangePushA(name); |  | ||||||
|     std::cout << "roctxRangePush "<<name<<std::endl; |  | ||||||
|   } |  | ||||||
|   ~GridTracer() { |  | ||||||
|     roctxRangePop(); |  | ||||||
|     std::cout << "roctxRangePop "<<std::endl; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| inline void tracePush(const char *name) { roctxRangePushA(name); } |  | ||||||
| inline void tracePop(const char *name) { roctxRangePop(); } |  | ||||||
| inline int  traceStart(const char *name) { roctxRangeStart(name); } |  | ||||||
| inline void traceStop(int ID) { roctxRangeStop(ID); } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef GRID_TRACING_TIMER |  | ||||||
| class GridTracer { |  | ||||||
|  public: |  | ||||||
|   const char *name; |  | ||||||
|   double elapsed; |  | ||||||
|   GridTracer(const char* _name) { |  | ||||||
|     name = _name; |  | ||||||
|     elapsed=-usecond(); |  | ||||||
|   } |  | ||||||
|   ~GridTracer() { |  | ||||||
|     elapsed+=usecond(); |  | ||||||
|     std::cout << GridLogTracing << name << " took " <<elapsed<< " us" <<std::endl; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| inline void tracePush(const char *name) {  } |  | ||||||
| inline void tracePop(const char *name) {  } |  | ||||||
| inline int  traceStart(const char *name) { return 0; } |  | ||||||
| inline void traceStop(int ID) {  } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef GRID_TRACING_NONE |  | ||||||
| #define GRID_TRACE(name)  |  | ||||||
| inline void tracePush(const char *name) {  } |  | ||||||
| inline void tracePop(const char *name) {  } |  | ||||||
| inline int  traceStart(const char *name) { return 0;  } |  | ||||||
| inline void traceStop(int ID) {  } |  | ||||||
| #else |  | ||||||
| #define GRID_TRACE(name) GridTracer uniq_name_using_macros##__COUNTER__(name); |  | ||||||
| #endif |  | ||||||
| NAMESPACE_END(Grid); |  | ||||||
| @@ -16,12 +16,8 @@ | |||||||
|  |  | ||||||
| #ifdef __NVCC__ | #ifdef __NVCC__ | ||||||
| #pragma push | #pragma push | ||||||
| #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ |  | ||||||
| #pragma nv_diag_suppress declared_but_not_referenced // suppress "function was declared but never referenced warning" |  | ||||||
| #else |  | ||||||
| #pragma diag_suppress declared_but_not_referenced // suppress "function was declared but never referenced warning" | #pragma diag_suppress declared_but_not_referenced // suppress "function was declared but never referenced warning" | ||||||
| #endif | #endif | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #include "pugixml.h" | #include "pugixml.h" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -63,6 +63,7 @@ static constexpr int Ngp=2; // gparity index range | |||||||
| #define ColourIndex  (2) | #define ColourIndex  (2) | ||||||
| #define SpinIndex    (1) | #define SpinIndex    (1) | ||||||
| #define LorentzIndex (0) | #define LorentzIndex (0) | ||||||
|  | #define GparityFlavourIndex (0) | ||||||
|  |  | ||||||
| // Also should make these a named enum type | // Also should make these a named enum type | ||||||
| static constexpr int DaggerNo=0; | static constexpr int DaggerNo=0; | ||||||
| @@ -87,6 +88,8 @@ template<typename T> struct isCoarsened { | |||||||
| template <typename T> using IfCoarsened    = Invoke<std::enable_if< isCoarsened<T>::value,int> > ; | template <typename T> using IfCoarsened    = Invoke<std::enable_if< isCoarsened<T>::value,int> > ; | ||||||
| template <typename T> using IfNotCoarsened = Invoke<std::enable_if<!isCoarsened<T>::value,int> > ; | template <typename T> using IfNotCoarsened = Invoke<std::enable_if<!isCoarsened<T>::value,int> > ; | ||||||
|  |  | ||||||
|  | const int GparityFlavourTensorIndex = 3; //TensorLevel counts from the bottom! | ||||||
|  |  | ||||||
| // ChrisK very keen to add extra space for Gparity doubling. | // ChrisK very keen to add extra space for Gparity doubling. | ||||||
| // | // | ||||||
| // Also add domain wall index, in a way where Wilson operator  | // Also add domain wall index, in a way where Wilson operator  | ||||||
| @@ -110,8 +113,10 @@ template<typename vtype> using iHalfSpinColourVector      = iScalar<iVector<iVec | |||||||
|     template<typename vtype> using iSpinColourSpinColourMatrix  = iScalar<iMatrix<iMatrix<iMatrix<iMatrix<vtype, Nc>, Ns>, Nc>, Ns> >; |     template<typename vtype> using iSpinColourSpinColourMatrix  = iScalar<iMatrix<iMatrix<iMatrix<iMatrix<vtype, Nc>, Ns>, Nc>, Ns> >; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template<typename vtype> using iGparityFlavourVector                = iVector<iScalar<iScalar<vtype> >, Ngp>; | ||||||
| template<typename vtype> using iGparitySpinColourVector       = iVector<iVector<iVector<vtype, Nc>, Ns>, Ngp >; | template<typename vtype> using iGparitySpinColourVector       = iVector<iVector<iVector<vtype, Nc>, Ns>, Ngp >; | ||||||
| template<typename vtype> using iGparityHalfSpinColourVector   = iVector<iVector<iVector<vtype, Nc>, Nhs>, Ngp >; | template<typename vtype> using iGparityHalfSpinColourVector   = iVector<iVector<iVector<vtype, Nc>, Nhs>, Ngp >; | ||||||
|  | template<typename vtype> using iGparityFlavourMatrix = iMatrix<iScalar<iScalar<vtype> >, Ngp>; | ||||||
|  |  | ||||||
| // Spin matrix | // Spin matrix | ||||||
| typedef iSpinMatrix<Complex  >          SpinMatrix; | typedef iSpinMatrix<Complex  >          SpinMatrix; | ||||||
| @@ -176,6 +181,16 @@ typedef iDoubleStoredColourMatrix<vComplex > vDoubleStoredColourMatrix; | |||||||
| typedef iDoubleStoredColourMatrix<vComplexF> vDoubleStoredColourMatrixF; | typedef iDoubleStoredColourMatrix<vComplexF> vDoubleStoredColourMatrixF; | ||||||
| typedef iDoubleStoredColourMatrix<vComplexD> vDoubleStoredColourMatrixD; | typedef iDoubleStoredColourMatrix<vComplexD> vDoubleStoredColourMatrixD; | ||||||
|  |  | ||||||
|  | //G-parity flavour matrix | ||||||
|  | typedef iGparityFlavourMatrix<Complex> GparityFlavourMatrix; | ||||||
|  | typedef iGparityFlavourMatrix<ComplexF> GparityFlavourMatrixF; | ||||||
|  | typedef iGparityFlavourMatrix<ComplexD> GparityFlavourMatrixD; | ||||||
|  |  | ||||||
|  | typedef iGparityFlavourMatrix<vComplex> vGparityFlavourMatrix; | ||||||
|  | typedef iGparityFlavourMatrix<vComplexF> vGparityFlavourMatrixF; | ||||||
|  | typedef iGparityFlavourMatrix<vComplexD> vGparityFlavourMatrixD; | ||||||
|  |  | ||||||
|  |  | ||||||
| // Spin vector | // Spin vector | ||||||
| typedef iSpinVector<Complex >           SpinVector; | typedef iSpinVector<Complex >           SpinVector; | ||||||
| typedef iSpinVector<ComplexF>           SpinVectorF; | typedef iSpinVector<ComplexF>           SpinVectorF; | ||||||
| @@ -221,6 +236,16 @@ typedef iHalfSpinColourVector<vComplex > vHalfSpinColourVector; | |||||||
| typedef iHalfSpinColourVector<vComplexF> vHalfSpinColourVectorF; | typedef iHalfSpinColourVector<vComplexF> vHalfSpinColourVectorF; | ||||||
| typedef iHalfSpinColourVector<vComplexD> vHalfSpinColourVectorD; | typedef iHalfSpinColourVector<vComplexD> vHalfSpinColourVectorD; | ||||||
|  |  | ||||||
|  | //G-parity flavour vector | ||||||
|  | typedef iGparityFlavourVector<Complex >         GparityFlavourVector; | ||||||
|  | typedef iGparityFlavourVector<ComplexF>         GparityFlavourVectorF; | ||||||
|  | typedef iGparityFlavourVector<ComplexD>         GparityFlavourVectorD; | ||||||
|  |  | ||||||
|  | typedef iGparityFlavourVector<vComplex >         vGparityFlavourVector; | ||||||
|  | typedef iGparityFlavourVector<vComplexF>         vGparityFlavourVectorF; | ||||||
|  | typedef iGparityFlavourVector<vComplexD>         vGparityFlavourVectorD; | ||||||
|  |  | ||||||
|  |      | ||||||
| // singlets | // singlets | ||||||
| typedef iSinglet<Complex >         TComplex;     // FIXME This is painful. Tensor singlet complex type. | typedef iSinglet<Complex >         TComplex;     // FIXME This is painful. Tensor singlet complex type. | ||||||
| typedef iSinglet<ComplexF>         TComplexF;    // FIXME This is painful. Tensor singlet complex type. | typedef iSinglet<ComplexF>         TComplexF;    // FIXME This is painful. Tensor singlet complex type. | ||||||
| @@ -451,20 +476,9 @@ template<class vobj> void pokeLorentz(vobj &lhs,const decltype(peekIndex<Lorentz | |||||||
| // Fermion <-> propagator assignements | // Fermion <-> propagator assignements | ||||||
| ////////////////////////////////////////////// | ////////////////////////////////////////////// | ||||||
| //template <class Prop, class Ferm> | //template <class Prop, class Ferm> | ||||||
| #define FAST_FERM_TO_PROP |  | ||||||
| template <class Fimpl> | template <class Fimpl> | ||||||
| void FermToProp(typename Fimpl::PropagatorField &p, const typename Fimpl::FermionField &f, const int s, const int c) | void FermToProp(typename Fimpl::PropagatorField &p, const typename Fimpl::FermionField &f, const int s, const int c) | ||||||
| { | { | ||||||
| #ifdef FAST_FERM_TO_PROP |  | ||||||
|   autoView(p_v,p,CpuWrite); |  | ||||||
|   autoView(f_v,f,CpuRead); |  | ||||||
|   thread_for(idx,p_v.oSites(),{ |  | ||||||
|       for(int ss = 0; ss < Ns; ++ss) { |  | ||||||
|       for(int cc = 0; cc < Fimpl::Dimension; ++cc) { |  | ||||||
| 	p_v[idx]()(ss,s)(cc,c) = f_v[idx]()(ss)(cc); // Propagator sink index is LEFT, suitable for left mult by gauge link (e.g.) |  | ||||||
|       }} |  | ||||||
|     }); |  | ||||||
| #else |  | ||||||
|   for(int j = 0; j < Ns; ++j) |   for(int j = 0; j < Ns; ++j) | ||||||
|     { |     { | ||||||
|       auto pjs = peekSpin(p, j, s); |       auto pjs = peekSpin(p, j, s); | ||||||
| @@ -476,23 +490,12 @@ void FermToProp(typename Fimpl::PropagatorField &p, const typename Fimpl::Fermio | |||||||
| 	} | 	} | ||||||
|       pokeSpin(p, pjs, j, s); |       pokeSpin(p, pjs, j, s); | ||||||
|     } |     } | ||||||
| #endif |  | ||||||
| } | } | ||||||
|      |      | ||||||
| //template <class Prop, class Ferm> | //template <class Prop, class Ferm> | ||||||
| template <class Fimpl> | template <class Fimpl> | ||||||
| void PropToFerm(typename Fimpl::FermionField &f, const typename Fimpl::PropagatorField &p, const int s, const int c) | void PropToFerm(typename Fimpl::FermionField &f, const typename Fimpl::PropagatorField &p, const int s, const int c) | ||||||
| { | { | ||||||
| #ifdef FAST_FERM_TO_PROP |  | ||||||
|   autoView(p_v,p,CpuRead); |  | ||||||
|   autoView(f_v,f,CpuWrite); |  | ||||||
|   thread_for(idx,p_v.oSites(),{ |  | ||||||
|       for(int ss = 0; ss < Ns; ++ss) { |  | ||||||
|       for(int cc = 0; cc < Fimpl::Dimension; ++cc) { |  | ||||||
| 	f_v[idx]()(ss)(cc) = p_v[idx]()(ss,s)(cc,c); // LEFT index is copied across for s,c right index |  | ||||||
|       }} |  | ||||||
|     }); |  | ||||||
| #else |  | ||||||
|   for(int j = 0; j < Ns; ++j) |   for(int j = 0; j < Ns; ++j) | ||||||
|     { |     { | ||||||
|       auto pjs = peekSpin(p, j, s); |       auto pjs = peekSpin(p, j, s); | ||||||
| @@ -504,7 +507,6 @@ void PropToFerm(typename Fimpl::FermionField &f, const typename Fimpl::Propagato | |||||||
| 	} | 	} | ||||||
|       pokeSpin(f, fj, j); |       pokeSpin(f, fj, j); | ||||||
|     } |     } | ||||||
| #endif |  | ||||||
| } | } | ||||||
|      |      | ||||||
| ////////////////////////////////////////////// | ////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -36,7 +36,8 @@ NAMESPACE_BEGIN(Grid); | |||||||
|  |  | ||||||
| // These can move into a params header and be given MacroMagic serialisation | // These can move into a params header and be given MacroMagic serialisation | ||||||
| struct GparityWilsonImplParams { | struct GparityWilsonImplParams { | ||||||
|   Coordinate twists; |   Coordinate twists; //Here the first Nd-1 directions are treated as "spatial", and a twist value of 1 indicates G-parity BCs in that direction.  | ||||||
|  |                      //mu=Nd-1 is assumed to be the time direction and a twist value of 1 indicates antiperiodic BCs | ||||||
|   GparityWilsonImplParams() : twists(Nd, 0) {}; |   GparityWilsonImplParams() : twists(Nd, 0) {}; | ||||||
| }; | }; | ||||||
|    |    | ||||||
| @@ -65,7 +66,8 @@ struct StaggeredImplParams { | |||||||
| 				    RealD, tolerance,  | 				    RealD, tolerance,  | ||||||
| 				    int,   degree,  | 				    int,   degree,  | ||||||
| 				    int,   precision, | 				    int,   precision, | ||||||
| 				    int,   BoundsCheckFreq); | 				    int,   BoundsCheckFreq, | ||||||
|  | 				    RealD, BoundsCheckTol); | ||||||
|      |      | ||||||
|   // MaxIter and tolerance, vectors?? |   // MaxIter and tolerance, vectors?? | ||||||
|      |      | ||||||
| @@ -76,16 +78,62 @@ struct StaggeredImplParams { | |||||||
| 				RealD tol      = 1.0e-8,  | 				RealD tol      = 1.0e-8,  | ||||||
|                            	int _degree    = 10, |                            	int _degree    = 10, | ||||||
| 				int _precision = 64, | 				int _precision = 64, | ||||||
| 				int _BoundsCheckFreq=20) | 				int _BoundsCheckFreq=20, | ||||||
|  | 				double _BoundsCheckTol=1e-6) | ||||||
|       : lo(_lo), |       : lo(_lo), | ||||||
| 	hi(_hi), | 	hi(_hi), | ||||||
| 	MaxIter(_maxit), | 	MaxIter(_maxit), | ||||||
| 	tolerance(tol), | 	tolerance(tol), | ||||||
| 	degree(_degree), | 	degree(_degree), | ||||||
|         precision(_precision), |         precision(_precision), | ||||||
|  |         BoundsCheckFreq(_BoundsCheckFreq), | ||||||
|  |         BoundsCheckTol(_BoundsCheckTol){}; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /*Action parameters for the generalized rational action | ||||||
|  |     The approximation is for (M^dag M)^{1/inv_pow} | ||||||
|  |     where inv_pow is the denominator of the fractional power. | ||||||
|  |     Default inv_pow=2 for square root, making this equivalent to  | ||||||
|  |     the OneFlavourRational action | ||||||
|  |   */ | ||||||
|  |     struct RationalActionParams : Serializable { | ||||||
|  |     GRID_SERIALIZABLE_CLASS_MEMBERS(RationalActionParams,  | ||||||
|  | 				    int, inv_pow,  | ||||||
|  | 				    RealD, lo, //low eigenvalue bound of rational approx | ||||||
|  | 				    RealD, hi, //high eigenvalue bound of rational approx | ||||||
|  | 				    int,   MaxIter,  //maximum iterations in msCG | ||||||
|  | 				    RealD, action_tolerance,  //msCG tolerance in action evaluation | ||||||
|  | 				    int,   action_degree, //rational approx tolerance in action evaluation | ||||||
|  | 				    RealD, md_tolerance,  //msCG tolerance in MD integration | ||||||
|  | 				    int,   md_degree, //rational approx tolerance in MD integration | ||||||
|  | 				    int,   precision, //precision of floating point arithmetic | ||||||
|  | 				    int,   BoundsCheckFreq); //frequency the approximation is tested (with Metropolis degree/tolerance); 0 disables the check | ||||||
|  |   // constructor  | ||||||
|  |   RationalActionParams(int _inv_pow = 2, | ||||||
|  | 		       RealD _lo      = 0.0,  | ||||||
|  | 		       RealD _hi      = 1.0,  | ||||||
|  | 		       int _maxit     = 1000, | ||||||
|  | 		       RealD _action_tolerance      = 1.0e-8,  | ||||||
|  | 		       int _action_degree    = 10, | ||||||
|  | 		       RealD _md_tolerance      = 1.0e-8,  | ||||||
|  | 		       int _md_degree    = 10, | ||||||
|  | 		       int _precision = 64, | ||||||
|  | 		       int _BoundsCheckFreq=20) | ||||||
|  |     : inv_pow(_inv_pow),  | ||||||
|  |       lo(_lo), | ||||||
|  |       hi(_hi), | ||||||
|  |       MaxIter(_maxit), | ||||||
|  |       action_tolerance(_action_tolerance), | ||||||
|  |       action_degree(_action_degree), | ||||||
|  |       md_tolerance(_md_tolerance), | ||||||
|  |       md_degree(_md_degree), | ||||||
|  |       precision(_precision), | ||||||
|       BoundsCheckFreq(_BoundsCheckFreq){}; |       BoundsCheckFreq(_BoundsCheckFreq){}; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -68,16 +68,9 @@ public: | |||||||
|   /////////////////////////////////////////////////////////////// |   /////////////////////////////////////////////////////////////// | ||||||
|   // Support for MADWF tricks |   // Support for MADWF tricks | ||||||
|   /////////////////////////////////////////////////////////////// |   /////////////////////////////////////////////////////////////// | ||||||
|   RealD Mass(void) { return (mass_plus + mass_minus) / 2.0; }; |   RealD Mass(void) { return mass; }; | ||||||
|   RealD MassPlus(void) { return mass_plus; }; |  | ||||||
|   RealD MassMinus(void) { return mass_minus; }; |  | ||||||
|   void  SetMass(RealD _mass) {  |   void  SetMass(RealD _mass) {  | ||||||
|     mass_plus=mass_minus=_mass;  |     mass=_mass;  | ||||||
|     SetCoefficientsInternal(_zolo_hi,_gamma,_b,_c);  // Reset coeffs |  | ||||||
|   } ; |  | ||||||
|   void  SetMass(RealD _mass_plus, RealD _mass_minus) {  |  | ||||||
|     mass_plus=_mass_plus; |  | ||||||
|     mass_minus=_mass_minus; |  | ||||||
|     SetCoefficientsInternal(_zolo_hi,_gamma,_b,_c);  // Reset coeffs |     SetCoefficientsInternal(_zolo_hi,_gamma,_b,_c);  // Reset coeffs | ||||||
|   } ; |   } ; | ||||||
|   void  P(const FermionField &psi, FermionField &chi); |   void  P(const FermionField &psi, FermionField &chi); | ||||||
| @@ -115,7 +108,7 @@ public: | |||||||
|   void   MeooeDag5D    (const FermionField &in, FermionField &out); |   void   MeooeDag5D    (const FermionField &in, FermionField &out); | ||||||
|  |  | ||||||
|   //    protected: |   //    protected: | ||||||
|   RealD mass_plus, mass_minus; |   RealD mass; | ||||||
|  |  | ||||||
|   // Save arguments to SetCoefficientsInternal |   // Save arguments to SetCoefficientsInternal | ||||||
|   Vector<Coeff_t> _gamma; |   Vector<Coeff_t> _gamma; | ||||||
|   | |||||||
| @@ -1,333 +0,0 @@ | |||||||
| /************************************************************************************* |  | ||||||
|  |  | ||||||
|     Grid physics library, www.github.com/paboyle/Grid |  | ||||||
|  |  | ||||||
|     Source file: ./lib/qcd/action/fermion/WilsonCloverFermionImplementation.h |  | ||||||
|  |  | ||||||
|     Copyright (C) 2017 - 2022 |  | ||||||
|  |  | ||||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> |  | ||||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> |  | ||||||
|     Author: Mattia Bruno <mattia.bruno@cern.ch> |  | ||||||
|  |  | ||||||
|     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/Grid.h> |  | ||||||
| #include <Grid/qcd/spin/Dirac.h> |  | ||||||
| #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////// |  | ||||||
| // Standard Clover |  | ||||||
| //   (4+m0) + csw * clover_term |  | ||||||
| // Exp Clover |  | ||||||
| //   (4+m0) * exp(csw/(4+m0) clover_term) |  | ||||||
| //   = (4+m0) + csw * clover_term + ... |  | ||||||
| //////////////////////////////////////////// |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ////////////////////////////////// |  | ||||||
| // Generic Standard Clover |  | ||||||
| ////////////////////////////////// |  | ||||||
|  |  | ||||||
| template<class Impl> |  | ||||||
| class CloverHelpers: public WilsonCloverHelpers<Impl> { |  | ||||||
| public: |  | ||||||
|  |  | ||||||
|   INHERIT_IMPL_TYPES(Impl); |  | ||||||
|   INHERIT_CLOVER_TYPES(Impl); |  | ||||||
|  |  | ||||||
|   typedef WilsonCloverHelpers<Impl> Helpers; |  | ||||||
|  |  | ||||||
|   static void Instantiate(CloverField& CloverTerm, CloverField& CloverTermInv, RealD csw_t, RealD diag_mass) { |  | ||||||
|     GridBase *grid = CloverTerm.Grid(); |  | ||||||
|     CloverTerm += diag_mass; |  | ||||||
|  |  | ||||||
|     int lvol = grid->lSites(); |  | ||||||
|     int DimRep = Impl::Dimension; |  | ||||||
|     { |  | ||||||
|       autoView(CTv,CloverTerm,CpuRead); |  | ||||||
|       autoView(CTIv,CloverTermInv,CpuWrite); |  | ||||||
|       thread_for(site, lvol, { |  | ||||||
|         Coordinate lcoor; |  | ||||||
|         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 SiteClover::scalar_object Qx = Zero(), Qxinv = Zero(); |  | ||||||
|         peekLocalSite(Qx, CTv, lcoor); |  | ||||||
|  |  | ||||||
|         for (int j = 0; j < Ns; j++) |  | ||||||
|           for (int k = 0; k < Ns; k++) |  | ||||||
|             for (int a = 0; a < DimRep; a++) |  | ||||||
|               for (int b = 0; b < DimRep; b++){ |  | ||||||
|                 auto zz =  Qx()(j, k)(a, b); |  | ||||||
|                 EigenCloverOp(a + j * DimRep, b + k * DimRep) = std::complex<double>(zz); |  | ||||||
|               } |  | ||||||
|  |  | ||||||
|         EigenInvCloverOp = EigenCloverOp.inverse(); |  | ||||||
|         for (int j = 0; j < Ns; j++) |  | ||||||
|           for (int k = 0; k < Ns; k++) |  | ||||||
|             for (int a = 0; a < DimRep; a++) |  | ||||||
|               for (int b = 0; b < DimRep; b++) |  | ||||||
|                 Qxinv()(j, k)(a, b) = EigenInvCloverOp(a + j * DimRep, b + k * DimRep); |  | ||||||
|                pokeLocalSite(Qxinv, CTIv, lcoor); |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) { |  | ||||||
|     return Helpers::Cmunu(U, lambda, mu, nu); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ////////////////////////////////// |  | ||||||
| // Generic Exp Clover |  | ||||||
| ////////////////////////////////// |  | ||||||
|  |  | ||||||
| template<class Impl> |  | ||||||
| class ExpCloverHelpers: public WilsonCloverHelpers<Impl> { |  | ||||||
| public: |  | ||||||
|  |  | ||||||
|   INHERIT_IMPL_TYPES(Impl); |  | ||||||
|   INHERIT_CLOVER_TYPES(Impl); |  | ||||||
|  |  | ||||||
|   template <typename vtype> using iImplClover = iScalar<iMatrix<iMatrix<vtype, Impl::Dimension>, Ns>>; |  | ||||||
|   typedef WilsonCloverHelpers<Impl> Helpers; |  | ||||||
|  |  | ||||||
|   // Can this be avoided? |  | ||||||
|   static void IdentityTimesC(const CloverField& in, RealD c) { |  | ||||||
|     int DimRep = Impl::Dimension; |  | ||||||
|  |  | ||||||
|     autoView(in_v, in, AcceleratorWrite); |  | ||||||
|  |  | ||||||
|     accelerator_for(ss, in.Grid()->oSites(), 1, { |  | ||||||
|       for (int sa=0; sa<Ns; sa++) |  | ||||||
|         for (int ca=0; ca<DimRep; ca++) |  | ||||||
|           in_v[ss]()(sa,sa)(ca,ca) = c; |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static int getNMAX(RealD prec, RealD R) { |  | ||||||
|     /* compute stop condition for exponential */ |  | ||||||
|     int NMAX=1; |  | ||||||
|     RealD cond=R*R/2.; |  | ||||||
|  |  | ||||||
|     while (cond*std::exp(R)>prec) { |  | ||||||
|       NMAX++; |  | ||||||
|       cond*=R/(double)(NMAX+1); |  | ||||||
|     } |  | ||||||
|     return NMAX; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static int getNMAX(Lattice<iImplClover<vComplexD>> &t, RealD R) {return getNMAX(1e-12,R);} |  | ||||||
|   static int getNMAX(Lattice<iImplClover<vComplexF>> &t, RealD R) {return getNMAX(1e-6,R);} |  | ||||||
|  |  | ||||||
|   static void Instantiate(CloverField& Clover, CloverField& CloverInv, RealD csw_t, RealD diag_mass) { |  | ||||||
|     GridBase* grid = Clover.Grid(); |  | ||||||
|     CloverField ExpClover(grid); |  | ||||||
|  |  | ||||||
|     int NMAX = getNMAX(Clover, 3.*csw_t/diag_mass); |  | ||||||
|  |  | ||||||
|     Clover *= (1.0/diag_mass); |  | ||||||
|  |  | ||||||
|     // Taylor expansion, slow but generic |  | ||||||
|     // Horner scheme: a0 + a1 x + a2 x^2 + .. = a0 + x (a1 + x(...)) |  | ||||||
|     // qN = cN |  | ||||||
|     // qn = cn + qn+1 X |  | ||||||
|     std::vector<RealD> cn(NMAX+1); |  | ||||||
|     cn[0] = 1.0; |  | ||||||
|     for (int i=1; i<=NMAX; i++) |  | ||||||
|       cn[i] = cn[i-1] / RealD(i); |  | ||||||
|  |  | ||||||
|     ExpClover = Zero(); |  | ||||||
|     IdentityTimesC(ExpClover, cn[NMAX]); |  | ||||||
|     for (int i=NMAX-1; i>=0; i--) |  | ||||||
|       ExpClover = ExpClover * Clover + cn[i]; |  | ||||||
|  |  | ||||||
|     // prepare inverse |  | ||||||
|     CloverInv = (-1.0)*Clover; |  | ||||||
|  |  | ||||||
|     Clover = ExpClover * diag_mass; |  | ||||||
|  |  | ||||||
|     ExpClover = Zero(); |  | ||||||
|     IdentityTimesC(ExpClover, cn[NMAX]); |  | ||||||
|     for (int i=NMAX-1; i>=0; i--) |  | ||||||
|       ExpClover = ExpClover * CloverInv + cn[i]; |  | ||||||
|  |  | ||||||
|     CloverInv = ExpClover * (1.0/diag_mass); |  | ||||||
|  |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) { |  | ||||||
|     assert(0); |  | ||||||
|     return lambda; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ////////////////////////////////// |  | ||||||
| // Compact Standard Clover |  | ||||||
| ////////////////////////////////// |  | ||||||
|  |  | ||||||
|  |  | ||||||
| template<class Impl> |  | ||||||
| class CompactCloverHelpers: public CompactWilsonCloverHelpers<Impl>, |  | ||||||
|                             public WilsonCloverHelpers<Impl> { |  | ||||||
| public: |  | ||||||
|  |  | ||||||
|   INHERIT_IMPL_TYPES(Impl); |  | ||||||
|   INHERIT_CLOVER_TYPES(Impl); |  | ||||||
|   INHERIT_COMPACT_CLOVER_TYPES(Impl); |  | ||||||
|  |  | ||||||
|   typedef WilsonCloverHelpers<Impl> Helpers; |  | ||||||
|   typedef CompactWilsonCloverHelpers<Impl> CompactHelpers; |  | ||||||
|  |  | ||||||
|   static void InstantiateClover(CloverField& Clover, CloverField& CloverInv, RealD csw_t, RealD diag_mass) { |  | ||||||
|     Clover += diag_mass; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static void InvertClover(CloverField& InvClover, |  | ||||||
|                             const CloverDiagonalField& diagonal, |  | ||||||
|                             const CloverTriangleField& triangle, |  | ||||||
|                             CloverDiagonalField&       diagonalInv, |  | ||||||
|                             CloverTriangleField&       triangleInv, |  | ||||||
|                             bool fixedBoundaries) { |  | ||||||
|  |  | ||||||
|     CompactHelpers::Invert(diagonal, triangle, diagonalInv, triangleInv); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // TODO: implement Cmunu for better performances with compact layout, but don't do it |  | ||||||
|   // here, but rather in WilsonCloverHelpers.h -> CompactWilsonCloverHelpers |  | ||||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) { |  | ||||||
|     return Helpers::Cmunu(U, lambda, mu, nu); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| ////////////////////////////////// |  | ||||||
| // Compact Exp Clover |  | ||||||
| ////////////////////////////////// |  | ||||||
|  |  | ||||||
| template<class Impl> |  | ||||||
| class CompactExpCloverHelpers: public CompactWilsonCloverHelpers<Impl> { |  | ||||||
| public: |  | ||||||
|  |  | ||||||
|   INHERIT_IMPL_TYPES(Impl); |  | ||||||
|   INHERIT_CLOVER_TYPES(Impl); |  | ||||||
|   INHERIT_COMPACT_CLOVER_TYPES(Impl); |  | ||||||
|  |  | ||||||
|   template <typename vtype> using iImplClover = iScalar<iMatrix<iMatrix<vtype, Impl::Dimension>, Ns>>; |  | ||||||
|   typedef CompactWilsonCloverHelpers<Impl> CompactHelpers; |  | ||||||
|  |  | ||||||
|   // Can this be avoided? |  | ||||||
|   static void IdentityTimesC(const CloverField& in, RealD c) { |  | ||||||
|     int DimRep = Impl::Dimension; |  | ||||||
|  |  | ||||||
|     autoView(in_v, in, AcceleratorWrite); |  | ||||||
|  |  | ||||||
|     accelerator_for(ss, in.Grid()->oSites(), 1, { |  | ||||||
|       for (int sa=0; sa<Ns; sa++) |  | ||||||
|         for (int ca=0; ca<DimRep; ca++) |  | ||||||
|           in_v[ss]()(sa,sa)(ca,ca) = c; |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static int getNMAX(RealD prec, RealD R) { |  | ||||||
|     /* compute stop condition for exponential */ |  | ||||||
|     int NMAX=1; |  | ||||||
|     RealD cond=R*R/2.; |  | ||||||
|  |  | ||||||
|     while (cond*std::exp(R)>prec) { |  | ||||||
|       NMAX++; |  | ||||||
|       cond*=R/(double)(NMAX+1); |  | ||||||
|     } |  | ||||||
|     return NMAX; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static int getNMAX(Lattice<iImplClover<vComplexD>> &t, RealD R) {return getNMAX(1e-12,R);} |  | ||||||
|   static int getNMAX(Lattice<iImplClover<vComplexF>> &t, RealD R) {return getNMAX(1e-6,R);} |  | ||||||
|  |  | ||||||
|   static void InstantiateClover(CloverField& Clover, CloverField& CloverInv, RealD csw_t, RealD diag_mass) { |  | ||||||
|  |  | ||||||
|     GridBase* grid = Clover.Grid(); |  | ||||||
|     CloverField ExpClover(grid); |  | ||||||
|  |  | ||||||
|     int NMAX = getNMAX(Clover, 3.*csw_t/diag_mass); |  | ||||||
|  |  | ||||||
|     Clover *= (1.0/diag_mass); |  | ||||||
|  |  | ||||||
|     // Taylor expansion, slow but generic |  | ||||||
|     // Horner scheme: a0 + a1 x + a2 x^2 + .. = a0 + x (a1 + x(...)) |  | ||||||
|     // qN = cN |  | ||||||
|     // qn = cn + qn+1 X |  | ||||||
|     std::vector<RealD> cn(NMAX+1); |  | ||||||
|     cn[0] = 1.0; |  | ||||||
|     for (int i=1; i<=NMAX; i++) |  | ||||||
|       cn[i] = cn[i-1] / RealD(i); |  | ||||||
|  |  | ||||||
|     ExpClover = Zero(); |  | ||||||
|     IdentityTimesC(ExpClover, cn[NMAX]); |  | ||||||
|     for (int i=NMAX-1; i>=0; i--) |  | ||||||
|       ExpClover = ExpClover * Clover + cn[i]; |  | ||||||
|  |  | ||||||
|     // prepare inverse |  | ||||||
|     CloverInv = (-1.0)*Clover; |  | ||||||
|  |  | ||||||
|     Clover = ExpClover * diag_mass; |  | ||||||
|  |  | ||||||
|     ExpClover = Zero(); |  | ||||||
|     IdentityTimesC(ExpClover, cn[NMAX]); |  | ||||||
|     for (int i=NMAX-1; i>=0; i--) |  | ||||||
|       ExpClover = ExpClover * CloverInv + cn[i]; |  | ||||||
|  |  | ||||||
|     CloverInv = ExpClover * (1.0/diag_mass); |  | ||||||
|  |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static void InvertClover(CloverField& InvClover, |  | ||||||
|                             const CloverDiagonalField& diagonal, |  | ||||||
|                             const CloverTriangleField& triangle, |  | ||||||
|                             CloverDiagonalField&       diagonalInv, |  | ||||||
|                             CloverTriangleField&       triangleInv, |  | ||||||
|                             bool fixedBoundaries) { |  | ||||||
|  |  | ||||||
|     if (fixedBoundaries) |  | ||||||
|     { |  | ||||||
|       CompactHelpers::Invert(diagonal, triangle, diagonalInv, triangleInv); |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|       CompactHelpers::ConvertLayout(InvClover, diagonalInv, triangleInv); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) { |  | ||||||
|     assert(0); |  | ||||||
|     return lambda; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); |  | ||||||
| @@ -31,7 +31,6 @@ | |||||||
|  |  | ||||||
| #include <Grid/qcd/action/fermion/WilsonCloverTypes.h> | #include <Grid/qcd/action/fermion/WilsonCloverTypes.h> | ||||||
| #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | ||||||
| #include <Grid/qcd/action/fermion/CloverHelpers.h> |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| @@ -86,7 +85,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
| //           + (2 * 1 + 4 * 1/2) triangle parts = 4 triangle parts =  60 complex words per site | //           + (2 * 1 + 4 * 1/2) triangle parts = 4 triangle parts =  60 complex words per site | ||||||
| //                                                                 =  84 complex words per site | //                                                                 =  84 complex words per site | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| class CompactWilsonCloverFermion : public WilsonFermion<Impl>, | class CompactWilsonCloverFermion : public WilsonFermion<Impl>, | ||||||
|                                    public WilsonCloverHelpers<Impl>, |                                    public WilsonCloverHelpers<Impl>, | ||||||
|                                    public CompactWilsonCloverHelpers<Impl> { |                                    public CompactWilsonCloverHelpers<Impl> { | ||||||
| @@ -225,7 +224,7 @@ public: | |||||||
|   RealD csw_t; |   RealD csw_t; | ||||||
|   RealD cF; |   RealD cF; | ||||||
|  |  | ||||||
|   bool fixedBoundaries; |   bool open_boundaries; | ||||||
|  |  | ||||||
|   CloverDiagonalField Diagonal,    DiagonalEven,    DiagonalOdd; |   CloverDiagonalField Diagonal,    DiagonalEven,    DiagonalOdd; | ||||||
|   CloverDiagonalField DiagonalInv, DiagonalInvEven, DiagonalInvOdd; |   CloverDiagonalField DiagonalInv, DiagonalInvEven, DiagonalInvOdd; | ||||||
|   | |||||||
| @@ -138,52 +138,38 @@ typedef WilsonTMFermion<WilsonImplF> WilsonTMFermionF; | |||||||
| typedef WilsonTMFermion<WilsonImplD> WilsonTMFermionD; | typedef WilsonTMFermion<WilsonImplD> WilsonTMFermionD; | ||||||
|  |  | ||||||
| // Clover fermions | // Clover fermions | ||||||
| template <typename WImpl> using WilsonClover = WilsonCloverFermion<WImpl, CloverHelpers<WImpl>>; | typedef WilsonCloverFermion<WilsonImplR> WilsonCloverFermionR; | ||||||
| template <typename WImpl> using WilsonExpClover = WilsonCloverFermion<WImpl, ExpCloverHelpers<WImpl>>; | typedef WilsonCloverFermion<WilsonImplF> WilsonCloverFermionF; | ||||||
|  | typedef WilsonCloverFermion<WilsonImplD> WilsonCloverFermionD; | ||||||
|  |  | ||||||
| typedef WilsonClover<WilsonImplR> WilsonCloverFermionR; | typedef WilsonCloverFermion<WilsonAdjImplR> WilsonCloverAdjFermionR; | ||||||
| typedef WilsonClover<WilsonImplF> WilsonCloverFermionF; | typedef WilsonCloverFermion<WilsonAdjImplF> WilsonCloverAdjFermionF; | ||||||
| typedef WilsonClover<WilsonImplD> WilsonCloverFermionD; | typedef WilsonCloverFermion<WilsonAdjImplD> WilsonCloverAdjFermionD; | ||||||
|  |  | ||||||
| typedef WilsonExpClover<WilsonImplR> WilsonExpCloverFermionR; | typedef WilsonCloverFermion<WilsonTwoIndexSymmetricImplR> WilsonCloverTwoIndexSymmetricFermionR; | ||||||
| typedef WilsonExpClover<WilsonImplF> WilsonExpCloverFermionF; | typedef WilsonCloverFermion<WilsonTwoIndexSymmetricImplF> WilsonCloverTwoIndexSymmetricFermionF; | ||||||
| typedef WilsonExpClover<WilsonImplD> WilsonExpCloverFermionD; | typedef WilsonCloverFermion<WilsonTwoIndexSymmetricImplD> WilsonCloverTwoIndexSymmetricFermionD; | ||||||
|  |  | ||||||
| typedef WilsonClover<WilsonAdjImplR> WilsonCloverAdjFermionR; | typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplR> WilsonCloverTwoIndexAntiSymmetricFermionR; | ||||||
| typedef WilsonClover<WilsonAdjImplF> WilsonCloverAdjFermionF; | typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplF> WilsonCloverTwoIndexAntiSymmetricFermionF; | ||||||
| typedef WilsonClover<WilsonAdjImplD> WilsonCloverAdjFermionD; | typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplD> WilsonCloverTwoIndexAntiSymmetricFermionD; | ||||||
|  |  | ||||||
| typedef WilsonClover<WilsonTwoIndexSymmetricImplR> WilsonCloverTwoIndexSymmetricFermionR; |  | ||||||
| typedef WilsonClover<WilsonTwoIndexSymmetricImplF> WilsonCloverTwoIndexSymmetricFermionF; |  | ||||||
| typedef WilsonClover<WilsonTwoIndexSymmetricImplD> WilsonCloverTwoIndexSymmetricFermionD; |  | ||||||
|  |  | ||||||
| typedef WilsonClover<WilsonTwoIndexAntiSymmetricImplR> WilsonCloverTwoIndexAntiSymmetricFermionR; |  | ||||||
| typedef WilsonClover<WilsonTwoIndexAntiSymmetricImplF> WilsonCloverTwoIndexAntiSymmetricFermionF; |  | ||||||
| typedef WilsonClover<WilsonTwoIndexAntiSymmetricImplD> WilsonCloverTwoIndexAntiSymmetricFermionD; |  | ||||||
|  |  | ||||||
| // Compact Clover fermions | // Compact Clover fermions | ||||||
| template <typename WImpl> using CompactWilsonClover = CompactWilsonCloverFermion<WImpl, CompactCloverHelpers<WImpl>>; | typedef CompactWilsonCloverFermion<WilsonImplR> CompactWilsonCloverFermionR; | ||||||
| template <typename WImpl> using CompactWilsonExpClover = CompactWilsonCloverFermion<WImpl, CompactExpCloverHelpers<WImpl>>; | typedef CompactWilsonCloverFermion<WilsonImplF> CompactWilsonCloverFermionF; | ||||||
|  | typedef CompactWilsonCloverFermion<WilsonImplD> CompactWilsonCloverFermionD; | ||||||
|  |  | ||||||
| typedef CompactWilsonClover<WilsonImplR> CompactWilsonCloverFermionR; | typedef CompactWilsonCloverFermion<WilsonAdjImplR> CompactWilsonCloverAdjFermionR; | ||||||
| typedef CompactWilsonClover<WilsonImplF> CompactWilsonCloverFermionF; | typedef CompactWilsonCloverFermion<WilsonAdjImplF> CompactWilsonCloverAdjFermionF; | ||||||
| typedef CompactWilsonClover<WilsonImplD> CompactWilsonCloverFermionD; | typedef CompactWilsonCloverFermion<WilsonAdjImplD> CompactWilsonCloverAdjFermionD; | ||||||
|  |  | ||||||
| typedef CompactWilsonExpClover<WilsonImplR> CompactWilsonExpCloverFermionR; | typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplR> CompactWilsonCloverTwoIndexSymmetricFermionR; | ||||||
| typedef CompactWilsonExpClover<WilsonImplF> CompactWilsonExpCloverFermionF; | typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplF> CompactWilsonCloverTwoIndexSymmetricFermionF; | ||||||
| typedef CompactWilsonExpClover<WilsonImplD> CompactWilsonExpCloverFermionD; | typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplD> CompactWilsonCloverTwoIndexSymmetricFermionD; | ||||||
|  |  | ||||||
| typedef CompactWilsonClover<WilsonAdjImplR> CompactWilsonCloverAdjFermionR; | typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplR> CompactWilsonCloverTwoIndexAntiSymmetricFermionR; | ||||||
| typedef CompactWilsonClover<WilsonAdjImplF> CompactWilsonCloverAdjFermionF; | typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplF> CompactWilsonCloverTwoIndexAntiSymmetricFermionF; | ||||||
| typedef CompactWilsonClover<WilsonAdjImplD> CompactWilsonCloverAdjFermionD; | typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplD> CompactWilsonCloverTwoIndexAntiSymmetricFermionD; | ||||||
|  |  | ||||||
| typedef CompactWilsonClover<WilsonTwoIndexSymmetricImplR> CompactWilsonCloverTwoIndexSymmetricFermionR; |  | ||||||
| typedef CompactWilsonClover<WilsonTwoIndexSymmetricImplF> CompactWilsonCloverTwoIndexSymmetricFermionF; |  | ||||||
| typedef CompactWilsonClover<WilsonTwoIndexSymmetricImplD> CompactWilsonCloverTwoIndexSymmetricFermionD; |  | ||||||
|  |  | ||||||
| typedef CompactWilsonClover<WilsonTwoIndexAntiSymmetricImplR> CompactWilsonCloverTwoIndexAntiSymmetricFermionR; |  | ||||||
| typedef CompactWilsonClover<WilsonTwoIndexAntiSymmetricImplF> CompactWilsonCloverTwoIndexAntiSymmetricFermionF; |  | ||||||
| typedef CompactWilsonClover<WilsonTwoIndexAntiSymmetricImplD> CompactWilsonCloverTwoIndexAntiSymmetricFermionD; |  | ||||||
|  |  | ||||||
| // Domain Wall fermions | // Domain Wall fermions | ||||||
| typedef DomainWallFermion<WilsonImplR> DomainWallFermionR; | typedef DomainWallFermion<WilsonImplR> DomainWallFermionR; | ||||||
|   | |||||||
| @@ -30,6 +30,18 @@ directory | |||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |   Policy implementation for G-parity boundary conditions | ||||||
|  |  | ||||||
|  |   Rather than treating the gauge field as a flavored field, the Grid implementation of G-parity treats the gauge field as a regular | ||||||
|  |   field with complex conjugate boundary conditions. In order to ensure the second flavor interacts with the conjugate links and the first | ||||||
|  |   with the regular links we overload the functionality of doubleStore, whose purpose is to store the gauge field and the barrel-shifted gauge field | ||||||
|  |   to avoid communicating links when applying the Dirac operator, such that the double-stored field contains also a flavor index which maps to | ||||||
|  |   either the link or the conjugate link. This flavored field is then used by multLink to apply the correct link to a spinor. | ||||||
|  |  | ||||||
|  |   Here the first Nd-1 directions are treated as "spatial", and a twist value of 1 indicates G-parity BCs in that direction.  | ||||||
|  |   mu=Nd-1 is assumed to be the time direction and a twist value of 1 indicates antiperiodic BCs | ||||||
|  |  */ | ||||||
| template <class S, class Representation = FundamentalRepresentation, class Options=CoeffReal> | template <class S, class Representation = FundamentalRepresentation, class Options=CoeffReal> | ||||||
| class GparityWilsonImpl : public ConjugateGaugeImpl<GaugeImplTypes<S, Representation::Dimension> > { | class GparityWilsonImpl : public ConjugateGaugeImpl<GaugeImplTypes<S, Representation::Dimension> > { | ||||||
| public: | public: | ||||||
| @@ -113,7 +125,7 @@ public: | |||||||
|     || ((distance== 1)&&(icoor[direction]==1)) |     || ((distance== 1)&&(icoor[direction]==1)) | ||||||
|     || ((distance==-1)&&(icoor[direction]==0)); |     || ((distance==-1)&&(icoor[direction]==0)); | ||||||
|  |  | ||||||
|     permute_lane = permute_lane && SE->_around_the_world && St.parameters.twists[mmu]; //only if we are going around the world |     permute_lane = permute_lane && SE->_around_the_world && St.parameters.twists[mmu] && mmu < Nd-1; //only if we are going around the world in a spatial direction | ||||||
|  |  | ||||||
|     //Apply the links |     //Apply the links | ||||||
|     int f_upper = permute_lane ? 1 : 0; |     int f_upper = permute_lane ? 1 : 0; | ||||||
| @@ -139,10 +151,10 @@ public: | |||||||
|     assert((distance == 1) || (distance == -1));  // nearest neighbour stencil hard code |     assert((distance == 1) || (distance == -1));  // nearest neighbour stencil hard code | ||||||
|     assert((sl == 1) || (sl == 2)); |     assert((sl == 1) || (sl == 2)); | ||||||
|  |  | ||||||
|     if ( SE->_around_the_world && St.parameters.twists[mmu] ) { |     //If this site is an global boundary site, perform the G-parity flavor twist | ||||||
|  |     if ( mmu < Nd-1 && SE->_around_the_world && St.parameters.twists[mmu] ) { | ||||||
|       if ( sl == 2 ) { |       if ( sl == 2 ) { | ||||||
|         | 	//Only do the twist for lanes on the edge of the physical node | ||||||
| 	ExtractBuffer<sobj> vals(Nsimd); | 	ExtractBuffer<sobj> vals(Nsimd); | ||||||
|  |  | ||||||
| 	extract(chi,vals); | 	extract(chi,vals); | ||||||
| @@ -197,6 +209,19 @@ public: | |||||||
|     reg = memory; |     reg = memory; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   //Poke 'poke_f0' onto flavor 0 and 'poke_f1' onto flavor 1 in direction mu of the doubled gauge field Uds | ||||||
|  |   inline void pokeGparityDoubledGaugeField(DoubledGaugeField &Uds, const GaugeLinkField &poke_f0, const GaugeLinkField &poke_f1, const int mu){ | ||||||
|  |     autoView(poke_f0_v, poke_f0, CpuRead); | ||||||
|  |     autoView(poke_f1_v, poke_f1, CpuRead); | ||||||
|  |     autoView(Uds_v, Uds, CpuWrite); | ||||||
|  |     thread_foreach(ss,poke_f0_v,{ | ||||||
|  | 	Uds_v[ss](0)(mu) = poke_f0_v[ss](); | ||||||
|  | 	Uds_v[ss](1)(mu) = poke_f1_v[ss](); | ||||||
|  |       }); | ||||||
|  |   } | ||||||
|  |      | ||||||
|  |  | ||||||
|   inline void DoubleStore(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu) |   inline void DoubleStore(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu) | ||||||
|   { |   { | ||||||
|     conformable(Uds.Grid(),GaugeGrid); |     conformable(Uds.Grid(),GaugeGrid); | ||||||
| @@ -208,13 +233,18 @@ public: | |||||||
|     |     | ||||||
|     Lattice<iScalar<vInteger> > coor(GaugeGrid); |     Lattice<iScalar<vInteger> > coor(GaugeGrid); | ||||||
|  |  | ||||||
|     for(int mu=0;mu<Nd;mu++){ |     //Here the first Nd-1 directions are treated as "spatial", and a twist value of 1 indicates G-parity BCs in that direction.  | ||||||
|  |     //mu=Nd-1 is assumed to be the time direction and a twist value of 1 indicates antiperiodic BCs         | ||||||
|  |     for(int mu=0;mu<Nd-1;mu++){ | ||||||
|  |  | ||||||
|  |       if( Params.twists[mu] ){ | ||||||
| 	LatticeCoordinate(coor,mu); | 	LatticeCoordinate(coor,mu); | ||||||
|  |       } | ||||||
|            |            | ||||||
|       U     = PeekIndex<LorentzIndex>(Umu,mu); |       U     = PeekIndex<LorentzIndex>(Umu,mu); | ||||||
|       Uconj = conjugate(U); |       Uconj = conjugate(U); | ||||||
|       |       | ||||||
|  |       // Implement the isospin rotation sign on the boundary between f=1 and f=0 | ||||||
|       // This phase could come from a simple bc 1,1,-1,1 .. |       // This phase could come from a simple bc 1,1,-1,1 .. | ||||||
|       int neglink = GaugeGrid->GlobalDimensions()[mu]-1; |       int neglink = GaugeGrid->GlobalDimensions()[mu]-1; | ||||||
|       if ( Params.twists[mu] ) {  |       if ( Params.twists[mu] ) {  | ||||||
| @@ -260,6 +290,38 @@ public: | |||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     { //periodic / antiperiodic temporal BCs | ||||||
|  |       int mu = Nd-1; | ||||||
|  |       int L   = GaugeGrid->GlobalDimensions()[mu]; | ||||||
|  |       int Lmu = L - 1; | ||||||
|  |  | ||||||
|  |       LatticeCoordinate(coor, mu); | ||||||
|  |  | ||||||
|  |       U = PeekIndex<LorentzIndex>(Umu, mu); //Get t-directed links | ||||||
|  |        | ||||||
|  |       GaugeLinkField *Upoke = &U; | ||||||
|  |  | ||||||
|  |       if(Params.twists[mu]){ //antiperiodic | ||||||
|  | 	Utmp =  where(coor == Lmu, -U, U); | ||||||
|  | 	Upoke = &Utmp; | ||||||
|  |       } | ||||||
|  |      | ||||||
|  |       Uconj = conjugate(*Upoke); //second flavor interacts with conjugate links       | ||||||
|  |       pokeGparityDoubledGaugeField(Uds, *Upoke, Uconj, mu); | ||||||
|  |  | ||||||
|  |       //Get the barrel-shifted field | ||||||
|  |       Utmp = adj(Cshift(U, mu, -1)); //is a forward shift! | ||||||
|  |       Upoke = &Utmp; | ||||||
|  |  | ||||||
|  |       if(Params.twists[mu]){ | ||||||
|  | 	U = where(coor == 0, -Utmp, Utmp);  //boundary phase | ||||||
|  | 	Upoke = &U; | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       Uconj = conjugate(*Upoke); | ||||||
|  |       pokeGparityDoubledGaugeField(Uds, *Upoke, Uconj, mu + 4); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|        |        | ||||||
|   inline void InsertForce4D(GaugeField &mat, FermionField &Btilde, FermionField &A, int mu) { |   inline void InsertForce4D(GaugeField &mat, FermionField &Btilde, FermionField &A, int mu) { | ||||||
| @@ -300,27 +362,47 @@ public: | |||||||
|   } |   } | ||||||
|   |   | ||||||
|   inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã, int mu) { |   inline void InsertForce5D(GaugeField &mat, FermionField &Btilde, FermionField Ã, int mu) { | ||||||
|  |  | ||||||
|     int Ls=Btilde.Grid()->_fdimensions[0]; |     int Ls=Btilde.Grid()->_fdimensions[0]; | ||||||
|      |      | ||||||
|     GaugeLinkField tmp(mat.Grid()); |  | ||||||
|     tmp = Zero(); |  | ||||||
|     { |     { | ||||||
|       autoView( tmp_v , tmp, CpuWrite); |       GridBase *GaugeGrid = mat.Grid(); | ||||||
|       autoView( Atilde_v , Atilde, CpuRead); |       Lattice<iScalar<vInteger> > coor(GaugeGrid); | ||||||
|       autoView( Btilde_v , Btilde, CpuRead); |  | ||||||
|       thread_for(ss,tmp.Grid()->oSites(),{ |       if( Params.twists[mu] ){ | ||||||
| 	  for (int s = 0; s < Ls; s++) { | 	LatticeCoordinate(coor,mu); | ||||||
| 	    int sF = s + Ls * ss; |  | ||||||
| 	    auto ttmp = traceIndex<SpinIndex>(outerProduct(Btilde_v[sF], Atilde_v[sF])); |  | ||||||
| 	    tmp_v[ss]() = tmp_v[ss]() + ttmp(0, 0) + conjugate(ttmp(1, 1)); |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       autoView( mat_v , mat, AcceleratorWrite); | ||||||
|  |       autoView( Btilde_v , Btilde, AcceleratorRead); | ||||||
|  |       autoView( Atilde_v , Atilde, AcceleratorRead); | ||||||
|  |       accelerator_for(sss,mat.Grid()->oSites(), FermionField::vector_type::Nsimd(),{	   | ||||||
|  |   	  int sU=sss; | ||||||
|  |   	  typedef decltype(coalescedRead(mat_v[sU](mu)() )) ColorMatrixType; | ||||||
|  |   	  ColorMatrixType sum; | ||||||
|  |   	  zeroit(sum); | ||||||
|  |   	  for(int s=0;s<Ls;s++){ | ||||||
|  |   	    int sF = s+Ls*sU; | ||||||
|  |   	    for(int spn=0;spn<Ns;spn++){ //sum over spin | ||||||
|  | 	      //Flavor 0 | ||||||
|  |   	      auto bb = coalescedRead(Btilde_v[sF](0)(spn) ); //color vector | ||||||
|  |   	      auto aa = coalescedRead(Atilde_v[sF](0)(spn) ); | ||||||
|  |   	      sum = sum + outerProduct(bb,aa); | ||||||
|  |  | ||||||
|  |   	      //Flavor 1 | ||||||
|  |   	      bb = coalescedRead(Btilde_v[sF](1)(spn) ); | ||||||
|  |   	      aa = coalescedRead(Atilde_v[sF](1)(spn) ); | ||||||
|  |   	      sum = sum + conjugate(outerProduct(bb,aa)); | ||||||
|  |   	    } | ||||||
|  |   	  }	     | ||||||
|  |   	  coalescedWrite(mat_v[sU](mu)(), sum); | ||||||
|   	}); |   	}); | ||||||
|     } |     } | ||||||
|     PokeIndex<LorentzIndex>(mat, tmp, mu); |  | ||||||
|     return; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    | ||||||
|  |  | ||||||
|  |    | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef GparityWilsonImpl<vComplex , FundamentalRepresentation,CoeffReal> GparityWilsonImplR;  // Real.. whichever prec | typedef GparityWilsonImpl<vComplex , FundamentalRepresentation,CoeffReal> GparityWilsonImplR;  // Real.. whichever prec | ||||||
|   | |||||||
| @@ -32,7 +32,6 @@ | |||||||
|  |  | ||||||
| #include <Grid/qcd/action/fermion/WilsonCloverTypes.h> | #include <Grid/qcd/action/fermion/WilsonCloverTypes.h> | ||||||
| #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | ||||||
| #include <Grid/qcd/action/fermion/CloverHelpers.h> |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| @@ -52,7 +51,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
| // csw_r = csw_t to recover the isotropic version | // csw_r = csw_t to recover the isotropic version | ||||||
| ////////////////////////////////////////////////////////////////// | ////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| class WilsonCloverFermion : public WilsonFermion<Impl>, | class WilsonCloverFermion : public WilsonFermion<Impl>, | ||||||
|                             public WilsonCloverHelpers<Impl> |                             public WilsonCloverHelpers<Impl> | ||||||
| { | { | ||||||
|   | |||||||
| @@ -209,8 +209,6 @@ public: | |||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////// |  | ||||||
|  |  | ||||||
| template<class Impl> class CompactWilsonCloverHelpers { | template<class Impl> class CompactWilsonCloverHelpers { | ||||||
| public: | public: | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,6 +47,8 @@ class CompactWilsonCloverTypes { | |||||||
| public: | public: | ||||||
|   INHERIT_IMPL_TYPES(Impl); |   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 Nred      = Nc * Nhs;        // 6 | ||||||
|   static constexpr int Nblock    = Nhs;             // 2 |   static constexpr int Nblock    = Nhs;             // 2 | ||||||
|   static constexpr int Ndiagonal = Nred;            // 6 |   static constexpr int Ndiagonal = Nred;            // 6 | ||||||
|   | |||||||
| @@ -117,19 +117,19 @@ public: | |||||||
|     typedef decltype(coalescedRead(*in))    sobj; |     typedef decltype(coalescedRead(*in))    sobj; | ||||||
|     typedef decltype(coalescedRead(*out0)) hsobj; |     typedef decltype(coalescedRead(*out0)) hsobj; | ||||||
|  |  | ||||||
|     constexpr unsigned int Nsimd = vobj::Nsimd(); |     unsigned int Nsimd = vobj::Nsimd(); | ||||||
|     unsigned int mask = Nsimd >> (type + 1); |     unsigned int mask = Nsimd >> (type + 1); | ||||||
|     int lane = acceleratorSIMTlane(Nsimd); |     int lane = acceleratorSIMTlane(Nsimd); | ||||||
|     int j0 = lane &(~mask); // inner coor zero |     int j0 = lane &(~mask); // inner coor zero | ||||||
|     int j1 = lane |(mask) ; // inner coor one |     int j1 = lane |(mask) ; // inner coor one | ||||||
|     const vobj *vp0 = &in[k];  // out0[j] = merge low bit of type from in[k] and in[m]  |     const vobj *vp0 = &in[k]; | ||||||
|     const vobj *vp1 = &in[m];  // out1[j] = merge hi  bit of type from in[k] and in[m] |     const vobj *vp1 = &in[m]; | ||||||
|     const vobj *vp = (lane&mask) ? vp1:vp0;// if my lane has high bit take vp1, low bit take vp0 |     const vobj *vp = (lane&mask) ? vp1:vp0; | ||||||
|     auto sa = coalescedRead(*vp,j0); // lane to read for out 0, NB 50% read coalescing |     auto sa = coalescedRead(*vp,j0); | ||||||
|     auto sb = coalescedRead(*vp,j1); // lane to read for out 1 |     auto sb = coalescedRead(*vp,j1); | ||||||
|     hsobj psa, psb; |     hsobj psa, psb; | ||||||
|     projector::Proj(psa,sa,mu,dag);  // spin project the result0 |     projector::Proj(psa,sa,mu,dag); | ||||||
|     projector::Proj(psb,sb,mu,dag);  // spin project the result1 |     projector::Proj(psb,sb,mu,dag); | ||||||
|     coalescedWrite(out0[j],psa); |     coalescedWrite(out0[j],psa); | ||||||
|     coalescedWrite(out1[j],psb); |     coalescedWrite(out1[j],psb); | ||||||
| #else | #else | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ CayleyFermion5D<Impl>::CayleyFermion5D(GaugeField &_Umu, | |||||||
| 			FiveDimRedBlackGrid, | 			FiveDimRedBlackGrid, | ||||||
| 			FourDimGrid, | 			FourDimGrid, | ||||||
| 			FourDimRedBlackGrid,_M5,p), | 			FourDimRedBlackGrid,_M5,p), | ||||||
|   mass_plus(_mass), mass_minus(_mass) |   mass(_mass) | ||||||
| {  | {  | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -209,8 +209,8 @@ void CayleyFermion5D<Impl>::M5D   (const FermionField &psi, FermionField &chi) | |||||||
| { | { | ||||||
|   int Ls=this->Ls; |   int Ls=this->Ls; | ||||||
|   Vector<Coeff_t> diag (Ls,1.0); |   Vector<Coeff_t> diag (Ls,1.0); | ||||||
|   Vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1]=mass_minus; |   Vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1]=mass; | ||||||
|   Vector<Coeff_t> lower(Ls,-1.0); lower[0]   =mass_plus; |   Vector<Coeff_t> lower(Ls,-1.0); lower[0]   =mass; | ||||||
|   M5D(psi,chi,chi,lower,diag,upper); |   M5D(psi,chi,chi,lower,diag,upper); | ||||||
| } | } | ||||||
| template<class Impl> | template<class Impl> | ||||||
| @@ -220,8 +220,8 @@ void CayleyFermion5D<Impl>::Meooe5D    (const FermionField &psi, FermionField &D | |||||||
|   Vector<Coeff_t> diag = bs; |   Vector<Coeff_t> diag = bs; | ||||||
|   Vector<Coeff_t> upper= cs; |   Vector<Coeff_t> upper= cs; | ||||||
|   Vector<Coeff_t> lower= cs;  |   Vector<Coeff_t> lower= cs;  | ||||||
|   upper[Ls-1]=-mass_minus*upper[Ls-1]; |   upper[Ls-1]=-mass*upper[Ls-1]; | ||||||
|   lower[0]   =-mass_plus*lower[0]; |   lower[0]   =-mass*lower[0]; | ||||||
|   M5D(psi,psi,Din,lower,diag,upper); |   M5D(psi,psi,Din,lower,diag,upper); | ||||||
| } | } | ||||||
| // FIXME Redunant with the above routine; check this and eliminate | // FIXME Redunant with the above routine; check this and eliminate | ||||||
| @@ -235,8 +235,8 @@ template<class Impl> void CayleyFermion5D<Impl>::Meo5D     (const FermionField & | |||||||
|     upper[i]=-ceo[i]; |     upper[i]=-ceo[i]; | ||||||
|     lower[i]=-ceo[i]; |     lower[i]=-ceo[i]; | ||||||
|   } |   } | ||||||
|   upper[Ls-1]=-mass_minus*upper[Ls-1]; |   upper[Ls-1]=-mass*upper[Ls-1]; | ||||||
|   lower[0]   =-mass_plus*lower[0]; |   lower[0]   =-mass*lower[0]; | ||||||
|   M5D(psi,psi,chi,lower,diag,upper); |   M5D(psi,psi,chi,lower,diag,upper); | ||||||
| } | } | ||||||
| template<class Impl> | template<class Impl> | ||||||
| @@ -250,8 +250,8 @@ void CayleyFermion5D<Impl>::Mooee       (const FermionField &psi, FermionField & | |||||||
|     upper[i]=-cee[i]; |     upper[i]=-cee[i]; | ||||||
|     lower[i]=-cee[i]; |     lower[i]=-cee[i]; | ||||||
|   } |   } | ||||||
|   upper[Ls-1]=-mass_minus*upper[Ls-1]; |   upper[Ls-1]=-mass*upper[Ls-1]; | ||||||
|   lower[0]   =-mass_plus*lower[0]; |   lower[0]   =-mass*lower[0]; | ||||||
|   M5D(psi,psi,chi,lower,diag,upper); |   M5D(psi,psi,chi,lower,diag,upper); | ||||||
| } | } | ||||||
| template<class Impl> | template<class Impl> | ||||||
| @@ -266,9 +266,9 @@ void CayleyFermion5D<Impl>::MooeeDag    (const FermionField &psi, FermionField & | |||||||
|     // Assemble the 5d matrix |     // Assemble the 5d matrix | ||||||
|     if ( s==0 ) { |     if ( s==0 ) { | ||||||
|       upper[s] = -cee[s+1] ; |       upper[s] = -cee[s+1] ; | ||||||
|       lower[s] = mass_minus*cee[Ls-1]; |       lower[s] = mass*cee[Ls-1]; | ||||||
|     } else if ( s==(Ls-1)) {  |     } else if ( s==(Ls-1)) {  | ||||||
|       upper[s] = mass_plus*cee[0]; |       upper[s] = mass*cee[0]; | ||||||
|       lower[s] = -cee[s-1]; |       lower[s] = -cee[s-1]; | ||||||
|     } else { |     } else { | ||||||
|       upper[s]=-cee[s+1]; |       upper[s]=-cee[s+1]; | ||||||
| @@ -291,8 +291,8 @@ void CayleyFermion5D<Impl>::M5Ddag (const FermionField &psi, FermionField &chi) | |||||||
|   Vector<Coeff_t> diag(Ls,1.0); |   Vector<Coeff_t> diag(Ls,1.0); | ||||||
|   Vector<Coeff_t> upper(Ls,-1.0); |   Vector<Coeff_t> upper(Ls,-1.0); | ||||||
|   Vector<Coeff_t> lower(Ls,-1.0); |   Vector<Coeff_t> lower(Ls,-1.0); | ||||||
|   upper[Ls-1]=-mass_plus*upper[Ls-1]; |   upper[Ls-1]=-mass*upper[Ls-1]; | ||||||
|   lower[0]   =-mass_minus*lower[0]; |   lower[0]   =-mass*lower[0]; | ||||||
|   M5Ddag(psi,chi,chi,lower,diag,upper); |   M5Ddag(psi,chi,chi,lower,diag,upper); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -307,9 +307,9 @@ void CayleyFermion5D<Impl>::MeooeDag5D    (const FermionField &psi, FermionField | |||||||
|   for (int s=0;s<Ls;s++){ |   for (int s=0;s<Ls;s++){ | ||||||
|     if ( s== 0 ) { |     if ( s== 0 ) { | ||||||
|       upper[s] = cs[s+1]; |       upper[s] = cs[s+1]; | ||||||
|       lower[s] =-mass_minus*cs[Ls-1]; |       lower[s] =-mass*cs[Ls-1]; | ||||||
|     } else if ( s==(Ls-1) ) {  |     } else if ( s==(Ls-1) ) {  | ||||||
|       upper[s] =-mass_plus*cs[0]; |       upper[s] =-mass*cs[0]; | ||||||
|       lower[s] = cs[s-1]; |       lower[s] = cs[s-1]; | ||||||
|     } else {  |     } else {  | ||||||
|       upper[s] = cs[s+1]; |       upper[s] = cs[s+1]; | ||||||
| @@ -552,7 +552,7 @@ void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,Vector<Coeff_t | |||||||
|        |        | ||||||
|       lee[i] =-cee[i+1]/bee[i]; // sub-diag entry on the ith column |       lee[i] =-cee[i+1]/bee[i]; // sub-diag entry on the ith column | ||||||
|        |        | ||||||
|       leem[i]=mass_minus*cee[Ls-1]/bee[0]; |       leem[i]=mass*cee[Ls-1]/bee[0]; | ||||||
|       for(int j=0;j<i;j++) { |       for(int j=0;j<i;j++) { | ||||||
| 	assert(bee[j+1]!=Coeff_t(0.0)); | 	assert(bee[j+1]!=Coeff_t(0.0)); | ||||||
| 	leem[i]*= aee[j]/bee[j+1]; | 	leem[i]*= aee[j]/bee[j+1]; | ||||||
| @@ -560,7 +560,7 @@ void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,Vector<Coeff_t | |||||||
|        |        | ||||||
|       uee[i] =-aee[i]/bee[i];   // up-diag entry on the ith row |       uee[i] =-aee[i]/bee[i];   // up-diag entry on the ith row | ||||||
|        |        | ||||||
|       ueem[i]=mass_plus; |       ueem[i]=mass; | ||||||
|       for(int j=1;j<=i;j++) ueem[i]*= cee[j]/bee[j]; |       for(int j=1;j<=i;j++) ueem[i]*= cee[j]/bee[j]; | ||||||
|       ueem[i]*= aee[0]/bee[0]; |       ueem[i]*= aee[0]/bee[0]; | ||||||
|        |        | ||||||
| @@ -573,7 +573,7 @@ void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,Vector<Coeff_t | |||||||
|   } |   } | ||||||
| 	 | 	 | ||||||
|   {  |   {  | ||||||
|     Coeff_t delta_d=mass_minus*cee[Ls-1]; |     Coeff_t delta_d=mass*cee[Ls-1]; | ||||||
|     for(int j=0;j<Ls-1;j++) { |     for(int j=0;j<Ls-1;j++) { | ||||||
|       assert(bee[j] != Coeff_t(0.0)); |       assert(bee[j] != Coeff_t(0.0)); | ||||||
|       delta_d *= cee[j]/bee[j]; |       delta_d *= cee[j]/bee[j]; | ||||||
| @@ -642,10 +642,6 @@ void CayleyFermion5D<Impl>::ContractConservedCurrent( PropagatorField &q_in_1, | |||||||
| 						      Current curr_type, | 						      Current curr_type, | ||||||
| 						      unsigned int mu) | 						      unsigned int mu) | ||||||
| { | { | ||||||
|  |  | ||||||
|   assert(mass_plus == mass_minus); |  | ||||||
|   RealD mass = mass_plus; |  | ||||||
|    |  | ||||||
| #if (!defined(GRID_HIP)) | #if (!defined(GRID_HIP)) | ||||||
|   Gamma::Algebra Gmu [] = { |   Gamma::Algebra Gmu [] = { | ||||||
|     Gamma::Algebra::GammaX, |     Gamma::Algebra::GammaX, | ||||||
| @@ -781,8 +777,6 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | |||||||
|   assert(mu>=0); |   assert(mu>=0); | ||||||
|   assert(mu<Nd); |   assert(mu<Nd); | ||||||
|  |  | ||||||
|   assert(mass_plus == mass_minus); |  | ||||||
|   RealD mass = mass_plus; |  | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
|   int tshift = (mu == Nd-1) ? 1 : 0; |   int tshift = (mu == Nd-1) ? 1 : 0; | ||||||
|   | |||||||
| @@ -32,10 +32,9 @@ | |||||||
| #include <Grid/qcd/spin/Dirac.h> | #include <Grid/qcd/spin/Dirac.h> | ||||||
| #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> | #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| CompactWilsonCloverFermion<Impl, CloverHelpers>::CompactWilsonCloverFermion(GaugeField& _Umu, | CompactWilsonCloverFermion<Impl>::CompactWilsonCloverFermion(GaugeField& _Umu, | ||||||
|                                                              GridCartesian& Fgrid, |                                                              GridCartesian& Fgrid, | ||||||
|                                                              GridRedBlackCartesian& Hgrid, |                                                              GridRedBlackCartesian& Hgrid, | ||||||
|                                                              const RealD _mass, |                                                              const RealD _mass, | ||||||
| @@ -48,7 +47,7 @@ CompactWilsonCloverFermion<Impl, CloverHelpers>::CompactWilsonCloverFermion(Gaug | |||||||
|   , csw_r(_csw_r) |   , csw_r(_csw_r) | ||||||
|   , csw_t(_csw_t) |   , csw_t(_csw_t) | ||||||
|   , cF(_cF) |   , cF(_cF) | ||||||
|   , fixedBoundaries(impl_p.boundary_phases[Nd-1] == 0.0) |   , open_boundaries(impl_p.boundary_phases[Nd-1] == 0.0) | ||||||
|   , Diagonal(&Fgrid),        Triangle(&Fgrid) |   , Diagonal(&Fgrid),        Triangle(&Fgrid) | ||||||
|   , DiagonalEven(&Hgrid),    TriangleEven(&Hgrid) |   , DiagonalEven(&Hgrid),    TriangleEven(&Hgrid) | ||||||
|   , DiagonalOdd(&Hgrid),     TriangleOdd(&Hgrid) |   , DiagonalOdd(&Hgrid),     TriangleOdd(&Hgrid) | ||||||
| @@ -59,85 +58,80 @@ CompactWilsonCloverFermion<Impl, CloverHelpers>::CompactWilsonCloverFermion(Gaug | |||||||
|   , BoundaryMask(&Fgrid) |   , BoundaryMask(&Fgrid) | ||||||
|   , BoundaryMaskEven(&Hgrid), BoundaryMaskOdd(&Hgrid) |   , BoundaryMaskEven(&Hgrid), BoundaryMaskOdd(&Hgrid) | ||||||
| { | { | ||||||
|   assert(Nd == 4 && Nc == 3 && Ns == 4 && Impl::Dimension == 3); |  | ||||||
|  |  | ||||||
|   csw_r *= 0.5; |   csw_r *= 0.5; | ||||||
|   csw_t *= 0.5; |   csw_t *= 0.5; | ||||||
|   if (clover_anisotropy.isAnisotropic) |   if (clover_anisotropy.isAnisotropic) | ||||||
|     csw_r /= clover_anisotropy.xi_0; |     csw_r /= clover_anisotropy.xi_0; | ||||||
|  |  | ||||||
|   ImportGauge(_Umu); |   ImportGauge(_Umu); | ||||||
|   if (fixedBoundaries) { |   if (open_boundaries) | ||||||
|     this->BoundaryMaskEven.Checkerboard() = Even; |  | ||||||
|     this->BoundaryMaskOdd.Checkerboard() = Odd; |  | ||||||
|     CompactHelpers::SetupMasks(this->BoundaryMask, this->BoundaryMaskEven, this->BoundaryMaskOdd); |     CompactHelpers::SetupMasks(this->BoundaryMask, this->BoundaryMaskEven, this->BoundaryMaskOdd); | ||||||
| } | } | ||||||
| } |  | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Dhop(const FermionField& in, FermionField& out, int dag) { | void CompactWilsonCloverFermion<Impl>::Dhop(const FermionField& in, FermionField& out, int dag) { | ||||||
|   WilsonBase::Dhop(in, out, dag); |   WilsonBase::Dhop(in, out, dag); | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::DhopOE(const FermionField& in, FermionField& out, int dag) { | void CompactWilsonCloverFermion<Impl>::DhopOE(const FermionField& in, FermionField& out, int dag) { | ||||||
|   WilsonBase::DhopOE(in, out, dag); |   WilsonBase::DhopOE(in, out, dag); | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::DhopEO(const FermionField& in, FermionField& out, int dag) { | void CompactWilsonCloverFermion<Impl>::DhopEO(const FermionField& in, FermionField& out, int dag) { | ||||||
|   WilsonBase::DhopEO(in, out, dag); |   WilsonBase::DhopEO(in, out, dag); | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::DhopDir(const FermionField& in, FermionField& out, int dir, int disp) { | void CompactWilsonCloverFermion<Impl>::DhopDir(const FermionField& in, FermionField& out, int dir, int disp) { | ||||||
|   WilsonBase::DhopDir(in, out, dir, disp); |   WilsonBase::DhopDir(in, out, dir, disp); | ||||||
|   if(this->fixedBoundaries) ApplyBoundaryMask(out); |   if(this->open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::DhopDirAll(const FermionField& in, std::vector<FermionField>& out) { | void CompactWilsonCloverFermion<Impl>::DhopDirAll(const FermionField& in, std::vector<FermionField>& out) { | ||||||
|   WilsonBase::DhopDirAll(in, out); |   WilsonBase::DhopDirAll(in, out); | ||||||
|   if(this->fixedBoundaries) { |   if(this->open_boundaries) { | ||||||
|     for(auto& o : out) ApplyBoundaryMask(o); |     for(auto& o : out) ApplyBoundaryMask(o); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::M(const FermionField& in, FermionField& out) { | void CompactWilsonCloverFermion<Impl>::M(const FermionField& in, FermionField& out) { | ||||||
|   out.Checkerboard() = in.Checkerboard(); |   out.Checkerboard() = in.Checkerboard(); | ||||||
|   WilsonBase::Dhop(in, out, DaggerNo); // call base to save applying bc |   WilsonBase::Dhop(in, out, DaggerNo); // call base to save applying bc | ||||||
|   Mooee(in, Tmp); |   Mooee(in, Tmp); | ||||||
|   axpy(out, 1.0, out, Tmp); |   axpy(out, 1.0, out, Tmp); | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Mdag(const FermionField& in, FermionField& out) { | void CompactWilsonCloverFermion<Impl>::Mdag(const FermionField& in, FermionField& out) { | ||||||
|   out.Checkerboard() = in.Checkerboard(); |   out.Checkerboard() = in.Checkerboard(); | ||||||
|   WilsonBase::Dhop(in, out, DaggerYes);  // call base to save applying bc |   WilsonBase::Dhop(in, out, DaggerYes);  // call base to save applying bc | ||||||
|   MooeeDag(in, Tmp); |   MooeeDag(in, Tmp); | ||||||
|   axpy(out, 1.0, out, Tmp); |   axpy(out, 1.0, out, Tmp); | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Meooe(const FermionField& in, FermionField& out) { | void CompactWilsonCloverFermion<Impl>::Meooe(const FermionField& in, FermionField& out) { | ||||||
|   WilsonBase::Meooe(in, out); |   WilsonBase::Meooe(in, out); | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MeooeDag(const FermionField& in, FermionField& out) { | void CompactWilsonCloverFermion<Impl>::MeooeDag(const FermionField& in, FermionField& out) { | ||||||
|   WilsonBase::MeooeDag(in, out); |   WilsonBase::MeooeDag(in, out); | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Mooee(const FermionField& in, FermionField& out) { | void CompactWilsonCloverFermion<Impl>::Mooee(const FermionField& in, FermionField& out) { | ||||||
|   if(in.Grid()->_isCheckerBoarded) { |   if(in.Grid()->_isCheckerBoarded) { | ||||||
|     if(in.Checkerboard() == Odd) { |     if(in.Checkerboard() == Odd) { | ||||||
|       MooeeInternal(in, out, DiagonalOdd, TriangleOdd); |       MooeeInternal(in, out, DiagonalOdd, TriangleOdd); | ||||||
| @@ -147,16 +141,16 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::Mooee(const FermionField& | |||||||
|   } else { |   } else { | ||||||
|     MooeeInternal(in, out, Diagonal, Triangle); |     MooeeInternal(in, out, Diagonal, Triangle); | ||||||
|   } |   } | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeDag(const FermionField& in, FermionField& out) { | void CompactWilsonCloverFermion<Impl>::MooeeDag(const FermionField& in, FermionField& out) { | ||||||
|   Mooee(in, out); // blocks are hermitian |   Mooee(in, out); // blocks are hermitian | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInv(const FermionField& in, FermionField& out) { | void CompactWilsonCloverFermion<Impl>::MooeeInv(const FermionField& in, FermionField& out) { | ||||||
|   if(in.Grid()->_isCheckerBoarded) { |   if(in.Grid()->_isCheckerBoarded) { | ||||||
|     if(in.Checkerboard() == Odd) { |     if(in.Checkerboard() == Odd) { | ||||||
|       MooeeInternal(in, out, DiagonalInvOdd, TriangleInvOdd); |       MooeeInternal(in, out, DiagonalInvOdd, TriangleInvOdd); | ||||||
| @@ -166,27 +160,27 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInv(const FermionFiel | |||||||
|   } else { |   } else { | ||||||
|     MooeeInternal(in, out, DiagonalInv, TriangleInv); |     MooeeInternal(in, out, DiagonalInv, TriangleInv); | ||||||
|   } |   } | ||||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); |   if(open_boundaries) ApplyBoundaryMask(out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInvDag(const FermionField& in, FermionField& out) { | void CompactWilsonCloverFermion<Impl>::MooeeInvDag(const FermionField& in, FermionField& out) { | ||||||
|   MooeeInv(in, out); // blocks are hermitian |   MooeeInv(in, out); // blocks are hermitian | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Mdir(const FermionField& in, FermionField& out, int dir, int disp) { | void CompactWilsonCloverFermion<Impl>::Mdir(const FermionField& in, FermionField& out, int dir, int disp) { | ||||||
|   DhopDir(in, out, dir, disp); |   DhopDir(in, out, dir, disp); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MdirAll(const FermionField& in, std::vector<FermionField>& out) { | void CompactWilsonCloverFermion<Impl>::MdirAll(const FermionField& in, std::vector<FermionField>& out) { | ||||||
|   DhopDirAll(in, out); |   DhopDirAll(in, out); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField& force, const FermionField& X, const FermionField& Y, int dag) { | void CompactWilsonCloverFermion<Impl>::MDeriv(GaugeField& force, const FermionField& X, const FermionField& Y, int dag) { | ||||||
|   assert(!fixedBoundaries); // TODO check for changes required for open bc |   assert(!open_boundaries); // TODO check for changes required for open bc | ||||||
|  |  | ||||||
|   // NOTE: code copied from original clover term |   // NOTE: code copied from original clover term | ||||||
|   conformable(X.Grid(), Y.Grid()); |   conformable(X.Grid(), Y.Grid()); | ||||||
| @@ -257,7 +251,7 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField& force, | |||||||
|       } |       } | ||||||
|       PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked |       PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked | ||||||
|       Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok |       Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok | ||||||
|       force_mu -= factor*CloverHelpers::Cmunu(U, lambda, mu, nu);   // checked |       force_mu -= factor*Helpers::Cmunu(U, lambda, mu, nu);   // checked | ||||||
|       count++; |       count++; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -267,18 +261,18 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField& force, | |||||||
|   force += clover_force; |   force += clover_force; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | void CompactWilsonCloverFermion<Impl>::MooDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | ||||||
|   assert(0); |   assert(0); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MeeDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | void CompactWilsonCloverFermion<Impl>::MeeDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | ||||||
|   assert(0); |   assert(0); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInternal(const FermionField&        in, | void CompactWilsonCloverFermion<Impl>::MooeeInternal(const FermionField&        in, | ||||||
|                     FermionField&              out, |                     FermionField&              out, | ||||||
|                     const CloverDiagonalField& diagonal, |                     const CloverDiagonalField& diagonal, | ||||||
|                     const CloverTriangleField& triangle) { |                     const CloverTriangleField& triangle) { | ||||||
| @@ -291,8 +285,8 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInternal(const Fermio | |||||||
|   CompactHelpers::MooeeKernel(diagonal.oSites(), 1, in, out, diagonal, triangle); |   CompactHelpers::MooeeKernel(diagonal.oSites(), 1, in, out, diagonal, triangle); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeField& _Umu) { | void CompactWilsonCloverFermion<Impl>::ImportGauge(const GaugeField& _Umu) { | ||||||
|   // NOTE: parts copied from original implementation |   // NOTE: parts copied from original implementation | ||||||
|  |  | ||||||
|   // Import gauge into base class |   // Import gauge into base class | ||||||
| @@ -305,7 +299,6 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeFie | |||||||
|   GridBase* grid = _Umu.Grid(); |   GridBase* grid = _Umu.Grid(); | ||||||
|   typename Impl::GaugeLinkField Bx(grid), By(grid), Bz(grid), Ex(grid), Ey(grid), Ez(grid); |   typename Impl::GaugeLinkField Bx(grid), By(grid), Bz(grid), Ex(grid), Ey(grid), Ez(grid); | ||||||
|   CloverField TmpOriginal(grid); |   CloverField TmpOriginal(grid); | ||||||
|   CloverField TmpInverse(grid); |  | ||||||
|  |  | ||||||
|   // Compute the field strength terms mu>nu |   // Compute the field strength terms mu>nu | ||||||
|   double t2 = usecond(); |   double t2 = usecond(); | ||||||
| @@ -325,30 +318,22 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeFie | |||||||
|   TmpOriginal += Helpers::fillCloverXT(Ex) * csw_t; |   TmpOriginal += Helpers::fillCloverXT(Ex) * csw_t; | ||||||
|   TmpOriginal += Helpers::fillCloverYT(Ey) * csw_t; |   TmpOriginal += Helpers::fillCloverYT(Ey) * csw_t; | ||||||
|   TmpOriginal += Helpers::fillCloverZT(Ez) * csw_t; |   TmpOriginal += Helpers::fillCloverZT(Ez) * csw_t; | ||||||
|  |   TmpOriginal += this->diag_mass; | ||||||
|   // Instantiate the clover term |  | ||||||
|   // - In case of the standard clover the mass term is added |  | ||||||
|   // - In case of the exponential clover the clover term is exponentiated |  | ||||||
|   double t4 = usecond(); |  | ||||||
|   CloverHelpers::InstantiateClover(TmpOriginal, TmpInverse, csw_t, this->diag_mass); |  | ||||||
|  |  | ||||||
|   // Convert the data layout of the clover term |   // Convert the data layout of the clover term | ||||||
|   double t5 = usecond(); |   double t4 = usecond(); | ||||||
|   CompactHelpers::ConvertLayout(TmpOriginal, Diagonal, Triangle); |   CompactHelpers::ConvertLayout(TmpOriginal, Diagonal, Triangle); | ||||||
|  |  | ||||||
|   // Modify the clover term at the temporal boundaries in case of open boundary conditions |   // Possible modify the boundary values | ||||||
|   double t6 = usecond(); |   double t5 = usecond(); | ||||||
|   if(fixedBoundaries) CompactHelpers::ModifyBoundaries(Diagonal, Triangle, csw_t, cF, this->diag_mass); |   if(open_boundaries) CompactHelpers::ModifyBoundaries(Diagonal, Triangle, csw_t, cF, this->diag_mass); | ||||||
|  |  | ||||||
|   // Invert the Clover term |   // Invert the clover term in the improved layout | ||||||
|   // In case of the exponential clover with (anti-)periodic boundary conditions exp(-Clover) saved |   double t6 = usecond(); | ||||||
|   // in TmpInverse can be used. In all other cases the clover term has to be explictly inverted. |   CompactHelpers::Invert(Diagonal, Triangle, DiagonalInv, TriangleInv); | ||||||
|   // TODO: For now this inversion is explictly done on the CPU |  | ||||||
|   double t7 = usecond(); |  | ||||||
|   CloverHelpers::InvertClover(TmpInverse, Diagonal, Triangle, DiagonalInv, TriangleInv, fixedBoundaries); |  | ||||||
|  |  | ||||||
|   // Fill the remaining clover fields |   // Fill the remaining clover fields | ||||||
|   double t8 = usecond(); |   double t7 = usecond(); | ||||||
|   pickCheckerboard(Even, DiagonalEven,    Diagonal); |   pickCheckerboard(Even, DiagonalEven,    Diagonal); | ||||||
|   pickCheckerboard(Even, TriangleEven,    Triangle); |   pickCheckerboard(Even, TriangleEven,    Triangle); | ||||||
|   pickCheckerboard(Odd,  DiagonalOdd,     Diagonal); |   pickCheckerboard(Odd,  DiagonalOdd,     Diagonal); | ||||||
| @@ -359,19 +344,20 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeFie | |||||||
|   pickCheckerboard(Odd,  TriangleInvOdd,  TriangleInv); |   pickCheckerboard(Odd,  TriangleInvOdd,  TriangleInv); | ||||||
|  |  | ||||||
|   // Report timings |   // Report timings | ||||||
|   double t9 = usecond(); |   double t8 = usecond(); | ||||||
|  | #if 0 | ||||||
|   std::cout << GridLogDebug << "CompactWilsonCloverFermion::ImportGauge timings:" << std::endl; |   std::cout << GridLogMessage << "CompactWilsonCloverFermion::ImportGauge timings:" | ||||||
|   std::cout << GridLogDebug << "WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 << std::endl; |             << " WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 | ||||||
|   std::cout << GridLogDebug << "allocations =                " << (t2 - t1) / 1e6 << std::endl; |             << ", allocations = "               << (t2 - t1) / 1e6 | ||||||
|   std::cout << GridLogDebug << "field strength =             " << (t3 - t2) / 1e6 << std::endl; |             << ", field strength = "            << (t3 - t2) / 1e6 | ||||||
|   std::cout << GridLogDebug << "fill clover =                " << (t4 - t3) / 1e6 << std::endl; |             << ", fill clover = "               << (t4 - t3) / 1e6 | ||||||
|   std::cout << GridLogDebug << "instantiate clover =         " << (t5 - t4) / 1e6 << std::endl; |             << ", convert = "                   << (t5 - t4) / 1e6 | ||||||
|   std::cout << GridLogDebug << "convert layout =             " << (t6 - t5) / 1e6 << std::endl; |             << ", boundaries = "                << (t6 - t5) / 1e6 | ||||||
|   std::cout << GridLogDebug << "modify boundaries =          " << (t7 - t6) / 1e6 << std::endl; |             << ", inversions = "                << (t7 - t6) / 1e6 | ||||||
|   std::cout << GridLogDebug << "invert clover =              " << (t8 - t7) / 1e6 << std::endl; |             << ", pick cbs = "                  << (t8 - t7) / 1e6 | ||||||
|   std::cout << GridLogDebug << "pick cbs =                   " << (t9 - t8) / 1e6 << std::endl; |             << ", total = "                     << (t8 - t0) / 1e6 | ||||||
|   std::cout << GridLogDebug << "total =                      " << (t9 - t0) / 1e6 << std::endl; |             << std::endl; | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|   | |||||||
| @@ -34,8 +34,8 @@ | |||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template<class Impl> | ||||||
| WilsonCloverFermion<Impl, CloverHelpers>::WilsonCloverFermion(GaugeField&                         _Umu, | WilsonCloverFermion<Impl>::WilsonCloverFermion(GaugeField&                         _Umu, | ||||||
|                                                GridCartesian&                      Fgrid, |                                                GridCartesian&                      Fgrid, | ||||||
|                                                GridRedBlackCartesian&              Hgrid, |                                                GridRedBlackCartesian&              Hgrid, | ||||||
|                                                const RealD                         _mass, |                                                const RealD                         _mass, | ||||||
| @@ -74,8 +74,8 @@ WilsonCloverFermion<Impl, CloverHelpers>::WilsonCloverFermion(GaugeField& | |||||||
| } | } | ||||||
|  |  | ||||||
| // *NOT* EO | // *NOT* EO | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::M(const FermionField &in, FermionField &out) | void WilsonCloverFermion<Impl>::M(const FermionField &in, FermionField &out) | ||||||
| { | { | ||||||
|   FermionField temp(out.Grid()); |   FermionField temp(out.Grid()); | ||||||
|  |  | ||||||
| @@ -89,8 +89,8 @@ void WilsonCloverFermion<Impl, CloverHelpers>::M(const FermionField &in, Fermion | |||||||
|   out += temp; |   out += temp; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::Mdag(const FermionField &in, FermionField &out) | void WilsonCloverFermion<Impl>::Mdag(const FermionField &in, FermionField &out) | ||||||
| { | { | ||||||
|   FermionField temp(out.Grid()); |   FermionField temp(out.Grid()); | ||||||
|  |  | ||||||
| @@ -104,8 +104,8 @@ void WilsonCloverFermion<Impl, CloverHelpers>::Mdag(const FermionField &in, Ferm | |||||||
|   out += temp; |   out += temp; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeField &_Umu) | void WilsonCloverFermion<Impl>::ImportGauge(const GaugeField &_Umu) | ||||||
| { | { | ||||||
|   double t0 = usecond(); |   double t0 = usecond(); | ||||||
|   WilsonFermion<Impl>::ImportGauge(_Umu); |   WilsonFermion<Impl>::ImportGauge(_Umu); | ||||||
| @@ -131,11 +131,47 @@ void WilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeField &_Um | |||||||
|   CloverTerm += Helpers::fillCloverXT(Ex) * csw_t; |   CloverTerm += Helpers::fillCloverXT(Ex) * csw_t; | ||||||
|   CloverTerm += Helpers::fillCloverYT(Ey) * csw_t; |   CloverTerm += Helpers::fillCloverYT(Ey) * csw_t; | ||||||
|   CloverTerm += Helpers::fillCloverZT(Ez) * csw_t; |   CloverTerm += Helpers::fillCloverZT(Ez) * csw_t; | ||||||
|  |   CloverTerm += diag_mass; | ||||||
|  |  | ||||||
|   double t4 = usecond(); |   double t4 = usecond(); | ||||||
|   CloverHelpers::Instantiate(CloverTerm, CloverTermInv, csw_t, this->diag_mass); |   int lvol = _Umu.Grid()->lSites(); | ||||||
|  |   int DimRep = Impl::Dimension; | ||||||
|  |  | ||||||
|   double t5 = usecond(); |   double t5 = usecond(); | ||||||
|  |   { | ||||||
|  |     autoView(CTv,CloverTerm,CpuRead); | ||||||
|  |     autoView(CTIv,CloverTermInv,CpuWrite); | ||||||
|  |     thread_for(site, lvol, { | ||||||
|  |       Coordinate lcoor; | ||||||
|  |       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 SiteClover::scalar_object Qx = Zero(), Qxinv = Zero(); | ||||||
|  |       peekLocalSite(Qx, CTv, lcoor); | ||||||
|  |       //if (csw!=0){ | ||||||
|  |       for (int j = 0; j < Ns; j++) | ||||||
|  | 	for (int k = 0; k < Ns; k++) | ||||||
|  | 	  for (int a = 0; a < DimRep; a++) | ||||||
|  | 	    for (int b = 0; b < DimRep; b++){ | ||||||
|  | 	      auto zz =  Qx()(j, k)(a, b); | ||||||
|  | 	      EigenCloverOp(a + j * DimRep, b + k * DimRep) = std::complex<double>(zz); | ||||||
|  | 	    } | ||||||
|  |       //   if (site==0) std::cout << "site =" << site << "\n" << EigenCloverOp << std::endl; | ||||||
|  |        | ||||||
|  |       EigenInvCloverOp = EigenCloverOp.inverse(); | ||||||
|  |       //std::cout << EigenInvCloverOp << std::endl; | ||||||
|  |       for (int j = 0; j < Ns; j++) | ||||||
|  | 	for (int k = 0; k < Ns; k++) | ||||||
|  | 	  for (int a = 0; a < DimRep; a++) | ||||||
|  | 	    for (int b = 0; b < DimRep; b++) | ||||||
|  | 	      Qxinv()(j, k)(a, b) = EigenInvCloverOp(a + j * DimRep, b + k * DimRep); | ||||||
|  |       //    if (site==0) std::cout << "site =" << site << "\n" << EigenInvCloverOp << std::endl; | ||||||
|  |       //  } | ||||||
|  |       pokeLocalSite(Qxinv, CTIv, lcoor); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   double t6 = usecond(); | ||||||
|   // Separate the even and odd parts |   // Separate the even and odd parts | ||||||
|   pickCheckerboard(Even, CloverTermEven, CloverTerm); |   pickCheckerboard(Even, CloverTermEven, CloverTerm); | ||||||
|   pickCheckerboard(Odd, CloverTermOdd, CloverTerm); |   pickCheckerboard(Odd, CloverTermOdd, CloverTerm); | ||||||
| @@ -148,44 +184,48 @@ void WilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeField &_Um | |||||||
|  |  | ||||||
|   pickCheckerboard(Even, CloverTermInvDagEven, adj(CloverTermInv)); |   pickCheckerboard(Even, CloverTermInvDagEven, adj(CloverTermInv)); | ||||||
|   pickCheckerboard(Odd, CloverTermInvDagOdd, adj(CloverTermInv)); |   pickCheckerboard(Odd, CloverTermInvDagOdd, adj(CloverTermInv)); | ||||||
|   double t6 = usecond(); |   double t7 = usecond(); | ||||||
|  |  | ||||||
|   std::cout << GridLogDebug << "WilsonCloverFermion::ImportGauge timings:" << std::endl; | #if 0 | ||||||
|   std::cout << GridLogDebug << "WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 << std::endl; |   std::cout << GridLogMessage << "WilsonCloverFermion::ImportGauge timings:" | ||||||
|   std::cout << GridLogDebug << "allocations =                " << (t2 - t1) / 1e6 << std::endl; |             << " WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 | ||||||
|   std::cout << GridLogDebug << "field strength =             " << (t3 - t2) / 1e6 << std::endl; |             << ", allocations = "               << (t2 - t1) / 1e6 | ||||||
|   std::cout << GridLogDebug << "fill clover =                " << (t4 - t3) / 1e6 << std::endl; |             << ", field strength = "            << (t3 - t2) / 1e6 | ||||||
|   std::cout << GridLogDebug << "instantiation =              " << (t5 - t4) / 1e6 << std::endl; |             << ", fill clover = "               << (t4 - t3) / 1e6 | ||||||
|   std::cout << GridLogDebug << "pick cbs =                   " << (t6 - t5) / 1e6 << std::endl; |             << ", misc = "                      << (t5 - t4) / 1e6 | ||||||
|   std::cout << GridLogDebug << "total =                      " << (t6 - t0) / 1e6 << std::endl; |             << ", inversions = "                << (t6 - t5) / 1e6 | ||||||
|  |             << ", pick cbs = "                  << (t7 - t6) / 1e6 | ||||||
|  |             << ", total = "                     << (t7 - t0) / 1e6 | ||||||
|  |             << std::endl; | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::Mooee(const FermionField &in, FermionField &out) | void WilsonCloverFermion<Impl>::Mooee(const FermionField &in, FermionField &out) | ||||||
| { | { | ||||||
|   this->MooeeInternal(in, out, DaggerNo, InverseNo); |   this->MooeeInternal(in, out, DaggerNo, InverseNo); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooeeDag(const FermionField &in, FermionField &out) | void WilsonCloverFermion<Impl>::MooeeDag(const FermionField &in, FermionField &out) | ||||||
| { | { | ||||||
|   this->MooeeInternal(in, out, DaggerYes, InverseNo); |   this->MooeeInternal(in, out, DaggerYes, InverseNo); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooeeInv(const FermionField &in, FermionField &out) | void WilsonCloverFermion<Impl>::MooeeInv(const FermionField &in, FermionField &out) | ||||||
| { | { | ||||||
|   this->MooeeInternal(in, out, DaggerNo, InverseYes); |   this->MooeeInternal(in, out, DaggerNo, InverseYes); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooeeInvDag(const FermionField &in, FermionField &out) | void WilsonCloverFermion<Impl>::MooeeInvDag(const FermionField &in, FermionField &out) | ||||||
| { | { | ||||||
|   this->MooeeInternal(in, out, DaggerYes, InverseYes); |   this->MooeeInternal(in, out, DaggerYes, InverseYes); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooeeInternal(const FermionField &in, FermionField &out, int dag, int inv) | void WilsonCloverFermion<Impl>::MooeeInternal(const FermionField &in, FermionField &out, int dag, int inv) | ||||||
| { | { | ||||||
|   out.Checkerboard() = in.Checkerboard(); |   out.Checkerboard() = in.Checkerboard(); | ||||||
|   CloverField *Clover; |   CloverField *Clover; | ||||||
| @@ -238,8 +278,8 @@ void WilsonCloverFermion<Impl, CloverHelpers>::MooeeInternal(const FermionField | |||||||
| } // MooeeInternal | } // MooeeInternal | ||||||
|  |  | ||||||
| // Derivative parts unpreconditioned pseudofermions | // Derivative parts unpreconditioned pseudofermions | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField &force, const FermionField &X, const FermionField &Y, int dag) | void WilsonCloverFermion<Impl>::MDeriv(GaugeField &force, const FermionField &X, const FermionField &Y, int dag) | ||||||
| { | { | ||||||
|   conformable(X.Grid(), Y.Grid()); |   conformable(X.Grid(), Y.Grid()); | ||||||
|   conformable(X.Grid(), force.Grid()); |   conformable(X.Grid(), force.Grid()); | ||||||
| @@ -309,7 +349,7 @@ void WilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField &force, const F | |||||||
|       } |       } | ||||||
|       PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked |       PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked | ||||||
|       Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok |       Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok | ||||||
|       force_mu -= factor*CloverHelpers::Cmunu(U, lambda, mu, nu);                   // checked |       force_mu -= factor*Helpers::Cmunu(U, lambda, mu, nu);                   // checked | ||||||
|       count++; |       count++; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -320,15 +360,15 @@ void WilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField &force, const F | |||||||
| } | } | ||||||
|  |  | ||||||
| // Derivative parts | // Derivative parts | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooDeriv(GaugeField &mat, const FermionField &X, const FermionField &Y, int dag) | void WilsonCloverFermion<Impl>::MooDeriv(GaugeField &mat, const FermionField &X, const FermionField &Y, int dag) | ||||||
| { | { | ||||||
|   assert(0); |   assert(0); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Derivative parts | // Derivative parts | ||||||
| template<class Impl, class CloverHelpers> | template <class Impl> | ||||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MeeDeriv(GaugeField &mat, const FermionField &U, const FermionField &V, int dag) | void WilsonCloverFermion<Impl>::MeeDeriv(GaugeField &mat, const FermionField &U, const FermionField &V, int dag) | ||||||
| { | { | ||||||
|   assert(0); // not implemented yet |   assert(0); // not implemented yet | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,13 +4,12 @@ Grid physics library, www.github.com/paboyle/Grid | |||||||
|  |  | ||||||
| Source file: ./lib/qcd/action/fermion/WilsonFermion.cc | Source file: ./lib/qcd/action/fermion/WilsonFermion.cc | ||||||
|  |  | ||||||
| Copyright (C) 2022 | Copyright (C) 2015 | ||||||
|  |  | ||||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
| Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
| Author: Fabian Joswig <fabian.joswig@ed.ac.uk> |  | ||||||
|  |  | ||||||
| This program is free software; you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | ||||||
| @@ -600,47 +599,11 @@ void WilsonFermion<Impl>::ContractConservedCurrent(PropagatorField &q_in_1, | |||||||
|                                                    Current curr_type, |                                                    Current curr_type, | ||||||
|                                                    unsigned int mu) |                                                    unsigned int mu) | ||||||
| { | { | ||||||
|   if(curr_type != Current::Vector) |  | ||||||
|   { |  | ||||||
|     std::cout << GridLogError << "Only the conserved vector current is implemented so far." << std::endl; |  | ||||||
|     exit(1); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   Gamma g5(Gamma::Algebra::Gamma5); |   Gamma g5(Gamma::Algebra::Gamma5); | ||||||
|   conformable(_grid, q_in_1.Grid()); |   conformable(_grid, q_in_1.Grid()); | ||||||
|   conformable(_grid, q_in_2.Grid()); |   conformable(_grid, q_in_2.Grid()); | ||||||
|   conformable(_grid, q_out.Grid()); |   conformable(_grid, q_out.Grid()); | ||||||
|   auto UGrid= this->GaugeGrid(); |   assert(0); | ||||||
|  |  | ||||||
|   PropagatorField tmp_shifted(UGrid); |  | ||||||
|   PropagatorField g5Lg5(UGrid); |  | ||||||
|   PropagatorField R(UGrid); |  | ||||||
|   PropagatorField gmuR(UGrid); |  | ||||||
|  |  | ||||||
|     Gamma::Algebra Gmu [] = { |  | ||||||
|     Gamma::Algebra::GammaX, |  | ||||||
|     Gamma::Algebra::GammaY, |  | ||||||
|     Gamma::Algebra::GammaZ, |  | ||||||
|     Gamma::Algebra::GammaT, |  | ||||||
|   }; |  | ||||||
|   Gamma gmu=Gamma(Gmu[mu]); |  | ||||||
|  |  | ||||||
|   g5Lg5=g5*q_in_1*g5; |  | ||||||
|   tmp_shifted=Cshift(q_in_2,mu,1); |  | ||||||
|   Impl::multLinkField(R,this->Umu,tmp_shifted,mu); |  | ||||||
|   gmuR=gmu*R; |  | ||||||
|  |  | ||||||
|   q_out=adj(g5Lg5)*R; |  | ||||||
|   q_out-=adj(g5Lg5)*gmuR; |  | ||||||
|  |  | ||||||
|   tmp_shifted=Cshift(q_in_1,mu,1); |  | ||||||
|   Impl::multLinkField(g5Lg5,this->Umu,tmp_shifted,mu); |  | ||||||
|   g5Lg5=g5*g5Lg5*g5; |  | ||||||
|   R=q_in_2; |  | ||||||
|   gmuR=gmu*R; |  | ||||||
|  |  | ||||||
|   q_out-=adj(g5Lg5)*R; |  | ||||||
|   q_out-=adj(g5Lg5)*gmuR; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -654,51 +617,9 @@ void WilsonFermion<Impl>::SeqConservedCurrent(PropagatorField &q_in, | |||||||
|                                               unsigned int tmax, |                                               unsigned int tmax, | ||||||
| 					      ComplexField &lattice_cmplx) | 					      ComplexField &lattice_cmplx) | ||||||
| { | { | ||||||
|   if(curr_type != Current::Vector) |  | ||||||
|   { |  | ||||||
|     std::cout << GridLogError << "Only the conserved vector current is implemented so far." << std::endl; |  | ||||||
|     exit(1); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   int tshift = (mu == Nd-1) ? 1 : 0; |  | ||||||
|   unsigned int LLt    = GridDefaultLatt()[Tp]; |  | ||||||
|   conformable(_grid, q_in.Grid()); |   conformable(_grid, q_in.Grid()); | ||||||
|   conformable(_grid, q_out.Grid()); |   conformable(_grid, q_out.Grid()); | ||||||
|   auto UGrid= this->GaugeGrid(); |   assert(0); | ||||||
|  |  | ||||||
|   PropagatorField tmp(UGrid); |  | ||||||
|   PropagatorField Utmp(UGrid); |  | ||||||
|   PropagatorField L(UGrid); |  | ||||||
|   PropagatorField zz (UGrid); |  | ||||||
|   zz=Zero(); |  | ||||||
|   LatticeInteger lcoor(UGrid); LatticeCoordinate(lcoor,Nd-1); |  | ||||||
|  |  | ||||||
|     Gamma::Algebra Gmu [] = { |  | ||||||
|     Gamma::Algebra::GammaX, |  | ||||||
|     Gamma::Algebra::GammaY, |  | ||||||
|     Gamma::Algebra::GammaZ, |  | ||||||
|     Gamma::Algebra::GammaT, |  | ||||||
|   }; |  | ||||||
|   Gamma gmu=Gamma(Gmu[mu]); |  | ||||||
|  |  | ||||||
|   tmp = Cshift(q_in,mu,1); |  | ||||||
|   Impl::multLinkField(Utmp,this->Umu,tmp,mu); |  | ||||||
|   tmp = ( Utmp*lattice_cmplx - gmu*Utmp*lattice_cmplx ); // Forward hop |  | ||||||
|   tmp = where((lcoor>=tmin),tmp,zz); // Mask the time |  | ||||||
|   q_out = where((lcoor<=tmax),tmp,zz); // Position of current complicated |  | ||||||
|  |  | ||||||
|   tmp = q_in *lattice_cmplx; |  | ||||||
|   tmp = Cshift(tmp,mu,-1); |  | ||||||
|   Impl::multLinkField(Utmp,this->Umu,tmp,mu+Nd); // Adjoint link |  | ||||||
|   tmp = -( Utmp + gmu*Utmp ); |  | ||||||
|   // 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); |  | ||||||
|   } |  | ||||||
|   q_out+= where((lcoor<=tmax+tshift),tmp,zz); // Position of current complicated |  | ||||||
| } | } | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|   | |||||||
| @@ -459,7 +459,11 @@ void WilsonKernels<Impl>::DhopKernel(int Opt,StencilImpl &st,  DoubledGaugeField | |||||||
|  |  | ||||||
|    if( interior && exterior ) { |    if( interior && exterior ) { | ||||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSite); return;} |      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSite); return;} | ||||||
|  | #ifdef SYCL_HACK      | ||||||
|  |      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL_TMP(HandDhopSiteSycl);    return; } | ||||||
|  | #else | ||||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSite);    return;} |      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSite);    return;} | ||||||
|  | #endif      | ||||||
| #ifndef GRID_CUDA | #ifndef GRID_CUDA | ||||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSite);    return;} |      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSite);    return;} | ||||||
| #endif | #endif | ||||||
| @@ -470,7 +474,6 @@ void WilsonKernels<Impl>::DhopKernel(int Opt,StencilImpl &st,  DoubledGaugeField | |||||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteInt);    return;} |      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteInt);    return;} | ||||||
| #endif | #endif | ||||||
|    } else if( exterior ) { |    } else if( exterior ) { | ||||||
|      acceleratorFenceComputeStream(); |  | ||||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSiteExt); return;} |      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSiteExt); return;} | ||||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSiteExt);    return;} |      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSiteExt);    return;} | ||||||
| #ifndef GRID_CUDA | #ifndef GRID_CUDA | ||||||
| @@ -496,19 +499,17 @@ void WilsonKernels<Impl>::DhopKernel(int Opt,StencilImpl &st,  DoubledGaugeField | |||||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteDag);     return;} |      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteDag);     return;} | ||||||
| #endif | #endif | ||||||
|    } else if( interior ) { |    } else if( interior ) { | ||||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALLNB(GenericDhopSiteDagInt); return;} |      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSiteDagInt); return;} | ||||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALLNB(HandDhopSiteDagInt);    return;} |      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSiteDagInt);    return;} | ||||||
| #ifndef GRID_CUDA | #ifndef GRID_CUDA | ||||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteDagInt);     return;} |      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteDagInt);     return;} | ||||||
| #endif | #endif | ||||||
|    } else if( exterior ) { |    } else if( exterior ) { | ||||||
|      acceleratorFenceComputeStream(); |  | ||||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSiteDagExt); return;} |      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSiteDagExt); return;} | ||||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSiteDagExt);    return;} |      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSiteDagExt);    return;} | ||||||
| #ifndef GRID_CUDA | #ifndef GRID_CUDA | ||||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteDagExt);     return;} |      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteDagExt);     return;} | ||||||
| #endif | #endif | ||||||
|      acceleratorFenceComputeStream(); |  | ||||||
|    } |    } | ||||||
|    assert(0 && " Kernel optimisation case not covered "); |    assert(0 && " Kernel optimisation case not covered "); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> |     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|     Author: Guido Cossu <guido.cossu@ed.ac.uk> |     Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> |     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||||
|     Author: Mattia Bruno <mattia.bruno@cern.ch> |  | ||||||
|  |  | ||||||
|     This program is free software; you can redistribute it and/or modify |     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 |     it under the terms of the GNU General Public License as published by | ||||||
| @@ -33,12 +32,10 @@ | |||||||
| #include <Grid/qcd/spin/Dirac.h> | #include <Grid/qcd/spin/Dirac.h> | ||||||
| #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> | #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> | ||||||
| #include <Grid/qcd/action/fermion/implementation/CompactWilsonCloverFermionImplementation.h> | #include <Grid/qcd/action/fermion/implementation/CompactWilsonCloverFermionImplementation.h> | ||||||
| #include <Grid/qcd/action/fermion/CloverHelpers.h> |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| #include "impl.h" | #include "impl.h" | ||||||
| template class CompactWilsonCloverFermion<IMPLEMENTATION, CompactCloverHelpers<IMPLEMENTATION>>;  | template class CompactWilsonCloverFermion<IMPLEMENTATION>;  | ||||||
| template class CompactWilsonCloverFermion<IMPLEMENTATION, CompactExpCloverHelpers<IMPLEMENTATION>>;  |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|   | |||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -8,7 +8,6 @@ | |||||||
|  |  | ||||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> |     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|     Author: Guido Cossu <guido.cossu@ed.ac.uk> |     Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||||
|     Author: Mattia Bruno <mattia.bruno@cern.ch> |  | ||||||
|  |  | ||||||
|     This program is free software; you can redistribute it and/or modify |     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 |     it under the terms of the GNU General Public License as published by | ||||||
| @@ -32,12 +31,10 @@ | |||||||
| #include <Grid/qcd/spin/Dirac.h> | #include <Grid/qcd/spin/Dirac.h> | ||||||
| #include <Grid/qcd/action/fermion/WilsonCloverFermion.h> | #include <Grid/qcd/action/fermion/WilsonCloverFermion.h> | ||||||
| #include <Grid/qcd/action/fermion/implementation/WilsonCloverFermionImplementation.h> | #include <Grid/qcd/action/fermion/implementation/WilsonCloverFermionImplementation.h> | ||||||
| #include <Grid/qcd/action/fermion/CloverHelpers.h> |  | ||||||
|  |  | ||||||
| NAMESPACE_BEGIN(Grid); | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
| #include "impl.h" | #include "impl.h" | ||||||
| template class WilsonCloverFermion<IMPLEMENTATION, CloverHelpers<IMPLEMENTATION>>;  | template class WilsonCloverFermion<IMPLEMENTATION>;  | ||||||
| template class WilsonCloverFermion<IMPLEMENTATION, ExpCloverHelpers<IMPLEMENTATION>>;  |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|   | |||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -1 +0,0 @@ | |||||||
| ../WilsonKernelsInstantiation.cc.master |  | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||||
|  |  | ||||||
|  | Copyright (C) 2015, 2020 | ||||||
|  |  | ||||||
|  | Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||||
|  | Author: paboyle <paboyle@ph.ed.ac.uk> | ||||||
|  | Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||||
|  |  | ||||||
|  | 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/qcd/action/fermion/FermionCore.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||||
|  |  | ||||||
|  | #ifndef AVX512 | ||||||
|  | #ifndef QPX | ||||||
|  | #ifndef A64FX | ||||||
|  | #ifndef A64FXFIXEDSIZE | ||||||
|  | #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | #include "impl.h" | ||||||
|  | template class WilsonKernels<IMPLEMENTATION>; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
| @@ -18,10 +18,6 @@ WILSON_IMPL_LIST=" \ | |||||||
| 	   GparityWilsonImplF \ | 	   GparityWilsonImplF \ | ||||||
| 	   GparityWilsonImplD " | 	   GparityWilsonImplD " | ||||||
|  |  | ||||||
| COMPACT_WILSON_IMPL_LIST=" \ |  | ||||||
| 	   WilsonImplF \ |  | ||||||
| 	   WilsonImplD " |  | ||||||
|  |  | ||||||
| DWF_IMPL_LIST=" \ | DWF_IMPL_LIST=" \ | ||||||
| 	   WilsonImplF \ | 	   WilsonImplF \ | ||||||
| 	   WilsonImplD \ | 	   WilsonImplD \ | ||||||
| @@ -44,7 +40,7 @@ EOF | |||||||
|  |  | ||||||
| done | done | ||||||
|  |  | ||||||
| CC_LIST="WilsonCloverFermionInstantiation WilsonFermionInstantiation WilsonKernelsInstantiation WilsonTMFermionInstantiation" | CC_LIST="WilsonCloverFermionInstantiation CompactWilsonCloverFermionInstantiation WilsonFermionInstantiation WilsonKernelsInstantiation WilsonTMFermionInstantiation" | ||||||
|  |  | ||||||
| for impl in $WILSON_IMPL_LIST | for impl in $WILSON_IMPL_LIST | ||||||
| do | do | ||||||
| @@ -54,16 +50,6 @@ do | |||||||
| done | done | ||||||
| done | done | ||||||
|  |  | ||||||
| CC_LIST="CompactWilsonCloverFermionInstantiation" |  | ||||||
|  |  | ||||||
| for impl in $COMPACT_WILSON_IMPL_LIST |  | ||||||
| do |  | ||||||
| for f in $CC_LIST |  | ||||||
| do |  | ||||||
|   ln -f -s ../$f.cc.master $impl/$f$impl.cc |  | ||||||
| done |  | ||||||
| done |  | ||||||
|  |  | ||||||
| CC_LIST=" \ | CC_LIST=" \ | ||||||
|   CayleyFermion5DInstantiation \ |   CayleyFermion5DInstantiation \ | ||||||
|   ContinuedFractionFermion5DInstantiation \ |   ContinuedFractionFermion5DInstantiation \ | ||||||
|   | |||||||
| @@ -69,6 +69,11 @@ public: | |||||||
|     return PeriodicBC::ShiftStaple(Link,mu); |     return PeriodicBC::ShiftStaple(Link,mu); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //Same as Cshift for periodic BCs | ||||||
|  |   static inline GaugeLinkField CshiftLink(const GaugeLinkField &Link, int mu, int shift){ | ||||||
|  |     return PeriodicBC::CshiftLink(Link,mu,shift); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   static inline bool isPeriodicGaugeField(void) { return true; } |   static inline bool isPeriodicGaugeField(void) { return true; } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -110,6 +115,11 @@ public: | |||||||
|       return PeriodicBC::CovShiftBackward(Link, mu, field); |       return PeriodicBC::CovShiftBackward(Link, mu, field); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //If mu is a conjugate BC direction | ||||||
|  |   //Out(x) = U^dag_\mu(x-mu)  | x_\mu != 0 | ||||||
|  |   //       = U^T_\mu(L-1)  | x_\mu == 0 | ||||||
|  |   //else | ||||||
|  |   //Out(x) = U^dag_\mu(x-mu mod L) | ||||||
|   static inline GaugeLinkField |   static inline GaugeLinkField | ||||||
|   CovShiftIdentityBackward(const GaugeLinkField &Link, int mu) |   CovShiftIdentityBackward(const GaugeLinkField &Link, int mu) | ||||||
|   { |   { | ||||||
| @@ -129,6 +139,13 @@ public: | |||||||
|       return PeriodicBC::CovShiftIdentityForward(Link,mu); |       return PeriodicBC::CovShiftIdentityForward(Link,mu); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   //If mu is a conjugate BC direction | ||||||
|  |   //Out(x) = S_\mu(x+mu)  | x_\mu != L-1 | ||||||
|  |   //       = S*_\mu(x+mu)  | x_\mu == L-1 | ||||||
|  |   //else | ||||||
|  |   //Out(x) = S_\mu(x+mu mod L) | ||||||
|  |   //Note: While this is used for Staples it is also applicable for shifting gauge links or gauge transformation matrices | ||||||
|   static inline GaugeLinkField ShiftStaple(const GaugeLinkField &Link, int mu) |   static inline GaugeLinkField ShiftStaple(const GaugeLinkField &Link, int mu) | ||||||
|   { |   { | ||||||
|     assert(_conjDirs.size() == Nd); |     assert(_conjDirs.size() == Nd); | ||||||
| @@ -138,6 +155,27 @@ public: | |||||||
|       return PeriodicBC::ShiftStaple(Link,mu); |       return PeriodicBC::ShiftStaple(Link,mu); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //Boundary-aware C-shift of gauge links / gauge transformation matrices | ||||||
|  |   //For conjugate BC direction | ||||||
|  |   //shift = 1 | ||||||
|  |   //Out(x) = U_\mu(x+\hat\mu)  | x_\mu != L-1 | ||||||
|  |   //       = U*_\mu(0)  | x_\mu == L-1 | ||||||
|  |   //shift = -1 | ||||||
|  |   //Out(x) = U_\mu(x-mu)  | x_\mu != 0 | ||||||
|  |   //       = U*_\mu(L-1)  | x_\mu == 0 | ||||||
|  |   //else | ||||||
|  |   //shift = 1 | ||||||
|  |   //Out(x) = U_\mu(x+\hat\mu mod L) | ||||||
|  |   //shift = -1 | ||||||
|  |   //Out(x) = U_\mu(x-\hat\mu mod L) | ||||||
|  |   static inline GaugeLinkField CshiftLink(const GaugeLinkField &Link, int mu, int shift){ | ||||||
|  |     assert(_conjDirs.size() == Nd); | ||||||
|  |     if(_conjDirs[mu])  | ||||||
|  |       return ConjugateBC::CshiftLink(Link,mu,shift); | ||||||
|  |     else      | ||||||
|  |       return PeriodicBC::CshiftLink(Link,mu,shift); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   static inline void       setDirections(std::vector<int> &conjDirs) { _conjDirs=conjDirs; } |   static inline void       setDirections(std::vector<int> &conjDirs) { _conjDirs=conjDirs; } | ||||||
|   static inline std::vector<int> getDirections(void) { return _conjDirs; } |   static inline std::vector<int> getDirections(void) { return _conjDirs; } | ||||||
|   static inline bool isPeriodicGaugeField(void) { return false; } |   static inline bool isPeriodicGaugeField(void) { return false; } | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
|      |      | ||||||
|     typedef Lattice<SiteLink>  LinkField; |     typedef Lattice<SiteLink>  LinkField; | ||||||
|     typedef Lattice<SiteField> Field; |     typedef Lattice<SiteField> Field; | ||||||
|     typedef LinkField          ComplexField; |     typedef Field              ComplexField; | ||||||
|   }; |   }; | ||||||
|    |    | ||||||
|   typedef QedGImpl<vComplex> QedGImplR; |   typedef QedGImpl<vComplex> QedGImplR; | ||||||
|   | |||||||
| @@ -40,13 +40,66 @@ NAMESPACE_BEGIN(Grid); | |||||||
|       X=X-Y; |       X=X-Y; | ||||||
|       RealD Nd = norm2(X); |       RealD Nd = norm2(X); | ||||||
|       std::cout << "************************* "<<std::endl; |       std::cout << "************************* "<<std::endl; | ||||||
|       std::cout << " noise                         = "<<Nx<<std::endl; |       std::cout << " | noise |^2                         = "<<Nx<<std::endl; | ||||||
|       std::cout << " (MdagM^-1/2)^2  noise         = "<<Nz<<std::endl; |       std::cout << " | (MdagM^-1/2)^2  noise |^2         = "<<Nz<<std::endl; | ||||||
|       std::cout << " MdagM (MdagM^-1/2)^2  noise   = "<<Ny<<std::endl; |       std::cout << " | MdagM (MdagM^-1/2)^2  noise |^2   = "<<Ny<<std::endl; | ||||||
|       std::cout << " noise - MdagM (MdagM^-1/2)^2  noise   = "<<Nd<<std::endl; |       std::cout << " | noise - MdagM (MdagM^-1/2)^2  noise |^2  = "<<Nd<<std::endl; | ||||||
|  |       std::cout << " | noise - MdagM (MdagM^-1/2)^2  noise|/|noise| = " << std::sqrt(Nd/Nx) << std::endl; | ||||||
|       std::cout << "************************* "<<std::endl; |       std::cout << "************************* "<<std::endl; | ||||||
|       assert( (std::sqrt(Nd/Nx)<tol) && " InverseSqrtBoundsCheck "); |       assert( (std::sqrt(Nd/Nx)<tol) && " InverseSqrtBoundsCheck "); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /* For a HermOp = M^dag M, check the approximation of  HermOp^{-1/inv_pow} | ||||||
|  |        by computing   |X -    HermOp * [ Hermop^{-1/inv_pow} ]^{inv_pow} X|  < tol   | ||||||
|  |        for noise X (aka GaussNoise). | ||||||
|  |        ApproxNegPow should be the rational approximation for   X^{-1/inv_pow} | ||||||
|  |     */ | ||||||
|  |     template<class Field> void InversePowerBoundsCheck(int inv_pow, | ||||||
|  | 						       int MaxIter,double tol, | ||||||
|  | 						       LinearOperatorBase<Field> &HermOp, | ||||||
|  | 						       Field &GaussNoise, | ||||||
|  | 						       MultiShiftFunction &ApproxNegPow)  | ||||||
|  |     { | ||||||
|  |       GridBase *FermionGrid = GaussNoise.Grid(); | ||||||
|  |  | ||||||
|  |       Field X(FermionGrid); | ||||||
|  |       Field Y(FermionGrid); | ||||||
|  |       Field Z(FermionGrid); | ||||||
|  |  | ||||||
|  |       Field tmp1(FermionGrid), tmp2(FermionGrid); | ||||||
|  |  | ||||||
|  |       X=GaussNoise; | ||||||
|  |       RealD Nx = norm2(X); | ||||||
|  |  | ||||||
|  |       ConjugateGradientMultiShift<Field> msCG(MaxIter,ApproxNegPow); | ||||||
|  |  | ||||||
|  |       tmp1 = X; | ||||||
|  |        | ||||||
|  |       Field* in = &tmp1; | ||||||
|  |       Field* out = &tmp2; | ||||||
|  |       for(int i=0;i<inv_pow;i++){ //apply  [ Hermop^{-1/inv_pow}  ]^{inv_pow} X =   HermOp^{-1} X | ||||||
|  | 	msCG(HermOp, *in, *out); //backwards conventions! | ||||||
|  | 	if(i!=inv_pow-1) std::swap(in, out); | ||||||
|  |       } | ||||||
|  |       Z = *out; | ||||||
|  |  | ||||||
|  |       RealD Nz = norm2(Z); | ||||||
|  |  | ||||||
|  |       HermOp.HermOp(Z,Y); | ||||||
|  |       RealD Ny = norm2(Y); | ||||||
|  |  | ||||||
|  |       X=X-Y; | ||||||
|  |       RealD Nd = norm2(X); | ||||||
|  |       std::cout << "************************* "<<std::endl; | ||||||
|  |       std::cout << " | noise |^2                         = "<<Nx<<std::endl; | ||||||
|  |       std::cout << " | (MdagM^-1/" << inv_pow << ")^" << inv_pow << " noise |^2        = "<<Nz<<std::endl; | ||||||
|  |       std::cout << " | MdagM (MdagM^-1/" << inv_pow << ")^" << inv_pow << " noise |^2   = "<<Ny<<std::endl; | ||||||
|  |       std::cout << " | noise - MdagM (MdagM^-1/" << inv_pow << ")^" << inv_pow << " noise |^2  = "<<Nd<<std::endl; | ||||||
|  |       std::cout << " | noise - MdagM (MdagM^-1/" << inv_pow << ")^" << inv_pow << " noise |/| noise |  = "<<std::sqrt(Nd/Nx)<<std::endl; | ||||||
|  |       std::cout << "************************* "<<std::endl; | ||||||
|  |       assert( (std::sqrt(Nd/Nx)<tol) && " InversePowerBoundsCheck "); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -44,6 +44,10 @@ NAMESPACE_BEGIN(Grid); | |||||||
|   // Exact one flavour implementation of DWF determinant ratio // |   // Exact one flavour implementation of DWF determinant ratio // | ||||||
|   /////////////////////////////////////////////////////////////// |   /////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  |   //Note: using mixed prec CG for the heatbath solver in this action class will not work | ||||||
|  |   //      because the L, R operators must have their shift coefficients updated throughout the heatbath step | ||||||
|  |   //      You will find that the heatbath solver simply won't converge. | ||||||
|  |   //      To use mixed precision here use the ExactOneFlavourRatioMixedPrecHeatbathPseudoFermionAction variant below | ||||||
|   template<class Impl> |   template<class Impl> | ||||||
|   class ExactOneFlavourRatioPseudoFermionAction : public Action<typename Impl::GaugeField> |   class ExactOneFlavourRatioPseudoFermionAction : public Action<typename Impl::GaugeField> | ||||||
|   { |   { | ||||||
| @@ -57,37 +61,60 @@ NAMESPACE_BEGIN(Grid); | |||||||
|       bool use_heatbath_forecasting; |       bool use_heatbath_forecasting; | ||||||
|       AbstractEOFAFermion<Impl>& Lop; // the basic LH operator |       AbstractEOFAFermion<Impl>& Lop; // the basic LH operator | ||||||
|       AbstractEOFAFermion<Impl>& Rop; // the basic RH operator |       AbstractEOFAFermion<Impl>& Rop; // the basic RH operator | ||||||
|       SchurRedBlackDiagMooeeSolve<FermionField> SolverHB; |       SchurRedBlackDiagMooeeSolve<FermionField> SolverHBL; | ||||||
|  |       SchurRedBlackDiagMooeeSolve<FermionField> SolverHBR; | ||||||
|       SchurRedBlackDiagMooeeSolve<FermionField> SolverL; |       SchurRedBlackDiagMooeeSolve<FermionField> SolverL; | ||||||
|       SchurRedBlackDiagMooeeSolve<FermionField> SolverR; |       SchurRedBlackDiagMooeeSolve<FermionField> SolverR; | ||||||
|       SchurRedBlackDiagMooeeSolve<FermionField> DerivativeSolverL; |       SchurRedBlackDiagMooeeSolve<FermionField> DerivativeSolverL; | ||||||
|       SchurRedBlackDiagMooeeSolve<FermionField> DerivativeSolverR; |       SchurRedBlackDiagMooeeSolve<FermionField> DerivativeSolverR; | ||||||
|       FermionField Phi; // the pseudofermion field for this trajectory |       FermionField Phi; // the pseudofermion field for this trajectory | ||||||
|  |  | ||||||
|  |       RealD norm2_eta; //|eta|^2 where eta is the random gaussian field used to generate the pseudofermion field | ||||||
|  |       bool initial_action; //true for the first call to S after refresh, for which the identity S = |eta|^2 holds provided the rational approx is good | ||||||
|     public: |     public: | ||||||
|  |  | ||||||
|  |       //Used in the heatbath, refresh the shift coefficients of the L (LorR=0) or R (LorR=1) operator | ||||||
|  |       virtual void heatbathRefreshShiftCoefficients(int LorR, RealD to){ | ||||||
|  | 	AbstractEOFAFermion<Impl>&op = LorR == 0 ? Lop : Rop; | ||||||
|  | 	op.RefreshShiftCoefficients(to); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |       //Use the same solver for L,R in all cases | ||||||
|       ExactOneFlavourRatioPseudoFermionAction(AbstractEOFAFermion<Impl>& _Lop,  |       ExactOneFlavourRatioPseudoFermionAction(AbstractEOFAFermion<Impl>& _Lop,  | ||||||
| 					      AbstractEOFAFermion<Impl>& _Rop, | 					      AbstractEOFAFermion<Impl>& _Rop, | ||||||
| 					      OperatorFunction<FermionField>& CG,  | 					      OperatorFunction<FermionField>& CG,  | ||||||
| 					      Params& p,  | 					      Params& p,  | ||||||
| 					      bool use_fc=false)  | 					      bool use_fc=false)  | ||||||
| 	: ExactOneFlavourRatioPseudoFermionAction(_Lop,_Rop,CG,CG,CG,CG,CG,p,use_fc) {}; | 	: ExactOneFlavourRatioPseudoFermionAction(_Lop,_Rop,CG,CG,CG,CG,CG,CG,p,use_fc) {}; | ||||||
|  |  | ||||||
|  |       //Use the same solver for L,R in the heatbath but different solvers elsewhere | ||||||
|       ExactOneFlavourRatioPseudoFermionAction(AbstractEOFAFermion<Impl>& _Lop,  |       ExactOneFlavourRatioPseudoFermionAction(AbstractEOFAFermion<Impl>& _Lop,  | ||||||
| 					      AbstractEOFAFermion<Impl>& _Rop, | 					      AbstractEOFAFermion<Impl>& _Rop, | ||||||
| 					      OperatorFunction<FermionField>& HeatbathCG, | 					      OperatorFunction<FermionField>& HeatbathCG, | ||||||
| 					      OperatorFunction<FermionField>& ActionCGL, OperatorFunction<FermionField>& ActionCGR,  | 					      OperatorFunction<FermionField>& ActionCGL, OperatorFunction<FermionField>& ActionCGR,  | ||||||
| 					      OperatorFunction<FermionField>& DerivCGL , OperatorFunction<FermionField>& DerivCGR,  | 					      OperatorFunction<FermionField>& DerivCGL , OperatorFunction<FermionField>& DerivCGR,  | ||||||
| 					      Params& p,  | 					      Params& p,  | ||||||
|  | 					      bool use_fc=false) | ||||||
|  | 	: ExactOneFlavourRatioPseudoFermionAction(_Lop,_Rop,HeatbathCG,HeatbathCG, ActionCGL, ActionCGR, DerivCGL,DerivCGR,p,use_fc) {}; | ||||||
|  |  | ||||||
|  |       //Use different solvers for L,R in all cases | ||||||
|  |       ExactOneFlavourRatioPseudoFermionAction(AbstractEOFAFermion<Impl>& _Lop,  | ||||||
|  | 					      AbstractEOFAFermion<Impl>& _Rop, | ||||||
|  | 					      OperatorFunction<FermionField>& HeatbathCGL, OperatorFunction<FermionField>& HeatbathCGR, | ||||||
|  | 					      OperatorFunction<FermionField>& ActionCGL, OperatorFunction<FermionField>& ActionCGR,  | ||||||
|  | 					      OperatorFunction<FermionField>& DerivCGL , OperatorFunction<FermionField>& DerivCGR,  | ||||||
|  | 					      Params& p,  | ||||||
| 					      bool use_fc=false) :  | 					      bool use_fc=false) :  | ||||||
|         Lop(_Lop),  |         Lop(_Lop),  | ||||||
| 	Rop(_Rop),  | 	Rop(_Rop),  | ||||||
| 	SolverHB(HeatbathCG,false,true), | 	SolverHBL(HeatbathCGL,false,true), SolverHBR(HeatbathCGR,false,true), | ||||||
| 	SolverL(ActionCGL, false, true), SolverR(ActionCGR, false, true),  | 	SolverL(ActionCGL, false, true), SolverR(ActionCGR, false, true),  | ||||||
| 	DerivativeSolverL(DerivCGL, false, true), DerivativeSolverR(DerivCGR, false, true),  | 	DerivativeSolverL(DerivCGL, false, true), DerivativeSolverR(DerivCGR, false, true),  | ||||||
| 	Phi(_Lop.FermionGrid()),  | 	Phi(_Lop.FermionGrid()),  | ||||||
| 	param(p),  | 	param(p),  | ||||||
|         use_heatbath_forecasting(use_fc) | 	use_heatbath_forecasting(use_fc), | ||||||
|  | 	initial_action(false) | ||||||
|       { |       { | ||||||
|         AlgRemez remez(param.lo, param.hi, param.precision); |         AlgRemez remez(param.lo, param.hi, param.precision); | ||||||
|  |  | ||||||
| @@ -97,6 +124,8 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         PowerNegHalf.Init(remez, param.tolerance, true); |         PowerNegHalf.Init(remez, param.tolerance, true); | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|  |       const FermionField &getPhi() const{ return Phi; } | ||||||
|  |  | ||||||
|       virtual std::string action_name() { return "ExactOneFlavourRatioPseudoFermionAction"; } |       virtual std::string action_name() { return "ExactOneFlavourRatioPseudoFermionAction"; } | ||||||
|  |  | ||||||
|       virtual std::string LogParameters() { |       virtual std::string LogParameters() { | ||||||
| @@ -117,6 +146,19 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         else{ for(int s=0; s<Ls; ++s){ axpby_ssp_pminus(out, 0.0, in, 1.0, in, s, s); } } |         else{ for(int s=0; s<Ls; ++s){ axpby_ssp_pminus(out, 0.0, in, 1.0, in, s, s); } } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) { | ||||||
|  |         // P(eta_o) = e^{- eta_o^dag eta_o} | ||||||
|  |         // | ||||||
|  |         // e^{x^2/2 sig^2} => sig^2 = 0.5. | ||||||
|  |         //  | ||||||
|  |         RealD scale = std::sqrt(0.5); | ||||||
|  |  | ||||||
|  |         FermionField eta    (Lop.FermionGrid()); | ||||||
|  |         gaussian(pRNG,eta); eta = eta * scale; | ||||||
|  |  | ||||||
|  | 	refresh(U,eta); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       // EOFA heatbath: see Eqn. (29) of arXiv:1706.05843 |       // EOFA heatbath: see Eqn. (29) of arXiv:1706.05843 | ||||||
|       // We generate a Gaussian noise vector \eta, and then compute |       // We generate a Gaussian noise vector \eta, and then compute | ||||||
|       //  \Phi = M_{\rm EOFA}^{-1/2} * \eta |       //  \Phi = M_{\rm EOFA}^{-1/2} * \eta | ||||||
| @@ -124,12 +166,10 @@ NAMESPACE_BEGIN(Grid); | |||||||
|       // |       // | ||||||
|       // As a check of rational require \Phi^dag M_{EOFA} \Phi == eta^dag M^-1/2^dag M M^-1/2 eta = eta^dag eta |       // As a check of rational require \Phi^dag M_{EOFA} \Phi == eta^dag M^-1/2^dag M M^-1/2 eta = eta^dag eta | ||||||
|       // |       // | ||||||
|       virtual void refresh(const GaugeField& U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) |      void refresh(const GaugeField &U, const FermionField &eta) { | ||||||
|       { |  | ||||||
|         Lop.ImportGauge(U); |         Lop.ImportGauge(U); | ||||||
|         Rop.ImportGauge(U); |         Rop.ImportGauge(U); | ||||||
|  |  | ||||||
|         FermionField eta         (Lop.FermionGrid()); |  | ||||||
|         FermionField CG_src      (Lop.FermionGrid()); |         FermionField CG_src      (Lop.FermionGrid()); | ||||||
|         FermionField CG_soln     (Lop.FermionGrid()); |         FermionField CG_soln     (Lop.FermionGrid()); | ||||||
|         FermionField Forecast_src(Lop.FermionGrid()); |         FermionField Forecast_src(Lop.FermionGrid()); | ||||||
| @@ -140,11 +180,6 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); } |         if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); } | ||||||
|         ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast; |         ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast; | ||||||
|  |  | ||||||
|         // Seed with Gaussian noise vector (var = 0.5) |  | ||||||
|         RealD scale = std::sqrt(0.5); |  | ||||||
|         gaussian(pRNG,eta); |  | ||||||
|         eta = eta * scale; |  | ||||||
|  |  | ||||||
|         // \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta |         // \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta | ||||||
|         RealD N(PowerNegHalf.norm); |         RealD N(PowerNegHalf.norm); | ||||||
|         for(int k=0; k<param.degree; ++k){ N += PowerNegHalf.residues[k] / ( 1.0 + PowerNegHalf.poles[k] ); } |         for(int k=0; k<param.degree; ++k){ N += PowerNegHalf.residues[k] / ( 1.0 + PowerNegHalf.poles[k] ); } | ||||||
| @@ -160,15 +195,16 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         tmp[1] = Zero(); |         tmp[1] = Zero(); | ||||||
|         for(int k=0; k<param.degree; ++k){ |         for(int k=0; k<param.degree; ++k){ | ||||||
|           gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] ); |           gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] ); | ||||||
|           Lop.RefreshShiftCoefficients(-gamma_l); |           heatbathRefreshShiftCoefficients(0, -gamma_l); | ||||||
|  | 	  //Lop.RefreshShiftCoefficients(-gamma_l); | ||||||
|           if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles |           if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles | ||||||
|             Lop.Mdag(CG_src, Forecast_src); |             Lop.Mdag(CG_src, Forecast_src); | ||||||
|             CG_soln = Forecast(Lop, Forecast_src, prev_solns); |             CG_soln = Forecast(Lop, Forecast_src, prev_solns); | ||||||
|             SolverHB(Lop, CG_src, CG_soln); |             SolverHBL(Lop, CG_src, CG_soln); | ||||||
|             prev_solns.push_back(CG_soln); |             prev_solns.push_back(CG_soln); | ||||||
|           } else { |           } else { | ||||||
|             CG_soln = Zero(); // Just use zero as the initial guess |             CG_soln = Zero(); // Just use zero as the initial guess | ||||||
|             SolverHB(Lop, CG_src, CG_soln); | 	    SolverHBL(Lop, CG_src, CG_soln); | ||||||
|           } |           } | ||||||
|           Lop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back |           Lop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back | ||||||
|           tmp[1] = tmp[1] + ( PowerNegHalf.residues[k]*gamma_l*gamma_l*Lop.k ) * tmp[0]; |           tmp[1] = tmp[1] + ( PowerNegHalf.residues[k]*gamma_l*gamma_l*Lop.k ) * tmp[0]; | ||||||
| @@ -187,15 +223,16 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         if(use_heatbath_forecasting){ prev_solns.clear(); } // empirically, LH solns don't help for RH solves |         if(use_heatbath_forecasting){ prev_solns.clear(); } // empirically, LH solns don't help for RH solves | ||||||
|         for(int k=0; k<param.degree; ++k){ |         for(int k=0; k<param.degree; ++k){ | ||||||
|           gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] ); |           gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] ); | ||||||
|           Rop.RefreshShiftCoefficients(-gamma_l*PowerNegHalf.poles[k]); | 	  heatbathRefreshShiftCoefficients(1, -gamma_l*PowerNegHalf.poles[k]); | ||||||
|  |           //Rop.RefreshShiftCoefficients(-gamma_l*PowerNegHalf.poles[k]); | ||||||
|           if(use_heatbath_forecasting){ |           if(use_heatbath_forecasting){ | ||||||
|             Rop.Mdag(CG_src, Forecast_src); |             Rop.Mdag(CG_src, Forecast_src); | ||||||
|             CG_soln = Forecast(Rop, Forecast_src, prev_solns); |             CG_soln = Forecast(Rop, Forecast_src, prev_solns); | ||||||
|             SolverHB(Rop, CG_src, CG_soln); |             SolverHBR(Rop, CG_src, CG_soln); | ||||||
|             prev_solns.push_back(CG_soln); |             prev_solns.push_back(CG_soln); | ||||||
|           } else { |           } else { | ||||||
|             CG_soln = Zero(); |             CG_soln = Zero(); | ||||||
|             SolverHB(Rop, CG_src, CG_soln); |             SolverHBR(Rop, CG_src, CG_soln); | ||||||
|           } |           } | ||||||
|           Rop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back |           Rop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back | ||||||
|           tmp[1] = tmp[1] - ( PowerNegHalf.residues[k]*gamma_l*gamma_l*Rop.k ) * tmp[0]; |           tmp[1] = tmp[1] - ( PowerNegHalf.residues[k]*gamma_l*gamma_l*Rop.k ) * tmp[0]; | ||||||
| @@ -205,49 +242,119 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         Phi = Phi + tmp[1]; |         Phi = Phi + tmp[1]; | ||||||
|  |  | ||||||
|         // Reset shift coefficients for energy and force evals |         // Reset shift coefficients for energy and force evals | ||||||
|         Lop.RefreshShiftCoefficients(0.0); |         //Lop.RefreshShiftCoefficients(0.0); | ||||||
|         Rop.RefreshShiftCoefficients(-1.0); |         //Rop.RefreshShiftCoefficients(-1.0); | ||||||
|  | 	heatbathRefreshShiftCoefficients(0, 0.0); | ||||||
|  | 	heatbathRefreshShiftCoefficients(1, -1.0); | ||||||
|  |  | ||||||
|  | 	//Mark that the next call to S is the first after refresh | ||||||
|  | 	initial_action = true; | ||||||
|  |  | ||||||
|  |  | ||||||
| 	// Bounds check | 	// Bounds check | ||||||
| 	RealD EtaDagEta = norm2(eta); | 	RealD EtaDagEta = norm2(eta); | ||||||
|  | 	norm2_eta = EtaDagEta; | ||||||
|  |  | ||||||
| 	//	RealD PhiDagMPhi= norm2(eta); | 	//	RealD PhiDagMPhi= norm2(eta); | ||||||
|  |  | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|       void Meofa(const GaugeField& U,const FermionField &phi, FermionField & Mphi)  |       void Meofa(const GaugeField& U,const FermionField &in, FermionField & out)  | ||||||
|       { |       { | ||||||
| #if 0 |  | ||||||
|         Lop.ImportGauge(U); |         Lop.ImportGauge(U); | ||||||
|         Rop.ImportGauge(U); |         Rop.ImportGauge(U); | ||||||
|  |  | ||||||
|         FermionField spProj_Phi(Lop.FermionGrid()); |         FermionField spProj_in(Lop.FermionGrid()); | ||||||
| 	FermionField mPhi(Lop.FermionGrid()); |  | ||||||
|         std::vector<FermionField> tmp(2, Lop.FermionGrid()); |         std::vector<FermionField> tmp(2, Lop.FermionGrid()); | ||||||
| 	mPhi = phi; | 	out = in; | ||||||
| 	 | 	 | ||||||
|         // LH term: S = S - k <\Phi| P_{-} \Omega_{-}^{\dagger} H(mf)^{-1} \Omega_{-} P_{-} |\Phi> |         // LH term: S = S - k <\Phi| P_{-} \Omega_{-}^{\dagger} H(mf)^{-1} \Omega_{-} P_{-} |\Phi> | ||||||
|         spProj(Phi, spProj_Phi, -1, Lop.Ls); |         spProj(in, spProj_in, -1, Lop.Ls); | ||||||
|         Lop.Omega(spProj_Phi, tmp[0], -1, 0); |         Lop.Omega(spProj_in, tmp[0], -1, 0); | ||||||
|         G5R5(tmp[1], tmp[0]); |         G5R5(tmp[1], tmp[0]); | ||||||
|         tmp[0] = Zero(); |         tmp[0] = Zero(); | ||||||
|         SolverL(Lop, tmp[1], tmp[0]); |         SolverL(Lop, tmp[1], tmp[0]); | ||||||
|         Lop.Dtilde(tmp[0], tmp[1]); // We actually solved Cayley preconditioned system: transform back |         Lop.Dtilde(tmp[0], tmp[1]); // We actually solved Cayley preconditioned system: transform back | ||||||
|         Lop.Omega(tmp[1], tmp[0], -1, 1); |         Lop.Omega(tmp[1], tmp[0], -1, 1); | ||||||
| 	mPhi = mPhi -  Lop.k * innerProduct(spProj_Phi, tmp[0]).real(); | 	spProj(tmp[0], tmp[1], -1, Lop.Ls); | ||||||
|  |  | ||||||
|  | 	out = out -  Lop.k * tmp[1]; | ||||||
|  |  | ||||||
|         // RH term: S = S + k <\Phi| P_{+} \Omega_{+}^{\dagger} ( H(mb) |         // RH term: S = S + k <\Phi| P_{+} \Omega_{+}^{\dagger} ( H(mb) | ||||||
|         //               - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{-} P_{-} |\Phi> |         //               - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} |\Phi> | ||||||
|         spProj(Phi, spProj_Phi, 1, Rop.Ls); |         spProj(in, spProj_in, 1, Rop.Ls); | ||||||
|         Rop.Omega(spProj_Phi, tmp[0], 1, 0); |         Rop.Omega(spProj_in, tmp[0], 1, 0); | ||||||
|         G5R5(tmp[1], tmp[0]); |         G5R5(tmp[1], tmp[0]); | ||||||
|         tmp[0] = Zero(); |         tmp[0] = Zero(); | ||||||
|         SolverR(Rop, tmp[1], tmp[0]); |         SolverR(Rop, tmp[1], tmp[0]); | ||||||
|         Rop.Dtilde(tmp[0], tmp[1]); |         Rop.Dtilde(tmp[0], tmp[1]); | ||||||
|         Rop.Omega(tmp[1], tmp[0], 1, 1); |         Rop.Omega(tmp[1], tmp[0], 1, 1); | ||||||
|         action += Rop.k * innerProduct(spProj_Phi, tmp[0]).real(); | 	spProj(tmp[0], tmp[1], 1, Rop.Ls); | ||||||
| #endif |  | ||||||
|  |         out = out + Rop.k * tmp[1]; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       //Due to the structure of EOFA, it is no more expensive to compute the inverse of Meofa | ||||||
|  |       //To ensure correctness we can simply reuse the heatbath code but use the rational approx | ||||||
|  |       //f(x) = 1/x   which corresponds to alpha_0=0,  alpha_1=1,  beta_1=0 => gamma_1=1 | ||||||
|  |       void MeofaInv(const GaugeField &U, const FermionField &in, FermionField &out) { | ||||||
|  |         Lop.ImportGauge(U); | ||||||
|  |         Rop.ImportGauge(U); | ||||||
|  |  | ||||||
|  |         FermionField CG_src      (Lop.FermionGrid()); | ||||||
|  |         FermionField CG_soln     (Lop.FermionGrid()); | ||||||
|  |         std::vector<FermionField> tmp(2, Lop.FermionGrid()); | ||||||
|  |  | ||||||
|  |         // \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta | ||||||
|  | 	// = 1 * \eta | ||||||
|  |         out = in; | ||||||
|  |  | ||||||
|  |         // LH terms: | ||||||
|  |         // \Phi = \Phi + k \sum_{k=1}^{N_{p}} P_{-} \Omega_{-}^{\dagger} ( H(mf) | ||||||
|  |         //          - \gamma_{l} \Delta_{-}(mf,mb) P_{-} )^{-1} \Omega_{-} P_{-} \eta | ||||||
|  |         spProj(in, tmp[0], -1, Lop.Ls); | ||||||
|  |         Lop.Omega(tmp[0], tmp[1], -1, 0); | ||||||
|  |         G5R5(CG_src, tmp[1]); | ||||||
|  |         { | ||||||
|  |           heatbathRefreshShiftCoefficients(0, -1.); //-gamma_1 = -1. | ||||||
|  |  | ||||||
|  | 	  CG_soln = Zero(); // Just use zero as the initial guess | ||||||
|  | 	  SolverHBL(Lop, CG_src, CG_soln); | ||||||
|  |  | ||||||
|  |           Lop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back | ||||||
|  |           tmp[1] = Lop.k * tmp[0]; | ||||||
|  |         } | ||||||
|  |         Lop.Omega(tmp[1], tmp[0], -1, 1); | ||||||
|  |         spProj(tmp[0], tmp[1], -1, Lop.Ls); | ||||||
|  |         out = out + tmp[1]; | ||||||
|  |  | ||||||
|  |         // RH terms: | ||||||
|  |         // \Phi = \Phi - k \sum_{k=1}^{N_{p}} P_{+} \Omega_{+}^{\dagger} ( H(mb) | ||||||
|  |         //          - \beta_l\gamma_{l} \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} \eta | ||||||
|  |         spProj(in, tmp[0], 1, Rop.Ls); | ||||||
|  |         Rop.Omega(tmp[0], tmp[1], 1, 0); | ||||||
|  |         G5R5(CG_src, tmp[1]); | ||||||
|  |         { | ||||||
|  | 	  heatbathRefreshShiftCoefficients(1, 0.); //-gamma_1 * beta_1 = 0 | ||||||
|  |  | ||||||
|  | 	  CG_soln = Zero(); | ||||||
|  | 	  SolverHBR(Rop, CG_src, CG_soln); | ||||||
|  |  | ||||||
|  |           Rop.Dtilde(CG_soln, tmp[0]); // We actually solved Cayley preconditioned system: transform back | ||||||
|  |           tmp[1] = - Rop.k * tmp[0]; | ||||||
|  |         } | ||||||
|  |         Rop.Omega(tmp[1], tmp[0], 1, 1); | ||||||
|  |         spProj(tmp[0], tmp[1], 1, Rop.Ls); | ||||||
|  |         out = out + tmp[1]; | ||||||
|  |  | ||||||
|  |         // Reset shift coefficients for energy and force evals | ||||||
|  | 	heatbathRefreshShiftCoefficients(0, 0.0); | ||||||
|  | 	heatbathRefreshShiftCoefficients(1, -1.0); | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|       // EOFA action: see Eqn. (10) of arXiv:1706.05843 |       // EOFA action: see Eqn. (10) of arXiv:1706.05843 | ||||||
|       virtual RealD S(const GaugeField& U) |       virtual RealD S(const GaugeField& U) | ||||||
|       { |       { | ||||||
| @@ -271,7 +378,7 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         action -= Lop.k * innerProduct(spProj_Phi, tmp[0]).real(); |         action -= Lop.k * innerProduct(spProj_Phi, tmp[0]).real(); | ||||||
|  |  | ||||||
|         // RH term: S = S + k <\Phi| P_{+} \Omega_{+}^{\dagger} ( H(mb) |         // RH term: S = S + k <\Phi| P_{+} \Omega_{+}^{\dagger} ( H(mb) | ||||||
|         //               - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{-} P_{-} |\Phi> |         //               - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} |\Phi> | ||||||
|         spProj(Phi, spProj_Phi, 1, Rop.Ls); |         spProj(Phi, spProj_Phi, 1, Rop.Ls); | ||||||
|         Rop.Omega(spProj_Phi, tmp[0], 1, 0); |         Rop.Omega(spProj_Phi, tmp[0], 1, 0); | ||||||
|         G5R5(tmp[1], tmp[0]); |         G5R5(tmp[1], tmp[0]); | ||||||
| @@ -281,6 +388,26 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         Rop.Omega(tmp[1], tmp[0], 1, 1); |         Rop.Omega(tmp[1], tmp[0], 1, 1); | ||||||
|         action += Rop.k * innerProduct(spProj_Phi, tmp[0]).real(); |         action += Rop.k * innerProduct(spProj_Phi, tmp[0]).real(); | ||||||
|  |  | ||||||
|  | 	if(initial_action){ | ||||||
|  | 	  //For the first call to S after refresh,  S = |eta|^2. We can use this to ensure the rational approx is good | ||||||
|  | 	  RealD diff = action - norm2_eta; | ||||||
|  |  | ||||||
|  | 	  //S_init = eta^dag M^{-1/2} M M^{-1/2} eta | ||||||
|  | 	  //S_init - eta^dag eta =  eta^dag ( M^{-1/2} M M^{-1/2} - 1 ) eta | ||||||
|  |  | ||||||
|  | 	  //If approximate solution | ||||||
|  | 	  //S_init - eta^dag eta =  eta^dag ( [M^{-1/2}+\delta M^{-1/2}] M [M^{-1/2}+\delta M^{-1/2}] - 1 ) eta | ||||||
|  | 	  //               \approx  eta^dag ( \delta M^{-1/2} M^{1/2} + M^{1/2}\delta M^{-1/2} ) eta | ||||||
|  | 	  // We divide out |eta|^2 to remove source scaling but the tolerance on this check should still be somewhat higher than the actual approx tolerance | ||||||
|  | 	  RealD test = fabs(diff)/norm2_eta; //test the quality of the rational approx | ||||||
|  |  | ||||||
|  | 	  std::cout << GridLogMessage << action_name() << " initial action " << action << " expect " << norm2_eta << "; diff " << diff << std::endl; | ||||||
|  | 	  std::cout << GridLogMessage << action_name() << "[ eta^dag ( M^{-1/2} M M^{-1/2} - 1 ) eta ]/|eta^2| = " << test << "  expect 0 (tol " << param.BoundsCheckTol << ")" << std::endl; | ||||||
|  |  | ||||||
|  | 	  assert( ( test < param.BoundsCheckTol ) && " Initial action check failed" ); | ||||||
|  | 	  initial_action = false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|         return action; |         return action; | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
| @@ -329,6 +456,40 @@ NAMESPACE_BEGIN(Grid); | |||||||
|       }; |       }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   template<class ImplD, class ImplF> | ||||||
|  |   class ExactOneFlavourRatioMixedPrecHeatbathPseudoFermionAction : public ExactOneFlavourRatioPseudoFermionAction<ImplD>{ | ||||||
|  |   public: | ||||||
|  |     INHERIT_IMPL_TYPES(ImplD); | ||||||
|  |     typedef OneFlavourRationalParams Params; | ||||||
|  |  | ||||||
|  |   private: | ||||||
|  |     AbstractEOFAFermion<ImplF>& LopF; // the basic LH operator | ||||||
|  |     AbstractEOFAFermion<ImplF>& RopF; // the basic RH operator | ||||||
|  |  | ||||||
|  |   public: | ||||||
|  |      | ||||||
|  |     virtual std::string action_name() { return "ExactOneFlavourRatioMixedPrecHeatbathPseudoFermionAction"; } | ||||||
|  |      | ||||||
|  |     //Used in the heatbath, refresh the shift coefficients of the L (LorR=0) or R (LorR=1) operator | ||||||
|  |     virtual void heatbathRefreshShiftCoefficients(int LorR, RealD to){ | ||||||
|  |       AbstractEOFAFermion<ImplF> &op = LorR == 0 ? LopF : RopF; | ||||||
|  |       op.RefreshShiftCoefficients(to); | ||||||
|  |       this->ExactOneFlavourRatioPseudoFermionAction<ImplD>::heatbathRefreshShiftCoefficients(LorR,to); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     ExactOneFlavourRatioMixedPrecHeatbathPseudoFermionAction(AbstractEOFAFermion<ImplF>& _LopF,  | ||||||
|  | 							     AbstractEOFAFermion<ImplF>& _RopF, | ||||||
|  | 							     AbstractEOFAFermion<ImplD>& _LopD,  | ||||||
|  | 							     AbstractEOFAFermion<ImplD>& _RopD, | ||||||
|  | 							     OperatorFunction<FermionField>& HeatbathCGL, OperatorFunction<FermionField>& HeatbathCGR, | ||||||
|  | 							     OperatorFunction<FermionField>& ActionCGL, OperatorFunction<FermionField>& ActionCGR,  | ||||||
|  | 							     OperatorFunction<FermionField>& DerivCGL , OperatorFunction<FermionField>& DerivCGR,  | ||||||
|  | 							     Params& p,  | ||||||
|  | 							     bool use_fc=false) :  | ||||||
|  |     LopF(_LopF), RopF(_RopF), ExactOneFlavourRatioPseudoFermionAction<ImplD>(_LopD, _RopD, HeatbathCGL, HeatbathCGR, ActionCGL, ActionCGR, DerivCGL, DerivCGR, p, use_fc){} | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										372
									
								
								Grid/qcd/action/pseudofermion/GeneralEvenOddRationalRatio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								Grid/qcd/action/pseudofermion/GeneralEvenOddRationalRatio.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,372 @@ | |||||||
|  |     /************************************************************************************* | ||||||
|  |  | ||||||
|  |     Grid physics library, www.github.com/paboyle/Grid  | ||||||
|  |  | ||||||
|  |     Source file: ./lib/qcd/action/pseudofermion/GeneralEvenOddRationalRatio.h | ||||||
|  |  | ||||||
|  |     Copyright (C) 2015 | ||||||
|  |  | ||||||
|  |     Author: Christopher Kelly <ckelly@bnl.gov> | ||||||
|  |     Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  |  | ||||||
|  |     This program is free software; you can redistribute it and/or modify | ||||||
|  |     it under the terms of the GNU General Public License as published by | ||||||
|  |     the Free Software Foundation; either version 2 of the License, or | ||||||
|  |     (at your option) any later version. | ||||||
|  |  | ||||||
|  |     This program is distributed in the hope that it will be useful, | ||||||
|  |     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |     GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |     You should have received a copy of the GNU General Public License along | ||||||
|  |     with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|  |     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  |  | ||||||
|  |     See the full license in the file "LICENSE" in the top level distribution directory | ||||||
|  |     *************************************************************************************/ | ||||||
|  |     /*  END LEGAL */ | ||||||
|  | #ifndef QCD_PSEUDOFERMION_GENERAL_EVEN_ODD_RATIONAL_RATIO_H | ||||||
|  | #define QCD_PSEUDOFERMION_GENERAL_EVEN_ODD_RATIONAL_RATIO_H | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  |     ///////////////////////////////////////////////////////// | ||||||
|  |     // Generic rational approximation for ratios of operators | ||||||
|  |     ///////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  |     /* S_f = -log( det(  [M^dag M]/[V^dag V] )^{1/inv_pow}  ) | ||||||
|  |            = chi^dag ( [M^dag M]/[V^dag V] )^{-1/inv_pow} chi\ | ||||||
|  | 	   = chi^dag ( [V^dag V]^{-1/2} [M^dag M] [V^dag V]^{-1/2} )^{-1/inv_pow} chi\ | ||||||
|  | 	   = chi^dag [V^dag V]^{1/(2*inv_pow)} [M^dag M]^{-1/inv_pow} [V^dag V]^{1/(2*inv_pow)} chi\ | ||||||
|  |  | ||||||
|  | 	   S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi        | ||||||
|  |      | ||||||
|  |        BIG WARNING:	    | ||||||
|  |        Here V^dag V is referred to in this code as the "numerator" operator and M^dag M is the *denominator* operator. | ||||||
|  |        this refers to their position in the pseudofermion action, which is the *inverse* of what appears in the determinant | ||||||
|  |        Thus for DWF the numerator operator is the Pauli-Villars operator | ||||||
|  |  | ||||||
|  |        Here P/Q \sim R_{1/(2*inv_pow)}  ~ (V^dagV)^{1/(2*inv_pow)}   | ||||||
|  |        Here N/D \sim R_{-1/inv_pow} ~ (M^dagM)^{-1/inv_pow}   | ||||||
|  |     */ | ||||||
|  |        | ||||||
|  |     template<class Impl> | ||||||
|  |     class GeneralEvenOddRatioRationalPseudoFermionAction : public Action<typename Impl::GaugeField> { | ||||||
|  |     public: | ||||||
|  |  | ||||||
|  |       INHERIT_IMPL_TYPES(Impl); | ||||||
|  |  | ||||||
|  |       typedef RationalActionParams Params; | ||||||
|  |       Params param; | ||||||
|  |  | ||||||
|  |       //For action evaluation | ||||||
|  |       MultiShiftFunction ApproxPowerAction   ;  //rational approx for X^{1/inv_pow} | ||||||
|  |       MultiShiftFunction ApproxNegPowerAction;  //rational approx for X^{-1/inv_pow} | ||||||
|  |       MultiShiftFunction ApproxHalfPowerAction;   //rational approx for X^{1/(2*inv_pow)} | ||||||
|  |       MultiShiftFunction ApproxNegHalfPowerAction; //rational approx for X^{-1/(2*inv_pow)} | ||||||
|  |  | ||||||
|  |       //For the MD integration | ||||||
|  |       MultiShiftFunction ApproxPowerMD   ;  //rational approx for X^{1/inv_pow} | ||||||
|  |       MultiShiftFunction ApproxNegPowerMD;  //rational approx for X^{-1/inv_pow} | ||||||
|  |       MultiShiftFunction ApproxHalfPowerMD;   //rational approx for X^{1/(2*inv_pow)} | ||||||
|  |       MultiShiftFunction ApproxNegHalfPowerMD; //rational approx for X^{-1/(2*inv_pow)} | ||||||
|  |  | ||||||
|  |     private: | ||||||
|  |       | ||||||
|  |       FermionOperator<Impl> & NumOp;// the basic operator | ||||||
|  |       FermionOperator<Impl> & DenOp;// the basic operator | ||||||
|  |       FermionField PhiEven; // the pseudo fermion field for this trajectory | ||||||
|  |       FermionField PhiOdd; // the pseudo fermion field for this trajectory | ||||||
|  |  | ||||||
|  |       //Generate the approximation to x^{1/inv_pow} (->approx)   and x^{-1/inv_pow} (-> approx_inv)  by an approx_degree degree rational approximation | ||||||
|  |       //CG_tolerance is used to issue a warning if the approximation error is larger than the tolerance of the CG and is otherwise just stored in the MultiShiftFunction for use by the multi-shift | ||||||
|  |       static void generateApprox(MultiShiftFunction &approx, MultiShiftFunction &approx_inv, int inv_pow, int approx_degree, double CG_tolerance, AlgRemez &remez){ | ||||||
|  | 	std::cout<<GridLogMessage << "Generating degree "<< approx_degree<<" approximation for x^(1/" << inv_pow << ")"<<std::endl; | ||||||
|  | 	double error = remez.generateApprox(approx_degree,1,inv_pow);	 | ||||||
|  | 	if(error > CG_tolerance) | ||||||
|  | 	  std::cout<<GridLogMessage << "WARNING: Remez approximation has a larger error " << error << " than the CG tolerance " << CG_tolerance << "! Try increasing the number of poles" << std::endl; | ||||||
|  | 	 | ||||||
|  | 	approx.Init(remez, CG_tolerance,false); | ||||||
|  | 	approx_inv.Init(remez, CG_tolerance,true); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     protected: | ||||||
|  |       static constexpr bool Numerator = true; | ||||||
|  |       static constexpr bool Denominator = false; | ||||||
|  |  | ||||||
|  |       //Allow derived classes to override the multishift CG | ||||||
|  |       virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionField &in, FermionField &out){ | ||||||
|  | 	SchurDifferentiableOperator<Impl> schurOp(numerator ? NumOp : DenOp); | ||||||
|  | 	ConjugateGradientMultiShift<FermionField> msCG(MaxIter, approx); | ||||||
|  | 	msCG(schurOp,in, out); | ||||||
|  |       } | ||||||
|  |       virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionField &in, std::vector<FermionField> &out_elems, FermionField &out){ | ||||||
|  | 	SchurDifferentiableOperator<Impl> schurOp(numerator ? NumOp : DenOp); | ||||||
|  | 	ConjugateGradientMultiShift<FermionField> msCG(MaxIter, approx); | ||||||
|  | 	msCG(schurOp,in, out_elems, out); | ||||||
|  |       } | ||||||
|  |       //Allow derived classes to override the gauge import | ||||||
|  |       virtual void ImportGauge(const GaugeField &U){ | ||||||
|  | 	NumOp.ImportGauge(U); | ||||||
|  | 	DenOp.ImportGauge(U); | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |     public: | ||||||
|  |  | ||||||
|  |       GeneralEvenOddRatioRationalPseudoFermionAction(FermionOperator<Impl>  &_NumOp,  | ||||||
|  | 						     FermionOperator<Impl>  &_DenOp,  | ||||||
|  | 						     const Params & p | ||||||
|  | 						     ) :  | ||||||
|  | 	NumOp(_NumOp),  | ||||||
|  | 	DenOp(_DenOp),  | ||||||
|  | 	PhiOdd (_NumOp.FermionRedBlackGrid()), | ||||||
|  | 	PhiEven(_NumOp.FermionRedBlackGrid()), | ||||||
|  | 	param(p)  | ||||||
|  |       { | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " initialize: starting" << std::endl; | ||||||
|  | 	AlgRemez remez(param.lo,param.hi,param.precision); | ||||||
|  |  | ||||||
|  | 	//Generate approximations for action eval | ||||||
|  | 	generateApprox(ApproxPowerAction, ApproxNegPowerAction, param.inv_pow, param.action_degree, param.action_tolerance, remez); | ||||||
|  | 	generateApprox(ApproxHalfPowerAction, ApproxNegHalfPowerAction, 2*param.inv_pow, param.action_degree, param.action_tolerance, remez); | ||||||
|  |  | ||||||
|  | 	//Generate approximations for MD | ||||||
|  | 	if(param.md_degree != param.action_degree){ //note the CG tolerance is unrelated to the stopping condition of the Remez algorithm | ||||||
|  | 	  generateApprox(ApproxPowerMD, ApproxNegPowerMD, param.inv_pow, param.md_degree, param.md_tolerance, remez); | ||||||
|  | 	  generateApprox(ApproxHalfPowerMD, ApproxNegHalfPowerMD, 2*param.inv_pow, param.md_degree, param.md_tolerance, remez); | ||||||
|  | 	}else{ | ||||||
|  | 	  std::cout<<GridLogMessage << "Using same rational approximations for MD as for action evaluation" << std::endl; | ||||||
|  | 	  ApproxPowerMD = ApproxPowerAction;  | ||||||
|  | 	  ApproxNegPowerMD = ApproxNegPowerAction; | ||||||
|  | 	  for(int i=0;i<ApproxPowerMD.tolerances.size();i++) | ||||||
|  | 	    ApproxNegPowerMD.tolerances[i] = ApproxPowerMD.tolerances[i] = param.md_tolerance; //used for multishift | ||||||
|  |  | ||||||
|  | 	  ApproxHalfPowerMD = ApproxHalfPowerAction; | ||||||
|  | 	  ApproxNegHalfPowerMD = ApproxNegHalfPowerAction; | ||||||
|  | 	  for(int i=0;i<ApproxPowerMD.tolerances.size();i++) | ||||||
|  | 	    ApproxNegHalfPowerMD.tolerances[i] = ApproxHalfPowerMD.tolerances[i] = param.md_tolerance; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " initialize: complete" << std::endl; | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |       virtual std::string action_name(){return "GeneralEvenOddRatioRationalPseudoFermionAction";} | ||||||
|  |  | ||||||
|  |       virtual std::string LogParameters(){ | ||||||
|  | 	std::stringstream sstream; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] Power              : 1/" << param.inv_pow <<  std::endl; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] Low                :" << param.lo <<  std::endl; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] High               :" << param.hi <<  std::endl; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] Max iterations     :" << param.MaxIter <<  std::endl; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] Tolerance (Action) :" << param.action_tolerance <<  std::endl; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] Degree (Action)    :" << param.action_degree <<  std::endl; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] Tolerance (MD)     :" << param.md_tolerance <<  std::endl; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] Degree (MD)        :" << param.md_degree <<  std::endl; | ||||||
|  | 	sstream << GridLogMessage << "["<<action_name()<<"] Precision          :" << param.precision <<  std::endl; | ||||||
|  | 	return sstream.str(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       //Access the fermion field | ||||||
|  |       const FermionField &getPhiOdd() const{ return PhiOdd; } | ||||||
|  |        | ||||||
|  |       virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) { | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " refresh: starting" << std::endl; | ||||||
|  | 	FermionField eta(NumOp.FermionGrid());	 | ||||||
|  |  | ||||||
|  | 	// P(eta) \propto e^{- eta^dag eta} | ||||||
|  | 	//	 | ||||||
|  | 	// The gaussian function draws from  P(x) \propto e^{- x^2 / 2 }    [i.e. sigma=1] | ||||||
|  | 	// Thus eta = x/sqrt{2} = x * sqrt(1/2) | ||||||
|  | 	RealD scale = std::sqrt(0.5); | ||||||
|  | 	gaussian(pRNG,eta);	eta=eta*scale; | ||||||
|  |  | ||||||
|  | 	refresh(U,eta); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       //Allow for manual specification of random field for testing | ||||||
|  |       void refresh(const GaugeField &U, const FermionField &eta) { | ||||||
|  |  | ||||||
|  | 	// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi        | ||||||
|  | 	// | ||||||
|  | 	// P(phi) = e^{- phi^dag (VdagV)^1/(2*inv_pow) (MdagM)^-1/inv_pow (VdagV)^1/(2*inv_pow) phi} | ||||||
|  | 	//        = e^{- phi^dag  (VdagV)^1/(2*inv_pow) (MdagM)^-1/(2*inv_pow) (MdagM)^-1/(2*inv_pow)  (VdagV)^1/(2*inv_pow) phi} | ||||||
|  | 	// | ||||||
|  | 	// Phi =  (VdagV)^-1/(2*inv_pow) Mdag^{1/(2*inv_pow)} eta  | ||||||
|  | 	 | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " refresh: starting" << std::endl; | ||||||
|  |  | ||||||
|  | 	FermionField etaOdd (NumOp.FermionRedBlackGrid()); | ||||||
|  | 	FermionField etaEven(NumOp.FermionRedBlackGrid()); | ||||||
|  | 	FermionField     tmp(NumOp.FermionRedBlackGrid()); | ||||||
|  |  | ||||||
|  | 	pickCheckerboard(Even,etaEven,eta); | ||||||
|  | 	pickCheckerboard(Odd,etaOdd,eta); | ||||||
|  |  | ||||||
|  | 	ImportGauge(U); | ||||||
|  |  | ||||||
|  | 	// MdagM^1/(2*inv_pow) eta | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " refresh: doing (M^dag M)^{1/" << 2*param.inv_pow << "} eta" << std::endl; | ||||||
|  | 	multiShiftInverse(Denominator, ApproxHalfPowerAction, param.MaxIter, etaOdd, tmp); | ||||||
|  |  | ||||||
|  | 	// VdagV^-1/(2*inv_pow) MdagM^1/(2*inv_pow) eta | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " refresh: doing (V^dag V)^{-1/" << 2*param.inv_pow << "} ( (M^dag M)^{1/" << 2*param.inv_pow << "} eta)" << std::endl; | ||||||
|  | 	multiShiftInverse(Numerator, ApproxNegHalfPowerAction, param.MaxIter, tmp, PhiOdd); | ||||||
|  | 		 | ||||||
|  | 	assert(NumOp.ConstEE() == 1); | ||||||
|  | 	assert(DenOp.ConstEE() == 1); | ||||||
|  | 	PhiEven = Zero(); | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " refresh: starting" << std::endl; | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |       ////////////////////////////////////////////////////// | ||||||
|  |       // S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi        | ||||||
|  |       ////////////////////////////////////////////////////// | ||||||
|  |       virtual RealD S(const GaugeField &U) { | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " compute action: starting" << std::endl; | ||||||
|  | 	ImportGauge(U); | ||||||
|  |  | ||||||
|  | 	FermionField X(NumOp.FermionRedBlackGrid()); | ||||||
|  | 	FermionField Y(NumOp.FermionRedBlackGrid()); | ||||||
|  |  | ||||||
|  | 	// VdagV^1/(2*inv_pow) Phi | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " compute action: doing (V^dag V)^{1/" << 2*param.inv_pow << "} Phi" << std::endl; | ||||||
|  | 	multiShiftInverse(Numerator, ApproxHalfPowerAction, param.MaxIter, PhiOdd,X); | ||||||
|  |  | ||||||
|  | 	// MdagM^-1/(2*inv_pow) VdagV^1/(2*inv_pow) Phi | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " compute action: doing (M^dag M)^{-1/" << 2*param.inv_pow << "} ( (V^dag V)^{1/" << 2*param.inv_pow << "} Phi)" << std::endl; | ||||||
|  | 	multiShiftInverse(Denominator, ApproxNegHalfPowerAction, param.MaxIter, X,Y); | ||||||
|  |  | ||||||
|  | 	// Randomly apply rational bounds checks. | ||||||
|  | 	int rcheck = rand(); | ||||||
|  | 	auto grid = NumOp.FermionGrid(); | ||||||
|  |         auto r=rand(); | ||||||
|  |         grid->Broadcast(0,r); | ||||||
|  |  | ||||||
|  | 	if ( param.BoundsCheckFreq != 0 && (r % param.BoundsCheckFreq)==0 ) {  | ||||||
|  | 	  std::cout<<GridLogMessage << action_name() << " compute action: doing bounds check" << std::endl; | ||||||
|  | 	  FermionField gauss(NumOp.FermionRedBlackGrid()); | ||||||
|  | 	  gauss = PhiOdd; | ||||||
|  | 	  SchurDifferentiableOperator<Impl> MdagM(DenOp); | ||||||
|  | 	  std::cout<<GridLogMessage << action_name() << " compute action: checking high bounds" << std::endl; | ||||||
|  | 	  HighBoundCheck(MdagM,gauss,param.hi); | ||||||
|  | 	  std::cout<<GridLogMessage << action_name() << " compute action: full approximation" << std::endl; | ||||||
|  | 	  InversePowerBoundsCheck(param.inv_pow,param.MaxIter,param.action_tolerance*100,MdagM,gauss,ApproxNegPowerAction); | ||||||
|  | 	  std::cout<<GridLogMessage << action_name() << " compute action: bounds check complete" << std::endl; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//  Phidag VdagV^1/(2*inv_pow) MdagM^-1/(2*inv_pow)  MdagM^-1/(2*inv_pow) VdagV^1/(2*inv_pow) Phi | ||||||
|  | 	RealD action = norm2(Y); | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " compute action: complete" << std::endl; | ||||||
|  |  | ||||||
|  | 	return action; | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |       // S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi        | ||||||
|  |       // | ||||||
|  |       // Here, M is some 5D operator and V is the Pauli-Villars field | ||||||
|  |       // N and D makeup the rat. poly of the M term and P and & makeup the rat.poly of the denom term | ||||||
|  |       // | ||||||
|  |       // Need   | ||||||
|  |       // dS_f/dU =  chi^dag d[P/Q]  N/D   P/Q  chi  | ||||||
|  |       //         +  chi^dag   P/Q d[N/D]  P/Q  chi  | ||||||
|  |       //         +  chi^dag   P/Q   N/D d[P/Q] chi  | ||||||
|  |       // | ||||||
|  |       // P/Q is expressed as partial fraction expansion:  | ||||||
|  |       //  | ||||||
|  |       //           a0 + \sum_k ak/(V^dagV + bk)  | ||||||
|  |       //   | ||||||
|  |       // d[P/Q] is then   | ||||||
|  |       // | ||||||
|  |       //          \sum_k -ak [V^dagV+bk]^{-1}  [ dV^dag V + V^dag dV ] [V^dag V + bk]^{-1}  | ||||||
|  |       //   | ||||||
|  |       // and similar for N/D.  | ||||||
|  |       //  | ||||||
|  |       // Need    | ||||||
|  |       //       MpvPhi_k   = [Vdag V + bk]^{-1} chi   | ||||||
|  |       //       MpvPhi     = {a0 +  \sum_k ak [Vdag V + bk]^{-1} }chi    | ||||||
|  |       //    | ||||||
|  |       //       MfMpvPhi_k = [MdagM+bk]^{-1} MpvPhi   | ||||||
|  |       //       MfMpvPhi   = {a0 +  \sum_k ak [Mdag M + bk]^{-1} } MpvPhi | ||||||
|  |       //  | ||||||
|  |       //       MpvMfMpvPhi_k = [Vdag V + bk]^{-1} MfMpvchi    | ||||||
|  |       //   | ||||||
|  |  | ||||||
|  |       virtual void deriv(const GaugeField &U,GaugeField & dSdU) { | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " deriv: starting" << std::endl; | ||||||
|  | 	const int n_f  = ApproxNegPowerMD.poles.size(); | ||||||
|  | 	const int n_pv = ApproxHalfPowerMD.poles.size(); | ||||||
|  |  | ||||||
|  | 	std::vector<FermionField> MpvPhi_k     (n_pv,NumOp.FermionRedBlackGrid()); | ||||||
|  | 	std::vector<FermionField> MpvMfMpvPhi_k(n_pv,NumOp.FermionRedBlackGrid()); | ||||||
|  | 	std::vector<FermionField> MfMpvPhi_k   (n_f ,NumOp.FermionRedBlackGrid()); | ||||||
|  |  | ||||||
|  | 	FermionField      MpvPhi(NumOp.FermionRedBlackGrid()); | ||||||
|  | 	FermionField    MfMpvPhi(NumOp.FermionRedBlackGrid()); | ||||||
|  | 	FermionField MpvMfMpvPhi(NumOp.FermionRedBlackGrid()); | ||||||
|  | 	FermionField           Y(NumOp.FermionRedBlackGrid()); | ||||||
|  |  | ||||||
|  | 	GaugeField   tmp(NumOp.GaugeGrid()); | ||||||
|  |  | ||||||
|  | 	ImportGauge(U); | ||||||
|  |  | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " deriv: doing (V^dag V)^{1/" << 2*param.inv_pow << "} Phi" << std::endl; | ||||||
|  | 	multiShiftInverse(Numerator, ApproxHalfPowerMD, param.MaxIter, PhiOdd,MpvPhi_k,MpvPhi); | ||||||
|  |  | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " deriv: doing (M^dag M)^{-1/" << param.inv_pow << "} ( (V^dag V)^{1/" << 2*param.inv_pow << "} Phi)" << std::endl; | ||||||
|  | 	multiShiftInverse(Denominator, ApproxNegPowerMD, param.MaxIter, MpvPhi,MfMpvPhi_k,MfMpvPhi); | ||||||
|  |  | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " deriv: doing (V^dag V)^{1/" << 2*param.inv_pow << "} ( (M^dag M)^{-1/" << param.inv_pow << "} (V^dag V)^{1/" << 2*param.inv_pow << "} Phi)" << std::endl; | ||||||
|  | 	multiShiftInverse(Numerator, ApproxHalfPowerMD, param.MaxIter, MfMpvPhi,MpvMfMpvPhi_k,MpvMfMpvPhi); | ||||||
|  | 		 | ||||||
|  |  | ||||||
|  | 	SchurDifferentiableOperator<Impl> MdagM(DenOp); | ||||||
|  | 	SchurDifferentiableOperator<Impl> VdagV(NumOp); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	RealD ak; | ||||||
|  |  | ||||||
|  | 	dSdU = Zero(); | ||||||
|  |  | ||||||
|  | 	// With these building blocks   | ||||||
|  | 	//   | ||||||
|  | 	//       dS/dU =  | ||||||
|  | 	//                 \sum_k -ak MfMpvPhi_k^dag      [ dM^dag M + M^dag dM ] MfMpvPhi_k         (1) | ||||||
|  | 	//             +   \sum_k -ak MpvMfMpvPhi_k^\dag  [ dV^dag V + V^dag dV ] MpvPhi_k           (2) | ||||||
|  | 	//                        -ak MpvPhi_k^dag        [ dV^dag V + V^dag dV ] MpvMfMpvPhi_k      (3) | ||||||
|  |  | ||||||
|  | 	//(1)	 | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " deriv: doing dS/dU part (1)" << std::endl; | ||||||
|  | 	for(int k=0;k<n_f;k++){ | ||||||
|  | 	  ak = ApproxNegPowerMD.residues[k]; | ||||||
|  | 	  MdagM.Mpc(MfMpvPhi_k[k],Y); | ||||||
|  | 	  MdagM.MpcDagDeriv(tmp , MfMpvPhi_k[k], Y );  dSdU=dSdU+ak*tmp; | ||||||
|  | 	  MdagM.MpcDeriv(tmp , Y, MfMpvPhi_k[k] );  dSdU=dSdU+ak*tmp; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	//(2) | ||||||
|  | 	//(3) | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " deriv: doing dS/dU part (2)+(3)" << std::endl; | ||||||
|  | 	for(int k=0;k<n_pv;k++){ | ||||||
|  |  | ||||||
|  |           ak = ApproxHalfPowerMD.residues[k]; | ||||||
|  | 	   | ||||||
|  | 	  VdagV.Mpc(MpvPhi_k[k],Y); | ||||||
|  | 	  VdagV.MpcDagDeriv(tmp,MpvMfMpvPhi_k[k],Y); dSdU=dSdU+ak*tmp; | ||||||
|  | 	  VdagV.MpcDeriv   (tmp,Y,MpvMfMpvPhi_k[k]);  dSdU=dSdU+ak*tmp;      | ||||||
|  | 	   | ||||||
|  | 	  VdagV.Mpc(MpvMfMpvPhi_k[k],Y);                // V as we take Ydag  | ||||||
|  | 	  VdagV.MpcDeriv   (tmp,Y, MpvPhi_k[k]); dSdU=dSdU+ak*tmp; | ||||||
|  | 	  VdagV.MpcDagDeriv(tmp,MpvPhi_k[k], Y); dSdU=dSdU+ak*tmp; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//dSdU = Ta(dSdU); | ||||||
|  | 	std::cout<<GridLogMessage << action_name() << " deriv: complete" << std::endl; | ||||||
|  |       }; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -0,0 +1,93 @@ | |||||||
|  |     /************************************************************************************* | ||||||
|  |  | ||||||
|  |     Grid physics library, www.github.com/paboyle/Grid  | ||||||
|  |  | ||||||
|  |     Source file: ./lib/qcd/action/pseudofermion/GeneralEvenOddRationalRatioMixedPrec.h | ||||||
|  |  | ||||||
|  |     Copyright (C) 2015 | ||||||
|  |  | ||||||
|  |     Author: Christopher Kelly <ckelly@bnl.gov> | ||||||
|  |     Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||||
|  |  | ||||||
|  |     This program is free software; you can redistribute it and/or modify | ||||||
|  |     it under the terms of the GNU General Public License as published by | ||||||
|  |     the Free Software Foundation; either version 2 of the License, or | ||||||
|  |     (at your option) any later version. | ||||||
|  |  | ||||||
|  |     This program is distributed in the hope that it will be useful, | ||||||
|  |     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |     GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |     You should have received a copy of the GNU General Public License along | ||||||
|  |     with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|  |     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  |  | ||||||
|  |     See the full license in the file "LICENSE" in the top level distribution directory | ||||||
|  |     *************************************************************************************/ | ||||||
|  |     /*  END LEGAL */ | ||||||
|  | #ifndef QCD_PSEUDOFERMION_GENERAL_EVEN_ODD_RATIONAL_RATIO_MIXED_PREC_H | ||||||
|  | #define QCD_PSEUDOFERMION_GENERAL_EVEN_ODD_RATIONAL_RATIO_MIXED_PREC_H | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  |     ///////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |     // Generic rational approximation for ratios of operators utilizing the mixed precision multishift algorithm | ||||||
|  |     // cf. GeneralEvenOddRational.h for details | ||||||
|  |     ///////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |        | ||||||
|  |     template<class ImplD, class ImplF> | ||||||
|  |     class GeneralEvenOddRatioRationalMixedPrecPseudoFermionAction : public GeneralEvenOddRatioRationalPseudoFermionAction<ImplD> { | ||||||
|  |     private: | ||||||
|  |       typedef typename ImplD::FermionField FermionFieldD; | ||||||
|  |       typedef typename ImplF::FermionField FermionFieldF; | ||||||
|  |  | ||||||
|  |       FermionOperator<ImplD> & NumOpD; | ||||||
|  |       FermionOperator<ImplD> & DenOpD; | ||||||
|  |       | ||||||
|  |       FermionOperator<ImplF> & NumOpF; | ||||||
|  |       FermionOperator<ImplF> & DenOpF; | ||||||
|  |  | ||||||
|  |       Integer ReliableUpdateFreq; | ||||||
|  |     protected: | ||||||
|  |  | ||||||
|  |       //Allow derived classes to override the multishift CG | ||||||
|  |       virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionFieldD &in, FermionFieldD &out){ | ||||||
|  | 	SchurDifferentiableOperator<ImplD> schurOpD(numerator ? NumOpD : DenOpD); | ||||||
|  | 	SchurDifferentiableOperator<ImplF> schurOpF(numerator ? NumOpF : DenOpF); | ||||||
|  |  | ||||||
|  | 	ConjugateGradientMultiShiftMixedPrec<FermionFieldD, FermionFieldF> msCG(MaxIter, approx, NumOpF.FermionRedBlackGrid(), schurOpF, ReliableUpdateFreq); | ||||||
|  | 	msCG(schurOpD, in, out); | ||||||
|  |       } | ||||||
|  |       virtual void multiShiftInverse(bool numerator, const MultiShiftFunction &approx, const Integer MaxIter, const FermionFieldD &in, std::vector<FermionFieldD> &out_elems, FermionFieldD &out){ | ||||||
|  | 	SchurDifferentiableOperator<ImplD> schurOpD(numerator ? NumOpD : DenOpD); | ||||||
|  | 	SchurDifferentiableOperator<ImplF> schurOpF(numerator ? NumOpF : DenOpF); | ||||||
|  |  | ||||||
|  | 	ConjugateGradientMultiShiftMixedPrec<FermionFieldD, FermionFieldF> msCG(MaxIter, approx, NumOpF.FermionRedBlackGrid(), schurOpF, ReliableUpdateFreq); | ||||||
|  | 	msCG(schurOpD, in, out_elems, out); | ||||||
|  |       } | ||||||
|  |       //Allow derived classes to override the gauge import | ||||||
|  |       virtual void ImportGauge(const typename ImplD::GaugeField &Ud){ | ||||||
|  | 	typename ImplF::GaugeField Uf(NumOpF.GaugeGrid()); | ||||||
|  | 	precisionChange(Uf, Ud); | ||||||
|  | 	 | ||||||
|  | 	NumOpD.ImportGauge(Ud); | ||||||
|  | 	DenOpD.ImportGauge(Ud); | ||||||
|  |  | ||||||
|  | 	NumOpF.ImportGauge(Uf); | ||||||
|  | 	DenOpF.ImportGauge(Uf); | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |     public: | ||||||
|  |       GeneralEvenOddRatioRationalMixedPrecPseudoFermionAction(FermionOperator<ImplD>  &_NumOpD, FermionOperator<ImplD>  &_DenOpD,  | ||||||
|  | 							      FermionOperator<ImplF>  &_NumOpF, FermionOperator<ImplF>  &_DenOpF,  | ||||||
|  | 							      const RationalActionParams & p, Integer _ReliableUpdateFreq | ||||||
|  | 							      ) : GeneralEvenOddRatioRationalPseudoFermionAction<ImplD>(_NumOpD, _DenOpD, p), | ||||||
|  | 								  ReliableUpdateFreq(_ReliableUpdateFreq), NumOpD(_NumOpD), DenOpD(_DenOpD), NumOpF(_NumOpF), DenOpF(_DenOpF){} | ||||||
|  |        | ||||||
|  |       virtual std::string action_name(){return "GeneralEvenOddRatioRationalMixedPrecPseudoFermionAction";} | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -40,249 +40,31 @@ NAMESPACE_BEGIN(Grid); | |||||||
|     // Here N/D \sim R_{-1/2} ~ (M^dagM)^{-1/2}   |     // Here N/D \sim R_{-1/2} ~ (M^dagM)^{-1/2}   | ||||||
|    |    | ||||||
|     template<class Impl> |     template<class Impl> | ||||||
|     class OneFlavourEvenOddRatioRationalPseudoFermionAction : public Action<typename Impl::GaugeField> { |     class OneFlavourEvenOddRatioRationalPseudoFermionAction : public GeneralEvenOddRatioRationalPseudoFermionAction<Impl> { | ||||||
|     public: |     public: | ||||||
|  |  | ||||||
|       INHERIT_IMPL_TYPES(Impl); |  | ||||||
|  |  | ||||||
|       typedef OneFlavourRationalParams Params; |       typedef OneFlavourRationalParams Params; | ||||||
|       Params param; |  | ||||||
|  |  | ||||||
|       MultiShiftFunction PowerHalf   ; |  | ||||||
|       MultiShiftFunction PowerNegHalf; |  | ||||||
|       MultiShiftFunction PowerQuarter; |  | ||||||
|       MultiShiftFunction PowerNegQuarter; |  | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|       |       static RationalActionParams transcribe(const Params &in){ | ||||||
|       FermionOperator<Impl> & NumOp;// the basic operator | 	RationalActionParams out; | ||||||
|       FermionOperator<Impl> & DenOp;// the basic operator | 	out.inv_pow = 2; | ||||||
|       FermionField PhiEven; // the pseudo fermion field for this trajectory | 	out.lo = in.lo; | ||||||
|       FermionField PhiOdd; // the pseudo fermion field for this trajectory | 	out.hi = in.hi; | ||||||
|  | 	out.MaxIter = in.MaxIter; | ||||||
|  | 	out.action_tolerance = out.md_tolerance = in.tolerance; | ||||||
|  | 	out.action_degree = out.md_degree = in.degree; | ||||||
|  | 	out.precision = in.precision; | ||||||
|  | 	out.BoundsCheckFreq = in.BoundsCheckFreq; | ||||||
|  | 	return out; | ||||||
|  |       } | ||||||
|  |  | ||||||
|     public: |     public: | ||||||
|  |  | ||||||
|       OneFlavourEvenOddRatioRationalPseudoFermionAction(FermionOperator<Impl>  &_NumOp,  |       OneFlavourEvenOddRatioRationalPseudoFermionAction(FermionOperator<Impl>  &_NumOp,  | ||||||
| 							FermionOperator<Impl>  &_DenOp,  | 							FermionOperator<Impl>  &_DenOp,  | ||||||
| 					    Params & p | 							const Params & p | ||||||
| 							) :  | 							) :  | ||||||
|       NumOp(_NumOp),  | 	GeneralEvenOddRatioRationalPseudoFermionAction<Impl>(_NumOp, _DenOp, transcribe(p)){} | ||||||
|       DenOp(_DenOp),  |  | ||||||
|       PhiOdd (_NumOp.FermionRedBlackGrid()), |  | ||||||
|       PhiEven(_NumOp.FermionRedBlackGrid()), |  | ||||||
|       param(p)  |  | ||||||
|       { |  | ||||||
| 	AlgRemez remez(param.lo,param.hi,param.precision); |  | ||||||
|  |  | ||||||
| 	// MdagM^(+- 1/2) |  | ||||||
| 	std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl; |  | ||||||
| 	remez.generateApprox(param.degree,1,2); |  | ||||||
| 	PowerHalf.Init(remez,param.tolerance,false); |  | ||||||
| 	PowerNegHalf.Init(remez,param.tolerance,true); |  | ||||||
|  |  | ||||||
| 	// MdagM^(+- 1/4) |  | ||||||
| 	std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/4)"<<std::endl; |  | ||||||
| 	remez.generateApprox(param.degree,1,4); |  | ||||||
|    	PowerQuarter.Init(remez,param.tolerance,false); |  | ||||||
| 	PowerNegQuarter.Init(remez,param.tolerance,true); |  | ||||||
|       }; |  | ||||||
|  |  | ||||||
|       virtual std::string action_name(){return "OneFlavourEvenOddRatioRationalPseudoFermionAction";}       |       virtual std::string action_name(){return "OneFlavourEvenOddRatioRationalPseudoFermionAction";}       | ||||||
|  |  | ||||||
|       virtual std::string LogParameters(){ |  | ||||||
| 	std::stringstream sstream; |  | ||||||
| 	sstream << GridLogMessage << "["<<action_name()<<"] Low            :" << param.lo <<  std::endl; |  | ||||||
| 	sstream << GridLogMessage << "["<<action_name()<<"] High           :" << param.hi <<  std::endl; |  | ||||||
| 	sstream << GridLogMessage << "["<<action_name()<<"] Max iterations :" << param.MaxIter <<  std::endl; |  | ||||||
| 	sstream << GridLogMessage << "["<<action_name()<<"] Tolerance      :" << param.tolerance <<  std::endl; |  | ||||||
| 	sstream << GridLogMessage << "["<<action_name()<<"] Degree         :" << param.degree <<  std::endl; |  | ||||||
| 	sstream << GridLogMessage << "["<<action_name()<<"] Precision      :" << param.precision <<  std::endl; |  | ||||||
| 	return sstream.str(); |  | ||||||
|       } |  | ||||||
|        |  | ||||||
|        |  | ||||||
|       virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) { |  | ||||||
|  |  | ||||||
| 	// S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi        |  | ||||||
| 	// |  | ||||||
| 	// P(phi) = e^{- phi^dag (VdagV)^1/4 (MdagM)^-1/2 (VdagV)^1/4 phi} |  | ||||||
| 	//        = e^{- phi^dag  (VdagV)^1/4 (MdagM)^-1/4 (MdagM)^-1/4  (VdagV)^1/4 phi} |  | ||||||
| 	// |  | ||||||
| 	// Phi =  (VdagV)^-1/4 Mdag^{1/4} eta  |  | ||||||
| 	// |  | ||||||
| 	// P(eta) = e^{- eta^dag eta} |  | ||||||
| 	// |  | ||||||
| 	// e^{x^2/2 sig^2} => sig^2 = 0.5. |  | ||||||
| 	//  |  | ||||||
| 	// So eta should be of width sig = 1/sqrt(2). |  | ||||||
|  |  | ||||||
| 	RealD scale = std::sqrt(0.5); |  | ||||||
|  |  | ||||||
| 	FermionField eta(NumOp.FermionGrid()); |  | ||||||
| 	FermionField etaOdd (NumOp.FermionRedBlackGrid()); |  | ||||||
| 	FermionField etaEven(NumOp.FermionRedBlackGrid()); |  | ||||||
| 	FermionField     tmp(NumOp.FermionRedBlackGrid()); |  | ||||||
|  |  | ||||||
| 	gaussian(pRNG,eta);	eta=eta*scale; |  | ||||||
|  |  | ||||||
| 	pickCheckerboard(Even,etaEven,eta); |  | ||||||
| 	pickCheckerboard(Odd,etaOdd,eta); |  | ||||||
|  |  | ||||||
| 	NumOp.ImportGauge(U); |  | ||||||
| 	DenOp.ImportGauge(U); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	// MdagM^1/4 eta |  | ||||||
| 	SchurDifferentiableOperator<Impl> MdagM(DenOp); |  | ||||||
| 	ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerQuarter); |  | ||||||
| 	msCG_M(MdagM,etaOdd,tmp); |  | ||||||
|  |  | ||||||
| 	// VdagV^-1/4 MdagM^1/4 eta |  | ||||||
| 	SchurDifferentiableOperator<Impl> VdagV(NumOp); |  | ||||||
| 	ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerNegQuarter); |  | ||||||
| 	msCG_V(VdagV,tmp,PhiOdd); |  | ||||||
|  |  | ||||||
| 	assert(NumOp.ConstEE() == 1); |  | ||||||
| 	assert(DenOp.ConstEE() == 1); |  | ||||||
| 	PhiEven = Zero(); |  | ||||||
| 	 |  | ||||||
|       }; |  | ||||||
|  |  | ||||||
|       ////////////////////////////////////////////////////// |  | ||||||
|       // S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi        |  | ||||||
|       ////////////////////////////////////////////////////// |  | ||||||
|       virtual RealD S(const GaugeField &U) { |  | ||||||
|  |  | ||||||
| 	NumOp.ImportGauge(U); |  | ||||||
| 	DenOp.ImportGauge(U); |  | ||||||
|  |  | ||||||
| 	FermionField X(NumOp.FermionRedBlackGrid()); |  | ||||||
| 	FermionField Y(NumOp.FermionRedBlackGrid()); |  | ||||||
|  |  | ||||||
| 	// VdagV^1/4 Phi |  | ||||||
| 	SchurDifferentiableOperator<Impl> VdagV(NumOp); |  | ||||||
| 	ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter); |  | ||||||
| 	msCG_V(VdagV,PhiOdd,X); |  | ||||||
|  |  | ||||||
| 	// MdagM^-1/4 VdagV^1/4 Phi |  | ||||||
| 	SchurDifferentiableOperator<Impl> MdagM(DenOp); |  | ||||||
| 	ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegQuarter); |  | ||||||
| 	msCG_M(MdagM,X,Y); |  | ||||||
|  |  | ||||||
| 	// Randomly apply rational bounds checks. |  | ||||||
| 	auto grid = NumOp.FermionGrid(); |  | ||||||
|         auto r=rand(); |  | ||||||
|         grid->Broadcast(0,r); |  | ||||||
|         if ( (r%param.BoundsCheckFreq)==0 ) {  |  | ||||||
| 	  FermionField gauss(NumOp.FermionRedBlackGrid()); |  | ||||||
| 	  gauss = PhiOdd; |  | ||||||
| 	  HighBoundCheck(MdagM,gauss,param.hi); |  | ||||||
| 	  InverseSqrtBoundsCheck(param.MaxIter,param.tolerance*100,MdagM,gauss,PowerNegHalf); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	//  Phidag VdagV^1/4 MdagM^-1/4  MdagM^-1/4 VdagV^1/4 Phi |  | ||||||
| 	RealD action = norm2(Y); |  | ||||||
|  |  | ||||||
| 	return action; |  | ||||||
|       }; |  | ||||||
|  |  | ||||||
|       // S_f = chi^dag* P(V^dag*V)/Q(V^dag*V)* N(M^dag*M)/D(M^dag*M)* P(V^dag*V)/Q(V^dag*V)* chi        |  | ||||||
|       // |  | ||||||
|       // Here, M is some 5D operator and V is the Pauli-Villars field |  | ||||||
|       // N and D makeup the rat. poly of the M term and P and & makeup the rat.poly of the denom term |  | ||||||
|       // |  | ||||||
|       // Need   |  | ||||||
|       // dS_f/dU =  chi^dag d[P/Q]  N/D   P/Q  chi  |  | ||||||
|       //         +  chi^dag   P/Q d[N/D]  P/Q  chi  |  | ||||||
|       //         +  chi^dag   P/Q   N/D d[P/Q] chi  |  | ||||||
|       // |  | ||||||
|       // P/Q is expressed as partial fraction expansion:  |  | ||||||
|       //  |  | ||||||
|       //           a0 + \sum_k ak/(V^dagV + bk)  |  | ||||||
|       //   |  | ||||||
|       // d[P/Q] is then   |  | ||||||
|       // |  | ||||||
|       //          \sum_k -ak [V^dagV+bk]^{-1}  [ dV^dag V + V^dag dV ] [V^dag V + bk]^{-1}  |  | ||||||
|       //   |  | ||||||
|       // and similar for N/D.  |  | ||||||
|       //  |  | ||||||
|       // Need    |  | ||||||
|       //       MpvPhi_k   = [Vdag V + bk]^{-1} chi   |  | ||||||
|       //       MpvPhi     = {a0 +  \sum_k ak [Vdag V + bk]^{-1} }chi    |  | ||||||
|       //    |  | ||||||
|       //       MfMpvPhi_k = [MdagM+bk]^{-1} MpvPhi   |  | ||||||
|       //       MfMpvPhi   = {a0 +  \sum_k ak [Mdag M + bk]^{-1} } MpvPhi |  | ||||||
|       //  |  | ||||||
|       //       MpvMfMpvPhi_k = [Vdag V + bk]^{-1} MfMpvchi    |  | ||||||
|       //   |  | ||||||
|  |  | ||||||
|       virtual void deriv(const GaugeField &U,GaugeField & dSdU) { |  | ||||||
|  |  | ||||||
| 	const int n_f  = PowerNegHalf.poles.size(); |  | ||||||
| 	const int n_pv = PowerQuarter.poles.size(); |  | ||||||
|  |  | ||||||
| 	std::vector<FermionField> MpvPhi_k     (n_pv,NumOp.FermionRedBlackGrid()); |  | ||||||
| 	std::vector<FermionField> MpvMfMpvPhi_k(n_pv,NumOp.FermionRedBlackGrid()); |  | ||||||
| 	std::vector<FermionField> MfMpvPhi_k   (n_f ,NumOp.FermionRedBlackGrid()); |  | ||||||
|  |  | ||||||
| 	FermionField      MpvPhi(NumOp.FermionRedBlackGrid()); |  | ||||||
| 	FermionField    MfMpvPhi(NumOp.FermionRedBlackGrid()); |  | ||||||
| 	FermionField MpvMfMpvPhi(NumOp.FermionRedBlackGrid()); |  | ||||||
| 	FermionField           Y(NumOp.FermionRedBlackGrid()); |  | ||||||
|  |  | ||||||
| 	GaugeField   tmp(NumOp.GaugeGrid()); |  | ||||||
|  |  | ||||||
| 	NumOp.ImportGauge(U); |  | ||||||
| 	DenOp.ImportGauge(U); |  | ||||||
|  |  | ||||||
| 	SchurDifferentiableOperator<Impl> VdagV(NumOp); |  | ||||||
| 	SchurDifferentiableOperator<Impl> MdagM(DenOp); |  | ||||||
|  |  | ||||||
| 	ConjugateGradientMultiShift<FermionField> msCG_V(param.MaxIter,PowerQuarter); |  | ||||||
| 	ConjugateGradientMultiShift<FermionField> msCG_M(param.MaxIter,PowerNegHalf); |  | ||||||
|  |  | ||||||
| 	msCG_V(VdagV,PhiOdd,MpvPhi_k,MpvPhi); |  | ||||||
| 	msCG_M(MdagM,MpvPhi,MfMpvPhi_k,MfMpvPhi); |  | ||||||
| 	msCG_V(VdagV,MfMpvPhi,MpvMfMpvPhi_k,MpvMfMpvPhi); |  | ||||||
|  |  | ||||||
| 	RealD ak; |  | ||||||
|  |  | ||||||
| 	dSdU = Zero(); |  | ||||||
|  |  | ||||||
| 	// With these building blocks   |  | ||||||
| 	//   |  | ||||||
| 	//       dS/dU =  |  | ||||||
| 	//                 \sum_k -ak MfMpvPhi_k^dag      [ dM^dag M + M^dag dM ] MfMpvPhi_k         (1) |  | ||||||
| 	//             +   \sum_k -ak MpvMfMpvPhi_k^\dag  [ dV^dag V + V^dag dV ] MpvPhi_k           (2) |  | ||||||
| 	//                        -ak MpvPhi_k^dag        [ dV^dag V + V^dag dV ] MpvMfMpvPhi_k      (3) |  | ||||||
|  |  | ||||||
| 	//(1) |  | ||||||
| 	for(int k=0;k<n_f;k++){ |  | ||||||
| 	  ak = PowerNegHalf.residues[k]; |  | ||||||
| 	  MdagM.Mpc(MfMpvPhi_k[k],Y); |  | ||||||
| 	  MdagM.MpcDagDeriv(tmp , MfMpvPhi_k[k], Y );  dSdU=dSdU+ak*tmp; |  | ||||||
| 	  MdagM.MpcDeriv(tmp , Y, MfMpvPhi_k[k] );  dSdU=dSdU+ak*tmp; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	//(2) |  | ||||||
| 	//(3) |  | ||||||
| 	for(int k=0;k<n_pv;k++){ |  | ||||||
|  |  | ||||||
|           ak = PowerQuarter.residues[k]; |  | ||||||
| 	   |  | ||||||
| 	  VdagV.Mpc(MpvPhi_k[k],Y); |  | ||||||
| 	  VdagV.MpcDagDeriv(tmp,MpvMfMpvPhi_k[k],Y); dSdU=dSdU+ak*tmp; |  | ||||||
| 	  VdagV.MpcDeriv   (tmp,Y,MpvMfMpvPhi_k[k]);  dSdU=dSdU+ak*tmp;      |  | ||||||
| 	   |  | ||||||
| 	  VdagV.Mpc(MpvMfMpvPhi_k[k],Y);                // V as we take Ydag  |  | ||||||
| 	  VdagV.MpcDeriv   (tmp,Y, MpvPhi_k[k]); dSdU=dSdU+ak*tmp; |  | ||||||
| 	  VdagV.MpcDagDeriv(tmp,MpvPhi_k[k], Y); dSdU=dSdU+ak*tmp; |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	//dSdU = Ta(dSdU); |  | ||||||
|  |  | ||||||
|       }; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|   | |||||||
| @@ -40,6 +40,8 @@ directory | |||||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourRational.h> | #include <Grid/qcd/action/pseudofermion/OneFlavourRational.h> | ||||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourRationalRatio.h> | #include <Grid/qcd/action/pseudofermion/OneFlavourRationalRatio.h> | ||||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRational.h> | #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRational.h> | ||||||
|  | #include <Grid/qcd/action/pseudofermion/GeneralEvenOddRationalRatio.h> | ||||||
|  | #include <Grid/qcd/action/pseudofermion/GeneralEvenOddRationalRatioMixedPrec.h> | ||||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRationalRatio.h> | #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRationalRatio.h> | ||||||
| #include <Grid/qcd/action/pseudofermion/ExactOneFlavourRatio.h> | #include <Grid/qcd/action/pseudofermion/ExactOneFlavourRatio.h> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -83,16 +83,10 @@ NAMESPACE_BEGIN(Grid); | |||||||
| 	return sstream.str(); | 	return sstream.str(); | ||||||
|       }  |       }  | ||||||
|  |  | ||||||
|  |       //Access the fermion field | ||||||
|  |       const FermionField &getPhiOdd() const{ return PhiOdd; } | ||||||
|  |  | ||||||
|       virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) { |       virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) { | ||||||
|  |  | ||||||
|         // P(phi) = e^{- phi^dag Vpc (MpcdagMpc)^-1 Vpcdag phi} |  | ||||||
|         // |  | ||||||
|         // NumOp == V |  | ||||||
|         // DenOp == M |  | ||||||
|         // |  | ||||||
|         // Take phi_o = Vpcdag^{-1} Mpcdag eta_o  ; eta_o = Mpcdag^{-1} Vpcdag Phi |  | ||||||
|         // |  | ||||||
|         // P(eta_o) = e^{- eta_o^dag eta_o} |         // P(eta_o) = e^{- eta_o^dag eta_o} | ||||||
|         // |         // | ||||||
|         // e^{x^2/2 sig^2} => sig^2 = 0.5. |         // e^{x^2/2 sig^2} => sig^2 = 0.5. | ||||||
| @@ -100,12 +94,22 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         RealD scale = std::sqrt(0.5); |         RealD scale = std::sqrt(0.5); | ||||||
|  |  | ||||||
|         FermionField eta    (NumOp.FermionGrid()); |         FermionField eta    (NumOp.FermionGrid()); | ||||||
|  |         gaussian(pRNG,eta); eta = eta * scale; | ||||||
|  |  | ||||||
|  | 	refresh(U,eta); | ||||||
|  |       } | ||||||
|  | 	 | ||||||
|  |       void refresh(const GaugeField &U, const FermionField &eta) { | ||||||
|  |         // P(phi) = e^{- phi^dag Vpc (MpcdagMpc)^-1 Vpcdag phi} | ||||||
|  |         // | ||||||
|  |         // NumOp == V | ||||||
|  |         // DenOp == M | ||||||
|  |         // | ||||||
|  |         // Take phi_o = Vpcdag^{-1} Mpcdag eta_o  ; eta_o = Mpcdag^{-1} Vpcdag Phi | ||||||
|         FermionField etaOdd (NumOp.FermionRedBlackGrid()); |         FermionField etaOdd (NumOp.FermionRedBlackGrid()); | ||||||
|         FermionField etaEven(NumOp.FermionRedBlackGrid()); |         FermionField etaEven(NumOp.FermionRedBlackGrid()); | ||||||
|         FermionField tmp    (NumOp.FermionRedBlackGrid()); |         FermionField tmp    (NumOp.FermionRedBlackGrid()); | ||||||
|  |  | ||||||
|         gaussian(pRNG,eta); |  | ||||||
|  |  | ||||||
|         pickCheckerboard(Even,etaEven,eta); |         pickCheckerboard(Even,etaEven,eta); | ||||||
|         pickCheckerboard(Odd,etaOdd,eta); |         pickCheckerboard(Odd,etaOdd,eta); | ||||||
|  |  | ||||||
| @@ -125,8 +129,8 @@ NAMESPACE_BEGIN(Grid); | |||||||
|         DenOp.MooeeDag(etaEven,tmp); |         DenOp.MooeeDag(etaEven,tmp); | ||||||
|         NumOp.MooeeInvDag(tmp,PhiEven); |         NumOp.MooeeInvDag(tmp,PhiEven); | ||||||
|  |  | ||||||
|         PhiOdd =PhiOdd*scale; |         //PhiOdd =PhiOdd*scale; | ||||||
|         PhiEven=PhiEven*scale; |         //PhiEven=PhiEven*scale; | ||||||
|          |          | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								Grid/qcd/gparity/Gparity.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Grid/qcd/gparity/Gparity.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #ifndef GRID_GPARITY_H_ | ||||||
|  | #define GRID_GPARITY_H_ | ||||||
|  |  | ||||||
|  | #include<Grid/qcd/gparity/GparityFlavour.h> | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										34
									
								
								Grid/qcd/gparity/GparityFlavour.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Grid/qcd/gparity/GparityFlavour.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | #include <Grid/Grid.h> | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | const std::array<const GparityFlavour, 3> GparityFlavour::sigma_mu = {{ | ||||||
|  |     GparityFlavour(GparityFlavour::Algebra::SigmaX), | ||||||
|  |     GparityFlavour(GparityFlavour::Algebra::SigmaY), | ||||||
|  |     GparityFlavour(GparityFlavour::Algebra::SigmaZ) | ||||||
|  |     }}; | ||||||
|  |  | ||||||
|  | const std::array<const GparityFlavour, 6> GparityFlavour::sigma_all = {{ | ||||||
|  |   GparityFlavour(GparityFlavour::Algebra::Identity), | ||||||
|  |   GparityFlavour(GparityFlavour::Algebra::SigmaX), | ||||||
|  |   GparityFlavour(GparityFlavour::Algebra::SigmaY), | ||||||
|  |   GparityFlavour(GparityFlavour::Algebra::SigmaZ), | ||||||
|  |   GparityFlavour(GparityFlavour::Algebra::ProjPlus), | ||||||
|  |   GparityFlavour(GparityFlavour::Algebra::ProjMinus) | ||||||
|  | }}; | ||||||
|  |  | ||||||
|  | const std::array<const char *, GparityFlavour::nSigma> GparityFlavour::name = {{ | ||||||
|  |     "SigmaX", | ||||||
|  |     "MinusSigmaX", | ||||||
|  |     "SigmaY", | ||||||
|  |     "MinusSigmaY", | ||||||
|  |     "SigmaZ", | ||||||
|  |     "MinusSigmaZ", | ||||||
|  |     "Identity", | ||||||
|  |     "MinusIdentity", | ||||||
|  |     "ProjPlus", | ||||||
|  |     "MinusProjPlus", | ||||||
|  |     "ProjMinus", | ||||||
|  |     "MinusProjMinus"}}; | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
							
								
								
									
										475
									
								
								Grid/qcd/gparity/GparityFlavour.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										475
									
								
								Grid/qcd/gparity/GparityFlavour.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,475 @@ | |||||||
|  | #ifndef GRID_QCD_GPARITY_FLAVOUR_H | ||||||
|  | #define GRID_QCD_GPARITY_FLAVOUR_H | ||||||
|  |  | ||||||
|  | //Support for flavour-matrix operations acting on the G-parity flavour index | ||||||
|  |  | ||||||
|  | #include <array> | ||||||
|  |  | ||||||
|  | NAMESPACE_BEGIN(Grid); | ||||||
|  |  | ||||||
|  | class GparityFlavour { | ||||||
|  |   public: | ||||||
|  |     GRID_SERIALIZABLE_ENUM(Algebra, undef, | ||||||
|  |                            SigmaX, 0, | ||||||
|  | 			   MinusSigmaX, 1, | ||||||
|  |                            SigmaY, 2, | ||||||
|  | 			   MinusSigmaY, 3, | ||||||
|  |                            SigmaZ, 4, | ||||||
|  | 			   MinusSigmaZ, 5, | ||||||
|  | 			   Identity, 6, | ||||||
|  | 			   MinusIdentity, 7, | ||||||
|  | 			   ProjPlus, 8, | ||||||
|  | 			   MinusProjPlus, 9, | ||||||
|  | 			   ProjMinus, 10, | ||||||
|  | 			   MinusProjMinus, 11 | ||||||
|  | 			   ); | ||||||
|  |     static constexpr unsigned int nSigma = 12; | ||||||
|  |     static const std::array<const char *, nSigma>                name; | ||||||
|  |     static const std::array<const GparityFlavour, 3>             sigma_mu; | ||||||
|  |     static const std::array<const GparityFlavour, 6>            sigma_all; | ||||||
|  |     Algebra                                                      g; | ||||||
|  |   public: | ||||||
|  |   accelerator GparityFlavour(Algebra initg): g(initg) {}   | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // 0 1  x   vector | ||||||
|  | // 1 0 | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourSigmaX(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = rhs(1); | ||||||
|  |   ret(1) = rhs(0); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourSigmaX(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = rhs(1,0); | ||||||
|  |   ret(0,1) = rhs(1,1); | ||||||
|  |   ret(1,0) = rhs(0,0); | ||||||
|  |   ret(1,1) = rhs(0,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourSigmaX(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = rhs(0,1); | ||||||
|  |   ret(0,1) = rhs(0,0); | ||||||
|  |   ret(1,0) = rhs(1,1); | ||||||
|  |   ret(1,1) = rhs(1,0); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourMinusSigmaX(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = -rhs(1); | ||||||
|  |   ret(1) = -rhs(0); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourMinusSigmaX(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -rhs(1,0); | ||||||
|  |   ret(0,1) = -rhs(1,1); | ||||||
|  |   ret(1,0) = -rhs(0,0); | ||||||
|  |   ret(1,1) = -rhs(0,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourMinusSigmaX(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -rhs(0,1); | ||||||
|  |   ret(0,1) = -rhs(0,0); | ||||||
|  |   ret(1,0) = -rhs(1,1); | ||||||
|  |   ret(1,1) = -rhs(1,0); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // 0 -i  x   vector | ||||||
|  | // i 0 | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourSigmaY(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = timesMinusI(rhs(1)); | ||||||
|  |   ret(1) = timesI(rhs(0)); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourSigmaY(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = timesMinusI(rhs(1,0)); | ||||||
|  |   ret(0,1) = timesMinusI(rhs(1,1)); | ||||||
|  |   ret(1,0) = timesI(rhs(0,0)); | ||||||
|  |   ret(1,1) = timesI(rhs(0,1)); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourSigmaY(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = timesI(rhs(0,1)); | ||||||
|  |   ret(0,1) = timesMinusI(rhs(0,0)); | ||||||
|  |   ret(1,0) = timesI(rhs(1,1)); | ||||||
|  |   ret(1,1) = timesMinusI(rhs(1,0)); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourMinusSigmaY(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = timesI(rhs(1)); | ||||||
|  |   ret(1) = timesMinusI(rhs(0)); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourMinusSigmaY(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = timesI(rhs(1,0)); | ||||||
|  |   ret(0,1) = timesI(rhs(1,1)); | ||||||
|  |   ret(1,0) = timesMinusI(rhs(0,0)); | ||||||
|  |   ret(1,1) = timesMinusI(rhs(0,1)); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourMinusSigmaY(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = timesMinusI(rhs(0,1)); | ||||||
|  |   ret(0,1) = timesI(rhs(0,0)); | ||||||
|  |   ret(1,0) = timesMinusI(rhs(1,1)); | ||||||
|  |   ret(1,1) = timesI(rhs(1,0)); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // 1 0  x   vector | ||||||
|  | // 0 -1 | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourSigmaZ(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = rhs(0); | ||||||
|  |   ret(1) = -rhs(1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourSigmaZ(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = rhs(0,0); | ||||||
|  |   ret(0,1) = rhs(0,1); | ||||||
|  |   ret(1,0) = -rhs(1,0); | ||||||
|  |   ret(1,1) = -rhs(1,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourSigmaZ(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = rhs(0,0); | ||||||
|  |   ret(0,1) = -rhs(0,1); | ||||||
|  |   ret(1,0) = rhs(1,0); | ||||||
|  |   ret(1,1) = -rhs(1,1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourMinusSigmaZ(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = -rhs(0); | ||||||
|  |   ret(1) = rhs(1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourMinusSigmaZ(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -rhs(0,0); | ||||||
|  |   ret(0,1) = -rhs(0,1); | ||||||
|  |   ret(1,0) = rhs(1,0); | ||||||
|  |   ret(1,1) = rhs(1,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourMinusSigmaZ(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -rhs(0,0); | ||||||
|  |   ret(0,1) = rhs(0,1); | ||||||
|  |   ret(1,0) = -rhs(1,0); | ||||||
|  |   ret(1,1) = rhs(1,1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourIdentity(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = rhs(0); | ||||||
|  |   ret(1) = rhs(1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourIdentity(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = rhs(0,0); | ||||||
|  |   ret(0,1) = rhs(0,1); | ||||||
|  |   ret(1,0) = rhs(1,0); | ||||||
|  |   ret(1,1) = rhs(1,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourIdentity(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = rhs(0,0); | ||||||
|  |   ret(0,1) = rhs(0,1); | ||||||
|  |   ret(1,0) = rhs(1,0); | ||||||
|  |   ret(1,1) = rhs(1,1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourMinusIdentity(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = -rhs(0); | ||||||
|  |   ret(1) = -rhs(1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourMinusIdentity(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -rhs(0,0); | ||||||
|  |   ret(0,1) = -rhs(0,1); | ||||||
|  |   ret(1,0) = -rhs(1,0); | ||||||
|  |   ret(1,1) = -rhs(1,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourMinusIdentity(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -rhs(0,0); | ||||||
|  |   ret(0,1) = -rhs(0,1); | ||||||
|  |   ret(1,0) = -rhs(1,0); | ||||||
|  |   ret(1,1) = -rhs(1,1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //G-parity flavour projection 1/2(1+\sigma_2) | ||||||
|  | //1 -i | ||||||
|  | //i  1 | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourProjPlus(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = 0.5*rhs(0) + 0.5*timesMinusI(rhs(1)); | ||||||
|  |   ret(1) = 0.5*timesI(rhs(0)) + 0.5*rhs(1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourProjPlus(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = 0.5*rhs(0,0) + 0.5*timesMinusI(rhs(1,0)); | ||||||
|  |   ret(0,1) = 0.5*rhs(0,1) + 0.5*timesMinusI(rhs(1,1)); | ||||||
|  |   ret(1,0) = 0.5*timesI(rhs(0,0)) + 0.5*rhs(1,0); | ||||||
|  |   ret(1,1) = 0.5*timesI(rhs(0,1)) + 0.5*rhs(1,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourProjPlus(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = 0.5*rhs(0,0) + 0.5*timesI(rhs(0,1)); | ||||||
|  |   ret(0,1) = 0.5*timesMinusI(rhs(0,0)) + 0.5*rhs(0,1); | ||||||
|  |   ret(1,0) = 0.5*rhs(1,0) + 0.5*timesI(rhs(1,1)); | ||||||
|  |   ret(1,1) = 0.5*timesMinusI(rhs(1,0)) + 0.5*rhs(1,1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourMinusProjPlus(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = -0.5*rhs(0) + 0.5*timesI(rhs(1)); | ||||||
|  |   ret(1) = 0.5*timesMinusI(rhs(0)) - 0.5*rhs(1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourMinusProjPlus(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -0.5*rhs(0,0) + 0.5*timesI(rhs(1,0)); | ||||||
|  |   ret(0,1) = -0.5*rhs(0,1) + 0.5*timesI(rhs(1,1)); | ||||||
|  |   ret(1,0) = 0.5*timesMinusI(rhs(0,0)) - 0.5*rhs(1,0); | ||||||
|  |   ret(1,1) = 0.5*timesMinusI(rhs(0,1)) - 0.5*rhs(1,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourMinusProjPlus(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -0.5*rhs(0,0) + 0.5*timesMinusI(rhs(0,1)); | ||||||
|  |   ret(0,1) = 0.5*timesI(rhs(0,0)) - 0.5*rhs(0,1); | ||||||
|  |   ret(1,0) = -0.5*rhs(1,0) + 0.5*timesMinusI(rhs(1,1)); | ||||||
|  |   ret(1,1) = 0.5*timesI(rhs(1,0)) - 0.5*rhs(1,1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //G-parity flavour projection 1/2(1-\sigma_2) | ||||||
|  | //1 i | ||||||
|  | //-i  1 | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourProjMinus(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = 0.5*rhs(0) + 0.5*timesI(rhs(1)); | ||||||
|  |   ret(1) = 0.5*timesMinusI(rhs(0)) + 0.5*rhs(1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourProjMinus(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = 0.5*rhs(0,0) + 0.5*timesI(rhs(1,0)); | ||||||
|  |   ret(0,1) = 0.5*rhs(0,1) + 0.5*timesI(rhs(1,1)); | ||||||
|  |   ret(1,0) = 0.5*timesMinusI(rhs(0,0)) + 0.5*rhs(1,0); | ||||||
|  |   ret(1,1) = 0.5*timesMinusI(rhs(0,1)) + 0.5*rhs(1,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourProjMinus(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = 0.5*rhs(0,0) + 0.5*timesMinusI(rhs(0,1)); | ||||||
|  |   ret(0,1) = 0.5*timesI(rhs(0,0)) + 0.5*rhs(0,1); | ||||||
|  |   ret(1,0) = 0.5*rhs(1,0) + 0.5*timesMinusI(rhs(1,1)); | ||||||
|  |   ret(1,1) = 0.5*timesI(rhs(1,0)) + 0.5*rhs(1,1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void multFlavourMinusProjMinus(iVector<vtype, Ngp> &ret, const iVector<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0) = -0.5*rhs(0) + 0.5*timesMinusI(rhs(1)); | ||||||
|  |   ret(1) = 0.5*timesI(rhs(0)) - 0.5*rhs(1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void lmultFlavourMinusProjMinus(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -0.5*rhs(0,0) + 0.5*timesMinusI(rhs(1,0)); | ||||||
|  |   ret(0,1) = -0.5*rhs(0,1) + 0.5*timesMinusI(rhs(1,1)); | ||||||
|  |   ret(1,0) = 0.5*timesI(rhs(0,0)) - 0.5*rhs(1,0); | ||||||
|  |   ret(1,1) = 0.5*timesI(rhs(0,1)) - 0.5*rhs(1,1); | ||||||
|  | }; | ||||||
|  | template<class vtype> | ||||||
|  | accelerator_inline void rmultFlavourMinusProjMinus(iMatrix<vtype, Ngp> &ret, const iMatrix<vtype, Ngp> &rhs) | ||||||
|  | { | ||||||
|  |   ret(0,0) = -0.5*rhs(0,0) + 0.5*timesI(rhs(0,1)); | ||||||
|  |   ret(0,1) = 0.5*timesMinusI(rhs(0,0)) - 0.5*rhs(0,1); | ||||||
|  |   ret(1,0) = -0.5*rhs(1,0) + 0.5*timesI(rhs(1,1)); | ||||||
|  |   ret(1,1) = 0.5*timesMinusI(rhs(1,0)) - 0.5*rhs(1,1); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template<class vtype>  | ||||||
|  | accelerator_inline auto operator*(const GparityFlavour &G, const iVector<vtype, Ngp> &arg) | ||||||
|  | ->typename std::enable_if<matchGridTensorIndex<iVector<vtype, Ngp>, GparityFlavourTensorIndex>::value, iVector<vtype, Ngp>>::type | ||||||
|  | { | ||||||
|  |   iVector<vtype, Ngp> ret; | ||||||
|  |  | ||||||
|  |   switch (G.g)  | ||||||
|  |   { | ||||||
|  |   case GparityFlavour::Algebra::SigmaX: | ||||||
|  |     multFlavourSigmaX(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaX: | ||||||
|  |     multFlavourMinusSigmaX(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::SigmaY: | ||||||
|  |     multFlavourSigmaY(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaY: | ||||||
|  |     multFlavourMinusSigmaY(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::SigmaZ: | ||||||
|  |     multFlavourSigmaZ(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaZ: | ||||||
|  |     multFlavourMinusSigmaZ(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::Identity: | ||||||
|  |     multFlavourIdentity(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusIdentity: | ||||||
|  |     multFlavourMinusIdentity(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::ProjPlus: | ||||||
|  |     multFlavourProjPlus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusProjPlus: | ||||||
|  |     multFlavourMinusProjPlus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::ProjMinus: | ||||||
|  |     multFlavourProjMinus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusProjMinus: | ||||||
|  |     multFlavourMinusProjMinus(ret, arg); break; | ||||||
|  |   default: assert(0); | ||||||
|  |   } | ||||||
|  |   | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<class vtype>  | ||||||
|  | accelerator_inline auto operator*(const GparityFlavour &G, const iMatrix<vtype, Ngp> &arg) | ||||||
|  | ->typename std::enable_if<matchGridTensorIndex<iMatrix<vtype, Ngp>, GparityFlavourTensorIndex>::value, iMatrix<vtype, Ngp>>::type | ||||||
|  | { | ||||||
|  |   iMatrix<vtype, Ngp> ret; | ||||||
|  |  | ||||||
|  |   switch (G.g)  | ||||||
|  |   { | ||||||
|  |   case GparityFlavour::Algebra::SigmaX: | ||||||
|  |     lmultFlavourSigmaX(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaX: | ||||||
|  |     lmultFlavourMinusSigmaX(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::SigmaY: | ||||||
|  |     lmultFlavourSigmaY(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaY: | ||||||
|  |     lmultFlavourMinusSigmaY(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::SigmaZ: | ||||||
|  |     lmultFlavourSigmaZ(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaZ: | ||||||
|  |     lmultFlavourMinusSigmaZ(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::Identity: | ||||||
|  |     lmultFlavourIdentity(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusIdentity: | ||||||
|  |     lmultFlavourMinusIdentity(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::ProjPlus: | ||||||
|  |     lmultFlavourProjPlus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusProjPlus: | ||||||
|  |     lmultFlavourMinusProjPlus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::ProjMinus: | ||||||
|  |     lmultFlavourProjMinus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusProjMinus: | ||||||
|  |     lmultFlavourMinusProjMinus(ret, arg); break;   | ||||||
|  |   default: assert(0); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<class vtype>  | ||||||
|  | accelerator_inline auto operator*(const iMatrix<vtype, Ngp> &arg, const GparityFlavour &G) | ||||||
|  | ->typename std::enable_if<matchGridTensorIndex<iMatrix<vtype, Ngp>, GparityFlavourTensorIndex>::value, iMatrix<vtype, Ngp>>::type | ||||||
|  | { | ||||||
|  |   iMatrix<vtype, Ngp> ret; | ||||||
|  |  | ||||||
|  |   switch (G.g)  | ||||||
|  |   { | ||||||
|  |   case GparityFlavour::Algebra::SigmaX: | ||||||
|  |     rmultFlavourSigmaX(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaX: | ||||||
|  |     rmultFlavourMinusSigmaX(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::SigmaY: | ||||||
|  |     rmultFlavourSigmaY(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaY: | ||||||
|  |     rmultFlavourMinusSigmaY(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::SigmaZ: | ||||||
|  |     rmultFlavourSigmaZ(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusSigmaZ: | ||||||
|  |     rmultFlavourMinusSigmaZ(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::Identity: | ||||||
|  |     rmultFlavourIdentity(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusIdentity: | ||||||
|  |     rmultFlavourMinusIdentity(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::ProjPlus: | ||||||
|  |     rmultFlavourProjPlus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusProjPlus: | ||||||
|  |     rmultFlavourMinusProjPlus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::ProjMinus: | ||||||
|  |     rmultFlavourProjMinus(ret, arg); break; | ||||||
|  |   case GparityFlavour::Algebra::MinusProjMinus: | ||||||
|  |     rmultFlavourMinusProjMinus(ret, arg); break; | ||||||
|  |   default: assert(0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | NAMESPACE_END(Grid); | ||||||
|  |  | ||||||
|  | #endif // include guard | ||||||
| @@ -129,18 +129,10 @@ public: | |||||||
|     Runner(S); |     Runner(S); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ////////////////////////////////////////////////////////////////// |   //Use the checkpointer to initialize the RNGs and the gauge field, writing the resulting gauge field into U. | ||||||
|  |   //This is called automatically by Run but may be useful elsewhere, e.g. for integrator tuning experiments | ||||||
| private: |   void initializeGaugeFieldAndRNGs(Field &U){ | ||||||
|   template <class SmearingPolicy> |     if(!Resources.haveRNGs()) Resources.AddRNGs(); | ||||||
|   void Runner(SmearingPolicy &Smearing) { |  | ||||||
|     auto UGrid = Resources.GetCartesian(); |  | ||||||
|     Resources.AddRNGs(); |  | ||||||
|     Field U(UGrid); |  | ||||||
|  |  | ||||||
|     // Can move this outside? |  | ||||||
|     typedef IntegratorType<SmearingPolicy> TheIntegrator; |  | ||||||
|     TheIntegrator MDynamics(UGrid, Parameters.MD, TheAction, Smearing); |  | ||||||
|  |  | ||||||
|     if (Parameters.StartingType == "HotStart") { |     if (Parameters.StartingType == "HotStart") { | ||||||
|       // Hot start |       // Hot start | ||||||
| @@ -159,14 +151,40 @@ private: | |||||||
|       Resources.GetCheckPointer()->CheckpointRestore(Parameters.StartTrajectory, U, |       Resources.GetCheckPointer()->CheckpointRestore(Parameters.StartTrajectory, U, | ||||||
| 						     Resources.GetSerialRNG(), | 						     Resources.GetSerialRNG(), | ||||||
| 						     Resources.GetParallelRNG()); | 						     Resources.GetParallelRNG()); | ||||||
|  |     } else if (Parameters.StartingType == "CheckpointStartReseed") { | ||||||
|  |       // Same as CheckpointRestart but reseed the RNGs using the fixed integer seeding used for ColdStart and HotStart | ||||||
|  |       // Useful for creating new evolution streams from an existing stream | ||||||
|  |        | ||||||
|  |       // WARNING: Unfortunately because the checkpointer doesn't presently allow us to separately restore the RNG and gauge fields we have to load | ||||||
|  |       // an existing RNG checkpoint first; make sure one is available and named correctly | ||||||
|  |       Resources.GetCheckPointer()->CheckpointRestore(Parameters.StartTrajectory, U, | ||||||
|  | 						     Resources.GetSerialRNG(), | ||||||
|  | 						     Resources.GetParallelRNG()); | ||||||
|  |       Resources.SeedFixedIntegers();       | ||||||
|     } else { |     } else { | ||||||
|       // others |       // others | ||||||
|       std::cout << GridLogError << "Unrecognized StartingType\n"; |       std::cout << GridLogError << "Unrecognized StartingType\n"; | ||||||
|       std::cout |       std::cout | ||||||
| 	<< GridLogError | 	<< GridLogError | ||||||
| 	<< "Valid [HotStart, ColdStart, TepidStart, CheckpointStart]\n"; | 	<< "Valid [HotStart, ColdStart, TepidStart, CheckpointStart, CheckpointStartReseed]\n"; | ||||||
|       exit(1); |       exit(1); | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   ////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |   template <class SmearingPolicy> | ||||||
|  |   void Runner(SmearingPolicy &Smearing) { | ||||||
|  |     auto UGrid = Resources.GetCartesian(); | ||||||
|  |     Field U(UGrid); | ||||||
|  |  | ||||||
|  |     initializeGaugeFieldAndRNGs(U); | ||||||
|  |  | ||||||
|  |     typedef IntegratorType<SmearingPolicy> TheIntegrator; | ||||||
|  |     TheIntegrator MDynamics(UGrid, Parameters.MD, TheAction, Smearing); | ||||||
|  |  | ||||||
|     Smearing.set_Field(U); |     Smearing.set_Field(U); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -115,21 +115,21 @@ private: | |||||||
|  |  | ||||||
|     random(sRNG, rn_test); |     random(sRNG, rn_test); | ||||||
|  |  | ||||||
|     std::cout << GridLogMessage |     std::cout << GridLogHMC | ||||||
|               << "--------------------------------------------------\n"; |               << "--------------------------------------------------\n"; | ||||||
|     std::cout << GridLogMessage << "exp(-dH) = " << prob |     std::cout << GridLogHMC << "exp(-dH) = " << prob | ||||||
|               << "  Random = " << rn_test << "\n"; |               << "  Random = " << rn_test << "\n"; | ||||||
|     std::cout << GridLogMessage |     std::cout << GridLogHMC | ||||||
|               << "Acc. Probability = " << ((prob < 1.0) ? prob : 1.0) << "\n"; |               << "Acc. Probability = " << ((prob < 1.0) ? prob : 1.0) << "\n"; | ||||||
|  |  | ||||||
|     if ((prob > 1.0) || (rn_test <= prob)) {  // accepted |     if ((prob > 1.0) || (rn_test <= prob)) {  // accepted | ||||||
|       std::cout << GridLogMessage << "Metropolis_test -- ACCEPTED\n"; |       std::cout << GridLogHMC << "Metropolis_test -- ACCEPTED\n"; | ||||||
|       std::cout << GridLogMessage |       std::cout << GridLogHMC | ||||||
|                 << "--------------------------------------------------\n"; |                 << "--------------------------------------------------\n"; | ||||||
|       return true; |       return true; | ||||||
|     } else {  // rejected |     } else {  // rejected | ||||||
|       std::cout << GridLogMessage << "Metropolis_test -- REJECTED\n"; |       std::cout << GridLogHMC << "Metropolis_test -- REJECTED\n"; | ||||||
|       std::cout << GridLogMessage |       std::cout << GridLogHMC | ||||||
|                 << "--------------------------------------------------\n"; |                 << "--------------------------------------------------\n"; | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
| @@ -145,7 +145,7 @@ private: | |||||||
|  |  | ||||||
|     std::streamsize current_precision = std::cout.precision(); |     std::streamsize current_precision = std::cout.precision(); | ||||||
|     std::cout.precision(15); |     std::cout.precision(15); | ||||||
|     std::cout << GridLogMessage << "Total H before trajectory = " << H0 << "\n"; |     std::cout << GridLogHMC << "Total H before trajectory = " << H0 << "\n"; | ||||||
|     std::cout.precision(current_precision); |     std::cout.precision(current_precision); | ||||||
|  |  | ||||||
|     TheIntegrator.integrate(U); |     TheIntegrator.integrate(U); | ||||||
| @@ -165,7 +165,7 @@ private: | |||||||
|  |  | ||||||
|  |  | ||||||
|     std::cout.precision(15); |     std::cout.precision(15); | ||||||
|     std::cout << GridLogMessage << "Total H after trajectory  = " << H1 |     std::cout << GridLogHMC << "Total H after trajectory  = " << H1 | ||||||
| 	      << "  dH = " << H1 - H0 << "\n"; | 	      << "  dH = " << H1 - H0 << "\n"; | ||||||
|     std::cout.precision(current_precision); |     std::cout.precision(current_precision); | ||||||
|      |      | ||||||
| @@ -196,9 +196,9 @@ public: | |||||||
|     // Actual updates (evolve a copy Ucopy then copy back eventually) |     // Actual updates (evolve a copy Ucopy then copy back eventually) | ||||||
|     unsigned int FinalTrajectory = Params.Trajectories + Params.NoMetropolisUntil + Params.StartTrajectory; |     unsigned int FinalTrajectory = Params.Trajectories + Params.NoMetropolisUntil + Params.StartTrajectory; | ||||||
|     for (int traj = Params.StartTrajectory; traj < FinalTrajectory; ++traj) { |     for (int traj = Params.StartTrajectory; traj < FinalTrajectory; ++traj) { | ||||||
|       std::cout << GridLogMessage << "-- # Trajectory = " << traj << "\n"; |       std::cout << GridLogHMC << "-- # Trajectory = " << traj << "\n"; | ||||||
|       if (traj < Params.StartTrajectory + Params.NoMetropolisUntil) { |       if (traj < Params.StartTrajectory + Params.NoMetropolisUntil) { | ||||||
|       	std::cout << GridLogMessage << "-- Thermalization" << std::endl; |       	std::cout << GridLogHMC << "-- Thermalization" << std::endl; | ||||||
|       } |       } | ||||||
|        |        | ||||||
|       double t0=usecond(); |       double t0=usecond(); | ||||||
| @@ -207,10 +207,10 @@ public: | |||||||
|       DeltaH = evolve_hmc_step(Ucopy); |       DeltaH = evolve_hmc_step(Ucopy); | ||||||
|       // Metropolis-Hastings test |       // Metropolis-Hastings test | ||||||
|       bool accept = true; |       bool accept = true; | ||||||
|       if (traj >= Params.StartTrajectory + Params.NoMetropolisUntil) { |       if (Params.MetropolisTest && traj >= Params.StartTrajectory + Params.NoMetropolisUntil) { | ||||||
|         accept = metropolis_test(DeltaH); |         accept = metropolis_test(DeltaH); | ||||||
|       } else { |       } else { | ||||||
|       	std::cout << GridLogMessage << "Skipping Metropolis test" << std::endl; |       	std::cout << GridLogHMC << "Skipping Metropolis test" << std::endl; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (accept) |       if (accept) | ||||||
| @@ -219,7 +219,7 @@ public: | |||||||
|       |       | ||||||
|        |        | ||||||
|       double t1=usecond(); |       double t1=usecond(); | ||||||
|       std::cout << GridLogMessage << "Total time for trajectory (s): " << (t1-t0)/1e6 << std::endl; |       std::cout << GridLogHMC << "Total time for trajectory (s): " << (t1-t0)/1e6 << std::endl; | ||||||
|  |  | ||||||
|  |  | ||||||
|       for (int obs = 0; obs < Observables.size(); obs++) { |       for (int obs = 0; obs < Observables.size(); obs++) { | ||||||
| @@ -228,7 +228,7 @@ public: | |||||||
|       	std::cout << GridLogDebug << "Observables pointer " << Observables[obs] << std::endl; |       	std::cout << GridLogDebug << "Observables pointer " << Observables[obs] << std::endl; | ||||||
|         Observables[obs]->TrajectoryComplete(traj + 1, Ucur, sRNG, pRNG); |         Observables[obs]->TrajectoryComplete(traj + 1, Ucur, sRNG, pRNG); | ||||||
|       } |       } | ||||||
|       std::cout << GridLogMessage << ":::::::::::::::::::::::::::::::::::::::::::" << std::endl; |       std::cout << GridLogHMC << ":::::::::::::::::::::::::::::::::::::::::::" << std::endl; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -80,7 +80,9 @@ public: | |||||||
|       std::cout << GridLogError << "Seeds not initialized" << std::endl; |       std::cout << GridLogError << "Seeds not initialized" << std::endl; | ||||||
|       exit(1); |       exit(1); | ||||||
|     } |     } | ||||||
|  |     std::cout << GridLogMessage << "Reseeding serial RNG with seed vector " << SerialSeeds << std::endl; | ||||||
|     sRNG_.SeedFixedIntegers(SerialSeeds); |     sRNG_.SeedFixedIntegers(SerialSeeds); | ||||||
|  |     std::cout << GridLogMessage << "Reseeding parallel RNG with seed vector " << ParallelSeeds << std::endl; | ||||||
|     pRNG_->SeedFixedIntegers(ParallelSeeds); |     pRNG_->SeedFixedIntegers(ParallelSeeds); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -227,6 +227,9 @@ public: | |||||||
|   // Random number generators |   // Random number generators | ||||||
|   ////////////////////////////////////////////////////// |   ////////////////////////////////////////////////////// | ||||||
|    |    | ||||||
|  |   //Return true if the RNG objects have been instantiated | ||||||
|  |   bool haveRNGs() const{ return have_RNG; } | ||||||
|  |  | ||||||
|   void AddRNGs(std::string s = "") { |   void AddRNGs(std::string s = "") { | ||||||
|     // Couple the RNGs to the GridModule tagged by s |     // Couple the RNGs to the GridModule tagged by s | ||||||
|     // the default is the first grid registered |     // the default is the first grid registered | ||||||
|   | |||||||
| @@ -136,8 +136,14 @@ protected: | |||||||
|       if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force); |       if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force); | ||||||
|       force = FieldImplementation::projectForce(force); // Ta for gauge fields |       force = FieldImplementation::projectForce(force); // Ta for gauge fields | ||||||
|       double end_force = usecond(); |       double end_force = usecond(); | ||||||
|       Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites()); |  | ||||||
|       std::cout << GridLogIntegrator << "["<<level<<"]["<<a<<"] Force average: " << force_abs << std::endl; |       Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites()); //average per-site norm.  nb. norm2(latt) = \sum_x norm2(latt[x])  | ||||||
|  |       Real impulse_abs = force_abs * ep * HMC_MOMENTUM_DENOMINATOR;     | ||||||
|  |  | ||||||
|  |       Real max_force_abs = std::sqrt(maxLocalNorm2(force)); | ||||||
|  |       Real max_impulse_abs = max_force_abs * ep * HMC_MOMENTUM_DENOMINATOR;     | ||||||
|  |  | ||||||
|  |       std::cout << GridLogIntegrator << "["<<level<<"]["<<a<<"] Force average: " << force_abs << " Max force: " << max_force_abs << " Time step: " << ep << " Impulse average: " << impulse_abs << " Max impulse: " << max_impulse_abs << std::endl; | ||||||
|       Mom -= force * ep* HMC_MOMENTUM_DENOMINATOR;;  |       Mom -= force * ep* HMC_MOMENTUM_DENOMINATOR;;  | ||||||
|       double end_full = usecond(); |       double end_full = usecond(); | ||||||
|       double time_full  = (end_full - start_full) / 1e3; |       double time_full  = (end_full - start_full) / 1e3; | ||||||
| @@ -249,15 +255,19 @@ public: | |||||||
|   void refresh(Field& U,  GridSerialRNG & sRNG, GridParallelRNG& pRNG)  |   void refresh(Field& U,  GridSerialRNG & sRNG, GridParallelRNG& pRNG)  | ||||||
|   { |   { | ||||||
|     assert(P.Grid() == U.Grid()); |     assert(P.Grid() == U.Grid()); | ||||||
|     std::cout << GridLogIntegrator << "Integrator refresh\n"; |     std::cout << GridLogIntegrator << "Integrator refresh" << std::endl; | ||||||
|  |  | ||||||
|  |     std::cout << GridLogIntegrator << "Generating momentum" << std::endl; | ||||||
|     FieldImplementation::generate_momenta(P, sRNG, pRNG); |     FieldImplementation::generate_momenta(P, sRNG, pRNG); | ||||||
|  |  | ||||||
|     // Update the smeared fields, can be implemented as observer |     // Update the smeared fields, can be implemented as observer | ||||||
|     // necessary to keep the fields updated even after a reject |     // necessary to keep the fields updated even after a reject | ||||||
|     // of the Metropolis |     // of the Metropolis | ||||||
|  |     std::cout << GridLogIntegrator << "Updating smeared fields" << std::endl; | ||||||
|     Smearer.set_Field(U); |     Smearer.set_Field(U); | ||||||
|     // Set the (eventual) representations gauge fields |     // Set the (eventual) representations gauge fields | ||||||
|  |  | ||||||
|  |     std::cout << GridLogIntegrator << "Updating representations" << std::endl; | ||||||
|     Representations.update(U); |     Representations.update(U); | ||||||
|  |  | ||||||
|     // The Smearer is attached to a pointer of the gauge field |     // The Smearer is attached to a pointer of the gauge field | ||||||
| @@ -267,6 +277,7 @@ public: | |||||||
|       for (int actionID = 0; actionID < as[level].actions.size(); ++actionID) { |       for (int actionID = 0; actionID < as[level].actions.size(); ++actionID) { | ||||||
|         // get gauge field from the SmearingPolicy and |         // get gauge field from the SmearingPolicy and | ||||||
|         // based on the boolean is_smeared in actionID |         // based on the boolean is_smeared in actionID | ||||||
|  | 	std::cout << GridLogIntegrator << "Refreshing integrator level " << level << " index " << actionID << std::endl; | ||||||
|         Field& Us = Smearer.get_U(as[level].actions.at(actionID)->is_smeared); |         Field& Us = Smearer.get_U(as[level].actions.at(actionID)->is_smeared); | ||||||
|         as[level].actions.at(actionID)->refresh(Us, sRNG, pRNG); |         as[level].actions.at(actionID)->refresh(Us, sRNG, pRNG); | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -99,7 +99,7 @@ public: | |||||||
| 	// using wilson flow by default here | 	// using wilson flow by default here | ||||||
| 	WilsonFlow<PeriodicGimplR> WF(Pars.Smearing.steps, Pars.Smearing.step_size, Pars.Smearing.meas_interval); | 	WilsonFlow<PeriodicGimplR> WF(Pars.Smearing.steps, Pars.Smearing.step_size, Pars.Smearing.meas_interval); | ||||||
| 	WF.smear_adaptive(Usmear, U, Pars.Smearing.maxTau); | 	WF.smear_adaptive(Usmear, U, Pars.Smearing.maxTau); | ||||||
| 	Real T0   = WF.energyDensityPlaquette(Usmear); | 	Real T0   = WF.energyDensityPlaquette(Pars.Smearing.maxTau, Usmear); | ||||||
| 	std::cout << GridLogMessage << std::setprecision(std::numeric_limits<Real>::digits10 + 1) | 	std::cout << GridLogMessage << std::setprecision(std::numeric_limits<Real>::digits10 + 1) | ||||||
| 		  << "T0                : [ " << traj << " ] "<< T0 << std::endl; | 		  << "T0                : [ " << traj << " ] "<< T0 << std::endl; | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ Source file: ./lib/qcd/modules/plaquette.h | |||||||
| Copyright (C) 2017 | Copyright (C) 2017 | ||||||
|  |  | ||||||
| Author: Guido Cossu <guido.cossu@ed.ac.uk> | Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||||
|  | Author: Christopher Kelly <ckelly@bnl.gov> | ||||||
|  |  | ||||||
| This program is free software; you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | ||||||
| @@ -33,28 +34,44 @@ NAMESPACE_BEGIN(Grid); | |||||||
|  |  | ||||||
| template <class Gimpl> | template <class Gimpl> | ||||||
| class WilsonFlow: public Smear<Gimpl>{ | class WilsonFlow: public Smear<Gimpl>{ | ||||||
|   unsigned int Nstep; | public: | ||||||
|   unsigned int measure_interval; |   //Store generic measurements to take during smearing process using std::function | ||||||
|   mutable RealD epsilon, taus; |   typedef std::function<void(int, RealD, const typename Gimpl::GaugeField &)> FunctionType;  //int: step,  RealD: flow time,  GaugeField : the gauge field | ||||||
|    |    | ||||||
|  | private: | ||||||
|  |   unsigned int Nstep; | ||||||
|  |   RealD epsilon; //for regular smearing this is the time step, for adaptive it is the initial time step | ||||||
|  |   | ||||||
|  |   std::vector< std::pair<int, FunctionType> > functions; //The int maps to the measurement frequency | ||||||
|  |  | ||||||
|   mutable WilsonGaugeAction<Gimpl> SG; |   mutable WilsonGaugeAction<Gimpl> SG; | ||||||
|  |  | ||||||
|   void evolve_step(typename Gimpl::GaugeField&) const; |   //Evolve the gauge field by 1 step and update tau | ||||||
|   void evolve_step_adaptive(typename Gimpl::GaugeField&, RealD); |   void evolve_step(typename Gimpl::GaugeField &U, RealD &tau) const; | ||||||
|   RealD tau(unsigned int t)const {return epsilon*(t+1.0); } |   //Evolve the gauge field by 1 step and update tau and the current time step eps | ||||||
|  |   void evolve_step_adaptive(typename Gimpl::GaugeField&U, RealD &tau, RealD &eps, RealD maxTau) const; | ||||||
|  |  | ||||||
| public: | public: | ||||||
|   INHERIT_GIMPL_TYPES(Gimpl) |   INHERIT_GIMPL_TYPES(Gimpl) | ||||||
|  |  | ||||||
|  |   void resetActions(){ functions.clear(); } | ||||||
|  |  | ||||||
|  |   void addMeasurement(int meas_interval, FunctionType meas){ functions.push_back({meas_interval, meas}); } | ||||||
|  |  | ||||||
|  |   //Set the class to perform the default measurements:  | ||||||
|  |   //the plaquette energy density every step | ||||||
|  |   //the plaquette topological charge every 'topq_meas_interval' steps | ||||||
|  |   //and output to stdout | ||||||
|  |   void setDefaultMeasurements(int topq_meas_interval = 1); | ||||||
|  |  | ||||||
|   explicit WilsonFlow(unsigned int Nstep, RealD epsilon, unsigned int interval = 1): |   explicit WilsonFlow(unsigned int Nstep, RealD epsilon, unsigned int interval = 1): | ||||||
|   Nstep(Nstep), |   Nstep(Nstep), | ||||||
|     epsilon(epsilon), |     epsilon(epsilon), | ||||||
|     measure_interval(interval), |  | ||||||
|     SG(WilsonGaugeAction<Gimpl>(3.0)) { |     SG(WilsonGaugeAction<Gimpl>(3.0)) { | ||||||
|     // WilsonGaugeAction with beta 3.0 |     // WilsonGaugeAction with beta 3.0 | ||||||
|     assert(epsilon > 0.0); |     assert(epsilon > 0.0); | ||||||
|     LogMessage(); |     LogMessage(); | ||||||
|  |     setDefaultMeasurements(interval); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void LogMessage() { |   void LogMessage() { | ||||||
| @@ -73,9 +90,29 @@ public: | |||||||
|     // undefined for WilsonFlow |     // undefined for WilsonFlow | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void smear_adaptive(GaugeField&, const GaugeField&, RealD maxTau); |   void smear_adaptive(GaugeField&, const GaugeField&, RealD maxTau) const; | ||||||
|   RealD energyDensityPlaquette(unsigned int step, const GaugeField& U) const; |  | ||||||
|   RealD energyDensityPlaquette(const GaugeField& U) const; |   //Compute t^2 <E(t)> for time t from the plaquette | ||||||
|  |   static RealD energyDensityPlaquette(const RealD t, const GaugeField& U); | ||||||
|  |  | ||||||
|  |   //Compute t^2 <E(t)> for time t from the 1x1 cloverleaf form | ||||||
|  |   //t is the Wilson flow time | ||||||
|  |   static RealD energyDensityCloverleaf(const RealD t, const GaugeField& U); | ||||||
|  |    | ||||||
|  |   //Evolve the gauge field by Nstep steps of epsilon and return the energy density computed every interval steps | ||||||
|  |   //The smeared field is output as V | ||||||
|  |   std::vector<RealD> flowMeasureEnergyDensityPlaquette(GaugeField &V, const GaugeField& U, int measure_interval = 1); | ||||||
|  |  | ||||||
|  |   //Version that does not return the smeared field | ||||||
|  |   std::vector<RealD> flowMeasureEnergyDensityPlaquette(const GaugeField& U, int measure_interval = 1); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   //Evolve the gauge field by Nstep steps of epsilon and return the Cloverleaf energy density computed every interval steps | ||||||
|  |   //The smeared field is output as V | ||||||
|  |   std::vector<RealD> flowMeasureEnergyDensityCloverleaf(GaugeField &V, const GaugeField& U, int measure_interval = 1); | ||||||
|  |  | ||||||
|  |   //Version that does not return the smeared field | ||||||
|  |   std::vector<RealD> flowMeasureEnergyDensityCloverleaf(const GaugeField& U, int measure_interval = 1); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -83,7 +120,7 @@ public: | |||||||
| // Implementations | // Implementations | ||||||
| //////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// | ||||||
| template <class Gimpl> | template <class Gimpl> | ||||||
| void WilsonFlow<Gimpl>::evolve_step(typename Gimpl::GaugeField &U) const{ | void WilsonFlow<Gimpl>::evolve_step(typename Gimpl::GaugeField &U, RealD &tau) const{ | ||||||
|   GaugeField Z(U.Grid()); |   GaugeField Z(U.Grid()); | ||||||
|   GaugeField tmp(U.Grid()); |   GaugeField tmp(U.Grid()); | ||||||
|   SG.deriv(U, Z); |   SG.deriv(U, Z); | ||||||
| @@ -99,12 +136,13 @@ void WilsonFlow<Gimpl>::evolve_step(typename Gimpl::GaugeField &U) const{ | |||||||
|   SG.deriv(U, tmp); Z += tmp;                 // 4/3*(17/36*Z0 -8/9*Z1) +Z2 |   SG.deriv(U, tmp); Z += tmp;                 // 4/3*(17/36*Z0 -8/9*Z1) +Z2 | ||||||
|   Z *= 3.0/4.0;                               // Z = 17/36*Z0 -8/9*Z1 +3/4*Z2 |   Z *= 3.0/4.0;                               // Z = 17/36*Z0 -8/9*Z1 +3/4*Z2 | ||||||
|   Gimpl::update_field(Z, U, -2.0*epsilon);    // V(t+e) = exp(ep*Z)*W2 |   Gimpl::update_field(Z, U, -2.0*epsilon);    // V(t+e) = exp(ep*Z)*W2 | ||||||
|  |   tau += epsilon; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <class Gimpl> | template <class Gimpl> | ||||||
| void WilsonFlow<Gimpl>::evolve_step_adaptive(typename Gimpl::GaugeField &U, RealD maxTau) { | void WilsonFlow<Gimpl>::evolve_step_adaptive(typename Gimpl::GaugeField &U, RealD &tau, RealD &eps, RealD maxTau) const{ | ||||||
|   if (maxTau - taus < epsilon){ |   if (maxTau - tau < eps){ | ||||||
|     epsilon = maxTau-taus; |     eps = maxTau-tau; | ||||||
|   } |   } | ||||||
|   //std::cout << GridLogMessage << "Integration epsilon : " << epsilon << std::endl; |   //std::cout << GridLogMessage << "Integration epsilon : " << epsilon << std::endl; | ||||||
|   GaugeField Z(U.Grid()); |   GaugeField Z(U.Grid()); | ||||||
| @@ -114,95 +152,151 @@ void WilsonFlow<Gimpl>::evolve_step_adaptive(typename Gimpl::GaugeField &U, Real | |||||||
|   SG.deriv(U, Z); |   SG.deriv(U, Z); | ||||||
|   Zprime = -Z; |   Zprime = -Z; | ||||||
|   Z *= 0.25;                                  // Z0 = 1/4 * F(U) |   Z *= 0.25;                                  // Z0 = 1/4 * F(U) | ||||||
|   Gimpl::update_field(Z, U, -2.0*epsilon);    // U = W1 = exp(ep*Z0)*W0 |   Gimpl::update_field(Z, U, -2.0*eps);    // U = W1 = exp(ep*Z0)*W0 | ||||||
|  |  | ||||||
|   Z *= -17.0/8.0; |   Z *= -17.0/8.0; | ||||||
|   SG.deriv(U, tmp); Z += tmp;                 // -17/32*Z0 +Z1 |   SG.deriv(U, tmp); Z += tmp;                 // -17/32*Z0 +Z1 | ||||||
|   Zprime += 2.0*tmp; |   Zprime += 2.0*tmp; | ||||||
|   Z *= 8.0/9.0;                               // Z = -17/36*Z0 +8/9*Z1 |   Z *= 8.0/9.0;                               // Z = -17/36*Z0 +8/9*Z1 | ||||||
|   Gimpl::update_field(Z, U, -2.0*epsilon);    // U_= W2 = exp(ep*Z)*W1 |   Gimpl::update_field(Z, U, -2.0*eps);    // U_= W2 = exp(ep*Z)*W1 | ||||||
|      |      | ||||||
|  |  | ||||||
|   Z *= -4.0/3.0; |   Z *= -4.0/3.0; | ||||||
|   SG.deriv(U, tmp); Z += tmp;                 // 4/3*(17/36*Z0 -8/9*Z1) +Z2 |   SG.deriv(U, tmp); Z += tmp;                 // 4/3*(17/36*Z0 -8/9*Z1) +Z2 | ||||||
|   Z *= 3.0/4.0;                               // Z = 17/36*Z0 -8/9*Z1 +3/4*Z2 |   Z *= 3.0/4.0;                               // Z = 17/36*Z0 -8/9*Z1 +3/4*Z2 | ||||||
|   Gimpl::update_field(Z, U, -2.0*epsilon);    // V(t+e) = exp(ep*Z)*W2 |   Gimpl::update_field(Z, U, -2.0*eps);    // V(t+e) = exp(ep*Z)*W2 | ||||||
|  |  | ||||||
|   // Ramos  |   // Ramos  | ||||||
|   Gimpl::update_field(Zprime, Uprime, -2.0*epsilon); // V'(t+e) = exp(ep*Z')*W0 |   Gimpl::update_field(Zprime, Uprime, -2.0*eps); // V'(t+e) = exp(ep*Z')*W0 | ||||||
|   // Compute distance as norm^2 of the difference |   // Compute distance as norm^2 of the difference | ||||||
|   GaugeField diffU = U - Uprime; |   GaugeField diffU = U - Uprime; | ||||||
|   RealD diff = norm2(diffU); |   RealD diff = norm2(diffU); | ||||||
|   // adjust integration step |   // adjust integration step | ||||||
|      |      | ||||||
|   taus += epsilon; |   tau += eps; | ||||||
|   //std::cout << GridLogMessage << "Adjusting integration step with distance: " << diff << std::endl; |   //std::cout << GridLogMessage << "Adjusting integration step with distance: " << diff << std::endl; | ||||||
|      |      | ||||||
|   epsilon = epsilon*0.95*std::pow(1e-4/diff,1./3.); |   eps = eps*0.95*std::pow(1e-4/diff,1./3.); | ||||||
|   //std::cout << GridLogMessage << "New epsilon : " << epsilon << std::endl; |   //std::cout << GridLogMessage << "New epsilon : " << epsilon << std::endl; | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| template <class Gimpl> | template <class Gimpl> | ||||||
| RealD WilsonFlow<Gimpl>::energyDensityPlaquette(unsigned int step, const GaugeField& U) const { | RealD WilsonFlow<Gimpl>::energyDensityPlaquette(const RealD t, const GaugeField& U){ | ||||||
|   RealD td = tau(step); |   static WilsonGaugeAction<Gimpl> SG(3.0); | ||||||
|   return 2.0 * td * td * SG.S(U)/U.Grid()->gSites(); |   return 2.0 * t * t * SG.S(U)/U.Grid()->gSites(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //Compute t^2 <E(t)> for time from the 1x1 cloverleaf form | ||||||
|  | template <class Gimpl> | ||||||
|  | RealD WilsonFlow<Gimpl>::energyDensityCloverleaf(const RealD t, const GaugeField& U){ | ||||||
|  |   typedef typename Gimpl::GaugeLinkField GaugeMat; | ||||||
|  |   typedef typename Gimpl::GaugeField GaugeLorentz; | ||||||
|  |  | ||||||
|  |   assert(Nd == 4); | ||||||
|  |   //E = 1/2 tr( F_munu F_munu ) | ||||||
|  |   //However as  F_numu = -F_munu, only need to sum the trace of the squares of the following 6 field strengths: | ||||||
|  |   //F_01 F_02 F_03   F_12 F_13  F_23 | ||||||
|  |   GaugeMat F(U.Grid()); | ||||||
|  |   LatticeComplexD R(U.Grid()); | ||||||
|  |   R = Zero(); | ||||||
|  |    | ||||||
|  |   for(int mu=0;mu<3;mu++){ | ||||||
|  |     for(int nu=mu+1;nu<4;nu++){ | ||||||
|  |       WilsonLoops<Gimpl>::FieldStrength(F, U, mu, nu); | ||||||
|  |       R = R + trace(F*F); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   ComplexD out = sum(R); | ||||||
|  |   out = t*t*out / RealD(U.Grid()->gSites()); | ||||||
|  |   return -real(out); //minus sign necessary for +ve energy | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | template <class Gimpl> | ||||||
|  | std::vector<RealD> WilsonFlow<Gimpl>::flowMeasureEnergyDensityPlaquette(GaugeField &V, const GaugeField& U, int measure_interval){ | ||||||
|  |   std::vector<RealD> out; | ||||||
|  |   resetActions(); | ||||||
|  |   addMeasurement(measure_interval, [&out](int step, RealD t, const typename Gimpl::GaugeField &U){  | ||||||
|  |       std::cout << GridLogMessage << "[WilsonFlow] Computing plaquette energy density for step " << step << std::endl; | ||||||
|  |       out.push_back( energyDensityPlaquette(t,U) ); | ||||||
|  |     });       | ||||||
|  |   smear(V,U); | ||||||
|  |   return out; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <class Gimpl> | template <class Gimpl> | ||||||
| RealD WilsonFlow<Gimpl>::energyDensityPlaquette(const GaugeField& U) const { | std::vector<RealD> WilsonFlow<Gimpl>::flowMeasureEnergyDensityPlaquette(const GaugeField& U, int measure_interval){ | ||||||
|   return 2.0 * taus * taus * SG.S(U)/U.Grid()->gSites(); |   GaugeField V(U); | ||||||
|  |   return flowMeasureEnergyDensityPlaquette(V,U, measure_interval); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <class Gimpl> | ||||||
|  | std::vector<RealD> WilsonFlow<Gimpl>::flowMeasureEnergyDensityCloverleaf(GaugeField &V, const GaugeField& U, int measure_interval){ | ||||||
|  |   std::vector<RealD> out; | ||||||
|  |   resetActions(); | ||||||
|  |   addMeasurement(measure_interval, [&out](int step, RealD t, const typename Gimpl::GaugeField &U){  | ||||||
|  |       std::cout << GridLogMessage << "[WilsonFlow] Computing Cloverleaf energy density for step " << step << std::endl; | ||||||
|  |       out.push_back( energyDensityCloverleaf(t,U) ); | ||||||
|  |     });       | ||||||
|  |   smear(V,U); | ||||||
|  |   return out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <class Gimpl> | ||||||
|  | std::vector<RealD> WilsonFlow<Gimpl>::flowMeasureEnergyDensityCloverleaf(const GaugeField& U, int measure_interval){ | ||||||
|  |   GaugeField V(U); | ||||||
|  |   return flowMeasureEnergyDensityCloverleaf(V,U, measure_interval); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //#define WF_TIMING  | //#define WF_TIMING  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| template <class Gimpl> | template <class Gimpl> | ||||||
| void WilsonFlow<Gimpl>::smear(GaugeField& out, const GaugeField& in) const{ | void WilsonFlow<Gimpl>::smear(GaugeField& out, const GaugeField& in) const{ | ||||||
|   out = in; |   out = in; | ||||||
|   for (unsigned int step = 1; step <= Nstep; step++) { |   RealD taus = 0.; | ||||||
|  |   for (unsigned int step = 1; step <= Nstep; step++) { //step indicates the number of smearing steps applied at the time of measurement | ||||||
|     auto start = std::chrono::high_resolution_clock::now(); |     auto start = std::chrono::high_resolution_clock::now(); | ||||||
|     evolve_step(out); |     evolve_step(out, taus); | ||||||
|     auto end = std::chrono::high_resolution_clock::now(); |     auto end = std::chrono::high_resolution_clock::now(); | ||||||
|     std::chrono::duration<double> diff = end - start; |     std::chrono::duration<double> diff = end - start; | ||||||
| #ifdef WF_TIMING | #ifdef WF_TIMING | ||||||
|     std::cout << "Time to evolve " << diff.count() << " s\n"; |     std::cout << "Time to evolve " << diff.count() << " s\n"; | ||||||
| #endif | #endif | ||||||
|     std::cout << GridLogMessage << "[WilsonFlow] Energy density (plaq) : " |     //Perform measurements | ||||||
| 		  << step << "  " << tau(step) << "  "  |     for(auto const &meas : functions) | ||||||
| 	      << energyDensityPlaquette(step,out) << std::endl; |       if( step % meas.first == 0 ) meas.second(step,taus,out); | ||||||
|     if( step % measure_interval == 0){ |  | ||||||
|       std::cout << GridLogMessage << "[WilsonFlow] Top. charge           : " |  | ||||||
| 		<< step << "  "  |  | ||||||
| 		<< WilsonLoops<PeriodicGimplR>::TopologicalCharge(out) << std::endl; |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| template <class Gimpl> | template <class Gimpl> | ||||||
| void WilsonFlow<Gimpl>::smear_adaptive(GaugeField& out, const GaugeField& in, RealD maxTau){ | void WilsonFlow<Gimpl>::smear_adaptive(GaugeField& out, const GaugeField& in, RealD maxTau) const{ | ||||||
|   out = in; |   out = in; | ||||||
|   taus = epsilon; |   RealD taus = 0.; | ||||||
|  |   RealD eps = epsilon; | ||||||
|   unsigned int step = 0; |   unsigned int step = 0; | ||||||
|   do{ |   do{ | ||||||
|     step++; |     step++; | ||||||
|     //std::cout << GridLogMessage << "Evolution time :"<< taus << std::endl; |     //std::cout << GridLogMessage << "Evolution time :"<< taus << std::endl; | ||||||
|     evolve_step_adaptive(out, maxTau); |     evolve_step_adaptive(out, taus, eps, maxTau); | ||||||
|     std::cout << GridLogMessage << "[WilsonFlow] Energy density (plaq) : " |     //Perform measurements | ||||||
| 		  << step << "  " << taus << "  " |     for(auto const &meas : functions) | ||||||
| 	      << energyDensityPlaquette(out) << std::endl; |       if( step % meas.first == 0 ) meas.second(step,taus,out); | ||||||
|     if( step % measure_interval == 0){ |  | ||||||
|       std::cout << GridLogMessage << "[WilsonFlow] Top. charge           : " |  | ||||||
| 		<< step << "  "  |  | ||||||
| 		<< WilsonLoops<PeriodicGimplR>::TopologicalCharge(out) << std::endl; |  | ||||||
|     } |  | ||||||
|   } while (taus < maxTau); |   } while (taus < maxTau); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <class Gimpl> | ||||||
|  | void WilsonFlow<Gimpl>::setDefaultMeasurements(int topq_meas_interval){ | ||||||
|  |   addMeasurement(1, [](int step, RealD t, const typename Gimpl::GaugeField &U){ | ||||||
|  |       std::cout << GridLogMessage << "[WilsonFlow] Energy density (plaq) : "  << step << "  " << t << "  " << energyDensityPlaquette(t,U) << std::endl; | ||||||
|  |     }); | ||||||
|  |   addMeasurement(topq_meas_interval, [](int step, RealD t, const typename Gimpl::GaugeField &U){ | ||||||
|  |       std::cout << GridLogMessage << "[WilsonFlow] Top. charge           : "  << step << "  " << WilsonLoops<Gimpl>::TopologicalCharge(U) << std::endl; | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| NAMESPACE_END(Grid); | NAMESPACE_END(Grid); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -88,6 +88,12 @@ namespace PeriodicBC { | |||||||
|     return CovShiftBackward(Link,mu,arg); |     return CovShiftBackward(Link,mu,arg); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //Boundary-aware C-shift of gauge links / gauge transformation matrices | ||||||
|  |   template<class gauge> Lattice<gauge> | ||||||
|  |   CshiftLink(const Lattice<gauge> &Link, int mu, int shift) | ||||||
|  |   { | ||||||
|  |     return Cshift(Link, mu, shift); | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -158,6 +164,9 @@ namespace ConjugateBC { | |||||||
|     //    std::cout<<"Gparity::CovCshiftBackward mu="<<mu<<std::endl; |     //    std::cout<<"Gparity::CovCshiftBackward mu="<<mu<<std::endl; | ||||||
|     return Cshift(tmp,mu,-1);// moves towards positive mu |     return Cshift(tmp,mu,-1);// moves towards positive mu | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //Out(x) = U^dag_\mu(x-mu)  | x_\mu != 0 | ||||||
|  |   //       = U^T_\mu(L-1)  | x_\mu == 0 | ||||||
|   template<class gauge> Lattice<gauge> |   template<class gauge> Lattice<gauge> | ||||||
|   CovShiftIdentityBackward(const Lattice<gauge> &Link, int mu) { |   CovShiftIdentityBackward(const Lattice<gauge> &Link, int mu) { | ||||||
|     GridBase *grid = Link.Grid(); |     GridBase *grid = Link.Grid(); | ||||||
| @@ -176,6 +185,9 @@ namespace ConjugateBC { | |||||||
|     return Link; |     return Link; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //Out(x) = S_\mu(x+\hat\mu)  | x_\mu != L-1 | ||||||
|  |   //       = S*_\mu(0)  | x_\mu == L-1 | ||||||
|  |   //Note: While this is used for Staples it is also applicable for shifting gauge links or gauge transformation matrices | ||||||
|   template<class gauge> Lattice<gauge> |   template<class gauge> Lattice<gauge> | ||||||
|   ShiftStaple(const Lattice<gauge> &Link, int mu) |   ShiftStaple(const Lattice<gauge> &Link, int mu) | ||||||
|   { |   { | ||||||
| @@ -208,6 +220,35 @@ namespace ConjugateBC { | |||||||
|     return CovShiftBackward(Link,mu,arg); |     return CovShiftBackward(Link,mu,arg); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   //Boundary-aware C-shift of gauge links / gauge transformation matrices | ||||||
|  |   //shift = 1 | ||||||
|  |   //Out(x) = U_\mu(x+\hat\mu)  | x_\mu != L-1 | ||||||
|  |   //       = U*_\mu(0)  | x_\mu == L-1 | ||||||
|  |   //shift = -1 | ||||||
|  |   //Out(x) = U_\mu(x-mu)  | x_\mu != 0 | ||||||
|  |   //       = U*_\mu(L-1)  | x_\mu == 0 | ||||||
|  |   template<class gauge> Lattice<gauge> | ||||||
|  |   CshiftLink(const Lattice<gauge> &Link, int mu, int shift) | ||||||
|  |   { | ||||||
|  |     GridBase *grid = Link.Grid(); | ||||||
|  |     int Lmu = grid->GlobalDimensions()[mu] - 1; | ||||||
|  |  | ||||||
|  |     Lattice<iScalar<vInteger>> coor(grid); | ||||||
|  |     LatticeCoordinate(coor, mu); | ||||||
|  |  | ||||||
|  |     Lattice<gauge> tmp(grid); | ||||||
|  |     if(shift == 1){ | ||||||
|  |       tmp = Cshift(Link, mu, 1); | ||||||
|  |       tmp = where(coor == Lmu, conjugate(tmp), tmp); | ||||||
|  |       return tmp; | ||||||
|  |     }else if(shift == -1){ | ||||||
|  |       tmp = Link; | ||||||
|  |       tmp = where(coor == Lmu, conjugate(tmp), tmp); | ||||||
|  |       return Cshift(tmp, mu, -1); | ||||||
|  |     }else assert(0 && "Invalid shift value"); | ||||||
|  |     return tmp; //shuts up the compiler fussing about the return type | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -40,27 +40,46 @@ public: | |||||||
|   typedef typename Gimpl::GaugeLinkField GaugeMat; |   typedef typename Gimpl::GaugeLinkField GaugeMat; | ||||||
|   typedef typename Gimpl::GaugeField GaugeLorentz; |   typedef typename Gimpl::GaugeField GaugeLorentz; | ||||||
|  |  | ||||||
|   static void GaugeLinkToLieAlgebraField(const std::vector<GaugeMat> &U,std::vector<GaugeMat> &A) { |   //A_\mu(x) = -i Ta(U_\mu(x) )   where Ta(U) = 1/2( U - U^dag ) - 1/2N tr(U - U^dag)  is the traceless antihermitian part. This is an O(A^3) approximation to the logarithm of U | ||||||
|     for(int mu=0;mu<Nd;mu++){ |   static void GaugeLinkToLieAlgebraField(const GaugeMat &U, GaugeMat &A) { | ||||||
|     Complex cmi(0.0,-1.0); |     Complex cmi(0.0,-1.0); | ||||||
|       A[mu] = Ta(U[mu]) * cmi; |     A = Ta(U) * cmi; | ||||||
|   } |   } | ||||||
|   } |    | ||||||
|   static void DmuAmu(const std::vector<GaugeMat> &A,GaugeMat &dmuAmu,int orthog) { |   //The derivative of the Lie algebra field | ||||||
|  |   static void DmuAmu(const std::vector<GaugeMat> &U, GaugeMat &dmuAmu,int orthog) { | ||||||
|  |     GridBase* grid = U[0].Grid(); | ||||||
|  |     GaugeMat Ax(grid); | ||||||
|  |     GaugeMat Axm1(grid); | ||||||
|  |     GaugeMat Utmp(grid); | ||||||
|  |  | ||||||
|     dmuAmu=Zero(); |     dmuAmu=Zero(); | ||||||
|     for(int mu=0;mu<Nd;mu++){ |     for(int mu=0;mu<Nd;mu++){ | ||||||
|       if ( mu != orthog ) { |       if ( mu != orthog ) { | ||||||
| 	dmuAmu = dmuAmu + A[mu] - Cshift(A[mu],mu,-1); | 	//Rather than define functionality to work out how the BCs apply to A_\mu we simply use the BC-aware Cshift to the gauge links and compute A_\mu(x) and A_\mu(x-1) separately | ||||||
|  | 	//Ax = A_\mu(x) | ||||||
|  | 	GaugeLinkToLieAlgebraField(U[mu], Ax); | ||||||
|  | 	 | ||||||
|  | 	//Axm1 = A_\mu(x_\mu-1) | ||||||
|  | 	Utmp = Gimpl::CshiftLink(U[mu], mu, -1); | ||||||
|  | 	GaugeLinkToLieAlgebraField(Utmp, Axm1); | ||||||
|  | 	 | ||||||
|  | 	//Derivative | ||||||
|  | 	dmuAmu = dmuAmu + Ax - Axm1; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   }   |   }   | ||||||
|  |  | ||||||
|   static void SteepestDescentGaugeFix(GaugeLorentz &Umu,Real & alpha,int maxiter,Real Omega_tol, Real Phi_tol,bool Fourier=false,int orthog=-1,bool err_on_no_converge=true) { |   //Fix the gauge field Umu | ||||||
|  |   //0 < alpha < 1 is related to the step size, cf https://arxiv.org/pdf/1405.5812.pdf | ||||||
|  |   static void SteepestDescentGaugeFix(GaugeLorentz &Umu, Real alpha,int maxiter,Real Omega_tol, Real Phi_tol,bool Fourier=false,int orthog=-1) { | ||||||
|     GridBase *grid = Umu.Grid(); |     GridBase *grid = Umu.Grid(); | ||||||
|     GaugeMat xform(grid); |     GaugeMat xform(grid); | ||||||
|     SteepestDescentGaugeFix(Umu,xform,alpha,maxiter,Omega_tol,Phi_tol,Fourier,orthog,err_on_no_converge); |     SteepestDescentGaugeFix(Umu,xform,alpha,maxiter,Omega_tol,Phi_tol,Fourier,orthog); | ||||||
|   } |   } | ||||||
|   static void SteepestDescentGaugeFix(GaugeLorentz &Umu,GaugeMat &xform,Real & alpha,int maxiter,Real Omega_tol, Real Phi_tol,bool Fourier=false,int orthog=-1,bool err_on_no_converge=true) { |  | ||||||
|  |   //Fix the gauge field Umu and also return the gauge transformation from the original gauge field, xform | ||||||
|  |   static void SteepestDescentGaugeFix(GaugeLorentz &Umu,GaugeMat &xform, Real alpha,int maxiter,Real Omega_tol, Real Phi_tol,bool Fourier=false,int orthog=-1) { | ||||||
|  |  | ||||||
|     GridBase *grid = Umu.Grid(); |     GridBase *grid = Umu.Grid(); | ||||||
|  |  | ||||||
| @@ -122,29 +141,24 @@ public: | |||||||
|  |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     std::cout << GridLogError << "Gauge fixing did not converge in " << maxiter << " iterations." << std::endl; |     assert(0 && "Gauge fixing did not converge within the specified number of iterations"); | ||||||
|     if (err_on_no_converge) assert(0); |  | ||||||
|   }; |   }; | ||||||
|   static Real SteepestDescentStep(std::vector<GaugeMat> &U,GaugeMat &xform,Real & alpha, GaugeMat & dmuAmu,int orthog) { |   static Real SteepestDescentStep(std::vector<GaugeMat> &U,GaugeMat &xform, Real alpha, GaugeMat & dmuAmu,int orthog) { | ||||||
|     GridBase *grid = U[0].Grid(); |     GridBase *grid = U[0].Grid(); | ||||||
|  |  | ||||||
|     std::vector<GaugeMat> A(Nd,grid); |  | ||||||
|     GaugeMat g(grid); |     GaugeMat g(grid); | ||||||
|  |     ExpiAlphaDmuAmu(U,g,alpha,dmuAmu,orthog); | ||||||
|     GaugeLinkToLieAlgebraField(U,A); |  | ||||||
|     ExpiAlphaDmuAmu(A,g,alpha,dmuAmu,orthog); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     Real vol = grid->gSites(); |     Real vol = grid->gSites(); | ||||||
|     Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc; |     Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc; | ||||||
|  |  | ||||||
|     xform = g*xform ; |     xform = g*xform ; | ||||||
|     SU<Nc>::GaugeTransform(U,g); |     SU<Nc>::GaugeTransform<Gimpl>(U,g); | ||||||
|  |  | ||||||
|     return trG; |     return trG; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static Real FourierAccelSteepestDescentStep(std::vector<GaugeMat> &U,GaugeMat &xform,Real & alpha, GaugeMat & dmuAmu,int orthog) { |   static Real FourierAccelSteepestDescentStep(std::vector<GaugeMat> &U,GaugeMat &xform, Real alpha, GaugeMat & dmuAmu,int orthog) { | ||||||
|  |  | ||||||
|     GridBase *grid = U[0].Grid(); |     GridBase *grid = U[0].Grid(); | ||||||
|  |  | ||||||
| @@ -159,11 +173,7 @@ public: | |||||||
|  |  | ||||||
|     GaugeMat g(grid); |     GaugeMat g(grid); | ||||||
|     GaugeMat dmuAmu_p(grid); |     GaugeMat dmuAmu_p(grid); | ||||||
|     std::vector<GaugeMat> A(Nd,grid); |     DmuAmu(U,dmuAmu,orthog); | ||||||
|  |  | ||||||
|     GaugeLinkToLieAlgebraField(U,A); |  | ||||||
|  |  | ||||||
|     DmuAmu(A,dmuAmu,orthog); |  | ||||||
|  |  | ||||||
|     std::vector<int> mask(Nd,1); |     std::vector<int> mask(Nd,1); | ||||||
|     for(int mu=0;mu<Nd;mu++) if (mu==orthog) mask[mu]=0; |     for(int mu=0;mu<Nd;mu++) if (mu==orthog) mask[mu]=0; | ||||||
| @@ -207,16 +217,16 @@ public: | |||||||
|     Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc; |     Real trG = TensorRemove(sum(trace(g))).real()/vol/Nc; | ||||||
|  |  | ||||||
|     xform = g*xform ; |     xform = g*xform ; | ||||||
|     SU<Nc>::GaugeTransform(U,g); |     SU<Nc>::GaugeTransform<Gimpl>(U,g); | ||||||
|  |  | ||||||
|     return trG; |     return trG; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static void ExpiAlphaDmuAmu(const std::vector<GaugeMat> &A,GaugeMat &g,Real & alpha, GaugeMat &dmuAmu,int orthog) { |   static void ExpiAlphaDmuAmu(const std::vector<GaugeMat> &U,GaugeMat &g, Real alpha, GaugeMat &dmuAmu,int orthog) { | ||||||
|     GridBase *grid = g.Grid(); |     GridBase *grid = g.Grid(); | ||||||
|     Complex cialpha(0.0,-alpha); |     Complex cialpha(0.0,-alpha); | ||||||
|     GaugeMat ciadmam(grid); |     GaugeMat ciadmam(grid); | ||||||
|     DmuAmu(A,dmuAmu,orthog); |     DmuAmu(U,dmuAmu,orthog); | ||||||
|     ciadmam = dmuAmu*cialpha; |     ciadmam = dmuAmu*cialpha; | ||||||
|     SU<Nc>::taExp(ciadmam,g); |     SU<Nc>::taExp(ciadmam,g); | ||||||
|   }   |   }   | ||||||
|   | |||||||
| @@ -694,32 +694,32 @@ public: | |||||||
|  * Adjoint rep gauge xform |  * Adjoint rep gauge xform | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|   template<typename GaugeField,typename GaugeMat> |   template<typename Gimpl> | ||||||
|   static void GaugeTransform( GaugeField &Umu, GaugeMat &g){ |   static void GaugeTransform(typename Gimpl::GaugeField &Umu, typename Gimpl::GaugeLinkField &g){ | ||||||
|     GridBase *grid = Umu.Grid(); |     GridBase *grid = Umu.Grid(); | ||||||
|     conformable(grid,g.Grid()); |     conformable(grid,g.Grid()); | ||||||
|  |  | ||||||
|     GaugeMat U(grid); |     typename Gimpl::GaugeLinkField U(grid); | ||||||
|     GaugeMat ag(grid); ag = adj(g); |     typename Gimpl::GaugeLinkField ag(grid); ag = adj(g); | ||||||
|  |  | ||||||
|     for(int mu=0;mu<Nd;mu++){ |     for(int mu=0;mu<Nd;mu++){ | ||||||
|       U= PeekIndex<LorentzIndex>(Umu,mu); |       U= PeekIndex<LorentzIndex>(Umu,mu); | ||||||
|       U = g*U*Cshift(ag, mu, 1); |       U = g*U*Gimpl::CshiftLink(ag, mu, 1); //BC-aware | ||||||
|       PokeIndex<LorentzIndex>(Umu,U,mu); |       PokeIndex<LorentzIndex>(Umu,U,mu); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   template<typename GaugeMat> |   template<typename Gimpl> | ||||||
|   static void GaugeTransform( std::vector<GaugeMat> &U, GaugeMat &g){ |   static void GaugeTransform( std::vector<typename Gimpl::GaugeLinkField> &U, typename Gimpl::GaugeLinkField &g){ | ||||||
|     GridBase *grid = g.Grid(); |     GridBase *grid = g.Grid(); | ||||||
|     GaugeMat ag(grid); ag = adj(g); |     typename Gimpl::GaugeLinkField ag(grid); ag = adj(g); | ||||||
|     for(int mu=0;mu<Nd;mu++){ |     for(int mu=0;mu<Nd;mu++){ | ||||||
|       U[mu] = g*U[mu]*Cshift(ag, mu, 1); |       U[mu] = g*U[mu]*Gimpl::CshiftLink(ag, mu, 1); //BC-aware | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   template<typename GaugeField,typename GaugeMat> |   template<typename Gimpl> | ||||||
|   static void RandomGaugeTransform(GridParallelRNG &pRNG, GaugeField &Umu, GaugeMat &g){ |   static void RandomGaugeTransform(GridParallelRNG &pRNG, typename Gimpl::GaugeField &Umu, typename Gimpl::GaugeLinkField &g){ | ||||||
|     LieRandomize(pRNG,g,1.0); |     LieRandomize(pRNG,g,1.0); | ||||||
|     GaugeTransform(Umu,g); |     GaugeTransform<Gimpl>(Umu,g); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Projects the algebra components a lattice matrix (of dimension ncol*ncol -1 ) |   // Projects the algebra components a lattice matrix (of dimension ncol*ncol -1 ) | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user