mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-10-21 16:34:44 +01:00 
			
		
		
		
	Compare commits
	
		
			84 Commits
		
	
	
		
			dirac-ITT
			...
			feature/dw
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 1edcf902b7 | ||
|  | e5c19e1fd7 | ||
|  | a11d0a33d1 | ||
|  | 4f8b6f26b4 | ||
|  | 073525c5b3 | ||
|  | fddeb29d6b | ||
|  | a9ec5cf564 | ||
|  | 946a8671b9 | ||
|  | 771a1b8e79 | ||
|  | bfb68e6f02 | ||
|  | 18c335198a | ||
|  | 17c5b0f152 | ||
|  | 5918769f97 | ||
|  | bbaf1ada91 | ||
|  | 1950ac9294 | ||
|  | 13fa70ac1a | ||
|  | 7cb2b11f26 | ||
|  | 1184ed29ae | ||
|  | 203c7bf6fa | ||
|  | c709883f3f | ||
|  | aed5de4d50 | ||
|  | ba27cc6571 | ||
|  | d856327250 | ||
|  | a5fe07c077 | ||
|  | b83b2b1415 | ||
|  | 59bd1fe21b | ||
|  | 4e907fef2c | ||
|  | 67888b657f | ||
|  | 74af885d4e | ||
|  | d36d2fb40d | ||
|  | 4b4c2a715b | ||
|  | 54a5e6c1d0 | ||
|  | f365a83fae | ||
|  | 34a9aeb331 | ||
|  | edabb3577f | ||
|  | ce5df177ee | ||
|  | a0bb8e5b46 | ||
|  | 46f88e6d72 | ||
|  | dd8f1ea189 | ||
|  | b61835c1a5 | ||
|  | 459f70e8d4 | ||
|  | 061e48fd73 | ||
|  | ab50145001 | ||
|  | 9d45fca8bc | ||
|  | ac9e6b63c0 | ||
|  | e140b3f802 | ||
|  | d9d3d30cc7 | ||
|  | 47a12ec7b5 | ||
|  | ec1e2f7a40 | ||
|  | 41f73ec083 | ||
|  | 6d0786ff9d | ||
|  | b7f93aeb4d | ||
|  | 202a7fe900 | ||
|  | 7d867a8134 | ||
|  | 9939b267d2 | ||
|  | 8f4b3049cd | ||
|  | 2a6e673a91 | ||
|  | 9b6cde173f | ||
|  | 9f280b82c4 | ||
|  | 7a53dc3715 | ||
|  | 9fa07eecde | ||
|  | f64fb7bd77 | ||
|  | 2a35449b91 | ||
|  | 184af5bd05 | ||
|  | 097c9637ee | ||
|  | d9593c4b81 | ||
|  | ac740f73ce | ||
|  | 75dc7794b9 | ||
|  | dee68fc728 | ||
|  | a2d3643634 | ||
|  | 57002924bc | ||
|  | 4a29ab0d0a | ||
|  | 0165bcb58e | ||
|  | 349d75e483 | ||
|  | e51475703a | ||
|  | 1feddf4ba6 | ||
|  | 600d7ddc2e | ||
|  | e504260f3d | ||
|  | 5e4bea8f20 | ||
|  | 6ebf9f15b7 | ||
|  | 1d7aa673a4 | ||
|  | b9104f3072 | ||
| b672717096 | |||
| 284ee194b1 | 
							
								
								
									
										12
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								TODO
									
									
									
									
									
								
							| @@ -3,19 +3,19 @@ TODO: | ||||
|  | ||||
| Large item work list: | ||||
|  | ||||
| 1)- BG/Q port and check | ||||
| 1)- BG/Q port and check ; Andrew says ok. | ||||
| 2)- Christoph's local basis expansion Lanczos | ||||
| 3)- Precision conversion and sort out localConvert      <-- partial | ||||
|  | ||||
|   - Consistent linear solver flop count/rate -- PARTIAL, time but no flop/s yet | ||||
| -- | ||||
| 3a)- RNG I/O in ILDG/SciDAC (minor) | ||||
| 3b)- Precision conversion and sort out localConvert      <-- partial/easy | ||||
| 3c)- Consistent linear solver flop count/rate -- PARTIAL, time but no flop/s yet | ||||
| 4)- Physical propagator interface | ||||
| 5)- Conserved currents | ||||
| 6)- Multigrid Wilson and DWF, compare to other Multigrid implementations | ||||
| 7)- HDCR resume | ||||
|  | ||||
| Recent DONE  | ||||
|  | ||||
| -- MultiRHS with spread out extra dim -- Go through filesystem with SciDAC I/O.  <--- DONE | ||||
| -- MultiRHS with spread out extra dim -- Go through filesystem with SciDAC I/O ; <-- DONE ; bmark cori | ||||
| -- Lanczos Remove DenseVector, DenseMatrix; Use Eigen instead. <-- DONE | ||||
| -- GaugeFix into central location                      <-- DONE | ||||
| -- Scidac and Ildg metadata handling                   <-- DONE | ||||
|   | ||||
| @@ -701,12 +701,14 @@ int main (int argc, char ** argv) | ||||
|   if ( do_su3 ) { | ||||
|     // empty for now | ||||
|   } | ||||
|  | ||||
| #if 1 | ||||
|   int sel=2; | ||||
|   std::vector<int> L_list({8,12,16,24}); | ||||
|  | ||||
|   //int sel=1; | ||||
|   //  std::vector<int> L_list({8,12}); | ||||
| #else | ||||
|   int sel=1; | ||||
|   std::vector<int> L_list({8,12}); | ||||
| #endif | ||||
|   int selm1=sel-1; | ||||
|   std::vector<double> robust_list; | ||||
|  | ||||
|   std::vector<double> wilson; | ||||
| @@ -785,7 +787,8 @@ int main (int argc, char ** argv) | ||||
|   std::cout<<GridLogMessage << "=================================================================================="<<std::endl; | ||||
|  | ||||
|   std::cout<<GridLogMessage << "=================================================================================="<<std::endl; | ||||
|   std::cout<<GridLogMessage << " Comparison point     result: "  << dwf4[sel]/NN << " Mflop/s per node"<<std::endl; | ||||
|   std::cout<<GridLogMessage << " Comparison point     result: "  << 0.5*(dwf4[sel]+dwf4[selm1])/NN << " Mflop/s per node"<<std::endl; | ||||
|   std::cout<<GridLogMessage << " Comparison point is 0.5*("<<dwf4[sel]/NN<<"+"<<dwf4[selm1]/NN << ") "<<std::endl; | ||||
|   std::cout<<std::setprecision(3); | ||||
|   std::cout<<GridLogMessage << " Comparison point robustness: "  << robust_list[sel] <<std::endl; | ||||
|   std::cout<<GridLogMessage << "=================================================================================="<<std::endl; | ||||
|   | ||||
| @@ -51,7 +51,13 @@ int main (int argc, char ** argv) | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|  | ||||
|   std::vector<int> latt4 = GridDefaultLatt(); | ||||
|   const int Ls=16; | ||||
|   int Ls=16; | ||||
|   for(int i=0;i<argc;i++) | ||||
|     if(std::string(argv[i]) == "-Ls"){ | ||||
|       std::stringstream ss(argv[i+1]); ss >> Ls; | ||||
|     } | ||||
|  | ||||
|  | ||||
|   GridCartesian         * UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()),GridDefaultMpi()); | ||||
|   GridRedBlackCartesian * UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian         * FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid); | ||||
|   | ||||
							
								
								
									
										190
									
								
								benchmarks/Benchmark_gparity.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								benchmarks/Benchmark_gparity.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| #include <Grid/Grid.h> | ||||
| #include <sstream> | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| template<class d> | ||||
| struct scal { | ||||
|   d internal; | ||||
| }; | ||||
|  | ||||
|   Gamma::Algebra Gmu [] = { | ||||
|     Gamma::Algebra::GammaX, | ||||
|     Gamma::Algebra::GammaY, | ||||
|     Gamma::Algebra::GammaZ, | ||||
|     Gamma::Algebra::GammaT | ||||
|   }; | ||||
|  | ||||
| typedef typename GparityDomainWallFermionF::FermionField GparityLatticeFermionF; | ||||
| typedef typename GparityDomainWallFermionD::FermionField GparityLatticeFermionD; | ||||
|  | ||||
|  | ||||
|  | ||||
| int main (int argc, char ** argv) | ||||
| { | ||||
|   Grid_init(&argc,&argv); | ||||
|  | ||||
|   int Ls=16; | ||||
|   for(int i=0;i<argc;i++) | ||||
|     if(std::string(argv[i]) == "-Ls"){ | ||||
|       std::stringstream ss(argv[i+1]); ss >> Ls; | ||||
|     } | ||||
|  | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   std::cout<<GridLogMessage << "Ls = " << Ls << std::endl; | ||||
|  | ||||
|   std::vector<int> latt4 = GridDefaultLatt(); | ||||
|  | ||||
|   GridCartesian         * UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplexF::Nsimd()),GridDefaultMpi()); | ||||
|   GridRedBlackCartesian * UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian         * FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid); | ||||
|   GridRedBlackCartesian * FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,UGrid); | ||||
|  | ||||
|   std::vector<int> seeds4({1,2,3,4}); | ||||
|   std::vector<int> seeds5({5,6,7,8}); | ||||
|    | ||||
|   std::cout << GridLogMessage << "Initialising 4d RNG" << std::endl; | ||||
|   GridParallelRNG          RNG4(UGrid);  RNG4.SeedFixedIntegers(seeds4); | ||||
|   std::cout << GridLogMessage << "Initialising 5d RNG" << std::endl; | ||||
|   GridParallelRNG          RNG5(FGrid);  RNG5.SeedFixedIntegers(seeds5); | ||||
|   std::cout << GridLogMessage << "Initialised RNGs" << std::endl; | ||||
|  | ||||
|   GparityLatticeFermionF src   (FGrid); random(RNG5,src); | ||||
|   RealD N2 = 1.0/::sqrt(norm2(src)); | ||||
|   src = src*N2; | ||||
|  | ||||
|   GparityLatticeFermionF result(FGrid); result=zero; | ||||
|   GparityLatticeFermionF    ref(FGrid);    ref=zero; | ||||
|   GparityLatticeFermionF    tmp(FGrid); | ||||
|   GparityLatticeFermionF    err(FGrid); | ||||
|  | ||||
|   std::cout << GridLogMessage << "Drawing gauge field" << std::endl; | ||||
|   LatticeGaugeFieldF Umu(UGrid);  | ||||
|   SU3::HotConfiguration(RNG4,Umu);  | ||||
|   std::cout << GridLogMessage << "Random gauge initialised " << std::endl; | ||||
|  | ||||
|   RealD mass=0.1; | ||||
|   RealD M5  =1.8; | ||||
|  | ||||
|   RealD NP = UGrid->_Nprocessors; | ||||
|   RealD NN = UGrid->NodeCount(); | ||||
|  | ||||
|   std::cout << GridLogMessage<< "*****************************************************************" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "* Kernel options --dslash-generic, --dslash-unroll, --dslash-asm" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "*****************************************************************" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "*****************************************************************" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "* Benchmarking DomainWallFermion::Dhop                  "<<std::endl; | ||||
|   std::cout << GridLogMessage<< "* Vectorising space-time by "<<vComplexF::Nsimd()<<std::endl; | ||||
| #ifdef GRID_OMP | ||||
|   if ( WilsonKernelsStatic::Comms == WilsonKernelsStatic::CommsAndCompute ) std::cout << GridLogMessage<< "* Using Overlapped Comms/Compute" <<std::endl; | ||||
|   if ( WilsonKernelsStatic::Comms == WilsonKernelsStatic::CommsThenCompute) std::cout << GridLogMessage<< "* Using sequential comms compute" <<std::endl; | ||||
| #endif | ||||
|   if ( WilsonKernelsStatic::Opt == WilsonKernelsStatic::OptGeneric   ) std::cout << GridLogMessage<< "* Using GENERIC Nc WilsonKernels" <<std::endl; | ||||
|   if ( WilsonKernelsStatic::Opt == WilsonKernelsStatic::OptHandUnroll) std::cout << GridLogMessage<< "* Using Nc=3       WilsonKernels" <<std::endl; | ||||
|   if ( WilsonKernelsStatic::Opt == WilsonKernelsStatic::OptInlineAsm ) std::cout << GridLogMessage<< "* Using Asm Nc=3   WilsonKernels" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "*****************************************************************" <<std::endl; | ||||
|  | ||||
|  | ||||
|  | ||||
|   std::cout << GridLogMessage<< "* SINGLE/SINGLE"<<std::endl; | ||||
|   GparityDomainWallFermionF Dw(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5); | ||||
|   int ncall =1000; | ||||
|   if (1) { | ||||
|     FGrid->Barrier(); | ||||
|     Dw.ZeroCounters(); | ||||
|     Dw.Dhop(src,result,0); | ||||
|     std::cout<<GridLogMessage<<"Called warmup"<<std::endl; | ||||
|     double t0=usecond(); | ||||
|     for(int i=0;i<ncall;i++){ | ||||
|       __SSC_START; | ||||
|       Dw.Dhop(src,result,0); | ||||
|       __SSC_STOP; | ||||
|     } | ||||
|     double t1=usecond(); | ||||
|     FGrid->Barrier(); | ||||
|      | ||||
|     double volume=Ls;  for(int mu=0;mu<Nd;mu++) volume=volume*latt4[mu]; | ||||
|     double flops=2*1344*volume*ncall; | ||||
|  | ||||
|     std::cout<<GridLogMessage << "Called Dw "<<ncall<<" times in "<<t1-t0<<" us"<<std::endl; | ||||
|     //    std::cout<<GridLogMessage << "norm result "<< norm2(result)<<std::endl; | ||||
|     //    std::cout<<GridLogMessage << "norm ref    "<< norm2(ref)<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s =   "<< flops/(t1-t0)<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s per rank =  "<< flops/(t1-t0)/NP<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s per node =  "<< flops/(t1-t0)/NN<<std::endl; | ||||
|     Dw.Report(); | ||||
|   } | ||||
|  | ||||
|   std::cout << GridLogMessage<< "* SINGLE/HALF"<<std::endl; | ||||
|   GparityDomainWallFermionFH DwH(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5); | ||||
|   if (1) { | ||||
|     FGrid->Barrier(); | ||||
|     DwH.ZeroCounters(); | ||||
|     DwH.Dhop(src,result,0); | ||||
|     double t0=usecond(); | ||||
|     for(int i=0;i<ncall;i++){ | ||||
|       __SSC_START; | ||||
|       DwH.Dhop(src,result,0); | ||||
|       __SSC_STOP; | ||||
|     } | ||||
|     double t1=usecond(); | ||||
|     FGrid->Barrier(); | ||||
|      | ||||
|     double volume=Ls;  for(int mu=0;mu<Nd;mu++) volume=volume*latt4[mu]; | ||||
|     double flops=2*1344*volume*ncall; | ||||
|  | ||||
|     std::cout<<GridLogMessage << "Called half prec comms Dw "<<ncall<<" times in "<<t1-t0<<" us"<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s =   "<< flops/(t1-t0)<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s per rank =  "<< flops/(t1-t0)/NP<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s per node =  "<< flops/(t1-t0)/NN<<std::endl; | ||||
|     DwH.Report(); | ||||
|   } | ||||
|  | ||||
|   GridCartesian         * UGrid_d   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplexD::Nsimd()),GridDefaultMpi()); | ||||
|   GridRedBlackCartesian * UrbGrid_d = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid_d); | ||||
|   GridCartesian         * FGrid_d   = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid_d); | ||||
|   GridRedBlackCartesian * FrbGrid_d = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,UGrid_d); | ||||
|  | ||||
|    | ||||
|   std::cout << GridLogMessage<< "* DOUBLE/DOUBLE"<<std::endl; | ||||
|   GparityLatticeFermionD src_d(FGrid_d); | ||||
|   precisionChange(src_d,src); | ||||
|  | ||||
|   LatticeGaugeFieldD Umu_d(UGrid_d);  | ||||
|   precisionChange(Umu_d,Umu); | ||||
|  | ||||
|   GparityLatticeFermionD result_d(FGrid_d); | ||||
|  | ||||
|   GparityDomainWallFermionD DwD(Umu_d,*FGrid_d,*FrbGrid_d,*UGrid_d,*UrbGrid_d,mass,M5); | ||||
|   if (1) { | ||||
|     FGrid_d->Barrier(); | ||||
|     DwD.ZeroCounters(); | ||||
|     DwD.Dhop(src_d,result_d,0); | ||||
|     std::cout<<GridLogMessage<<"Called warmup"<<std::endl; | ||||
|     double t0=usecond(); | ||||
|     for(int i=0;i<ncall;i++){ | ||||
|       __SSC_START; | ||||
|       DwD.Dhop(src_d,result_d,0); | ||||
|       __SSC_STOP; | ||||
|     } | ||||
|     double t1=usecond(); | ||||
|     FGrid_d->Barrier(); | ||||
|      | ||||
|     double volume=Ls;  for(int mu=0;mu<Nd;mu++) volume=volume*latt4[mu]; | ||||
|     double flops=2*1344*volume*ncall; | ||||
|  | ||||
|     std::cout<<GridLogMessage << "Called Dw "<<ncall<<" times in "<<t1-t0<<" us"<<std::endl; | ||||
|     //    std::cout<<GridLogMessage << "norm result "<< norm2(result)<<std::endl; | ||||
|     //    std::cout<<GridLogMessage << "norm ref    "<< norm2(ref)<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s =   "<< flops/(t1-t0)<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s per rank =  "<< flops/(t1-t0)/NP<<std::endl; | ||||
|     std::cout<<GridLogMessage << "mflop/s per node =  "<< flops/(t1-t0)/NN<<std::endl; | ||||
|     DwD.Report(); | ||||
|   } | ||||
|  | ||||
|   Grid_finalize(); | ||||
| } | ||||
|  | ||||
| @@ -40,7 +40,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
| @@ -58,7 +58,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
| @@ -93,7 +93,7 @@ int main (int argc, char ** argv) | ||||
| 	  std::cout << latt_size.back() << "\t\t"; | ||||
|  | ||||
| 	  GridCartesian           Grid(latt_size,simd_layout,mpi_layout); | ||||
| 	  GridRedBlackCartesian RBGrid(latt_size,simd_layout,mpi_layout); | ||||
| 	  GridRedBlackCartesian RBGrid(&Grid); | ||||
|  | ||||
| 	  GridParallelRNG  pRNG(&Grid); pRNG.SeedFixedIntegers(seeds); | ||||
| 	  LatticeGaugeField Umu(&Grid); random(pRNG,Umu); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/Algorithms.h | ||||
|  | ||||
| @@ -37,6 +37,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| #include <Grid/algorithms/approx/Chebyshev.h> | ||||
| #include <Grid/algorithms/approx/Remez.h> | ||||
| #include <Grid/algorithms/approx/MultiShiftFunction.h> | ||||
| #include <Grid/algorithms/approx/Forecast.h> | ||||
|  | ||||
| #include <Grid/algorithms/iterative/ConjugateGradient.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateResidual.h> | ||||
| @@ -44,30 +45,16 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| #include <Grid/algorithms/iterative/SchurRedBlack.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientMultiShift.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientMixedPrec.h> | ||||
|  | ||||
| // Lanczos support | ||||
| //#include <Grid/algorithms/iterative/MatrixUtils.h> | ||||
| #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientReliableUpdate.h> | ||||
| #include <Grid/algorithms/iterative/ImplicitlyRestartedLanczos.h> | ||||
| #include <Grid/algorithms/CoarsenedMatrix.h> | ||||
| #include <Grid/algorithms/FFT.h> | ||||
|  | ||||
| // Eigen/lanczos | ||||
| // EigCg | ||||
| // MCR | ||||
| // Pcg | ||||
| // Multishift CG | ||||
| // Hdcg | ||||
| // GCR | ||||
| // etc.. | ||||
|  | ||||
| // integrator/Leapfrog | ||||
| // integrator/Omelyan | ||||
| // integrator/ForceGradient | ||||
|  | ||||
| // montecarlo/hmc | ||||
| // montecarlo/rhmc | ||||
| // montecarlo/metropolis | ||||
| // etc... | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -230,6 +230,7 @@ namespace Grid { | ||||
|       // Barrel shift and collect global pencil | ||||
|       std::vector<int> lcoor(Nd), gcoor(Nd); | ||||
|       result = source; | ||||
|       int pc = processor_coor[dim]; | ||||
|       for(int p=0;p<processors[dim];p++) { | ||||
|         PARALLEL_REGION | ||||
|         { | ||||
| @@ -240,7 +241,8 @@ namespace Grid { | ||||
|           for(int idx=0;idx<sgrid->lSites();idx++) { | ||||
|             sgrid->LocalIndexToLocalCoor(idx,cbuf); | ||||
|             peekLocalSite(s,result,cbuf); | ||||
|             cbuf[dim]+=p*L; | ||||
| 	    cbuf[dim]+=((pc+p) % processors[dim])*L; | ||||
| 	    //            cbuf[dim]+=p*L; | ||||
|             pokeLocalSite(s,pgbuf,cbuf); | ||||
|           } | ||||
|         } | ||||
| @@ -278,7 +280,6 @@ namespace Grid { | ||||
|       flops+= flops_call*NN; | ||||
|        | ||||
|       // writing out result | ||||
|       int pc = processor_coor[dim]; | ||||
|       PARALLEL_REGION | ||||
|       { | ||||
|         std::vector<int> clbuf(Nd), cgbuf(Nd); | ||||
|   | ||||
							
								
								
									
										152
									
								
								lib/algorithms/approx/Forecast.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								lib/algorithms/approx/Forecast.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/algorithms/approx/Forecast.h | ||||
|  | ||||
| Copyright (C) 2015 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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 INCLUDED_FORECAST_H | ||||
| #define INCLUDED_FORECAST_H | ||||
|  | ||||
| namespace Grid { | ||||
|  | ||||
|   // Abstract base class. | ||||
|   // Takes a matrix (Mat), a source (phi), and a vector of Fields (chi) | ||||
|   // and returns a forecasted solution to the system D*psi = phi (psi). | ||||
|   template<class Matrix, class Field> | ||||
|   class Forecast | ||||
|   { | ||||
|     public: | ||||
|       virtual Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& chi) = 0; | ||||
|   }; | ||||
|  | ||||
|   // Implementation of Brower et al.'s chronological inverter (arXiv:hep-lat/9509012), | ||||
|   // used to forecast solutions across poles of the EOFA heatbath. | ||||
|   // | ||||
|   // Modified from CPS (cps_pp/src/util/dirac_op/d_op_base/comsrc/minresext.C) | ||||
|   template<class Matrix, class Field> | ||||
|   class ChronoForecast : public Forecast<Matrix,Field> | ||||
|   { | ||||
|     public: | ||||
|       Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& prev_solns) | ||||
|       { | ||||
|         int degree = prev_solns.size(); | ||||
|         Field chi(phi); // forecasted solution | ||||
|  | ||||
|         // Trivial cases | ||||
|         if(degree == 0){ chi = zero; return chi; } | ||||
|         else if(degree == 1){ return prev_solns[0]; } | ||||
|  | ||||
|         RealD dot; | ||||
|         ComplexD xp; | ||||
|         Field r(phi); // residual | ||||
|         Field Mv(phi); | ||||
|         std::vector<Field> v(prev_solns); // orthonormalized previous solutions | ||||
|         std::vector<Field> MdagMv(degree,phi); | ||||
|  | ||||
|         // Array to hold the matrix elements | ||||
|         std::vector<std::vector<ComplexD>> G(degree, std::vector<ComplexD>(degree)); | ||||
|  | ||||
|         // Solution and source vectors | ||||
|         std::vector<ComplexD> a(degree); | ||||
|         std::vector<ComplexD> b(degree); | ||||
|  | ||||
|         // Orthonormalize the vector basis | ||||
|         for(int i=0; i<degree; i++){ | ||||
|           v[i] *= 1.0/std::sqrt(norm2(v[i])); | ||||
|           for(int j=i+1; j<degree; j++){ v[j] -= innerProduct(v[i],v[j]) * v[i]; } | ||||
|         } | ||||
|  | ||||
|         // Perform sparse matrix multiplication and construct rhs | ||||
|         for(int i=0; i<degree; i++){ | ||||
|           b[i] = innerProduct(v[i],phi); | ||||
|           Mat.M(v[i],Mv); | ||||
|           Mat.Mdag(Mv,MdagMv[i]); | ||||
|           G[i][i] = innerProduct(v[i],MdagMv[i]); | ||||
|         } | ||||
|  | ||||
|         // Construct the matrix | ||||
|         for(int j=0; j<degree; j++){ | ||||
|         for(int k=j+1; k<degree; k++){ | ||||
|           G[j][k] = innerProduct(v[j],MdagMv[k]); | ||||
|           G[k][j] = std::conj(G[j][k]); | ||||
|         }} | ||||
|  | ||||
|         // Gauss-Jordan elimination with partial pivoting | ||||
|         for(int i=0; i<degree; i++){ | ||||
|  | ||||
|           // Perform partial pivoting | ||||
|           int k = i; | ||||
|           for(int j=i+1; j<degree; j++){ if(std::abs(G[j][j]) > std::abs(G[k][k])){ k = j; } } | ||||
|           if(k != i){ | ||||
|             xp = b[k]; | ||||
|             b[k] = b[i]; | ||||
|             b[i] = xp; | ||||
|             for(int j=0; j<degree; j++){ | ||||
|               xp = G[k][j]; | ||||
|               G[k][j] = G[i][j]; | ||||
|               G[i][j] = xp; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           // Convert matrix to upper triangular form | ||||
|           for(int j=i+1; j<degree; j++){ | ||||
|             xp = G[j][i]/G[i][i]; | ||||
|             b[j] -= xp * b[i]; | ||||
|             for(int k=0; k<degree; k++){ G[j][k] -= xp*G[i][k]; } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         // Use Gaussian elimination to solve equations and calculate initial guess | ||||
|         chi = zero; | ||||
|         r = phi; | ||||
|         for(int i=degree-1; i>=0; i--){ | ||||
|           a[i] = 0.0; | ||||
|           for(int j=i+1; j<degree; j++){ a[i] += G[i][j] * a[j]; } | ||||
|           a[i] = (b[i]-a[i])/G[i][i]; | ||||
|           chi += a[i]*v[i]; | ||||
|           r -= a[i]*MdagMv[i]; | ||||
|         } | ||||
|  | ||||
|         RealD true_r(0.0); | ||||
|         ComplexD tmp; | ||||
|         for(int i=0; i<degree; i++){ | ||||
|           tmp = -b[i]; | ||||
|           for(int j=0; j<degree; j++){ tmp += G[i][j]*a[j]; } | ||||
|           tmp = std::conj(tmp)*tmp; | ||||
|           true_r += std::sqrt(tmp.real()); | ||||
|         } | ||||
|  | ||||
|         RealD error = std::sqrt(norm2(r)/norm2(phi)); | ||||
|         std::cout << GridLogMessage << "ChronoForecast: |res|/|src| = " << error << std::endl; | ||||
|  | ||||
|         return chi; | ||||
|       }; | ||||
|   }; | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -87,15 +87,22 @@ void ThinQRfact (Eigen::MatrixXcd &m_rr, | ||||
|   //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   sliceInnerProductMatrix(m_rr,R,R,Orthog); | ||||
|  | ||||
|   //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Cholesky from Eigen | ||||
|   // There exists a ldlt that is documented as more stable | ||||
|   //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   Eigen::MatrixXcd L    = m_rr.llt().matrixL();  | ||||
|   // Force manifest hermitian to avoid rounding related | ||||
|   m_rr = 0.5*(m_rr+m_rr.adjoint()); | ||||
|  | ||||
| #if 0 | ||||
|   std::cout << " Calling Cholesky  ldlt on m_rr "  << m_rr <<std::endl; | ||||
|   Eigen::MatrixXcd L_ldlt = m_rr.ldlt().matrixL();  | ||||
|   std::cout << " Called Cholesky  ldlt on m_rr "  << L_ldlt <<std::endl; | ||||
|   auto  D_ldlt = m_rr.ldlt().vectorD();  | ||||
|   std::cout << " Called Cholesky  ldlt on m_rr "  << D_ldlt <<std::endl; | ||||
| #endif | ||||
|  | ||||
|   //  std::cout << " Calling Cholesky  llt on m_rr "  <<std::endl; | ||||
|   Eigen::MatrixXcd L    = m_rr.llt().matrixL();  | ||||
|   //  std::cout << " Called Cholesky  llt on m_rr "  << L <<std::endl; | ||||
|   C    = L.adjoint(); | ||||
|   Cinv = C.inverse(); | ||||
|  | ||||
|   //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Q = R C^{-1} | ||||
|   // | ||||
| @@ -103,7 +110,6 @@ void ThinQRfact (Eigen::MatrixXcd &m_rr, | ||||
|   // | ||||
|   // NB maddMatrix conventions are Right multiplication X[j] a[j,i] already | ||||
|   //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // FIXME:: make a sliceMulMatrix to avoid zero vector | ||||
|   sliceMulMatrix(Q,Cinv,R,Orthog); | ||||
| } | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -52,8 +52,8 @@ class ConjugateGradient : public OperatorFunction<Field> { | ||||
|         MaxIterations(maxit), | ||||
|         ErrorOnNoConverge(err_on_no_conv){}; | ||||
|  | ||||
|   void operator()(LinearOperatorBase<Field> &Linop, const Field &src, | ||||
|                   Field &psi) { | ||||
|   void operator()(LinearOperatorBase<Field> &Linop, const Field &src, Field &psi) { | ||||
|  | ||||
|     psi.checkerboard = src.checkerboard; | ||||
|     conformable(psi, src); | ||||
|  | ||||
|   | ||||
							
								
								
									
										256
									
								
								lib/algorithms/iterative/ConjugateGradientReliableUpdate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								lib/algorithms/iterative/ConjugateGradientReliableUpdate.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,256 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|  | ||||
|     Source file: ./lib/algorithms/iterative/ConjugateGradientReliableUpdate.h | ||||
|  | ||||
|     Copyright (C) 2015 | ||||
|  | ||||
| Author: Christopher Kelly <ckelly@phys.columbia.edu> | ||||
|  | ||||
|     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_RELIABLE_UPDATE_H | ||||
| #define GRID_CONJUGATE_GRADIENT_RELIABLE_UPDATE_H | ||||
|  | ||||
| namespace Grid { | ||||
|  | ||||
|   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 ConjugateGradientReliableUpdate : public LinearFunction<FieldD> { | ||||
|   public: | ||||
|     bool ErrorOnNoConverge;  // throw an assert when the CG fails to converge. | ||||
|     // Defaults true. | ||||
|     RealD Tolerance; | ||||
|     Integer MaxIterations; | ||||
|     Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion | ||||
|     Integer ReliableUpdatesPerformed; | ||||
|  | ||||
|     bool DoFinalCleanup; //Final DP cleanup, defaults to true | ||||
|     Integer IterationsToCleanup; //Final DP cleanup step iterations | ||||
|      | ||||
|     LinearOperatorBase<FieldF> &Linop_f; | ||||
|     LinearOperatorBase<FieldD> &Linop_d; | ||||
|     GridBase* SinglePrecGrid; | ||||
|     RealD Delta; //reliable update parameter | ||||
|  | ||||
|     //Optional ability to switch to a different linear operator once the tolerance reaches a certain point. Useful for single/half -> single/single | ||||
|     LinearOperatorBase<FieldF> *Linop_fallback; | ||||
|     RealD fallback_transition_tol; | ||||
|  | ||||
|      | ||||
|     ConjugateGradientReliableUpdate(RealD tol, Integer maxit, RealD _delta, GridBase* _sp_grid, LinearOperatorBase<FieldF> &_Linop_f, LinearOperatorBase<FieldD> &_Linop_d, bool err_on_no_conv = true) | ||||
|       : Tolerance(tol), | ||||
|         MaxIterations(maxit), | ||||
| 	Delta(_delta), | ||||
| 	Linop_f(_Linop_f), | ||||
| 	Linop_d(_Linop_d), | ||||
| 	SinglePrecGrid(_sp_grid), | ||||
|         ErrorOnNoConverge(err_on_no_conv), | ||||
| 	DoFinalCleanup(true), | ||||
| 	Linop_fallback(NULL) | ||||
|     {}; | ||||
|  | ||||
|     void setFallbackLinop(LinearOperatorBase<FieldF> &_Linop_fallback, const RealD _fallback_transition_tol){ | ||||
|       Linop_fallback = &_Linop_fallback; | ||||
|       fallback_transition_tol = _fallback_transition_tol;       | ||||
|     } | ||||
|      | ||||
|     void operator()(const FieldD &src, FieldD &psi) { | ||||
|       LinearOperatorBase<FieldF> *Linop_f_use = &Linop_f; | ||||
|       bool using_fallback = false; | ||||
|        | ||||
|       psi.checkerboard = src.checkerboard; | ||||
|       conformable(psi, src); | ||||
|  | ||||
|       RealD cp, c, a, d, b, ssq, qq, b_pred; | ||||
|  | ||||
|       FieldD p(src); | ||||
|       FieldD mmp(src); | ||||
|       FieldD r(src); | ||||
|  | ||||
|       // Initial residual computation & set up | ||||
|       RealD guess = norm2(psi); | ||||
|       assert(std::isnan(guess) == 0); | ||||
|      | ||||
|       Linop_d.HermOpAndNorm(psi, mmp, d, b); | ||||
|      | ||||
|       r = src - mmp; | ||||
|       p = r; | ||||
|  | ||||
|       a = norm2(p); | ||||
|       cp = a; | ||||
|       ssq = norm2(src); | ||||
|  | ||||
|       std::cout << GridLogIterative << std::setprecision(4) << "ConjugateGradientReliableUpdate: guess " << guess << std::endl; | ||||
|       std::cout << GridLogIterative << std::setprecision(4) << "ConjugateGradientReliableUpdate:   src " << ssq << std::endl; | ||||
|       std::cout << GridLogIterative << std::setprecision(4) << "ConjugateGradientReliableUpdate:    mp " << d << std::endl; | ||||
|       std::cout << GridLogIterative << std::setprecision(4) << "ConjugateGradientReliableUpdate:   mmp " << b << std::endl; | ||||
|       std::cout << GridLogIterative << std::setprecision(4) << "ConjugateGradientReliableUpdate:  cp,r " << cp << std::endl; | ||||
|       std::cout << GridLogIterative << std::setprecision(4) << "ConjugateGradientReliableUpdate:     p " << a << std::endl; | ||||
|  | ||||
|       RealD rsq = Tolerance * Tolerance * ssq; | ||||
|  | ||||
|       // Check if guess is really REALLY good :) | ||||
|       if (cp <= rsq) { | ||||
| 	std::cout << GridLogMessage << "ConjugateGradientReliableUpdate guess was REALLY good\n"; | ||||
| 	std::cout << GridLogMessage << "\tComputed residual " << sqrt(cp / ssq)<<std::endl; | ||||
| 	return; | ||||
|       } | ||||
|  | ||||
|       //Single prec initialization | ||||
|       FieldF r_f(SinglePrecGrid); | ||||
|       r_f.checkerboard = r.checkerboard; | ||||
|       precisionChange(r_f, r); | ||||
|  | ||||
|       FieldF psi_f(r_f); | ||||
|       psi_f = zero; | ||||
|  | ||||
|       FieldF p_f(r_f); | ||||
|       FieldF mmp_f(r_f); | ||||
|  | ||||
|       RealD MaxResidSinceLastRelUp = cp; //initial residual     | ||||
|      | ||||
|       std::cout << GridLogIterative << std::setprecision(4) | ||||
| 		<< "ConjugateGradient: k=0 residual " << cp << " target " << rsq << std::endl; | ||||
|  | ||||
|       GridStopWatch LinalgTimer; | ||||
|       GridStopWatch MatrixTimer; | ||||
|       GridStopWatch SolverTimer; | ||||
|  | ||||
|       SolverTimer.Start(); | ||||
|       int k = 0; | ||||
|       int l = 0; | ||||
|      | ||||
|       for (k = 1; k <= MaxIterations; k++) { | ||||
| 	c = cp; | ||||
|  | ||||
| 	MatrixTimer.Start(); | ||||
| 	Linop_f_use->HermOpAndNorm(p_f, mmp_f, d, qq); | ||||
| 	MatrixTimer.Stop(); | ||||
|  | ||||
| 	LinalgTimer.Start(); | ||||
|  | ||||
| 	a = c / d; | ||||
| 	b_pred = a * (a * qq - d) / c; | ||||
|  | ||||
| 	cp = axpy_norm(r_f, -a, mmp_f, r_f); | ||||
| 	b = cp / c; | ||||
|  | ||||
| 	// Fuse these loops ; should be really easy | ||||
| 	psi_f = a * p_f + psi_f; | ||||
| 	//p_f = p_f * b + r_f; | ||||
|  | ||||
| 	LinalgTimer.Stop(); | ||||
|  | ||||
| 	std::cout << GridLogIterative << "ConjugateGradientReliableUpdate: Iteration " << k | ||||
| 		  << " residual " << cp << " target " << rsq << std::endl; | ||||
| 	std::cout << GridLogDebug << "a = "<< a << " b_pred = "<< b_pred << "  b = "<< b << std::endl; | ||||
| 	std::cout << GridLogDebug << "qq = "<< qq << " d = "<< d << "  c = "<< c << std::endl; | ||||
|  | ||||
| 	if(cp > MaxResidSinceLastRelUp){ | ||||
| 	  std::cout << GridLogIterative << "ConjugateGradientReliableUpdate: updating MaxResidSinceLastRelUp : " << MaxResidSinceLastRelUp << " -> " << cp << std::endl; | ||||
| 	  MaxResidSinceLastRelUp = cp; | ||||
| 	} | ||||
| 	   | ||||
| 	// Stopping condition | ||||
| 	if (cp <= rsq) { | ||||
| 	  //Although not written in the paper, I assume that I have to add on the final solution | ||||
| 	  precisionChange(mmp, psi_f); | ||||
| 	  psi = psi + mmp; | ||||
| 	 | ||||
| 	 | ||||
| 	  SolverTimer.Stop(); | ||||
| 	  Linop_d.HermOpAndNorm(psi, mmp, d, qq); | ||||
| 	  p = mmp - src; | ||||
|  | ||||
| 	  RealD srcnorm = sqrt(norm2(src)); | ||||
| 	  RealD resnorm = sqrt(norm2(p)); | ||||
| 	  RealD true_residual = resnorm / srcnorm; | ||||
|  | ||||
| 	  std::cout << GridLogMessage << "ConjugateGradientReliableUpdate Converged on iteration " << k << " after " << l << " reliable updates" << std::endl; | ||||
| 	  std::cout << GridLogMessage << "\tComputed residual " << sqrt(cp / ssq)<<std::endl; | ||||
| 	  std::cout << GridLogMessage << "\tTrue residual " << true_residual<<std::endl; | ||||
| 	  std::cout << GridLogMessage << "\tTarget " << Tolerance << std::endl; | ||||
|  | ||||
| 	  std::cout << GridLogMessage << "Time breakdown "<<std::endl; | ||||
| 	  std::cout << GridLogMessage << "\tElapsed    " << SolverTimer.Elapsed() <<std::endl; | ||||
| 	  std::cout << GridLogMessage << "\tMatrix     " << MatrixTimer.Elapsed() <<std::endl; | ||||
| 	  std::cout << GridLogMessage << "\tLinalg     " << LinalgTimer.Elapsed() <<std::endl; | ||||
|  | ||||
| 	  IterationsToComplete = k;	 | ||||
| 	  ReliableUpdatesPerformed = l; | ||||
| 	   | ||||
| 	  if(DoFinalCleanup){ | ||||
| 	    //Do a final CG to cleanup | ||||
| 	    std::cout << GridLogMessage << "ConjugateGradientReliableUpdate performing final cleanup.\n"; | ||||
| 	    ConjugateGradient<FieldD> CG(Tolerance,MaxIterations); | ||||
| 	    CG.ErrorOnNoConverge = ErrorOnNoConverge; | ||||
| 	    CG(Linop_d,src,psi); | ||||
| 	    IterationsToCleanup = CG.IterationsToComplete; | ||||
| 	  } | ||||
| 	  else if (ErrorOnNoConverge) assert(true_residual / Tolerance < 10000.0); | ||||
|  | ||||
| 	  std::cout << GridLogMessage << "ConjugateGradientReliableUpdate complete.\n"; | ||||
| 	  return; | ||||
| 	} | ||||
| 	else if(cp < Delta * MaxResidSinceLastRelUp) { //reliable update | ||||
| 	  std::cout << GridLogMessage << "ConjugateGradientReliableUpdate " | ||||
| 		    << cp << "(residual) < " << Delta << "(Delta) * " << MaxResidSinceLastRelUp << "(MaxResidSinceLastRelUp) on iteration " << k << " : performing reliable update\n"; | ||||
| 	  precisionChange(mmp, psi_f); | ||||
| 	  psi = psi + mmp; | ||||
|  | ||||
| 	  Linop_d.HermOpAndNorm(psi, mmp, d, qq); | ||||
| 	  r = src - mmp; | ||||
|  | ||||
| 	  psi_f = zero; | ||||
| 	  precisionChange(r_f, r); | ||||
| 	  cp = norm2(r); | ||||
| 	  MaxResidSinceLastRelUp = cp; | ||||
|  | ||||
| 	  b = cp/c; | ||||
| 	   | ||||
| 	  std::cout << GridLogMessage << "ConjugateGradientReliableUpdate new residual " << cp << std::endl; | ||||
| 	   | ||||
| 	  l = l+1; | ||||
| 	} | ||||
|  | ||||
| 	p_f = p_f * b + r_f; //update search vector after reliable update appears to help convergence | ||||
|  | ||||
| 	if(!using_fallback && Linop_fallback != NULL && cp < fallback_transition_tol){ | ||||
| 	  std::cout << GridLogMessage << "ConjugateGradientReliableUpdate switching to fallback linear operator on iteration " << k << " at residual " << cp << std::endl; | ||||
| 	  Linop_f_use = Linop_fallback; | ||||
| 	  using_fallback = true; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|       } | ||||
|       std::cout << GridLogMessage << "ConjugateGradientReliableUpdate did NOT converge" | ||||
| 		<< std::endl; | ||||
|        | ||||
|       if (ErrorOnNoConverge) assert(0); | ||||
|       IterationsToComplete = k; | ||||
|       ReliableUpdatesPerformed = l;       | ||||
|     }     | ||||
|   }; | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @@ -1,7 +1,5 @@ | ||||
|  | ||||
|  | ||||
|  | ||||
| #include <Grid/GridCore.h> | ||||
| #include <fcntl.h> | ||||
|  | ||||
| namespace Grid { | ||||
|  | ||||
| @@ -63,4 +61,37 @@ void *PointerCache::Lookup(size_t bytes) { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| void check_huge_pages(void *Buf,uint64_t BYTES) | ||||
| { | ||||
| #ifdef __linux__ | ||||
|   int fd = open("/proc/self/pagemap", O_RDONLY); | ||||
|   assert(fd >= 0); | ||||
|   const int page_size = 4096; | ||||
|   uint64_t virt_pfn = (uint64_t)Buf / page_size; | ||||
|   off_t offset = sizeof(uint64_t) * virt_pfn; | ||||
|   uint64_t npages = (BYTES + page_size-1) / page_size; | ||||
|   uint64_t pagedata[npages]; | ||||
|   uint64_t ret = lseek(fd, offset, SEEK_SET); | ||||
|   assert(ret == offset); | ||||
|   ret = ::read(fd, pagedata, sizeof(uint64_t)*npages); | ||||
|   assert(ret == sizeof(uint64_t) * npages); | ||||
|   int nhugepages = npages / 512; | ||||
|   int n4ktotal, nnothuge; | ||||
|   n4ktotal = 0; | ||||
|   nnothuge = 0; | ||||
|   for (int i = 0; i < nhugepages; ++i) { | ||||
|     uint64_t baseaddr = (pagedata[i*512] & 0x7fffffffffffffULL) * page_size; | ||||
|     for (int j = 0; j < 512; ++j) { | ||||
|       uint64_t pageaddr = (pagedata[i*512+j] & 0x7fffffffffffffULL) * page_size; | ||||
|       ++n4ktotal; | ||||
|       if (pageaddr != baseaddr + j * page_size) | ||||
| 	++nnothuge; | ||||
|       } | ||||
|   } | ||||
|   int rank = CartesianCommunicator::RankWorld(); | ||||
|   printf("rank %d Allocated %d 4k pages, %d not in huge pages\n", rank, n4ktotal, nnothuge); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -64,6 +64,8 @@ namespace Grid { | ||||
|  | ||||
|   }; | ||||
|  | ||||
|   void check_huge_pages(void *Buf,uint64_t BYTES); | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////// | ||||
| // A lattice of something, but assume the something is SIMDized. | ||||
| //////////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -49,6 +49,8 @@ public: | ||||
|     template<class object> friend class Lattice; | ||||
|  | ||||
|     GridBase(const std::vector<int> & processor_grid) : CartesianCommunicator(processor_grid) {}; | ||||
|     GridBase(const std::vector<int> & processor_grid, | ||||
| 	     const CartesianCommunicator &parent) : CartesianCommunicator(processor_grid,parent) {}; | ||||
|  | ||||
|     // Physics Grid information. | ||||
|     std::vector<int> _simd_layout;// Which dimensions get relayed out over simd lanes. | ||||
| @@ -210,9 +212,6 @@ public: | ||||
|       assert(lidx<lSites()); | ||||
|       Lexicographic::CoorFromIndex(lcoor,lidx,_ldimensions); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     void GlobalCoorToGlobalIndex(const std::vector<int> & gcoor,int & gidx){ | ||||
|       gidx=0; | ||||
|       int mult=1; | ||||
|   | ||||
| @@ -61,9 +61,29 @@ public: | ||||
|     virtual int CheckerBoardShift(int source_cb,int dim,int shift, int osite){ | ||||
|       return shift; | ||||
|     } | ||||
|     ///////////////////////////////////////////////////////////////////////// | ||||
|     // Constructor takes a parent grid and possibly subdivides communicator. | ||||
|     ///////////////////////////////////////////////////////////////////////// | ||||
|     GridCartesian(const std::vector<int> &dimensions, | ||||
|                   const std::vector<int> &simd_layout, | ||||
|                   const std::vector<int> &processor_grid) : GridBase(processor_grid) | ||||
| 		  const std::vector<int> &simd_layout, | ||||
| 		  const std::vector<int> &processor_grid, | ||||
| 		  const GridCartesian &parent) : GridBase(processor_grid,parent) | ||||
|     { | ||||
|       Init(dimensions,simd_layout,processor_grid); | ||||
|     } | ||||
|     ///////////////////////////////////////////////////////////////////////// | ||||
|     // Construct from comm world | ||||
|     ///////////////////////////////////////////////////////////////////////// | ||||
|     GridCartesian(const std::vector<int> &dimensions, | ||||
| 		  const std::vector<int> &simd_layout, | ||||
| 		  const std::vector<int> &processor_grid) : GridBase(processor_grid) | ||||
|     { | ||||
|       Init(dimensions,simd_layout,processor_grid); | ||||
|     } | ||||
|  | ||||
|     void Init(const std::vector<int> &dimensions, | ||||
| 	      const std::vector<int> &simd_layout, | ||||
| 	      const std::vector<int> &processor_grid) | ||||
|     { | ||||
|       /////////////////////// | ||||
|       // Grid information | ||||
|   | ||||
| @@ -112,24 +112,57 @@ public: | ||||
|       } | ||||
|     }; | ||||
|  | ||||
|     GridRedBlackCartesian(const GridBase *base) : GridRedBlackCartesian(base->_fdimensions,base->_simd_layout,base->_processors)  {}; | ||||
|     //////////////////////////////////////////////////////////// | ||||
|     // Create Redblack from original grid; require full grid pointer ? | ||||
|     //////////////////////////////////////////////////////////// | ||||
|     GridRedBlackCartesian(const GridBase *base) : GridBase(base->_processors,*base) | ||||
|     { | ||||
|       int dims = base->_ndimension; | ||||
|       std::vector<int> checker_dim_mask(dims,1); | ||||
|       int checker_dim = 0; | ||||
|       Init(base->_fdimensions,base->_simd_layout,base->_processors,checker_dim_mask,checker_dim); | ||||
|     }; | ||||
|  | ||||
|     GridRedBlackCartesian(const std::vector<int> &dimensions, | ||||
|     //////////////////////////////////////////////////////////// | ||||
|     // Create redblack from original grid, with non-trivial checker dim mask | ||||
|     //////////////////////////////////////////////////////////// | ||||
|     GridRedBlackCartesian(const GridBase *base, | ||||
| 			  const std::vector<int> &checker_dim_mask, | ||||
| 			  int checker_dim | ||||
| 			  ) :  GridBase(base->_processors,*base)  | ||||
|     { | ||||
|       Init(base->_fdimensions,base->_simd_layout,base->_processors,checker_dim_mask,checker_dim)  ; | ||||
|     } | ||||
| #if 0 | ||||
|     //////////////////////////////////////////////////////////// | ||||
|     // Create redblack grid ;; deprecate these. Should not | ||||
|     // need direct creation of redblack without a full grid to base on | ||||
|     //////////////////////////////////////////////////////////// | ||||
|     GridRedBlackCartesian(const GridBase *base, | ||||
| 			  const std::vector<int> &dimensions, | ||||
| 			  const std::vector<int> &simd_layout, | ||||
| 			  const std::vector<int> &processor_grid, | ||||
| 			  const std::vector<int> &checker_dim_mask, | ||||
| 			  int checker_dim | ||||
| 			  ) :  GridBase(processor_grid)  | ||||
| 			  ) :  GridBase(processor_grid,*base)  | ||||
|     { | ||||
|       Init(dimensions,simd_layout,processor_grid,checker_dim_mask,checker_dim); | ||||
|     } | ||||
|     GridRedBlackCartesian(const std::vector<int> &dimensions, | ||||
|  | ||||
|     //////////////////////////////////////////////////////////// | ||||
|     // Create redblack grid | ||||
|     //////////////////////////////////////////////////////////// | ||||
|     GridRedBlackCartesian(const GridBase *base, | ||||
| 			  const std::vector<int> &dimensions, | ||||
| 			  const std::vector<int> &simd_layout, | ||||
| 			  const std::vector<int> &processor_grid) : GridBase(processor_grid)  | ||||
| 			  const std::vector<int> &processor_grid) : GridBase(processor_grid,*base)  | ||||
|     { | ||||
|       std::vector<int> checker_dim_mask(dimensions.size(),1); | ||||
|       Init(dimensions,simd_layout,processor_grid,checker_dim_mask,0); | ||||
|       int checker_dim = 0; | ||||
|       Init(dimensions,simd_layout,processor_grid,checker_dim_mask,checker_dim); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     void Init(const std::vector<int> &dimensions, | ||||
|               const std::vector<int> &simd_layout, | ||||
|               const std::vector<int> &processor_grid, | ||||
|   | ||||
| @@ -67,7 +67,7 @@ void CartesianCommunicator::ShmBufferFreeAll(void) { | ||||
| ///////////////////////////////// | ||||
| // Grid information queries | ||||
| ///////////////////////////////// | ||||
| int                      CartesianCommunicator::Dimensions(void)         { return _ndimension; }; | ||||
| int                      CartesianCommunicator::Dimensions(void)        { return _ndimension; }; | ||||
| int                      CartesianCommunicator::IsBoss(void)            { return _processor==0; }; | ||||
| int                      CartesianCommunicator::BossRank(void)          { return 0; }; | ||||
| int                      CartesianCommunicator::ThisRank(void)          { return _processor; }; | ||||
| @@ -147,8 +147,13 @@ void *CartesianCommunicator::ShmBufferTranslate(int rank,void * local_p) { | ||||
| } | ||||
| void CartesianCommunicator::ShmInitGeneric(void){ | ||||
| #if 1 | ||||
|  | ||||
|   int mmap_flag = MAP_SHARED | MAP_ANONYMOUS; | ||||
|   int mmap_flag =0; | ||||
| #ifdef MAP_ANONYMOUS | ||||
|   mmap_flag = mmap_flag| MAP_SHARED | MAP_ANONYMOUS; | ||||
| #endif | ||||
| #ifdef MAP_ANON | ||||
|   mmap_flag = mmap_flag| MAP_SHARED | MAP_ANON; | ||||
| #endif | ||||
| #ifdef MAP_HUGETLB | ||||
|   if ( Hugepages ) mmap_flag |= MAP_HUGETLB; | ||||
| #endif | ||||
| @@ -157,7 +162,9 @@ void CartesianCommunicator::ShmInitGeneric(void){ | ||||
|     perror("mmap failed "); | ||||
|     exit(EXIT_FAILURE);   | ||||
|   } | ||||
| #ifdef MADV_HUGEPAGE | ||||
|   if (!Hugepages ) madvise(ShmCommBuf,MAX_MPI_SHM_BYTES,MADV_HUGEPAGE); | ||||
| #endif | ||||
| #else  | ||||
|   ShmBufStorageVector.resize(MAX_MPI_SHM_BYTES); | ||||
|   ShmCommBuf=(void *)&ShmBufStorageVector[0]; | ||||
|   | ||||
| @@ -83,6 +83,7 @@ class CartesianCommunicator { | ||||
|   std::vector<MPI_Comm> communicator_halo; | ||||
|  | ||||
|   typedef MPI_Request CommsRequest_t; | ||||
|  | ||||
| #else  | ||||
|   typedef int CommsRequest_t; | ||||
| #endif | ||||
| @@ -147,11 +148,24 @@ class CartesianCommunicator { | ||||
|   // Must call in Grid startup | ||||
|   //////////////////////////////////////////////// | ||||
|   static void Init(int *argc, char ***argv); | ||||
|    | ||||
|  | ||||
|   //////////////////////////////////////////////// | ||||
|   // Constructor of any given grid | ||||
|   // Constructors to sub-divide a parent communicator | ||||
|   // and default to comm world | ||||
|   //////////////////////////////////////////////// | ||||
|   CartesianCommunicator(const std::vector<int> &processors,const CartesianCommunicator &parent); | ||||
|   CartesianCommunicator(const std::vector<int> &pdimensions_in); | ||||
|  | ||||
|  private: | ||||
| #if defined (GRID_COMMS_MPI)  | ||||
|   //|| defined (GRID_COMMS_MPI3)  | ||||
|   //////////////////////////////////////////////// | ||||
|   // Private initialise from an MPI communicator | ||||
|   // Can use after an MPI_Comm_split, but hidden from user so private | ||||
|   //////////////////////////////////////////////// | ||||
|   void InitFromMPICommunicator(const std::vector<int> &processors, MPI_Comm communicator_base); | ||||
| #endif | ||||
|  public: | ||||
|    | ||||
|   //////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Wraps MPI_Cart routines, or implements equivalent on other impls | ||||
|   | ||||
| @@ -53,24 +53,90 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | ||||
|   ShmInitGeneric(); | ||||
| } | ||||
|  | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors)  | ||||
| { | ||||
|   InitFromMPICommunicator(processors,communicator_world); | ||||
|   //  std::cout << "Passed communicator world to a new communicator" <<communicator<<std::endl; | ||||
| } | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors,const CartesianCommunicator &parent)  | ||||
| { | ||||
|   _ndimension = processors.size(); | ||||
|   std::vector<int> periodic(_ndimension,1); | ||||
|   assert(_ndimension = parent._ndimension); | ||||
|    | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // split the communicator | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   int Nparent; | ||||
|   MPI_Comm_size(parent.communicator,&Nparent); | ||||
|  | ||||
|   int childsize=1; | ||||
|   for(int d=0;d<processors.size();d++) { | ||||
|     childsize *= processors[d]; | ||||
|   } | ||||
|   int Nchild = Nparent/childsize; | ||||
|   assert (childsize * Nchild == Nparent); | ||||
|  | ||||
|   int prank;  MPI_Comm_rank(parent.communicator,&prank); | ||||
|   int crank = prank % childsize; | ||||
|   int ccomm = prank / childsize; | ||||
|  | ||||
|   MPI_Comm comm_split; | ||||
|   if ( Nchild > 1 ) {  | ||||
|  | ||||
|     std::cout << GridLogMessage<<"Child communicator of "<< std::hex << parent.communicator << std::dec<<std::endl; | ||||
|     std::cout << GridLogMessage<<" parent grid["<< parent._ndimension<<"]    "; | ||||
|     for(int d=0;d<parent._processors.size();d++)  std::cout << parent._processors[d] << " "; | ||||
|     std::cout<<std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage<<" child grid["<< _ndimension <<"]    "; | ||||
|     for(int d=0;d<processors.size();d++)  std::cout << processors[d] << " "; | ||||
|     std::cout<<std::endl; | ||||
|  | ||||
|     int ierr= MPI_Comm_split(parent.communicator, ccomm,crank,&comm_split); | ||||
|     assert(ierr==0); | ||||
|     ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|     // Declare victory | ||||
|     ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|     std::cout << GridLogMessage<<"Divided communicator "<< parent._Nprocessors<<" into " | ||||
| 	      <<Nchild <<" communicators with " << childsize << " ranks"<<std::endl; | ||||
|   } else { | ||||
|     comm_split=parent.communicator; | ||||
|     //    std::cout << "Passed parental communicator to a new communicator" <<std::endl; | ||||
|   } | ||||
|  | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Set up from the new split communicator | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   InitFromMPICommunicator(processors,comm_split); | ||||
|  | ||||
| } | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Take an MPI_Comm and self assemble | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| void CartesianCommunicator::InitFromMPICommunicator(const std::vector<int> &processors, MPI_Comm communicator_base) | ||||
| { | ||||
|   //  if ( communicator_base != communicator_world ) { | ||||
|   //    std::cout << "Cartesian communicator created with a non-world communicator"<<std::endl; | ||||
|   //  } | ||||
|   _ndimension = processors.size(); | ||||
|   _processor_coor.resize(_ndimension); | ||||
|  | ||||
|   ///////////////////////////////// | ||||
|   // Count the requested nodes | ||||
|   ///////////////////////////////// | ||||
|   _Nprocessors=1; | ||||
|   _processors = processors; | ||||
|   _processor_coor.resize(_ndimension); | ||||
|    | ||||
|   MPI_Cart_create(communicator_world, _ndimension,&_processors[0],&periodic[0],1,&communicator); | ||||
|   MPI_Comm_rank(communicator,&_processor); | ||||
|   MPI_Cart_coords(communicator,_processor,_ndimension,&_processor_coor[0]); | ||||
|  | ||||
|   for(int i=0;i<_ndimension;i++){ | ||||
|     _Nprocessors*=_processors[i]; | ||||
|   } | ||||
|    | ||||
|   int Size;  | ||||
|  | ||||
|   std::vector<int> periodic(_ndimension,1); | ||||
|   MPI_Cart_create(communicator_base, _ndimension,&_processors[0],&periodic[0],1,&communicator); | ||||
|   MPI_Comm_rank(communicator,&_processor); | ||||
|   MPI_Cart_coords(communicator,_processor,_ndimension,&_processor_coor[0]); | ||||
|  | ||||
|   int Size; | ||||
|   MPI_Comm_size(communicator,&Size); | ||||
|    | ||||
|   assert(Size==_Nprocessors); | ||||
|   | ||||
| @@ -215,8 +215,10 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | ||||
|       perror("open hugetlbfs"); | ||||
|       exit(0); | ||||
|     } | ||||
|      | ||||
|     int mmap_flag = MAP_SHARED |MAP_POPULATE; | ||||
|     int mmap_flag = MAP_SHARED ; | ||||
| #ifdef MAP_POPULATE     | ||||
|     mmap_flag|=MAP_POPULATE; | ||||
| #endif | ||||
| #ifdef MAP_HUGETLB | ||||
|     if ( Hugepages ) mmap_flag |= MAP_HUGETLB; | ||||
| #endif | ||||
| @@ -249,7 +251,10 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | ||||
|       if ( fd < 0 ) {	perror("failed shm_open");	assert(0);      } | ||||
|       ftruncate(fd, size); | ||||
|        | ||||
|       int mmap_flag = MAP_SHARED|MAP_POPULATE; | ||||
|       int mmap_flag = MAP_SHARED; | ||||
| #ifdef MAP_POPULATE  | ||||
|       mmap_flag |= MAP_POPULATE; | ||||
| #endif | ||||
| #ifdef MAP_HUGETLB | ||||
|       if (Hugepages) mmap_flag |= MAP_HUGETLB; | ||||
| #endif | ||||
| @@ -445,6 +450,15 @@ void  CartesianCommunicator::ProcessorCoorFromRank(int rank, std::vector<int> &c | ||||
|   assert(lr!=-1); | ||||
|   Lexicographic::CoorFromIndex(coor,lr,_processors); | ||||
| } | ||||
|  | ||||
| ////////////////////////////////// | ||||
| // Try to subdivide communicator | ||||
| ////////////////////////////////// | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors,const CartesianCommunicator &parent)  | ||||
|   : CartesianCommunicator(processors)  | ||||
| { | ||||
|   std::cout << "Attempts to split MPI3 communicators will fail until implemented" <<std::endl; | ||||
| } | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) | ||||
| {  | ||||
|   int ierr; | ||||
|   | ||||
| @@ -38,6 +38,9 @@ void CartesianCommunicator::Init(int *argc, char *** arv) | ||||
|   ShmInitGeneric(); | ||||
| } | ||||
|  | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors,const CartesianCommunicator &parent)  | ||||
|   : CartesianCommunicator(processors) {} | ||||
|  | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) | ||||
| { | ||||
|   _processors = processors; | ||||
|   | ||||
| @@ -75,6 +75,11 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | ||||
|   ShmInitGeneric(); | ||||
| } | ||||
|  | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors,const CartesianCommunicator &parent)  | ||||
|   : CartesianCommunicator(processors)  | ||||
| { | ||||
|   std::cout << "Attempts to split SHMEM communicators will fail " <<std::endl; | ||||
| } | ||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) | ||||
| { | ||||
|   _ndimension = processors.size(); | ||||
|   | ||||
							
								
								
									
										16252
									
								
								lib/json/json.hpp
									
									
									
									
									
								
							
							
						
						
									
										16252
									
								
								lib/json/json.hpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -544,7 +544,6 @@ static void sliceInnerProductMatrix(  Eigen::MatrixXcd &mat, const Lattice<vobj> | ||||
|       for(int i=0;i<Nblock;i++){ | ||||
|       for(int j=0;j<Nblock;j++){ | ||||
| 	auto tmp = innerProduct(Left[i],Right[j]); | ||||
| 	//	vector_typeD rtmp = TensorRemove(tmp); | ||||
| 	auto rtmp = TensorRemove(tmp); | ||||
| 	mat_thread(i,j) += Reduce(rtmp); | ||||
|       }} | ||||
|   | ||||
| @@ -84,10 +84,6 @@ namespace QCD { | ||||
|    stream << "GRID_"; | ||||
|    stream << ScidacWordMnemonic<stype>(); | ||||
|  | ||||
|    //   std::cout << " Lorentz N/S/V/M : " << _LorentzN<<" "<<_LorentzScalar<<"/"<<_LorentzVector<<"/"<<_LorentzMatrix<<std::endl; | ||||
|    //   std::cout << " Spin    N/S/V/M : " << _SpinN   <<" "<<_SpinScalar   <<"/"<<_SpinVector   <<"/"<<_SpinMatrix<<std::endl; | ||||
|    //   std::cout << " Colour  N/S/V/M : " << _ColourN <<" "<<_ColourScalar <<"/"<<_ColourVector <<"/"<<_ColourMatrix<<std::endl; | ||||
|  | ||||
|    if ( _LorentzVector )   stream << "_LorentzVector"<<_LorentzN; | ||||
|    if ( _LorentzMatrix )   stream << "_LorentzMatrix"<<_LorentzN; | ||||
|  | ||||
| @@ -182,7 +178,7 @@ class GridLimeReader : public BinaryIO { | ||||
|    ///////////////////////////////////////////// | ||||
|    // Open the file | ||||
|    ///////////////////////////////////////////// | ||||
|    void open(std::string &_filename)  | ||||
|    void open(const std::string &_filename)  | ||||
|    { | ||||
|      filename= _filename; | ||||
|      File = fopen(filename.c_str(), "r"); | ||||
| @@ -210,19 +206,33 @@ class GridLimeReader : public BinaryIO { | ||||
|  | ||||
|     while ( limeReaderNextRecord(LimeR) == LIME_SUCCESS ) {  | ||||
|  | ||||
|       std::cout << GridLogMessage << limeReaderType(LimeR) <<std::endl; | ||||
| 	 | ||||
|       if ( strncmp(limeReaderType(LimeR), record_name.c_str(),strlen(record_name.c_str()) )  ) { | ||||
|       uint64_t file_bytes =limeReaderBytes(LimeR); | ||||
|  | ||||
|       //      std::cout << GridLogMessage << limeReaderType(LimeR) << " "<< file_bytes <<" bytes "<<std::endl; | ||||
|       //      std::cout << GridLogMessage<< " readLimeObject seeking "<<  record_name <<" found record :" <<limeReaderType(LimeR) <<std::endl; | ||||
|  | ||||
|       if ( !strncmp(limeReaderType(LimeR), record_name.c_str(),strlen(record_name.c_str()) )  ) { | ||||
|  | ||||
| 	//	std::cout << GridLogMessage<< " readLimeLatticeBinaryObject matches ! " <<std::endl; | ||||
|  | ||||
| 	uint64_t PayloadSize = sizeof(sobj) * field._grid->_gsites; | ||||
|  | ||||
| 	//	std::cout << "R sizeof(sobj)= " <<sizeof(sobj)<<std::endl; | ||||
| 	//	std::cout << "R Gsites " <<field._grid->_gsites<<std::endl; | ||||
| 	//	std::cout << "R Payload expected " <<PayloadSize<<std::endl; | ||||
| 	//	std::cout << "R file size " <<file_bytes <<std::endl; | ||||
|  | ||||
| 	assert(PayloadSize == file_bytes);// Must match or user error | ||||
|  | ||||
| 	off_t offset= ftell(File); | ||||
| 	//	std::cout << " ReadLatticeObject from offset "<<offset << std::endl; | ||||
| 	BinarySimpleMunger<sobj,sobj> munge; | ||||
| 	BinaryIO::readLatticeObject< sobj, sobj >(field, filename, munge, offset, format,nersc_csum,scidac_csuma,scidac_csumb); | ||||
| 	BinaryIO::readLatticeObject< vobj, sobj >(field, filename, munge, offset, format,nersc_csum,scidac_csuma,scidac_csumb); | ||||
|  | ||||
| 	///////////////////////////////////////////// | ||||
| 	// Insist checksum is next record | ||||
| 	///////////////////////////////////////////// | ||||
| 	readLimeObject(scidacChecksum_,std::string("scidacChecksum"),record_name); | ||||
| 	readLimeObject(scidacChecksum_,std::string("scidacChecksum"),std::string(SCIDAC_CHECKSUM)); | ||||
|  | ||||
| 	///////////////////////////////////////////// | ||||
| 	// Verify checksums | ||||
| @@ -242,11 +252,19 @@ class GridLimeReader : public BinaryIO { | ||||
|     // should this be a do while; can we miss a first record?? | ||||
|     while ( limeReaderNextRecord(LimeR) == LIME_SUCCESS ) {  | ||||
|  | ||||
|       //      std::cout << GridLogMessage<< " readLimeObject seeking "<< record_name <<" found record :" <<limeReaderType(LimeR) <<std::endl; | ||||
|  | ||||
|       uint64_t nbytes = limeReaderBytes(LimeR);//size of this record (configuration) | ||||
|  | ||||
|       if ( strncmp(limeReaderType(LimeR), record_name.c_str(),strlen(record_name.c_str()) )  ) { | ||||
|       if ( !strncmp(limeReaderType(LimeR), record_name.c_str(),strlen(record_name.c_str()) )  ) { | ||||
|  | ||||
| 	//	std::cout << GridLogMessage<< " readLimeObject matches ! " << record_name <<std::endl; | ||||
|  | ||||
| 	std::vector<char> xmlc(nbytes+1,'\0'); | ||||
| 	limeReaderReadData((void *)&xmlc[0], &nbytes, LimeR);     | ||||
|  | ||||
| 	//	std::cout << GridLogMessage<< " readLimeObject matches XML " << &xmlc[0] <<std::endl; | ||||
|  | ||||
| 	XmlReader RD(&xmlc[0],""); | ||||
| 	read(RD,object_name,object); | ||||
| 	return; | ||||
| @@ -261,13 +279,14 @@ class GridLimeWriter : public BinaryIO { | ||||
|  public: | ||||
|    /////////////////////////////////////////////////// | ||||
|    // FIXME: format for RNG? Now just binary out instead | ||||
|    // FIXME: collective calls or not ? | ||||
|    //      : must know if I am the I/O boss | ||||
|    /////////////////////////////////////////////////// | ||||
|  | ||||
|    FILE       *File; | ||||
|    LimeWriter *LimeW; | ||||
|    std::string filename; | ||||
|  | ||||
|    void open(std::string &_filename) {  | ||||
|    void open(const std::string &_filename) {  | ||||
|      filename= _filename; | ||||
|      File = fopen(filename.c_str(), "w"); | ||||
|      LimeW = limeCreateWriter(File); assert(LimeW != NULL ); | ||||
| @@ -302,14 +321,18 @@ class GridLimeWriter : public BinaryIO { | ||||
|       write(WR,object_name,object); | ||||
|       xmlstring = WR.XmlString(); | ||||
|     } | ||||
|     //    std::cout << "WriteLimeObject" << record_name <<std::endl; | ||||
|     uint64_t nbytes = xmlstring.size(); | ||||
|     //    std::cout << " xmlstring "<< nbytes<< " " << xmlstring <<std::endl; | ||||
|     int err; | ||||
|     LimeRecordHeader *h = limeCreateHeader(MB, ME,(char *)record_name.c_str(), nbytes); assert(h!= NULL); | ||||
|     LimeRecordHeader *h = limeCreateHeader(MB, ME,const_cast<char *>(record_name.c_str()), nbytes);  | ||||
|     assert(h!= NULL); | ||||
|  | ||||
|     err=limeWriteRecordHeader(h, LimeW);                    assert(err>=0); | ||||
|     err=limeWriteRecordData(&xmlstring[0], &nbytes, LimeW); assert(err>=0); | ||||
|     err=limeWriterCloseRecord(LimeW);                       assert(err>=0); | ||||
|     limeDestroyHeader(h); | ||||
|     //    std::cout << " File offset is now"<<ftell(File) << std::endl; | ||||
|   } | ||||
|   //////////////////////////////////////////// | ||||
|   // Write a generic lattice field and csum | ||||
| @@ -326,6 +349,11 @@ class GridLimeWriter : public BinaryIO { | ||||
|     uint64_t PayloadSize = sizeof(sobj) * field._grid->_gsites; | ||||
|     createLimeRecordHeader(record_name, 0, 0, PayloadSize); | ||||
|  | ||||
|  | ||||
|     //    std::cout << "W sizeof(sobj)"      <<sizeof(sobj)<<std::endl; | ||||
|     //    std::cout << "W Gsites "           <<field._grid->_gsites<<std::endl; | ||||
|     //    std::cout << "W Payload expected " <<PayloadSize<<std::endl; | ||||
|  | ||||
|     //////////////////////////////////////////////////////////////////// | ||||
|     // NB: FILE and iostream are jointly writing disjoint sequences in the | ||||
|     // the same file through different file handles (integer units). | ||||
| @@ -340,6 +368,7 @@ class GridLimeWriter : public BinaryIO { | ||||
|     //  v) Continue writing scidac record. | ||||
|     //////////////////////////////////////////////////////////////////// | ||||
|     off_t offset = ftell(File); | ||||
|     //    std::cout << " Writing to offset "<<offset << std::endl; | ||||
|     std::string format = getFormatString<vobj>(); | ||||
|     BinarySimpleMunger<sobj,sobj> munge; | ||||
|     BinaryIO::writeLatticeObject<vobj,sobj>(field, filename, munge, offset, format,nersc_csum,scidac_csuma,scidac_csumb); | ||||
| @@ -354,7 +383,7 @@ class GridLimeWriter : public BinaryIO { | ||||
|     checksum.suma= streama.str(); | ||||
|     checksum.sumb= streamb.str(); | ||||
|     std::cout << GridLogMessage<<" writing scidac checksums "<<std::hex<<scidac_csuma<<"/"<<scidac_csumb<<std::dec<<std::endl; | ||||
|     writeLimeObject(0,1,checksum,std::string("scidacChecksum"    ),std::string(SCIDAC_CHECKSUM)); | ||||
|     writeLimeObject(0,1,checksum,std::string("scidacChecksum"),std::string(SCIDAC_CHECKSUM)); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -371,11 +400,9 @@ class ScidacWriter : public GridLimeWriter { | ||||
|   //////////////////////////////////////////////// | ||||
|   // Write generic lattice field in scidac format | ||||
|   //////////////////////////////////////////////// | ||||
|    template <class vobj, class userRecord> | ||||
|   template <class vobj, class userRecord> | ||||
|   void writeScidacFieldRecord(Lattice<vobj> &field,userRecord _userRecord)  | ||||
|   { | ||||
|     typedef typename vobj::scalar_object sobj; | ||||
|     uint64_t nbytes; | ||||
|     GridBase * grid = field._grid; | ||||
|  | ||||
|     //////////////////////////////////////// | ||||
| @@ -397,6 +424,66 @@ class ScidacWriter : public GridLimeWriter { | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| class ScidacReader : public GridLimeReader { | ||||
|  public: | ||||
|  | ||||
|    template<class SerialisableUserFile> | ||||
|    void readScidacFileRecord(GridBase *grid,SerialisableUserFile &_userFile) | ||||
|    { | ||||
|      scidacFile    _scidacFile(grid); | ||||
|      readLimeObject(_scidacFile,_scidacFile.SerialisableClassName(),std::string(SCIDAC_PRIVATE_FILE_XML)); | ||||
|      readLimeObject(_userFile,_userFile.SerialisableClassName(),std::string(SCIDAC_FILE_XML)); | ||||
|    } | ||||
|   //////////////////////////////////////////////// | ||||
|   // Write generic lattice field in scidac format | ||||
|   //////////////////////////////////////////////// | ||||
|   template <class vobj, class userRecord> | ||||
|   void readScidacFieldRecord(Lattice<vobj> &field,userRecord &_userRecord)  | ||||
|   { | ||||
|     typedef typename vobj::scalar_object sobj; | ||||
|     GridBase * grid = field._grid; | ||||
|  | ||||
|     //////////////////////////////////////// | ||||
|     // fill the Grid header | ||||
|     //////////////////////////////////////// | ||||
|     FieldMetaData header; | ||||
|     scidacRecord  _scidacRecord; | ||||
|     scidacFile    _scidacFile; | ||||
|  | ||||
|     ////////////////////////////////////////////// | ||||
|     // Fill the Lime file record by record | ||||
|     ////////////////////////////////////////////// | ||||
|     readLimeObject(header ,std::string("FieldMetaData"),std::string(GRID_FORMAT)); // Open message  | ||||
|     readLimeObject(_userRecord,_userRecord.SerialisableClassName(),std::string(SCIDAC_RECORD_XML)); | ||||
|     readLimeObject(_scidacRecord,_scidacRecord.SerialisableClassName(),std::string(SCIDAC_PRIVATE_RECORD_XML)); | ||||
|     readLimeLatticeBinaryObject(field,std::string(ILDG_BINARY_DATA)); | ||||
|   } | ||||
|   void skipPastBinaryRecord(void) { | ||||
|     std::string rec_name(ILDG_BINARY_DATA); | ||||
|     while ( limeReaderNextRecord(LimeR) == LIME_SUCCESS ) {  | ||||
|       if ( !strncmp(limeReaderType(LimeR), rec_name.c_str(),strlen(rec_name.c_str()) )  ) { | ||||
| 	skipPastObjectRecord(std::string(SCIDAC_CHECKSUM)); | ||||
| 	return; | ||||
|       } | ||||
|     }     | ||||
|   } | ||||
|   void skipPastObjectRecord(std::string rec_name) { | ||||
|     while ( limeReaderNextRecord(LimeR) == LIME_SUCCESS ) {  | ||||
|       if ( !strncmp(limeReaderType(LimeR), rec_name.c_str(),strlen(rec_name.c_str()) )  ) { | ||||
| 	return; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   void skipScidacFieldRecord() { | ||||
|     skipPastObjectRecord(std::string(GRID_FORMAT)); | ||||
|     skipPastObjectRecord(std::string(SCIDAC_RECORD_XML)); | ||||
|     skipPastObjectRecord(std::string(SCIDAC_PRIVATE_RECORD_XML)); | ||||
|     skipPastBinaryRecord(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| class IldgWriter : public ScidacWriter { | ||||
|  public: | ||||
|  | ||||
| @@ -425,8 +512,6 @@ class IldgWriter : public ScidacWriter { | ||||
|     typedef iLorentzColourMatrix<vsimd> vobj; | ||||
|     typedef typename vobj::scalar_object sobj; | ||||
|  | ||||
|     uint64_t nbytes; | ||||
|  | ||||
|     //////////////////////////////////////// | ||||
|     // fill the Grid header | ||||
|     //////////////////////////////////////// | ||||
|   | ||||
| @@ -64,6 +64,11 @@ namespace Grid { | ||||
| // file compatability, so should be correct to assume the undocumented but defacto file structure. | ||||
| ///////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| struct emptyUserRecord : Serializable {  | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(emptyUserRecord,int,dummy); | ||||
|   emptyUserRecord() { dummy=0; }; | ||||
| }; | ||||
|  | ||||
| //////////////////////// | ||||
| // Scidac private file xml | ||||
| // <?xml version="1.0" encoding="UTF-8"?><scidacFile><version>1.1</version><spacetime>4</spacetime><dims>16 16 16 32 </dims><volfmt>0</volfmt></scidacFile> | ||||
|   | ||||
| @@ -85,6 +85,9 @@ namespace Grid { | ||||
| 	nd=4; | ||||
| 	dimension.resize(4); | ||||
| 	boundary.resize(4); | ||||
| 	scidac_checksuma=0; | ||||
| 	scidac_checksumb=0; | ||||
| 	checksum=0; | ||||
|       } | ||||
|     }; | ||||
|  | ||||
| @@ -104,6 +107,7 @@ namespace Grid { | ||||
|       header.nd = nd; | ||||
|       header.dimension.resize(nd); | ||||
|       header.boundary.resize(nd); | ||||
|       header.data_start = 0; | ||||
|       for(int d=0;d<nd;d++) { | ||||
| 	header.dimension[d] = grid->_fdimensions[d]; | ||||
|       } | ||||
|   | ||||
							
								
								
									
										100
									
								
								lib/qcd/action/fermion/AbstractEOFAFermion.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								lib/qcd/action/fermion/AbstractEOFAFermion.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/AbstractEOFAFermion.h | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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_QCD_ABSTRACT_EOFA_FERMION_H | ||||
| #define  GRID_QCD_ABSTRACT_EOFA_FERMION_H | ||||
|  | ||||
| #include <Grid/qcd/action/fermion/CayleyFermion5D.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|   // DJM: Abstract base class for EOFA fermion types. | ||||
|   // Defines layout of additional EOFA-specific parameters and operators. | ||||
|   // Use to construct EOFA pseudofermion actions that are agnostic to | ||||
|   // Shamir / Mobius / etc., and ensure that no one can construct EOFA | ||||
|   // pseudofermion action with non-EOFA fermion type. | ||||
|   template<class Impl> | ||||
|   class AbstractEOFAFermion : public CayleyFermion5D<Impl> { | ||||
|     public: | ||||
|       INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|     public: | ||||
|       // Fermion operator: D(mq1) + shift*\gamma_{5}*R_{5}*\Delta_{\pm}(mq2,mq3)*P_{\pm} | ||||
|       RealD mq1; | ||||
|       RealD mq2; | ||||
|       RealD mq3; | ||||
|       RealD shift; | ||||
|       int pm; | ||||
|  | ||||
|       RealD alpha; // Mobius scale | ||||
|       RealD k;     // EOFA normalization constant | ||||
|  | ||||
|       virtual void Instantiatable(void) = 0; | ||||
|  | ||||
|       // EOFA-specific operations | ||||
|       // Force user to implement in derived classes | ||||
|       virtual void  Omega    (const FermionField& in, FermionField& out, int sign, int dag) = 0; | ||||
|       virtual void  Dtilde   (const FermionField& in, FermionField& out) = 0; | ||||
|       virtual void  DtildeInv(const FermionField& in, FermionField& out) = 0; | ||||
|  | ||||
|       // Implement derivatives in base class: | ||||
|       // for EOFA both DWF and Mobius just need d(Dw)/dU | ||||
|       virtual void MDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag){ | ||||
|         this->DhopDeriv(mat, U, V, dag); | ||||
|       }; | ||||
|       virtual void MoeDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag){ | ||||
|         this->DhopDerivOE(mat, U, V, dag); | ||||
|       }; | ||||
|       virtual void MeoDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag){ | ||||
|         this->DhopDerivEO(mat, U, V, dag); | ||||
|       }; | ||||
|  | ||||
|       // Recompute 5D coefficients for different value of shift constant | ||||
|       // (needed for heatbath loop over poles) | ||||
|       virtual void RefreshShiftCoefficients(RealD new_shift) = 0; | ||||
|  | ||||
|       // Constructors | ||||
|       AbstractEOFAFermion(GaugeField& _Umu, GridCartesian& FiveDimGrid, GridRedBlackCartesian& FiveDimRedBlackGrid, | ||||
|         GridCartesian& FourDimGrid, GridRedBlackCartesian& FourDimRedBlackGrid, | ||||
|         RealD _mq1, RealD _mq2, RealD _mq3, RealD _shift, int _pm, | ||||
|         RealD _M5, RealD _b, RealD _c, const ImplParams& p=ImplParams()) | ||||
|         : CayleyFermion5D<Impl>(_Umu, FiveDimGrid, FiveDimRedBlackGrid, FourDimGrid, FourDimRedBlackGrid, | ||||
|           _mq1, _M5, p), mq1(_mq1), mq2(_mq2), mq3(_mq3), shift(_shift), pm(_pm) | ||||
|       { | ||||
|         int Ls = this->Ls; | ||||
|         this->alpha = _b + _c; | ||||
|         this->k = this->alpha * (_mq3-_mq2) * std::pow(this->alpha+1.0,2*Ls) / | ||||
|                     ( std::pow(this->alpha+1.0,Ls) + _mq2*std::pow(this->alpha-1.0,Ls) ) / | ||||
|                     ( std::pow(this->alpha+1.0,Ls) + _mq3*std::pow(this->alpha-1.0,Ls) ); | ||||
|       }; | ||||
|   }; | ||||
| }} | ||||
|  | ||||
| #endif | ||||
| @@ -1,6 +1,6 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/CayleyFermion5D.h | ||||
|  | ||||
| @@ -35,24 +35,24 @@ namespace Grid { | ||||
|  | ||||
|   namespace QCD { | ||||
|  | ||||
|      template<typename T> struct switcheroo   {   | ||||
|        static inline int iscomplex()  { return 0; }  | ||||
|      template<typename T> struct switcheroo   { | ||||
|        static inline int iscomplex()  { return 0; } | ||||
|  | ||||
|        template<class vec> | ||||
|        static inline vec mult(vec a, vec b) { | ||||
| 	 return real_mult(a,b); | ||||
|        } | ||||
|      }; | ||||
|      template<> struct switcheroo<ComplexD> {   | ||||
|        static inline int iscomplex()  { return 1; }  | ||||
|      template<> struct switcheroo<ComplexD> { | ||||
|        static inline int iscomplex()  { return 1; } | ||||
|  | ||||
|        template<class vec> | ||||
|        static inline vec mult(vec a, vec b) { | ||||
| 	 return a*b; | ||||
|        } | ||||
|      }; | ||||
|      template<> struct switcheroo<ComplexF> {   | ||||
|        static inline int iscomplex()  { return 1; }  | ||||
|      template<> struct switcheroo<ComplexF> { | ||||
|        static inline int iscomplex()  { return 1; } | ||||
|        template<class vec> | ||||
|        static inline vec mult(vec a, vec b) { | ||||
| 	 return a*b; | ||||
| @@ -90,14 +90,14 @@ namespace Grid { | ||||
|       // Instantiate different versions depending on Impl | ||||
|       ///////////////////////////////////////////////////// | ||||
|       void M5D(const FermionField &psi, | ||||
| 	       const FermionField &phi,  | ||||
| 	       const FermionField &phi, | ||||
| 	       FermionField &chi, | ||||
| 	       std::vector<Coeff_t> &lower, | ||||
| 	       std::vector<Coeff_t> &diag, | ||||
| 	       std::vector<Coeff_t> &upper); | ||||
|  | ||||
|       void M5Ddag(const FermionField &psi, | ||||
| 		  const FermionField &phi,  | ||||
| 		  const FermionField &phi, | ||||
| 		  FermionField &chi, | ||||
| 		  std::vector<Coeff_t> &lower, | ||||
| 		  std::vector<Coeff_t> &diag, | ||||
| @@ -125,7 +125,7 @@ namespace Grid { | ||||
|  | ||||
|       // Efficient support for multigrid coarsening | ||||
|       virtual void  Mdir (const FermionField &in, FermionField &out,int dir,int disp); | ||||
|        | ||||
|  | ||||
|       void   Meooe5D       (const FermionField &in, FermionField &out); | ||||
|       void   MeooeDag5D    (const FermionField &in, FermionField &out); | ||||
|  | ||||
| @@ -133,23 +133,23 @@ namespace Grid { | ||||
|       RealD mass; | ||||
|  | ||||
|       // Cayley form Moebius (tanh and zolotarev) | ||||
|       std::vector<Coeff_t> omega;  | ||||
|       std::vector<Coeff_t> omega; | ||||
|       std::vector<Coeff_t> bs;    // S dependent coeffs | ||||
|       std::vector<Coeff_t> cs;     | ||||
|       std::vector<Coeff_t> as;     | ||||
|       std::vector<Coeff_t> cs; | ||||
|       std::vector<Coeff_t> as; | ||||
|       // For preconditioning Cayley form | ||||
|       std::vector<Coeff_t> bee;     | ||||
|       std::vector<Coeff_t> cee;     | ||||
|       std::vector<Coeff_t> aee;     | ||||
|       std::vector<Coeff_t> beo;     | ||||
|       std::vector<Coeff_t> ceo;     | ||||
|       std::vector<Coeff_t> aeo;     | ||||
|       std::vector<Coeff_t> bee; | ||||
|       std::vector<Coeff_t> cee; | ||||
|       std::vector<Coeff_t> aee; | ||||
|       std::vector<Coeff_t> beo; | ||||
|       std::vector<Coeff_t> ceo; | ||||
|       std::vector<Coeff_t> aeo; | ||||
|       // LDU factorisation of the eeoo matrix | ||||
|       std::vector<Coeff_t> lee;     | ||||
|       std::vector<Coeff_t> leem;     | ||||
|       std::vector<Coeff_t> uee;     | ||||
|       std::vector<Coeff_t> ueem;     | ||||
|       std::vector<Coeff_t> dee;     | ||||
|       std::vector<Coeff_t> lee; | ||||
|       std::vector<Coeff_t> leem; | ||||
|       std::vector<Coeff_t> uee; | ||||
|       std::vector<Coeff_t> ueem; | ||||
|       std::vector<Coeff_t> dee; | ||||
|  | ||||
|       // Matrices of 5d ee inverse params | ||||
|       Vector<iSinglet<Simd> >  MatpInv; | ||||
| @@ -165,7 +165,7 @@ namespace Grid { | ||||
| 		      GridRedBlackCartesian &FourDimRedBlackGrid, | ||||
| 		      RealD _mass,RealD _M5,const ImplParams &p= ImplParams()); | ||||
|  | ||||
|        | ||||
|  | ||||
|  | ||||
|      void CayleyReport(void); | ||||
|      void CayleyZeroCounters(void); | ||||
| @@ -179,9 +179,9 @@ namespace Grid { | ||||
|      double MooeeInvTime; | ||||
|  | ||||
|     protected: | ||||
|       void SetCoefficientsZolotarev(RealD zolohi,Approx::zolotarev_data *zdata,RealD b,RealD c); | ||||
|       void SetCoefficientsTanh(Approx::zolotarev_data *zdata,RealD b,RealD c); | ||||
|       void SetCoefficientsInternal(RealD zolo_hi,std::vector<Coeff_t> & gamma,RealD b,RealD c); | ||||
|       virtual void SetCoefficientsZolotarev(RealD zolohi,Approx::zolotarev_data *zdata,RealD b,RealD c); | ||||
|       virtual void SetCoefficientsTanh(Approx::zolotarev_data *zdata,RealD b,RealD c); | ||||
|       virtual void SetCoefficientsInternal(RealD zolo_hi,std::vector<Coeff_t> & gamma,RealD b,RealD c); | ||||
|     }; | ||||
|  | ||||
|   } | ||||
|   | ||||
							
								
								
									
										438
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermion.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										438
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermion.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,438 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/DomainWallEOFAFermion.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid_Eigen_Dense.h> | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/DomainWallEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|     template<class Impl> | ||||
|     DomainWallEOFAFermion<Impl>::DomainWallEOFAFermion( | ||||
|       GaugeField            &_Umu, | ||||
|       GridCartesian         &FiveDimGrid, | ||||
|       GridRedBlackCartesian &FiveDimRedBlackGrid, | ||||
|       GridCartesian         &FourDimGrid, | ||||
|       GridRedBlackCartesian &FourDimRedBlackGrid, | ||||
|       RealD _mq1, RealD _mq2, RealD _mq3, | ||||
|       RealD _shift, int _pm, RealD _M5, const ImplParams &p) : | ||||
|     AbstractEOFAFermion<Impl>(_Umu, FiveDimGrid, FiveDimRedBlackGrid, | ||||
|         FourDimGrid, FourDimRedBlackGrid, _mq1, _mq2, _mq3, | ||||
|         _shift, _pm, _M5, 1.0, 0.0, p) | ||||
|     { | ||||
|         RealD eps = 1.0; | ||||
|         Approx::zolotarev_data *zdata = Approx::higham(eps,this->Ls); | ||||
|         assert(zdata->n == this->Ls); | ||||
|  | ||||
|         std::cout << GridLogMessage << "DomainWallEOFAFermion with Ls=" << this->Ls << std::endl; | ||||
|         this->SetCoefficientsTanh(zdata, 1.0, 0.0); | ||||
|  | ||||
|         Approx::zolotarev_free(zdata); | ||||
|     } | ||||
|  | ||||
|     /*************************************************************** | ||||
|     /* Additional EOFA operators only called outside the inverter. | ||||
|     /* Since speed is not essential, simple axpby-style | ||||
|     /* implementations should be fine. | ||||
|     /***************************************************************/ | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::Omega(const FermionField& psi, FermionField& Din, int sign, int dag) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         Din = zero; | ||||
|         if((sign == 1) && (dag == 0)){ axpby_ssp(Din, 0.0, psi, 1.0, psi, Ls-1, 0); } | ||||
|         else if((sign == -1) && (dag == 0)){ axpby_ssp(Din, 0.0, psi, 1.0, psi, 0, 0); } | ||||
|         else if((sign == 1 ) && (dag == 1)){ axpby_ssp(Din, 0.0, psi, 1.0, psi, 0, Ls-1); } | ||||
|         else if((sign == -1) && (dag == 1)){ axpby_ssp(Din, 0.0, psi, 1.0, psi, 0, 0); } | ||||
|     } | ||||
|  | ||||
|     // This is just the identity for DWF | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::Dtilde(const FermionField& psi, FermionField& chi){ chi = psi; } | ||||
|  | ||||
|     // This is just the identity for DWF | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::DtildeInv(const FermionField& psi, FermionField& chi){ chi = psi; } | ||||
|  | ||||
|     /*****************************************************************************************************/ | ||||
|  | ||||
|     template<class Impl> | ||||
|     RealD DomainWallEOFAFermion<Impl>::M(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         FermionField Din(psi._grid); | ||||
|  | ||||
|         this->Meooe5D(psi, Din); | ||||
|         this->DW(Din, chi, DaggerNo); | ||||
|         axpby(chi, 1.0, 1.0, chi, psi); | ||||
|         this->M5D(psi, chi); | ||||
|         return(norm2(chi)); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     RealD DomainWallEOFAFermion<Impl>::Mdag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         FermionField Din(psi._grid); | ||||
|  | ||||
|         this->DW(psi, Din, DaggerYes); | ||||
|         this->MeooeDag5D(Din, chi); | ||||
|         this->M5Ddag(psi, chi); | ||||
|         axpby(chi, 1.0, 1.0, chi, psi); | ||||
|         return(norm2(chi)); | ||||
|     } | ||||
|  | ||||
|     /******************************************************************** | ||||
|     /* Performance critical fermion operators called inside the inverter | ||||
|     /********************************************************************/ | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::M5D(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         int   Ls    = this->Ls; | ||||
|         int   pm    = this->pm; | ||||
|         RealD shift = this->shift; | ||||
|         RealD mq1   = this->mq1; | ||||
|         RealD mq2   = this->mq2; | ||||
|         RealD mq3   = this->mq3; | ||||
|  | ||||
|         // coefficients for shift operator ( = shift*\gamma_{5}*R_{5}*\Delta_{\pm}(mq2,mq3)*P_{\pm} ) | ||||
|         Coeff_t shiftp(0.0), shiftm(0.0); | ||||
|         if(shift != 0.0){ | ||||
|           if(pm == 1){ shiftp = shift*(mq3-mq2); } | ||||
|           else{ shiftm = -shift*(mq3-mq2); } | ||||
|         } | ||||
|  | ||||
|         std::vector<Coeff_t> diag(Ls,1.0); | ||||
|         std::vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1] = mq1 + shiftm; | ||||
|         std::vector<Coeff_t> lower(Ls,-1.0); lower[0]    = mq1 + shiftp; | ||||
|  | ||||
|         #if(0) | ||||
|             std::cout << GridLogMessage << "DomainWallEOFAFermion::M5D(FF&,FF&):" << std::endl; | ||||
|             for(int i=0; i<diag.size(); ++i){ | ||||
|                 std::cout << GridLogMessage << "diag[" << i << "] =" << diag[i] << std::endl; | ||||
|             } | ||||
|             for(int i=0; i<upper.size(); ++i){ | ||||
|                 std::cout << GridLogMessage << "upper[" << i << "] =" << upper[i] << std::endl; | ||||
|             } | ||||
|             for(int i=0; i<lower.size(); ++i){ | ||||
|                 std::cout << GridLogMessage << "lower[" << i << "] =" << lower[i] << std::endl; | ||||
|             } | ||||
|         #endif | ||||
|  | ||||
|         this->M5D(psi, chi, chi, lower, diag, upper); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::M5Ddag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         int   Ls    = this->Ls; | ||||
|         int   pm    = this->pm; | ||||
|         RealD shift = this->shift; | ||||
|         RealD mq1   = this->mq1; | ||||
|         RealD mq2   = this->mq2; | ||||
|         RealD mq3   = this->mq3; | ||||
|  | ||||
|         // coefficients for shift operator ( = shift*\gamma_{5}*R_{5}*\Delta_{\pm}(mq2,mq3)*P_{\pm} ) | ||||
|         Coeff_t shiftp(0.0), shiftm(0.0); | ||||
|         if(shift != 0.0){ | ||||
|           if(pm == 1){ shiftp = shift*(mq3-mq2); } | ||||
|           else{ shiftm = -shift*(mq3-mq2); } | ||||
|         } | ||||
|  | ||||
|         std::vector<Coeff_t> diag(Ls,1.0); | ||||
|         std::vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1] = mq1 + shiftp; | ||||
|         std::vector<Coeff_t> lower(Ls,-1.0); lower[0]    = mq1 + shiftm; | ||||
|  | ||||
|         #if(0) | ||||
|             std::cout << GridLogMessage << "DomainWallEOFAFermion::M5Ddag(FF&,FF&):" << std::endl; | ||||
|             for(int i=0; i<diag.size(); ++i){ | ||||
|                 std::cout << GridLogMessage << "diag[" << i << "] =" << diag[i] << std::endl; | ||||
|             } | ||||
|             for(int i=0; i<upper.size(); ++i){ | ||||
|                 std::cout << GridLogMessage << "upper[" << i << "] =" << upper[i] << std::endl; | ||||
|             } | ||||
|             for(int i=0; i<lower.size(); ++i){ | ||||
|                 std::cout << GridLogMessage << "lower[" << i << "] =" << lower[i] << std::endl; | ||||
|             } | ||||
|         #endif | ||||
|  | ||||
|         this->M5Ddag(psi, chi, chi, lower, diag, upper); | ||||
|     } | ||||
|  | ||||
|     // half checkerboard operations | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::Mooee(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         std::vector<Coeff_t> diag = this->bee; | ||||
|         std::vector<Coeff_t> upper(Ls); | ||||
|         std::vector<Coeff_t> lower(Ls); | ||||
|  | ||||
|         for(int s=0; s<Ls; s++){ | ||||
|           upper[s] = -this->cee[s]; | ||||
|           lower[s] = -this->cee[s]; | ||||
|         } | ||||
|         upper[Ls-1] = this->dm; | ||||
|         lower[0]    = this->dp; | ||||
|  | ||||
|         this->M5D(psi, psi, chi, lower, diag, upper); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeDag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         std::vector<Coeff_t> diag = this->bee; | ||||
|         std::vector<Coeff_t> upper(Ls); | ||||
|         std::vector<Coeff_t> lower(Ls); | ||||
|  | ||||
|         for(int s=0; s<Ls; s++){ | ||||
|           upper[s] = -this->cee[s]; | ||||
|           lower[s] = -this->cee[s]; | ||||
|         } | ||||
|         upper[Ls-1] = this->dp; | ||||
|         lower[0]    = this->dm; | ||||
|  | ||||
|         this->M5Ddag(psi, psi, chi, lower, diag, upper); | ||||
|     } | ||||
|  | ||||
|     /****************************************************************************************/ | ||||
|  | ||||
|     //Zolo | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::SetCoefficientsInternal(RealD zolo_hi, std::vector<Coeff_t>& gamma, RealD b, RealD c) | ||||
|     { | ||||
|         int   Ls    = this->Ls; | ||||
|         int   pm    = this->pm; | ||||
|         RealD mq1   = this->mq1; | ||||
|         RealD mq2   = this->mq2; | ||||
|         RealD mq3   = this->mq3; | ||||
|         RealD shift = this->shift; | ||||
|  | ||||
|         //////////////////////////////////////////////////////// | ||||
|         // Constants for the preconditioned matrix Cayley form | ||||
|         //////////////////////////////////////////////////////// | ||||
|         this->bs.resize(Ls); | ||||
|         this->cs.resize(Ls); | ||||
|         this->aee.resize(Ls); | ||||
|         this->aeo.resize(Ls); | ||||
|         this->bee.resize(Ls); | ||||
|         this->beo.resize(Ls); | ||||
|         this->cee.resize(Ls); | ||||
|         this->ceo.resize(Ls); | ||||
|  | ||||
|         for(int i=0; i<Ls; ++i){ | ||||
|           this->bee[i] = 4.0 - this->M5 + 1.0; | ||||
|           this->cee[i] = 1.0; | ||||
|         } | ||||
|  | ||||
|         for(int i=0; i<Ls; ++i){ | ||||
|           this->aee[i] = this->cee[i]; | ||||
|           this->bs[i] = this->beo[i] = 1.0; | ||||
|           this->cs[i] = this->ceo[i] = 0.0; | ||||
|         } | ||||
|  | ||||
|         ////////////////////////////////////////// | ||||
|         // EOFA shift terms | ||||
|         ////////////////////////////////////////// | ||||
|         if(pm == 1){ | ||||
|           this->dp = mq1*this->cee[0] + shift*(mq3-mq2); | ||||
|           this->dm = mq1*this->cee[Ls-1]; | ||||
|         } else if(this->pm == -1) { | ||||
|           this->dp = mq1*this->cee[0]; | ||||
|           this->dm = mq1*this->cee[Ls-1] - shift*(mq3-mq2); | ||||
|         } else { | ||||
|           this->dp = mq1*this->cee[0]; | ||||
|           this->dm = mq1*this->cee[Ls-1]; | ||||
|         } | ||||
|  | ||||
|         ////////////////////////////////////////// | ||||
|         // LDU decomposition of eeoo | ||||
|         ////////////////////////////////////////// | ||||
|         this->dee.resize(Ls+1); | ||||
|         this->lee.resize(Ls); | ||||
|         this->leem.resize(Ls); | ||||
|         this->uee.resize(Ls); | ||||
|         this->ueem.resize(Ls); | ||||
|  | ||||
|         for(int i=0; i<Ls; ++i){ | ||||
|  | ||||
|           if(i < Ls-1){ | ||||
|  | ||||
|             this->lee[i] = -this->cee[i+1]/this->bee[i]; // sub-diag entry on the ith column | ||||
|  | ||||
|             this->leem[i] = this->dm/this->bee[i]; | ||||
|             for(int j=0; j<i; j++){ this->leem[i] *= this->aee[j]/this->bee[j]; } | ||||
|  | ||||
|             this->dee[i] = this->bee[i]; | ||||
|  | ||||
|             this->uee[i] = -this->aee[i]/this->bee[i];   // up-diag entry on the ith row | ||||
|  | ||||
|             this->ueem[i] = this->dp / this->bee[0]; | ||||
|             for(int j=1; j<=i; j++){ this->ueem[i] *= this->cee[j]/this->bee[j]; } | ||||
|  | ||||
|           } else { | ||||
|  | ||||
|             this->lee[i]  = 0.0; | ||||
|             this->leem[i] = 0.0; | ||||
|             this->uee[i]  = 0.0; | ||||
|             this->ueem[i] = 0.0; | ||||
|  | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         { | ||||
|           Coeff_t delta_d = 1.0 / this->bee[0]; | ||||
|           for(int j=1; j<Ls-1; j++){ delta_d *= this->cee[j] / this->bee[j]; } | ||||
|           this->dee[Ls-1] = this->bee[Ls-1] + this->cee[0] * this->dm * delta_d; | ||||
|           this->dee[Ls] = this->bee[Ls-1] + this->cee[Ls-1] * this->dp * delta_d; | ||||
|         } | ||||
|  | ||||
|         int inv = 1; | ||||
|         this->MooeeInternalCompute(0, inv, this->MatpInv, this->MatmInv); | ||||
|         this->MooeeInternalCompute(1, inv, this->MatpInvDag, this->MatmInvDag); | ||||
|     } | ||||
|  | ||||
|     // Recompute Cayley-form coefficients for different shift | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::RefreshShiftCoefficients(RealD new_shift) | ||||
|     { | ||||
|         this->shift = new_shift; | ||||
|         Approx::zolotarev_data *zdata = Approx::higham(1.0, this->Ls); | ||||
|         this->SetCoefficientsTanh(zdata, 1.0, 0.0); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInternalCompute(int dag, int inv, | ||||
|         Vector<iSinglet<Simd> >& Matp, Vector<iSinglet<Simd> >& Matm) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         GridBase* grid = this->FermionRedBlackGrid(); | ||||
|         int LLs = grid->_rdimensions[0]; | ||||
|  | ||||
|         if(LLs == Ls){ return; } // Not vectorised in 5th direction | ||||
|  | ||||
|         Eigen::MatrixXcd Pplus  = Eigen::MatrixXcd::Zero(Ls,Ls); | ||||
|         Eigen::MatrixXcd Pminus = Eigen::MatrixXcd::Zero(Ls,Ls); | ||||
|  | ||||
|         for(int s=0; s<Ls; s++){ | ||||
|             Pplus(s,s)  = this->bee[s]; | ||||
|             Pminus(s,s) = this->bee[s]; | ||||
|         } | ||||
|  | ||||
|         for(int s=0; s<Ls-1; s++){ | ||||
|             Pminus(s,s+1) = -this->cee[s]; | ||||
|         } | ||||
|  | ||||
|         for(int s=0; s<Ls-1; s++){ | ||||
|             Pplus(s+1,s) = -this->cee[s+1]; | ||||
|         } | ||||
|  | ||||
|         Pplus (0,Ls-1) = this->dp; | ||||
|         Pminus(Ls-1,0) = this->dm; | ||||
|  | ||||
|         Eigen::MatrixXcd PplusMat ; | ||||
|         Eigen::MatrixXcd PminusMat; | ||||
|  | ||||
|         #if(0) | ||||
|             std::cout << GridLogMessage << "Pplus:" << std::endl; | ||||
|             for(int s=0; s<Ls; ++s){ | ||||
|                 for(int ss=0; ss<Ls; ++ss){ | ||||
|                     std::cout << Pplus(s,ss) << "\t"; | ||||
|                 } | ||||
|                 std::cout << std::endl; | ||||
|             } | ||||
|             std::cout << GridLogMessage << "Pminus:" << std::endl; | ||||
|             for(int s=0; s<Ls; ++s){ | ||||
|                 for(int ss=0; ss<Ls; ++ss){ | ||||
|                     std::cout << Pminus(s,ss) << "\t"; | ||||
|                 } | ||||
|                 std::cout << std::endl; | ||||
|             } | ||||
|         #endif | ||||
|  | ||||
|         if(inv) { | ||||
|             PplusMat  = Pplus.inverse(); | ||||
|             PminusMat = Pminus.inverse(); | ||||
|         } else { | ||||
|             PplusMat  = Pplus; | ||||
|             PminusMat = Pminus; | ||||
|         } | ||||
|  | ||||
|         if(dag){ | ||||
|             PplusMat.adjointInPlace(); | ||||
|             PminusMat.adjointInPlace(); | ||||
|         } | ||||
|  | ||||
|         typedef typename SiteHalfSpinor::scalar_type scalar_type; | ||||
|         const int Nsimd = Simd::Nsimd(); | ||||
|         Matp.resize(Ls*LLs); | ||||
|         Matm.resize(Ls*LLs); | ||||
|  | ||||
|         for(int s2=0; s2<Ls; s2++){ | ||||
|         for(int s1=0; s1<LLs; s1++){ | ||||
|             int istride = LLs; | ||||
|             int ostride = 1; | ||||
|             Simd Vp; | ||||
|             Simd Vm; | ||||
|             scalar_type *sp = (scalar_type*) &Vp; | ||||
|             scalar_type *sm = (scalar_type*) &Vm; | ||||
|             for(int l=0; l<Nsimd; l++){ | ||||
|                 if(switcheroo<Coeff_t>::iscomplex()) { | ||||
|                     sp[l] = PplusMat (l*istride+s1*ostride,s2); | ||||
|                     sm[l] = PminusMat(l*istride+s1*ostride,s2); | ||||
|                 } else { | ||||
|                     // if real | ||||
|                     scalar_type tmp; | ||||
|                     tmp = PplusMat (l*istride+s1*ostride,s2); | ||||
|                     sp[l] = scalar_type(tmp.real(),tmp.real()); | ||||
|                     tmp = PminusMat(l*istride+s1*ostride,s2); | ||||
|                     sm[l] = scalar_type(tmp.real(),tmp.real()); | ||||
|                 } | ||||
|             } | ||||
|             Matp[LLs*s2+s1] = Vp; | ||||
|             Matm[LLs*s2+s1] = Vm; | ||||
|         }} | ||||
|     } | ||||
|  | ||||
|     FermOpTemplateInstantiate(DomainWallEOFAFermion); | ||||
|     GparityFermOpTemplateInstantiate(DomainWallEOFAFermion); | ||||
|  | ||||
| }} | ||||
							
								
								
									
										115
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermion.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermion.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/DomainWallEOFAFermion.h | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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_QCD_DOMAIN_WALL_EOFA_FERMION_H | ||||
| #define  GRID_QCD_DOMAIN_WALL_EOFA_FERMION_H | ||||
|  | ||||
| #include <Grid/qcd/action/fermion/AbstractEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|   template<class Impl> | ||||
|   class DomainWallEOFAFermion : public AbstractEOFAFermion<Impl> | ||||
|   { | ||||
|     public: | ||||
|       INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|     public: | ||||
|       // Modified (0,Ls-1) and (Ls-1,0) elements of Mooee | ||||
|       // for red-black preconditioned Shamir EOFA | ||||
|       Coeff_t dm; | ||||
|       Coeff_t dp; | ||||
|  | ||||
|       virtual void Instantiatable(void) {}; | ||||
|  | ||||
|       // EOFA-specific operations | ||||
|       virtual void  Omega      (const FermionField& in, FermionField& out, int sign, int dag); | ||||
|       virtual void  Dtilde     (const FermionField& in, FermionField& out); | ||||
|       virtual void  DtildeInv  (const FermionField& in, FermionField& out); | ||||
|  | ||||
|       // override multiply | ||||
|       virtual RealD M          (const FermionField& in, FermionField& out); | ||||
|       virtual RealD Mdag       (const FermionField& in, FermionField& out); | ||||
|  | ||||
|       // half checkerboard operations | ||||
|       virtual void  Mooee      (const FermionField& in, FermionField& out); | ||||
|       virtual void  MooeeDag   (const FermionField& in, FermionField& out); | ||||
|       virtual void  MooeeInv   (const FermionField& in, FermionField& out); | ||||
|       virtual void  MooeeInvDag(const FermionField& in, FermionField& out); | ||||
|  | ||||
|       virtual void   M5D       (const FermionField& psi, FermionField& chi); | ||||
|       virtual void   M5Ddag    (const FermionField& psi, FermionField& chi); | ||||
|  | ||||
|       ///////////////////////////////////////////////////// | ||||
|       // Instantiate different versions depending on Impl | ||||
|       ///////////////////////////////////////////////////// | ||||
|       void M5D(const FermionField& psi, const FermionField& phi, FermionField& chi, | ||||
|         std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper); | ||||
|  | ||||
|       void M5Ddag(const FermionField& psi, const FermionField& phi, FermionField& chi, | ||||
|         std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper); | ||||
|  | ||||
|       void MooeeInternal(const FermionField& in, FermionField& out, int dag, int inv); | ||||
|  | ||||
|       void MooeeInternalCompute(int dag, int inv, Vector<iSinglet<Simd>>& Matp, Vector<iSinglet<Simd>>& Matm); | ||||
|  | ||||
|       void MooeeInternalAsm(const FermionField& in, FermionField& out, int LLs, int site, | ||||
|         Vector<iSinglet<Simd>>& Matp, Vector<iSinglet<Simd>>& Matm); | ||||
|  | ||||
|       void MooeeInternalZAsm(const FermionField& in, FermionField& out, int LLs, int site, | ||||
|         Vector<iSinglet<Simd>>& Matp, Vector<iSinglet<Simd>>& Matm); | ||||
|  | ||||
|       virtual void RefreshShiftCoefficients(RealD new_shift); | ||||
|  | ||||
|       // Constructors | ||||
|       DomainWallEOFAFermion(GaugeField& _Umu, GridCartesian& FiveDimGrid, GridRedBlackCartesian& FiveDimRedBlackGrid, | ||||
|         GridCartesian& FourDimGrid, GridRedBlackCartesian& FourDimRedBlackGrid, | ||||
|         RealD _mq1, RealD _mq2, RealD _mq3, RealD _shift, int pm, | ||||
|         RealD _M5, const ImplParams& p=ImplParams()); | ||||
|  | ||||
|     protected: | ||||
|       void SetCoefficientsInternal(RealD zolo_hi, std::vector<Coeff_t>& gamma, RealD b, RealD c); | ||||
|   }; | ||||
| }} | ||||
|  | ||||
| #define INSTANTIATE_DPERP_DWF_EOFA(A)\ | ||||
| template void DomainWallEOFAFermion<A>::M5D(const FermionField& psi, const FermionField& phi, FermionField& chi, \ | ||||
|   std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper); \ | ||||
| template void DomainWallEOFAFermion<A>::M5Ddag(const FermionField& psi, const FermionField& phi, FermionField& chi, \ | ||||
|   std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper); \ | ||||
| template void DomainWallEOFAFermion<A>::MooeeInv(const FermionField& psi, FermionField& chi); \ | ||||
| template void DomainWallEOFAFermion<A>::MooeeInvDag(const FermionField& psi, FermionField& chi); | ||||
|  | ||||
| #undef  DOMAIN_WALL_EOFA_DPERP_DENSE | ||||
| #define DOMAIN_WALL_EOFA_DPERP_CACHE | ||||
| #undef  DOMAIN_WALL_EOFA_DPERP_LINALG | ||||
| #define DOMAIN_WALL_EOFA_DPERP_VEC | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										248
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermioncache.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermioncache.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,248 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/DomainWallEOFAFermioncache.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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/DomainWallEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|     // FIXME -- make a version of these routines with site loop outermost for cache reuse. | ||||
|  | ||||
|     // Pminus fowards | ||||
|     // Pplus  backwards.. | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::M5D(const FermionField& psi, const FermionField& phi, | ||||
|         FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|         GridBase* grid = psi._grid; | ||||
|  | ||||
|         assert(phi.checkerboard == psi.checkerboard); | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|         // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|         this->M5Dcalls++; | ||||
|         this->M5Dtime -= usecond(); | ||||
|  | ||||
|         parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ // adds Ls | ||||
|             for(int s=0; s<Ls; s++){ | ||||
|                 auto tmp = psi._odata[0]; | ||||
|                 if(s==0) { | ||||
|                     spProj5m(tmp, psi._odata[ss+s+1]); | ||||
|                     chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|                     spProj5p(tmp, psi._odata[ss+Ls-1]); | ||||
|                     chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|                 } else if(s==(Ls-1)) { | ||||
|                     spProj5m(tmp, psi._odata[ss+0]); | ||||
|                     chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|                     spProj5p(tmp, psi._odata[ss+s-1]); | ||||
|                     chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|                 } else { | ||||
|                     spProj5m(tmp, psi._odata[ss+s+1]); | ||||
|                     chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|                     spProj5p(tmp, psi._odata[ss+s-1]); | ||||
|                     chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this->M5Dtime += usecond(); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::M5Ddag(const FermionField& psi, const FermionField& phi, | ||||
|         FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|         GridBase* grid = psi._grid; | ||||
|         assert(phi.checkerboard == psi.checkerboard); | ||||
|         chi.checkerboard=psi.checkerboard; | ||||
|  | ||||
|         // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|         this->M5Dcalls++; | ||||
|         this->M5Dtime -= usecond(); | ||||
|  | ||||
|         parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ // adds Ls | ||||
|             auto tmp = psi._odata[0]; | ||||
|             for(int s=0; s<Ls; s++){ | ||||
|                 if(s==0) { | ||||
|                     spProj5p(tmp, psi._odata[ss+s+1]); | ||||
|                     chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|                     spProj5m(tmp, psi._odata[ss+Ls-1]); | ||||
|                     chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|                 } else if(s==(Ls-1)) { | ||||
|                     spProj5p(tmp, psi._odata[ss+0]); | ||||
|                     chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|                     spProj5m(tmp, psi._odata[ss+s-1]); | ||||
|                     chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|                 } else { | ||||
|                     spProj5p(tmp, psi._odata[ss+s+1]); | ||||
|                     chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|                     spProj5m(tmp, psi._odata[ss+s-1]); | ||||
|                     chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this->M5Dtime += usecond(); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInv(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         GridBase* grid = psi._grid; | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|         this->MooeeInvCalls++; | ||||
|         this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|         parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ // adds Ls | ||||
|  | ||||
|             auto tmp1 = psi._odata[0]; | ||||
|             auto tmp2 = psi._odata[0]; | ||||
|  | ||||
|             // flops = 12*2*Ls + 12*2*Ls + 3*12*Ls + 12*2*Ls  = 12*Ls * (9) = 108*Ls flops | ||||
|             // Apply (L^{\prime})^{-1} | ||||
|             chi[ss] = psi[ss]; // chi[0]=psi[0] | ||||
|             for(int s=1; s<Ls; s++){ | ||||
|                 spProj5p(tmp1, chi[ss+s-1]); | ||||
|                 chi[ss+s] = psi[ss+s] - this->lee[s-1]*tmp1; | ||||
|             } | ||||
|  | ||||
|             // L_m^{-1} | ||||
|             for(int s=0; s<Ls-1; s++){ // Chi[ee] = 1 - sum[s<Ls-1] -leem[s]P_- chi | ||||
|                 spProj5m(tmp1, chi[ss+s]); | ||||
|                 chi[ss+Ls-1] = chi[ss+Ls-1] - this->leem[s]*tmp1; | ||||
|             } | ||||
|  | ||||
|             // U_m^{-1} D^{-1} | ||||
|             for(int s=0; s<Ls-1; s++){ // Chi[s] + 1/d chi[s] | ||||
|                 spProj5p(tmp1, chi[ss+Ls-1]); | ||||
|                 chi[ss+s] = (1.0/this->dee[s])*chi[ss+s] - (this->ueem[s]/this->dee[Ls])*tmp1; | ||||
|             } | ||||
|             spProj5m(tmp2, chi[ss+Ls-1]); | ||||
|             chi[ss+Ls-1] = (1.0/this->dee[Ls])*tmp1 + (1.0/this->dee[Ls-1])*tmp2; | ||||
|  | ||||
|             // Apply U^{-1} | ||||
|             for(int s=Ls-2; s>=0; s--){ | ||||
|                 spProj5m(tmp1, chi[ss+s+1]); | ||||
|                 chi[ss+s] = chi[ss+s] - this->uee[s]*tmp1; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this->MooeeInvTime += usecond(); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         GridBase* grid = psi._grid; | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         assert(psi.checkerboard == psi.checkerboard); | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|         std::vector<Coeff_t> ueec(Ls); | ||||
|         std::vector<Coeff_t> deec(Ls+1); | ||||
|         std::vector<Coeff_t> leec(Ls); | ||||
|         std::vector<Coeff_t> ueemc(Ls); | ||||
|         std::vector<Coeff_t> leemc(Ls); | ||||
|  | ||||
|         for(int s=0; s<ueec.size(); s++){ | ||||
|             ueec[s]  = conjugate(this->uee[s]); | ||||
|             deec[s]  = conjugate(this->dee[s]); | ||||
|             leec[s]  = conjugate(this->lee[s]); | ||||
|             ueemc[s] = conjugate(this->ueem[s]); | ||||
|             leemc[s] = conjugate(this->leem[s]); | ||||
|         } | ||||
|         deec[Ls] = conjugate(this->dee[Ls]); | ||||
|  | ||||
|         this->MooeeInvCalls++; | ||||
|         this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|         parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ // adds Ls | ||||
|  | ||||
|             auto tmp1 = psi._odata[0]; | ||||
|             auto tmp2 = psi._odata[0]; | ||||
|  | ||||
|             // Apply (U^{\prime})^{-dagger} | ||||
|             chi[ss] = psi[ss]; | ||||
|             for(int s=1; s<Ls; s++){ | ||||
|                 spProj5m(tmp1, chi[ss+s-1]); | ||||
|                 chi[ss+s] = psi[ss+s] - ueec[s-1]*tmp1; | ||||
|             } | ||||
|  | ||||
|             // U_m^{-\dagger} | ||||
|             for(int s=0; s<Ls-1; s++){ | ||||
|                 spProj5p(tmp1, chi[ss+s]); | ||||
|                 chi[ss+Ls-1] = chi[ss+Ls-1] - ueemc[s]*tmp1; | ||||
|             } | ||||
|  | ||||
|             // L_m^{-\dagger} D^{-dagger} | ||||
|             for(int s=0; s<Ls-1; s++){ | ||||
|                 spProj5m(tmp1, chi[ss+Ls-1]); | ||||
|                 chi[ss+s] = (1.0/deec[s])*chi[ss+s] - (leemc[s]/deec[Ls-1])*tmp1; | ||||
|             } | ||||
|             spProj5p(tmp2, chi[ss+Ls-1]); | ||||
|             chi[ss+Ls-1] = (1.0/deec[Ls-1])*tmp1 + (1.0/deec[Ls])*tmp2; | ||||
|  | ||||
|             // Apply L^{-dagger} | ||||
|             for(int s=Ls-2; s>=0; s--){ | ||||
|                 spProj5p(tmp1, chi[ss+s+1]); | ||||
|                 chi[ss+s] = chi[ss+s] - leec[s]*tmp1; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this->MooeeInvTime += usecond(); | ||||
|     } | ||||
|  | ||||
|     #ifdef DOMAIN_WALL_EOFA_DPERP_CACHE | ||||
|  | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplD); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplD); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplD); | ||||
|  | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplDF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplDF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplDF); | ||||
|  | ||||
|     #endif | ||||
|  | ||||
| }} | ||||
							
								
								
									
										159
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermiondense.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermiondense.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/DomainWallEOFAFermiondense.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid_Eigen_Dense.h> | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/DomainWallEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|     /* | ||||
|     * Dense matrix versions of routines | ||||
|     */ | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         this->MooeeInternal(psi, chi, DaggerYes, InverseYes); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInv(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         this->MooeeInternal(psi, chi, DaggerNo, InverseYes); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv) | ||||
|     { | ||||
|         int Ls = this->Ls; | ||||
|         int LLs = psi._grid->_rdimensions[0]; | ||||
|         int vol = psi._grid->oSites()/LLs; | ||||
|  | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|         assert(Ls==LLs); | ||||
|  | ||||
|         Eigen::MatrixXd Pplus  = Eigen::MatrixXd::Zero(Ls,Ls); | ||||
|         Eigen::MatrixXd Pminus = Eigen::MatrixXd::Zero(Ls,Ls); | ||||
|  | ||||
|         for(int s=0;s<Ls;s++){ | ||||
|             Pplus(s,s)  = this->bee[s]; | ||||
|             Pminus(s,s) = this->bee[s]; | ||||
|         } | ||||
|  | ||||
|         for(int s=0; s<Ls-1; s++){ | ||||
|             Pminus(s,s+1) = -this->cee[s]; | ||||
|         } | ||||
|  | ||||
|         for(int s=0; s<Ls-1; s++){ | ||||
|             Pplus(s+1,s) = -this->cee[s+1]; | ||||
|         } | ||||
|  | ||||
|         Pplus (0,Ls-1) = this->dp; | ||||
|         Pminus(Ls-1,0) = this->dm; | ||||
|  | ||||
|         Eigen::MatrixXd PplusMat ; | ||||
|         Eigen::MatrixXd PminusMat; | ||||
|  | ||||
|         if(inv) { | ||||
|             PplusMat  = Pplus.inverse(); | ||||
|             PminusMat = Pminus.inverse(); | ||||
|         } else { | ||||
|             PplusMat  = Pplus; | ||||
|             PminusMat = Pminus; | ||||
|         } | ||||
|  | ||||
|         if(dag){ | ||||
|             PplusMat.adjointInPlace(); | ||||
|             PminusMat.adjointInPlace(); | ||||
|         } | ||||
|  | ||||
|         // For the non-vectorised s-direction this is simple | ||||
|  | ||||
|         for(auto site=0; site<vol; site++){ | ||||
|  | ||||
|             SiteSpinor     SiteChi; | ||||
|             SiteHalfSpinor SitePplus; | ||||
|             SiteHalfSpinor SitePminus; | ||||
|  | ||||
|             for(int s1=0; s1<Ls; s1++){ | ||||
|                 SiteChi = zero; | ||||
|                 for(int s2=0; s2<Ls; s2++){ | ||||
|                     int lex2 = s2 + Ls*site; | ||||
|                     if(PplusMat(s1,s2) != 0.0){ | ||||
|                         spProj5p(SitePplus,psi[lex2]); | ||||
|                         accumRecon5p(SiteChi, PplusMat(s1,s2)*SitePplus); | ||||
|                     } | ||||
|                     if(PminusMat(s1,s2) != 0.0){ | ||||
|                         spProj5m(SitePminus, psi[lex2]); | ||||
|                         accumRecon5m(SiteChi, PminusMat(s1,s2)*SitePminus); | ||||
|                     } | ||||
|                 } | ||||
|                 chi[s1+Ls*site] = SiteChi*0.5; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #ifdef DOMAIN_WALL_EOFA_DPERP_DENSE | ||||
|  | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplD); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplD); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplD); | ||||
|  | ||||
|         template void DomainWallEOFAFermion<GparityWilsonImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<GparityWilsonImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<WilsonImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<WilsonImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<ZWilsonImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<ZWilsonImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|  | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplDF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplDF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplDF); | ||||
|  | ||||
|         template void DomainWallEOFAFermion<GparityWilsonImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<GparityWilsonImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<WilsonImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<WilsonImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<ZWilsonImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<ZWilsonImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|  | ||||
|     #endif | ||||
|  | ||||
| }} | ||||
							
								
								
									
										168
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermionssp.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermionssp.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/DomainWallEOFAFermionssp.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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/DomainWallEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|     // FIXME -- make a version of these routines with site loop outermost for cache reuse. | ||||
|     // Pminus fowards | ||||
|     // Pplus  backwards | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::M5D(const FermionField& psi, const FermionField& phi, | ||||
|         FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|     { | ||||
|         Coeff_t one(1.0); | ||||
|         int Ls = this->Ls; | ||||
|         for(int s=0; s<Ls; s++){ | ||||
|             if(s==0) { | ||||
|               axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|               axpby_ssp_pplus (chi, one, chi, lower[s], psi, s, Ls-1); | ||||
|             } else if (s==(Ls-1)) { | ||||
|               axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, 0); | ||||
|               axpby_ssp_pplus (chi, one, chi, lower[s], psi, s, s-1); | ||||
|             } else { | ||||
|               axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|               axpby_ssp_pplus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::M5Ddag(const FermionField& psi, const FermionField& phi, | ||||
|         FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|     { | ||||
|         Coeff_t one(1.0); | ||||
|         int Ls = this->Ls; | ||||
|         for(int s=0; s<Ls; s++){ | ||||
|             if(s==0) { | ||||
|               axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|               axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, Ls-1); | ||||
|             } else if (s==(Ls-1)) { | ||||
|               axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, 0); | ||||
|               axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|             } else { | ||||
|               axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|               axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInv(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         Coeff_t one(1.0); | ||||
|         Coeff_t czero(0.0); | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         FermionField tmp(psi._grid); | ||||
|  | ||||
|         // Apply (L^{\prime})^{-1} | ||||
|         axpby_ssp(chi, one, psi, czero, psi, 0, 0);      // chi[0]=psi[0] | ||||
|         for(int s=1; s<Ls; s++){ | ||||
|             axpby_ssp_pplus(chi, one, psi, -this->lee[s-1], chi, s, s-1);// recursion Psi[s] -lee P_+ chi[s-1] | ||||
|         } | ||||
|  | ||||
|         // L_m^{-1} | ||||
|         for(int s=0; s<Ls-1; s++){ // Chi[ee] = 1 - sum[s<Ls-1] -leem[s]P_- chi | ||||
|             axpby_ssp_pminus(chi, one, chi, -this->leem[s], chi, Ls-1, s); | ||||
|         } | ||||
|  | ||||
|         // U_m^{-1} D^{-1} | ||||
|         for(int s=0; s<Ls-1; s++){ | ||||
|             axpby_ssp_pplus(chi, one/this->dee[s], chi, -this->ueem[s]/this->dee[Ls], chi, s, Ls-1); | ||||
|         } | ||||
|         axpby_ssp_pminus(tmp, czero, chi, one/this->dee[Ls-1], chi, Ls-1, Ls-1); | ||||
|         axpby_ssp_pplus(chi, one, tmp, one/this->dee[Ls], chi, Ls-1, Ls-1); | ||||
|  | ||||
|         // Apply U^{-1} | ||||
|         for(int s=Ls-2; s>=0; s--){ | ||||
|             axpby_ssp_pminus(chi, one, chi, -this->uee[s], chi, s, s+1);  // chi[Ls] | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         Coeff_t one(1.0); | ||||
|         Coeff_t czero(0.0); | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|         int Ls = this->Ls; | ||||
|  | ||||
|         FermionField tmp(psi._grid); | ||||
|  | ||||
|         // Apply (U^{\prime})^{-dagger} | ||||
|         axpby_ssp(chi, one, psi, czero, psi, 0, 0);      // chi[0]=psi[0] | ||||
|         for(int s=1; s<Ls; s++){ | ||||
|             axpby_ssp_pminus(chi, one, psi, -conjugate(this->uee[s-1]), chi, s, s-1); | ||||
|         } | ||||
|  | ||||
|         // U_m^{-\dagger} | ||||
|         for(int s=0; s<Ls-1; s++){ | ||||
|             axpby_ssp_pplus(chi, one, chi, -conjugate(this->ueem[s]), chi, Ls-1, s); | ||||
|         } | ||||
|  | ||||
|         // L_m^{-\dagger} D^{-dagger} | ||||
|         for(int s=0; s<Ls-1; s++){ | ||||
|             axpby_ssp_pminus(chi, one/conjugate(this->dee[s]), chi, -conjugate(this->leem[s]/this->dee[Ls-1]), chi, s, Ls-1); | ||||
|         } | ||||
|         axpby_ssp_pminus(tmp, czero, chi, one/conjugate(this->dee[Ls-1]), chi, Ls-1, Ls-1); | ||||
|         axpby_ssp_pplus(chi, one, tmp, one/conjugate(this->dee[Ls]), chi, Ls-1, Ls-1); | ||||
|  | ||||
|         // Apply L^{-dagger} | ||||
|         for(int s=Ls-2; s>=0; s--){ | ||||
|             axpby_ssp_pplus(chi, one, chi, -conjugate(this->lee[s]), chi, s, s+1);  // chi[Ls] | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #ifdef DOMAIN_WALL_EOFA_DPERP_LINALG | ||||
|  | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplD); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplD); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplD); | ||||
|  | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(WilsonImplDF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(GparityWilsonImplDF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZWilsonImplDF); | ||||
|  | ||||
|     #endif | ||||
|  | ||||
| }} | ||||
							
								
								
									
										605
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermionvec.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										605
									
								
								lib/qcd/action/fermion/DomainWallEOFAFermionvec.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,605 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/DomainWallEOFAFermionvec.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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/DomainWallEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|     /* | ||||
|     * Dense matrix versions of routines | ||||
|     */ | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         this->MooeeInternal(psi, chi, DaggerYes, InverseYes); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInv(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|         this->MooeeInternal(psi, chi, DaggerNo, InverseYes); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::M5D(const FermionField& psi, const FermionField& phi, | ||||
|         FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|     { | ||||
|         GridBase* grid = psi._grid; | ||||
|         int Ls  = this->Ls; | ||||
|         int LLs = grid->_rdimensions[0]; | ||||
|         const int nsimd = Simd::Nsimd(); | ||||
|  | ||||
|         Vector<iSinglet<Simd> > u(LLs); | ||||
|         Vector<iSinglet<Simd> > l(LLs); | ||||
|         Vector<iSinglet<Simd> > d(LLs); | ||||
|  | ||||
|         assert(Ls/LLs == nsimd); | ||||
|         assert(phi.checkerboard == psi.checkerboard); | ||||
|  | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|         // just directly address via type pun | ||||
|         typedef typename Simd::scalar_type scalar_type; | ||||
|         scalar_type* u_p = (scalar_type*) &u[0]; | ||||
|         scalar_type* l_p = (scalar_type*) &l[0]; | ||||
|         scalar_type* d_p = (scalar_type*) &d[0]; | ||||
|  | ||||
|         for(int o=0;o<LLs;o++){ // outer | ||||
|         for(int i=0;i<nsimd;i++){ //inner | ||||
|             int s  = o + i*LLs; | ||||
|             int ss = o*nsimd + i; | ||||
|             u_p[ss] = upper[s]; | ||||
|             l_p[ss] = lower[s]; | ||||
|             d_p[ss] = diag[s]; | ||||
|         }} | ||||
|  | ||||
|         this->M5Dcalls++; | ||||
|         this->M5Dtime -= usecond(); | ||||
|  | ||||
|         assert(Nc == 3); | ||||
|  | ||||
|         parallel_for(int ss=0; ss<grid->oSites(); ss+=LLs){ // adds LLs | ||||
|  | ||||
|             #if 0 | ||||
|  | ||||
|                 alignas(64) SiteHalfSpinor hp; | ||||
|                 alignas(64) SiteHalfSpinor hm; | ||||
|                 alignas(64) SiteSpinor fp; | ||||
|                 alignas(64) SiteSpinor fm; | ||||
|  | ||||
|                 for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|                     int vp = (v+1)%LLs; | ||||
|                     int vm = (v+LLs-1)%LLs; | ||||
|  | ||||
|                     spProj5m(hp, psi[ss+vp]); | ||||
|                     spProj5p(hm, psi[ss+vm]); | ||||
|  | ||||
|                     if (vp <= v){ rotate(hp, hp, 1); } | ||||
|                     if (vm >= v){ rotate(hm, hm, nsimd-1); } | ||||
|  | ||||
|                     hp = 0.5*hp; | ||||
|                     hm = 0.5*hm; | ||||
|  | ||||
|                     spRecon5m(fp, hp); | ||||
|                     spRecon5p(fm, hm); | ||||
|  | ||||
|                     chi[ss+v] = d[v]*phi[ss+v]; | ||||
|                     chi[ss+v] = chi[ss+v] + u[v]*fp; | ||||
|                     chi[ss+v] = chi[ss+v] + l[v]*fm; | ||||
|  | ||||
|                 } | ||||
|  | ||||
|             #else | ||||
|  | ||||
|                 for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|                     vprefetch(psi[ss+v+LLs]); | ||||
|  | ||||
|                     int vp = (v==LLs-1) ? 0     : v+1; | ||||
|                     int vm = (v==0)     ? LLs-1 : v-1; | ||||
|  | ||||
|                     Simd hp_00 = psi[ss+vp]()(2)(0); | ||||
|                     Simd hp_01 = psi[ss+vp]()(2)(1); | ||||
|                     Simd hp_02 = psi[ss+vp]()(2)(2); | ||||
|                     Simd hp_10 = psi[ss+vp]()(3)(0); | ||||
|                     Simd hp_11 = psi[ss+vp]()(3)(1); | ||||
|                     Simd hp_12 = psi[ss+vp]()(3)(2); | ||||
|  | ||||
|                     Simd hm_00 = psi[ss+vm]()(0)(0); | ||||
|                     Simd hm_01 = psi[ss+vm]()(0)(1); | ||||
|                     Simd hm_02 = psi[ss+vm]()(0)(2); | ||||
|                     Simd hm_10 = psi[ss+vm]()(1)(0); | ||||
|                     Simd hm_11 = psi[ss+vm]()(1)(1); | ||||
|                     Simd hm_12 = psi[ss+vm]()(1)(2); | ||||
|  | ||||
|                     if(vp <= v){ | ||||
|                         hp_00.v = Optimization::Rotate::tRotate<2>(hp_00.v); | ||||
|                         hp_01.v = Optimization::Rotate::tRotate<2>(hp_01.v); | ||||
|                         hp_02.v = Optimization::Rotate::tRotate<2>(hp_02.v); | ||||
|                         hp_10.v = Optimization::Rotate::tRotate<2>(hp_10.v); | ||||
|                         hp_11.v = Optimization::Rotate::tRotate<2>(hp_11.v); | ||||
|                         hp_12.v = Optimization::Rotate::tRotate<2>(hp_12.v); | ||||
|                     } | ||||
|  | ||||
|                     if(vm >= v){ | ||||
|                         hm_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_00.v); | ||||
|                         hm_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_01.v); | ||||
|                         hm_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_02.v); | ||||
|                         hm_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_10.v); | ||||
|                         hm_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_11.v); | ||||
|                         hm_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_12.v); | ||||
|                     } | ||||
|  | ||||
|                     // Can force these to real arithmetic and save 2x. | ||||
|                     Simd p_00 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_00); | ||||
|                     Simd p_01 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_01); | ||||
|                     Simd p_02 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_02); | ||||
|                     Simd p_10 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_10); | ||||
|                     Simd p_11 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_11); | ||||
|                     Simd p_12 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_12); | ||||
|                     Simd p_20 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_00); | ||||
|                     Simd p_21 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_01); | ||||
|                     Simd p_22 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_02); | ||||
|                     Simd p_30 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_10); | ||||
|                     Simd p_31 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_11); | ||||
|                     Simd p_32 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_12); | ||||
|  | ||||
|                     vstream(chi[ss+v]()(0)(0), p_00); | ||||
|                     vstream(chi[ss+v]()(0)(1), p_01); | ||||
|                     vstream(chi[ss+v]()(0)(2), p_02); | ||||
|                     vstream(chi[ss+v]()(1)(0), p_10); | ||||
|                     vstream(chi[ss+v]()(1)(1), p_11); | ||||
|                     vstream(chi[ss+v]()(1)(2), p_12); | ||||
|                     vstream(chi[ss+v]()(2)(0), p_20); | ||||
|                     vstream(chi[ss+v]()(2)(1), p_21); | ||||
|                     vstream(chi[ss+v]()(2)(2), p_22); | ||||
|                     vstream(chi[ss+v]()(3)(0), p_30); | ||||
|                     vstream(chi[ss+v]()(3)(1), p_31); | ||||
|                     vstream(chi[ss+v]()(3)(2), p_32); | ||||
|                 } | ||||
|  | ||||
|             #endif | ||||
|         } | ||||
|  | ||||
|         this->M5Dtime += usecond(); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::M5Ddag(const FermionField& psi, const FermionField& phi, | ||||
|         FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|     { | ||||
|         GridBase* grid = psi._grid; | ||||
|         int Ls  = this->Ls; | ||||
|         int LLs = grid->_rdimensions[0]; | ||||
|         int nsimd = Simd::Nsimd(); | ||||
|  | ||||
|         Vector<iSinglet<Simd> > u(LLs); | ||||
|         Vector<iSinglet<Simd> > l(LLs); | ||||
|         Vector<iSinglet<Simd> > d(LLs); | ||||
|  | ||||
|         assert(Ls/LLs == nsimd); | ||||
|         assert(phi.checkerboard == psi.checkerboard); | ||||
|  | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|         // just directly address via type pun | ||||
|         typedef typename Simd::scalar_type scalar_type; | ||||
|         scalar_type* u_p = (scalar_type*) &u[0]; | ||||
|         scalar_type* l_p = (scalar_type*) &l[0]; | ||||
|         scalar_type* d_p = (scalar_type*) &d[0]; | ||||
|  | ||||
|         for(int o=0; o<LLs; o++){ // outer | ||||
|         for(int i=0; i<nsimd; i++){ //inner | ||||
|             int s  = o + i*LLs; | ||||
|             int ss = o*nsimd + i; | ||||
|             u_p[ss] = upper[s]; | ||||
|             l_p[ss] = lower[s]; | ||||
|             d_p[ss] = diag[s]; | ||||
|         }} | ||||
|  | ||||
|         this->M5Dcalls++; | ||||
|         this->M5Dtime -= usecond(); | ||||
|  | ||||
|         parallel_for(int ss=0; ss<grid->oSites(); ss+=LLs){ // adds LLs | ||||
|  | ||||
|         #if 0 | ||||
|  | ||||
|             alignas(64) SiteHalfSpinor hp; | ||||
|             alignas(64) SiteHalfSpinor hm; | ||||
|             alignas(64) SiteSpinor fp; | ||||
|             alignas(64) SiteSpinor fm; | ||||
|  | ||||
|             for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|                 int vp = (v+1)%LLs; | ||||
|                 int vm = (v+LLs-1)%LLs; | ||||
|  | ||||
|                 spProj5p(hp, psi[ss+vp]); | ||||
|                 spProj5m(hm, psi[ss+vm]); | ||||
|  | ||||
|                 if(vp <= v){ rotate(hp, hp, 1); } | ||||
|                 if(vm >= v){ rotate(hm, hm, nsimd-1); } | ||||
|  | ||||
|                 hp = hp*0.5; | ||||
|                 hm = hm*0.5; | ||||
|                 spRecon5p(fp, hp); | ||||
|                 spRecon5m(fm, hm); | ||||
|  | ||||
|                 chi[ss+v] = d[v]*phi[ss+v]+u[v]*fp; | ||||
|                 chi[ss+v] = chi[ss+v]     +l[v]*fm; | ||||
|             } | ||||
|  | ||||
|         #else | ||||
|  | ||||
|             for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|                 vprefetch(psi[ss+v+LLs]); | ||||
|  | ||||
|                 int vp = (v == LLs-1) ? 0     : v+1; | ||||
|                 int vm = (v == 0    ) ? LLs-1 : v-1; | ||||
|  | ||||
|                 Simd hp_00 = psi[ss+vp]()(0)(0); | ||||
|                 Simd hp_01 = psi[ss+vp]()(0)(1); | ||||
|                 Simd hp_02 = psi[ss+vp]()(0)(2); | ||||
|                 Simd hp_10 = psi[ss+vp]()(1)(0); | ||||
|                 Simd hp_11 = psi[ss+vp]()(1)(1); | ||||
|                 Simd hp_12 = psi[ss+vp]()(1)(2); | ||||
|  | ||||
|                 Simd hm_00 = psi[ss+vm]()(2)(0); | ||||
|                 Simd hm_01 = psi[ss+vm]()(2)(1); | ||||
|                 Simd hm_02 = psi[ss+vm]()(2)(2); | ||||
|                 Simd hm_10 = psi[ss+vm]()(3)(0); | ||||
|                 Simd hm_11 = psi[ss+vm]()(3)(1); | ||||
|                 Simd hm_12 = psi[ss+vm]()(3)(2); | ||||
|  | ||||
|                 if (vp <= v){ | ||||
|                     hp_00.v = Optimization::Rotate::tRotate<2>(hp_00.v); | ||||
|                     hp_01.v = Optimization::Rotate::tRotate<2>(hp_01.v); | ||||
|                     hp_02.v = Optimization::Rotate::tRotate<2>(hp_02.v); | ||||
|                     hp_10.v = Optimization::Rotate::tRotate<2>(hp_10.v); | ||||
|                     hp_11.v = Optimization::Rotate::tRotate<2>(hp_11.v); | ||||
|                     hp_12.v = Optimization::Rotate::tRotate<2>(hp_12.v); | ||||
|                 } | ||||
|  | ||||
|                 if(vm >= v){ | ||||
|                     hm_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_00.v); | ||||
|                     hm_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_01.v); | ||||
|                     hm_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_02.v); | ||||
|                     hm_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_10.v); | ||||
|                     hm_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_11.v); | ||||
|                     hm_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_12.v); | ||||
|                 } | ||||
|  | ||||
|                 Simd p_00 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_00); | ||||
|                 Simd p_01 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_01); | ||||
|                 Simd p_02 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_02); | ||||
|                 Simd p_10 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_10); | ||||
|                 Simd p_11 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_11); | ||||
|                 Simd p_12 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_12); | ||||
|                 Simd p_20 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_00); | ||||
|                 Simd p_21 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_01); | ||||
|                 Simd p_22 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_02); | ||||
|                 Simd p_30 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_10); | ||||
|                 Simd p_31 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_11); | ||||
|                 Simd p_32 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_12); | ||||
|  | ||||
|                 vstream(chi[ss+v]()(0)(0), p_00); | ||||
|                 vstream(chi[ss+v]()(0)(1), p_01); | ||||
|                 vstream(chi[ss+v]()(0)(2), p_02); | ||||
|                 vstream(chi[ss+v]()(1)(0), p_10); | ||||
|                 vstream(chi[ss+v]()(1)(1), p_11); | ||||
|                 vstream(chi[ss+v]()(1)(2), p_12); | ||||
|                 vstream(chi[ss+v]()(2)(0), p_20); | ||||
|                 vstream(chi[ss+v]()(2)(1), p_21); | ||||
|                 vstream(chi[ss+v]()(2)(2), p_22); | ||||
|                 vstream(chi[ss+v]()(3)(0), p_30); | ||||
|                 vstream(chi[ss+v]()(3)(1), p_31); | ||||
|                 vstream(chi[ss+v]()(3)(2), p_32); | ||||
|             } | ||||
|         #endif | ||||
|  | ||||
|         } | ||||
|  | ||||
|         this->M5Dtime += usecond(); | ||||
|     } | ||||
|  | ||||
|     #ifdef AVX512 | ||||
|         #include<simd/Intel512common.h> | ||||
|         #include<simd/Intel512avx.h> | ||||
|         #include<simd/Intel512single.h> | ||||
|     #endif | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInternalAsm(const FermionField& psi, FermionField& chi, | ||||
|         int LLs, int site, Vector<iSinglet<Simd> >& Matp, Vector<iSinglet<Simd> >& Matm) | ||||
|     { | ||||
|         #ifndef AVX512 | ||||
|         { | ||||
|             SiteHalfSpinor BcastP; | ||||
|             SiteHalfSpinor BcastM; | ||||
|             SiteHalfSpinor SiteChiP; | ||||
|             SiteHalfSpinor SiteChiM; | ||||
|  | ||||
|             // Ls*Ls * 2 * 12 * vol flops | ||||
|             for(int s1=0; s1<LLs; s1++){ | ||||
|  | ||||
|                 for(int s2=0; s2<LLs; s2++){ | ||||
|                 for(int l=0; l < Simd::Nsimd(); l++){ // simd lane | ||||
|  | ||||
|                     int s = s2 + l*LLs; | ||||
|                     int lex = s2 + LLs*site; | ||||
|  | ||||
|                     if( s2==0 && l==0 ){ | ||||
|                         SiteChiP=zero; | ||||
|                         SiteChiM=zero; | ||||
|                     } | ||||
|  | ||||
|                     for(int sp=0; sp<2;  sp++){ | ||||
|                     for(int co=0; co<Nc; co++){ | ||||
|                         vbroadcast(BcastP()(sp)(co), psi[lex]()(sp)(co), l); | ||||
|                     }} | ||||
|  | ||||
|                     for(int sp=0; sp<2;  sp++){ | ||||
|                     for(int co=0; co<Nc; co++){ | ||||
|                         vbroadcast(BcastM()(sp)(co), psi[lex]()(sp+2)(co), l); | ||||
|                     }} | ||||
|  | ||||
|                     for(int sp=0; sp<2;  sp++){ | ||||
|                     for(int co=0; co<Nc; co++){ | ||||
|                         SiteChiP()(sp)(co) = real_madd(Matp[LLs*s+s1]()()(), BcastP()(sp)(co), SiteChiP()(sp)(co)); // 1100 us. | ||||
|                         SiteChiM()(sp)(co) = real_madd(Matm[LLs*s+s1]()()(), BcastM()(sp)(co), SiteChiM()(sp)(co)); // each found by commenting out | ||||
|                     }} | ||||
|                 }} | ||||
|  | ||||
|                 { | ||||
|                     int lex = s1 + LLs*site; | ||||
|                     for(int sp=0; sp<2;  sp++){ | ||||
|                     for(int co=0; co<Nc; co++){ | ||||
|                         vstream(chi[lex]()(sp)(co),   SiteChiP()(sp)(co)); | ||||
|                         vstream(chi[lex]()(sp+2)(co), SiteChiM()(sp)(co)); | ||||
|                     }} | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         #else | ||||
|         { | ||||
|             // pointers | ||||
|             //  MASK_REGS; | ||||
|             #define Chi_00 %%zmm1 | ||||
|             #define Chi_01 %%zmm2 | ||||
|             #define Chi_02 %%zmm3 | ||||
|             #define Chi_10 %%zmm4 | ||||
|             #define Chi_11 %%zmm5 | ||||
|             #define Chi_12 %%zmm6 | ||||
|             #define Chi_20 %%zmm7 | ||||
|             #define Chi_21 %%zmm8 | ||||
|             #define Chi_22 %%zmm9 | ||||
|             #define Chi_30 %%zmm10 | ||||
|             #define Chi_31 %%zmm11 | ||||
|             #define Chi_32 %%zmm12 | ||||
|  | ||||
|             #define BCAST0  %%zmm13 | ||||
|             #define BCAST1  %%zmm14 | ||||
|             #define BCAST2  %%zmm15 | ||||
|             #define BCAST3  %%zmm16 | ||||
|             #define BCAST4  %%zmm17 | ||||
|             #define BCAST5  %%zmm18 | ||||
|             #define BCAST6  %%zmm19 | ||||
|             #define BCAST7  %%zmm20 | ||||
|             #define BCAST8  %%zmm21 | ||||
|             #define BCAST9  %%zmm22 | ||||
|             #define BCAST10 %%zmm23 | ||||
|             #define BCAST11 %%zmm24 | ||||
|  | ||||
|             int incr = LLs*LLs*sizeof(iSinglet<Simd>); | ||||
|             for(int s1=0; s1<LLs; s1++){ | ||||
|  | ||||
|                 for(int s2=0; s2<LLs; s2++){ | ||||
|  | ||||
|                     int lex = s2 + LLs*site; | ||||
|                     uint64_t a0 = (uint64_t) &Matp[LLs*s2+s1]; // should be cacheable | ||||
|                     uint64_t a1 = (uint64_t) &Matm[LLs*s2+s1]; | ||||
|                     uint64_t a2 = (uint64_t) &psi[lex]; | ||||
|  | ||||
|                     for(int l=0; l<Simd::Nsimd(); l++){ // simd lane | ||||
|                         if((s2+l)==0) { | ||||
|                             asm( | ||||
|                                     VPREFETCH1(0,%2)              VPREFETCH1(0,%1) | ||||
|                                     VPREFETCH1(12,%2)  	          VPREFETCH1(13,%2) | ||||
|                                     VPREFETCH1(14,%2)  	          VPREFETCH1(15,%2) | ||||
|                                     VBCASTCDUP(0,%2,BCAST0) | ||||
|                                     VBCASTCDUP(1,%2,BCAST1) | ||||
|                                     VBCASTCDUP(2,%2,BCAST2) | ||||
|                                     VBCASTCDUP(3,%2,BCAST3) | ||||
|                                     VBCASTCDUP(4,%2,BCAST4)       VMULMEM(0,%0,BCAST0,Chi_00) | ||||
|                                     VBCASTCDUP(5,%2,BCAST5)       VMULMEM(0,%0,BCAST1,Chi_01) | ||||
|                                     VBCASTCDUP(6,%2,BCAST6)       VMULMEM(0,%0,BCAST2,Chi_02) | ||||
|                                     VBCASTCDUP(7,%2,BCAST7)       VMULMEM(0,%0,BCAST3,Chi_10) | ||||
|                                     VBCASTCDUP(8,%2,BCAST8)       VMULMEM(0,%0,BCAST4,Chi_11) | ||||
|                                     VBCASTCDUP(9,%2,BCAST9)       VMULMEM(0,%0,BCAST5,Chi_12) | ||||
|                                     VBCASTCDUP(10,%2,BCAST10)     VMULMEM(0,%1,BCAST6,Chi_20) | ||||
|                                     VBCASTCDUP(11,%2,BCAST11)     VMULMEM(0,%1,BCAST7,Chi_21) | ||||
|                                     VMULMEM(0,%1,BCAST8,Chi_22) | ||||
|                                     VMULMEM(0,%1,BCAST9,Chi_30) | ||||
|                                     VMULMEM(0,%1,BCAST10,Chi_31) | ||||
|                                     VMULMEM(0,%1,BCAST11,Chi_32) | ||||
|                                     : : "r" (a0), "r" (a1), "r" (a2)                            ); | ||||
|                         } else { | ||||
|                             asm( | ||||
|                                     VBCASTCDUP(0,%2,BCAST0)   VMADDMEM(0,%0,BCAST0,Chi_00) | ||||
|                                     VBCASTCDUP(1,%2,BCAST1)   VMADDMEM(0,%0,BCAST1,Chi_01) | ||||
|                                     VBCASTCDUP(2,%2,BCAST2)   VMADDMEM(0,%0,BCAST2,Chi_02) | ||||
|                                     VBCASTCDUP(3,%2,BCAST3)   VMADDMEM(0,%0,BCAST3,Chi_10) | ||||
|                                     VBCASTCDUP(4,%2,BCAST4)   VMADDMEM(0,%0,BCAST4,Chi_11) | ||||
|                                     VBCASTCDUP(5,%2,BCAST5)   VMADDMEM(0,%0,BCAST5,Chi_12) | ||||
|                                     VBCASTCDUP(6,%2,BCAST6)   VMADDMEM(0,%1,BCAST6,Chi_20) | ||||
|                                     VBCASTCDUP(7,%2,BCAST7)   VMADDMEM(0,%1,BCAST7,Chi_21) | ||||
|                                     VBCASTCDUP(8,%2,BCAST8)   VMADDMEM(0,%1,BCAST8,Chi_22) | ||||
|                                     VBCASTCDUP(9,%2,BCAST9)   VMADDMEM(0,%1,BCAST9,Chi_30) | ||||
|                                     VBCASTCDUP(10,%2,BCAST10) VMADDMEM(0,%1,BCAST10,Chi_31) | ||||
|                                     VBCASTCDUP(11,%2,BCAST11) VMADDMEM(0,%1,BCAST11,Chi_32) | ||||
|                                     : : "r" (a0), "r" (a1), "r" (a2)                            ); | ||||
|                         } | ||||
|                         a0 = a0 + incr; | ||||
|                         a1 = a1 + incr; | ||||
|                         a2 = a2 + sizeof(Simd::scalar_type); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 { | ||||
|                   int lexa = s1+LLs*site; | ||||
|                   asm ( | ||||
|                      VSTORE(0,%0,Chi_00) VSTORE(1 ,%0,Chi_01)  VSTORE(2 ,%0,Chi_02) | ||||
|                      VSTORE(3,%0,Chi_10) VSTORE(4 ,%0,Chi_11)  VSTORE(5 ,%0,Chi_12) | ||||
|                      VSTORE(6,%0,Chi_20) VSTORE(7 ,%0,Chi_21)  VSTORE(8 ,%0,Chi_22) | ||||
|                      VSTORE(9,%0,Chi_30) VSTORE(10,%0,Chi_31)  VSTORE(11,%0,Chi_32) | ||||
|                      : : "r" ((uint64_t)&chi[lexa]) : "memory" ); | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #undef Chi_00 | ||||
|         #undef Chi_01 | ||||
|         #undef Chi_02 | ||||
|         #undef Chi_10 | ||||
|         #undef Chi_11 | ||||
|         #undef Chi_12 | ||||
|         #undef Chi_20 | ||||
|         #undef Chi_21 | ||||
|         #undef Chi_22 | ||||
|         #undef Chi_30 | ||||
|         #undef Chi_31 | ||||
|         #undef Chi_32 | ||||
|  | ||||
|         #undef BCAST0 | ||||
|         #undef BCAST1 | ||||
|         #undef BCAST2 | ||||
|         #undef BCAST3 | ||||
|         #undef BCAST4 | ||||
|         #undef BCAST5 | ||||
|         #undef BCAST6 | ||||
|         #undef BCAST7 | ||||
|         #undef BCAST8 | ||||
|         #undef BCAST9 | ||||
|         #undef BCAST10 | ||||
|         #undef BCAST11 | ||||
|         #endif | ||||
|     }; | ||||
|  | ||||
|     // Z-mobius version | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInternalZAsm(const FermionField& psi, FermionField& chi, | ||||
|         int LLs, int site, Vector<iSinglet<Simd> >& Matp, Vector<iSinglet<Simd> >& Matm) | ||||
|     { | ||||
|         std::cout << "Error: zMobius not implemented for EOFA" << std::endl; | ||||
|         exit(-1); | ||||
|     }; | ||||
|  | ||||
|     template<class Impl> | ||||
|     void DomainWallEOFAFermion<Impl>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv) | ||||
|     { | ||||
|         int Ls  = this->Ls; | ||||
|         int LLs = psi._grid->_rdimensions[0]; | ||||
|         int vol = psi._grid->oSites()/LLs; | ||||
|  | ||||
|         chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|         Vector<iSinglet<Simd> > Matp; | ||||
|         Vector<iSinglet<Simd> > Matm; | ||||
|         Vector<iSinglet<Simd> > *_Matp; | ||||
|         Vector<iSinglet<Simd> > *_Matm; | ||||
|  | ||||
|         //  MooeeInternalCompute(dag,inv,Matp,Matm); | ||||
|         if(inv && dag){ | ||||
|             _Matp = &this->MatpInvDag; | ||||
|             _Matm = &this->MatmInvDag; | ||||
|         } | ||||
|  | ||||
|         if(inv && (!dag)){ | ||||
|             _Matp = &this->MatpInv; | ||||
|             _Matm = &this->MatmInv; | ||||
|         } | ||||
|  | ||||
|         if(!inv){ | ||||
|             MooeeInternalCompute(dag, inv, Matp, Matm); | ||||
|             _Matp = &Matp; | ||||
|             _Matm = &Matm; | ||||
|         } | ||||
|  | ||||
|         assert(_Matp->size() == Ls*LLs); | ||||
|  | ||||
|         this->MooeeInvCalls++; | ||||
|         this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|         if(switcheroo<Coeff_t>::iscomplex()){ | ||||
|             parallel_for(auto site=0; site<vol; site++){ | ||||
|                 MooeeInternalZAsm(psi, chi, LLs, site, *_Matp, *_Matm); | ||||
|             } | ||||
|         } else { | ||||
|             parallel_for(auto site=0; site<vol; site++){ | ||||
|                 MooeeInternalAsm(psi, chi, LLs, site, *_Matp, *_Matm); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this->MooeeInvTime += usecond(); | ||||
|     } | ||||
|  | ||||
|     #ifdef DOMAIN_WALL_EOFA_DPERP_VEC | ||||
|  | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(DomainWallVec5dImplD); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(DomainWallVec5dImplF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZDomainWallVec5dImplD); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZDomainWallVec5dImplF); | ||||
|  | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(DomainWallVec5dImplDF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(DomainWallVec5dImplFH); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZDomainWallVec5dImplDF); | ||||
|         INSTANTIATE_DPERP_DWF_EOFA(ZDomainWallVec5dImplFH); | ||||
|  | ||||
|         template void DomainWallEOFAFermion<DomainWallVec5dImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<DomainWallVec5dImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<ZDomainWallVec5dImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<ZDomainWallVec5dImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|  | ||||
|         template void DomainWallEOFAFermion<DomainWallVec5dImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<DomainWallVec5dImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<ZDomainWallVec5dImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|         template void DomainWallEOFAFermion<ZDomainWallVec5dImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|  | ||||
|     #endif | ||||
|  | ||||
| }} | ||||
| @@ -1,6 +1,6 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/Fermion_base_aggregate.h | ||||
|  | ||||
| @@ -38,6 +38,8 @@ Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| // - ContinuedFractionFermion5D.cc | ||||
| // - WilsonFermion.cc | ||||
| // - WilsonKernels.cc | ||||
| // - DomainWallEOFAFermion.cc | ||||
| // - MobiusEOFAFermion.cc | ||||
| // | ||||
| // The explicit instantiation is only avoidable if we move this source to headers and end up with include/parse/recompile | ||||
| // for EVERY .cc file. This define centralises the list and restores global push of impl cases | ||||
| @@ -55,8 +57,9 @@ Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| #include <Grid/qcd/action/fermion/ImprovedStaggeredFermion5D.h> | ||||
| #include <Grid/qcd/action/fermion/CayleyFermion5D.h>     // Cayley types | ||||
| #include <Grid/qcd/action/fermion/DomainWallFermion.h> | ||||
| #include <Grid/qcd/action/fermion/DomainWallFermion.h> | ||||
| #include <Grid/qcd/action/fermion/DomainWallEOFAFermion.h> | ||||
| #include <Grid/qcd/action/fermion/MobiusFermion.h> | ||||
| #include <Grid/qcd/action/fermion/MobiusEOFAFermion.h> | ||||
| #include <Grid/qcd/action/fermion/ZMobiusFermion.h> | ||||
| #include <Grid/qcd/action/fermion/SchurDiagTwoKappa.h> | ||||
| #include <Grid/qcd/action/fermion/ScaledShamirFermion.h> | ||||
| @@ -113,6 +116,14 @@ typedef DomainWallFermion<WilsonImplRL> DomainWallFermionRL; | ||||
| typedef DomainWallFermion<WilsonImplFH> DomainWallFermionFH; | ||||
| typedef DomainWallFermion<WilsonImplDF> DomainWallFermionDF; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<WilsonImplR> DomainWallEOFAFermionR; | ||||
| typedef DomainWallEOFAFermion<WilsonImplF> DomainWallEOFAFermionF; | ||||
| typedef DomainWallEOFAFermion<WilsonImplD> DomainWallEOFAFermionD; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<WilsonImplRL> DomainWallEOFAFermionRL; | ||||
| typedef DomainWallEOFAFermion<WilsonImplFH> DomainWallEOFAFermionFH; | ||||
| typedef DomainWallEOFAFermion<WilsonImplDF> DomainWallEOFAFermionDF; | ||||
|  | ||||
| typedef MobiusFermion<WilsonImplR> MobiusFermionR; | ||||
| typedef MobiusFermion<WilsonImplF> MobiusFermionF; | ||||
| typedef MobiusFermion<WilsonImplD> MobiusFermionD; | ||||
| @@ -121,6 +132,14 @@ typedef MobiusFermion<WilsonImplRL> MobiusFermionRL; | ||||
| typedef MobiusFermion<WilsonImplFH> MobiusFermionFH; | ||||
| typedef MobiusFermion<WilsonImplDF> MobiusFermionDF; | ||||
|  | ||||
| typedef MobiusEOFAFermion<WilsonImplR> MobiusEOFAFermionR; | ||||
| typedef MobiusEOFAFermion<WilsonImplF> MobiusEOFAFermionF; | ||||
| typedef MobiusEOFAFermion<WilsonImplD> MobiusEOFAFermionD; | ||||
|  | ||||
| typedef MobiusEOFAFermion<WilsonImplRL> MobiusEOFAFermionRL; | ||||
| typedef MobiusEOFAFermion<WilsonImplFH> MobiusEOFAFermionFH; | ||||
| typedef MobiusEOFAFermion<WilsonImplDF> MobiusEOFAFermionDF; | ||||
|  | ||||
| typedef ZMobiusFermion<ZWilsonImplR> ZMobiusFermionR; | ||||
| typedef ZMobiusFermion<ZWilsonImplF> ZMobiusFermionF; | ||||
| typedef ZMobiusFermion<ZWilsonImplD> ZMobiusFermionD; | ||||
| @@ -129,7 +148,7 @@ typedef ZMobiusFermion<ZWilsonImplRL> ZMobiusFermionRL; | ||||
| typedef ZMobiusFermion<ZWilsonImplFH> ZMobiusFermionFH; | ||||
| typedef ZMobiusFermion<ZWilsonImplDF> ZMobiusFermionDF; | ||||
|  | ||||
| // Ls vectorised  | ||||
| // Ls vectorised | ||||
| typedef DomainWallFermion<DomainWallVec5dImplR> DomainWallFermionVec5dR; | ||||
| typedef DomainWallFermion<DomainWallVec5dImplF> DomainWallFermionVec5dF; | ||||
| typedef DomainWallFermion<DomainWallVec5dImplD> DomainWallFermionVec5dD; | ||||
| @@ -138,6 +157,14 @@ typedef DomainWallFermion<DomainWallVec5dImplRL> DomainWallFermionVec5dRL; | ||||
| typedef DomainWallFermion<DomainWallVec5dImplFH> DomainWallFermionVec5dFH; | ||||
| typedef DomainWallFermion<DomainWallVec5dImplDF> DomainWallFermionVec5dDF; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<DomainWallVec5dImplR> DomainWallEOFAFermionVec5dR; | ||||
| typedef DomainWallEOFAFermion<DomainWallVec5dImplF> DomainWallEOFAFermionVec5dF; | ||||
| typedef DomainWallEOFAFermion<DomainWallVec5dImplD> DomainWallEOFAFermionVec5dD; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<DomainWallVec5dImplRL> DomainWallEOFAFermionVec5dRL; | ||||
| typedef DomainWallEOFAFermion<DomainWallVec5dImplFH> DomainWallEOFAFermionVec5dFH; | ||||
| typedef DomainWallEOFAFermion<DomainWallVec5dImplDF> DomainWallEOFAFermionVec5dDF; | ||||
|  | ||||
| typedef MobiusFermion<DomainWallVec5dImplR> MobiusFermionVec5dR; | ||||
| typedef MobiusFermion<DomainWallVec5dImplF> MobiusFermionVec5dF; | ||||
| typedef MobiusFermion<DomainWallVec5dImplD> MobiusFermionVec5dD; | ||||
| @@ -146,6 +173,14 @@ typedef MobiusFermion<DomainWallVec5dImplRL> MobiusFermionVec5dRL; | ||||
| typedef MobiusFermion<DomainWallVec5dImplFH> MobiusFermionVec5dFH; | ||||
| typedef MobiusFermion<DomainWallVec5dImplDF> MobiusFermionVec5dDF; | ||||
|  | ||||
| typedef MobiusEOFAFermion<DomainWallVec5dImplR> MobiusEOFAFermionVec5dR; | ||||
| typedef MobiusEOFAFermion<DomainWallVec5dImplF> MobiusEOFAFermionVec5dF; | ||||
| typedef MobiusEOFAFermion<DomainWallVec5dImplD> MobiusEOFAFermionVec5dD; | ||||
|  | ||||
| typedef MobiusEOFAFermion<DomainWallVec5dImplRL> MobiusEOFAFermionVec5dRL; | ||||
| typedef MobiusEOFAFermion<DomainWallVec5dImplFH> MobiusEOFAFermionVec5dFH; | ||||
| typedef MobiusEOFAFermion<DomainWallVec5dImplDF> MobiusEOFAFermionVec5dDF; | ||||
|  | ||||
| typedef ZMobiusFermion<ZDomainWallVec5dImplR> ZMobiusFermionVec5dR; | ||||
| typedef ZMobiusFermion<ZDomainWallVec5dImplF> ZMobiusFermionVec5dF; | ||||
| typedef ZMobiusFermion<ZDomainWallVec5dImplD> ZMobiusFermionVec5dD; | ||||
| @@ -206,6 +241,14 @@ typedef DomainWallFermion<GparityWilsonImplRL> GparityDomainWallFermionRL; | ||||
| typedef DomainWallFermion<GparityWilsonImplFH> GparityDomainWallFermionFH; | ||||
| typedef DomainWallFermion<GparityWilsonImplDF> GparityDomainWallFermionDF; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplR> GparityDomainWallEOFAFermionR; | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplF> GparityDomainWallEOFAFermionF; | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplD> GparityDomainWallEOFAFermionD; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplRL> GparityDomainWallEOFAFermionRL; | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplFH> GparityDomainWallEOFAFermionFH; | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplDF> GparityDomainWallEOFAFermionDF; | ||||
|  | ||||
| typedef WilsonTMFermion<GparityWilsonImplR> GparityWilsonTMFermionR; | ||||
| typedef WilsonTMFermion<GparityWilsonImplF> GparityWilsonTMFermionF; | ||||
| typedef WilsonTMFermion<GparityWilsonImplD> GparityWilsonTMFermionD; | ||||
| @@ -222,6 +265,14 @@ typedef MobiusFermion<GparityWilsonImplRL> GparityMobiusFermionRL; | ||||
| typedef MobiusFermion<GparityWilsonImplFH> GparityMobiusFermionFH; | ||||
| typedef MobiusFermion<GparityWilsonImplDF> GparityMobiusFermionDF; | ||||
|  | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplR> GparityMobiusEOFAFermionR; | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplF> GparityMobiusEOFAFermionF; | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplD> GparityMobiusEOFAFermionD; | ||||
|  | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplRL> GparityMobiusEOFAFermionRL; | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplFH> GparityMobiusEOFAFermionFH; | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplDF> GparityMobiusEOFAFermionDF; | ||||
|  | ||||
| typedef ImprovedStaggeredFermion<StaggeredImplR> ImprovedStaggeredFermionR; | ||||
| typedef ImprovedStaggeredFermion<StaggeredImplF> ImprovedStaggeredFermionF; | ||||
| typedef ImprovedStaggeredFermion<StaggeredImplD> ImprovedStaggeredFermionD; | ||||
|   | ||||
| @@ -538,6 +538,12 @@ class GparityWilsonImpl : public ConjugateGaugeImpl<GaugeImplTypes<S, Nrepresent | ||||
|     | ||||
|  } | ||||
|  | ||||
|  | ||||
|  template <class ref> | ||||
|  inline void loadLinkElement(Simd ®, ref &memory) { | ||||
|    reg = memory; | ||||
|  } | ||||
|  | ||||
|  inline void DoubleStore(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu) | ||||
|  { | ||||
|    conformable(Uds._grid,GaugeGrid); | ||||
|   | ||||
							
								
								
									
										502
									
								
								lib/qcd/action/fermion/MobiusEOFAFermion.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										502
									
								
								lib/qcd/action/fermion/MobiusEOFAFermion.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,502 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/MobiusEOFAFermion.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid_Eigen_Dense.h> | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/MobiusEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|   template<class Impl> | ||||
|     MobiusEOFAFermion<Impl>::MobiusEOFAFermion( | ||||
|       GaugeField            &_Umu, | ||||
|       GridCartesian         &FiveDimGrid, | ||||
|       GridRedBlackCartesian &FiveDimRedBlackGrid, | ||||
|       GridCartesian         &FourDimGrid, | ||||
|       GridRedBlackCartesian &FourDimRedBlackGrid, | ||||
|       RealD _mq1, RealD _mq2, RealD _mq3, | ||||
|       RealD _shift, int _pm, RealD _M5, | ||||
|       RealD _b, RealD _c, const ImplParams &p) : | ||||
|     AbstractEOFAFermion<Impl>(_Umu, FiveDimGrid, FiveDimRedBlackGrid, | ||||
|         FourDimGrid, FourDimRedBlackGrid, _mq1, _mq2, _mq3, | ||||
|         _shift, _pm, _M5, _b, _c, p) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|  | ||||
|       RealD eps = 1.0; | ||||
|       Approx::zolotarev_data *zdata = Approx::higham(eps, this->Ls); | ||||
|       assert(zdata->n == this->Ls); | ||||
|  | ||||
|       std::cout << GridLogMessage << "MobiusEOFAFermion (b=" << _b << | ||||
|         ",c=" << _c << ") with Ls=" << Ls << std::endl; | ||||
|       this->SetCoefficientsTanh(zdata, _b, _c); | ||||
|       std::cout << GridLogMessage << "EOFA parameters: (mq1=" << _mq1 << | ||||
|         ",mq2=" << _mq2 << ",mq3=" << _mq3 << ",shift=" << _shift << | ||||
|         ",pm=" << _pm << ")" << std::endl; | ||||
|  | ||||
|       Approx::zolotarev_free(zdata); | ||||
|  | ||||
|       if(_shift != 0.0){ | ||||
|         SetCoefficientsPrecondShiftOps(); | ||||
|       } else { | ||||
|         Mooee_shift.resize(Ls, 0.0); | ||||
|         MooeeInv_shift_lc.resize(Ls, 0.0); | ||||
|         MooeeInv_shift_norm.resize(Ls, 0.0); | ||||
|         MooeeInvDag_shift_lc.resize(Ls, 0.0); | ||||
|         MooeeInvDag_shift_norm.resize(Ls, 0.0); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     /*************************************************************** | ||||
|     /* Additional EOFA operators only called outside the inverter. | ||||
|     /* Since speed is not essential, simple axpby-style | ||||
|     /* implementations should be fine. | ||||
|     /***************************************************************/ | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::Omega(const FermionField& psi, FermionField& Din, int sign, int dag) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|       RealD alpha = this->alpha; | ||||
|  | ||||
|       Din = zero; | ||||
|       if((sign == 1) && (dag == 0)) { // \Omega_{+} | ||||
|         for(int s=0; s<Ls; ++s){ | ||||
|           axpby_ssp(Din, 0.0, psi, 2.0*std::pow(1.0-alpha,Ls-s-1)/std::pow(1.0+alpha,Ls-s), psi, s, 0); | ||||
|         } | ||||
|       } else if((sign == -1) && (dag == 0)) { // \Omega_{-} | ||||
|         for(int s=0; s<Ls; ++s){ | ||||
|           axpby_ssp(Din, 0.0, psi, 2.0*std::pow(1.0-alpha,s)/std::pow(1.0+alpha,s+1), psi, s, 0); | ||||
|         } | ||||
|       } else if((sign == 1 ) && (dag == 1)) { // \Omega_{+}^{\dagger} | ||||
|         for(int sp=0; sp<Ls; ++sp){ | ||||
|           axpby_ssp(Din, 1.0, Din, 2.0*std::pow(1.0-alpha,Ls-sp-1)/std::pow(1.0+alpha,Ls-sp), psi, 0, sp); | ||||
|         } | ||||
|       } else if((sign == -1) && (dag == 1)) { // \Omega_{-}^{\dagger} | ||||
|         for(int sp=0; sp<Ls; ++sp){ | ||||
|           axpby_ssp(Din, 1.0, Din, 2.0*std::pow(1.0-alpha,sp)/std::pow(1.0+alpha,sp+1), psi, 0, sp); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // This is the operator relating the usual Ddwf to TWQCD's EOFA Dirac operator (arXiv:1706.05843, Eqn. 6). | ||||
|     // It also relates the preconditioned and unpreconditioned systems described in Appendix B.2. | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::Dtilde(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|       int Ls    = this->Ls; | ||||
|       RealD b   = 0.5 * ( 1.0 + this->alpha ); | ||||
|       RealD c   = 0.5 * ( 1.0 - this->alpha ); | ||||
|       RealD mq1 = this->mq1; | ||||
|  | ||||
|       for(int s=0; s<Ls; ++s){ | ||||
|         if(s == 0) { | ||||
|           axpby_ssp_pminus(chi, b, psi, -c, psi, s, s+1); | ||||
|           axpby_ssp_pplus (chi, 1.0, chi, mq1*c, psi, s, Ls-1); | ||||
|         } else if(s == (Ls-1)) { | ||||
|           axpby_ssp_pminus(chi, b, psi, mq1*c, psi, s, 0); | ||||
|           axpby_ssp_pplus (chi, 1.0, chi, -c, psi, s, s-1); | ||||
|         } else { | ||||
|           axpby_ssp_pminus(chi, b, psi, -c, psi, s, s+1); | ||||
|           axpby_ssp_pplus (chi, 1.0, chi, -c, psi, s, s-1); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::DtildeInv(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|       RealD m = this->mq1; | ||||
|       RealD c = 0.5 * this->alpha; | ||||
|       RealD d = 0.5; | ||||
|  | ||||
|       RealD DtInv_p(0.0), DtInv_m(0.0); | ||||
|       RealD N = std::pow(c+d,Ls) + m*std::pow(c-d,Ls); | ||||
|       FermionField tmp(this->FermionGrid()); | ||||
|  | ||||
|       for(int s=0; s<Ls; ++s){ | ||||
|       for(int sp=0; sp<Ls; ++sp){ | ||||
|  | ||||
|         DtInv_p = m * std::pow(-1.0,s-sp+1) * std::pow(c-d,Ls+s-sp) / std::pow(c+d,s-sp+1) / N; | ||||
|         DtInv_p += (s < sp) ? 0.0 : std::pow(-1.0,s-sp) * std::pow(c-d,s-sp) / std::pow(c+d,s-sp+1); | ||||
|         DtInv_m = m * std::pow(-1.0,sp-s+1) * std::pow(c-d,Ls+sp-s) / std::pow(c+d,sp-s+1) / N; | ||||
|         DtInv_m += (s > sp) ? 0.0 : std::pow(-1.0,sp-s) * std::pow(c-d,sp-s) / std::pow(c+d,sp-s+1); | ||||
|  | ||||
|         if(sp == 0){ | ||||
|           axpby_ssp_pplus (tmp, 0.0, tmp, DtInv_p, psi, s, sp); | ||||
|           axpby_ssp_pminus(tmp, 0.0, tmp, DtInv_m, psi, s, sp); | ||||
|         } else { | ||||
|           axpby_ssp_pplus (tmp, 1.0, tmp, DtInv_p, psi, s, sp); | ||||
|           axpby_ssp_pminus(tmp, 1.0, tmp, DtInv_m, psi, s, sp); | ||||
|         } | ||||
|  | ||||
|       }} | ||||
|     } | ||||
|  | ||||
|     /*****************************************************************************************************/ | ||||
|  | ||||
|     template<class Impl> | ||||
|     RealD MobiusEOFAFermion<Impl>::M(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|  | ||||
|       FermionField Din(psi._grid); | ||||
|  | ||||
|       this->Meooe5D(psi, Din); | ||||
|       this->DW(Din, chi, DaggerNo); | ||||
|       axpby(chi, 1.0, 1.0, chi, psi); | ||||
|       this->M5D(psi, chi); | ||||
|       return(norm2(chi)); | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     RealD MobiusEOFAFermion<Impl>::Mdag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|  | ||||
|       FermionField Din(psi._grid); | ||||
|  | ||||
|       this->DW(psi, Din, DaggerYes); | ||||
|       this->MeooeDag5D(Din, chi); | ||||
|       this->M5Ddag(psi, chi); | ||||
|       axpby(chi, 1.0, 1.0, chi, psi); | ||||
|       return(norm2(chi)); | ||||
|     } | ||||
|  | ||||
|     /******************************************************************** | ||||
|     /* Performance critical fermion operators called inside the inverter | ||||
|     /********************************************************************/ | ||||
|  | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::M5D(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|  | ||||
|       std::vector<Coeff_t> diag(Ls,1.0); | ||||
|       std::vector<Coeff_t> upper(Ls,-1.0);  upper[Ls-1] = this->mq1; | ||||
|       std::vector<Coeff_t> lower(Ls,-1.0);  lower[0]    = this->mq1; | ||||
|  | ||||
|       // no shift term | ||||
|       if(this->shift == 0.0){ this->M5D(psi, chi, chi, lower, diag, upper); } | ||||
|  | ||||
|       // fused M + shift operation | ||||
|       else{ this->M5D_shift(psi, chi, chi, lower, diag, upper, Mooee_shift); } | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::M5Ddag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|  | ||||
|       std::vector<Coeff_t> diag(Ls,1.0); | ||||
|       std::vector<Coeff_t> upper(Ls,-1.0);  upper[Ls-1] = this->mq1; | ||||
|       std::vector<Coeff_t> lower(Ls,-1.0);  lower[0]    = this->mq1; | ||||
|  | ||||
|       // no shift term | ||||
|       if(this->shift == 0.0){ this->M5Ddag(psi, chi, chi, lower, diag, upper); } | ||||
|  | ||||
|       // fused M + shift operation | ||||
|       else{ this->M5Ddag_shift(psi, chi, chi, lower, diag, upper, Mooee_shift); } | ||||
|     } | ||||
|  | ||||
|     // half checkerboard operations | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::Mooee(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|  | ||||
|       // coefficients of Mooee | ||||
|       std::vector<Coeff_t> diag = this->bee; | ||||
|       std::vector<Coeff_t> upper(Ls); | ||||
|       std::vector<Coeff_t> lower(Ls); | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         upper[s] = -this->cee[s]; | ||||
|         lower[s] = -this->cee[s]; | ||||
|       } | ||||
|       upper[Ls-1] *= -this->mq1; | ||||
|       lower[0]    *= -this->mq1; | ||||
|  | ||||
|       // no shift term | ||||
|       if(this->shift == 0.0){ this->M5D(psi, psi, chi, lower, diag, upper); } | ||||
|  | ||||
|       // fused M + shift operation | ||||
|       else { this->M5D_shift(psi, psi, chi, lower, diag, upper, Mooee_shift); } | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::MooeeDag(const FermionField& psi, FermionField& chi) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|  | ||||
|       // coefficients of MooeeDag | ||||
|       std::vector<Coeff_t> diag = this->bee; | ||||
|       std::vector<Coeff_t> upper(Ls); | ||||
|       std::vector<Coeff_t> lower(Ls); | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         if(s==0) { | ||||
|           upper[s] = -this->cee[s+1]; | ||||
|           lower[s] = this->mq1*this->cee[Ls-1]; | ||||
|         } else if(s==(Ls-1)) { | ||||
|           upper[s] = this->mq1*this->cee[0]; | ||||
|           lower[s] = -this->cee[s-1]; | ||||
|         } else { | ||||
|           upper[s] = -this->cee[s+1]; | ||||
|           lower[s] = -this->cee[s-1]; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       // no shift term | ||||
|       if(this->shift == 0.0){ this->M5Ddag(psi, psi, chi, lower, diag, upper); } | ||||
|  | ||||
|       // fused M + shift operation | ||||
|       else{ this->M5Ddag_shift(psi, psi, chi, lower, diag, upper, Mooee_shift); } | ||||
|     } | ||||
|  | ||||
|     /****************************************************************************************/ | ||||
|  | ||||
|     // Computes coefficients for applying Cayley preconditioned shift operators | ||||
|     //  (Mooee + \Delta) --> Mooee_shift | ||||
|     //  (Mooee + \Delta)^{-1} --> MooeeInv_shift_lc, MooeeInv_shift_norm | ||||
|     //  (Mooee + \Delta)^{-dag} --> MooeeInvDag_shift_lc, MooeeInvDag_shift_norm | ||||
|     // For the latter two cases, the operation takes the form | ||||
|     //  [ (Mooee + \Delta)^{-1} \psi ]_{i} = Mooee_{ij} \psi_{j} + | ||||
|     //      ( MooeeInv_shift_norm )_{i} ( \sum_{j} [ MooeeInv_shift_lc ]_{j} P_{pm} \psi_{j} ) | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::SetCoefficientsPrecondShiftOps() | ||||
|     { | ||||
|       int   Ls    = this->Ls; | ||||
|       int   pm    = this->pm; | ||||
|       RealD alpha = this->alpha; | ||||
|       RealD k     = this->k; | ||||
|       RealD mq1   = this->mq1; | ||||
|       RealD shift = this->shift; | ||||
|  | ||||
|       // Initialize | ||||
|       Mooee_shift.resize(Ls); | ||||
|       MooeeInv_shift_lc.resize(Ls); | ||||
|       MooeeInv_shift_norm.resize(Ls); | ||||
|       MooeeInvDag_shift_lc.resize(Ls); | ||||
|       MooeeInvDag_shift_norm.resize(Ls); | ||||
|  | ||||
|       // Construct Mooee_shift | ||||
|       int idx(0); | ||||
|       Coeff_t N = ( (pm == 1) ? 1.0 : -1.0 ) * (2.0*shift*k) * | ||||
|                   ( std::pow(alpha+1.0,Ls) + mq1*std::pow(alpha-1.0,Ls) ); | ||||
|       for(int s=0; s<Ls; ++s){ | ||||
|         idx = (pm == 1) ? (s) : (Ls-1-s); | ||||
|         Mooee_shift[idx] = N * std::pow(-1.0,s) * std::pow(alpha-1.0,s) / std::pow(alpha+1.0,Ls+s+1); | ||||
|       } | ||||
|  | ||||
|       // Tridiagonal solve for MooeeInvDag_shift_lc | ||||
|       { | ||||
|         Coeff_t m(0.0); | ||||
|         std::vector<Coeff_t> d = Mooee_shift; | ||||
|         std::vector<Coeff_t> u(Ls,0.0); | ||||
|         std::vector<Coeff_t> y(Ls,0.0); | ||||
|         std::vector<Coeff_t> q(Ls,0.0); | ||||
|         if(pm == 1){ u[0] = 1.0; } | ||||
|         else{ u[Ls-1] = 1.0; } | ||||
|  | ||||
|         // Tridiagonal matrix algorithm + Sherman-Morrison formula | ||||
|         // | ||||
|         // We solve | ||||
|         //  ( Mooee' + u \otimes v ) MooeeInvDag_shift_lc = Mooee_shift | ||||
|         // where Mooee' is the tridiagonal part of Mooee_{+}, and | ||||
|         // u = (1,0,...,0) and v = (0,...,0,mq1*cee[0]) are chosen | ||||
|         // so that the outer-product u \otimes v gives the (0,Ls-1) | ||||
|         // entry of Mooee_{+}. | ||||
|         // | ||||
|         // We do this as two solves: Mooee'*y = d and Mooee'*q = u, | ||||
|         // and then construct the solution to the original system | ||||
|         //  MooeeInvDag_shift_lc = y - <v,y> / ( 1 + <v,q> ) q | ||||
|         if(pm == 1){ | ||||
|           for(int s=1; s<Ls; ++s){ | ||||
|             m = -this->cee[s] / this->bee[s-1]; | ||||
|             d[s] -= m*d[s-1]; | ||||
|             u[s] -= m*u[s-1]; | ||||
|           } | ||||
|         } | ||||
|         y[Ls-1] = d[Ls-1] / this->bee[Ls-1]; | ||||
|         q[Ls-1] = u[Ls-1] / this->bee[Ls-1]; | ||||
|         for(int s=Ls-2; s>=0; --s){ | ||||
|           if(pm == 1){ | ||||
|             y[s] = d[s] / this->bee[s]; | ||||
|             q[s] = u[s] / this->bee[s]; | ||||
|           } else { | ||||
|             y[s] = ( d[s] + this->cee[s]*y[s+1] ) / this->bee[s]; | ||||
|             q[s] = ( u[s] + this->cee[s]*q[s+1] ) / this->bee[s]; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         // Construct MooeeInvDag_shift_lc | ||||
|         for(int s=0; s<Ls; ++s){ | ||||
|           if(pm == 1){ | ||||
|             MooeeInvDag_shift_lc[s] = y[s] - mq1*this->cee[0]*y[Ls-1] / | ||||
|               (1.0+mq1*this->cee[0]*q[Ls-1]) * q[s]; | ||||
|           } else { | ||||
|             MooeeInvDag_shift_lc[s] = y[s] - mq1*this->cee[Ls-1]*y[0] / | ||||
|               (1.0+mq1*this->cee[Ls-1]*q[0]) * q[s]; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         // Compute remaining coefficients | ||||
|         N = (pm == 1) ? (1.0 + MooeeInvDag_shift_lc[Ls-1]) : (1.0 + MooeeInvDag_shift_lc[0]); | ||||
|         for(int s=0; s<Ls; ++s){ | ||||
|  | ||||
|           // MooeeInv_shift_lc | ||||
|           if(pm == 1){ MooeeInv_shift_lc[s] = std::pow(this->bee[s],s) * std::pow(this->cee[s],Ls-1-s); } | ||||
|           else{ MooeeInv_shift_lc[s] = std::pow(this->bee[s],Ls-1-s) * std::pow(this->cee[s],s); } | ||||
|  | ||||
|           // MooeeInv_shift_norm | ||||
|           MooeeInv_shift_norm[s] = -MooeeInvDag_shift_lc[s] / | ||||
|             ( std::pow(this->bee[s],Ls) + mq1*std::pow(this->cee[s],Ls) ) / N; | ||||
|  | ||||
|           // MooeeInvDag_shift_norm | ||||
|           if(pm == 1){ MooeeInvDag_shift_norm[s] = -std::pow(this->bee[s],s) * std::pow(this->cee[s],Ls-1-s) / | ||||
|             ( std::pow(this->bee[s],Ls) + mq1*std::pow(this->cee[s],Ls) ) / N; } | ||||
|           else{ MooeeInvDag_shift_norm[s] = -std::pow(this->bee[s],Ls-1-s) * std::pow(this->cee[s],s) / | ||||
|             ( std::pow(this->bee[s],Ls) + mq1*std::pow(this->cee[s],Ls) ) / N; } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Recompute coefficients for a different value of shift constant | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::RefreshShiftCoefficients(RealD new_shift) | ||||
|     { | ||||
|       this->shift = new_shift; | ||||
|       if(new_shift != 0.0){ | ||||
|         SetCoefficientsPrecondShiftOps(); | ||||
|       } else { | ||||
|         int Ls = this->Ls; | ||||
|         Mooee_shift.resize(Ls,0.0); | ||||
|         MooeeInv_shift_lc.resize(Ls,0.0); | ||||
|         MooeeInv_shift_norm.resize(Ls,0.0); | ||||
|         MooeeInvDag_shift_lc.resize(Ls,0.0); | ||||
|         MooeeInvDag_shift_norm.resize(Ls,0.0); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     template<class Impl> | ||||
|     void MobiusEOFAFermion<Impl>::MooeeInternalCompute(int dag, int inv, | ||||
|       Vector<iSinglet<Simd> >& Matp, Vector<iSinglet<Simd> >& Matm) | ||||
|     { | ||||
|       int Ls = this->Ls; | ||||
|  | ||||
|       GridBase* grid = this->FermionRedBlackGrid(); | ||||
|       int LLs = grid->_rdimensions[0]; | ||||
|  | ||||
|       if(LLs == Ls){ return; } // Not vectorised in 5th direction | ||||
|  | ||||
|       Eigen::MatrixXcd Pplus  = Eigen::MatrixXcd::Zero(Ls,Ls); | ||||
|       Eigen::MatrixXcd Pminus = Eigen::MatrixXcd::Zero(Ls,Ls); | ||||
|  | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         Pplus(s,s)  = this->bee[s]; | ||||
|         Pminus(s,s) = this->bee[s]; | ||||
|       } | ||||
|  | ||||
|       for(int s=0; s<Ls-1; s++){ | ||||
|         Pminus(s,s+1) = -this->cee[s]; | ||||
|         Pplus(s+1,s) = -this->cee[s+1]; | ||||
|       } | ||||
|  | ||||
|       Pplus (0,Ls-1) = this->mq1*this->cee[0]; | ||||
|       Pminus(Ls-1,0) = this->mq1*this->cee[Ls-1]; | ||||
|  | ||||
|       if(this->shift != 0.0){ | ||||
|         RealD c = 0.5 * this->alpha; | ||||
|         RealD d = 0.5; | ||||
|         RealD N = this->shift * this->k * ( std::pow(c+d,Ls) + this->mq1*std::pow(c-d,Ls) ); | ||||
|         if(this->pm == 1) { | ||||
|           for(int s=0; s<Ls; ++s){ | ||||
|             Pplus(s,Ls-1) += N * std::pow(-1.0,s) * std::pow(c-d,s) / std::pow(c+d,Ls+s+1); | ||||
|           } | ||||
|         } else { | ||||
|           for(int s=0; s<Ls; ++s){ | ||||
|             Pminus(s,0) += N * std::pow(-1.0,s+1) * std::pow(c-d,Ls-1-s) / std::pow(c+d,2*Ls-s); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       Eigen::MatrixXcd PplusMat ; | ||||
|       Eigen::MatrixXcd PminusMat; | ||||
|  | ||||
|       if(inv) { | ||||
|         PplusMat  = Pplus.inverse(); | ||||
|         PminusMat = Pminus.inverse(); | ||||
|       } else { | ||||
|         PplusMat  = Pplus; | ||||
|         PminusMat = Pminus; | ||||
|       } | ||||
|  | ||||
|       if(dag){ | ||||
|         PplusMat.adjointInPlace(); | ||||
|         PminusMat.adjointInPlace(); | ||||
|       } | ||||
|  | ||||
|       typedef typename SiteHalfSpinor::scalar_type scalar_type; | ||||
|       const int Nsimd = Simd::Nsimd(); | ||||
|       Matp.resize(Ls*LLs); | ||||
|       Matm.resize(Ls*LLs); | ||||
|  | ||||
|       for(int s2=0; s2<Ls; s2++){ | ||||
|       for(int s1=0; s1<LLs; s1++){ | ||||
|         int istride = LLs; | ||||
|         int ostride = 1; | ||||
|         Simd Vp; | ||||
|         Simd Vm; | ||||
|         scalar_type *sp = (scalar_type*) &Vp; | ||||
|         scalar_type *sm = (scalar_type*) &Vm; | ||||
|         for(int l=0; l<Nsimd; l++){ | ||||
|           if(switcheroo<Coeff_t>::iscomplex()) { | ||||
|             sp[l] = PplusMat (l*istride+s1*ostride,s2); | ||||
|             sm[l] = PminusMat(l*istride+s1*ostride,s2); | ||||
|           } else { | ||||
|             // if real | ||||
|             scalar_type tmp; | ||||
|             tmp = PplusMat (l*istride+s1*ostride,s2); | ||||
|             sp[l] = scalar_type(tmp.real(),tmp.real()); | ||||
|             tmp = PminusMat(l*istride+s1*ostride,s2); | ||||
|             sm[l] = scalar_type(tmp.real(),tmp.real()); | ||||
|           } | ||||
|         } | ||||
|         Matp[LLs*s2+s1] = Vp; | ||||
|         Matm[LLs*s2+s1] = Vm; | ||||
|       }} | ||||
|   } | ||||
|  | ||||
|   FermOpTemplateInstantiate(MobiusEOFAFermion); | ||||
|   GparityFermOpTemplateInstantiate(MobiusEOFAFermion); | ||||
|  | ||||
| }} | ||||
							
								
								
									
										133
									
								
								lib/qcd/action/fermion/MobiusEOFAFermion.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								lib/qcd/action/fermion/MobiusEOFAFermion.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/MobiusEOFAFermion.h | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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_QCD_MOBIUS_EOFA_FERMION_H | ||||
| #define  GRID_QCD_MOBIUS_EOFA_FERMION_H | ||||
|  | ||||
| #include <Grid/qcd/action/fermion/AbstractEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|   template<class Impl> | ||||
|   class MobiusEOFAFermion : public AbstractEOFAFermion<Impl> | ||||
|   { | ||||
|     public: | ||||
|       INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|     public: | ||||
|       // Shift operator coefficients for red-black preconditioned Mobius EOFA | ||||
|       std::vector<Coeff_t> Mooee_shift; | ||||
|       std::vector<Coeff_t> MooeeInv_shift_lc; | ||||
|       std::vector<Coeff_t> MooeeInv_shift_norm; | ||||
|       std::vector<Coeff_t> MooeeInvDag_shift_lc; | ||||
|       std::vector<Coeff_t> MooeeInvDag_shift_norm; | ||||
|  | ||||
|       virtual void Instantiatable(void) {}; | ||||
|  | ||||
|       // EOFA-specific operations | ||||
|       virtual void  Omega            (const FermionField& in, FermionField& out, int sign, int dag); | ||||
|       virtual void  Dtilde           (const FermionField& in, FermionField& out); | ||||
|       virtual void  DtildeInv        (const FermionField& in, FermionField& out); | ||||
|  | ||||
|       // override multiply | ||||
|       virtual RealD M                (const FermionField& in, FermionField& out); | ||||
|       virtual RealD Mdag             (const FermionField& in, FermionField& out); | ||||
|  | ||||
|       // half checkerboard operations | ||||
|       virtual void  Mooee            (const FermionField& in, FermionField& out); | ||||
|       virtual void  MooeeDag         (const FermionField& in, FermionField& out); | ||||
|       virtual void  MooeeInv         (const FermionField& in, FermionField& out); | ||||
|       virtual void  MooeeInv_shift   (const FermionField& in, FermionField& out); | ||||
|       virtual void  MooeeInvDag      (const FermionField& in, FermionField& out); | ||||
|       virtual void  MooeeInvDag_shift(const FermionField& in, FermionField& out); | ||||
|  | ||||
|       virtual void   M5D             (const FermionField& psi, FermionField& chi); | ||||
|       virtual void   M5Ddag          (const FermionField& psi, FermionField& chi); | ||||
|  | ||||
|       ///////////////////////////////////////////////////// | ||||
|       // Instantiate different versions depending on Impl | ||||
|       ///////////////////////////////////////////////////// | ||||
|       void M5D(const FermionField& psi, const FermionField& phi, FermionField& chi, | ||||
|         std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper); | ||||
|  | ||||
|       void M5D_shift(const FermionField& psi, const FermionField& phi, FermionField& chi, | ||||
|         std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper, | ||||
|         std::vector<Coeff_t>& shift_coeffs); | ||||
|  | ||||
|       void M5Ddag(const FermionField& psi, const FermionField& phi, FermionField& chi, | ||||
|         std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper); | ||||
|  | ||||
|       void M5Ddag_shift(const FermionField& psi, const FermionField& phi, FermionField& chi, | ||||
|         std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper, | ||||
|         std::vector<Coeff_t>& shift_coeffs); | ||||
|  | ||||
|       void MooeeInternal(const FermionField& in, FermionField& out, int dag, int inv); | ||||
|  | ||||
|       void MooeeInternalCompute(int dag, int inv, Vector<iSinglet<Simd>>& Matp, Vector<iSinglet<Simd>>& Matm); | ||||
|  | ||||
|       void MooeeInternalAsm(const FermionField& in, FermionField& out, int LLs, int site, | ||||
|         Vector<iSinglet<Simd>>& Matp, Vector<iSinglet<Simd>>& Matm); | ||||
|  | ||||
|       void MooeeInternalZAsm(const FermionField& in, FermionField& out, int LLs, int site, | ||||
|         Vector<iSinglet<Simd>>& Matp, Vector<iSinglet<Simd>>& Matm); | ||||
|  | ||||
|       virtual void RefreshShiftCoefficients(RealD new_shift); | ||||
|  | ||||
|       // Constructors | ||||
|       MobiusEOFAFermion(GaugeField& _Umu, GridCartesian& FiveDimGrid, GridRedBlackCartesian& FiveDimRedBlackGrid, | ||||
|         GridCartesian& FourDimGrid, GridRedBlackCartesian& FourDimRedBlackGrid, | ||||
|         RealD _mq1, RealD _mq2, RealD _mq3, RealD _shift, int pm, | ||||
|         RealD _M5, RealD _b, RealD _c, const ImplParams& p=ImplParams()); | ||||
|  | ||||
|     protected: | ||||
|       void SetCoefficientsPrecondShiftOps(void); | ||||
|   }; | ||||
| }} | ||||
|  | ||||
| #define INSTANTIATE_DPERP_MOBIUS_EOFA(A)\ | ||||
| template void MobiusEOFAFermion<A>::M5D(const FermionField& psi, const FermionField& phi, FermionField& chi, \ | ||||
|   std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper); \ | ||||
| template void MobiusEOFAFermion<A>::M5D_shift(const FermionField& psi, const FermionField& phi, FermionField& chi, \ | ||||
|   std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper, std::vector<Coeff_t>& shift_coeffs); \ | ||||
| template void MobiusEOFAFermion<A>::M5Ddag(const FermionField& psi, const FermionField& phi, FermionField& chi, \ | ||||
|   std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper); \ | ||||
| template void MobiusEOFAFermion<A>::M5Ddag_shift(const FermionField& psi, const FermionField& phi, FermionField& chi, \ | ||||
|   std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper, std::vector<Coeff_t>& shift_coeffs); \ | ||||
| template void MobiusEOFAFermion<A>::MooeeInv(const FermionField& psi, FermionField& chi); \ | ||||
| template void MobiusEOFAFermion<A>::MooeeInv_shift(const FermionField& psi, FermionField& chi); \ | ||||
| template void MobiusEOFAFermion<A>::MooeeInvDag(const FermionField& psi, FermionField& chi); \ | ||||
| template void MobiusEOFAFermion<A>::MooeeInvDag_shift(const FermionField& psi, FermionField& chi); | ||||
|  | ||||
| #undef  MOBIUS_EOFA_DPERP_DENSE | ||||
| #define MOBIUS_EOFA_DPERP_CACHE | ||||
| #undef  MOBIUS_EOFA_DPERP_LINALG | ||||
| #define MOBIUS_EOFA_DPERP_VEC | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										429
									
								
								lib/qcd/action/fermion/MobiusEOFAFermioncache.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								lib/qcd/action/fermion/MobiusEOFAFermioncache.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,429 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/MobiusEOFAFermioncache.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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/MobiusEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|   // FIXME -- make a version of these routines with site loop outermost for cache reuse. | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5D(const FermionField &psi, const FermionField &phi, FermionField &chi, | ||||
|     std::vector<Coeff_t> &lower, std::vector<Coeff_t> &diag, std::vector<Coeff_t> &upper) | ||||
|   { | ||||
|     int Ls = this->Ls; | ||||
|     GridBase *grid = psi._grid; | ||||
|  | ||||
|     assert(phi.checkerboard == psi.checkerboard); | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|     this->M5Dcalls++; | ||||
|     this->M5Dtime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         auto tmp = psi._odata[0]; | ||||
|         if(s==0){ | ||||
|           spProj5m(tmp, psi._odata[ss+s+1]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5p(tmp, psi._odata[ss+Ls-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } else if(s==(Ls-1)) { | ||||
|           spProj5m(tmp, psi._odata[ss+0]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5p(tmp, psi._odata[ss+s-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } else { | ||||
|           spProj5m(tmp, psi._odata[ss+s+1]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5p(tmp, psi._odata[ss+s-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->M5Dtime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5D_shift(const FermionField &psi, const FermionField &phi, FermionField &chi, | ||||
|     std::vector<Coeff_t> &lower, std::vector<Coeff_t> &diag, std::vector<Coeff_t> &upper, | ||||
|     std::vector<Coeff_t> &shift_coeffs) | ||||
|   { | ||||
|     int Ls = this->Ls; | ||||
|     int shift_s = (this->pm == 1) ? (Ls-1) : 0; // s-component modified by shift operator | ||||
|     GridBase *grid = psi._grid; | ||||
|  | ||||
|     assert(phi.checkerboard == psi.checkerboard); | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|     this->M5Dcalls++; | ||||
|     this->M5Dtime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         auto tmp = psi._odata[0]; | ||||
|         if(s==0){ | ||||
|           spProj5m(tmp, psi._odata[ss+s+1]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5p(tmp, psi._odata[ss+Ls-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } else if(s==(Ls-1)) { | ||||
|           spProj5m(tmp, psi._odata[ss+0]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5p(tmp, psi._odata[ss+s-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } else { | ||||
|           spProj5m(tmp, psi._odata[ss+s+1]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5p(tmp, psi._odata[ss+s-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } | ||||
|         if(this->pm == 1){ spProj5p(tmp, psi._odata[ss+shift_s]); } | ||||
|         else{ spProj5m(tmp, psi._odata[ss+shift_s]); } | ||||
|         chi[ss+s] = chi[ss+s] + shift_coeffs[s]*tmp; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->M5Dtime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5Ddag(const FermionField &psi, const FermionField &phi, FermionField &chi, | ||||
|     std::vector<Coeff_t> &lower, std::vector<Coeff_t> &diag, std::vector<Coeff_t> &upper) | ||||
|   { | ||||
|     int Ls = this->Ls; | ||||
|     GridBase *grid = psi._grid; | ||||
|  | ||||
|     assert(phi.checkerboard == psi.checkerboard); | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|     this->M5Dcalls++; | ||||
|     this->M5Dtime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ | ||||
|       auto tmp = psi._odata[0]; | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         if(s==0) { | ||||
|           spProj5p(tmp, psi._odata[ss+s+1]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5m(tmp, psi._odata[ss+Ls-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } else if(s==(Ls-1)) { | ||||
|           spProj5p(tmp, psi._odata[ss+0]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5m(tmp, psi._odata[ss+s-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } else { | ||||
|           spProj5p(tmp, psi._odata[ss+s+1]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5m(tmp, psi._odata[ss+s-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->M5Dtime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5Ddag_shift(const FermionField &psi, const FermionField &phi, FermionField &chi, | ||||
|     std::vector<Coeff_t> &lower, std::vector<Coeff_t> &diag, std::vector<Coeff_t> &upper, | ||||
|     std::vector<Coeff_t> &shift_coeffs) | ||||
|   { | ||||
|     int Ls = this->Ls; | ||||
|     int shift_s = (this->pm == 1) ? (Ls-1) : 0; // s-component modified by shift operator | ||||
|     GridBase *grid = psi._grid; | ||||
|  | ||||
|     assert(phi.checkerboard == psi.checkerboard); | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|     this->M5Dcalls++; | ||||
|     this->M5Dtime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ | ||||
|       chi[ss+Ls-1] = zero; | ||||
|       auto tmp = psi._odata[0]; | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         if(s==0) { | ||||
|           spProj5p(tmp, psi._odata[ss+s+1]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5m(tmp, psi._odata[ss+Ls-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } else if(s==(Ls-1)) { | ||||
|           spProj5p(tmp, psi._odata[ss+0]); | ||||
|           chi[ss+s] = chi[ss+s] + diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5m(tmp, psi._odata[ss+s-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } else { | ||||
|           spProj5p(tmp, psi._odata[ss+s+1]); | ||||
|           chi[ss+s] = diag[s]*phi[ss+s] + upper[s]*tmp; | ||||
|           spProj5m(tmp, psi._odata[ss+s-1]); | ||||
|           chi[ss+s] = chi[ss+s] + lower[s]*tmp; | ||||
|         } | ||||
|         if(this->pm == 1){ spProj5p(tmp, psi._odata[ss+s]); } | ||||
|         else{ spProj5m(tmp, psi._odata[ss+s]); } | ||||
|         chi[ss+shift_s] = chi[ss+shift_s] + shift_coeffs[s]*tmp; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->M5Dtime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInv(const FermionField &psi, FermionField &chi) | ||||
|   { | ||||
|     if(this->shift != 0.0){ MooeeInv_shift(psi,chi); return; } | ||||
|  | ||||
|     GridBase *grid = psi._grid; | ||||
|     int Ls = this->Ls; | ||||
|  | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     this->MooeeInvCalls++; | ||||
|     this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ | ||||
|  | ||||
|       auto tmp = psi._odata[0]; | ||||
|  | ||||
|       // Apply (L^{\prime})^{-1} | ||||
|       chi[ss] = psi[ss]; // chi[0]=psi[0] | ||||
|       for(int s=1; s<Ls; s++){ | ||||
|         spProj5p(tmp, chi[ss+s-1]); | ||||
|         chi[ss+s] = psi[ss+s] - this->lee[s-1]*tmp; | ||||
|       } | ||||
|  | ||||
|       // L_m^{-1} | ||||
|       for(int s=0; s<Ls-1; s++){ // Chi[ee] = 1 - sum[s<Ls-1] -leem[s]P_- chi | ||||
|         spProj5m(tmp, chi[ss+s]); | ||||
|         chi[ss+Ls-1] = chi[ss+Ls-1] - this->leem[s]*tmp; | ||||
|       } | ||||
|  | ||||
|       // U_m^{-1} D^{-1} | ||||
|       for(int s=0; s<Ls-1; s++){ // Chi[s] + 1/d chi[s] | ||||
|         spProj5p(tmp, chi[ss+Ls-1]); | ||||
|         chi[ss+s] = (1.0/this->dee[s])*chi[ss+s] - (this->ueem[s]/this->dee[Ls-1])*tmp; | ||||
|       } | ||||
|       chi[ss+Ls-1] = (1.0/this->dee[Ls-1])*chi[ss+Ls-1]; | ||||
|  | ||||
|       // Apply U^{-1} | ||||
|       for(int s=Ls-2; s>=0; s--){ | ||||
|         spProj5m(tmp, chi[ss+s+1]); | ||||
|         chi[ss+s] = chi[ss+s] - this->uee[s]*tmp; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->MooeeInvTime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInv_shift(const FermionField &psi, FermionField &chi) | ||||
|   { | ||||
|     GridBase *grid = psi._grid; | ||||
|     int Ls = this->Ls; | ||||
|  | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     this->MooeeInvCalls++; | ||||
|     this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ | ||||
|  | ||||
|       auto tmp1        = psi._odata[0]; | ||||
|       auto tmp2        = psi._odata[0]; | ||||
|       auto tmp2_spProj = psi._odata[0]; | ||||
|  | ||||
|       // Apply (L^{\prime})^{-1} and accumulate MooeeInv_shift_lc[j]*psi[j] in tmp2 | ||||
|       chi[ss] = psi[ss]; // chi[0]=psi[0] | ||||
|       tmp2 = MooeeInv_shift_lc[0]*psi[ss]; | ||||
|       for(int s=1; s<Ls; s++){ | ||||
|         spProj5p(tmp1, chi[ss+s-1]); | ||||
|         chi[ss+s] = psi[ss+s] - this->lee[s-1]*tmp1; | ||||
|         tmp2 = tmp2 + MooeeInv_shift_lc[s]*psi[ss+s]; | ||||
|       } | ||||
|       if(this->pm == 1){ spProj5p(tmp2_spProj, tmp2);} | ||||
|       else{ spProj5m(tmp2_spProj, tmp2); } | ||||
|  | ||||
|       // L_m^{-1} | ||||
|       for(int s=0; s<Ls-1; s++){ // Chi[ee] = 1 - sum[s<Ls-1] -leem[s]P_- chi | ||||
|         spProj5m(tmp1, chi[ss+s]); | ||||
|         chi[ss+Ls-1] = chi[ss+Ls-1] - this->leem[s]*tmp1; | ||||
|       } | ||||
|  | ||||
|       // U_m^{-1} D^{-1} | ||||
|       for(int s=0; s<Ls-1; s++){ // Chi[s] + 1/d chi[s] | ||||
|         spProj5p(tmp1, chi[ss+Ls-1]); | ||||
|         chi[ss+s] = (1.0/this->dee[s])*chi[ss+s] - (this->ueem[s]/this->dee[Ls-1])*tmp1; | ||||
|       } | ||||
|       // chi[ss+Ls-1] = (1.0/this->dee[Ls-1])*chi[ss+Ls-1] + MooeeInv_shift_norm[Ls-1]*tmp2_spProj; | ||||
|       chi[ss+Ls-1] = (1.0/this->dee[Ls-1])*chi[ss+Ls-1]; | ||||
|       spProj5m(tmp1, chi[ss+Ls-1]); | ||||
|       chi[ss+Ls-1] = chi[ss+Ls-1] + MooeeInv_shift_norm[Ls-1]*tmp2_spProj; | ||||
|  | ||||
|       // Apply U^{-1} and add shift term | ||||
|       for(int s=Ls-2; s>=0; s--){ | ||||
|         chi[ss+s] = chi[ss+s] - this->uee[s]*tmp1; | ||||
|         spProj5m(tmp1, chi[ss+s]); | ||||
|         chi[ss+s] = chi[ss+s] + MooeeInv_shift_norm[s]*tmp2_spProj; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->MooeeInvTime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInvDag(const FermionField &psi, FermionField &chi) | ||||
|   { | ||||
|     if(this->shift != 0.0){ MooeeInvDag_shift(psi,chi); return; } | ||||
|  | ||||
|     GridBase *grid = psi._grid; | ||||
|     int Ls = this->Ls; | ||||
|  | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     this->MooeeInvCalls++; | ||||
|     this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ | ||||
|  | ||||
|       auto tmp = psi._odata[0]; | ||||
|  | ||||
|       // Apply (U^{\prime})^{-dag} | ||||
|       chi[ss] = psi[ss]; | ||||
|       for(int s=1; s<Ls; s++){ | ||||
|         spProj5m(tmp, chi[ss+s-1]); | ||||
|         chi[ss+s] = psi[ss+s] - this->uee[s-1]*tmp; | ||||
|       } | ||||
|  | ||||
|       // U_m^{-\dag} | ||||
|       for(int s=0; s<Ls-1; s++){ | ||||
|         spProj5p(tmp, chi[ss+s]); | ||||
|         chi[ss+Ls-1] = chi[ss+Ls-1] - this->ueem[s]*tmp; | ||||
|       } | ||||
|  | ||||
|       // L_m^{-\dag} D^{-dag} | ||||
|       for(int s=0; s<Ls-1; s++){ | ||||
|         spProj5m(tmp, chi[ss+Ls-1]); | ||||
|         chi[ss+s] = (1.0/this->dee[s])*chi[ss+s] - (this->leem[s]/this->dee[Ls-1])*tmp; | ||||
|       } | ||||
|       chi[ss+Ls-1] = (1.0/this->dee[Ls-1])*chi[ss+Ls-1]; | ||||
|  | ||||
|       // Apply L^{-dag} | ||||
|       for(int s=Ls-2; s>=0; s--){ | ||||
|         spProj5p(tmp, chi[ss+s+1]); | ||||
|         chi[ss+s] = chi[ss+s] - this->lee[s]*tmp; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->MooeeInvTime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInvDag_shift(const FermionField &psi, FermionField &chi) | ||||
|   { | ||||
|     GridBase *grid = psi._grid; | ||||
|     int Ls = this->Ls; | ||||
|  | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     this->MooeeInvCalls++; | ||||
|     this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=Ls){ | ||||
|  | ||||
|       auto tmp1        = psi._odata[0]; | ||||
|       auto tmp2        = psi._odata[0]; | ||||
|       auto tmp2_spProj = psi._odata[0]; | ||||
|  | ||||
|       // Apply (U^{\prime})^{-dag} and accumulate MooeeInvDag_shift_lc[j]*psi[j] in tmp2 | ||||
|       chi[ss] = psi[ss]; | ||||
|       tmp2 = MooeeInvDag_shift_lc[0]*psi[ss]; | ||||
|       for(int s=1; s<Ls; s++){ | ||||
|         spProj5m(tmp1, chi[ss+s-1]); | ||||
|         chi[ss+s] = psi[ss+s] - this->uee[s-1]*tmp1; | ||||
|         tmp2 = tmp2 + MooeeInvDag_shift_lc[s]*psi[ss+s]; | ||||
|       } | ||||
|       if(this->pm == 1){ spProj5p(tmp2_spProj, tmp2);} | ||||
|       else{ spProj5m(tmp2_spProj, tmp2); } | ||||
|  | ||||
|       // U_m^{-\dag} | ||||
|       for(int s=0; s<Ls-1; s++){ | ||||
|         spProj5p(tmp1, chi[ss+s]); | ||||
|         chi[ss+Ls-1] = chi[ss+Ls-1] - this->ueem[s]*tmp1; | ||||
|       } | ||||
|  | ||||
|       // L_m^{-\dag} D^{-dag} | ||||
|       for(int s=0; s<Ls-1; s++){ | ||||
|         spProj5m(tmp1, chi[ss+Ls-1]); | ||||
|         chi[ss+s] = (1.0/this->dee[s])*chi[ss+s] - (this->leem[s]/this->dee[Ls-1])*tmp1; | ||||
|       } | ||||
|       chi[ss+Ls-1] = (1.0/this->dee[Ls-1])*chi[ss+Ls-1]; | ||||
|       spProj5p(tmp1, chi[ss+Ls-1]); | ||||
|       chi[ss+Ls-1] = chi[ss+Ls-1] + MooeeInvDag_shift_norm[Ls-1]*tmp2_spProj; | ||||
|  | ||||
|       // Apply L^{-dag} | ||||
|       for(int s=Ls-2; s>=0; s--){ | ||||
|         chi[ss+s] = chi[ss+s] - this->lee[s]*tmp1; | ||||
|         spProj5p(tmp1, chi[ss+s]); | ||||
|         chi[ss+s] = chi[ss+s] + MooeeInvDag_shift_norm[s]*tmp2_spProj; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->MooeeInvTime += usecond(); | ||||
|   } | ||||
|  | ||||
|   #ifdef MOBIUS_EOFA_DPERP_CACHE | ||||
|  | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplD); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplD); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplD); | ||||
|  | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplDF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplDF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplDF); | ||||
|  | ||||
|   #endif | ||||
|  | ||||
| }} | ||||
							
								
								
									
										184
									
								
								lib/qcd/action/fermion/MobiusEOFAFermiondense.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								lib/qcd/action/fermion/MobiusEOFAFermiondense.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/MobiusEOFAFermiondense.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid_Eigen_Dense.h> | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/MobiusEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|   /* | ||||
|   * Dense matrix versions of routines | ||||
|   */ | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInv(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     this->MooeeInternal(psi, chi, DaggerNo, InverseYes); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInv_shift(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     this->MooeeInternal(psi, chi, DaggerNo, InverseYes); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     this->MooeeInternal(psi, chi, DaggerYes, InverseYes); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInvDag_shift(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     this->MooeeInternal(psi, chi, DaggerYes, InverseYes); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv) | ||||
|   { | ||||
|     int Ls = this->Ls; | ||||
|     int LLs = psi._grid->_rdimensions[0]; | ||||
|     int vol = psi._grid->oSites()/LLs; | ||||
|  | ||||
|     int pm      = this->pm; | ||||
|     RealD shift = this->shift; | ||||
|     RealD alpha = this->alpha; | ||||
|     RealD k     = this->k; | ||||
|     RealD mq1   = this->mq1; | ||||
|  | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     assert(Ls==LLs); | ||||
|  | ||||
|     Eigen::MatrixXd Pplus  = Eigen::MatrixXd::Zero(Ls,Ls); | ||||
|     Eigen::MatrixXd Pminus = Eigen::MatrixXd::Zero(Ls,Ls); | ||||
|  | ||||
|     for(int s=0;s<Ls;s++){ | ||||
|         Pplus(s,s)  = this->bee[s]; | ||||
|         Pminus(s,s) = this->bee[s]; | ||||
|     } | ||||
|  | ||||
|     for(int s=0; s<Ls-1; s++){ | ||||
|         Pminus(s,s+1) = -this->cee[s]; | ||||
|     } | ||||
|  | ||||
|     for(int s=0; s<Ls-1; s++){ | ||||
|         Pplus(s+1,s) = -this->cee[s+1]; | ||||
|     } | ||||
|     Pplus (0,Ls-1) = mq1*this->cee[0]; | ||||
|     Pminus(Ls-1,0) = mq1*this->cee[Ls-1]; | ||||
|  | ||||
|     if(shift != 0.0){ | ||||
|       Coeff_t N = 2.0 * ( std::pow(alpha+1.0,Ls) + mq1*std::pow(alpha-1.0,Ls) ); | ||||
|       for(int s=0; s<Ls; ++s){ | ||||
|         if(pm == 1){ Pplus(s,Ls-1) += shift * k * N * std::pow(-1.0,s) * std::pow(alpha-1.0,s) / std::pow(alpha+1.0,Ls+s+1); } | ||||
|         else{ Pminus(Ls-1-s,Ls-1) -= shift * k * N * std::pow(-1.0,s) * std::pow(alpha-1.0,s) / std::pow(alpha+1.0,Ls+s+1); } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     Eigen::MatrixXd PplusMat ; | ||||
|     Eigen::MatrixXd PminusMat; | ||||
|  | ||||
|     if(inv){ | ||||
|       PplusMat  = Pplus.inverse(); | ||||
|       PminusMat = Pminus.inverse(); | ||||
|     } else { | ||||
|       PplusMat  = Pplus; | ||||
|       PminusMat = Pminus; | ||||
|     } | ||||
|  | ||||
|     if(dag){ | ||||
|       PplusMat.adjointInPlace(); | ||||
|       PminusMat.adjointInPlace(); | ||||
|     } | ||||
|  | ||||
|     // For the non-vectorised s-direction this is simple | ||||
|  | ||||
|     for(auto site=0; site<vol; site++){ | ||||
|  | ||||
|         SiteSpinor     SiteChi; | ||||
|         SiteHalfSpinor SitePplus; | ||||
|         SiteHalfSpinor SitePminus; | ||||
|  | ||||
|         for(int s1=0; s1<Ls; s1++){ | ||||
|             SiteChi = zero; | ||||
|             for(int s2=0; s2<Ls; s2++){ | ||||
|                 int lex2 = s2 + Ls*site; | ||||
|                 if(PplusMat(s1,s2) != 0.0){ | ||||
|                     spProj5p(SitePplus,psi[lex2]); | ||||
|                     accumRecon5p(SiteChi, PplusMat(s1,s2)*SitePplus); | ||||
|                 } | ||||
|                 if(PminusMat(s1,s2) != 0.0){ | ||||
|                     spProj5m(SitePminus, psi[lex2]); | ||||
|                     accumRecon5m(SiteChi, PminusMat(s1,s2)*SitePminus); | ||||
|                 } | ||||
|             } | ||||
|             chi[s1+Ls*site] = SiteChi*0.5; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #ifdef MOBIUS_EOFA_DPERP_DENSE | ||||
|  | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplD); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplD); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplD); | ||||
|  | ||||
|     template void MobiusEOFAFermion<GparityWilsonImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<GparityWilsonImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<WilsonImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<WilsonImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<ZWilsonImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<ZWilsonImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|  | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplDF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplDF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplDF); | ||||
|  | ||||
|     template void MobiusEOFAFermion<GparityWilsonImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<GparityWilsonImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<WilsonImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<WilsonImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<ZWilsonImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<ZWilsonImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|  | ||||
|   #endif | ||||
|  | ||||
| }} | ||||
							
								
								
									
										290
									
								
								lib/qcd/action/fermion/MobiusEOFAFermionssp.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										290
									
								
								lib/qcd/action/fermion/MobiusEOFAFermionssp.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,290 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/MobiusEOFAFermionssp.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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/MobiusEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|   // FIXME -- make a version of these routines with site loop outermost for cache reuse. | ||||
|   // Pminus fowards | ||||
|   // Pplus  backwards | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5D(const FermionField& psi, const FermionField& phi, | ||||
|     FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|   { | ||||
|     Coeff_t one(1.0); | ||||
|     int Ls = this->Ls; | ||||
|     for(int s=0; s<Ls; s++){ | ||||
|       if(s==0) { | ||||
|         axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|         axpby_ssp_pplus (chi, one, chi, lower[s], psi, s, Ls-1); | ||||
|       } else if (s==(Ls-1)) { | ||||
|         axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, 0); | ||||
|         axpby_ssp_pplus (chi, one, chi, lower[s], psi, s, s-1); | ||||
|       } else { | ||||
|         axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|         axpby_ssp_pplus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5D_shift(const FermionField& psi, const FermionField& phi, | ||||
|     FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper, | ||||
|     std::vector<Coeff_t>& shift_coeffs) | ||||
|   { | ||||
|     Coeff_t one(1.0); | ||||
|     int Ls = this->Ls; | ||||
|     for(int s=0; s<Ls; s++){ | ||||
|       if(s==0) { | ||||
|         axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|         axpby_ssp_pplus (chi, one, chi, lower[s], psi, s, Ls-1); | ||||
|       } else if (s==(Ls-1)) { | ||||
|         axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, 0); | ||||
|         axpby_ssp_pplus (chi, one, chi, lower[s], psi, s, s-1); | ||||
|       } else { | ||||
|         axpby_ssp_pminus(chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|         axpby_ssp_pplus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|       } | ||||
|       if(this->pm == 1){ axpby_ssp_pplus(chi, one, chi, shift_coeffs[s], psi, s, Ls-1); } | ||||
|       else{ axpby_ssp_pminus(chi, one, chi, shift_coeffs[s], psi, s, 0); } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5Ddag(const FermionField& psi, const FermionField& phi, | ||||
|     FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|   { | ||||
|     Coeff_t one(1.0); | ||||
|     int Ls = this->Ls; | ||||
|     for(int s=0; s<Ls; s++){ | ||||
|       if(s==0) { | ||||
|         axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|         axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, Ls-1); | ||||
|       } else if (s==(Ls-1)) { | ||||
|         axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, 0); | ||||
|         axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|       } else { | ||||
|         axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|         axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5Ddag_shift(const FermionField& psi, const FermionField& phi, | ||||
|     FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper, | ||||
|     std::vector<Coeff_t>& shift_coeffs) | ||||
|   { | ||||
|     Coeff_t one(1.0); | ||||
|     int Ls = this->Ls; | ||||
|     for(int s=0; s<Ls; s++){ | ||||
|       if(s==0) { | ||||
|         axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|         axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, Ls-1); | ||||
|       } else if (s==(Ls-1)) { | ||||
|         axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, 0); | ||||
|         axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|       } else { | ||||
|         axpby_ssp_pplus (chi, diag[s], phi, upper[s], psi, s, s+1); | ||||
|         axpby_ssp_pminus(chi, one, chi, lower[s], psi, s, s-1); | ||||
|       } | ||||
|       if(this->pm == 1){ axpby_ssp_pplus(chi, one, chi, shift_coeffs[s], psi, Ls-1, s); } | ||||
|       else{ axpby_ssp_pminus(chi, one, chi, shift_coeffs[s], psi, 0, s); } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInv(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     if(this->shift != 0.0){ MooeeInv_shift(psi,chi); return; } | ||||
|  | ||||
|     Coeff_t one(1.0); | ||||
|     Coeff_t czero(0.0); | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|     int Ls = this->Ls; | ||||
|  | ||||
|     // Apply (L^{\prime})^{-1} | ||||
|     axpby_ssp(chi, one, psi, czero, psi, 0, 0);      // chi[0]=psi[0] | ||||
|     for(int s=1; s<Ls; s++){ | ||||
|       axpby_ssp_pplus(chi, one, psi, -this->lee[s-1], chi, s, s-1);// recursion Psi[s] -lee P_+ chi[s-1] | ||||
|     } | ||||
|  | ||||
|     // L_m^{-1} | ||||
|     for(int s=0; s<Ls-1; s++){ // Chi[ee] = 1 - sum[s<Ls-1] -leem[s]P_- chi | ||||
|       axpby_ssp_pminus(chi, one, chi, -this->leem[s], chi, Ls-1, s); | ||||
|     } | ||||
|  | ||||
|     // U_m^{-1} D^{-1} | ||||
|     for(int s=0; s<Ls-1; s++){ | ||||
|       axpby_ssp_pplus(chi, one/this->dee[s], chi, -this->ueem[s]/this->dee[Ls-1], chi, s, Ls-1); | ||||
|     } | ||||
|     axpby_ssp(chi, one/this->dee[Ls-1], chi, czero, chi, Ls-1, Ls-1); | ||||
|  | ||||
|     // Apply U^{-1} | ||||
|     for(int s=Ls-2; s>=0; s--){ | ||||
|       axpby_ssp_pminus(chi, one, chi, -this->uee[s], chi, s, s+1);  // chi[Ls] | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInv_shift(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     Coeff_t one(1.0); | ||||
|     Coeff_t czero(0.0); | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|     int Ls = this->Ls; | ||||
|  | ||||
|     FermionField tmp(psi._grid); | ||||
|  | ||||
|     // Apply (L^{\prime})^{-1} | ||||
|     axpby_ssp(chi, one, psi, czero, psi, 0, 0);      // chi[0]=psi[0] | ||||
|     axpby_ssp(tmp, czero, tmp, this->MooeeInv_shift_lc[0], psi, 0, 0); | ||||
|     for(int s=1; s<Ls; s++){ | ||||
|       axpby_ssp_pplus(chi, one, psi, -this->lee[s-1], chi, s, s-1);// recursion Psi[s] -lee P_+ chi[s-1] | ||||
|       axpby_ssp(tmp, one, tmp, this->MooeeInv_shift_lc[s], psi, 0, s); | ||||
|     } | ||||
|  | ||||
|     // L_m^{-1} | ||||
|     for(int s=0; s<Ls-1; s++){ // Chi[ee] = 1 - sum[s<Ls-1] -leem[s]P_- chi | ||||
|       axpby_ssp_pminus(chi, one, chi, -this->leem[s], chi, Ls-1, s); | ||||
|     } | ||||
|  | ||||
|     // U_m^{-1} D^{-1} | ||||
|     for(int s=0; s<Ls-1; s++){ | ||||
|       axpby_ssp_pplus(chi, one/this->dee[s], chi, -this->ueem[s]/this->dee[Ls-1], chi, s, Ls-1); | ||||
|     } | ||||
|     axpby_ssp(chi, one/this->dee[Ls-1], chi, czero, chi, Ls-1, Ls-1); | ||||
|  | ||||
|     // Apply U^{-1} and add shift term | ||||
|     if(this->pm == 1){ axpby_ssp_pplus(chi, one, chi, this->MooeeInv_shift_norm[Ls-1], tmp, Ls-1, 0); } | ||||
|     else{ axpby_ssp_pminus(chi, one, chi, this->MooeeInv_shift_norm[Ls-1], tmp, Ls-1, 0); } | ||||
|     for(int s=Ls-2; s>=0; s--){ | ||||
|       axpby_ssp_pminus(chi, one, chi, -this->uee[s], chi, s, s+1);  // chi[Ls] | ||||
|       if(this->pm == 1){ axpby_ssp_pplus(chi, one, chi, this->MooeeInv_shift_norm[s], tmp, s, 0); } | ||||
|       else{ axpby_ssp_pminus(chi, one, chi, this->MooeeInv_shift_norm[s], tmp, s, 0); } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     if(this->shift != 0.0){ MooeeInvDag_shift(psi,chi); return; } | ||||
|  | ||||
|     Coeff_t one(1.0); | ||||
|     Coeff_t czero(0.0); | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|     int Ls = this->Ls; | ||||
|  | ||||
|     // Apply (U^{\prime})^{-dagger} | ||||
|     axpby_ssp(chi, one, psi, czero, psi, 0, 0);      // chi[0]=psi[0] | ||||
|     for(int s=1; s<Ls; s++){ | ||||
|       axpby_ssp_pminus(chi, one, psi, -conjugate(this->uee[s-1]), chi, s, s-1); | ||||
|     } | ||||
|  | ||||
|     // U_m^{-\dagger} | ||||
|     for(int s=0; s<Ls-1; s++){ | ||||
|       axpby_ssp_pplus(chi, one, chi, -conjugate(this->ueem[s]), chi, Ls-1, s); | ||||
|     } | ||||
|  | ||||
|     // L_m^{-\dagger} D^{-dagger} | ||||
|     for(int s=0; s<Ls-1; s++){ | ||||
|       axpby_ssp_pminus(chi, one/conjugate(this->dee[s]), chi, -conjugate(this->leem[s]/this->dee[Ls-1]), chi, s, Ls-1); | ||||
|     } | ||||
|     axpby_ssp(chi, one/conjugate(this->dee[Ls-1]), chi, czero, chi, Ls-1, Ls-1); | ||||
|  | ||||
|     // Apply L^{-dagger} | ||||
|     for(int s=Ls-2; s>=0; s--){ | ||||
|       axpby_ssp_pplus(chi, one, chi, -conjugate(this->lee[s]), chi, s, s+1);  // chi[Ls] | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInvDag_shift(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     Coeff_t one(1.0); | ||||
|     Coeff_t czero(0.0); | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|     int Ls = this->Ls; | ||||
|  | ||||
|     FermionField tmp(psi._grid); | ||||
|  | ||||
|     // Apply (U^{\prime})^{-dagger} and accumulate (MooeeInvDag_shift_lc)_{j} \psi_{j} in tmp[0] | ||||
|     axpby_ssp(chi, one, psi, czero, psi, 0, 0);      // chi[0]=psi[0] | ||||
|     axpby_ssp(tmp, czero, tmp, this->MooeeInvDag_shift_lc[0], psi, 0, 0); | ||||
|     for(int s=1; s<Ls; s++){ | ||||
|       axpby_ssp_pminus(chi, one, psi, -conjugate(this->uee[s-1]), chi, s, s-1); | ||||
|       axpby_ssp(tmp, one, tmp, this->MooeeInvDag_shift_lc[s], psi, 0, s); | ||||
|     } | ||||
|  | ||||
|     // U_m^{-\dagger} | ||||
|     for(int s=0; s<Ls-1; s++){ | ||||
|       axpby_ssp_pplus(chi, one, chi, -conjugate(this->ueem[s]), chi, Ls-1, s); | ||||
|     } | ||||
|  | ||||
|     // L_m^{-\dagger} D^{-dagger} | ||||
|     for(int s=0; s<Ls-1; s++){ | ||||
|       axpby_ssp_pminus(chi, one/conjugate(this->dee[s]), chi, -conjugate(this->leem[s]/this->dee[Ls-1]), chi, s, Ls-1); | ||||
|     } | ||||
|     axpby_ssp(chi, one/conjugate(this->dee[Ls-1]), chi, czero, chi, Ls-1, Ls-1); | ||||
|  | ||||
|     // Apply L^{-dagger} and add shift | ||||
|     if(this->pm == 1){ axpby_ssp_pplus(chi, one, chi, this->MooeeInvDag_shift_norm[Ls-1], tmp, Ls-1, 0); } | ||||
|     else{ axpby_ssp_pminus(chi, one, chi, this->MooeeInvDag_shift_norm[Ls-1], tmp, Ls-1, 0); } | ||||
|     for(int s=Ls-2; s>=0; s--){ | ||||
|       axpby_ssp_pplus(chi, one, chi, -conjugate(this->lee[s]), chi, s, s+1);  // chi[Ls] | ||||
|       if(this->pm == 1){ axpby_ssp_pplus(chi, one, chi, this->MooeeInvDag_shift_norm[s], tmp, s, 0); } | ||||
|       else{ axpby_ssp_pminus(chi, one, chi, this->MooeeInvDag_shift_norm[s], tmp, s, 0); } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #ifdef MOBIUS_EOFA_DPERP_LINALG | ||||
|  | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplD); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplD); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplD); | ||||
|  | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(WilsonImplDF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(GparityWilsonImplDF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZWilsonImplDF); | ||||
|  | ||||
|   #endif | ||||
|  | ||||
| }} | ||||
							
								
								
									
										983
									
								
								lib/qcd/action/fermion/MobiusEOFAFermionvec.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										983
									
								
								lib/qcd/action/fermion/MobiusEOFAFermionvec.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,983 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/MobiusEOFAFermionvec.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| 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: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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/MobiusEOFAFermion.h> | ||||
|  | ||||
| namespace Grid { | ||||
| namespace QCD { | ||||
|  | ||||
|   /* | ||||
|   * Dense matrix versions of routines | ||||
|   */ | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInv(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     this->MooeeInternal(psi, chi, DaggerNo, InverseYes); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInv_shift(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     this->MooeeInternal(psi, chi, DaggerNo, InverseYes); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     this->MooeeInternal(psi, chi, DaggerYes, InverseYes); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInvDag_shift(const FermionField& psi, FermionField& chi) | ||||
|   { | ||||
|     this->MooeeInternal(psi, chi, DaggerYes, InverseYes); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5D(const FermionField& psi, const FermionField& phi, | ||||
|     FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|   { | ||||
|     GridBase* grid  = psi._grid; | ||||
|     int Ls          = this->Ls; | ||||
|     int LLs         = grid->_rdimensions[0]; | ||||
|     const int nsimd = Simd::Nsimd(); | ||||
|  | ||||
|     Vector<iSinglet<Simd>> u(LLs); | ||||
|     Vector<iSinglet<Simd>> l(LLs); | ||||
|     Vector<iSinglet<Simd>> d(LLs); | ||||
|  | ||||
|     assert(Ls/LLs == nsimd); | ||||
|     assert(phi.checkerboard == psi.checkerboard); | ||||
|  | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     // just directly address via type pun | ||||
|     typedef typename Simd::scalar_type scalar_type; | ||||
|     scalar_type* u_p = (scalar_type*) &u[0]; | ||||
|     scalar_type* l_p = (scalar_type*) &l[0]; | ||||
|     scalar_type* d_p = (scalar_type*) &d[0]; | ||||
|  | ||||
|     for(int o=0; o<LLs; o++){ // outer | ||||
|     for(int i=0; i<nsimd; i++){ //inner | ||||
|       int s   = o + i*LLs; | ||||
|       int ss  = o*nsimd + i; | ||||
|       u_p[ss] = upper[s]; | ||||
|       l_p[ss] = lower[s]; | ||||
|       d_p[ss] = diag[s]; | ||||
|     }} | ||||
|  | ||||
|     this->M5Dcalls++; | ||||
|     this->M5Dtime -= usecond(); | ||||
|  | ||||
|     assert(Nc == 3); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=LLs){ // adds LLs | ||||
|  | ||||
|       #if 0 | ||||
|  | ||||
|         alignas(64) SiteHalfSpinor hp; | ||||
|         alignas(64) SiteHalfSpinor hm; | ||||
|         alignas(64) SiteSpinor fp; | ||||
|         alignas(64) SiteSpinor fm; | ||||
|  | ||||
|         for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|           int vp = (v+1)%LLs; | ||||
|           int vm = (v+LLs-1)%LLs; | ||||
|  | ||||
|           spProj5m(hp, psi[ss+vp]); | ||||
|           spProj5p(hm, psi[ss+vm]); | ||||
|  | ||||
|           if (vp <= v){ rotate(hp, hp, 1); } | ||||
|           if (vm >= v){ rotate(hm, hm, nsimd-1); } | ||||
|  | ||||
|           hp = 0.5*hp; | ||||
|           hm = 0.5*hm; | ||||
|  | ||||
|           spRecon5m(fp, hp); | ||||
|           spRecon5p(fm, hm); | ||||
|  | ||||
|           chi[ss+v] = d[v]*phi[ss+v]; | ||||
|           chi[ss+v] = chi[ss+v] + u[v]*fp; | ||||
|           chi[ss+v] = chi[ss+v] + l[v]*fm; | ||||
|  | ||||
|         } | ||||
|  | ||||
|       #else | ||||
|  | ||||
|         for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|           vprefetch(psi[ss+v+LLs]); | ||||
|  | ||||
|           int vp = (v == LLs-1) ? 0     : v+1; | ||||
|           int vm = (v == 0)     ? LLs-1 : v-1; | ||||
|  | ||||
|           Simd hp_00 = psi[ss+vp]()(2)(0); | ||||
|           Simd hp_01 = psi[ss+vp]()(2)(1); | ||||
|           Simd hp_02 = psi[ss+vp]()(2)(2); | ||||
|           Simd hp_10 = psi[ss+vp]()(3)(0); | ||||
|           Simd hp_11 = psi[ss+vp]()(3)(1); | ||||
|           Simd hp_12 = psi[ss+vp]()(3)(2); | ||||
|  | ||||
|           Simd hm_00 = psi[ss+vm]()(0)(0); | ||||
|           Simd hm_01 = psi[ss+vm]()(0)(1); | ||||
|           Simd hm_02 = psi[ss+vm]()(0)(2); | ||||
|           Simd hm_10 = psi[ss+vm]()(1)(0); | ||||
|           Simd hm_11 = psi[ss+vm]()(1)(1); | ||||
|           Simd hm_12 = psi[ss+vm]()(1)(2); | ||||
|  | ||||
|           if(vp <= v){ | ||||
|             hp_00.v = Optimization::Rotate::tRotate<2>(hp_00.v); | ||||
|             hp_01.v = Optimization::Rotate::tRotate<2>(hp_01.v); | ||||
|             hp_02.v = Optimization::Rotate::tRotate<2>(hp_02.v); | ||||
|             hp_10.v = Optimization::Rotate::tRotate<2>(hp_10.v); | ||||
|             hp_11.v = Optimization::Rotate::tRotate<2>(hp_11.v); | ||||
|             hp_12.v = Optimization::Rotate::tRotate<2>(hp_12.v); | ||||
|           } | ||||
|  | ||||
|           if(vm >= v){ | ||||
|             hm_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_00.v); | ||||
|             hm_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_01.v); | ||||
|             hm_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_02.v); | ||||
|             hm_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_10.v); | ||||
|             hm_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_11.v); | ||||
|             hm_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_12.v); | ||||
|           } | ||||
|  | ||||
|           // Can force these to real arithmetic and save 2x. | ||||
|           Simd p_00 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_00); | ||||
|           Simd p_01 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_01); | ||||
|           Simd p_02 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_02); | ||||
|           Simd p_10 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_10); | ||||
|           Simd p_11 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_11); | ||||
|           Simd p_12 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_12); | ||||
|           Simd p_20 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_00); | ||||
|           Simd p_21 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_01); | ||||
|           Simd p_22 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_02); | ||||
|           Simd p_30 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_10); | ||||
|           Simd p_31 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_11); | ||||
|           Simd p_32 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_12); | ||||
|  | ||||
|           vstream(chi[ss+v]()(0)(0), p_00); | ||||
|           vstream(chi[ss+v]()(0)(1), p_01); | ||||
|           vstream(chi[ss+v]()(0)(2), p_02); | ||||
|           vstream(chi[ss+v]()(1)(0), p_10); | ||||
|           vstream(chi[ss+v]()(1)(1), p_11); | ||||
|           vstream(chi[ss+v]()(1)(2), p_12); | ||||
|           vstream(chi[ss+v]()(2)(0), p_20); | ||||
|           vstream(chi[ss+v]()(2)(1), p_21); | ||||
|           vstream(chi[ss+v]()(2)(2), p_22); | ||||
|           vstream(chi[ss+v]()(3)(0), p_30); | ||||
|           vstream(chi[ss+v]()(3)(1), p_31); | ||||
|           vstream(chi[ss+v]()(3)(2), p_32); | ||||
|         } | ||||
|  | ||||
|       #endif | ||||
|     } | ||||
|  | ||||
|     this->M5Dtime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5D_shift(const FermionField& psi, const FermionField& phi, | ||||
|     FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper, | ||||
|     std::vector<Coeff_t>& shift_coeffs) | ||||
|   { | ||||
|     #if 0 | ||||
|  | ||||
|       this->M5D(psi, phi, chi, lower, diag, upper); | ||||
|  | ||||
|       // FIXME: possible gain from vectorizing shift operation as well? | ||||
|       Coeff_t one(1.0); | ||||
|       int Ls = this->Ls; | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         if(this->pm == 1){ axpby_ssp_pplus(chi, one, chi, shift_coeffs[s], psi, s, Ls-1); } | ||||
|         else{ axpby_ssp_pminus(chi, one, chi, shift_coeffs[s], psi, s, 0); } | ||||
|       } | ||||
|  | ||||
|     #else | ||||
|  | ||||
|       GridBase* grid  = psi._grid; | ||||
|       int Ls          = this->Ls; | ||||
|       int LLs         = grid->_rdimensions[0]; | ||||
|       const int nsimd = Simd::Nsimd(); | ||||
|  | ||||
|       Vector<iSinglet<Simd>> u(LLs); | ||||
|       Vector<iSinglet<Simd>> l(LLs); | ||||
|       Vector<iSinglet<Simd>> d(LLs); | ||||
|       Vector<iSinglet<Simd>> s(LLs); | ||||
|  | ||||
|       assert(Ls/LLs == nsimd); | ||||
|       assert(phi.checkerboard == psi.checkerboard); | ||||
|  | ||||
|       chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|       // just directly address via type pun | ||||
|       typedef typename Simd::scalar_type scalar_type; | ||||
|       scalar_type* u_p = (scalar_type*) &u[0]; | ||||
|       scalar_type* l_p = (scalar_type*) &l[0]; | ||||
|       scalar_type* d_p = (scalar_type*) &d[0]; | ||||
|       scalar_type* s_p = (scalar_type*) &s[0]; | ||||
|  | ||||
|       for(int o=0; o<LLs; o++){ // outer | ||||
|       for(int i=0; i<nsimd; i++){ //inner | ||||
|         int s   = o + i*LLs; | ||||
|         int ss  = o*nsimd + i; | ||||
|         u_p[ss] = upper[s]; | ||||
|         l_p[ss] = lower[s]; | ||||
|         d_p[ss] = diag[s]; | ||||
|         s_p[ss] = shift_coeffs[s]; | ||||
|       }} | ||||
|  | ||||
|       this->M5Dcalls++; | ||||
|       this->M5Dtime -= usecond(); | ||||
|  | ||||
|       assert(Nc == 3); | ||||
|  | ||||
|       parallel_for(int ss=0; ss<grid->oSites(); ss+=LLs){ // adds LLs | ||||
|  | ||||
|         int vs     = (this->pm == 1) ? LLs-1 : 0; | ||||
|         Simd hs_00 = (this->pm == 1) ? psi[ss+vs]()(2)(0) : psi[ss+vs]()(0)(0); | ||||
|         Simd hs_01 = (this->pm == 1) ? psi[ss+vs]()(2)(1) : psi[ss+vs]()(0)(1); | ||||
|         Simd hs_02 = (this->pm == 1) ? psi[ss+vs]()(2)(2) : psi[ss+vs]()(0)(2); | ||||
|         Simd hs_10 = (this->pm == 1) ? psi[ss+vs]()(3)(0) : psi[ss+vs]()(1)(0); | ||||
|         Simd hs_11 = (this->pm == 1) ? psi[ss+vs]()(3)(1) : psi[ss+vs]()(1)(1); | ||||
|         Simd hs_12 = (this->pm == 1) ? psi[ss+vs]()(3)(2) : psi[ss+vs]()(1)(2); | ||||
|  | ||||
|         for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|           vprefetch(psi[ss+v+LLs]); | ||||
|  | ||||
|           int vp = (v == LLs-1) ? 0     : v+1; | ||||
|           int vm = (v == 0)     ? LLs-1 : v-1; | ||||
|  | ||||
|           Simd hp_00 = psi[ss+vp]()(2)(0); | ||||
|           Simd hp_01 = psi[ss+vp]()(2)(1); | ||||
|           Simd hp_02 = psi[ss+vp]()(2)(2); | ||||
|           Simd hp_10 = psi[ss+vp]()(3)(0); | ||||
|           Simd hp_11 = psi[ss+vp]()(3)(1); | ||||
|           Simd hp_12 = psi[ss+vp]()(3)(2); | ||||
|  | ||||
|           Simd hm_00 = psi[ss+vm]()(0)(0); | ||||
|           Simd hm_01 = psi[ss+vm]()(0)(1); | ||||
|           Simd hm_02 = psi[ss+vm]()(0)(2); | ||||
|           Simd hm_10 = psi[ss+vm]()(1)(0); | ||||
|           Simd hm_11 = psi[ss+vm]()(1)(1); | ||||
|           Simd hm_12 = psi[ss+vm]()(1)(2); | ||||
|  | ||||
|           if(vp <= v){ | ||||
|             hp_00.v = Optimization::Rotate::tRotate<2>(hp_00.v); | ||||
|             hp_01.v = Optimization::Rotate::tRotate<2>(hp_01.v); | ||||
|             hp_02.v = Optimization::Rotate::tRotate<2>(hp_02.v); | ||||
|             hp_10.v = Optimization::Rotate::tRotate<2>(hp_10.v); | ||||
|             hp_11.v = Optimization::Rotate::tRotate<2>(hp_11.v); | ||||
|             hp_12.v = Optimization::Rotate::tRotate<2>(hp_12.v); | ||||
|           } | ||||
|  | ||||
|           if(this->pm == 1 && vs <= v){ | ||||
|             hs_00.v = Optimization::Rotate::tRotate<2>(hs_00.v); | ||||
|             hs_01.v = Optimization::Rotate::tRotate<2>(hs_01.v); | ||||
|             hs_02.v = Optimization::Rotate::tRotate<2>(hs_02.v); | ||||
|             hs_10.v = Optimization::Rotate::tRotate<2>(hs_10.v); | ||||
|             hs_11.v = Optimization::Rotate::tRotate<2>(hs_11.v); | ||||
|             hs_12.v = Optimization::Rotate::tRotate<2>(hs_12.v); | ||||
|           } | ||||
|  | ||||
|           if(vm >= v){ | ||||
|             hm_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_00.v); | ||||
|             hm_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_01.v); | ||||
|             hm_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_02.v); | ||||
|             hm_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_10.v); | ||||
|             hm_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_11.v); | ||||
|             hm_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_12.v); | ||||
|           } | ||||
|  | ||||
|           if(this->pm == -1 && vs >= v){ | ||||
|             hs_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_00.v); | ||||
|             hs_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_01.v); | ||||
|             hs_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_02.v); | ||||
|             hs_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_10.v); | ||||
|             hs_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_11.v); | ||||
|             hs_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_12.v); | ||||
|           } | ||||
|  | ||||
|           // Can force these to real arithmetic and save 2x. | ||||
|           Simd p_00 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_00) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_00) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_00); | ||||
|           Simd p_01 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_01) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_01) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_01); | ||||
|           Simd p_02 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_02) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_02) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_02); | ||||
|           Simd p_10 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_10) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_10) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_10); | ||||
|           Simd p_11 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_11) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_11) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_11); | ||||
|           Simd p_12 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_12) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_12) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_12); | ||||
|           Simd p_20 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_00) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_00) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_00); | ||||
|           Simd p_21 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_01) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_01) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_01); | ||||
|           Simd p_22 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_02) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_02) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_02); | ||||
|           Simd p_30 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_10) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_10) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_10); | ||||
|           Simd p_31 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_11) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_11) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_11); | ||||
|           Simd p_32 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_12) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_12) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_12); | ||||
|  | ||||
|           vstream(chi[ss+v]()(0)(0), p_00); | ||||
|           vstream(chi[ss+v]()(0)(1), p_01); | ||||
|           vstream(chi[ss+v]()(0)(2), p_02); | ||||
|           vstream(chi[ss+v]()(1)(0), p_10); | ||||
|           vstream(chi[ss+v]()(1)(1), p_11); | ||||
|           vstream(chi[ss+v]()(1)(2), p_12); | ||||
|           vstream(chi[ss+v]()(2)(0), p_20); | ||||
|           vstream(chi[ss+v]()(2)(1), p_21); | ||||
|           vstream(chi[ss+v]()(2)(2), p_22); | ||||
|           vstream(chi[ss+v]()(3)(0), p_30); | ||||
|           vstream(chi[ss+v]()(3)(1), p_31); | ||||
|           vstream(chi[ss+v]()(3)(2), p_32); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       this->M5Dtime += usecond(); | ||||
|  | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5Ddag(const FermionField& psi, const FermionField& phi, | ||||
|     FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper) | ||||
|   { | ||||
|     GridBase* grid = psi._grid; | ||||
|     int Ls  = this->Ls; | ||||
|     int LLs = grid->_rdimensions[0]; | ||||
|     int nsimd = Simd::Nsimd(); | ||||
|  | ||||
|     Vector<iSinglet<Simd>> u(LLs); | ||||
|     Vector<iSinglet<Simd>> l(LLs); | ||||
|     Vector<iSinglet<Simd>> d(LLs); | ||||
|  | ||||
|     assert(Ls/LLs == nsimd); | ||||
|     assert(phi.checkerboard == psi.checkerboard); | ||||
|  | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     // just directly address via type pun | ||||
|     typedef typename Simd::scalar_type scalar_type; | ||||
|     scalar_type* u_p = (scalar_type*) &u[0]; | ||||
|     scalar_type* l_p = (scalar_type*) &l[0]; | ||||
|     scalar_type* d_p = (scalar_type*) &d[0]; | ||||
|  | ||||
|     for(int o=0; o<LLs; o++){ // outer | ||||
|     for(int i=0; i<nsimd; i++){ //inner | ||||
|       int s  = o + i*LLs; | ||||
|       int ss = o*nsimd + i; | ||||
|       u_p[ss] = upper[s]; | ||||
|       l_p[ss] = lower[s]; | ||||
|       d_p[ss] = diag[s]; | ||||
|     }} | ||||
|  | ||||
|     this->M5Dcalls++; | ||||
|     this->M5Dtime -= usecond(); | ||||
|  | ||||
|     parallel_for(int ss=0; ss<grid->oSites(); ss+=LLs){ // adds LLs | ||||
|  | ||||
|       #if 0 | ||||
|  | ||||
|         alignas(64) SiteHalfSpinor hp; | ||||
|         alignas(64) SiteHalfSpinor hm; | ||||
|         alignas(64) SiteSpinor fp; | ||||
|         alignas(64) SiteSpinor fm; | ||||
|  | ||||
|         for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|           int vp = (v+1)%LLs; | ||||
|           int vm = (v+LLs-1)%LLs; | ||||
|  | ||||
|           spProj5p(hp, psi[ss+vp]); | ||||
|           spProj5m(hm, psi[ss+vm]); | ||||
|  | ||||
|           if(vp <= v){ rotate(hp, hp, 1); } | ||||
|           if(vm >= v){ rotate(hm, hm, nsimd-1); } | ||||
|  | ||||
|           hp = hp*0.5; | ||||
|           hm = hm*0.5; | ||||
|           spRecon5p(fp, hp); | ||||
|           spRecon5m(fm, hm); | ||||
|  | ||||
|           chi[ss+v] = d[v]*phi[ss+v]+u[v]*fp; | ||||
|           chi[ss+v] = chi[ss+v]     +l[v]*fm; | ||||
|  | ||||
|         } | ||||
|  | ||||
|       #else | ||||
|  | ||||
|         for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|           vprefetch(psi[ss+v+LLs]); | ||||
|  | ||||
|           int vp = (v == LLs-1) ? 0     : v+1; | ||||
|           int vm = (v == 0    ) ? LLs-1 : v-1; | ||||
|  | ||||
|           Simd hp_00 = psi[ss+vp]()(0)(0); | ||||
|           Simd hp_01 = psi[ss+vp]()(0)(1); | ||||
|           Simd hp_02 = psi[ss+vp]()(0)(2); | ||||
|           Simd hp_10 = psi[ss+vp]()(1)(0); | ||||
|           Simd hp_11 = psi[ss+vp]()(1)(1); | ||||
|           Simd hp_12 = psi[ss+vp]()(1)(2); | ||||
|  | ||||
|           Simd hm_00 = psi[ss+vm]()(2)(0); | ||||
|           Simd hm_01 = psi[ss+vm]()(2)(1); | ||||
|           Simd hm_02 = psi[ss+vm]()(2)(2); | ||||
|           Simd hm_10 = psi[ss+vm]()(3)(0); | ||||
|           Simd hm_11 = psi[ss+vm]()(3)(1); | ||||
|           Simd hm_12 = psi[ss+vm]()(3)(2); | ||||
|  | ||||
|           if (vp <= v){ | ||||
|             hp_00.v = Optimization::Rotate::tRotate<2>(hp_00.v); | ||||
|             hp_01.v = Optimization::Rotate::tRotate<2>(hp_01.v); | ||||
|             hp_02.v = Optimization::Rotate::tRotate<2>(hp_02.v); | ||||
|             hp_10.v = Optimization::Rotate::tRotate<2>(hp_10.v); | ||||
|             hp_11.v = Optimization::Rotate::tRotate<2>(hp_11.v); | ||||
|             hp_12.v = Optimization::Rotate::tRotate<2>(hp_12.v); | ||||
|           } | ||||
|  | ||||
|           if(vm >= v){ | ||||
|             hm_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_00.v); | ||||
|             hm_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_01.v); | ||||
|             hm_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_02.v); | ||||
|             hm_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_10.v); | ||||
|             hm_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_11.v); | ||||
|             hm_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_12.v); | ||||
|           } | ||||
|  | ||||
|           Simd p_00 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_00); | ||||
|           Simd p_01 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_01); | ||||
|           Simd p_02 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_02); | ||||
|           Simd p_10 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_10); | ||||
|           Simd p_11 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_11); | ||||
|           Simd p_12 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_12); | ||||
|           Simd p_20 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_00); | ||||
|           Simd p_21 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_01); | ||||
|           Simd p_22 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_02); | ||||
|           Simd p_30 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_10); | ||||
|           Simd p_31 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_11); | ||||
|           Simd p_32 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_12); | ||||
|  | ||||
|           vstream(chi[ss+v]()(0)(0), p_00); | ||||
|           vstream(chi[ss+v]()(0)(1), p_01); | ||||
|           vstream(chi[ss+v]()(0)(2), p_02); | ||||
|           vstream(chi[ss+v]()(1)(0), p_10); | ||||
|           vstream(chi[ss+v]()(1)(1), p_11); | ||||
|           vstream(chi[ss+v]()(1)(2), p_12); | ||||
|           vstream(chi[ss+v]()(2)(0), p_20); | ||||
|           vstream(chi[ss+v]()(2)(1), p_21); | ||||
|           vstream(chi[ss+v]()(2)(2), p_22); | ||||
|           vstream(chi[ss+v]()(3)(0), p_30); | ||||
|           vstream(chi[ss+v]()(3)(1), p_31); | ||||
|           vstream(chi[ss+v]()(3)(2), p_32); | ||||
|  | ||||
|         } | ||||
|  | ||||
|       #endif | ||||
|  | ||||
|     } | ||||
|  | ||||
|     this->M5Dtime += usecond(); | ||||
|   } | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::M5Ddag_shift(const FermionField& psi, const FermionField& phi, | ||||
|     FermionField& chi, std::vector<Coeff_t>& lower, std::vector<Coeff_t>& diag, std::vector<Coeff_t>& upper, | ||||
|     std::vector<Coeff_t>& shift_coeffs) | ||||
|   { | ||||
|     #if 0 | ||||
|  | ||||
|       this->M5Ddag(psi, phi, chi, lower, diag, upper); | ||||
|  | ||||
|       // FIXME: possible gain from vectorizing shift operation as well? | ||||
|       Coeff_t one(1.0); | ||||
|       int Ls = this->Ls; | ||||
|       for(int s=0; s<Ls; s++){ | ||||
|         if(this->pm == 1){ axpby_ssp_pplus(chi, one, chi, shift_coeffs[s], psi, Ls-1, s); } | ||||
|         else{ axpby_ssp_pminus(chi, one, chi, shift_coeffs[s], psi, 0, s); } | ||||
|       } | ||||
|  | ||||
|     #else | ||||
|  | ||||
|       GridBase* grid = psi._grid; | ||||
|       int Ls  = this->Ls; | ||||
|       int LLs = grid->_rdimensions[0]; | ||||
|       int nsimd = Simd::Nsimd(); | ||||
|  | ||||
|       Vector<iSinglet<Simd>> u(LLs); | ||||
|       Vector<iSinglet<Simd>> l(LLs); | ||||
|       Vector<iSinglet<Simd>> d(LLs); | ||||
|       Vector<iSinglet<Simd>> s(LLs); | ||||
|  | ||||
|       assert(Ls/LLs == nsimd); | ||||
|       assert(phi.checkerboard == psi.checkerboard); | ||||
|  | ||||
|       chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|       // just directly address via type pun | ||||
|       typedef typename Simd::scalar_type scalar_type; | ||||
|       scalar_type* u_p = (scalar_type*) &u[0]; | ||||
|       scalar_type* l_p = (scalar_type*) &l[0]; | ||||
|       scalar_type* d_p = (scalar_type*) &d[0]; | ||||
|       scalar_type* s_p = (scalar_type*) &s[0]; | ||||
|  | ||||
|       for(int o=0; o<LLs; o++){ // outer | ||||
|       for(int i=0; i<nsimd; i++){ //inner | ||||
|         int s  = o + i*LLs; | ||||
|         int ss = o*nsimd + i; | ||||
|         u_p[ss] = upper[s]; | ||||
|         l_p[ss] = lower[s]; | ||||
|         d_p[ss] = diag[s]; | ||||
|         s_p[ss] = shift_coeffs[s]; | ||||
|       }} | ||||
|  | ||||
|       this->M5Dcalls++; | ||||
|       this->M5Dtime -= usecond(); | ||||
|  | ||||
|       parallel_for(int ss=0; ss<grid->oSites(); ss+=LLs){ // adds LLs | ||||
|  | ||||
|         int vs     = (this->pm == 1) ? LLs-1 : 0; | ||||
|         Simd hs_00 = (this->pm == 1) ? psi[ss+vs]()(0)(0) : psi[ss+vs]()(2)(0); | ||||
|         Simd hs_01 = (this->pm == 1) ? psi[ss+vs]()(0)(1) : psi[ss+vs]()(2)(1); | ||||
|         Simd hs_02 = (this->pm == 1) ? psi[ss+vs]()(0)(2) : psi[ss+vs]()(2)(2); | ||||
|         Simd hs_10 = (this->pm == 1) ? psi[ss+vs]()(1)(0) : psi[ss+vs]()(3)(0); | ||||
|         Simd hs_11 = (this->pm == 1) ? psi[ss+vs]()(1)(1) : psi[ss+vs]()(3)(1); | ||||
|         Simd hs_12 = (this->pm == 1) ? psi[ss+vs]()(1)(2) : psi[ss+vs]()(3)(2); | ||||
|  | ||||
|         for(int v=0; v<LLs; v++){ | ||||
|  | ||||
|           vprefetch(psi[ss+v+LLs]); | ||||
|  | ||||
|           int vp = (v == LLs-1) ? 0     : v+1; | ||||
|           int vm = (v == 0    ) ? LLs-1 : v-1; | ||||
|  | ||||
|           Simd hp_00 = psi[ss+vp]()(0)(0); | ||||
|           Simd hp_01 = psi[ss+vp]()(0)(1); | ||||
|           Simd hp_02 = psi[ss+vp]()(0)(2); | ||||
|           Simd hp_10 = psi[ss+vp]()(1)(0); | ||||
|           Simd hp_11 = psi[ss+vp]()(1)(1); | ||||
|           Simd hp_12 = psi[ss+vp]()(1)(2); | ||||
|  | ||||
|           Simd hm_00 = psi[ss+vm]()(2)(0); | ||||
|           Simd hm_01 = psi[ss+vm]()(2)(1); | ||||
|           Simd hm_02 = psi[ss+vm]()(2)(2); | ||||
|           Simd hm_10 = psi[ss+vm]()(3)(0); | ||||
|           Simd hm_11 = psi[ss+vm]()(3)(1); | ||||
|           Simd hm_12 = psi[ss+vm]()(3)(2); | ||||
|  | ||||
|           if (vp <= v){ | ||||
|             hp_00.v = Optimization::Rotate::tRotate<2>(hp_00.v); | ||||
|             hp_01.v = Optimization::Rotate::tRotate<2>(hp_01.v); | ||||
|             hp_02.v = Optimization::Rotate::tRotate<2>(hp_02.v); | ||||
|             hp_10.v = Optimization::Rotate::tRotate<2>(hp_10.v); | ||||
|             hp_11.v = Optimization::Rotate::tRotate<2>(hp_11.v); | ||||
|             hp_12.v = Optimization::Rotate::tRotate<2>(hp_12.v); | ||||
|           } | ||||
|  | ||||
|           if(this->pm == 1 && vs <= v){ | ||||
|             hs_00.v = Optimization::Rotate::tRotate<2>(hs_00.v); | ||||
|             hs_01.v = Optimization::Rotate::tRotate<2>(hs_01.v); | ||||
|             hs_02.v = Optimization::Rotate::tRotate<2>(hs_02.v); | ||||
|             hs_10.v = Optimization::Rotate::tRotate<2>(hs_10.v); | ||||
|             hs_11.v = Optimization::Rotate::tRotate<2>(hs_11.v); | ||||
|             hs_12.v = Optimization::Rotate::tRotate<2>(hs_12.v); | ||||
|           } | ||||
|  | ||||
|           if(vm >= v){ | ||||
|             hm_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_00.v); | ||||
|             hm_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_01.v); | ||||
|             hm_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_02.v); | ||||
|             hm_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_10.v); | ||||
|             hm_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_11.v); | ||||
|             hm_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_12.v); | ||||
|           } | ||||
|  | ||||
|           if(this->pm == -1 && vs >= v){ | ||||
|             hs_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_00.v); | ||||
|             hs_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_01.v); | ||||
|             hs_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_02.v); | ||||
|             hs_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_10.v); | ||||
|             hs_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_11.v); | ||||
|             hs_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hs_12.v); | ||||
|           } | ||||
|  | ||||
|           Simd p_00 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_00) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_00) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_00); | ||||
|           Simd p_01 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_01) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_01) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_01); | ||||
|           Simd p_02 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_02) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_02) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_02); | ||||
|           Simd p_10 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_10) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_10) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_10); | ||||
|           Simd p_11 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_11) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_11) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_11); | ||||
|           Simd p_12 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_12) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_12) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(), hp_12); | ||||
|           Simd p_20 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_00) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_00) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_00); | ||||
|           Simd p_21 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_01) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_01) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_01); | ||||
|           Simd p_22 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_02) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_02) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_02); | ||||
|           Simd p_30 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_10) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_10) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_10); | ||||
|           Simd p_31 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_11) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_11) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_11); | ||||
|           Simd p_32 = (this->pm == 1) ? switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_12) | ||||
|                                       : switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(), hm_12) | ||||
|                                                                                                  + switcheroo<Coeff_t>::mult(s[v]()()(), hs_12); | ||||
|  | ||||
|           vstream(chi[ss+v]()(0)(0), p_00); | ||||
|           vstream(chi[ss+v]()(0)(1), p_01); | ||||
|           vstream(chi[ss+v]()(0)(2), p_02); | ||||
|           vstream(chi[ss+v]()(1)(0), p_10); | ||||
|           vstream(chi[ss+v]()(1)(1), p_11); | ||||
|           vstream(chi[ss+v]()(1)(2), p_12); | ||||
|           vstream(chi[ss+v]()(2)(0), p_20); | ||||
|           vstream(chi[ss+v]()(2)(1), p_21); | ||||
|           vstream(chi[ss+v]()(2)(2), p_22); | ||||
|           vstream(chi[ss+v]()(3)(0), p_30); | ||||
|           vstream(chi[ss+v]()(3)(1), p_31); | ||||
|           vstream(chi[ss+v]()(3)(2), p_32); | ||||
|  | ||||
|         } | ||||
|  | ||||
|       } | ||||
|  | ||||
|       this->M5Dtime += usecond(); | ||||
|  | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   #ifdef AVX512 | ||||
|     #include<simd/Intel512common.h> | ||||
|     #include<simd/Intel512avx.h> | ||||
|     #include<simd/Intel512single.h> | ||||
|   #endif | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInternalAsm(const FermionField& psi, FermionField& chi, | ||||
|     int LLs, int site, Vector<iSinglet<Simd> >& Matp, Vector<iSinglet<Simd> >& Matm) | ||||
|   { | ||||
|     #ifndef AVX512 | ||||
|       { | ||||
|         SiteHalfSpinor BcastP; | ||||
|         SiteHalfSpinor BcastM; | ||||
|         SiteHalfSpinor SiteChiP; | ||||
|         SiteHalfSpinor SiteChiM; | ||||
|  | ||||
|         // Ls*Ls * 2 * 12 * vol flops | ||||
|         for(int s1=0; s1<LLs; s1++){ | ||||
|  | ||||
|           for(int s2=0; s2<LLs; s2++){ | ||||
|           for(int l=0; l < Simd::Nsimd(); l++){ // simd lane | ||||
|  | ||||
|             int s = s2 + l*LLs; | ||||
|             int lex = s2 + LLs*site; | ||||
|  | ||||
|             if( s2==0 && l==0 ){ | ||||
|               SiteChiP=zero; | ||||
|               SiteChiM=zero; | ||||
|             } | ||||
|  | ||||
|             for(int sp=0; sp<2;  sp++){ | ||||
|             for(int co=0; co<Nc; co++){ | ||||
|               vbroadcast(BcastP()(sp)(co), psi[lex]()(sp)(co), l); | ||||
|             }} | ||||
|  | ||||
|             for(int sp=0; sp<2;  sp++){ | ||||
|             for(int co=0; co<Nc; co++){ | ||||
|               vbroadcast(BcastM()(sp)(co), psi[lex]()(sp+2)(co), l); | ||||
|             }} | ||||
|  | ||||
|             for(int sp=0; sp<2;  sp++){ | ||||
|             for(int co=0; co<Nc; co++){ | ||||
|               SiteChiP()(sp)(co) = real_madd(Matp[LLs*s+s1]()()(), BcastP()(sp)(co), SiteChiP()(sp)(co)); // 1100 us. | ||||
|               SiteChiM()(sp)(co) = real_madd(Matm[LLs*s+s1]()()(), BcastM()(sp)(co), SiteChiM()(sp)(co)); // each found by commenting out | ||||
|             }} | ||||
|           }} | ||||
|  | ||||
|           { | ||||
|             int lex = s1 + LLs*site; | ||||
|             for(int sp=0; sp<2;  sp++){ | ||||
|             for(int co=0; co<Nc; co++){ | ||||
|               vstream(chi[lex]()(sp)(co),   SiteChiP()(sp)(co)); | ||||
|               vstream(chi[lex]()(sp+2)(co), SiteChiM()(sp)(co)); | ||||
|             }} | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     #else | ||||
|       { | ||||
|         // pointers | ||||
|         //  MASK_REGS; | ||||
|         #define Chi_00 %%zmm1 | ||||
|         #define Chi_01 %%zmm2 | ||||
|         #define Chi_02 %%zmm3 | ||||
|         #define Chi_10 %%zmm4 | ||||
|         #define Chi_11 %%zmm5 | ||||
|         #define Chi_12 %%zmm6 | ||||
|         #define Chi_20 %%zmm7 | ||||
|         #define Chi_21 %%zmm8 | ||||
|         #define Chi_22 %%zmm9 | ||||
|         #define Chi_30 %%zmm10 | ||||
|         #define Chi_31 %%zmm11 | ||||
|         #define Chi_32 %%zmm12 | ||||
|  | ||||
|         #define BCAST0  %%zmm13 | ||||
|         #define BCAST1  %%zmm14 | ||||
|         #define BCAST2  %%zmm15 | ||||
|         #define BCAST3  %%zmm16 | ||||
|         #define BCAST4  %%zmm17 | ||||
|         #define BCAST5  %%zmm18 | ||||
|         #define BCAST6  %%zmm19 | ||||
|         #define BCAST7  %%zmm20 | ||||
|         #define BCAST8  %%zmm21 | ||||
|         #define BCAST9  %%zmm22 | ||||
|         #define BCAST10 %%zmm23 | ||||
|         #define BCAST11 %%zmm24 | ||||
|  | ||||
|         int incr = LLs*LLs*sizeof(iSinglet<Simd>); | ||||
|  | ||||
|         for(int s1=0; s1<LLs; s1++){ | ||||
|  | ||||
|           for(int s2=0; s2<LLs; s2++){ | ||||
|  | ||||
|             int lex = s2 + LLs*site; | ||||
|             uint64_t a0 = (uint64_t) &Matp[LLs*s2+s1]; // should be cacheable | ||||
|             uint64_t a1 = (uint64_t) &Matm[LLs*s2+s1]; | ||||
|             uint64_t a2 = (uint64_t) &psi[lex]; | ||||
|  | ||||
|             for(int l=0; l<Simd::Nsimd(); l++){ // simd lane | ||||
|  | ||||
|               if((s2+l)==0) { | ||||
|                 asm( | ||||
|                       VPREFETCH1(0,%2)              VPREFETCH1(0,%1) | ||||
|                       VPREFETCH1(12,%2)  	          VPREFETCH1(13,%2) | ||||
|                       VPREFETCH1(14,%2)  	          VPREFETCH1(15,%2) | ||||
|                       VBCASTCDUP(0,%2,BCAST0) | ||||
|                       VBCASTCDUP(1,%2,BCAST1) | ||||
|                       VBCASTCDUP(2,%2,BCAST2) | ||||
|                       VBCASTCDUP(3,%2,BCAST3) | ||||
|                       VBCASTCDUP(4,%2,BCAST4)       VMULMEM(0,%0,BCAST0,Chi_00) | ||||
|                       VBCASTCDUP(5,%2,BCAST5)       VMULMEM(0,%0,BCAST1,Chi_01) | ||||
|                       VBCASTCDUP(6,%2,BCAST6)       VMULMEM(0,%0,BCAST2,Chi_02) | ||||
|                       VBCASTCDUP(7,%2,BCAST7)       VMULMEM(0,%0,BCAST3,Chi_10) | ||||
|                       VBCASTCDUP(8,%2,BCAST8)       VMULMEM(0,%0,BCAST4,Chi_11) | ||||
|                       VBCASTCDUP(9,%2,BCAST9)       VMULMEM(0,%0,BCAST5,Chi_12) | ||||
|                       VBCASTCDUP(10,%2,BCAST10)     VMULMEM(0,%1,BCAST6,Chi_20) | ||||
|                       VBCASTCDUP(11,%2,BCAST11)     VMULMEM(0,%1,BCAST7,Chi_21) | ||||
|                       VMULMEM(0,%1,BCAST8,Chi_22) | ||||
|                       VMULMEM(0,%1,BCAST9,Chi_30) | ||||
|                       VMULMEM(0,%1,BCAST10,Chi_31) | ||||
|                       VMULMEM(0,%1,BCAST11,Chi_32) | ||||
|                       : : "r" (a0), "r" (a1), "r" (a2)                            ); | ||||
|               } else { | ||||
|                 asm( | ||||
|                       VBCASTCDUP(0,%2,BCAST0)   VMADDMEM(0,%0,BCAST0,Chi_00) | ||||
|                       VBCASTCDUP(1,%2,BCAST1)   VMADDMEM(0,%0,BCAST1,Chi_01) | ||||
|                       VBCASTCDUP(2,%2,BCAST2)   VMADDMEM(0,%0,BCAST2,Chi_02) | ||||
|                       VBCASTCDUP(3,%2,BCAST3)   VMADDMEM(0,%0,BCAST3,Chi_10) | ||||
|                       VBCASTCDUP(4,%2,BCAST4)   VMADDMEM(0,%0,BCAST4,Chi_11) | ||||
|                       VBCASTCDUP(5,%2,BCAST5)   VMADDMEM(0,%0,BCAST5,Chi_12) | ||||
|                       VBCASTCDUP(6,%2,BCAST6)   VMADDMEM(0,%1,BCAST6,Chi_20) | ||||
|                       VBCASTCDUP(7,%2,BCAST7)   VMADDMEM(0,%1,BCAST7,Chi_21) | ||||
|                       VBCASTCDUP(8,%2,BCAST8)   VMADDMEM(0,%1,BCAST8,Chi_22) | ||||
|                       VBCASTCDUP(9,%2,BCAST9)   VMADDMEM(0,%1,BCAST9,Chi_30) | ||||
|                       VBCASTCDUP(10,%2,BCAST10) VMADDMEM(0,%1,BCAST10,Chi_31) | ||||
|                       VBCASTCDUP(11,%2,BCAST11) VMADDMEM(0,%1,BCAST11,Chi_32) | ||||
|                       : : "r" (a0), "r" (a1), "r" (a2)                            ); | ||||
|               } | ||||
|  | ||||
|               a0 = a0 + incr; | ||||
|               a1 = a1 + incr; | ||||
|               a2 = a2 + sizeof(Simd::scalar_type); | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           { | ||||
|             int lexa = s1+LLs*site; | ||||
|             asm ( | ||||
|                VSTORE(0,%0,Chi_00) VSTORE(1 ,%0,Chi_01)  VSTORE(2 ,%0,Chi_02) | ||||
|                VSTORE(3,%0,Chi_10) VSTORE(4 ,%0,Chi_11)  VSTORE(5 ,%0,Chi_12) | ||||
|                VSTORE(6,%0,Chi_20) VSTORE(7 ,%0,Chi_21)  VSTORE(8 ,%0,Chi_22) | ||||
|                VSTORE(9,%0,Chi_30) VSTORE(10,%0,Chi_31)  VSTORE(11,%0,Chi_32) | ||||
|                : : "r" ((uint64_t)&chi[lexa]) : "memory" ); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       #undef Chi_00 | ||||
|       #undef Chi_01 | ||||
|       #undef Chi_02 | ||||
|       #undef Chi_10 | ||||
|       #undef Chi_11 | ||||
|       #undef Chi_12 | ||||
|       #undef Chi_20 | ||||
|       #undef Chi_21 | ||||
|       #undef Chi_22 | ||||
|       #undef Chi_30 | ||||
|       #undef Chi_31 | ||||
|       #undef Chi_32 | ||||
|  | ||||
|       #undef BCAST0 | ||||
|       #undef BCAST1 | ||||
|       #undef BCAST2 | ||||
|       #undef BCAST3 | ||||
|       #undef BCAST4 | ||||
|       #undef BCAST5 | ||||
|       #undef BCAST6 | ||||
|       #undef BCAST7 | ||||
|       #undef BCAST8 | ||||
|       #undef BCAST9 | ||||
|       #undef BCAST10 | ||||
|       #undef BCAST11 | ||||
|  | ||||
|     #endif | ||||
|   }; | ||||
|  | ||||
|   // Z-mobius version | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInternalZAsm(const FermionField& psi, FermionField& chi, | ||||
|     int LLs, int site, Vector<iSinglet<Simd> >& Matp, Vector<iSinglet<Simd> >& Matm) | ||||
|   { | ||||
|     std::cout << "Error: zMobius not implemented for EOFA" << std::endl; | ||||
|     exit(-1); | ||||
|   }; | ||||
|  | ||||
|   template<class Impl> | ||||
|   void MobiusEOFAFermion<Impl>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv) | ||||
|   { | ||||
|     int Ls  = this->Ls; | ||||
|     int LLs = psi._grid->_rdimensions[0]; | ||||
|     int vol = psi._grid->oSites()/LLs; | ||||
|  | ||||
|     chi.checkerboard = psi.checkerboard; | ||||
|  | ||||
|     Vector<iSinglet<Simd>>   Matp; | ||||
|     Vector<iSinglet<Simd>>   Matm; | ||||
|     Vector<iSinglet<Simd>>* _Matp; | ||||
|     Vector<iSinglet<Simd>>* _Matm; | ||||
|  | ||||
|     //  MooeeInternalCompute(dag,inv,Matp,Matm); | ||||
|     if(inv && dag){ | ||||
|       _Matp = &this->MatpInvDag; | ||||
|       _Matm = &this->MatmInvDag; | ||||
|     } | ||||
|  | ||||
|     if(inv && (!dag)){ | ||||
|       _Matp = &this->MatpInv; | ||||
|       _Matm = &this->MatmInv; | ||||
|     } | ||||
|  | ||||
|     if(!inv){ | ||||
|       MooeeInternalCompute(dag, inv, Matp, Matm); | ||||
|       _Matp = &Matp; | ||||
|       _Matm = &Matm; | ||||
|     } | ||||
|  | ||||
|     assert(_Matp->size() == Ls*LLs); | ||||
|  | ||||
|     this->MooeeInvCalls++; | ||||
|     this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|     if(switcheroo<Coeff_t>::iscomplex()){ | ||||
|       parallel_for(auto site=0; site<vol; site++){ | ||||
|         MooeeInternalZAsm(psi, chi, LLs, site, *_Matp, *_Matm); | ||||
|       } | ||||
|     } else { | ||||
|       parallel_for(auto site=0; site<vol; site++){ | ||||
|         MooeeInternalAsm(psi, chi, LLs, site, *_Matp, *_Matm); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     this->MooeeInvTime += usecond(); | ||||
|   } | ||||
|  | ||||
|   #ifdef MOBIUS_EOFA_DPERP_VEC | ||||
|  | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(DomainWallVec5dImplD); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(DomainWallVec5dImplF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZDomainWallVec5dImplD); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZDomainWallVec5dImplF); | ||||
|  | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(DomainWallVec5dImplDF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(DomainWallVec5dImplFH); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZDomainWallVec5dImplDF); | ||||
|     INSTANTIATE_DPERP_MOBIUS_EOFA(ZDomainWallVec5dImplFH); | ||||
|  | ||||
|     template void MobiusEOFAFermion<DomainWallVec5dImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<DomainWallVec5dImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<ZDomainWallVec5dImplF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<ZDomainWallVec5dImplD>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|  | ||||
|     template void MobiusEOFAFermion<DomainWallVec5dImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<DomainWallVec5dImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<ZDomainWallVec5dImplFH>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|     template void MobiusEOFAFermion<ZDomainWallVec5dImplDF>::MooeeInternal(const FermionField& psi, FermionField& chi, int dag, int inv); | ||||
|  | ||||
|   #endif | ||||
|  | ||||
| }} | ||||
| @@ -30,60 +30,181 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|  | ||||
| #define REGISTER | ||||
|  | ||||
| #define LOAD_CHIMU \ | ||||
|   {const SiteSpinor & ref (in._odata[offset]);	\ | ||||
|     Chimu_00=ref()(0)(0);\ | ||||
|     Chimu_01=ref()(0)(1);\ | ||||
|     Chimu_02=ref()(0)(2);\ | ||||
|     Chimu_10=ref()(1)(0);\ | ||||
|     Chimu_11=ref()(1)(1);\ | ||||
|     Chimu_12=ref()(1)(2);\ | ||||
|     Chimu_20=ref()(2)(0);\ | ||||
|     Chimu_21=ref()(2)(1);\ | ||||
|     Chimu_22=ref()(2)(2);\ | ||||
|     Chimu_30=ref()(3)(0);\ | ||||
|     Chimu_31=ref()(3)(1);\ | ||||
|     Chimu_32=ref()(3)(2);} | ||||
| #define LOAD_CHIMU_BODY(F)			\ | ||||
|   Chimu_00=ref(F)(0)(0);			\ | ||||
|   Chimu_01=ref(F)(0)(1);			\ | ||||
|   Chimu_02=ref(F)(0)(2);			\ | ||||
|   Chimu_10=ref(F)(1)(0);			\ | ||||
|   Chimu_11=ref(F)(1)(1);			\ | ||||
|   Chimu_12=ref(F)(1)(2);			\ | ||||
|   Chimu_20=ref(F)(2)(0);			\ | ||||
|   Chimu_21=ref(F)(2)(1);			\ | ||||
|   Chimu_22=ref(F)(2)(2);			\ | ||||
|   Chimu_30=ref(F)(3)(0);			\ | ||||
|   Chimu_31=ref(F)(3)(1);			\ | ||||
|   Chimu_32=ref(F)(3)(2) | ||||
|  | ||||
| #define LOAD_CHI\ | ||||
|   {const SiteHalfSpinor &ref(buf[offset]);	\ | ||||
|     Chi_00 = ref()(0)(0);\ | ||||
|     Chi_01 = ref()(0)(1);\ | ||||
|     Chi_02 = ref()(0)(2);\ | ||||
|     Chi_10 = ref()(1)(0);\ | ||||
|     Chi_11 = ref()(1)(1);\ | ||||
|     Chi_12 = ref()(1)(2);} | ||||
| #define LOAD_CHIMU(DIR,F,PERM)						\ | ||||
|   { const SiteSpinor & ref (in._odata[offset]); LOAD_CHIMU_BODY(F); } | ||||
|  | ||||
| #define LOAD_CHI_BODY(F)				\ | ||||
|     Chi_00 = ref(F)(0)(0);\ | ||||
|     Chi_01 = ref(F)(0)(1);\ | ||||
|     Chi_02 = ref(F)(0)(2);\ | ||||
|     Chi_10 = ref(F)(1)(0);\ | ||||
|     Chi_11 = ref(F)(1)(1);\ | ||||
|     Chi_12 = ref(F)(1)(2) | ||||
|  | ||||
| #define LOAD_CHI(DIR,F,PERM)					\ | ||||
|   {const SiteHalfSpinor &ref(buf[offset]); LOAD_CHI_BODY(F); } | ||||
|  | ||||
|  | ||||
| //G-parity implementations using in-place intrinsic ops | ||||
|  | ||||
| //1l 1h -> 1h 1l | ||||
| //0l 0h , 1h 1l -> 0l 1h 0h,1l | ||||
| //0h,1l -> 1l,0h | ||||
| //if( (distance == 1 && !perm_will_occur) || (distance == -1 && perm_will_occur) ) | ||||
| //Pulled fermion through forwards face, GPBC on upper component | ||||
| //Need 0= 0l 1h   1= 1l 0h | ||||
| //else if( (distance == -1 && !perm) || (distance == 1 && perm) ) | ||||
| //Pulled fermion through backwards face, GPBC on lower component | ||||
| //Need 0= 1l 0h   1= 0l 1h | ||||
|  | ||||
| //1l 1h -> 1h 1l | ||||
| //0l 0h , 1h 1l -> 0l 1h 0h,1l | ||||
| #define DO_TWIST_0L_1H(INTO,S,C,F, PERM, tmp1, tmp2, tmp3)			\ | ||||
|   permute##PERM(tmp1, ref(1)(S)(C));				\ | ||||
|   exchange##PERM(tmp2,tmp3, ref(0)(S)(C), tmp1);		\ | ||||
|   INTO = tmp2; | ||||
|  | ||||
| //0l 0h -> 0h 0l | ||||
| //1l 1h, 0h 0l -> 1l 0h, 1h 0l | ||||
| #define DO_TWIST_1L_0H(INTO,S,C,F, PERM, tmp1, tmp2, tmp3)			\ | ||||
|   permute##PERM(tmp1, ref(0)(S)(C));				\ | ||||
|   exchange##PERM(tmp2,tmp3, ref(1)(S)(C), tmp1);		\ | ||||
|   INTO = tmp2; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #define LOAD_CHI_SETUP(DIR,F)						\ | ||||
|   g = F;								\ | ||||
|   direction = st._directions[DIR];				\ | ||||
|   distance = st._distances[DIR];				\ | ||||
|   sl = st._grid->_simd_layout[direction];			\ | ||||
|   inplace_twist = 0;						\ | ||||
|   if(SE->_around_the_world && this->Params.twists[DIR % 4]){		\ | ||||
|     if(sl == 1){							\ | ||||
|       g = (F+1) % 2;							\ | ||||
|     }else{								\ | ||||
|       inplace_twist = 1;						\ | ||||
|     }									\ | ||||
|   }   | ||||
|  | ||||
| #define LOAD_CHIMU_GPARITY_INPLACE_TWIST(DIR,F,PERM)			\ | ||||
|   { const SiteSpinor &ref(in._odata[offset]);				\ | ||||
|     LOAD_CHI_SETUP(DIR,F);						\ | ||||
|     if(!inplace_twist){							\ | ||||
|       LOAD_CHIMU_BODY(g);						\ | ||||
|     }else{								\ | ||||
|       if(  ( F==0 && ((distance == 1 && !perm) || (distance == -1 && perm)) ) || \ | ||||
| 	   ( F==1 && ((distance == -1 && !perm) || (distance == 1 && perm)) ) ){ \ | ||||
| 	DO_TWIST_0L_1H(Chimu_00,0,0,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_01,0,1,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_02,0,2,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_10,1,0,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_11,1,1,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_12,1,2,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_20,2,0,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_21,2,1,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_22,2,2,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_30,3,0,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_31,3,1,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_0L_1H(Chimu_32,3,2,F,PERM,  U_11,U_20,U_21);		\ | ||||
|       }else{								\ | ||||
| 	DO_TWIST_1L_0H(Chimu_00,0,0,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_01,0,1,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_02,0,2,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_10,1,0,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_11,1,1,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_12,1,2,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_20,2,0,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_21,2,1,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_22,2,2,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_30,3,0,F,PERM,  U_11,U_20,U_21);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_31,3,1,F,PERM,  U_00,U_01,U_10);		\ | ||||
| 	DO_TWIST_1L_0H(Chimu_32,3,2,F,PERM,  U_11,U_20,U_21);		\ | ||||
|       } \ | ||||
|     } \ | ||||
|   } | ||||
|  | ||||
|  | ||||
| #define LOAD_CHI_GPARITY_INPLACE_TWIST(DIR,F,PERM)				\ | ||||
|   { const SiteHalfSpinor &ref(buf[offset]);				\ | ||||
|     LOAD_CHI_SETUP(DIR,F);						\ | ||||
|     if(!inplace_twist){							\ | ||||
|       LOAD_CHI_BODY(g);							\ | ||||
|     }else{								\ | ||||
|       if(  ( F==0 && ((distance == 1 && !perm) || (distance == -1 && perm)) ) || \ | ||||
| 	   ( F==1 && ((distance == -1 && !perm) || (distance == 1 && perm)) ) ){ \ | ||||
| 	DO_TWIST_0L_1H(Chi_00,0,0,F,PERM,  U_00,U_01,U_10);			\ | ||||
| 	DO_TWIST_0L_1H(Chi_01,0,1,F,PERM,  U_11,U_20,U_21);			\ | ||||
| 	DO_TWIST_0L_1H(Chi_02,0,2,F,PERM,  UChi_00,UChi_01,UChi_02);		\ | ||||
| 	DO_TWIST_0L_1H(Chi_10,1,0,F,PERM,  UChi_10,UChi_11,UChi_12);		\ | ||||
| 	DO_TWIST_0L_1H(Chi_11,1,1,F,PERM,  U_00,U_01,U_10);			\ | ||||
| 	DO_TWIST_0L_1H(Chi_12,1,2,F,PERM,  U_11,U_20,U_21);			\ | ||||
|       }else{								\ | ||||
| 	DO_TWIST_1L_0H(Chi_00,0,0,F,PERM,  U_00,U_01,U_10);			\ | ||||
| 	DO_TWIST_1L_0H(Chi_01,0,1,F,PERM,  U_11,U_20,U_21);			\ | ||||
| 	DO_TWIST_1L_0H(Chi_02,0,2,F,PERM,  UChi_00,UChi_01,UChi_02);		\ | ||||
| 	DO_TWIST_1L_0H(Chi_10,1,0,F,PERM,  UChi_10,UChi_11,UChi_12);		\ | ||||
| 	DO_TWIST_1L_0H(Chi_11,1,1,F,PERM,  U_00,U_01,U_10);			\ | ||||
| 	DO_TWIST_1L_0H(Chi_12,1,2,F,PERM,  U_11,U_20,U_21);			\ | ||||
|       }									\ | ||||
|     }									\ | ||||
|   } | ||||
|  | ||||
|  | ||||
| #define LOAD_CHI_GPARITY(DIR,F,PERM) LOAD_CHI_GPARITY_INPLACE_TWIST(DIR,F,PERM) | ||||
| #define LOAD_CHIMU_GPARITY(DIR,F,PERM) LOAD_CHIMU_GPARITY_INPLACE_TWIST(DIR,F,PERM) | ||||
|  | ||||
| // To splat or not to splat depends on the implementation | ||||
| #define MULT_2SPIN(A)\ | ||||
|   {auto & ref(U._odata[sU](A));			\ | ||||
|    Impl::loadLinkElement(U_00,ref()(0,0));	\ | ||||
|    Impl::loadLinkElement(U_10,ref()(1,0));	\ | ||||
|    Impl::loadLinkElement(U_20,ref()(2,0));	\ | ||||
|    Impl::loadLinkElement(U_01,ref()(0,1));	\ | ||||
|    Impl::loadLinkElement(U_11,ref()(1,1));	\ | ||||
|    Impl::loadLinkElement(U_21,ref()(2,1));	\ | ||||
|     UChi_00 = U_00*Chi_00;\ | ||||
|     UChi_10 = U_00*Chi_10;\ | ||||
|     UChi_01 = U_10*Chi_00;\ | ||||
|     UChi_11 = U_10*Chi_10;\ | ||||
|     UChi_02 = U_20*Chi_00;\ | ||||
|     UChi_12 = U_20*Chi_10;\ | ||||
|     UChi_00+= U_01*Chi_01;\ | ||||
|     UChi_10+= U_01*Chi_11;\ | ||||
|     UChi_01+= U_11*Chi_01;\ | ||||
|     UChi_11+= U_11*Chi_11;\ | ||||
|     UChi_02+= U_21*Chi_01;\ | ||||
|     UChi_12+= U_21*Chi_11;\ | ||||
|     Impl::loadLinkElement(U_00,ref()(0,2));	\ | ||||
|     Impl::loadLinkElement(U_10,ref()(1,2));	\ | ||||
|     Impl::loadLinkElement(U_20,ref()(2,2));	\ | ||||
|     UChi_00+= U_00*Chi_02;\ | ||||
|     UChi_10+= U_00*Chi_12;\ | ||||
|     UChi_01+= U_10*Chi_02;\ | ||||
|     UChi_11+= U_10*Chi_12;\ | ||||
|     UChi_02+= U_20*Chi_02;\ | ||||
|     UChi_12+= U_20*Chi_12;} | ||||
| #define MULT_2SPIN_BODY \ | ||||
|   Impl::loadLinkElement(U_00,ref()(0,0));	\ | ||||
|   Impl::loadLinkElement(U_10,ref()(1,0));	\ | ||||
|   Impl::loadLinkElement(U_20,ref()(2,0));	\ | ||||
|   Impl::loadLinkElement(U_01,ref()(0,1));	\ | ||||
|   Impl::loadLinkElement(U_11,ref()(1,1));	\ | ||||
|   Impl::loadLinkElement(U_21,ref()(2,1));	\ | ||||
|   UChi_00 = U_00*Chi_00;			\ | ||||
|   UChi_10 = U_00*Chi_10;			\ | ||||
|   UChi_01 = U_10*Chi_00;			\ | ||||
|   UChi_11 = U_10*Chi_10;			\ | ||||
|   UChi_02 = U_20*Chi_00;			\ | ||||
|   UChi_12 = U_20*Chi_10;			\ | ||||
|   UChi_00+= U_01*Chi_01;			\ | ||||
|   UChi_10+= U_01*Chi_11;			\ | ||||
|   UChi_01+= U_11*Chi_01;			\ | ||||
|   UChi_11+= U_11*Chi_11;			\ | ||||
|   UChi_02+= U_21*Chi_01;			\ | ||||
|   UChi_12+= U_21*Chi_11;			\ | ||||
|   Impl::loadLinkElement(U_00,ref()(0,2));	\ | ||||
|   Impl::loadLinkElement(U_10,ref()(1,2));	\ | ||||
|   Impl::loadLinkElement(U_20,ref()(2,2));	\ | ||||
|   UChi_00+= U_00*Chi_02;			\ | ||||
|   UChi_10+= U_00*Chi_12;			\ | ||||
|   UChi_01+= U_10*Chi_02;			\ | ||||
|   UChi_11+= U_10*Chi_12;			\ | ||||
|   UChi_02+= U_20*Chi_02;			\ | ||||
|   UChi_12+= U_20*Chi_12 | ||||
|  | ||||
|  | ||||
| #define MULT_2SPIN(A,F)					\ | ||||
|   {auto & ref(U._odata[sU](A)); MULT_2SPIN_BODY; } | ||||
|  | ||||
| #define MULT_2SPIN_GPARITY(A,F)				\ | ||||
|   {auto & ref(U._odata[sU](F)(A)); MULT_2SPIN_BODY; } | ||||
|  | ||||
|  | ||||
| #define PERMUTE_DIR(dir)			\ | ||||
| @@ -307,84 +428,87 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|   result_31-= UChi_11;	\ | ||||
|   result_32-= UChi_12; | ||||
|  | ||||
| #define HAND_STENCIL_LEG(PROJ,PERM,DIR,RECON)	\ | ||||
| #define HAND_STENCIL_LEG(PROJ,PERM,DIR,RECON,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||
|   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||
|   offset = SE->_offset;				\ | ||||
|   local  = SE->_is_local;			\ | ||||
|   perm   = SE->_permute;			\ | ||||
|   if ( local ) {				\ | ||||
|     LOAD_CHIMU;					\ | ||||
|     LOAD_CHIMU_IMPL(DIR,F,PERM);			\ | ||||
|     PROJ;					\ | ||||
|     if ( perm) {				\ | ||||
|       PERMUTE_DIR(PERM);			\ | ||||
|     }						\ | ||||
|   } else {					\ | ||||
|     LOAD_CHI;					\ | ||||
|     LOAD_CHI_IMPL(DIR,F,PERM);			\ | ||||
|   }						\ | ||||
|   MULT_2SPIN(DIR);				\ | ||||
|   MULT_2SPIN_IMPL(DIR,F);			\ | ||||
|   RECON;					 | ||||
|  | ||||
| #define HAND_STENCIL_LEG_INT(PROJ,PERM,DIR,RECON)	\ | ||||
|  | ||||
| #define HAND_STENCIL_LEG_INT(PROJ,PERM,DIR,RECON,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL)	\ | ||||
|   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||
|   offset = SE->_offset;				\ | ||||
|   local  = SE->_is_local;			\ | ||||
|   perm   = SE->_permute;			\ | ||||
|   if ( local ) {				\ | ||||
|     LOAD_CHIMU;					\ | ||||
|     LOAD_CHIMU_IMPL(DIR,F,PERM);			\ | ||||
|     PROJ;					\ | ||||
|     if ( perm) {				\ | ||||
|       PERMUTE_DIR(PERM);			\ | ||||
|     }						\ | ||||
|   } else if ( st.same_node[DIR] ) {		\ | ||||
|     LOAD_CHI;					\ | ||||
|     LOAD_CHI_IMPL(DIR,F,PERM);			\ | ||||
|   }						\ | ||||
|   if (local || st.same_node[DIR] ) {		\ | ||||
|     MULT_2SPIN(DIR);				\ | ||||
|     MULT_2SPIN_IMPL(DIR,F);			\ | ||||
|     RECON;					\ | ||||
|   } | ||||
|  | ||||
| #define HAND_STENCIL_LEG_EXT(PROJ,PERM,DIR,RECON)	\ | ||||
| #define HAND_STENCIL_LEG_EXT(PROJ,PERM,DIR,RECON,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL)	\ | ||||
|   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||
|   offset = SE->_offset;				\ | ||||
|   local  = SE->_is_local;			\ | ||||
|   perm   = SE->_permute;			\ | ||||
|   if((!SE->_is_local)&&(!st.same_node[DIR]) ) {	\ | ||||
|     LOAD_CHI;					\ | ||||
|     MULT_2SPIN(DIR);				\ | ||||
|     LOAD_CHI_IMPL(DIR,F,PERM);			\ | ||||
|     MULT_2SPIN_IMPL(DIR,F);			\ | ||||
|     RECON;					\ | ||||
|     nmu++;					\ | ||||
|   } | ||||
|  | ||||
| #define HAND_RESULT(ss)				\ | ||||
| #define HAND_RESULT(ss,F)			\ | ||||
|   {						\ | ||||
|     SiteSpinor & ref (out._odata[ss]);		\ | ||||
|     vstream(ref()(0)(0),result_00);		\ | ||||
|     vstream(ref()(0)(1),result_01);		\ | ||||
|     vstream(ref()(0)(2),result_02);		\ | ||||
|     vstream(ref()(1)(0),result_10);		\ | ||||
|     vstream(ref()(1)(1),result_11);		\ | ||||
|     vstream(ref()(1)(2),result_12);		\ | ||||
|     vstream(ref()(2)(0),result_20);		\ | ||||
|     vstream(ref()(2)(1),result_21);		\ | ||||
|     vstream(ref()(2)(2),result_22);		\ | ||||
|     vstream(ref()(3)(0),result_30);		\ | ||||
|     vstream(ref()(3)(1),result_31);		\ | ||||
|     vstream(ref()(3)(2),result_32);		\ | ||||
|     vstream(ref(F)(0)(0),result_00);		\ | ||||
|     vstream(ref(F)(0)(1),result_01);		\ | ||||
|     vstream(ref(F)(0)(2),result_02);		\ | ||||
|     vstream(ref(F)(1)(0),result_10);		\ | ||||
|     vstream(ref(F)(1)(1),result_11);		\ | ||||
|     vstream(ref(F)(1)(2),result_12);		\ | ||||
|     vstream(ref(F)(2)(0),result_20);		\ | ||||
|     vstream(ref(F)(2)(1),result_21);		\ | ||||
|     vstream(ref(F)(2)(2),result_22);		\ | ||||
|     vstream(ref(F)(3)(0),result_30);		\ | ||||
|     vstream(ref(F)(3)(1),result_31);		\ | ||||
|     vstream(ref(F)(3)(2),result_32);		\ | ||||
|   } | ||||
|  | ||||
| #define HAND_RESULT_EXT(ss)			\ | ||||
| #define HAND_RESULT_EXT(ss,F)			\ | ||||
|   if (nmu){					\ | ||||
|     SiteSpinor & ref (out._odata[ss]);		\ | ||||
|     ref()(0)(0)+=result_00;		\ | ||||
|     ref()(0)(1)+=result_01;		\ | ||||
|     ref()(0)(2)+=result_02;		\ | ||||
|     ref()(1)(0)+=result_10;		\ | ||||
|     ref()(1)(1)+=result_11;		\ | ||||
|     ref()(1)(2)+=result_12;		\ | ||||
|     ref()(2)(0)+=result_20;		\ | ||||
|     ref()(2)(1)+=result_21;		\ | ||||
|     ref()(2)(2)+=result_22;		\ | ||||
|     ref()(3)(0)+=result_30;		\ | ||||
|     ref()(3)(1)+=result_31;		\ | ||||
|     ref()(3)(2)+=result_32;		\ | ||||
|     ref(F)(0)(0)+=result_00;		\ | ||||
|     ref(F)(0)(1)+=result_01;		\ | ||||
|     ref(F)(0)(2)+=result_02;		\ | ||||
|     ref(F)(1)(0)+=result_10;		\ | ||||
|     ref(F)(1)(1)+=result_11;		\ | ||||
|     ref(F)(1)(2)+=result_12;		\ | ||||
|     ref(F)(2)(0)+=result_20;		\ | ||||
|     ref(F)(2)(1)+=result_21;		\ | ||||
|     ref(F)(2)(2)+=result_22;		\ | ||||
|     ref(F)(3)(0)+=result_30;		\ | ||||
|     ref(F)(3)(1)+=result_31;		\ | ||||
|     ref(F)(3)(2)+=result_32;		\ | ||||
|   } | ||||
|  | ||||
|  | ||||
| @@ -463,15 +587,18 @@ WilsonKernels<Impl>::HandDhopSite(StencilImpl &st,LebesgueOrder &lo,DoubledGauge | ||||
|   int offset,local,perm, ptype; | ||||
|   StencilEntry *SE; | ||||
|  | ||||
|   HAND_STENCIL_LEG(XM_PROJ,3,Xp,XM_RECON); | ||||
|   HAND_STENCIL_LEG(YM_PROJ,2,Yp,YM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(ZM_PROJ,1,Zp,ZM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(TM_PROJ,0,Tp,TM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(XP_PROJ,3,Xm,XP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(YP_PROJ,2,Ym,YP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(TP_PROJ,0,Tm,TP_RECON_ACCUM); | ||||
|   HAND_RESULT(ss); | ||||
| #define HAND_DOP_SITE(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||
|   HAND_STENCIL_LEG(XM_PROJ,3,Xp,XM_RECON,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(YM_PROJ,2,Yp,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);	\ | ||||
|   HAND_STENCIL_LEG(ZM_PROJ,1,Zp,ZM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(TM_PROJ,0,Tp,TM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(XP_PROJ,3,Xm,XP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(YP_PROJ,2,Ym,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(ZP_PROJ,1,Zm,ZP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(TP_PROJ,0,Tm,TP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_RESULT(ss,F) | ||||
|  | ||||
|   HAND_DOP_SITE(, LOAD_CHI,LOAD_CHIMU,MULT_2SPIN); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -485,16 +612,19 @@ void WilsonKernels<Impl>::HandDhopSiteDag(StencilImpl &st,LebesgueOrder &lo,Doub | ||||
|  | ||||
|   StencilEntry *SE; | ||||
|   int offset,local,perm, ptype; | ||||
|    | ||||
|   HAND_STENCIL_LEG(XP_PROJ,3,Xp,XP_RECON); | ||||
|   HAND_STENCIL_LEG(YP_PROJ,2,Yp,YP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(ZP_PROJ,1,Zp,ZP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(TP_PROJ,0,Tp,TP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(XM_PROJ,3,Xm,XM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(YM_PROJ,2,Ym,YM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG(TM_PROJ,0,Tm,TM_RECON_ACCUM); | ||||
|   HAND_RESULT(ss); | ||||
|  | ||||
| #define HAND_DOP_SITE_DAG(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||
|   HAND_STENCIL_LEG(XP_PROJ,3,Xp,XP_RECON,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(YP_PROJ,2,Yp,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(ZP_PROJ,1,Zp,ZP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(TP_PROJ,0,Tp,TP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(XM_PROJ,3,Xm,XM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(YM_PROJ,2,Ym,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(ZM_PROJ,1,Zm,ZM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG(TM_PROJ,0,Tm,TM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_RESULT(ss,F) | ||||
|  | ||||
|   HAND_DOP_SITE_DAG(, LOAD_CHI,LOAD_CHIMU,MULT_2SPIN); | ||||
| } | ||||
|  | ||||
| template<class Impl> void  | ||||
| @@ -509,16 +639,20 @@ WilsonKernels<Impl>::HandDhopSiteInt(StencilImpl &st,LebesgueOrder &lo,DoubledGa | ||||
|  | ||||
|   int offset,local,perm, ptype; | ||||
|   StencilEntry *SE; | ||||
|   ZERO_RESULT; | ||||
|   HAND_STENCIL_LEG_INT(XM_PROJ,3,Xp,XM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(YM_PROJ,2,Yp,YM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(ZM_PROJ,1,Zp,ZM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(TM_PROJ,0,Tp,TM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(XP_PROJ,3,Xm,XP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(YP_PROJ,2,Ym,YP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(TP_PROJ,0,Tm,TP_RECON_ACCUM); | ||||
|   HAND_RESULT(ss); | ||||
|  | ||||
| #define HAND_DOP_SITE_INT(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||
|   ZERO_RESULT; \ | ||||
|   HAND_STENCIL_LEG_INT(XM_PROJ,3,Xp,XM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_INT(YM_PROJ,2,Yp,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_INT(ZM_PROJ,1,Zp,ZM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_INT(TM_PROJ,0,Tp,TM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_INT(XP_PROJ,3,Xm,XP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_INT(YP_PROJ,2,Ym,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_INT(ZP_PROJ,1,Zm,ZP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_INT(TP_PROJ,0,Tm,TP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_RESULT(ss,F) | ||||
|  | ||||
|   HAND_DOP_SITE_INT(, LOAD_CHI,LOAD_CHIMU,MULT_2SPIN); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -532,16 +666,20 @@ void WilsonKernels<Impl>::HandDhopSiteDagInt(StencilImpl &st,LebesgueOrder &lo,D | ||||
|  | ||||
|   StencilEntry *SE; | ||||
|   int offset,local,perm, ptype; | ||||
|   ZERO_RESULT; | ||||
|   HAND_STENCIL_LEG_INT(XP_PROJ,3,Xp,XP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(YP_PROJ,2,Yp,YP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(ZP_PROJ,1,Zp,ZP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(TP_PROJ,0,Tp,TP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(XM_PROJ,3,Xm,XM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(YM_PROJ,2,Ym,YM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_INT(TM_PROJ,0,Tm,TM_RECON_ACCUM); | ||||
|   HAND_RESULT(ss); | ||||
|  | ||||
| #define HAND_DOP_SITE_DAG_INT(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL)				\ | ||||
|   ZERO_RESULT;							\ | ||||
|   HAND_STENCIL_LEG_INT(XP_PROJ,3,Xp,XP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||
|   HAND_STENCIL_LEG_INT(YP_PROJ,2,Yp,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||
|   HAND_STENCIL_LEG_INT(ZP_PROJ,1,Zp,ZP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||
|   HAND_STENCIL_LEG_INT(TP_PROJ,0,Tp,TP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||
|   HAND_STENCIL_LEG_INT(XM_PROJ,3,Xm,XM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||
|   HAND_STENCIL_LEG_INT(YM_PROJ,2,Ym,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||
|   HAND_STENCIL_LEG_INT(ZM_PROJ,1,Zm,ZM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||
|   HAND_STENCIL_LEG_INT(TM_PROJ,0,Tm,TM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||
|   HAND_RESULT(ss,F) | ||||
|    | ||||
|   HAND_DOP_SITE_DAG_INT(, LOAD_CHI,LOAD_CHIMU,MULT_2SPIN); | ||||
| } | ||||
|  | ||||
| template<class Impl> void  | ||||
| @@ -557,16 +695,20 @@ WilsonKernels<Impl>::HandDhopSiteExt(StencilImpl &st,LebesgueOrder &lo,DoubledGa | ||||
|   int offset,local,perm, ptype; | ||||
|   StencilEntry *SE; | ||||
|   int nmu=0; | ||||
|   ZERO_RESULT; | ||||
|   HAND_STENCIL_LEG_EXT(XM_PROJ,3,Xp,XM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(YM_PROJ,2,Yp,YM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(ZM_PROJ,1,Zp,ZM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(TM_PROJ,0,Tp,TM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(XP_PROJ,3,Xm,XP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(YP_PROJ,2,Ym,YP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(TP_PROJ,0,Tm,TP_RECON_ACCUM); | ||||
|   HAND_RESULT_EXT(ss); | ||||
|  | ||||
| #define HAND_DOP_SITE_EXT(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||
|   ZERO_RESULT; \ | ||||
|   HAND_STENCIL_LEG_EXT(XM_PROJ,3,Xp,XM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(YM_PROJ,2,Yp,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(ZM_PROJ,1,Zp,ZM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(TM_PROJ,0,Tp,TM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(XP_PROJ,3,Xm,XP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(YP_PROJ,2,Ym,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(ZP_PROJ,1,Zm,ZP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(TP_PROJ,0,Tm,TP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_RESULT_EXT(ss,F) | ||||
|  | ||||
|   HAND_DOP_SITE_EXT(, LOAD_CHI,LOAD_CHIMU,MULT_2SPIN); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -581,16 +723,20 @@ void WilsonKernels<Impl>::HandDhopSiteDagExt(StencilImpl &st,LebesgueOrder &lo,D | ||||
|   StencilEntry *SE; | ||||
|   int offset,local,perm, ptype; | ||||
|   int nmu=0; | ||||
|   ZERO_RESULT; | ||||
|   HAND_STENCIL_LEG_EXT(XP_PROJ,3,Xp,XP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(YP_PROJ,2,Yp,YP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(ZP_PROJ,1,Zp,ZP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(TP_PROJ,0,Tp,TP_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(XM_PROJ,3,Xm,XM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(YM_PROJ,2,Ym,YM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); | ||||
|   HAND_STENCIL_LEG_EXT(TM_PROJ,0,Tm,TM_RECON_ACCUM); | ||||
|   HAND_RESULT_EXT(ss); | ||||
|  | ||||
| #define HAND_DOP_SITE_DAG_EXT(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||
|   ZERO_RESULT; \ | ||||
|   HAND_STENCIL_LEG_EXT(XP_PROJ,3,Xp,XP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(YP_PROJ,2,Yp,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(ZP_PROJ,1,Zp,ZP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(TP_PROJ,0,Tp,TP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(XM_PROJ,3,Xm,XM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(YM_PROJ,2,Ym,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(ZM_PROJ,1,Zm,ZM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_STENCIL_LEG_EXT(TM_PROJ,0,Tm,TM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||
|   HAND_RESULT_EXT(ss,F) | ||||
|  | ||||
|   HAND_DOP_SITE_DAG_EXT(, LOAD_CHI,LOAD_CHIMU,MULT_2SPIN); | ||||
| } | ||||
|  | ||||
|   //////////////////////////////////////////////// | ||||
| @@ -646,11 +792,124 @@ void WilsonKernels<Impl>::HandDhopSiteDagExt(StencilImpl &st,LebesgueOrder &lo,D | ||||
| 				    const FermionField &in,		\ | ||||
| 				    FermionField &out){ assert(0); }	\ | ||||
|  | ||||
|   HAND_SPECIALISE_EMPTY(GparityWilsonImplF); | ||||
|   HAND_SPECIALISE_EMPTY(GparityWilsonImplD); | ||||
|   HAND_SPECIALISE_EMPTY(GparityWilsonImplFH); | ||||
|   HAND_SPECIALISE_EMPTY(GparityWilsonImplDF); | ||||
|  | ||||
|  | ||||
| #define HAND_SPECIALISE_GPARITY(IMPL)					\ | ||||
|   template<> void							\ | ||||
|   WilsonKernels<IMPL>::HandDhopSite(StencilImpl &st,LebesgueOrder &lo,DoubledGaugeField &U,SiteHalfSpinor  *buf, \ | ||||
| 				    int ss,int sU,const FermionField &in, FermionField &out) \ | ||||
|   {									\ | ||||
|     typedef IMPL Impl;							\ | ||||
|     typedef typename Simd::scalar_type S;				\ | ||||
|     typedef typename Simd::vector_type V;				\ | ||||
| 									\ | ||||
|     HAND_DECLARATIONS(ignore);						\ | ||||
| 									\ | ||||
|     int offset,local,perm, ptype, g, direction, distance, sl, inplace_twist; \ | ||||
|     StencilEntry *SE;							\ | ||||
|     HAND_DOP_SITE(0, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|     HAND_DOP_SITE(1, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|   }									\ | ||||
| 									\ | ||||
|   template<>								\ | ||||
|   void WilsonKernels<IMPL>::HandDhopSiteDag(StencilImpl &st,LebesgueOrder &lo,DoubledGaugeField &U,SiteHalfSpinor *buf, \ | ||||
| 					    int ss,int sU,const FermionField &in, FermionField &out) \ | ||||
|   {									\ | ||||
|     typedef IMPL Impl;							\ | ||||
|     typedef typename Simd::scalar_type S;				\ | ||||
|     typedef typename Simd::vector_type V;				\ | ||||
| 									\ | ||||
|     HAND_DECLARATIONS(ignore);						\ | ||||
| 									\ | ||||
|     StencilEntry *SE;							\ | ||||
|     int offset,local,perm, ptype, g, direction, distance, sl, inplace_twist;					\ | ||||
|     HAND_DOP_SITE_DAG(0, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|     HAND_DOP_SITE_DAG(1, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|   }									\ | ||||
| 									\ | ||||
|   template<> void							\ | ||||
|   WilsonKernels<IMPL>::HandDhopSiteInt(StencilImpl &st,LebesgueOrder &lo,DoubledGaugeField &U,SiteHalfSpinor  *buf, \ | ||||
| 						     int ss,int sU,const FermionField &in, FermionField &out) \ | ||||
|   {									\ | ||||
|     typedef IMPL Impl;							\ | ||||
|     typedef typename Simd::scalar_type S;				\ | ||||
|     typedef typename Simd::vector_type V;				\ | ||||
| 									\ | ||||
|     HAND_DECLARATIONS(ignore);						\ | ||||
| 									\ | ||||
|     int offset,local,perm, ptype, g, direction, distance, sl, inplace_twist;					\ | ||||
|     StencilEntry *SE;							\ | ||||
|     HAND_DOP_SITE_INT(0, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|     HAND_DOP_SITE_INT(1, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|   }									\ | ||||
| 									\ | ||||
|   template<>								\ | ||||
|   void WilsonKernels<IMPL>::HandDhopSiteDagInt(StencilImpl &st,LebesgueOrder &lo,DoubledGaugeField &U,SiteHalfSpinor *buf, \ | ||||
| 							     int ss,int sU,const FermionField &in, FermionField &out) \ | ||||
|   {									\ | ||||
|     typedef IMPL Impl;							\ | ||||
|     typedef typename Simd::scalar_type S;				\ | ||||
|     typedef typename Simd::vector_type V;				\ | ||||
| 									\ | ||||
|     HAND_DECLARATIONS(ignore);						\ | ||||
| 									\ | ||||
|     StencilEntry *SE;							\ | ||||
|     int offset,local,perm, ptype, g, direction, distance, sl, inplace_twist; \ | ||||
|     HAND_DOP_SITE_DAG_INT(0, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|     HAND_DOP_SITE_DAG_INT(1, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|   }									\ | ||||
| 									\ | ||||
|   template<> void							\ | ||||
|   WilsonKernels<IMPL>::HandDhopSiteExt(StencilImpl &st,LebesgueOrder &lo,DoubledGaugeField &U,SiteHalfSpinor  *buf, \ | ||||
| 						     int ss,int sU,const FermionField &in, FermionField &out) \ | ||||
|   {									\ | ||||
|     typedef IMPL Impl;							\ | ||||
|     typedef typename Simd::scalar_type S;				\ | ||||
|     typedef typename Simd::vector_type V;				\ | ||||
| 									\ | ||||
|     HAND_DECLARATIONS(ignore);						\ | ||||
| 									\ | ||||
|     int offset,local,perm, ptype, g, direction, distance, sl, inplace_twist; \ | ||||
|     StencilEntry *SE;							\ | ||||
|     int nmu=0;								\ | ||||
|     HAND_DOP_SITE_EXT(0, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|     nmu = 0;								\ | ||||
|     HAND_DOP_SITE_EXT(1, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|   }									\ | ||||
|   template<>								\ | ||||
|   void WilsonKernels<IMPL>::HandDhopSiteDagExt(StencilImpl &st,LebesgueOrder &lo,DoubledGaugeField &U,SiteHalfSpinor *buf, \ | ||||
| 							     int ss,int sU,const FermionField &in, FermionField &out) \ | ||||
|   {									\ | ||||
|     typedef IMPL Impl;							\ | ||||
|     typedef typename Simd::scalar_type S;				\ | ||||
|     typedef typename Simd::vector_type V;				\ | ||||
| 									\ | ||||
|     HAND_DECLARATIONS(ignore);						\ | ||||
| 									\ | ||||
|     StencilEntry *SE;							\ | ||||
|     int offset,local,perm, ptype, g, direction, distance, sl, inplace_twist; \ | ||||
|     int nmu=0;								\ | ||||
|     HAND_DOP_SITE_DAG_EXT(0, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|     nmu = 0;								\ | ||||
|     HAND_DOP_SITE_DAG_EXT(1, LOAD_CHI_GPARITY,LOAD_CHIMU_GPARITY,MULT_2SPIN_GPARITY); \ | ||||
|   } | ||||
|  | ||||
|  | ||||
| HAND_SPECIALISE_GPARITY(GparityWilsonImplF); | ||||
| HAND_SPECIALISE_GPARITY(GparityWilsonImplD); | ||||
| HAND_SPECIALISE_GPARITY(GparityWilsonImplFH); | ||||
| HAND_SPECIALISE_GPARITY(GparityWilsonImplDF); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|    | ||||
| ////////////// Wilson ; uses this implementation ///////////////////// | ||||
|  | ||||
| #define INSTANTIATE_THEM(A) \ | ||||
|   | ||||
							
								
								
									
										264
									
								
								lib/qcd/action/pseudofermion/ExactOneFlavourRatio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								lib/qcd/action/pseudofermion/ExactOneFlavourRatio.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,264 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/pseudofermion/ExactOneFlavourRatio.h | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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 */ | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////// | ||||
| // Implementation of exact one flavour algorithm (EOFA)         // | ||||
| // using fermion classes defined in:                           // | ||||
| //    Grid/qcd/action/fermion/DomainWallEOFAFermion.h (Shamir) // | ||||
| //    Grid/qcd/action/fermion/MobiusEOFAFermion.h (Mobius)     // | ||||
| // arXiv: 1403.1683, 1706.05843                                // | ||||
| ///////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #ifndef QCD_PSEUDOFERMION_EXACT_ONE_FLAVOUR_RATIO_H | ||||
| #define QCD_PSEUDOFERMION_EXACT_ONE_FLAVOUR_RATIO_H | ||||
|  | ||||
| namespace Grid{ | ||||
| namespace QCD{ | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Exact one flavour implementation of DWF determinant ratio // | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|  | ||||
|   template<class Impl> | ||||
|   class ExactOneFlavourRatioPseudoFermionAction : public Action<typename Impl::GaugeField> | ||||
|   { | ||||
|     public: | ||||
|       INHERIT_IMPL_TYPES(Impl); | ||||
|       typedef OneFlavourRationalParams Params; | ||||
|       Params param; | ||||
|       MultiShiftFunction PowerNegHalf; | ||||
|  | ||||
|     private: | ||||
|       bool use_heatbath_forecasting; | ||||
|       AbstractEOFAFermion<Impl>& Lop; // the basic LH operator | ||||
|       AbstractEOFAFermion<Impl>& Rop; // the basic RH operator | ||||
|       SchurRedBlackDiagMooeeSolve<FermionField> Solver; | ||||
|       FermionField Phi; // the pseudofermion field for this trajectory | ||||
|  | ||||
|     public: | ||||
|       ExactOneFlavourRatioPseudoFermionAction(AbstractEOFAFermion<Impl>& _Lop, AbstractEOFAFermion<Impl>& _Rop, | ||||
|         OperatorFunction<FermionField>& S, Params& p, bool use_fc=false) : Lop(_Lop), Rop(_Rop), Solver(S), | ||||
|         Phi(_Lop.FermionGrid()), param(p), use_heatbath_forecasting(use_fc) | ||||
|       { | ||||
|         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); | ||||
|         PowerNegHalf.Init(remez, param.tolerance, true); | ||||
|       }; | ||||
|  | ||||
|       virtual std::string action_name() { return "ExactOneFlavourRatioPseudoFermionAction"; } | ||||
|  | ||||
|       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(); | ||||
|       } | ||||
|  | ||||
|       // Spin projection | ||||
|       void spProj(const FermionField& in, FermionField& out, int sign, int Ls) | ||||
|       { | ||||
|         if(sign == 1){ for(int s=0; s<Ls; ++s){ axpby_ssp_pplus(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); } } | ||||
|       } | ||||
|  | ||||
|       // EOFA heatbath: see Eqn. (29) of arXiv:1706.05843 | ||||
|       // We generate a Gaussian noise vector \eta, and then compute | ||||
|       //  \Phi = M_{\rm EOFA}^{-1/2} * \eta | ||||
|       // using a rational approximation to the inverse square root | ||||
|       virtual void refresh(const GaugeField& U, GridParallelRNG& pRNG) | ||||
|       { | ||||
|         Lop.ImportGauge(U); | ||||
|         Rop.ImportGauge(U); | ||||
|  | ||||
|         FermionField eta         (Lop.FermionGrid()); | ||||
|         FermionField CG_src      (Lop.FermionGrid()); | ||||
|         FermionField CG_soln     (Lop.FermionGrid()); | ||||
|         FermionField Forecast_src(Lop.FermionGrid()); | ||||
|         std::vector<FermionField> tmp(2, Lop.FermionGrid()); | ||||
|  | ||||
|         // Use chronological inverter to forecast solutions across poles | ||||
|         std::vector<FermionField> prev_solns; | ||||
|         if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); } | ||||
|         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; | ||||
|         printf("Heatbath source vector: <\\eta|\\eta> = %1.15e\n", norm2(eta)); | ||||
|  | ||||
|         // \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta | ||||
|         RealD N(PowerNegHalf.norm); | ||||
|         for(int k=0; k<param.degree; ++k){ N += PowerNegHalf.residues[k] / ( 1.0 + PowerNegHalf.poles[k] ); } | ||||
|         Phi = eta * N; | ||||
|  | ||||
|         // 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 | ||||
|         RealD gamma_l(0.0); | ||||
|         spProj(eta, tmp[0], -1, Lop.Ls); | ||||
|         Lop.Omega(tmp[0], tmp[1], -1, 0); | ||||
|         G5R5(CG_src, tmp[1]); | ||||
|         tmp[1] = zero; | ||||
|         for(int k=0; k<param.degree; ++k){ | ||||
|           gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] ); | ||||
|           Lop.RefreshShiftCoefficients(-gamma_l); | ||||
|           if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles | ||||
|             Lop.Mdag(CG_src, Forecast_src); | ||||
|             CG_soln = Forecast(Lop, Forecast_src, prev_solns); | ||||
|             Solver(Lop, CG_src, CG_soln); | ||||
|             prev_solns.push_back(CG_soln); | ||||
|           } else { | ||||
|             CG_soln = zero; // Just use zero as the initial guess | ||||
|             Solver(Lop, CG_src, CG_soln); | ||||
|           } | ||||
|           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]; | ||||
|         } | ||||
|         Lop.Omega(tmp[1], tmp[0], -1, 1); | ||||
|         spProj(tmp[0], tmp[1], -1, Lop.Ls); | ||||
|         Phi = Phi + tmp[1]; | ||||
|  | ||||
|         // RH terms: | ||||
|         // \Phi = \Phi - k \sum_{k=1}^{N_{p}} P_{+} \Omega_{+}^{\dagger} ( H(mb) | ||||
|         //          + \gamma_{l} \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} \eta | ||||
|         spProj(eta, tmp[0], 1, Rop.Ls); | ||||
|         Rop.Omega(tmp[0], tmp[1], 1, 0); | ||||
|         G5R5(CG_src, tmp[1]); | ||||
|         tmp[1] = zero; | ||||
|         if(use_heatbath_forecasting){ prev_solns.clear(); } // empirically, LH solns don't help for RH solves | ||||
|         for(int k=0; k<param.degree; ++k){ | ||||
|           gamma_l = 1.0 / ( 1.0 + PowerNegHalf.poles[k] ); | ||||
|           Rop.RefreshShiftCoefficients(-gamma_l*PowerNegHalf.poles[k]); | ||||
|           if(use_heatbath_forecasting){ | ||||
|             Rop.Mdag(CG_src, Forecast_src); | ||||
|             CG_soln = Forecast(Rop, Forecast_src, prev_solns); | ||||
|             Solver(Rop, CG_src, CG_soln); | ||||
|             prev_solns.push_back(CG_soln); | ||||
|           } else { | ||||
|             CG_soln = zero; | ||||
|             Solver(Rop, CG_src, CG_soln); | ||||
|           } | ||||
|           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]; | ||||
|         } | ||||
|         Rop.Omega(tmp[1], tmp[0], 1, 1); | ||||
|         spProj(tmp[0], tmp[1], 1, Rop.Ls); | ||||
|         Phi = Phi + tmp[1]; | ||||
|  | ||||
|         // Reset shift coefficients for energy and force evals | ||||
|         Lop.RefreshShiftCoefficients(0.0); | ||||
|         Rop.RefreshShiftCoefficients(-1.0); | ||||
|       }; | ||||
|  | ||||
|       // EOFA action: see Eqn. (10) of arXiv:1706.05843 | ||||
|       virtual RealD S(const GaugeField& U) | ||||
|       { | ||||
|         Lop.ImportGauge(U); | ||||
|         Rop.ImportGauge(U); | ||||
|  | ||||
|         FermionField spProj_Phi(Lop.FermionGrid()); | ||||
|         std::vector<FermionField> tmp(2, Lop.FermionGrid()); | ||||
|  | ||||
|         // S = <\Phi|\Phi> | ||||
|         RealD action(norm2(Phi)); | ||||
|  | ||||
|         // LH term: S = S - k <\Phi| P_{-} \Omega_{-}^{\dagger} H(mf)^{-1} \Omega_{-} P_{-} |\Phi> | ||||
|         spProj(Phi, spProj_Phi, -1, Lop.Ls); | ||||
|         Lop.Omega(spProj_Phi, tmp[0], -1, 0); | ||||
|         G5R5(tmp[1], tmp[0]); | ||||
|         tmp[0] = zero; | ||||
|         Solver(Lop, tmp[1], tmp[0]); | ||||
|         Lop.Dtilde(tmp[0], tmp[1]); // We actually solved Cayley preconditioned system: transform back | ||||
|         Lop.Omega(tmp[1], tmp[0], -1, 1); | ||||
|         action -= Lop.k * innerProduct(spProj_Phi, tmp[0]).real(); | ||||
|  | ||||
|         // RH term: S = S + k <\Phi| P_{+} \Omega_{+}^{\dagger} ( H(mb) | ||||
|         //               - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{-} P_{-} |\Phi> | ||||
|         spProj(Phi, spProj_Phi, 1, Rop.Ls); | ||||
|         Rop.Omega(spProj_Phi, tmp[0], 1, 0); | ||||
|         G5R5(tmp[1], tmp[0]); | ||||
|         tmp[0] = zero; | ||||
|         Solver(Rop, tmp[1], tmp[0]); | ||||
|         Rop.Dtilde(tmp[0], tmp[1]); | ||||
|         Rop.Omega(tmp[1], tmp[0], 1, 1); | ||||
|         action += Rop.k * innerProduct(spProj_Phi, tmp[0]).real(); | ||||
|  | ||||
|         return action; | ||||
|       }; | ||||
|  | ||||
|       // EOFA pseudofermion force: see Eqns. (34)-(36) of arXiv:1706.05843 | ||||
|       virtual void deriv(const GaugeField& U, GaugeField& dSdU) | ||||
|       { | ||||
|         Lop.ImportGauge(U); | ||||
|         Rop.ImportGauge(U); | ||||
|  | ||||
|         FermionField spProj_Phi      (Lop.FermionGrid()); | ||||
|         FermionField Omega_spProj_Phi(Lop.FermionGrid()); | ||||
|         FermionField CG_src          (Lop.FermionGrid()); | ||||
|         FermionField Chi             (Lop.FermionGrid()); | ||||
|         FermionField g5_R5_Chi       (Lop.FermionGrid()); | ||||
|  | ||||
|         GaugeField force(Lop.GaugeGrid()); | ||||
|  | ||||
|         // LH: dSdU = k \chi_{L}^{\dagger} \gamma_{5} R_{5} ( \partial_{x,\mu} D_{w} ) \chi_{L} | ||||
|         //     \chi_{L} = H(mf)^{-1} \Omega_{-} P_{-} \Phi | ||||
|         spProj(Phi, spProj_Phi, -1, Lop.Ls); | ||||
|         Lop.Omega(spProj_Phi, Omega_spProj_Phi, -1, 0); | ||||
|         G5R5(CG_src, Omega_spProj_Phi); | ||||
|         spProj_Phi = zero; | ||||
|         Solver(Lop, CG_src, spProj_Phi); | ||||
|         Lop.Dtilde(spProj_Phi, Chi); | ||||
|         G5R5(g5_R5_Chi, Chi); | ||||
|         Lop.MDeriv(force, g5_R5_Chi, Chi, DaggerNo); | ||||
|         dSdU = Lop.k * force; | ||||
|  | ||||
|         // RH: dSdU = dSdU - k \chi_{R}^{\dagger} \gamma_{5} R_{5} ( \partial_{x,\mu} D_{w} ) \chi_{} | ||||
|         //     \chi_{R} = ( H(mb) - \Delta_{+}(mf,mb) P_{+} )^{-1} \Omega_{+} P_{+} \Phi | ||||
|         spProj(Phi, spProj_Phi, 1, Rop.Ls); | ||||
|         Rop.Omega(spProj_Phi, Omega_spProj_Phi, 1, 0); | ||||
|         G5R5(CG_src, Omega_spProj_Phi); | ||||
|         spProj_Phi = zero; | ||||
|         Solver(Rop, CG_src, spProj_Phi); | ||||
|         Rop.Dtilde(spProj_Phi, Chi); | ||||
|         G5R5(g5_R5_Chi, Chi); | ||||
|         Lop.MDeriv(force, g5_R5_Chi, Chi, DaggerNo); | ||||
|         dSdU = dSdU - Rop.k * force; | ||||
|       }; | ||||
|   }; | ||||
| }} | ||||
|  | ||||
| #endif | ||||
| @@ -38,5 +38,6 @@ directory | ||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourRationalRatio.h> | ||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRational.h> | ||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRationalRatio.h> | ||||
| #include <Grid/qcd/action/pseudofermion/ExactOneFlavourRatio.h> | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -72,7 +72,7 @@ protected: | ||||
|   } | ||||
|  | ||||
|   virtual unsigned int Ls(){ | ||||
|     return 0;   | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   virtual void print_parameters(){ | ||||
| @@ -97,7 +97,7 @@ class HMC_FermionOperatorModuleFactory | ||||
|     : public Factory < FermionOperatorModuleBase<QCD::FermionOperator<FermionImpl> > ,  Reader<ReaderClass> > { | ||||
|  public: | ||||
|   // use SINGLETON FUNCTOR MACRO HERE | ||||
|   typedef Reader<ReaderClass> TheReader;  | ||||
|   typedef Reader<ReaderClass> TheReader; | ||||
|  | ||||
|   HMC_FermionOperatorModuleFactory(const HMC_FermionOperatorModuleFactory& e) = delete; | ||||
|   void operator=(const HMC_FermionOperatorModuleFactory& e) = delete; | ||||
| @@ -122,7 +122,7 @@ namespace QCD{ | ||||
| // Modules | ||||
| class WilsonFermionParameters : Serializable { | ||||
|  public: | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(WilsonFermionParameters,  | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(WilsonFermionParameters, | ||||
|     RealD, mass); | ||||
| }; | ||||
|  | ||||
| @@ -144,7 +144,7 @@ class WilsonFermionModule: public FermionOperatorModule<WilsonFermion, FermionIm | ||||
|  | ||||
| class MobiusFermionParameters : Serializable { | ||||
|  public: | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(MobiusFermionParameters,  | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(MobiusFermionParameters, | ||||
|     RealD, mass, | ||||
|     RealD, M5, | ||||
|     RealD, b, | ||||
| @@ -166,7 +166,7 @@ class MobiusFermionModule: public FermionOperatorModule<MobiusFermion, FermionIm | ||||
|     auto GridMod = this->GridRefs[0]; | ||||
|     auto GridMod5d = this->GridRefs[1]; | ||||
|     typename FermionImpl::GaugeField U(GridMod->get_full()); | ||||
|     this->FOPtr.reset(new MobiusFermion<FermionImpl>( U, *(GridMod->get_full()), *(GridMod->get_rb()),  | ||||
|     this->FOPtr.reset(new MobiusFermion<FermionImpl>( U, *(GridMod->get_full()), *(GridMod->get_rb()), | ||||
|                                                       *(GridMod5d->get_full()), *(GridMod5d->get_rb()), | ||||
|                                                       this->Par_.mass, this->Par_.M5, this->Par_.b, this->Par_.c)); | ||||
|   } | ||||
| @@ -175,7 +175,7 @@ class MobiusFermionModule: public FermionOperatorModule<MobiusFermion, FermionIm | ||||
|  | ||||
| class DomainWallFermionParameters : Serializable { | ||||
|  public: | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(DomainWallFermionParameters,  | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(DomainWallFermionParameters, | ||||
|     RealD, mass, | ||||
|     RealD, M5, | ||||
|     unsigned int, Ls); | ||||
| @@ -195,16 +195,49 @@ class DomainWallFermionModule: public FermionOperatorModule<DomainWallFermion, F | ||||
|     auto GridMod = this->GridRefs[0]; | ||||
|     auto GridMod5d = this->GridRefs[1]; | ||||
|     typename FermionImpl::GaugeField U(GridMod->get_full()); | ||||
|     this->FOPtr.reset(new DomainWallFermion<FermionImpl>( U, *(GridMod->get_full()), *(GridMod->get_rb()),  | ||||
|     this->FOPtr.reset(new DomainWallFermion<FermionImpl>( U, *(GridMod->get_full()), *(GridMod->get_rb()), | ||||
|                                                       *(GridMod5d->get_full()), *(GridMod5d->get_rb()), | ||||
|                                                       this->Par_.mass, this->Par_.M5)); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| class DomainWallEOFAFermionParameters : Serializable { | ||||
|  public: | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(DomainWallEOFAFermionParameters, | ||||
|     RealD, mq1, | ||||
|     RealD, mq2, | ||||
|     RealD, mq3, | ||||
|     RealD, shift, | ||||
|     int, pm, | ||||
|     RealD, M5, | ||||
|     unsigned int, Ls); | ||||
| }; | ||||
|  | ||||
| template <class FermionImpl > | ||||
| class DomainWallEOFAFermionModule: public FermionOperatorModule<DomainWallEOFAFermion, FermionImpl, DomainWallEOFAFermionParameters> { | ||||
|   typedef FermionOperatorModule<DomainWallEOFAFermion, FermionImpl, DomainWallEOFAFermionParameters> FermBase; | ||||
|   using FermBase::FermBase; // for constructors | ||||
|  | ||||
|   virtual unsigned int Ls(){ | ||||
|     return this->Par_.Ls; | ||||
|   } | ||||
|  | ||||
|   // acquire resource | ||||
|   virtual void initialize(){ | ||||
|     auto GridMod = this->GridRefs[0]; | ||||
|     auto GridMod5d = this->GridRefs[1]; | ||||
|     typename FermionImpl::GaugeField U(GridMod->get_full()); | ||||
|     this->FOPtr.reset(new DomainWallEOFAFermion<FermionImpl>( U, *(GridMod->get_full()), *(GridMod->get_rb()), | ||||
|                                                       *(GridMod5d->get_full()), *(GridMod5d->get_rb()), | ||||
|                                                       this->Par_.mq1, this->Par_.mq2, this->Par_.mq3, | ||||
|                                                       this->Par_.shift, this->Par_.pm, this->Par_.M5)); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| } // QCD | ||||
| } // Grid | ||||
|  | ||||
|  | ||||
| #endif //FERMIONOPERATOR_MODULES_H | ||||
| #endif //FERMIONOPERATOR_MODULES_H | ||||
|   | ||||
| @@ -60,7 +60,7 @@ GridCartesian         *SpaceTimeGrid::makeFiveDimGrid(int Ls,const GridCartesian | ||||
|     simd5.push_back(FourDimGrid->_simd_layout[d]); | ||||
|      mpi5.push_back(FourDimGrid->_processors[d]); | ||||
|   } | ||||
|   return new GridCartesian(latt5,simd5,mpi5);  | ||||
|   return new GridCartesian(latt5,simd5,mpi5,*FourDimGrid);  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -68,18 +68,14 @@ GridRedBlackCartesian *SpaceTimeGrid::makeFiveDimRedBlackGrid(int Ls,const GridC | ||||
| { | ||||
|   int N4=FourDimGrid->_ndimension; | ||||
|   int cbd=1; | ||||
|   std::vector<int> latt5(1,Ls); | ||||
|   std::vector<int> simd5(1,1); | ||||
|   std::vector<int>  mpi5(1,1); | ||||
|   std::vector<int>   cb5(1,0); | ||||
|      | ||||
|   for(int d=0;d<N4;d++){ | ||||
|     latt5.push_back(FourDimGrid->_fdimensions[d]); | ||||
|     simd5.push_back(FourDimGrid->_simd_layout[d]); | ||||
|      mpi5.push_back(FourDimGrid->_processors[d]); | ||||
|       cb5.push_back(  1); | ||||
|     } | ||||
|   return new GridRedBlackCartesian(latt5,simd5,mpi5,cb5,cbd);  | ||||
|   } | ||||
|   GridCartesian *tmp = makeFiveDimGrid(Ls,FourDimGrid); | ||||
|   GridRedBlackCartesian *ret = new GridRedBlackCartesian(tmp,cb5,cbd);  | ||||
|   delete tmp; | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -97,26 +93,24 @@ GridCartesian         *SpaceTimeGrid::makeFiveDimDWFGrid(int Ls,const GridCartes | ||||
|     simd5.push_back(1); | ||||
|      mpi5.push_back(FourDimGrid->_processors[d]); | ||||
|   } | ||||
|   return new GridCartesian(latt5,simd5,mpi5);  | ||||
|   return new GridCartesian(latt5,simd5,mpi5,*FourDimGrid);  | ||||
| } | ||||
|  | ||||
| /////////////////////////////////////////////////// | ||||
| // Interface is inefficient and forces the deletion | ||||
| // Pass in the non-redblack grid | ||||
| /////////////////////////////////////////////////// | ||||
| GridRedBlackCartesian *SpaceTimeGrid::makeFiveDimDWFRedBlackGrid(int Ls,const GridCartesian *FourDimGrid) | ||||
| { | ||||
|   int N4=FourDimGrid->_ndimension; | ||||
|   int nsimd = FourDimGrid->Nsimd(); | ||||
|   int cbd=1; | ||||
|   std::vector<int> latt5(1,Ls); | ||||
|   std::vector<int> simd5(1,nsimd); | ||||
|   std::vector<int>  mpi5(1,1); | ||||
|   std::vector<int>   cb5(1,0); | ||||
|      | ||||
|   for(int d=0;d<N4;d++){ | ||||
|     latt5.push_back(FourDimGrid->_fdimensions[d]); | ||||
|     simd5.push_back(1); | ||||
|      mpi5.push_back(FourDimGrid->_processors[d]); | ||||
|       cb5.push_back(1); | ||||
|     } | ||||
|   return new GridRedBlackCartesian(latt5,simd5,mpi5,cb5,cbd);  | ||||
|   } | ||||
|   GridCartesian *tmp         = makeFiveDimDWFGrid(Ls,FourDimGrid); | ||||
|   GridRedBlackCartesian *ret = new GridRedBlackCartesian(tmp,cb5,cbd);  | ||||
|   delete tmp; | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -86,7 +86,7 @@ namespace Grid { | ||||
|                                       or element<T>::is_number; | ||||
|   }; | ||||
|    | ||||
|   // Vector flatening utility class //////////////////////////////////////////// | ||||
|   // Vector flattening utility class //////////////////////////////////////////// | ||||
|   // Class to flatten a multidimensional std::vector | ||||
|   template <typename V> | ||||
|   class Flatten | ||||
|   | ||||
| @@ -42,6 +42,7 @@ JSONWriter::~JSONWriter(void) | ||||
|  | ||||
|   // write prettified JSON to file | ||||
|   std::ofstream os(fileName_); | ||||
|   //std::cout << "JSONWriter::~JSONWriter" << std::endl; | ||||
|   os << std::setw(2) << json::parse(ss_.str()) << std::endl; | ||||
| } | ||||
|  | ||||
| @@ -56,6 +57,7 @@ void JSONWriter::push(const string &s) | ||||
|  | ||||
| void JSONWriter::pop(void) | ||||
| { | ||||
|   //std::cout << "JSONWriter::pop" << std::endl; | ||||
|   delete_comma(); | ||||
|   ss_ << "},"; | ||||
| } | ||||
| @@ -67,20 +69,22 @@ void JSONWriter::delete_comma() | ||||
|   ss_.str(dlast); | ||||
| } | ||||
|  | ||||
|  | ||||
| // here we are hitting a g++ bug (Bug 56480) | ||||
| // compiles fine with clang | ||||
| // have to wrap in the Grid namespace | ||||
| // annoying, but necessary for TravisCI | ||||
| namespace Grid | ||||
| { | ||||
|   template<> | ||||
|   void JSONWriter::writeDefault(const std::string &s, | ||||
| 				const std::string &x) | ||||
|   void JSONWriter::writeDefault(const std::string &s,	const std::string &x) | ||||
|   { | ||||
|     //std::cout << "JSONWriter::writeDefault(string) : " << s <<  std::endl; | ||||
|     std::ostringstream os; | ||||
|     os << std::boolalpha << x; | ||||
|     if (s.size()) | ||||
|       ss_ << "\""<< s << "\" : \"" << x << "\" ," ;  | ||||
|       ss_ << "\""<< s << "\" : \"" << os.str() << "\" ," ; | ||||
|     else | ||||
|       ss_ << "\"" << x << "\" ," ; | ||||
|      ss_ << os.str() << " ," ; | ||||
|   } | ||||
| }// namespace Grid  | ||||
|  | ||||
| @@ -138,6 +142,7 @@ void JSONReader::pop(void) | ||||
|  | ||||
| bool JSONReader::nextElement(const std::string &s) | ||||
| { | ||||
|   // Work in progress | ||||
|   // JSON dictionaries do not support multiple names  | ||||
|   // Same name objects must be packed in vectors | ||||
|   ++it_; | ||||
|   | ||||
| @@ -58,10 +58,15 @@ namespace Grid | ||||
|     void writeDefault(const std::string &s, const std::complex<U> &x); | ||||
|     template <typename U> | ||||
|     void writeDefault(const std::string &s, const std::vector<U> &x); | ||||
|     template <typename U, typename P> | ||||
|     void writeDefault(const std::string &s, const std::pair<U,P> &x); | ||||
|  | ||||
|     template<std::size_t N> | ||||
|     void writeDefault(const std::string &s, const char(&x)[N]); | ||||
|  | ||||
|     void writeDefault(const std::string &s, const std::string &x); | ||||
|  | ||||
|  | ||||
|   private: | ||||
|     void delete_comma(); | ||||
|     std::string         fileName_; | ||||
| @@ -82,6 +87,8 @@ namespace Grid | ||||
|     void readDefault(const std::string &s, std::complex<U> &output); | ||||
|     template <typename U> | ||||
|     void readDefault(const std::string &s, std::vector<U> &output); | ||||
|     template <typename U, typename P> | ||||
|     void readDefault(const std::string &s, std::pair<U,P> &output); | ||||
|   private: | ||||
|     json                jobject_; // main object | ||||
|     json                jcur_;  // current json object | ||||
| @@ -106,7 +113,7 @@ namespace Grid | ||||
|   template <typename U> | ||||
|   void JSONWriter::writeDefault(const std::string &s, const U &x) | ||||
|   { | ||||
|     //std::cout << "JSONReader::writeDefault(U) : " << s <<  std::endl; | ||||
|     //std::cout << "JSONWriter::writeDefault(U) : " << s <<  " " << x <<std::endl; | ||||
|     std::ostringstream os; | ||||
|     os << std::boolalpha << x; | ||||
|     if (s.size()) | ||||
| @@ -118,7 +125,7 @@ namespace Grid | ||||
|   template <typename U> | ||||
|   void JSONWriter::writeDefault(const std::string &s, const std::complex<U> &x) | ||||
|   { | ||||
|     //std::cout << "JSONReader::writeDefault(complex) : " << s <<  std::endl; | ||||
|     //std::cout << "JSONWriter::writeDefault(complex) : " << s <<  " " << x <<  std::endl; | ||||
|     std::ostringstream os; | ||||
|     os << "["<< std::boolalpha << x.real() << ", " << x.imag() << "]"; | ||||
|     if (s.size()) | ||||
| @@ -127,10 +134,22 @@ namespace Grid | ||||
|      ss_ << os.str() << " ," ; | ||||
|   } | ||||
|  | ||||
|   template <typename U, typename P> | ||||
|   void JSONWriter::writeDefault(const std::string &s, const std::pair<U,P> &x) | ||||
|   { | ||||
|     //std::cout << "JSONWriter::writeDefault(pair) : " << s <<  " " << x <<  std::endl; | ||||
|     std::ostringstream os; | ||||
|     os << "["<< std::boolalpha << "\""<< x.first << "\" , \"" << x.second << "\" ]"; | ||||
|     if (s.size()) | ||||
|       ss_ << "\""<< s << "\" : " << os.str() << " ," ; | ||||
|     else | ||||
|      ss_ << os.str() << " ," ; | ||||
|   } | ||||
|  | ||||
|   template <typename U> | ||||
|   void JSONWriter::writeDefault(const std::string &s, const std::vector<U> &x) | ||||
|   { | ||||
|     //std::cout << "JSONReader::writeDefault(vec U) : " << s <<  std::endl; | ||||
|     //std::cout << "JSONWriter::writeDefault(vec U) : " << s <<  std::endl; | ||||
|  | ||||
|     if (s.size()) | ||||
|       ss_ << " \""<<s<<"\" : ["; | ||||
| @@ -146,12 +165,12 @@ namespace Grid | ||||
|  | ||||
|   template<std::size_t N> | ||||
|   void JSONWriter::writeDefault(const std::string &s, const char(&x)[N]){ | ||||
|     //std::cout << "JSONReader::writeDefault(char U) : " << s <<  std::endl; | ||||
|     //std::cout << "JSONWriter::writeDefault(char U) : " << s <<  "  " << x << std::endl; | ||||
|  | ||||
|     if (s.size()) | ||||
|     ss_ << "\""<< s << "\" : \"" << x << "\" ," ; | ||||
|       ss_ << "\""<< s << "\" : \"" << x << "\" ," ; | ||||
|     else | ||||
|     ss_ << "\"" << x << "\" ," ; | ||||
|       ss_ << "\"" << x << "\" ," ; | ||||
|   } | ||||
|  | ||||
|   // Reader template implementation //////////////////////////////////////////// | ||||
| @@ -173,11 +192,35 @@ namespace Grid | ||||
|  | ||||
|   } | ||||
|  | ||||
|   // Reader template implementation //////////////////////////////////////////// | ||||
|   template <typename U, typename P> | ||||
|   void JSONReader::readDefault(const std::string &s, std::pair<U,P> &output) | ||||
|   { | ||||
|     U first; | ||||
|     P second; | ||||
|     json j; | ||||
|     if (s.size()){ | ||||
|       //std::cout << "JSONReader::readDefault(pair) : " << s << "  |  "<< jcur_[s] << std::endl; | ||||
|       j = jcur_[s]; | ||||
|     } else { | ||||
|       j = jcur_; | ||||
|     } | ||||
|     json::iterator it = j.begin(); | ||||
|     jcur_ = *it; | ||||
|     read("", first); | ||||
|     it++; | ||||
|     jcur_ = *it; | ||||
|     read("", second); | ||||
|     output = std::pair<U,P>(first,second); | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
|   template <typename U> | ||||
|   void JSONReader::readDefault(const std::string &s, std::complex<U> &output) | ||||
|   { | ||||
|     U tmp1, tmp2; | ||||
|     //std::cout << "JSONReader::readDefault( complex U) : " << s << "  :  "<< jcur_ << std::endl; | ||||
|     //std::cout << "JSONReader::readDefault(complex U) : " << s << "  :  "<< jcur_ << std::endl; | ||||
|     json j = jcur_; | ||||
|     json::iterator it = j.begin(); | ||||
|     jcur_ = *it; | ||||
|   | ||||
| @@ -82,11 +82,11 @@ namespace Optimization { | ||||
|       double tmp[2]={a,b}; | ||||
|       return vld1q_f64(tmp); | ||||
|     } | ||||
|     //Real double // N:tbc | ||||
|     //Real double | ||||
|     inline float64x2_t operator()(double a){ | ||||
|       return vdupq_n_f64(a); | ||||
|     } | ||||
|     //Integer // N:tbc | ||||
|     //Integer | ||||
|     inline uint32x4_t operator()(Integer a){ | ||||
|       return vdupq_n_u32(a); | ||||
|     } | ||||
| @@ -124,33 +124,32 @@ namespace Optimization { | ||||
|   // Nils: Vset untested; not used currently in Grid at all; | ||||
|   // git commit 4a8c4ccfba1d05159348d21a9698028ea847e77b | ||||
|   struct Vset{ | ||||
|     // Complex float // N:ok | ||||
|     // Complex float | ||||
|     inline float32x4_t operator()(Grid::ComplexF *a){ | ||||
|       float tmp[4]={a[1].imag(),a[1].real(),a[0].imag(),a[0].real()}; | ||||
|       return vld1q_f32(tmp); | ||||
|     } | ||||
|     // Complex double // N:ok | ||||
|     // Complex double | ||||
|     inline float64x2_t operator()(Grid::ComplexD *a){ | ||||
|       double tmp[2]={a[0].imag(),a[0].real()}; | ||||
|       return vld1q_f64(tmp); | ||||
|     } | ||||
|     // Real float // N:ok | ||||
|     // Real float | ||||
|     inline float32x4_t operator()(float *a){ | ||||
|       float tmp[4]={a[3],a[2],a[1],a[0]}; | ||||
|       return vld1q_f32(tmp); | ||||
|     } | ||||
|     // Real double // N:ok | ||||
|     // Real double | ||||
|     inline float64x2_t operator()(double *a){ | ||||
|       double tmp[2]={a[1],a[0]}; | ||||
|       return vld1q_f64(tmp); | ||||
|     } | ||||
|     // Integer // N:ok | ||||
|     // Integer | ||||
|     inline uint32x4_t operator()(Integer *a){ | ||||
|       return vld1q_dup_u32(a); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   // N:leaving as is | ||||
|   template <typename Out_type, typename In_type> | ||||
|   struct Reduce{ | ||||
|     //Need templated class to overload output type | ||||
| @@ -249,9 +248,9 @@ namespace Optimization { | ||||
|       return vfmaq_f32(r4, r0, a); //  ar*br-ai*bi ai*br+ar*bi ... | ||||
|  | ||||
|       // no fma, use mul and add | ||||
|       //float32x4_t r5; | ||||
|       //r5 = vmulq_f32(r0, a); | ||||
|       //return vaddq_f32(r4, r5); | ||||
|       // float32x4_t r5; | ||||
|       // r5 = vmulq_f32(r0, a); | ||||
|       // return vaddq_f32(r4, r5); | ||||
|     } | ||||
|     // Complex double | ||||
|     inline float64x2_t operator()(float64x2_t a, float64x2_t b){ | ||||
| @@ -272,9 +271,9 @@ namespace Optimization { | ||||
|       return vfmaq_f64(r4, r0, a); //  ar*br-ai*bi ai*br+ar*bi | ||||
|  | ||||
|       // no fma, use mul and add | ||||
|       //float64x2_t r5; | ||||
|       //r5 = vmulq_f64(r0, a); | ||||
|       //return vaddq_f64(r4, r5); | ||||
|       // float64x2_t r5; | ||||
|       // r5 = vmulq_f64(r0, a); | ||||
|       // return vaddq_f64(r4, r5); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
| @@ -421,11 +420,6 @@ namespace Optimization { | ||||
|       } | ||||
|     } | ||||
|  | ||||
| // working, but no restriction on n | ||||
| //    template<int n> static inline float32x4_t tRotate(float32x4_t in){ return vextq_f32(in,in,n); }; | ||||
| //    template<int n> static inline float64x2_t tRotate(float64x2_t in){ return vextq_f64(in,in,n); }; | ||||
|  | ||||
| // restriction on n | ||||
|     template<int n> static inline float32x4_t tRotate(float32x4_t in){ return vextq_f32(in,in,n%4); }; | ||||
|     template<int n> static inline float64x2_t tRotate(float64x2_t in){ return vextq_f64(in,in,n%2); }; | ||||
|  | ||||
| @@ -441,7 +435,7 @@ namespace Optimization { | ||||
|       sb = vcvt_high_f32_f16(h); | ||||
|       // there is no direct conversion from lower float32x4_t to float64x2_t | ||||
|       // vextq_f16 not supported by clang 3.8 / 4.0 / arm clang | ||||
|       //float16x8_t h1 = vextq_f16(h, h, 4); // correct, but not supported by clang | ||||
|       // float16x8_t h1 = vextq_f16(h, h, 4); // correct, but not supported by clang | ||||
|       // workaround for clang | ||||
|       uint32x4_t h1u = reinterpret_cast<uint32x4_t>(h); | ||||
|       float16x8_t h1 = reinterpret_cast<float16x8_t>(vextq_u32(h1u, h1u, 2)); | ||||
| @@ -547,7 +541,7 @@ namespace Optimization { | ||||
|  | ||||
|  | ||||
|   //Complex double Reduce | ||||
|   template<> // N:by Boyle | ||||
|   template<> | ||||
|   inline Grid::ComplexD Reduce<Grid::ComplexD, float64x2_t>::operator()(float64x2_t in){ | ||||
|     u128d conv; conv.v = in; | ||||
|     return Grid::ComplexD(conv.f[0],conv.f[1]); | ||||
| @@ -562,9 +556,7 @@ namespace Optimization { | ||||
|   //Integer Reduce | ||||
|   template<> | ||||
|   inline Integer Reduce<Integer, uint32x4_t>::operator()(uint32x4_t in){ | ||||
|     // FIXME unimplemented | ||||
|     printf("Reduce : Missing integer implementation -> FIX\n"); | ||||
|     assert(0); | ||||
|     return vaddvq_u32(in); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -603,4 +595,5 @@ namespace Optimization { | ||||
|   typedef Optimization::TimesMinusI TimesMinusISIMD; | ||||
|   typedef Optimization::TimesI      TimesISIMD; | ||||
|  | ||||
| } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -376,7 +376,18 @@ class Grid_simd { | ||||
|       Optimization::Exchange::Exchange0(out1.v,out2.v,in1.v,in2.v); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   friend inline void exchange0(Grid_simd &out1,Grid_simd &out2,Grid_simd in1,Grid_simd in2){     | ||||
|     Optimization::Exchange::Exchange0(out1.v,out2.v,in1.v,in2.v); | ||||
|   } | ||||
|   friend inline void exchange1(Grid_simd &out1,Grid_simd &out2,Grid_simd in1,Grid_simd in2){     | ||||
|     Optimization::Exchange::Exchange1(out1.v,out2.v,in1.v,in2.v); | ||||
|   } | ||||
|   friend inline void exchange2(Grid_simd &out1,Grid_simd &out2,Grid_simd in1,Grid_simd in2){     | ||||
|     Optimization::Exchange::Exchange2(out1.v,out2.v,in1.v,in2.v); | ||||
|   } | ||||
|   friend inline void exchange3(Grid_simd &out1,Grid_simd &out2,Grid_simd in1,Grid_simd in2){     | ||||
|     Optimization::Exchange::Exchange3(out1.v,out2.v,in1.v,in2.v); | ||||
|   } | ||||
|   //////////////////////////////////////////////////////////////////// | ||||
|   // General permute; assumes vector length is same across | ||||
|   // all subtypes; may not be a good assumption, but could | ||||
|   | ||||
| @@ -400,11 +400,13 @@ class CartesianStencil { // Stencil runs along coordinate axes only; NO diagonal | ||||
|       if ( sshift[0] == sshift[1] ) { | ||||
| 	if (splice_dim) { | ||||
| 	  splicetime-=usecond(); | ||||
| 	  same_node = same_node && GatherSimd(source,dimension,shift,0x3,compress,face_idx); | ||||
| 	  auto tmp  = GatherSimd(source,dimension,shift,0x3,compress,face_idx); | ||||
| 	  same_node = same_node && tmp; | ||||
| 	  splicetime+=usecond(); | ||||
| 	} else {  | ||||
| 	  nosplicetime-=usecond(); | ||||
| 	  same_node = same_node && Gather(source,dimension,shift,0x3,compress,face_idx); | ||||
| 	  auto tmp  = Gather(source,dimension,shift,0x3,compress,face_idx); | ||||
| 	  same_node = same_node && tmp; | ||||
| 	  nosplicetime+=usecond(); | ||||
| 	} | ||||
|       } else { | ||||
| @@ -412,13 +414,15 @@ class CartesianStencil { // Stencil runs along coordinate axes only; NO diagonal | ||||
| 	  splicetime-=usecond(); | ||||
| 	  // if checkerboard is unfavourable take two passes | ||||
| 	  // both with block stride loop iteration | ||||
| 	  same_node = same_node && GatherSimd(source,dimension,shift,0x1,compress,face_idx); | ||||
| 	  same_node = same_node && GatherSimd(source,dimension,shift,0x2,compress,face_idx); | ||||
| 	  auto tmp1 =  GatherSimd(source,dimension,shift,0x1,compress,face_idx); | ||||
| 	  auto tmp2 =  GatherSimd(source,dimension,shift,0x2,compress,face_idx); | ||||
| 	  same_node = same_node && tmp1 && tmp2; | ||||
| 	  splicetime+=usecond(); | ||||
| 	} else { | ||||
| 	  nosplicetime-=usecond(); | ||||
| 	  same_node = same_node && Gather(source,dimension,shift,0x1,compress,face_idx); | ||||
| 	  same_node = same_node && Gather(source,dimension,shift,0x2,compress,face_idx); | ||||
| 	  auto tmp1 = Gather(source,dimension,shift,0x1,compress,face_idx); | ||||
| 	  auto tmp2 = Gather(source,dimension,shift,0x2,compress,face_idx); | ||||
| 	  same_node = same_node && tmp1 && tmp2; | ||||
| 	  nosplicetime+=usecond(); | ||||
| 	} | ||||
|       } | ||||
|   | ||||
| @@ -175,7 +175,7 @@ class TensorIndexRecursion { | ||||
|       } | ||||
|     } | ||||
|   template<class vtype,int N> inline static  | ||||
|     void pokeIndex(iVector<vtype,N> &ret, const iVector<decltype(TensorIndexRecursion<Level-1>::peekIndex(ret._internal[0],0)),N> &arg, int i,int j) | ||||
|     void pokeIndex(iVector<vtype,N> &ret, const iVector<decltype(TensorIndexRecursion<Level-1>::peekIndex(ret._internal[0],0,0)),N> &arg, int i,int j) | ||||
|     { | ||||
|       for(int ii=0;ii<N;ii++){ | ||||
| 	TensorIndexRecursion<Level-1>::pokeIndex(ret._internal[ii],arg._internal[ii],i,j); | ||||
| @@ -191,7 +191,7 @@ class TensorIndexRecursion { | ||||
|       }} | ||||
|     } | ||||
|   template<class vtype,int N> inline static  | ||||
|     void pokeIndex(iMatrix<vtype,N> &ret, const iMatrix<decltype(TensorIndexRecursion<Level-1>::peekIndex(ret._internal[0][0],0)),N> &arg, int i,int j) | ||||
|     void pokeIndex(iMatrix<vtype,N> &ret, const iMatrix<decltype(TensorIndexRecursion<Level-1>::peekIndex(ret._internal[0][0],0,0)),N> &arg, int i,int j) | ||||
|     { | ||||
|       for(int ii=0;ii<N;ii++){ | ||||
|       for(int jj=0;jj<N;jj++){ | ||||
|   | ||||
| @@ -7,7 +7,7 @@ namespace Grid{ | ||||
|   class Lexicographic { | ||||
|   public: | ||||
|  | ||||
|     static inline void CoorFromIndex (std::vector<int>& coor,int index,std::vector<int> &dims){ | ||||
|     static inline void CoorFromIndex (std::vector<int>& coor,int index,const std::vector<int> &dims){ | ||||
|       int nd= dims.size(); | ||||
|       coor.resize(nd); | ||||
|       for(int d=0;d<nd;d++){ | ||||
| @@ -16,7 +16,7 @@ namespace Grid{ | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     static inline void IndexFromCoor (std::vector<int>& coor,int &index,std::vector<int> &dims){ | ||||
|     static inline void IndexFromCoor (const std::vector<int>& coor,int &index,const std::vector<int> &dims){ | ||||
|       int nd=dims.size(); | ||||
|       int stride=1; | ||||
|       index=0; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./tests/Test_serialisation.cc | ||||
|  | ||||
| @@ -29,12 +29,11 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
|     /*  END LEGAL */ | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
|  | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| GRID_SERIALIZABLE_ENUM(myenum, undef, red, 1, blue, 2, green, 3); | ||||
|    | ||||
|  | ||||
| class myclass: Serializable { | ||||
| public: | ||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(myclass, | ||||
| @@ -79,14 +78,14 @@ void ioTest(const std::string &filename, const O &object, const std::string &nam | ||||
|   // writer needs to be destroyed so that writing physically happens | ||||
|   { | ||||
|     W writer(filename); | ||||
|      | ||||
|  | ||||
|     write(writer, "testobject", object); | ||||
|   } | ||||
|    | ||||
|  | ||||
|   R    reader(filename); | ||||
|   O    buf; | ||||
|   bool good; | ||||
|    | ||||
|  | ||||
|   read(reader, "testobject", buf); | ||||
|   good = (object == buf); | ||||
|   std::cout << name << " IO test: " << (good ? "success" : "failure"); | ||||
| @@ -98,7 +97,7 @@ int main(int argc,char **argv) | ||||
| { | ||||
|   std::cout << "==== basic IO" << std::endl; | ||||
|   XmlWriter WR("bother.xml"); | ||||
|    | ||||
|  | ||||
|   // test basic type writing | ||||
|   std::cout << "-- basic writing to 'bother.xml'..." << std::endl; | ||||
|   push(WR,"BasicTypes"); | ||||
| @@ -112,12 +111,12 @@ int main(int argc,char **argv) | ||||
|   write(WR,"d",d); | ||||
|   write(WR,"b",b); | ||||
|   pop(WR); | ||||
|    | ||||
|  | ||||
|   // test serializable class writing | ||||
|   myclass              obj(1234); // non-trivial constructor | ||||
|   std::vector<myclass> vec; | ||||
|   std::pair<myenum, myenum> pair; | ||||
|    | ||||
|  | ||||
|   std::cout << "-- serialisable class writing to 'bother.xml'..." << std::endl; | ||||
|   write(WR,"obj",obj); | ||||
|   WR.write("obj2", obj); | ||||
| @@ -132,11 +131,11 @@ int main(int argc,char **argv) | ||||
|   std::cout << "-- serialisable class comparison:" << std::endl; | ||||
|   std::cout << "vec[0] == obj: " << ((vec[0] == obj) ? "true" : "false") << std::endl; | ||||
|   std::cout << "vec[1] == obj: " << ((vec[1] == obj) ? "true" : "false") << std::endl; | ||||
|    | ||||
|  | ||||
|   write(WR, "objpair", pair); | ||||
|   std::cout << "-- pair writing to std::cout:" << std::endl; | ||||
|   std::cout << pair << std::endl; | ||||
|    | ||||
|  | ||||
|   // read tests | ||||
|   std::cout << "\n==== IO self-consistency tests" << std::endl; | ||||
|   //// XML | ||||
| @@ -151,6 +150,11 @@ int main(int argc,char **argv) | ||||
|   ioTest<TextWriter, TextReader>("iotest.dat", obj, "text   (object)           "); | ||||
|   ioTest<TextWriter, TextReader>("iotest.dat", vec, "text   (vector of objects)"); | ||||
|   ioTest<TextWriter, TextReader>("iotest.dat", pair, "text   (pair of objects)"); | ||||
|   //// text | ||||
|   ioTest<JSONWriter, JSONReader>("iotest.json", obj,  "JSON   (object)           "); | ||||
|   ioTest<JSONWriter, JSONReader>("iotest.json", vec,  "JSON   (vector of objects)"); | ||||
|   ioTest<JSONWriter, JSONReader>("iotest.json", pair, "JSON   (pair of objects)"); | ||||
|  | ||||
|   //// HDF5 | ||||
| #undef HAVE_HDF5 | ||||
| #ifdef HAVE_HDF5 | ||||
| @@ -158,13 +162,13 @@ int main(int argc,char **argv) | ||||
|   ioTest<Hdf5Writer, Hdf5Reader>("iotest.h5", vec, "HDF5   (vector of objects)"); | ||||
|   ioTest<Hdf5Writer, Hdf5Reader>("iotest.h5", pair, "HDF5   (pair of objects)"); | ||||
| #endif | ||||
|    | ||||
|  | ||||
|   std::cout << "\n==== vector flattening/reconstruction" << std::endl; | ||||
|   typedef std::vector<std::vector<std::vector<double>>> vec3d; | ||||
|    | ||||
|  | ||||
|   vec3d dv, buf; | ||||
|   double d = 0.; | ||||
|    | ||||
|  | ||||
|   dv.resize(4); | ||||
|   for (auto &v1: dv) | ||||
|   { | ||||
| @@ -180,14 +184,14 @@ int main(int argc,char **argv) | ||||
|   } | ||||
|   std::cout << "original 3D vector:" << std::endl; | ||||
|   std::cout << dv << std::endl; | ||||
|    | ||||
|  | ||||
|   Flatten<vec3d> flatdv(dv); | ||||
|    | ||||
|  | ||||
|   std::cout << "\ndimensions:" << std::endl; | ||||
|   std::cout << flatdv.getDim() << std::endl; | ||||
|   std::cout << "\nflattened vector:" << std::endl; | ||||
|   std::cout << flatdv.getFlatVector() << std::endl; | ||||
|    | ||||
|  | ||||
|   Reconstruct<vec3d> rec(flatdv.getFlatVector(), flatdv.getDim()); | ||||
|   std::cout << "\nreconstructed vector:" << std::endl; | ||||
|   std::cout << flatdv.getVector() << std::endl; | ||||
| @@ -199,10 +203,12 @@ int main(int argc,char **argv) | ||||
|  | ||||
|   { | ||||
|     JSONWriter JW("bother.json"); | ||||
|      | ||||
|  | ||||
|     // test basic type writing | ||||
|     myenum a = myenum::red; | ||||
|     push(JW,"BasicTypes"); | ||||
|     write(JW,std::string("i16"),i16); | ||||
|     write(JW,"myenum",a); | ||||
|     write(JW,"u16",u16); | ||||
|     write(JW,"i32",i32); | ||||
|     write(JW,"u32",u32); | ||||
| @@ -212,23 +218,25 @@ int main(int argc,char **argv) | ||||
|     write(JW,"d",d); | ||||
|     write(JW,"b",b); | ||||
|     pop(JW); | ||||
|      | ||||
|  | ||||
|  | ||||
|     // test serializable class writing | ||||
|     myclass obj(1234); // non-trivial constructor | ||||
|     std::cout << obj << std::endl; | ||||
|     std::cout << "-- serialisable class writing to 'bother.json'..." << std::endl; | ||||
|     write(JW,"obj",obj); | ||||
|     JW.write("obj2", obj); | ||||
|      | ||||
|     std::cout << obj << std::endl; | ||||
|      | ||||
|  | ||||
|  | ||||
|     std::vector<myclass> vec; | ||||
|     vec.push_back(myclass(1234)); | ||||
|     vec.push_back(myclass(5678)); | ||||
|     vec.push_back(myclass(3838)); | ||||
|     write(JW, "objvec", vec); | ||||
|      | ||||
|  | ||||
|   } | ||||
|  | ||||
|  | ||||
|   { | ||||
|     JSONReader RD("bother.json"); | ||||
|     myclass jcopy1; | ||||
| @@ -238,8 +246,9 @@ int main(int argc,char **argv) | ||||
|     std::cout << "Loaded (JSON) -----------------" << std::endl; | ||||
|     std::cout << jcopy1 << std::endl << jveccopy1 << std::endl; | ||||
|   } | ||||
|    | ||||
| /*  | ||||
|   | ||||
|  | ||||
| /* | ||||
|   // This is still work in progress | ||||
|   { | ||||
|     // Testing the next element function | ||||
|   | ||||
| @@ -80,31 +80,47 @@ int main (int argc, char ** argv) | ||||
|  | ||||
|  | ||||
|   LatticeFermionD    src_o(FrbGrid); | ||||
|   LatticeFermionD result_o(FrbGrid); | ||||
|   LatticeFermionD result_o_2(FrbGrid); | ||||
|   LatticeFermionD result_cg(FrbGrid); | ||||
|   pickCheckerboard(Odd,src_o,src); | ||||
|   result_o.checkerboard = Odd; | ||||
|   result_o = zero; | ||||
|   result_o_2.checkerboard = Odd; | ||||
|   result_o_2 = zero; | ||||
|   result_cg.checkerboard = Odd; | ||||
|   result_cg = zero; | ||||
|   LatticeFermionD result_mcg(result_cg); | ||||
|   LatticeFermionD result_rlcg(result_cg); | ||||
|  | ||||
|   SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf); | ||||
|   SchurDiagMooeeOperator<DomainWallFermionFH,LatticeFermionF> HermOpEO_f(Ddwf_f); | ||||
|  | ||||
|   //#define DO_MIXED_CG | ||||
| #define DO_RLUP_CG | ||||
|  | ||||
| #ifdef DO_MIXED_CG | ||||
|   std::cout << "Starting mixed CG" << std::endl; | ||||
|   MixedPrecisionConjugateGradient<LatticeFermionD,LatticeFermionF> mCG(1.0e-8, 10000, 50, FrbGrid_f, HermOpEO_f, HermOpEO); | ||||
|   mCG.InnerTolerance = 3.0e-5; | ||||
|   mCG(src_o,result_o); | ||||
|   mCG(src_o,result_mcg); | ||||
| #endif | ||||
|  | ||||
| #ifdef DO_RLUP_CG | ||||
|   std::cout << "Starting reliable update CG" << std::endl; | ||||
|   ConjugateGradientReliableUpdate<LatticeFermionD,LatticeFermionF> rlCG(1.e-8, 10000, 0.1, FrbGrid_f, HermOpEO_f, HermOpEO); | ||||
|   rlCG(src_o,result_rlcg); | ||||
| #endif | ||||
|    | ||||
|   std::cout << "Starting regular CG" << std::endl; | ||||
|   ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000); | ||||
|   CG(HermOpEO,src_o,result_o_2); | ||||
|   CG(HermOpEO,src_o,result_cg); | ||||
|  | ||||
|   LatticeFermionD diff_o(FrbGrid); | ||||
|   RealD diff = axpy_norm(diff_o, -1.0, result_o, result_o_2); | ||||
|  | ||||
|   std::cout << "Diff between mixed and regular CG: " << diff << std::endl; | ||||
| #ifdef DO_MIXED_CG | ||||
|   LatticeFermionD diff_mcg(FrbGrid); | ||||
|   RealD vdiff_mcg = axpy_norm(diff_mcg, -1.0, result_cg, result_mcg); | ||||
|   std::cout << "Diff between mixed and regular CG: " << vdiff_mcg << std::endl; | ||||
| #endif | ||||
|  | ||||
| #ifdef DO_RLUP_CG | ||||
|   LatticeFermionD diff_rlcg(FrbGrid); | ||||
|   RealD vdiff_rlcg = axpy_norm(diff_rlcg, -1.0, result_cg, result_rlcg); | ||||
|   std::cout << "Diff between reliable update and regular CG: " << vdiff_rlcg << std::endl; | ||||
| #endif | ||||
|    | ||||
|   Grid_finalize(); | ||||
| } | ||||
|   | ||||
| @@ -48,7 +48,7 @@ int main(int argc, char ** argv) { | ||||
|   double volume = latt_size[0]*latt_size[1]*latt_size[2]*latt_size[3]; | ||||
|  | ||||
|   GridCartesian Fine(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian rbFine(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian rbFine(&Fine); | ||||
|   GridParallelRNG       fRNG(&Fine); | ||||
|  | ||||
|   //  fRNG.SeedFixedIntegers(std::vector<int>({45,12,81,9}); | ||||
|   | ||||
| @@ -47,7 +47,7 @@ int main (int argc, char ** argv) | ||||
|   mask[0]=0; | ||||
|  | ||||
|   GridCartesian         Fine  (latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian RBFine(latt_size,simd_layout,mpi_layout,mask,1); | ||||
|   GridRedBlackCartesian RBFine(&Fine,mask,1); | ||||
|  | ||||
|   GridParallelRNG      FineRNG(&Fine);  FineRNG.SeedFixedIntegers(std::vector<int>({45,12,81,9})); | ||||
|  | ||||
|   | ||||
| @@ -47,7 +47,7 @@ int main (int argc, char ** argv) | ||||
|   mask[0]=0; | ||||
|  | ||||
|   GridCartesian         Fine  (latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian RBFine(latt_size,simd_layout,mpi_layout,mask,1); | ||||
|   GridRedBlackCartesian RBFine(&Fine,mask,1); | ||||
|  | ||||
|   GridParallelRNG      FineRNG(&Fine);  FineRNG.SeedFixedIntegers(std::vector<int>({45,12,81,9})); | ||||
|  | ||||
|   | ||||
							
								
								
									
										239
									
								
								tests/core/Test_dwf_eofa_even_odd.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								tests/core/Test_dwf_eofa_even_odd.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,239 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/core/Test_dwf_eofa_even_odd.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| template<class d> | ||||
| struct scal { | ||||
|     d internal; | ||||
| }; | ||||
|  | ||||
| Gamma::Algebra Gmu [] = { | ||||
|     Gamma::Algebra::GammaX, | ||||
|     Gamma::Algebra::GammaY, | ||||
|     Gamma::Algebra::GammaZ, | ||||
|     Gamma::Algebra::GammaT | ||||
| }; | ||||
|  | ||||
| int main (int argc, char ** argv) | ||||
| { | ||||
|     Grid_init(&argc, &argv); | ||||
|  | ||||
|     int threads = GridThread::GetThreads(); | ||||
|     std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|     const int Ls = 8; | ||||
|     // GridCartesian*         UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|     GridCartesian*         UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|     GridCartesian*         FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|     GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|     GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|     std::vector<int> seeds4({1,2,3,4}); | ||||
|     std::vector<int> seeds5({5,6,7,8}); | ||||
|  | ||||
|     GridParallelRNG RNG4(UGrid); RNG4.SeedFixedIntegers(seeds4); | ||||
|     GridParallelRNG RNG5(FGrid); RNG5.SeedFixedIntegers(seeds5); | ||||
|  | ||||
|     LatticeFermion    src   (FGrid); random(RNG5, src); | ||||
|     LatticeFermion    phi   (FGrid); random(RNG5, phi); | ||||
|     LatticeFermion    chi   (FGrid); random(RNG5, chi); | ||||
|     LatticeFermion    result(FGrid); result = zero; | ||||
|     LatticeFermion    ref   (FGrid); ref = zero; | ||||
|     LatticeFermion    tmp   (FGrid); tmp = zero; | ||||
|     LatticeFermion    err   (FGrid); err = zero; | ||||
|     LatticeGaugeField Umu   (UGrid); SU3::HotConfiguration(RNG4, Umu); | ||||
|     std::vector<LatticeColourMatrix> U(4,UGrid); | ||||
|  | ||||
|     // Only one non-zero (y) | ||||
|     Umu = zero; | ||||
|     for(int nn=0; nn<Nd; nn++){ | ||||
|         random(RNG4, U[nn]); | ||||
|         if(nn>0){ U[nn] = zero; } | ||||
|         PokeIndex<LorentzIndex>(Umu, U[nn], nn); | ||||
|     } | ||||
|  | ||||
|     RealD mq1   = 0.1; | ||||
|     RealD mq2   = 0.5; | ||||
|     RealD mq3   = 1.0; | ||||
|     RealD shift = 0.1234; | ||||
|     RealD M5    = 1.8; | ||||
|     int   pm    = 1; | ||||
|     DomainWallEOFAFermionR Ddwf(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mq1, mq2, mq3, shift, pm, M5); | ||||
|  | ||||
|     LatticeFermion src_e (FrbGrid); | ||||
|     LatticeFermion src_o (FrbGrid); | ||||
|     LatticeFermion r_e   (FrbGrid); | ||||
|     LatticeFermion r_o   (FrbGrid); | ||||
|     LatticeFermion r_eo  (FGrid); | ||||
|     LatticeFermion r_eeoo(FGrid); | ||||
|  | ||||
|     std::cout << GridLogMessage << "==========================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Testing that Meo + Moe + Moo + Mee = Munprec " << std::endl; | ||||
|     std::cout << GridLogMessage << "==========================================================" << std::endl; | ||||
|  | ||||
|     pickCheckerboard(Even, src_e, src); | ||||
|     pickCheckerboard(Odd,  src_o, src); | ||||
|  | ||||
|     Ddwf.Meooe(src_e, r_o); std::cout << GridLogMessage << "Applied Meo" << std::endl; | ||||
|     Ddwf.Meooe(src_o, r_e); std::cout << GridLogMessage << "Applied Moe" << std::endl; | ||||
|     setCheckerboard(r_eo, r_o); | ||||
|     setCheckerboard(r_eo, r_e); | ||||
|  | ||||
|     Ddwf.Mooee(src_e, r_e); std::cout << GridLogMessage << "Applied Mee" << std::endl; | ||||
|     Ddwf.Mooee(src_o, r_o); std::cout << GridLogMessage << "Applied Moo" << std::endl; | ||||
|     setCheckerboard(r_eeoo, r_e); | ||||
|     setCheckerboard(r_eeoo, r_o); | ||||
|  | ||||
|     r_eo = r_eo + r_eeoo; | ||||
|     Ddwf.M(src, ref); | ||||
|  | ||||
|     // std::cout << GridLogMessage << r_eo << std::endl; | ||||
|     // std::cout << GridLogMessage << ref  << std::endl; | ||||
|  | ||||
|     err = ref - r_eo; | ||||
|     std::cout << GridLogMessage << "EO norm diff   " << norm2(err) << " " << norm2(ref) << " " << norm2(r_eo) << std::endl; | ||||
|  | ||||
|     LatticeComplex cerr(FGrid); | ||||
|     cerr = localInnerProduct(err,err); | ||||
|     // std::cout << GridLogMessage << cerr << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Test Ddagger is the dagger of D by requiring                " << std::endl; | ||||
|     std::cout << GridLogMessage << "=  < phi | Deo | chi > * = < chi | Deo^dag| phi>  " << std::endl; | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|  | ||||
|     LatticeFermion chi_e (FrbGrid); | ||||
|     LatticeFermion chi_o (FrbGrid); | ||||
|  | ||||
|     LatticeFermion dchi_e(FrbGrid); | ||||
|     LatticeFermion dchi_o(FrbGrid); | ||||
|  | ||||
|     LatticeFermion phi_e (FrbGrid); | ||||
|     LatticeFermion phi_o (FrbGrid); | ||||
|  | ||||
|     LatticeFermion dphi_e(FrbGrid); | ||||
|     LatticeFermion dphi_o(FrbGrid); | ||||
|  | ||||
|     pickCheckerboard(Even, chi_e, chi); | ||||
|     pickCheckerboard(Odd , chi_o, chi); | ||||
|     pickCheckerboard(Even, phi_e, phi); | ||||
|     pickCheckerboard(Odd , phi_o, phi); | ||||
|  | ||||
|     Ddwf.Meooe   (chi_e, dchi_o); | ||||
|     Ddwf.Meooe   (chi_o, dchi_e); | ||||
|     Ddwf.MeooeDag(phi_e, dphi_o); | ||||
|     Ddwf.MeooeDag(phi_o, dphi_e); | ||||
|  | ||||
|     ComplexD pDce = innerProduct(phi_e, dchi_e); | ||||
|     ComplexD pDco = innerProduct(phi_o, dchi_o); | ||||
|     ComplexD cDpe = innerProduct(chi_e, dphi_e); | ||||
|     ComplexD cDpo = innerProduct(chi_o, dphi_o); | ||||
|  | ||||
|     std::cout << GridLogMessage << "e " << pDce << " " << cDpe << std::endl; | ||||
|     std::cout << GridLogMessage << "o " << pDco << " " << cDpo << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "pDce - conj(cDpo) " << pDce-conj(cDpo) << std::endl; | ||||
|     std::cout << GridLogMessage << "pDco - conj(cDpe) " << pDco-conj(cDpe) << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Test MeeInv Mee = 1                                         " << std::endl; | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|  | ||||
|     pickCheckerboard(Even, chi_e, chi); | ||||
|     pickCheckerboard(Odd , chi_o, chi); | ||||
|  | ||||
|     Ddwf.Mooee   (chi_e, src_e); | ||||
|     Ddwf.MooeeInv(src_e, phi_e); | ||||
|  | ||||
|     Ddwf.Mooee   (chi_o, src_o); | ||||
|     Ddwf.MooeeInv(src_o, phi_o); | ||||
|  | ||||
|     setCheckerboard(phi, phi_e); | ||||
|     setCheckerboard(phi, phi_o); | ||||
|  | ||||
|     err = phi - chi; | ||||
|     std::cout << GridLogMessage << "norm diff   " << norm2(err) << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Test MeeInvDag MeeDag = 1                                   " << std::endl; | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|  | ||||
|     pickCheckerboard(Even, chi_e, chi); | ||||
|     pickCheckerboard(Odd , chi_o, chi); | ||||
|  | ||||
|     Ddwf.MooeeDag   (chi_e, src_e); | ||||
|     Ddwf.MooeeInvDag(src_e, phi_e); | ||||
|  | ||||
|     Ddwf.MooeeDag   (chi_o, src_o); | ||||
|     Ddwf.MooeeInvDag(src_o, phi_o); | ||||
|  | ||||
|     setCheckerboard(phi, phi_e); | ||||
|     setCheckerboard(phi, phi_o); | ||||
|  | ||||
|     err = phi - chi; | ||||
|     std::cout << GridLogMessage << "norm diff   " << norm2(err) << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Test MpcDagMpc is Hermitian              " << std::endl; | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|  | ||||
|     random(RNG5, phi); | ||||
|     random(RNG5, chi); | ||||
|     pickCheckerboard(Even, chi_e, chi); | ||||
|     pickCheckerboard(Odd , chi_o, chi); | ||||
|     pickCheckerboard(Even, phi_e, phi); | ||||
|     pickCheckerboard(Odd , phi_o, phi); | ||||
|     RealD t1,t2; | ||||
|  | ||||
|     SchurDiagMooeeOperator<DomainWallEOFAFermionR,LatticeFermion> HermOpEO(Ddwf); | ||||
|     HermOpEO.MpcDagMpc(chi_e, dchi_e, t1, t2); | ||||
|     HermOpEO.MpcDagMpc(chi_o, dchi_o, t1, t2); | ||||
|  | ||||
|     HermOpEO.MpcDagMpc(phi_e, dphi_e, t1, t2); | ||||
|     HermOpEO.MpcDagMpc(phi_o, dphi_o, t1, t2); | ||||
|  | ||||
|     pDce = innerProduct(phi_e, dchi_e); | ||||
|     pDco = innerProduct(phi_o, dchi_o); | ||||
|     cDpe = innerProduct(chi_e, dphi_e); | ||||
|     cDpo = innerProduct(chi_o, dphi_o); | ||||
|  | ||||
|     std::cout << GridLogMessage << "e " << pDce << " " << cDpe << std::endl; | ||||
|     std::cout << GridLogMessage << "o " << pDco << " " << cDpo << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "pDce - conj(cDpo) " << pDco-conj(cDpo) << std::endl; | ||||
|     std::cout << GridLogMessage << "pDco - conj(cDpe) " << pDce-conj(cDpe) << std::endl; | ||||
|  | ||||
|     Grid_finalize(); | ||||
| } | ||||
| @@ -47,7 +47,7 @@ int main (int argc, char ** argv) | ||||
|     vol = vol * latt_size[d]; | ||||
|   } | ||||
|   GridCartesian         GRID(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian RBGRID(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian RBGRID(&GRID); | ||||
|  | ||||
|   LatticeComplexD     one(&GRID); | ||||
|   LatticeComplexD      zz(&GRID); | ||||
|   | ||||
| @@ -33,22 +33,68 @@ using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| typedef typename GparityDomainWallFermionR::FermionField FermionField; | ||||
| //typedef GparityDomainWallFermionD GparityDiracOp; | ||||
| //typedef DomainWallFermionD StandardDiracOp; | ||||
| //#define DOP_PARAMS | ||||
|  | ||||
| typedef GparityMobiusFermionD GparityDiracOp; | ||||
| typedef MobiusFermionD StandardDiracOp; | ||||
| #define DOP_PARAMS ,1.5, 0.5 | ||||
|  | ||||
|  | ||||
| typedef typename GparityDiracOp::FermionField GparityFermionField; | ||||
| typedef typename GparityDiracOp::GaugeField GparityGaugeField; | ||||
| typedef typename GparityFermionField::vector_type vComplexType; | ||||
|  | ||||
| typedef typename StandardDiracOp::FermionField StandardFermionField; | ||||
| typedef typename StandardDiracOp::GaugeField StandardGaugeField; | ||||
|  | ||||
| enum{ same_vComplex = std::is_same<vComplexType, typename StandardFermionField::vector_type>::value }; | ||||
| static_assert(same_vComplex == 1, "Dirac Operators must have same underlying SIMD complex type"); | ||||
|  | ||||
| int main (int argc, char ** argv) | ||||
| { | ||||
|   const int nu = 3; | ||||
|   int nu = 0; | ||||
|  | ||||
|   Grid_init(&argc,&argv); | ||||
|  | ||||
|   for(int i=1;i<argc;i++){ | ||||
|     if(std::string(argv[i]) == "--Gparity-dir"){ | ||||
|       std::stringstream ss; ss << argv[i+1]; ss >> nu; | ||||
|       std::cout << GridLogMessage << "Set Gparity direction to " << nu << std::endl; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   std::cout << GridLogMessage<< "*****************************************************************" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "* Kernel options --dslash-generic, --dslash-unroll, --dslash-asm" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "*****************************************************************" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "*****************************************************************" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "* Testing Gparity Dirac operator                  "<<std::endl; | ||||
|   std::cout << GridLogMessage<< "* Vectorising space-time by "<<vComplexType::Nsimd()<<std::endl; | ||||
| #ifdef GRID_OMP | ||||
|   if ( WilsonKernelsStatic::Comms == WilsonKernelsStatic::CommsAndCompute ) std::cout << GridLogMessage<< "* Using Overlapped Comms/Compute" <<std::endl; | ||||
|   if ( WilsonKernelsStatic::Comms == WilsonKernelsStatic::CommsThenCompute) std::cout << GridLogMessage<< "* Using sequential comms compute" <<std::endl; | ||||
| #endif | ||||
|   if ( WilsonKernelsStatic::Opt == WilsonKernelsStatic::OptGeneric   ) std::cout << GridLogMessage<< "* Using GENERIC Nc WilsonKernels" <<std::endl; | ||||
|   if ( WilsonKernelsStatic::Opt == WilsonKernelsStatic::OptHandUnroll) std::cout << GridLogMessage<< "* Using UNROLLED Nc=3       WilsonKernels" <<std::endl; | ||||
|   if ( WilsonKernelsStatic::Opt == WilsonKernelsStatic::OptInlineAsm ) std::cout << GridLogMessage<< "* Using Asm Nc=3   WilsonKernels" <<std::endl; | ||||
|   std::cout << GridLogMessage<< "*****************************************************************" <<std::endl; | ||||
|  | ||||
|   const int Ls=4; | ||||
|   const int L =4; | ||||
|   std::vector<int> latt_2f(Nd,L); | ||||
|   std::vector<int> latt_1f(Nd,L); latt_1f[nu] = 2*L; | ||||
|   //const int L =4; | ||||
|   //std::vector<int> latt_2f(Nd,L); | ||||
|  | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> latt_2f = GridDefaultLatt(); | ||||
|   std::vector<int> latt_1f(latt_2f); latt_1f[nu] = 2*latt_2f[nu]; | ||||
|   int L = latt_2f[nu]; | ||||
|  | ||||
|  | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplexType::Nsimd()); | ||||
|  | ||||
|   std::cout << GridLogMessage << "SIMD layout: "; | ||||
|   for(int i=0;i<simd_layout.size();i++) std::cout << simd_layout[i] << " "; | ||||
|   std::cout << std::endl; | ||||
|    | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); //node layout | ||||
|  | ||||
|   GridCartesian         * UGrid_1f   = SpaceTimeGrid::makeFourDimGrid(latt_1f, simd_layout, mpi_layout); | ||||
| @@ -67,13 +113,13 @@ int main (int argc, char ** argv) | ||||
|   GridParallelRNG          RNG5_2f(FGrid_2f);  RNG5_2f.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG          RNG4_2f(UGrid_2f);  RNG4_2f.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   LatticeGaugeField Umu_2f(UGrid_2f); | ||||
|   GparityGaugeField Umu_2f(UGrid_2f); | ||||
|   SU3::HotConfiguration(RNG4_2f,Umu_2f); | ||||
|  | ||||
|   LatticeFermion    src   (FGrid_2f);  | ||||
|   LatticeFermion    tmpsrc(FGrid_2f);  | ||||
|   FermionField      src_2f(FGrid_2f);  | ||||
|   LatticeFermion    src_1f(FGrid_1f);  | ||||
|   StandardFermionField    src   (FGrid_2f);  | ||||
|   StandardFermionField    tmpsrc(FGrid_2f);  | ||||
|   GparityFermionField      src_2f(FGrid_2f);  | ||||
|   StandardFermionField    src_1f(FGrid_1f);  | ||||
|  | ||||
|   // Replicate fermion source | ||||
|   random(RNG5_2f,src); | ||||
| @@ -81,8 +127,8 @@ int main (int argc, char ** argv) | ||||
|   tmpsrc=src*2.0; | ||||
|   PokeIndex<0>(src_2f,tmpsrc,1); | ||||
|  | ||||
|   LatticeFermion result_1f(FGrid_1f); result_1f=zero; | ||||
|   LatticeGaugeField Umu_1f(UGrid_1f);  | ||||
|   StandardFermionField result_1f(FGrid_1f); result_1f=zero; | ||||
|   StandardGaugeField Umu_1f(UGrid_1f);  | ||||
|   Replicate(Umu_2f,Umu_1f); | ||||
|  | ||||
|   //Coordinate grid for reference | ||||
| @@ -92,7 +138,7 @@ int main (int argc, char ** argv) | ||||
|   //Copy-conjugate the gauge field | ||||
|   //First C-shift the lattice by Lx/2 | ||||
|   { | ||||
|     LatticeGaugeField Umu_shift = conjugate( Cshift(Umu_1f,nu,L) ); | ||||
|     StandardGaugeField Umu_shift = conjugate( Cshift(Umu_1f,nu,L) ); | ||||
|     Umu_1f = where( xcoor_1f >= Integer(L), Umu_shift, Umu_1f ); | ||||
|  | ||||
|     // hack test to check the same | ||||
| @@ -101,7 +147,7 @@ int main (int argc, char ** argv) | ||||
|     cout << GridLogMessage << "Umu diff " << norm2(Umu_shift)<<std::endl; | ||||
|  | ||||
|     //Make the gauge field antiperiodic in nu-direction | ||||
|     LatticeColourMatrix Unu(UGrid_1f); | ||||
|     decltype(PeekIndex<LorentzIndex>(Umu_1f,nu)) Unu(UGrid_1f); | ||||
|     Unu = PeekIndex<LorentzIndex>(Umu_1f,nu); | ||||
|     Unu = where(xcoor_1f == Integer(2*L-1), -Unu, Unu); | ||||
|     PokeIndex<LorentzIndex>(Umu_1f,Unu,nu); | ||||
| @@ -115,33 +161,33 @@ int main (int argc, char ** argv) | ||||
|  | ||||
|   RealD mass=0.0; | ||||
|   RealD M5=1.8; | ||||
|   DomainWallFermionR Ddwf(Umu_1f,*FGrid_1f,*FrbGrid_1f,*UGrid_1f,*UrbGrid_1f,mass,M5); | ||||
|   StandardDiracOp Ddwf(Umu_1f,*FGrid_1f,*FrbGrid_1f,*UGrid_1f,*UrbGrid_1f,mass,M5 DOP_PARAMS); | ||||
|  | ||||
|   LatticeFermion    src_o_1f(FrbGrid_1f); | ||||
|   LatticeFermion result_o_1f(FrbGrid_1f); | ||||
|   StandardFermionField    src_o_1f(FrbGrid_1f); | ||||
|   StandardFermionField result_o_1f(FrbGrid_1f); | ||||
|   pickCheckerboard(Odd,src_o_1f,src_1f); | ||||
|   result_o_1f=zero; | ||||
|  | ||||
|   SchurDiagMooeeOperator<DomainWallFermionR,LatticeFermion> HermOpEO(Ddwf); | ||||
|   ConjugateGradient<LatticeFermion> CG(1.0e-8,10000); | ||||
|   SchurDiagMooeeOperator<StandardDiracOp,StandardFermionField> HermOpEO(Ddwf); | ||||
|   ConjugateGradient<StandardFermionField> CG(1.0e-8,10000); | ||||
|   CG(HermOpEO,src_o_1f,result_o_1f); | ||||
|    | ||||
|   //  const int nu = 3; | ||||
|   std::vector<int> twists(Nd,0); | ||||
|   twists[nu] = 1; | ||||
|   GparityDomainWallFermionR::ImplParams params; | ||||
|   GparityDiracOp::ImplParams params; | ||||
|   params.twists = twists; | ||||
|   GparityDomainWallFermionR GPDdwf(Umu_2f,*FGrid_2f,*FrbGrid_2f,*UGrid_2f,*UrbGrid_2f,mass,M5,params); | ||||
|   GparityDiracOp GPDdwf(Umu_2f,*FGrid_2f,*FrbGrid_2f,*UGrid_2f,*UrbGrid_2f,mass,M5 DOP_PARAMS,params); | ||||
|  | ||||
|   for(int disp=-1;disp<=1;disp+=2) | ||||
|   for(int mu=0;mu<5;mu++) | ||||
|   {  | ||||
|     FermionField Dsrc_2f(FGrid_2f); | ||||
|     GparityFermionField Dsrc_2f(FGrid_2f); | ||||
|  | ||||
|     LatticeFermion Dsrc_1f(FGrid_1f); | ||||
|     LatticeFermion Dsrc_2freplica(FGrid_1f); | ||||
|     LatticeFermion Dsrc_2freplica0(FGrid_1f); | ||||
|     LatticeFermion Dsrc_2freplica1(FGrid_1f); | ||||
|     StandardFermionField Dsrc_1f(FGrid_1f); | ||||
|     StandardFermionField Dsrc_2freplica(FGrid_1f); | ||||
|     StandardFermionField Dsrc_2freplica0(FGrid_1f); | ||||
|     StandardFermionField Dsrc_2freplica1(FGrid_1f); | ||||
|  | ||||
|     if ( mu ==0 ) { | ||||
|       std::cout << GridLogMessage<< " Cross checking entire hopping term"<<std::endl; | ||||
| @@ -156,8 +202,8 @@ int main (int argc, char ** argv) | ||||
|     std::cout << GridLogMessage << "S norms "<< norm2(src_2f) << " " << norm2(src_1f)  <<std::endl; | ||||
|     std::cout << GridLogMessage << "D norms "<< norm2(Dsrc_2f)<< " " << norm2(Dsrc_1f) <<std::endl; | ||||
|  | ||||
|     LatticeFermion Dsrc_2f0(FGrid_2f); Dsrc_2f0 = PeekIndex<0>(Dsrc_2f,0); | ||||
|     LatticeFermion Dsrc_2f1(FGrid_2f); Dsrc_2f1 = PeekIndex<0>(Dsrc_2f,1); | ||||
|     StandardFermionField Dsrc_2f0(FGrid_2f); Dsrc_2f0 = PeekIndex<0>(Dsrc_2f,0); | ||||
|     StandardFermionField Dsrc_2f1(FGrid_2f); Dsrc_2f1 = PeekIndex<0>(Dsrc_2f,1); | ||||
|  | ||||
|     //    Dsrc_2f1 = Dsrc_2f1 - Dsrc_2f0; | ||||
|     //    std::cout << GridLogMessage << " Cross check two halves " <<norm2(Dsrc_2f1)<<std::endl; | ||||
| @@ -174,20 +220,20 @@ int main (int argc, char ** argv) | ||||
|   } | ||||
|  | ||||
|   { | ||||
|     FermionField chi   (FGrid_2f); gaussian(RNG5_2f,chi); | ||||
|     FermionField phi   (FGrid_2f); gaussian(RNG5_2f,phi); | ||||
|     GparityFermionField chi   (FGrid_2f); gaussian(RNG5_2f,chi); | ||||
|     GparityFermionField phi   (FGrid_2f); gaussian(RNG5_2f,phi); | ||||
|    | ||||
|     FermionField chi_e   (FrbGrid_2f); | ||||
|     FermionField chi_o   (FrbGrid_2f); | ||||
|     GparityFermionField chi_e   (FrbGrid_2f); | ||||
|     GparityFermionField chi_o   (FrbGrid_2f); | ||||
|      | ||||
|     FermionField dchi_e  (FrbGrid_2f); | ||||
|     FermionField dchi_o  (FrbGrid_2f); | ||||
|     GparityFermionField dchi_e  (FrbGrid_2f); | ||||
|     GparityFermionField dchi_o  (FrbGrid_2f); | ||||
|      | ||||
|     FermionField phi_e   (FrbGrid_2f); | ||||
|     FermionField phi_o   (FrbGrid_2f); | ||||
|     GparityFermionField phi_e   (FrbGrid_2f); | ||||
|     GparityFermionField phi_o   (FrbGrid_2f); | ||||
|      | ||||
|     FermionField dphi_e  (FrbGrid_2f); | ||||
|     FermionField dphi_o  (FrbGrid_2f); | ||||
|     GparityFermionField dphi_e  (FrbGrid_2f); | ||||
|     GparityFermionField dphi_o  (FrbGrid_2f); | ||||
|  | ||||
|     pickCheckerboard(Even,chi_e,chi); | ||||
|     pickCheckerboard(Odd ,chi_o,chi); | ||||
| @@ -212,14 +258,14 @@ int main (int argc, char ** argv) | ||||
|  | ||||
|   } | ||||
|  | ||||
|   FermionField result_2f(FGrid_2f); result_2f=zero; | ||||
|   FermionField    src_o_2f(FrbGrid_2f); | ||||
|   FermionField result_o_2f(FrbGrid_2f); | ||||
|   GparityFermionField result_2f(FGrid_2f); result_2f=zero; | ||||
|   GparityFermionField    src_o_2f(FrbGrid_2f); | ||||
|   GparityFermionField result_o_2f(FrbGrid_2f); | ||||
|   pickCheckerboard(Odd,src_o_2f,src_2f); | ||||
|   result_o_2f=zero; | ||||
|  | ||||
|   ConjugateGradient<FermionField> CG2f(1.0e-8,10000); | ||||
|   SchurDiagMooeeOperator<GparityDomainWallFermionR,FermionField> HermOpEO2f(GPDdwf); | ||||
|   ConjugateGradient<GparityFermionField> CG2f(1.0e-8,10000); | ||||
|   SchurDiagMooeeOperator<GparityDiracOp,GparityFermionField> HermOpEO2f(GPDdwf); | ||||
|   CG2f(HermOpEO2f,src_o_2f,result_o_2f); | ||||
|  | ||||
|   std::cout << "2f cb "<<result_o_2f.checkerboard<<std::endl; | ||||
| @@ -227,10 +273,10 @@ int main (int argc, char ** argv) | ||||
|  | ||||
|   std::cout << " result norms " <<norm2(result_o_2f)<<" " <<norm2(result_o_1f)<<std::endl; | ||||
|  | ||||
|   LatticeFermion    res0o  (FrbGrid_2f);  | ||||
|   LatticeFermion    res1o  (FrbGrid_2f);  | ||||
|   LatticeFermion    res0  (FGrid_2f);  | ||||
|   LatticeFermion    res1  (FGrid_2f);  | ||||
|   StandardFermionField    res0o  (FrbGrid_2f);  | ||||
|   StandardFermionField    res1o  (FrbGrid_2f);  | ||||
|   StandardFermionField    res0  (FGrid_2f);  | ||||
|   StandardFermionField    res1  (FGrid_2f);  | ||||
|  | ||||
|   res0=zero; | ||||
|   res1=zero; | ||||
| @@ -244,9 +290,9 @@ int main (int argc, char ** argv) | ||||
|   setCheckerboard(res0,res0o); | ||||
|   setCheckerboard(res1,res1o); | ||||
|  | ||||
|   LatticeFermion replica (FGrid_1f); | ||||
|   LatticeFermion replica0(FGrid_1f); | ||||
|   LatticeFermion replica1(FGrid_1f); | ||||
|   StandardFermionField replica (FGrid_1f); | ||||
|   StandardFermionField replica0(FGrid_1f); | ||||
|   StandardFermionField replica1(FGrid_1f); | ||||
|   Replicate(res0,replica0); | ||||
|   Replicate(res1,replica1); | ||||
|  | ||||
|   | ||||
| @@ -40,7 +40,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
| @@ -84,7 +84,7 @@ int main(int argc, char **argv) { | ||||
|       double volume = latt_size[0] * latt_size[1] * latt_size[2] * latt_size[3]; | ||||
|  | ||||
|       GridCartesian Fine(latt_size, simd_layout, mpi_layout); | ||||
|       GridRedBlackCartesian rbFine(latt_size, simd_layout, mpi_layout); | ||||
|       GridRedBlackCartesian rbFine(&Fine); | ||||
|       GridParallelRNG FineRNG(&Fine); | ||||
|       GridSerialRNG SerialRNG; | ||||
|       GridSerialRNG SerialRNG1; | ||||
|   | ||||
							
								
								
									
										241
									
								
								tests/core/Test_mobius_eofa_even_odd.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								tests/core/Test_mobius_eofa_even_odd.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,241 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/core/Test_dwf_eofa_even_odd.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| template<class d> | ||||
| struct scal { | ||||
|     d internal; | ||||
| }; | ||||
|  | ||||
| Gamma::Algebra Gmu [] = { | ||||
|     Gamma::Algebra::GammaX, | ||||
|     Gamma::Algebra::GammaY, | ||||
|     Gamma::Algebra::GammaZ, | ||||
|     Gamma::Algebra::GammaT | ||||
| }; | ||||
|  | ||||
| int main (int argc, char ** argv) | ||||
| { | ||||
|     Grid_init(&argc, &argv); | ||||
|  | ||||
|     int threads = GridThread::GetThreads(); | ||||
|     std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|     const int Ls = 8; | ||||
|     // GridCartesian*         UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|     GridCartesian*         UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|     GridCartesian*         FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|     GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|     GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|     std::vector<int> seeds4({1,2,3,4}); | ||||
|     std::vector<int> seeds5({5,6,7,8}); | ||||
|  | ||||
|     GridParallelRNG RNG4(UGrid); RNG4.SeedFixedIntegers(seeds4); | ||||
|     GridParallelRNG RNG5(FGrid); RNG5.SeedFixedIntegers(seeds5); | ||||
|  | ||||
|     LatticeFermion    src   (FGrid); random(RNG5, src); | ||||
|     LatticeFermion    phi   (FGrid); random(RNG5, phi); | ||||
|     LatticeFermion    chi   (FGrid); random(RNG5, chi); | ||||
|     LatticeFermion    result(FGrid); result = zero; | ||||
|     LatticeFermion    ref   (FGrid); ref = zero; | ||||
|     LatticeFermion    tmp   (FGrid); tmp = zero; | ||||
|     LatticeFermion    err   (FGrid); err = zero; | ||||
|     LatticeGaugeField Umu   (UGrid); SU3::HotConfiguration(RNG4, Umu); | ||||
|     std::vector<LatticeColourMatrix> U(4,UGrid); | ||||
|  | ||||
|     // Only one non-zero (y) | ||||
|     Umu = zero; | ||||
|     for(int nn=0; nn<Nd; nn++){ | ||||
|         random(RNG4, U[nn]); | ||||
|         if(nn>0){ U[nn] = zero; } | ||||
|         PokeIndex<LorentzIndex>(Umu, U[nn], nn); | ||||
|     } | ||||
|  | ||||
|     RealD b     = 2.5; | ||||
|     RealD c     = 1.5; | ||||
|     RealD mq1   = 0.1; | ||||
|     RealD mq2   = 0.5; | ||||
|     RealD mq3   = 1.0; | ||||
|     RealD shift = 0.1234; | ||||
|     RealD M5    = 1.8; | ||||
|     int   pm    = 1; | ||||
|     MobiusEOFAFermionR Ddwf(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mq1, mq2, mq3, shift, pm, M5, b, c); | ||||
|  | ||||
|     LatticeFermion src_e (FrbGrid); | ||||
|     LatticeFermion src_o (FrbGrid); | ||||
|     LatticeFermion r_e   (FrbGrid); | ||||
|     LatticeFermion r_o   (FrbGrid); | ||||
|     LatticeFermion r_eo  (FGrid); | ||||
|     LatticeFermion r_eeoo(FGrid); | ||||
|  | ||||
|     std::cout << GridLogMessage << "==========================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Testing that Meo + Moe + Moo + Mee = Munprec " << std::endl; | ||||
|     std::cout << GridLogMessage << "==========================================================" << std::endl; | ||||
|  | ||||
|     pickCheckerboard(Even, src_e, src); | ||||
|     pickCheckerboard(Odd,  src_o, src); | ||||
|  | ||||
|     Ddwf.Meooe(src_e, r_o); std::cout << GridLogMessage << "Applied Meo" << std::endl; | ||||
|     Ddwf.Meooe(src_o, r_e); std::cout << GridLogMessage << "Applied Moe" << std::endl; | ||||
|     setCheckerboard(r_eo, r_o); | ||||
|     setCheckerboard(r_eo, r_e); | ||||
|  | ||||
|     Ddwf.Mooee(src_e, r_e); std::cout << GridLogMessage << "Applied Mee" << std::endl; | ||||
|     Ddwf.Mooee(src_o, r_o); std::cout << GridLogMessage << "Applied Moo" << std::endl; | ||||
|     setCheckerboard(r_eeoo, r_e); | ||||
|     setCheckerboard(r_eeoo, r_o); | ||||
|  | ||||
|     r_eo = r_eo + r_eeoo; | ||||
|     Ddwf.M(src, ref); | ||||
|  | ||||
|     // std::cout << GridLogMessage << r_eo << std::endl; | ||||
|     // std::cout << GridLogMessage << ref  << std::endl; | ||||
|  | ||||
|     err = ref - r_eo; | ||||
|     std::cout << GridLogMessage << "EO norm diff   " << norm2(err) << " " << norm2(ref) << " " << norm2(r_eo) << std::endl; | ||||
|  | ||||
|     LatticeComplex cerr(FGrid); | ||||
|     cerr = localInnerProduct(err,err); | ||||
|     // std::cout << GridLogMessage << cerr << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Test Ddagger is the dagger of D by requiring                " << std::endl; | ||||
|     std::cout << GridLogMessage << "=  < phi | Deo | chi > * = < chi | Deo^dag| phi>  " << std::endl; | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|  | ||||
|     LatticeFermion chi_e (FrbGrid); | ||||
|     LatticeFermion chi_o (FrbGrid); | ||||
|  | ||||
|     LatticeFermion dchi_e(FrbGrid); | ||||
|     LatticeFermion dchi_o(FrbGrid); | ||||
|  | ||||
|     LatticeFermion phi_e (FrbGrid); | ||||
|     LatticeFermion phi_o (FrbGrid); | ||||
|  | ||||
|     LatticeFermion dphi_e(FrbGrid); | ||||
|     LatticeFermion dphi_o(FrbGrid); | ||||
|  | ||||
|     pickCheckerboard(Even, chi_e, chi); | ||||
|     pickCheckerboard(Odd , chi_o, chi); | ||||
|     pickCheckerboard(Even, phi_e, phi); | ||||
|     pickCheckerboard(Odd , phi_o, phi); | ||||
|  | ||||
|     Ddwf.Meooe   (chi_e, dchi_o); | ||||
|     Ddwf.Meooe   (chi_o, dchi_e); | ||||
|     Ddwf.MeooeDag(phi_e, dphi_o); | ||||
|     Ddwf.MeooeDag(phi_o, dphi_e); | ||||
|  | ||||
|     ComplexD pDce = innerProduct(phi_e, dchi_e); | ||||
|     ComplexD pDco = innerProduct(phi_o, dchi_o); | ||||
|     ComplexD cDpe = innerProduct(chi_e, dphi_e); | ||||
|     ComplexD cDpo = innerProduct(chi_o, dphi_o); | ||||
|  | ||||
|     std::cout << GridLogMessage << "e " << pDce << " " << cDpe << std::endl; | ||||
|     std::cout << GridLogMessage << "o " << pDco << " " << cDpo << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "pDce - conj(cDpo) " << pDce-conj(cDpo) << std::endl; | ||||
|     std::cout << GridLogMessage << "pDco - conj(cDpe) " << pDco-conj(cDpe) << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Test MeeInv Mee = 1                                         " << std::endl; | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|  | ||||
|     pickCheckerboard(Even, chi_e, chi); | ||||
|     pickCheckerboard(Odd , chi_o, chi); | ||||
|  | ||||
|     Ddwf.Mooee   (chi_e, src_e); | ||||
|     Ddwf.MooeeInv(src_e, phi_e); | ||||
|  | ||||
|     Ddwf.Mooee   (chi_o, src_o); | ||||
|     Ddwf.MooeeInv(src_o, phi_o); | ||||
|  | ||||
|     setCheckerboard(phi, phi_e); | ||||
|     setCheckerboard(phi, phi_o); | ||||
|  | ||||
|     err = phi - chi; | ||||
|     std::cout << GridLogMessage << "norm diff   " << norm2(err) << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Test MeeInvDag MeeDag = 1                                   " << std::endl; | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|  | ||||
|     pickCheckerboard(Even, chi_e, chi); | ||||
|     pickCheckerboard(Odd , chi_o, chi); | ||||
|  | ||||
|     Ddwf.MooeeDag   (chi_e, src_e); | ||||
|     Ddwf.MooeeInvDag(src_e, phi_e); | ||||
|  | ||||
|     Ddwf.MooeeDag   (chi_o, src_o); | ||||
|     Ddwf.MooeeInvDag(src_o, phi_o); | ||||
|  | ||||
|     setCheckerboard(phi, phi_e); | ||||
|     setCheckerboard(phi, phi_o); | ||||
|  | ||||
|     err = phi - chi; | ||||
|     std::cout << GridLogMessage << "norm diff   " << norm2(err) << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|     std::cout << GridLogMessage << "= Test MpcDagMpc is Hermitian              " << std::endl; | ||||
|     std::cout << GridLogMessage << "==============================================================" << std::endl; | ||||
|  | ||||
|     random(RNG5, phi); | ||||
|     random(RNG5, chi); | ||||
|     pickCheckerboard(Even, chi_e, chi); | ||||
|     pickCheckerboard(Odd , chi_o, chi); | ||||
|     pickCheckerboard(Even, phi_e, phi); | ||||
|     pickCheckerboard(Odd , phi_o, phi); | ||||
|     RealD t1,t2; | ||||
|  | ||||
|     SchurDiagMooeeOperator<MobiusEOFAFermionR,LatticeFermion> HermOpEO(Ddwf); | ||||
|     HermOpEO.MpcDagMpc(chi_e, dchi_e, t1, t2); | ||||
|     HermOpEO.MpcDagMpc(chi_o, dchi_o, t1, t2); | ||||
|  | ||||
|     HermOpEO.MpcDagMpc(phi_e, dphi_e, t1, t2); | ||||
|     HermOpEO.MpcDagMpc(phi_o, dphi_o, t1, t2); | ||||
|  | ||||
|     pDce = innerProduct(phi_e, dchi_e); | ||||
|     pDco = innerProduct(phi_o, dchi_o); | ||||
|     cDpe = innerProduct(chi_e, dphi_e); | ||||
|     cDpo = innerProduct(chi_o, dphi_o); | ||||
|  | ||||
|     std::cout << GridLogMessage << "e " << pDce << " " << cDpe << std::endl; | ||||
|     std::cout << GridLogMessage << "o " << pDco << " " << cDpo << std::endl; | ||||
|  | ||||
|     std::cout << GridLogMessage << "pDce - conj(cDpo) " << pDco-conj(cDpo) << std::endl; | ||||
|     std::cout << GridLogMessage << "pDco - conj(cDpe) " << pDce-conj(cDpe) << std::endl; | ||||
|  | ||||
|     Grid_finalize(); | ||||
| } | ||||
| @@ -40,7 +40,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
| @@ -51,7 +51,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
| @@ -52,7 +52,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
							
								
								
									
										102
									
								
								tests/debug/Test_heatbath_dwf_eofa.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								tests/debug/Test_heatbath_dwf_eofa.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./tests/debug/Test_heatbath_dwf_eofa.cc | ||||
|  | ||||
|     Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
|     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 */ | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // This program sets up the initial pseudofermion field |Phi> = Meofa^{-1/2}*|eta>, and | ||||
| // then uses this Phi to compute the action <Phi|Meofa|Phi>. | ||||
| // If all is working, one should find that <eta|eta> = <Phi|Meofa|Phi>. | ||||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| // Parameters for test | ||||
| const std::vector<int> grid_dim = { 8, 8, 8, 8 }; | ||||
| const int              Ls       = 8; | ||||
| const int              Npoles   = 12; | ||||
| const RealD            mf       = 0.01; | ||||
| const RealD            mpv      = 1.0; | ||||
| const RealD            M5       = 1.8; | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout << GridLogMessage << "Grid is set up to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|   // Initialize spacetime grid | ||||
|   std::cout << GridLogMessage << "Lattice dimensions: " << grid_dim << "  Ls: " << Ls << std::endl; | ||||
|   GridCartesian*         UGrid   = SpaceTimeGrid::makeFourDimGrid(grid_dim, | ||||
|                                       GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian*         FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Set up RNGs | ||||
|   std::vector<int> seeds4({1, 2, 3, 4}); | ||||
|   std::vector<int> seeds5({5, 6, 7, 8}); | ||||
|   GridParallelRNG RNG5(FGrid); | ||||
|   RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid); | ||||
|   RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   // Random gauge field | ||||
|   LatticeGaugeField Umu(UGrid); | ||||
|   SU3::HotConfiguration(RNG4, Umu); | ||||
|  | ||||
|   DomainWallEOFAFermionR Lop(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf,  mf, mpv,  0.0, -1, M5); | ||||
|   DomainWallEOFAFermionR Rop(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mpv, mf, mpv, -1.0,  1, M5); | ||||
|  | ||||
|   // Construct the action and test the heatbath (zero initial guess) | ||||
|   { | ||||
|     OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, Npoles); | ||||
|     ConjugateGradient<LatticeFermion> CG(1.0e-12, 5000); | ||||
|     ExactOneFlavourRatioPseudoFermionAction<WilsonImplR> Meofa(Lop, Rop, CG, Params, false); | ||||
|  | ||||
|     Meofa.refresh(Umu, RNG5); | ||||
|     printf("<Phi|Meofa|Phi> = %1.15e\n", Meofa.S(Umu)); | ||||
|   } | ||||
|  | ||||
|   // Construct the action and test the heatbath (forecasted initial guesses) | ||||
|   { | ||||
|     OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, Npoles); | ||||
|     ConjugateGradient<LatticeFermion> CG(1.0e-12, 5000); | ||||
|     ExactOneFlavourRatioPseudoFermionAction<WilsonImplR> Meofa(Lop, Rop, CG, Params, true); | ||||
|  | ||||
|     Meofa.refresh(Umu, RNG5); | ||||
|     printf("<Phi|Meofa|Phi> = %1.15e\n", Meofa.S(Umu)); | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										108
									
								
								tests/debug/Test_heatbath_dwf_eofa_gparity.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								tests/debug/Test_heatbath_dwf_eofa_gparity.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./tests/debug/Test_heatbath_dwf_eofa.cc | ||||
|  | ||||
|     Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
|     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 */ | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // This program sets up the initial pseudofermion field |Phi> = Meofa^{-1/2}*|eta>, and | ||||
| // then uses this Phi to compute the action <Phi|Meofa|Phi>. | ||||
| // If all is working, one should find that <eta|eta> = <Phi|Meofa|Phi>. | ||||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| typedef GparityWilsonImplR FermionImplPolicy; | ||||
| typedef GparityDomainWallEOFAFermionR FermionAction; | ||||
| typedef typename FermionAction::FermionField FermionField; | ||||
|  | ||||
| // Parameters for test | ||||
| const std::vector<int> grid_dim = { 8, 8, 8, 8 }; | ||||
| const int              Ls       = 8; | ||||
| const int              Npoles   = 12; | ||||
| const RealD            mf       = 0.01; | ||||
| const RealD            mpv      = 1.0; | ||||
| const RealD            M5       = 1.8; | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout << GridLogMessage << "Grid is set up to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|   // Initialize spacetime grid | ||||
|   std::cout << GridLogMessage << "Lattice dimensions: " << grid_dim << "  Ls: " << Ls << std::endl; | ||||
|   GridCartesian*         UGrid   = SpaceTimeGrid::makeFourDimGrid(grid_dim, | ||||
|                                       GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian*         FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Set up RNGs | ||||
|   std::vector<int> seeds4({1, 2, 3, 4}); | ||||
|   std::vector<int> seeds5({5, 6, 7, 8}); | ||||
|   GridParallelRNG RNG5(FGrid); | ||||
|   RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid); | ||||
|   RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   // Random gauge field | ||||
|   LatticeGaugeField Umu(UGrid); | ||||
|   SU3::HotConfiguration(RNG4, Umu); | ||||
|  | ||||
|   // GparityDomainWallFermionR::ImplParams params; | ||||
|   FermionAction::ImplParams params; | ||||
|   FermionAction Lop(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf,  mf, mpv,  0.0, -1, M5, params); | ||||
|   FermionAction Rop(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mpv, mf, mpv, -1.0,  1, M5, params); | ||||
|  | ||||
|   // Construct the action and test the heatbath (zero initial guess) | ||||
|   { | ||||
|     OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, Npoles); | ||||
|     ConjugateGradient<FermionField> CG(1.0e-12, 5000); | ||||
|     ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> Meofa(Lop, Rop, CG, Params, false); | ||||
|  | ||||
|     Meofa.refresh(Umu, RNG5); | ||||
|     printf("<Phi|Meofa|Phi> = %1.15e\n", Meofa.S(Umu)); | ||||
|   } | ||||
|  | ||||
|   // Construct the action and test the heatbath (forecasted initial guesses) | ||||
|   { | ||||
|     OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, Npoles); | ||||
|     ConjugateGradient<FermionField> CG(1.0e-12, 5000); | ||||
|     ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> Meofa(Lop, Rop, CG, Params, true); | ||||
|  | ||||
|     Meofa.refresh(Umu, RNG5); | ||||
|     printf("<Phi|Meofa|Phi> = %1.15e\n", Meofa.S(Umu)); | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										104
									
								
								tests/debug/Test_heatbath_mobius_eofa.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								tests/debug/Test_heatbath_mobius_eofa.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/debug/Test_heatbath_dwf_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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 */ | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // This program sets up the initial pseudofermion field |Phi> = Meofa^{-1/2}*|eta>, and | ||||
| // then uses this Phi to compute the action <Phi|Meofa|Phi>. | ||||
| // If all is working, one should find that <eta|eta> = <Phi|Meofa|Phi>. | ||||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| // Parameters for test | ||||
| const std::vector<int> grid_dim = { 8, 8, 8, 8 }; | ||||
| const int              Ls       = 8; | ||||
| const int              Npoles   = 12; | ||||
| const RealD            b        = 2.5; | ||||
| const RealD            c        = 1.5; | ||||
| const RealD            mf       = 0.01; | ||||
| const RealD            mpv      = 1.0; | ||||
| const RealD            M5       = 1.8; | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout << GridLogMessage << "Grid is set up to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|   // Initialize spacetime grid | ||||
|   std::cout << GridLogMessage << "Lattice dimensions: " << grid_dim << "  Ls: " << Ls << std::endl; | ||||
|   GridCartesian*         UGrid   = SpaceTimeGrid::makeFourDimGrid(grid_dim, | ||||
|                                     GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian*         FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Set up RNGs | ||||
|   std::vector<int> seeds4({1, 2, 3, 4}); | ||||
|   std::vector<int> seeds5({5, 6, 7, 8}); | ||||
|   GridParallelRNG RNG5(FGrid); | ||||
|   RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid); | ||||
|   RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   // Random gauge field | ||||
|   LatticeGaugeField Umu(UGrid); | ||||
|   SU3::HotConfiguration(RNG4, Umu); | ||||
|  | ||||
|   MobiusEOFAFermionR Lop(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf,  mf, mpv,  0.0, -1, M5, b, c); | ||||
|   MobiusEOFAFermionR Rop(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mpv, mf, mpv, -1.0,  1, M5, b, c); | ||||
|  | ||||
|   // Construct the action and test the heatbath (zero initial guess) | ||||
|   { | ||||
|     OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, Npoles); | ||||
|     ConjugateGradient<LatticeFermion> CG(1.0e-12, 5000); | ||||
|     ExactOneFlavourRatioPseudoFermionAction<WilsonImplR> Meofa(Lop, Rop, CG, Params, false); | ||||
|  | ||||
|     Meofa.refresh(Umu, RNG5); | ||||
|     printf("<Phi|Meofa|Phi> = %1.15e\n", Meofa.S(Umu)); | ||||
|   } | ||||
|  | ||||
|   // Construct the action and test the heatbath (forecasted initial guesses) | ||||
|   { | ||||
|     OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, Npoles); | ||||
|     ConjugateGradient<LatticeFermion> CG(1.0e-12, 5000); | ||||
|     ExactOneFlavourRatioPseudoFermionAction<WilsonImplR> Meofa(Lop, Rop, CG, Params, true); | ||||
|  | ||||
|     Meofa.refresh(Umu, RNG5); | ||||
|     printf("<Phi|Meofa|Phi> = %1.15e\n", Meofa.S(Umu)); | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										109
									
								
								tests/debug/Test_heatbath_mobius_eofa_gparity.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								tests/debug/Test_heatbath_mobius_eofa_gparity.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/debug/Test_heatbath_dwf_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| 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 */ | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // This program sets up the initial pseudofermion field |Phi> = Meofa^{-1/2}*|eta>, and | ||||
| // then uses this Phi to compute the action <Phi|Meofa|Phi>. | ||||
| // If all is working, one should find that <eta|eta> = <Phi|Meofa|Phi>. | ||||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| typedef GparityWilsonImplR FermionImplPolicy; | ||||
| typedef GparityMobiusEOFAFermionR FermionAction; | ||||
| typedef typename FermionAction::FermionField FermionField; | ||||
|  | ||||
| // Parameters for test | ||||
| const std::vector<int> grid_dim = { 8, 8, 8, 8 }; | ||||
| const int              Ls       = 8; | ||||
| const int              Npoles   = 12; | ||||
| const RealD            b        = 2.5; | ||||
| const RealD            c        = 1.5; | ||||
| const RealD            mf       = 0.01; | ||||
| const RealD            mpv      = 1.0; | ||||
| const RealD            M5       = 1.8; | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout << GridLogMessage << "Grid is set up to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|   // Initialize spacetime grid | ||||
|   std::cout << GridLogMessage << "Lattice dimensions: " << grid_dim << "  Ls: " << Ls << std::endl; | ||||
|   GridCartesian*         UGrid   = SpaceTimeGrid::makeFourDimGrid(grid_dim, | ||||
|                                     GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian*         FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Set up RNGs | ||||
|   std::vector<int> seeds4({1, 2, 3, 4}); | ||||
|   std::vector<int> seeds5({5, 6, 7, 8}); | ||||
|   GridParallelRNG RNG5(FGrid); | ||||
|   RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid); | ||||
|   RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   // Random gauge field | ||||
|   LatticeGaugeField Umu(UGrid); | ||||
|   SU3::HotConfiguration(RNG4, Umu); | ||||
|  | ||||
|   FermionAction::ImplParams params; | ||||
|   FermionAction Lop(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf,  mf, mpv,  0.0, -1, M5, b, c, params); | ||||
|   FermionAction Rop(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mpv, mf, mpv, -1.0,  1, M5, b, c, params); | ||||
|  | ||||
|   // Construct the action and test the heatbath (zero initial guess) | ||||
|   { | ||||
|     OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, Npoles); | ||||
|     ConjugateGradient<FermionField> CG(1.0e-12, 5000); | ||||
|     ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> Meofa(Lop, Rop, CG, Params, false); | ||||
|  | ||||
|     Meofa.refresh(Umu, RNG5); | ||||
|     printf("<Phi|Meofa|Phi> = %1.15e\n", Meofa.S(Umu)); | ||||
|   } | ||||
|  | ||||
|   // Construct the action and test the heatbath (forecasted initial guesses) | ||||
|   { | ||||
|     OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, Npoles); | ||||
|     ConjugateGradient<FermionField> CG(1.0e-12, 5000); | ||||
|     ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> Meofa(Lop, Rop, CG, Params, true); | ||||
|  | ||||
|     Meofa.refresh(Umu, RNG5); | ||||
|     printf("<Phi|Meofa|Phi> = %1.15e\n", Meofa.S(Umu)); | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										206
									
								
								tests/debug/Test_reweight_dwf_eofa.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								tests/debug/Test_reweight_dwf_eofa.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/debug/Test_reweight_dwf_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| // parameters for test | ||||
| const std::vector<int> grid_dim = { 8, 8, 8, 8 }; | ||||
| const int Ls = 8; | ||||
| const int Nhits = 25; | ||||
| const int max_iter = 5000; | ||||
| const RealD mf = 0.1; | ||||
| const RealD mb = 0.11; | ||||
| const RealD M5 = 1.8; | ||||
| const RealD stop_tol = 1.0e-12; | ||||
|  | ||||
| RealD mean(const std::vector<RealD>& data) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     RealD mean(0.0); | ||||
|     for(int i=0; i<N; ++i){ mean += data[i]; } | ||||
|     return mean/RealD(N); | ||||
| } | ||||
|  | ||||
| RealD jack_mean(const std::vector<RealD>& data, int sample) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     RealD mean(0.0); | ||||
|     for(int i=0; i<N; ++i){ if(i != sample){ mean += data[i]; } } | ||||
|     return mean/RealD(N-1); | ||||
| } | ||||
|  | ||||
| RealD jack_std(const std::vector<RealD>& jacks, RealD mean) | ||||
| { | ||||
|     int N = jacks.size(); | ||||
|     RealD std(0.0); | ||||
|     for(int i=0; i<N; ++i){ std += std::pow(jacks[i]-mean, 2.0); } | ||||
|     return std::sqrt(RealD(N-1)/RealD(N)*std); | ||||
| } | ||||
|  | ||||
| std::vector<RealD> jack_stats(const std::vector<RealD>& data) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     std::vector<RealD> jack_samples(N); | ||||
|     std::vector<RealD> jack_stats(2); | ||||
|  | ||||
|     jack_stats[0] = mean(data); | ||||
|     for(int i=0; i<N; i++){ jack_samples[i] = jack_mean(data,i); } | ||||
|     jack_stats[1] = jack_std(jack_samples, jack_stats[0]); | ||||
|     return jack_stats; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   // Initialize spacetime grid | ||||
|   std::cout << GridLogMessage << "Lattice dimensions: " | ||||
|     << grid_dim << "   Ls: " << Ls << std::endl; | ||||
|   GridCartesian* UGrid = SpaceTimeGrid::makeFourDimGrid(grid_dim, | ||||
|       GridDefaultSimd(Nd, vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian* FGrid = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Set up RNGs | ||||
|   std::vector<int> seeds4({1, 2, 3, 4}); | ||||
|   std::vector<int> seeds5({5, 6, 7, 8}); | ||||
|   GridParallelRNG RNG5(FGrid); | ||||
|   RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid); | ||||
|   RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   // Random gauge field | ||||
|   LatticeGaugeField Umu(UGrid); | ||||
|   SU3::HotConfiguration(RNG4, Umu); | ||||
|  | ||||
|   // Initialize RHMC fermion operators | ||||
|   DomainWallFermionR Ddwf_f(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, M5); | ||||
|   DomainWallFermionR Ddwf_b(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, M5); | ||||
|   SchurDiagMooeeOperator<DomainWallFermionR, LatticeFermion> MdagM(Ddwf_f); | ||||
|   SchurDiagMooeeOperator<DomainWallFermionR, LatticeFermion> VdagV(Ddwf_b); | ||||
|  | ||||
|   // Degree 12 rational approximations to x^(1/4) and x^(-1/4) | ||||
|   double     lo = 0.0001; | ||||
|   double     hi = 95.0; | ||||
|   int precision = 64; | ||||
|   int    degree = 12; | ||||
|   AlgRemez remez(lo, hi, precision); | ||||
|   std::cout << GridLogMessage << "Generating degree " << degree << " for x^(1/4)" << std::endl; | ||||
|   remez.generateApprox(degree, 1, 4); | ||||
|   MultiShiftFunction PowerQuarter(remez, stop_tol, false); | ||||
|   MultiShiftFunction PowerNegQuarter(remez, stop_tol, true); | ||||
|  | ||||
|   // Stochastically estimate reweighting factor via RHMC | ||||
|   RealD scale = std::sqrt(0.5); | ||||
|   std::vector<RealD> rw_rhmc(Nhits); | ||||
|   ConjugateGradientMultiShift<LatticeFermion> msCG_V(max_iter, PowerQuarter); | ||||
|   ConjugateGradientMultiShift<LatticeFermion> msCG_M(max_iter, PowerNegQuarter); | ||||
|   std::cout.precision(12); | ||||
|  | ||||
|   for(int hit=0; hit<Nhits; hit++){ | ||||
|  | ||||
|     // Gaussian source | ||||
|     LatticeFermion Phi    (Ddwf_f.FermionGrid()); | ||||
|     LatticeFermion PhiOdd (Ddwf_f.FermionRedBlackGrid()); | ||||
|     std::vector<LatticeFermion> tmp(2, Ddwf_f.FermionRedBlackGrid()); | ||||
|     gaussian(RNG5, Phi); | ||||
|     Phi = Phi*scale; | ||||
|  | ||||
|     pickCheckerboard(Odd, PhiOdd, Phi); | ||||
|  | ||||
|     // evaluate -log(rw) | ||||
|     msCG_V(VdagV, PhiOdd, tmp[0]); | ||||
|     msCG_M(MdagM, tmp[0], tmp[1]); | ||||
|     rw_rhmc[hit] = norm2(tmp[1]) - norm2(PhiOdd); | ||||
|     std::cout << std::endl << "==================================================" << std::endl; | ||||
|     std::cout << " --- RHMC: Hit " << hit << ": rw = " << rw_rhmc[hit]; | ||||
|     std::cout << std::endl << "==================================================" << std::endl << std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   // Initialize EOFA fermion operators | ||||
|   RealD shift_L = 0.0; | ||||
|   RealD shift_R = -1.0; | ||||
|   int pm = 1; | ||||
|   DomainWallEOFAFermionR Deofa_L(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, shift_L, pm, M5); | ||||
|   DomainWallEOFAFermionR Deofa_R(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, shift_R, pm, M5); | ||||
|   MdagMLinearOperator<DomainWallEOFAFermionR, LatticeFermion> LdagL(Deofa_L); | ||||
|   MdagMLinearOperator<DomainWallEOFAFermionR, LatticeFermion> RdagR(Deofa_R); | ||||
|  | ||||
|   // Stochastically estimate reweighting factor via EOFA | ||||
|   RealD k = Deofa_L.k; | ||||
|   std::vector<RealD> rw_eofa(Nhits); | ||||
|   ConjugateGradient<LatticeFermion> CG(stop_tol, max_iter); | ||||
|   SchurRedBlackDiagMooeeSolve<LatticeFermion> SchurSolver(CG); | ||||
|  | ||||
|   for(int hit=0; hit<Nhits; hit++){ | ||||
|  | ||||
|     // Gaussian source | ||||
|     LatticeFermion Phi       (Deofa_L.FermionGrid()); | ||||
|     LatticeFermion spProj_Phi(Deofa_L.FermionGrid()); | ||||
|     std::vector<LatticeFermion> tmp(2, Deofa_L.FermionGrid()); | ||||
|     gaussian(RNG5, Phi); | ||||
|     Phi = Phi*scale; | ||||
|  | ||||
|     // evaluate -log(rw) | ||||
|     // LH term | ||||
|     for(int s=0; s<Ls; ++s){ axpby_ssp_pminus(spProj_Phi, 0.0, Phi, 1.0, Phi, s, s); } | ||||
|     Deofa_L.Omega(spProj_Phi, tmp[0], -1, 0); | ||||
|     G5R5(tmp[1], tmp[0]); | ||||
|     tmp[0] = zero; | ||||
|     SchurSolver(Deofa_L, tmp[1], tmp[0]); | ||||
|     Deofa_L.Omega(tmp[0], tmp[1], -1, 1); | ||||
|     rw_eofa[hit] = -k*innerProduct(spProj_Phi,tmp[1]).real(); | ||||
|  | ||||
|     // RH term | ||||
|     for(int s=0; s<Ls; ++s){ axpby_ssp_pplus(spProj_Phi, 0.0, Phi, 1.0, Phi, s, s); } | ||||
|     Deofa_R.Omega(spProj_Phi, tmp[0], 1, 0); | ||||
|     G5R5(tmp[1], tmp[0]); | ||||
|     tmp[0] = zero; | ||||
|     SchurSolver(Deofa_R, tmp[1], tmp[0]); | ||||
|     Deofa_R.Omega(tmp[0], tmp[1], 1, 1); | ||||
|     rw_eofa[hit] += k*innerProduct(spProj_Phi,tmp[1]).real(); | ||||
|     std::cout << std::endl << "==================================================" << std::endl; | ||||
|     std::cout << " --- EOFA: Hit " << hit << ": rw = " << rw_eofa[hit]; | ||||
|     std::cout << std::endl << "==================================================" << std::endl << std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   std::vector<RealD> rhmc_result = jack_stats(rw_rhmc); | ||||
|   std::vector<RealD> eofa_result = jack_stats(rw_eofa); | ||||
|   std::cout << std::endl << "RHMC: rw = " << rhmc_result[0] << " +/- " << rhmc_result[1] << std::endl; | ||||
|   std::cout << std::endl << "EOFA: rw = " << eofa_result[0] << " +/- " << eofa_result[1] << std::endl; | ||||
|  | ||||
|   Grid_finalize(); | ||||
| } | ||||
							
								
								
									
										209
									
								
								tests/debug/Test_reweight_dwf_eofa_gparity.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								tests/debug/Test_reweight_dwf_eofa_gparity.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/debug/Test_reweight_dwf_eofa_gparity.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| typedef typename GparityDomainWallFermionR::FermionField FermionField; | ||||
|  | ||||
| // parameters for test | ||||
| const std::vector<int> grid_dim = { 8, 8, 8, 8 }; | ||||
| const int Ls = 8; | ||||
| const int Nhits = 10; | ||||
| const int max_iter = 5000; | ||||
| const RealD mf = 0.1; | ||||
| const RealD mb = 0.11; | ||||
| const RealD M5 = 1.8; | ||||
| const RealD stop_tol = 1.0e-12; | ||||
|  | ||||
| RealD mean(const std::vector<RealD>& data) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     RealD mean(0.0); | ||||
|     for(int i=0; i<N; ++i){ mean += data[i]; } | ||||
|     return mean/RealD(N); | ||||
| } | ||||
|  | ||||
| RealD jack_mean(const std::vector<RealD>& data, int sample) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     RealD mean(0.0); | ||||
|     for(int i=0; i<N; ++i){ if(i != sample){ mean += data[i]; } } | ||||
|     return mean/RealD(N-1); | ||||
| } | ||||
|  | ||||
| RealD jack_std(const std::vector<RealD>& jacks, RealD mean) | ||||
| { | ||||
|     int N = jacks.size(); | ||||
|     RealD std(0.0); | ||||
|     for(int i=0; i<N; ++i){ std += std::pow(jacks[i]-mean, 2.0); } | ||||
|     return std::sqrt(RealD(N-1)/RealD(N)*std); | ||||
| } | ||||
|  | ||||
| std::vector<RealD> jack_stats(const std::vector<RealD>& data) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     std::vector<RealD> jack_samples(N); | ||||
|     std::vector<RealD> jack_stats(2); | ||||
|  | ||||
|     jack_stats[0] = mean(data); | ||||
|     for(int i=0; i<N; i++){ jack_samples[i] = jack_mean(data,i); } | ||||
|     jack_stats[1] = jack_std(jack_samples, jack_stats[0]); | ||||
|     return jack_stats; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   // Initialize spacetime grid | ||||
|   std::cout << GridLogMessage << "Lattice dimensions: " | ||||
|     << grid_dim << "   Ls: " << Ls << std::endl; | ||||
|   GridCartesian* UGrid = SpaceTimeGrid::makeFourDimGrid(grid_dim, | ||||
|       GridDefaultSimd(Nd, vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian* FGrid = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Set up RNGs | ||||
|   std::vector<int> seeds4({1, 2, 3, 4}); | ||||
|   std::vector<int> seeds5({5, 6, 7, 8}); | ||||
|   GridParallelRNG RNG5(FGrid); | ||||
|   RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid); | ||||
|   RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   // Random gauge field | ||||
|   LatticeGaugeField Umu(UGrid); | ||||
|   SU3::HotConfiguration(RNG4, Umu); | ||||
|  | ||||
|   // Initialize RHMC fermion operators | ||||
|   GparityDomainWallFermionR::ImplParams params; | ||||
|   GparityDomainWallFermionR Ddwf_f(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, M5, params); | ||||
|   GparityDomainWallFermionR Ddwf_b(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, M5, params); | ||||
|   SchurDiagMooeeOperator<GparityDomainWallFermionR, FermionField> MdagM(Ddwf_f); | ||||
|   SchurDiagMooeeOperator<GparityDomainWallFermionR, FermionField> VdagV(Ddwf_b); | ||||
|  | ||||
|   // Degree 12 rational approximations to x^(1/4) and x^(-1/4) | ||||
|   double     lo = 0.0001; | ||||
|   double     hi = 95.0; | ||||
|   int precision = 64; | ||||
|   int    degree = 12; | ||||
|   AlgRemez remez(lo, hi, precision); | ||||
|   std::cout << GridLogMessage << "Generating degree " << degree << " for x^(1/4)" << std::endl; | ||||
|   remez.generateApprox(degree, 1, 4); | ||||
|   MultiShiftFunction PowerQuarter(remez, stop_tol, false); | ||||
|   MultiShiftFunction PowerNegQuarter(remez, stop_tol, true); | ||||
|  | ||||
|   // Stochastically estimate reweighting factor via RHMC | ||||
|   RealD scale = std::sqrt(0.5); | ||||
|   std::vector<RealD> rw_rhmc(Nhits); | ||||
|   ConjugateGradientMultiShift<FermionField> msCG_V(max_iter, PowerQuarter); | ||||
|   ConjugateGradientMultiShift<FermionField> msCG_M(max_iter, PowerNegQuarter); | ||||
|   std::cout.precision(12); | ||||
|  | ||||
|   for(int hit=0; hit<Nhits; hit++){ | ||||
|  | ||||
|     // Gaussian source | ||||
|     FermionField Phi    (Ddwf_f.FermionGrid()); | ||||
|     FermionField PhiOdd (Ddwf_f.FermionRedBlackGrid()); | ||||
|     std::vector<FermionField> tmp(2, Ddwf_f.FermionRedBlackGrid()); | ||||
|     gaussian(RNG5, Phi); | ||||
|     Phi = Phi*scale; | ||||
|  | ||||
|     pickCheckerboard(Odd, PhiOdd, Phi); | ||||
|  | ||||
|     // evaluate -log(rw) | ||||
|     msCG_V(VdagV, PhiOdd, tmp[0]); | ||||
|     msCG_M(MdagM, tmp[0], tmp[1]); | ||||
|     rw_rhmc[hit] = norm2(tmp[1]) - norm2(PhiOdd); | ||||
|     std::cout << std::endl << "==================================================" << std::endl; | ||||
|     std::cout << " --- RHMC: Hit " << hit << ": rw = " << rw_rhmc[hit]; | ||||
|     std::cout << std::endl << "==================================================" << std::endl << std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   // Initialize EOFA fermion operators | ||||
|   RealD shift_L = 0.0; | ||||
|   RealD shift_R = -1.0; | ||||
|   int pm = 1; | ||||
|   GparityDomainWallEOFAFermionR Deofa_L(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, shift_L, pm, M5, params); | ||||
|   GparityDomainWallEOFAFermionR Deofa_R(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, shift_R, pm, M5, params); | ||||
|   MdagMLinearOperator<GparityDomainWallEOFAFermionR, FermionField> LdagL(Deofa_L); | ||||
|   MdagMLinearOperator<GparityDomainWallEOFAFermionR, FermionField> RdagR(Deofa_R); | ||||
|  | ||||
|   // Stochastically estimate reweighting factor via EOFA | ||||
|   RealD k = Deofa_L.k; | ||||
|   std::vector<RealD> rw_eofa(Nhits); | ||||
|   ConjugateGradient<FermionField> CG(stop_tol, max_iter); | ||||
|   SchurRedBlackDiagMooeeSolve<FermionField> SchurSolver(CG); | ||||
|  | ||||
|   for(int hit=0; hit<Nhits; hit++){ | ||||
|  | ||||
|     // Gaussian source | ||||
|     FermionField Phi       (Deofa_L.FermionGrid()); | ||||
|     FermionField spProj_Phi(Deofa_L.FermionGrid()); | ||||
|     std::vector<FermionField> tmp(2, Deofa_L.FermionGrid()); | ||||
|     gaussian(RNG5, Phi); | ||||
|     Phi = Phi*scale; | ||||
|  | ||||
|     // evaluate -log(rw) | ||||
|     // LH term | ||||
|     for(int s=0; s<Ls; ++s){ axpby_ssp_pminus(spProj_Phi, 0.0, Phi, 1.0, Phi, s, s); } | ||||
|     Deofa_L.Omega(spProj_Phi, tmp[0], -1, 0); | ||||
|     G5R5(tmp[1], tmp[0]); | ||||
|     tmp[0] = zero; | ||||
|     SchurSolver(Deofa_L, tmp[1], tmp[0]); | ||||
|     Deofa_L.Omega(tmp[0], tmp[1], -1, 1); | ||||
|     rw_eofa[hit] = -k*innerProduct(spProj_Phi,tmp[1]).real(); | ||||
|  | ||||
|     // RH term | ||||
|     for(int s=0; s<Ls; ++s){ axpby_ssp_pplus(spProj_Phi, 0.0, Phi, 1.0, Phi, s, s); } | ||||
|     Deofa_R.Omega(spProj_Phi, tmp[0], 1, 0); | ||||
|     G5R5(tmp[1], tmp[0]); | ||||
|     tmp[0] = zero; | ||||
|     SchurSolver(Deofa_R, tmp[1], tmp[0]); | ||||
|     Deofa_R.Omega(tmp[0], tmp[1], 1, 1); | ||||
|     rw_eofa[hit] += k*innerProduct(spProj_Phi,tmp[1]).real(); | ||||
|     std::cout << std::endl << "==================================================" << std::endl; | ||||
|     std::cout << " --- EOFA: Hit " << hit << ": rw = " << rw_eofa[hit]; | ||||
|     std::cout << std::endl << "==================================================" << std::endl << std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   std::vector<RealD> rhmc_result = jack_stats(rw_rhmc); | ||||
|   std::vector<RealD> eofa_result = jack_stats(rw_eofa); | ||||
|   std::cout << std::endl << "RHMC: rw = " << rhmc_result[0] << " +/- " << rhmc_result[1] << std::endl; | ||||
|   std::cout << std::endl << "EOFA: rw = " << eofa_result[0] << " +/- " << eofa_result[1] << std::endl; | ||||
|  | ||||
|   Grid_finalize(); | ||||
| } | ||||
							
								
								
									
										215
									
								
								tests/debug/Test_reweight_mobius_eofa.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								tests/debug/Test_reweight_mobius_eofa.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/debug/Test_reweight_dwf_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| // parameters for test | ||||
| const std::vector<int> grid_dim = { 8, 8, 8, 8 }; | ||||
| const int Ls = 8; | ||||
| const int Nhits = 10; | ||||
| const int max_iter = 5000; | ||||
| const RealD b  = 2.5; | ||||
| const RealD c  = 1.5; | ||||
| const RealD mf = 0.1; | ||||
| const RealD mb = 0.11; | ||||
| const RealD M5 = 1.8; | ||||
| const RealD stop_tol = 1.0e-12; | ||||
|  | ||||
| RealD mean(const std::vector<RealD>& data) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     RealD mean(0.0); | ||||
|     for(int i=0; i<N; ++i){ mean += data[i]; } | ||||
|     return mean/RealD(N); | ||||
| } | ||||
|  | ||||
| RealD jack_mean(const std::vector<RealD>& data, int sample) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     RealD mean(0.0); | ||||
|     for(int i=0; i<N; ++i){ if(i != sample){ mean += data[i]; } } | ||||
|     return mean/RealD(N-1); | ||||
| } | ||||
|  | ||||
| RealD jack_std(const std::vector<RealD>& jacks, RealD mean) | ||||
| { | ||||
|     int N = jacks.size(); | ||||
|     RealD std(0.0); | ||||
|     for(int i=0; i<N; ++i){ std += std::pow(jacks[i]-mean, 2.0); } | ||||
|     return std::sqrt(RealD(N-1)/RealD(N)*std); | ||||
| } | ||||
|  | ||||
| std::vector<RealD> jack_stats(const std::vector<RealD>& data) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     std::vector<RealD> jack_samples(N); | ||||
|     std::vector<RealD> jack_stats(2); | ||||
|  | ||||
|     jack_stats[0] = mean(data); | ||||
|     for(int i=0; i<N; i++){ jack_samples[i] = jack_mean(data,i); } | ||||
|     jack_stats[1] = jack_std(jack_samples, jack_stats[0]); | ||||
|     return jack_stats; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   // Initialize spacetime grid | ||||
|   std::cout << GridLogMessage << "Lattice dimensions: " | ||||
|     << grid_dim << "   Ls: " << Ls << std::endl; | ||||
|   GridCartesian* UGrid = SpaceTimeGrid::makeFourDimGrid(grid_dim, | ||||
|       GridDefaultSimd(Nd, vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian* FGrid = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Set up RNGs | ||||
|   std::vector<int> seeds4({1, 2, 3, 4}); | ||||
|   std::vector<int> seeds5({5, 6, 7, 8}); | ||||
|   GridParallelRNG RNG5(FGrid); | ||||
|   RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid); | ||||
|   RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   // Random gauge field | ||||
|   LatticeGaugeField Umu(UGrid); | ||||
|   SU3::HotConfiguration(RNG4, Umu); | ||||
|  | ||||
|   // Initialize RHMC fermion operators | ||||
|   MobiusFermionR Ddwf_f(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, M5, b, c); | ||||
|   MobiusFermionR Ddwf_b(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, M5, b, c); | ||||
|   SchurDiagMooeeOperator<MobiusFermionR, LatticeFermion> MdagM(Ddwf_f); | ||||
|   SchurDiagMooeeOperator<MobiusFermionR, LatticeFermion> VdagV(Ddwf_b); | ||||
|  | ||||
|   // Degree 12 rational approximations to x^(1/4) and x^(-1/4) | ||||
|   double     lo = 0.0001; | ||||
|   double     hi = 95.0; | ||||
|   int precision = 64; | ||||
|   int    degree = 12; | ||||
|   AlgRemez remez(lo, hi, precision); | ||||
|   std::cout << GridLogMessage << "Generating degree " << degree << " for x^(1/4)" << std::endl; | ||||
|   remez.generateApprox(degree, 1, 4); | ||||
|   MultiShiftFunction PowerQuarter(remez, stop_tol, false); | ||||
|   MultiShiftFunction PowerNegQuarter(remez, stop_tol, true); | ||||
|  | ||||
|   // Stochastically estimate reweighting factor via RHMC | ||||
|   RealD scale = std::sqrt(0.5); | ||||
|   std::vector<RealD> rw_rhmc(Nhits); | ||||
|   ConjugateGradientMultiShift<LatticeFermion> msCG_V(max_iter, PowerQuarter); | ||||
|   ConjugateGradientMultiShift<LatticeFermion> msCG_M(max_iter, PowerNegQuarter); | ||||
|   std::cout.precision(12); | ||||
|  | ||||
|   for(int hit=0; hit<Nhits; hit++){ | ||||
|  | ||||
|     // Gaussian source | ||||
|     LatticeFermion Phi    (Ddwf_f.FermionGrid()); | ||||
|     LatticeFermion PhiOdd (Ddwf_f.FermionRedBlackGrid()); | ||||
|     std::vector<LatticeFermion> tmp(2, Ddwf_f.FermionRedBlackGrid()); | ||||
|     gaussian(RNG5, Phi); | ||||
|     Phi = Phi*scale; | ||||
|  | ||||
|     pickCheckerboard(Odd, PhiOdd, Phi); | ||||
|  | ||||
|     // evaluate -log(rw) | ||||
|     msCG_V(VdagV, PhiOdd, tmp[0]); | ||||
|     msCG_M(MdagM, tmp[0], tmp[1]); | ||||
|     rw_rhmc[hit] = norm2(tmp[1]) - norm2(PhiOdd); | ||||
|     std::cout << std::endl << "==================================================" << std::endl; | ||||
|     std::cout << " --- RHMC: Hit " << hit << ": rw = " << rw_rhmc[hit]; | ||||
|     std::cout << std::endl << "==================================================" << std::endl << std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   // Initialize EOFA fermion operators | ||||
|   RealD shift_L = 0.0; | ||||
|   RealD shift_R = -1.0; | ||||
|   int pm = 1; | ||||
|   MobiusEOFAFermionR Deofa_L(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, shift_L, pm, M5, b, c); | ||||
|   MobiusEOFAFermionR Deofa_R(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, shift_R, pm, M5, b, c); | ||||
|   MdagMLinearOperator<MobiusEOFAFermionR, LatticeFermion> LdagL(Deofa_L); | ||||
|   MdagMLinearOperator<MobiusEOFAFermionR, LatticeFermion> RdagR(Deofa_R); | ||||
|  | ||||
|   // Stochastically estimate reweighting factor via EOFA | ||||
|   RealD k = Deofa_L.k; | ||||
|   std::vector<RealD> rw_eofa(Nhits); | ||||
|   ConjugateGradient<LatticeFermion> CG(stop_tol, max_iter); | ||||
|   SchurRedBlackDiagMooeeSolve<LatticeFermion> SchurSolver(CG); | ||||
|  | ||||
|   // Compute -log(Z), where: ( RHMC det ratio ) = Z * ( EOFA det ratio ) | ||||
|   RealD Z = std::pow(b+c+1.0,Ls) + mf*std::pow(b+c-1.0,Ls); | ||||
|   Z /= std::pow(b+c+1.0,Ls) + mb*std::pow(b+c-1.0,Ls); | ||||
|   Z = -12.0*grid_dim[0]*grid_dim[1]*grid_dim[2]*grid_dim[3]*std::log(Z); | ||||
|  | ||||
|   for(int hit=0; hit<Nhits; hit++){ | ||||
|  | ||||
|     // Gaussian source | ||||
|     LatticeFermion Phi       (Deofa_L.FermionGrid()); | ||||
|     LatticeFermion spProj_Phi(Deofa_L.FermionGrid()); | ||||
|     std::vector<LatticeFermion> tmp(2, Deofa_L.FermionGrid()); | ||||
|     gaussian(RNG5, Phi); | ||||
|     Phi = Phi*scale; | ||||
|  | ||||
|     // evaluate -log(rw) | ||||
|     // LH term | ||||
|     for(int s=0; s<Ls; ++s){ axpby_ssp_pminus(spProj_Phi, 0.0, Phi, 1.0, Phi, s, s); } | ||||
|     Deofa_L.Omega(spProj_Phi, tmp[0], -1, 0); | ||||
|     G5R5(tmp[1], tmp[0]); | ||||
|     tmp[0] = zero; | ||||
|     SchurSolver(Deofa_L, tmp[1], tmp[0]); | ||||
|     Deofa_L.Dtilde(tmp[0], tmp[1]); | ||||
|     Deofa_L.Omega(tmp[1], tmp[0], -1, 1); | ||||
|     rw_eofa[hit] = Z - k*innerProduct(spProj_Phi,tmp[0]).real(); | ||||
|  | ||||
|     // RH term | ||||
|     for(int s=0; s<Ls; ++s){ axpby_ssp_pplus(spProj_Phi, 0.0, Phi, 1.0, Phi, s, s); } | ||||
|     Deofa_R.Omega(spProj_Phi, tmp[0], 1, 0); | ||||
|     G5R5(tmp[1], tmp[0]); | ||||
|     tmp[0] = zero; | ||||
|     SchurSolver(Deofa_R, tmp[1], tmp[0]); | ||||
|     Deofa_R.Dtilde(tmp[0], tmp[1]); | ||||
|     Deofa_R.Omega(tmp[1], tmp[0], 1, 1); | ||||
|     rw_eofa[hit] += k*innerProduct(spProj_Phi,tmp[0]).real(); | ||||
|     std::cout << std::endl << "==================================================" << std::endl; | ||||
|     std::cout << " --- EOFA: Hit " << hit << ": rw = " << rw_eofa[hit]; | ||||
|     std::cout << std::endl << "==================================================" << std::endl << std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   std::vector<RealD> rhmc_result = jack_stats(rw_rhmc); | ||||
|   std::vector<RealD> eofa_result = jack_stats(rw_eofa); | ||||
|   std::cout << std::endl << "RHMC: rw = " << rhmc_result[0] << " +/- " << rhmc_result[1] << std::endl; | ||||
|   std::cout << std::endl << "EOFA: rw = " << eofa_result[0] << " +/- " << eofa_result[1] << std::endl; | ||||
|  | ||||
|   Grid_finalize(); | ||||
| } | ||||
							
								
								
									
										218
									
								
								tests/debug/Test_reweight_mobius_eofa_gparity.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								tests/debug/Test_reweight_mobius_eofa_gparity.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,218 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/debug/Test_reweight_dwf_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| typedef typename GparityDomainWallFermionR::FermionField FermionField; | ||||
|  | ||||
| // parameters for test | ||||
| const std::vector<int> grid_dim = { 8, 8, 8, 8 }; | ||||
| const int Ls = 8; | ||||
| const int Nhits = 10; | ||||
| const int max_iter = 5000; | ||||
| const RealD b  = 2.5; | ||||
| const RealD c  = 1.5; | ||||
| const RealD mf = 0.1; | ||||
| const RealD mb = 0.11; | ||||
| const RealD M5 = 1.8; | ||||
| const RealD stop_tol = 1.0e-12; | ||||
|  | ||||
| RealD mean(const std::vector<RealD>& data) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     RealD mean(0.0); | ||||
|     for(int i=0; i<N; ++i){ mean += data[i]; } | ||||
|     return mean/RealD(N); | ||||
| } | ||||
|  | ||||
| RealD jack_mean(const std::vector<RealD>& data, int sample) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     RealD mean(0.0); | ||||
|     for(int i=0; i<N; ++i){ if(i != sample){ mean += data[i]; } } | ||||
|     return mean/RealD(N-1); | ||||
| } | ||||
|  | ||||
| RealD jack_std(const std::vector<RealD>& jacks, RealD mean) | ||||
| { | ||||
|     int N = jacks.size(); | ||||
|     RealD std(0.0); | ||||
|     for(int i=0; i<N; ++i){ std += std::pow(jacks[i]-mean, 2.0); } | ||||
|     return std::sqrt(RealD(N-1)/RealD(N)*std); | ||||
| } | ||||
|  | ||||
| std::vector<RealD> jack_stats(const std::vector<RealD>& data) | ||||
| { | ||||
|     int N = data.size(); | ||||
|     std::vector<RealD> jack_samples(N); | ||||
|     std::vector<RealD> jack_stats(2); | ||||
|  | ||||
|     jack_stats[0] = mean(data); | ||||
|     for(int i=0; i<N; i++){ jack_samples[i] = jack_mean(data,i); } | ||||
|     jack_stats[1] = jack_std(jack_samples, jack_stats[0]); | ||||
|     return jack_stats; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   // Initialize spacetime grid | ||||
|   std::cout << GridLogMessage << "Lattice dimensions: " | ||||
|     << grid_dim << "   Ls: " << Ls << std::endl; | ||||
|   GridCartesian* UGrid = SpaceTimeGrid::makeFourDimGrid(grid_dim, | ||||
|       GridDefaultSimd(Nd, vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian* UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian* FGrid = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian* FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Set up RNGs | ||||
|   std::vector<int> seeds4({1, 2, 3, 4}); | ||||
|   std::vector<int> seeds5({5, 6, 7, 8}); | ||||
|   GridParallelRNG RNG5(FGrid); | ||||
|   RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid); | ||||
|   RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   // Random gauge field | ||||
|   LatticeGaugeField Umu(UGrid); | ||||
|   SU3::HotConfiguration(RNG4, Umu); | ||||
|  | ||||
|   // Initialize RHMC fermion operators | ||||
|   GparityDomainWallFermionR::ImplParams params; | ||||
|   GparityMobiusFermionR Ddwf_f(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, M5, b, c, params); | ||||
|   GparityMobiusFermionR Ddwf_b(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, M5, b, c, params); | ||||
|   SchurDiagMooeeOperator<GparityMobiusFermionR, FermionField> MdagM(Ddwf_f); | ||||
|   SchurDiagMooeeOperator<GparityMobiusFermionR, FermionField> VdagV(Ddwf_b); | ||||
|  | ||||
|   // Degree 12 rational approximations to x^(1/4) and x^(-1/4) | ||||
|   double     lo = 0.0001; | ||||
|   double     hi = 95.0; | ||||
|   int precision = 64; | ||||
|   int    degree = 12; | ||||
|   AlgRemez remez(lo, hi, precision); | ||||
|   std::cout << GridLogMessage << "Generating degree " << degree << " for x^(1/4)" << std::endl; | ||||
|   remez.generateApprox(degree, 1, 4); | ||||
|   MultiShiftFunction PowerQuarter(remez, stop_tol, false); | ||||
|   MultiShiftFunction PowerNegQuarter(remez, stop_tol, true); | ||||
|  | ||||
|   // Stochastically estimate reweighting factor via RHMC | ||||
|   RealD scale = std::sqrt(0.5); | ||||
|   std::vector<RealD> rw_rhmc(Nhits); | ||||
|   ConjugateGradientMultiShift<FermionField> msCG_V(max_iter, PowerQuarter); | ||||
|   ConjugateGradientMultiShift<FermionField> msCG_M(max_iter, PowerNegQuarter); | ||||
|   std::cout.precision(12); | ||||
|  | ||||
|   for(int hit=0; hit<Nhits; hit++){ | ||||
|  | ||||
|     // Gaussian source | ||||
|     FermionField Phi    (Ddwf_f.FermionGrid()); | ||||
|     FermionField PhiOdd (Ddwf_f.FermionRedBlackGrid()); | ||||
|     std::vector<FermionField> tmp(2, Ddwf_f.FermionRedBlackGrid()); | ||||
|     gaussian(RNG5, Phi); | ||||
|     Phi = Phi*scale; | ||||
|  | ||||
|     pickCheckerboard(Odd, PhiOdd, Phi); | ||||
|  | ||||
|     // evaluate -log(rw) | ||||
|     msCG_V(VdagV, PhiOdd, tmp[0]); | ||||
|     msCG_M(MdagM, tmp[0], tmp[1]); | ||||
|     rw_rhmc[hit] = norm2(tmp[1]) - norm2(PhiOdd); | ||||
|     std::cout << std::endl << "==================================================" << std::endl; | ||||
|     std::cout << " --- RHMC: Hit " << hit << ": rw = " << rw_rhmc[hit]; | ||||
|     std::cout << std::endl << "==================================================" << std::endl << std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   // Initialize EOFA fermion operators | ||||
|   RealD shift_L = 0.0; | ||||
|   RealD shift_R = -1.0; | ||||
|   int pm = 1; | ||||
|   GparityMobiusEOFAFermionR Deofa_L(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, shift_L, pm, M5, b, c, params); | ||||
|   GparityMobiusEOFAFermionR Deofa_R(Umu, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, shift_R, pm, M5, b, c, params); | ||||
|   MdagMLinearOperator<GparityMobiusEOFAFermionR, FermionField> LdagL(Deofa_L); | ||||
|   MdagMLinearOperator<GparityMobiusEOFAFermionR, FermionField> RdagR(Deofa_R); | ||||
|  | ||||
|   // Stochastically estimate reweighting factor via EOFA | ||||
|   RealD k = Deofa_L.k; | ||||
|   std::vector<RealD> rw_eofa(Nhits); | ||||
|   ConjugateGradient<FermionField> CG(stop_tol, max_iter); | ||||
|   SchurRedBlackDiagMooeeSolve<FermionField> SchurSolver(CG); | ||||
|  | ||||
|   // Compute -log(Z), where: ( RHMC det ratio ) = Z * ( EOFA det ratio ) | ||||
|   RealD Z = std::pow(b+c+1.0,Ls) + mf*std::pow(b+c-1.0,Ls); | ||||
|   Z /= std::pow(b+c+1.0,Ls) + mb*std::pow(b+c-1.0,Ls); | ||||
|   Z = -12.0*grid_dim[0]*grid_dim[1]*grid_dim[2]*grid_dim[3]*std::log(Z); | ||||
|  | ||||
|   for(int hit=0; hit<Nhits; hit++){ | ||||
|  | ||||
|     // Gaussian source | ||||
|     FermionField Phi       (Deofa_L.FermionGrid()); | ||||
|     FermionField spProj_Phi(Deofa_L.FermionGrid()); | ||||
|     std::vector<FermionField> tmp(2, Deofa_L.FermionGrid()); | ||||
|     gaussian(RNG5, Phi); | ||||
|     Phi = Phi*scale; | ||||
|  | ||||
|     // evaluate -log(rw) | ||||
|     // LH term | ||||
|     for(int s=0; s<Ls; ++s){ axpby_ssp_pminus(spProj_Phi, 0.0, Phi, 1.0, Phi, s, s); } | ||||
|     Deofa_L.Omega(spProj_Phi, tmp[0], -1, 0); | ||||
|     G5R5(tmp[1], tmp[0]); | ||||
|     tmp[0] = zero; | ||||
|     SchurSolver(Deofa_L, tmp[1], tmp[0]); | ||||
|     Deofa_L.Dtilde(tmp[0], tmp[1]); | ||||
|     Deofa_L.Omega(tmp[1], tmp[0], -1, 1); | ||||
|     rw_eofa[hit] = 2.0*Z - k*innerProduct(spProj_Phi,tmp[0]).real(); | ||||
|  | ||||
|     // RH term | ||||
|     for(int s=0; s<Ls; ++s){ axpby_ssp_pplus(spProj_Phi, 0.0, Phi, 1.0, Phi, s, s); } | ||||
|     Deofa_R.Omega(spProj_Phi, tmp[0], 1, 0); | ||||
|     G5R5(tmp[1], tmp[0]); | ||||
|     tmp[0] = zero; | ||||
|     SchurSolver(Deofa_R, tmp[1], tmp[0]); | ||||
|     Deofa_R.Dtilde(tmp[0], tmp[1]); | ||||
|     Deofa_R.Omega(tmp[1], tmp[0], 1, 1); | ||||
|     rw_eofa[hit] += k*innerProduct(spProj_Phi,tmp[0]).real(); | ||||
|     std::cout << std::endl << "==================================================" << std::endl; | ||||
|     std::cout << " --- EOFA: Hit " << hit << ": rw = " << rw_eofa[hit]; | ||||
|     std::cout << std::endl << "==================================================" << std::endl << std::endl; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   std::vector<RealD> rhmc_result = jack_stats(rw_rhmc); | ||||
|   std::vector<RealD> eofa_result = jack_stats(rw_eofa); | ||||
|   std::cout << std::endl << "RHMC: rw = " << rhmc_result[0] << " +/- " << rhmc_result[1] << std::endl; | ||||
|   std::cout << std::endl << "EOFA: rw = " << eofa_result[0] << " +/- " << eofa_result[1] << std::endl; | ||||
|  | ||||
|   Grid_finalize(); | ||||
| } | ||||
							
								
								
									
										164
									
								
								tests/forces/Test_dwf_force_eofa.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								tests/forces/Test_dwf_force_eofa.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/forces/Test_dwf_force_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| int main (int argc, char** argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   std::vector<int> latt_size   = GridDefaultLatt(); | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|  | ||||
|   const int Ls = 8; | ||||
|  | ||||
|   GridCartesian         *UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian *UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian         *FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian *FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Want a different conf at every run | ||||
|   // First create an instance of an engine. | ||||
|   std::random_device rnd_device; | ||||
|   // Specify the engine and distribution. | ||||
|   std::mt19937 mersenne_engine(rnd_device()); | ||||
|   std::uniform_int_distribution<int> dist(1, 100); | ||||
|  | ||||
|   auto gen = std::bind(dist, mersenne_engine); | ||||
|   std::vector<int> seeds4(4); | ||||
|   generate(begin(seeds4), end(seeds4), gen); | ||||
|  | ||||
|   //std::vector<int> seeds4({1,2,3,5}); | ||||
|   std::vector<int> seeds5({5,6,7,8}); | ||||
|   GridParallelRNG RNG5(FGrid);  RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid);  RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|   LatticeFermion phi        (FGrid);  gaussian(RNG5, phi); | ||||
|   LatticeFermion Mphi       (FGrid); | ||||
|   LatticeFermion MphiPrime  (FGrid); | ||||
|  | ||||
|   LatticeGaugeField U(UGrid); | ||||
|   SU3::HotConfiguration(RNG4,U); | ||||
|  | ||||
|   //////////////////////////////////// | ||||
|   // Unmodified matrix element | ||||
|   //////////////////////////////////// | ||||
|   RealD mf = 0.01; | ||||
|   RealD mb = 1.0; | ||||
|   RealD M5 = 1.8; | ||||
|   DomainWallEOFAFermionR Lop(U, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, 0.0, -1, M5); | ||||
|   DomainWallEOFAFermionR Rop(U, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, -1.0, 1, M5); | ||||
|   OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, 12); | ||||
|   ConjugateGradient<LatticeFermion> CG(1.0e-12, 5000); | ||||
|   ExactOneFlavourRatioPseudoFermionAction<WilsonImplR> Meofa(Lop, Rop, CG, Params, true); | ||||
|  | ||||
|   Meofa.refresh(U, RNG5); | ||||
|   RealD S = Meofa.S(U); // pdag M p | ||||
|  | ||||
|   // get the deriv of phidag M phi with respect to "U" | ||||
|   LatticeGaugeField UdSdU(UGrid); | ||||
|   Meofa.deriv(U, UdSdU); | ||||
|  | ||||
|   //////////////////////////////////// | ||||
|   // Modify the gauge field a little | ||||
|   //////////////////////////////////// | ||||
|   RealD dt = 0.0001; | ||||
|  | ||||
|   LatticeColourMatrix mommu(UGrid); | ||||
|   LatticeColourMatrix forcemu(UGrid); | ||||
|   LatticeGaugeField mom(UGrid); | ||||
|   LatticeGaugeField Uprime(UGrid); | ||||
|  | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|  | ||||
|     SU3::GaussianFundamentalLieAlgebraMatrix(RNG4, mommu); // Traceless antihermitian momentum; gaussian in lie alg | ||||
|  | ||||
|     PokeIndex<LorentzIndex>(mom, mommu, mu); | ||||
|  | ||||
|     // fourth order exponential approx | ||||
|     parallel_for(auto i=mom.begin(); i<mom.end(); i++){ | ||||
|       Uprime[i](mu) = U[i](mu) + mom[i](mu)*U[i](mu)*dt + mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt/2.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt/6.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt/24.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt*dt/120.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt*dt*dt/720.0); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /*Ddwf.ImportGauge(Uprime); | ||||
|   Ddwf.M          (phi,MphiPrime); | ||||
|  | ||||
|   ComplexD Sprime    = innerProduct(MphiPrime   ,MphiPrime);*/ | ||||
|   RealD Sprime = Meofa.S(Uprime); | ||||
|  | ||||
|   ////////////////////////////////////////////// | ||||
|   // Use derivative to estimate dS | ||||
|   ////////////////////////////////////////////// | ||||
|  | ||||
|   LatticeComplex dS(UGrid); | ||||
|   dS = zero; | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|     mommu = PeekIndex<LorentzIndex>(UdSdU, mu); | ||||
|     mommu = Ta(mommu)*2.0; | ||||
|     PokeIndex<LorentzIndex>(UdSdU, mommu, mu); | ||||
|   } | ||||
|  | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|     forcemu = PeekIndex<LorentzIndex>(UdSdU, mu); | ||||
|     mommu   = PeekIndex<LorentzIndex>(mom, mu); | ||||
|  | ||||
|     // Update PF action density | ||||
|     dS = dS + trace(mommu*forcemu)*dt; | ||||
|   } | ||||
|  | ||||
|   ComplexD dSpred = sum(dS); | ||||
|  | ||||
|   /*std::cout << GridLogMessage << " S      " << S << std::endl; | ||||
|   std::cout << GridLogMessage << " Sprime " << Sprime << std::endl; | ||||
|   std::cout << GridLogMessage << "dS      " << Sprime-S << std::endl; | ||||
|   std::cout << GridLogMessage << "predict dS    " << dSpred << std::endl;*/ | ||||
|   printf("\nS = %1.15e\n", S); | ||||
|   printf("Sprime = %1.15e\n", Sprime); | ||||
|   printf("dS = %1.15e\n", Sprime - S); | ||||
|   printf("real(dS_predict) = %1.15e\n", dSpred.real()); | ||||
|   printf("imag(dS_predict) = %1.15e\n\n", dSpred.imag()); | ||||
|  | ||||
|   assert( fabs(real(Sprime-S-dSpred)) < 1.0 ) ; | ||||
|  | ||||
|   std::cout << GridLogMessage << "Done" << std::endl; | ||||
|   Grid_finalize(); | ||||
| } | ||||
							
								
								
									
										169
									
								
								tests/forces/Test_dwf_gpforce_eofa.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								tests/forces/Test_dwf_gpforce_eofa.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/forces/Test_dwf_force_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| typedef GparityWilsonImplR FermionImplPolicy; | ||||
| typedef GparityDomainWallEOFAFermionR FermionAction; | ||||
| typedef typename FermionAction::FermionField FermionField; | ||||
|  | ||||
| int main (int argc, char** argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   std::vector<int> latt_size   = GridDefaultLatt(); | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|  | ||||
|   const int Ls = 8; | ||||
|  | ||||
|   GridCartesian         *UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian *UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian         *FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian *FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Want a different conf at every run | ||||
|   // First create an instance of an engine. | ||||
|   std::random_device rnd_device; | ||||
|   // Specify the engine and distribution. | ||||
|   std::mt19937 mersenne_engine(rnd_device()); | ||||
|   std::uniform_int_distribution<int> dist(1, 100); | ||||
|  | ||||
|   auto gen = std::bind(dist, mersenne_engine); | ||||
|   std::vector<int> seeds4(4); | ||||
|   generate(begin(seeds4), end(seeds4), gen); | ||||
|  | ||||
|   //std::vector<int> seeds4({1,2,3,5}); | ||||
|   std::vector<int> seeds5({5,6,7,8}); | ||||
|   GridParallelRNG RNG5(FGrid);  RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid);  RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|   FermionField phi        (FGrid);  gaussian(RNG5, phi); | ||||
|   FermionField Mphi       (FGrid); | ||||
|   FermionField MphiPrime  (FGrid); | ||||
|  | ||||
|   LatticeGaugeField U(UGrid); | ||||
|   SU3::HotConfiguration(RNG4,U); | ||||
|  | ||||
|   //////////////////////////////////// | ||||
|   // Unmodified matrix element | ||||
|   //////////////////////////////////// | ||||
|   RealD mf = 0.01; | ||||
|   RealD mb = 1.0; | ||||
|   RealD M5 = 1.8; | ||||
|   FermionAction::ImplParams params; | ||||
|   FermionAction Lop(U, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, 0.0, -1, M5, params); | ||||
|   FermionAction Rop(U, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, -1.0, 1, M5, params); | ||||
|   OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, 12); | ||||
|   ConjugateGradient<FermionField> CG(1.0e-12, 5000); | ||||
|   ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> Meofa(Lop, Rop, CG, Params, true); | ||||
|  | ||||
|   Meofa.refresh(U, RNG5); | ||||
|   RealD S = Meofa.S(U); // pdag M p | ||||
|  | ||||
|   // get the deriv of phidag M phi with respect to "U" | ||||
|   LatticeGaugeField UdSdU(UGrid); | ||||
|   Meofa.deriv(U, UdSdU); | ||||
|  | ||||
|   //////////////////////////////////// | ||||
|   // Modify the gauge field a little | ||||
|   //////////////////////////////////// | ||||
|   RealD dt = 0.0001; | ||||
|  | ||||
|   LatticeColourMatrix mommu(UGrid); | ||||
|   LatticeColourMatrix forcemu(UGrid); | ||||
|   LatticeGaugeField mom(UGrid); | ||||
|   LatticeGaugeField Uprime(UGrid); | ||||
|  | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|  | ||||
|     SU3::GaussianFundamentalLieAlgebraMatrix(RNG4, mommu); // Traceless antihermitian momentum; gaussian in lie alg | ||||
|  | ||||
|     PokeIndex<LorentzIndex>(mom, mommu, mu); | ||||
|  | ||||
|     // fourth order exponential approx | ||||
|     parallel_for(auto i=mom.begin(); i<mom.end(); i++){ | ||||
|       Uprime[i](mu) = U[i](mu) + mom[i](mu)*U[i](mu)*dt + mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt/2.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt/6.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt/24.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt*dt/120.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt*dt*dt/720.0); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /*Ddwf.ImportGauge(Uprime); | ||||
|   Ddwf.M          (phi,MphiPrime); | ||||
|  | ||||
|   ComplexD Sprime    = innerProduct(MphiPrime   ,MphiPrime);*/ | ||||
|   RealD Sprime = Meofa.S(Uprime); | ||||
|  | ||||
|   ////////////////////////////////////////////// | ||||
|   // Use derivative to estimate dS | ||||
|   ////////////////////////////////////////////// | ||||
|  | ||||
|   LatticeComplex dS(UGrid); | ||||
|   dS = zero; | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|     mommu = PeekIndex<LorentzIndex>(UdSdU, mu); | ||||
|     mommu = Ta(mommu)*2.0; | ||||
|     PokeIndex<LorentzIndex>(UdSdU, mommu, mu); | ||||
|   } | ||||
|  | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|     forcemu = PeekIndex<LorentzIndex>(UdSdU, mu); | ||||
|     mommu   = PeekIndex<LorentzIndex>(mom, mu); | ||||
|  | ||||
|     // Update PF action density | ||||
|     dS = dS + trace(mommu*forcemu)*dt; | ||||
|   } | ||||
|  | ||||
|   ComplexD dSpred = sum(dS); | ||||
|  | ||||
|   /*std::cout << GridLogMessage << " S      " << S << std::endl; | ||||
|   std::cout << GridLogMessage << " Sprime " << Sprime << std::endl; | ||||
|   std::cout << GridLogMessage << "dS      " << Sprime-S << std::endl; | ||||
|   std::cout << GridLogMessage << "predict dS    " << dSpred << std::endl;*/ | ||||
|   printf("\nS = %1.15e\n", S); | ||||
|   printf("Sprime = %1.15e\n", Sprime); | ||||
|   printf("dS = %1.15e\n", Sprime - S); | ||||
|   printf("real(dS_predict) = %1.15e\n", dSpred.real()); | ||||
|   printf("imag(dS_predict) = %1.15e\n\n", dSpred.imag()); | ||||
|  | ||||
|   assert( fabs(real(Sprime-S-dSpred)) < 1.0 ) ; | ||||
|  | ||||
|   std::cout << GridLogMessage << "Done" << std::endl; | ||||
|   Grid_finalize(); | ||||
| } | ||||
| @@ -42,7 +42,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|  | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
| @@ -42,7 +42,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|  | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
							
								
								
									
										166
									
								
								tests/forces/Test_mobius_force_eofa.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								tests/forces/Test_mobius_force_eofa.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/forces/Test_dwf_force_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| int main (int argc, char** argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   std::vector<int> latt_size   = GridDefaultLatt(); | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|  | ||||
|   const int Ls = 8; | ||||
|  | ||||
|   GridCartesian         *UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian *UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian         *FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian *FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Want a different conf at every run | ||||
|   // First create an instance of an engine. | ||||
|   std::random_device rnd_device; | ||||
|   // Specify the engine and distribution. | ||||
|   std::mt19937 mersenne_engine(rnd_device()); | ||||
|   std::uniform_int_distribution<int> dist(1, 100); | ||||
|  | ||||
|   auto gen = std::bind(dist, mersenne_engine); | ||||
|   std::vector<int> seeds4(4); | ||||
|   generate(begin(seeds4), end(seeds4), gen); | ||||
|  | ||||
|   //std::vector<int> seeds4({1,2,3,5}); | ||||
|   std::vector<int> seeds5({5,6,7,8}); | ||||
|   GridParallelRNG RNG5(FGrid);  RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid);  RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|   LatticeFermion phi        (FGrid);  gaussian(RNG5, phi); | ||||
|   LatticeFermion Mphi       (FGrid); | ||||
|   LatticeFermion MphiPrime  (FGrid); | ||||
|  | ||||
|   LatticeGaugeField U(UGrid); | ||||
|   SU3::HotConfiguration(RNG4,U); | ||||
|  | ||||
|   //////////////////////////////////// | ||||
|   // Unmodified matrix element | ||||
|   //////////////////////////////////// | ||||
|   RealD b  = 2.5; | ||||
|   RealD c  = 1.5; | ||||
|   RealD mf = 0.01; | ||||
|   RealD mb = 1.0; | ||||
|   RealD M5 = 1.8; | ||||
|   MobiusEOFAFermionR Lop(U, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, 0.0, -1, M5, b, c); | ||||
|   MobiusEOFAFermionR Rop(U, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, -1.0, 1, M5, b, c); | ||||
|   OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, 12); | ||||
|   ConjugateGradient<LatticeFermion> CG(1.0e-12, 5000); | ||||
|   ExactOneFlavourRatioPseudoFermionAction<WilsonImplR> Meofa(Lop, Rop, CG, Params, false); | ||||
|  | ||||
|   Meofa.refresh(U, RNG5); | ||||
|   RealD S = Meofa.S(U); // pdag M p | ||||
|  | ||||
|   // get the deriv of phidag M phi with respect to "U" | ||||
|   LatticeGaugeField UdSdU(UGrid); | ||||
|   Meofa.deriv(U, UdSdU); | ||||
|  | ||||
|   //////////////////////////////////// | ||||
|   // Modify the gauge field a little | ||||
|   //////////////////////////////////// | ||||
|   RealD dt = 0.0001; | ||||
|  | ||||
|   LatticeColourMatrix mommu(UGrid); | ||||
|   LatticeColourMatrix forcemu(UGrid); | ||||
|   LatticeGaugeField mom(UGrid); | ||||
|   LatticeGaugeField Uprime(UGrid); | ||||
|  | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|  | ||||
|     SU3::GaussianFundamentalLieAlgebraMatrix(RNG4, mommu); // Traceless antihermitian momentum; gaussian in lie alg | ||||
|  | ||||
|     PokeIndex<LorentzIndex>(mom, mommu, mu); | ||||
|  | ||||
|     // fourth order exponential approx | ||||
|     parallel_for(auto i=mom.begin(); i<mom.end(); i++){ | ||||
|       Uprime[i](mu) = U[i](mu) + mom[i](mu)*U[i](mu)*dt + mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt/2.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt/6.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt/24.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt*dt/120.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt*dt*dt/720.0); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /*Ddwf.ImportGauge(Uprime); | ||||
|   Ddwf.M          (phi,MphiPrime); | ||||
|  | ||||
|   ComplexD Sprime    = innerProduct(MphiPrime   ,MphiPrime);*/ | ||||
|   RealD Sprime = Meofa.S(Uprime); | ||||
|  | ||||
|   ////////////////////////////////////////////// | ||||
|   // Use derivative to estimate dS | ||||
|   ////////////////////////////////////////////// | ||||
|  | ||||
|   LatticeComplex dS(UGrid); | ||||
|   dS = zero; | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|     mommu = PeekIndex<LorentzIndex>(UdSdU, mu); | ||||
|     mommu = Ta(mommu)*2.0; | ||||
|     PokeIndex<LorentzIndex>(UdSdU, mommu, mu); | ||||
|   } | ||||
|  | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|     forcemu = PeekIndex<LorentzIndex>(UdSdU, mu); | ||||
|     mommu   = PeekIndex<LorentzIndex>(mom, mu); | ||||
|  | ||||
|     // Update PF action density | ||||
|     dS = dS + trace(mommu*forcemu)*dt; | ||||
|   } | ||||
|  | ||||
|   ComplexD dSpred = sum(dS); | ||||
|  | ||||
|   /*std::cout << GridLogMessage << " S      " << S << std::endl; | ||||
|   std::cout << GridLogMessage << " Sprime " << Sprime << std::endl; | ||||
|   std::cout << GridLogMessage << "dS      " << Sprime-S << std::endl; | ||||
|   std::cout << GridLogMessage << "predict dS    " << dSpred << std::endl;*/ | ||||
|   printf("\nS = %1.15e\n", S); | ||||
|   printf("Sprime = %1.15e\n", Sprime); | ||||
|   printf("dS = %1.15e\n", Sprime - S); | ||||
|   printf("real(dS_predict) = %1.15e\n", dSpred.real()); | ||||
|   printf("imag(dS_predict) = %1.15e\n\n", dSpred.imag()); | ||||
|  | ||||
|   assert( fabs(real(Sprime-S-dSpred)) < 1.0 ) ; | ||||
|  | ||||
|   std::cout << GridLogMessage << "Done" << std::endl; | ||||
|   Grid_finalize(); | ||||
| } | ||||
							
								
								
									
										171
									
								
								tests/forces/Test_mobius_gpforce_eofa.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								tests/forces/Test_mobius_gpforce_eofa.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./tests/forces/Test_dwf_force_eofa.cc | ||||
|  | ||||
| Copyright (C) 2017 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: David Murphy <dmurphy@phys.columbia.edu> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| typedef GparityWilsonImplR FermionImplPolicy; | ||||
| typedef GparityMobiusEOFAFermionR FermionAction; | ||||
| typedef typename FermionAction::FermionField FermionField; | ||||
|  | ||||
| int main (int argc, char** argv) | ||||
| { | ||||
|   Grid_init(&argc, &argv); | ||||
|  | ||||
|   std::vector<int> latt_size   = GridDefaultLatt(); | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|  | ||||
|   const int Ls = 8; | ||||
|  | ||||
|   GridCartesian         *UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()), GridDefaultMpi()); | ||||
|   GridRedBlackCartesian *UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||
|   GridCartesian         *FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls, UGrid); | ||||
|   GridRedBlackCartesian *FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, UGrid); | ||||
|  | ||||
|   // Want a different conf at every run | ||||
|   // First create an instance of an engine. | ||||
|   std::random_device rnd_device; | ||||
|   // Specify the engine and distribution. | ||||
|   std::mt19937 mersenne_engine(rnd_device()); | ||||
|   std::uniform_int_distribution<int> dist(1, 100); | ||||
|  | ||||
|   auto gen = std::bind(dist, mersenne_engine); | ||||
|   std::vector<int> seeds4(4); | ||||
|   generate(begin(seeds4), end(seeds4), gen); | ||||
|  | ||||
|   //std::vector<int> seeds4({1,2,3,5}); | ||||
|   std::vector<int> seeds5({5,6,7,8}); | ||||
|   GridParallelRNG RNG5(FGrid);  RNG5.SeedFixedIntegers(seeds5); | ||||
|   GridParallelRNG RNG4(UGrid);  RNG4.SeedFixedIntegers(seeds4); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl; | ||||
|  | ||||
|   FermionField phi        (FGrid);  gaussian(RNG5, phi); | ||||
|   FermionField Mphi       (FGrid); | ||||
|   FermionField MphiPrime  (FGrid); | ||||
|  | ||||
|   LatticeGaugeField U(UGrid); | ||||
|   SU3::HotConfiguration(RNG4,U); | ||||
|  | ||||
|   //////////////////////////////////// | ||||
|   // Unmodified matrix element | ||||
|   //////////////////////////////////// | ||||
|   RealD b  = 2.5; | ||||
|   RealD c  = 1.5; | ||||
|   RealD mf = 0.01; | ||||
|   RealD mb = 1.0; | ||||
|   RealD M5 = 1.8; | ||||
|   FermionAction::ImplParams params; | ||||
|   FermionAction Lop(U, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mf, mf, mb, 0.0, -1, M5, b, c, params); | ||||
|   FermionAction Rop(U, *FGrid, *FrbGrid, *UGrid, *UrbGrid, mb, mf, mb, -1.0, 1, M5, b, c, params); | ||||
|   OneFlavourRationalParams Params(0.95, 100.0, 5000, 1.0e-12, 12); | ||||
|   ConjugateGradient<FermionField> CG(1.0e-12, 5000); | ||||
|   ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> Meofa(Lop, Rop, CG, Params, false); | ||||
|  | ||||
|   Meofa.refresh(U, RNG5); | ||||
|   RealD S = Meofa.S(U); // pdag M p | ||||
|  | ||||
|   // get the deriv of phidag M phi with respect to "U" | ||||
|   LatticeGaugeField UdSdU(UGrid); | ||||
|   Meofa.deriv(U, UdSdU); | ||||
|  | ||||
|   //////////////////////////////////// | ||||
|   // Modify the gauge field a little | ||||
|   //////////////////////////////////// | ||||
|   RealD dt = 0.0001; | ||||
|  | ||||
|   LatticeColourMatrix mommu(UGrid); | ||||
|   LatticeColourMatrix forcemu(UGrid); | ||||
|   LatticeGaugeField mom(UGrid); | ||||
|   LatticeGaugeField Uprime(UGrid); | ||||
|  | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|  | ||||
|     SU3::GaussianFundamentalLieAlgebraMatrix(RNG4, mommu); // Traceless antihermitian momentum; gaussian in lie alg | ||||
|  | ||||
|     PokeIndex<LorentzIndex>(mom, mommu, mu); | ||||
|  | ||||
|     // fourth order exponential approx | ||||
|     parallel_for(auto i=mom.begin(); i<mom.end(); i++){ | ||||
|       Uprime[i](mu) = U[i](mu) + mom[i](mu)*U[i](mu)*dt + mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt/2.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt/6.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt/24.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt*dt/120.0) | ||||
|                         + mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *mom[i](mu) *U[i](mu)*(dt*dt*dt*dt*dt*dt/720.0); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /*Ddwf.ImportGauge(Uprime); | ||||
|   Ddwf.M          (phi,MphiPrime); | ||||
|  | ||||
|   ComplexD Sprime    = innerProduct(MphiPrime   ,MphiPrime);*/ | ||||
|   RealD Sprime = Meofa.S(Uprime); | ||||
|  | ||||
|   ////////////////////////////////////////////// | ||||
|   // Use derivative to estimate dS | ||||
|   ////////////////////////////////////////////// | ||||
|  | ||||
|   LatticeComplex dS(UGrid); | ||||
|   dS = zero; | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|     mommu = PeekIndex<LorentzIndex>(UdSdU, mu); | ||||
|     mommu = Ta(mommu)*2.0; | ||||
|     PokeIndex<LorentzIndex>(UdSdU, mommu, mu); | ||||
|   } | ||||
|  | ||||
|   for(int mu=0; mu<Nd; mu++){ | ||||
|     forcemu = PeekIndex<LorentzIndex>(UdSdU, mu); | ||||
|     mommu   = PeekIndex<LorentzIndex>(mom, mu); | ||||
|  | ||||
|     // Update PF action density | ||||
|     dS = dS + trace(mommu*forcemu)*dt; | ||||
|   } | ||||
|  | ||||
|   ComplexD dSpred = sum(dS); | ||||
|  | ||||
|   /*std::cout << GridLogMessage << " S      " << S << std::endl; | ||||
|   std::cout << GridLogMessage << " Sprime " << Sprime << std::endl; | ||||
|   std::cout << GridLogMessage << "dS      " << Sprime-S << std::endl; | ||||
|   std::cout << GridLogMessage << "predict dS    " << dSpred << std::endl;*/ | ||||
|   printf("\nS = %1.15e\n", S); | ||||
|   printf("Sprime = %1.15e\n", Sprime); | ||||
|   printf("dS = %1.15e\n", Sprime - S); | ||||
|   printf("real(dS_predict) = %1.15e\n", dSpred.real()); | ||||
|   printf("imag(dS_predict) = %1.15e\n\n", dSpred.imag()); | ||||
|  | ||||
|   assert( fabs(real(Sprime-S-dSpred)) < 1.0 ) ; | ||||
|  | ||||
|   std::cout << GridLogMessage << "Done" << std::endl; | ||||
|   Grid_finalize(); | ||||
| } | ||||
| @@ -42,7 +42,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|  | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
| @@ -42,7 +42,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|  | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   int threads = GridThread::GetThreads(); | ||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||
|   | ||||
| @@ -71,7 +71,7 @@ int main(int argc, char **argv) { | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd, vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size, simd_layout, mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size, simd_layout, mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   std::vector<int> seeds({1, 2, 3, 4, 5}); | ||||
|   GridSerialRNG sRNG; | ||||
| @@ -149,4 +149,4 @@ JSON | ||||
| } | ||||
|  | ||||
|  | ||||
| */ | ||||
| */ | ||||
|   | ||||
							
								
								
									
										195
									
								
								tests/solver/Test_dwf_mrhs_cg.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								tests/solver/Test_dwf_mrhs_cg.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|  | ||||
|     Source file: ./tests/Test_dwf_mrhs_cg.cc | ||||
|  | ||||
|     Copyright (C) 2015 | ||||
|  | ||||
| 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 */ | ||||
| #include <Grid/Grid.h> | ||||
| #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| int main (int argc, char ** argv) | ||||
| { | ||||
|   typedef typename DomainWallFermionR::FermionField FermionField;  | ||||
|   typedef typename DomainWallFermionR::ComplexField ComplexField;  | ||||
|   typename DomainWallFermionR::ImplParams params;  | ||||
|  | ||||
|   const int Ls=8; | ||||
|  | ||||
|   Grid_init(&argc,&argv); | ||||
|  | ||||
|   std::vector<int> latt_size   = GridDefaultLatt(); | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   std::vector<int> mpi_split (mpi_layout.size(),1); | ||||
|  | ||||
|   std::cout << "UGrid (world root)"<<std::endl; | ||||
|   GridCartesian         * UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()),GridDefaultMpi()); | ||||
|  | ||||
|   std::cout << "FGrid (child of UGrid)"<<std::endl; | ||||
|   GridCartesian         * FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid); | ||||
|  | ||||
|   int nrhs = UGrid->RankCount() ; | ||||
|  | ||||
|   ///////////////////////////////////////////// | ||||
|   // Split into 1^4 mpi communicators | ||||
|   ///////////////////////////////////////////// | ||||
|   std::cout << "SGrid (world root)"<<std::endl; | ||||
|   GridCartesian         * SGrid = new GridCartesian(GridDefaultLatt(), | ||||
| 						    GridDefaultSimd(Nd,vComplex::Nsimd()), | ||||
| 						    mpi_split, | ||||
| 						    *UGrid);  | ||||
|  | ||||
|   GridCartesian         * SFGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls,SGrid); | ||||
|   std::cout << "SFGrid"<<std::endl; | ||||
|   GridRedBlackCartesian * SrbGrid  = SpaceTimeGrid::makeFourDimRedBlackGrid(SGrid); | ||||
|   std::cout << "SrbGrid"<<std::endl; | ||||
|   GridRedBlackCartesian * SFrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,SGrid); | ||||
|   std::cout << "SFrbGrid"<<std::endl; | ||||
|  | ||||
|   /////////////////////////////////////////////// | ||||
|   // Set up the problem as a 4d spreadout job | ||||
|   /////////////////////////////////////////////// | ||||
|   std::vector<int> seeds({1,2,3,4}); | ||||
|  | ||||
|   GridParallelRNG pRNG(UGrid );  pRNG.SeedFixedIntegers(seeds); | ||||
|   GridParallelRNG pRNG5(FGrid);  pRNG5.SeedFixedIntegers(seeds); | ||||
|   std::vector<FermionField>    src(nrhs,FGrid); | ||||
|   std::vector<FermionField> result(nrhs,FGrid); | ||||
|  | ||||
|   for(int s=0;s<nrhs;s++) random(pRNG5,src[s]); | ||||
|   for(int s=0;s<nrhs;s++) result[s] = zero; | ||||
|  | ||||
|   LatticeGaugeField Umu(UGrid); SU3::HotConfiguration(pRNG,Umu); | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Bounce these fields to disk | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|  | ||||
|   std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|   std::cout << GridLogMessage << " Writing out in parallel view "<<std::endl; | ||||
|   std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|   emptyUserRecord record; | ||||
|   std::string file("./scratch.scidac"); | ||||
|   std::string filef("./scratch.scidac.ferm"); | ||||
|   int me = UGrid->ThisRank(); | ||||
|   LatticeGaugeField s_Umu(SGrid); | ||||
|   FermionField s_src(SFGrid); | ||||
|   FermionField s_res(SFGrid); | ||||
|  | ||||
|   { | ||||
|     FGrid->Barrier(); | ||||
|     ScidacWriter _ScidacWriter; | ||||
|     _ScidacWriter.open(file); | ||||
|     std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|     std::cout << GridLogMessage << " Writing out gauge field "<<std::endl; | ||||
|     std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|     _ScidacWriter.writeScidacFieldRecord(Umu,record); | ||||
|     _ScidacWriter.close(); | ||||
|     FGrid->Barrier(); | ||||
|     std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|     std::cout << GridLogMessage << " Reading in gauge field "<<std::endl; | ||||
|     std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|     ScidacReader  _ScidacReader; | ||||
|     _ScidacReader.open(file); | ||||
|     _ScidacReader.readScidacFieldRecord(s_Umu,record); | ||||
|     _ScidacReader.close(); | ||||
|     FGrid->Barrier(); | ||||
|     std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|     std::cout << GridLogMessage << " Read in gauge field "<<std::endl; | ||||
|     std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   { | ||||
|     for(int n=0;n<nrhs;n++){ | ||||
|  | ||||
|       std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|       std::cout << GridLogMessage << " Writing out record "<<n<<std::endl; | ||||
|       std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|  | ||||
|       std::stringstream filefn;      filefn << filef << "."<< n; | ||||
|       ScidacWriter _ScidacWriter; | ||||
|       _ScidacWriter.open(filefn.str()); | ||||
|       _ScidacWriter.writeScidacFieldRecord(src[n],record); | ||||
|       _ScidacWriter.close(); | ||||
|     } | ||||
|        | ||||
|     FGrid->Barrier(); | ||||
|  | ||||
|     std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|     std::cout << GridLogMessage << " Reading back in the single process view "<<std::endl; | ||||
|     std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|        | ||||
|     for(int n=0;n<nrhs;n++){ | ||||
|       if ( n==me ) {  | ||||
| 	std::stringstream filefn;	filefn << filef << "."<< n; | ||||
| 	ScidacReader  _ScidacReader; | ||||
| 	_ScidacReader.open(filefn.str()); | ||||
| 	_ScidacReader.readScidacFieldRecord(s_src,record); | ||||
| 	_ScidacReader.close(); | ||||
|       } | ||||
|     } | ||||
|     FGrid->Barrier(); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Set up N-solvers as trivially parallel | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|  | ||||
|   RealD mass=0.01; | ||||
|   RealD M5=1.8; | ||||
|   DomainWallFermionR Ddwf(s_Umu,*SFGrid,*SFrbGrid,*SGrid,*SrbGrid,mass,M5); | ||||
|  | ||||
|   std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|   std::cout << GridLogMessage << " Calling DWF CG "<<std::endl; | ||||
|   std::cout << GridLogMessage << "****************************************************************** "<<std::endl; | ||||
|  | ||||
|   MdagMLinearOperator<DomainWallFermionR,FermionField> HermOp(Ddwf); | ||||
|   ConjugateGradient<FermionField> CG((1.0e-8/(me+1)),10000); | ||||
|   s_res = zero; | ||||
|   CG(HermOp,s_src,s_res); | ||||
|  | ||||
|   /////////////////////////////////////// | ||||
|   // Share the information | ||||
|   /////////////////////////////////////// | ||||
|   std::vector<uint32_t> iterations(nrhs,0); | ||||
|   iterations[me] = CG.IterationsToComplete; | ||||
|  | ||||
|   for(int n=0;n<nrhs;n++){ | ||||
|     UGrid->GlobalSum(iterations[n]); | ||||
|   } | ||||
|  | ||||
|   ///////////////////////////////////////////////////////////// | ||||
|   // Report how long they all took | ||||
|   ///////////////////////////////////////////////////////////// | ||||
|   for(int r=0;r<nrhs;r++){ | ||||
|     std::cout << GridLogMessage<<" Rank "<<r<<" "<< iterations[r]<<" CG iterations"<<std::endl; | ||||
|   } | ||||
|   Grid_finalize(); | ||||
| } | ||||
| @@ -40,7 +40,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   std::vector<int> seeds({1,2,3,4,5}); | ||||
|   GridParallelRNG          pRNG(&Grid);  pRNG.SeedFixedIntegers(seeds); | ||||
|   | ||||
| @@ -27,7 +27,6 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
|     *************************************************************************************/ | ||||
|     /*  END LEGAL */ | ||||
| #include <Grid/Grid.h> | ||||
| #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
|   | ||||
							
								
								
									
										87
									
								
								tests/solver/Test_staggered_cg_prec.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								tests/solver/Test_staggered_cg_prec.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
|     /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|  | ||||
|     Source file: ./tests/Test_wilson_cg_unprec.cc | ||||
|  | ||||
|     Copyright (C) 2015 | ||||
|  | ||||
| Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk> | ||||
| 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 */ | ||||
| #include <Grid/Grid.h> | ||||
| #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace Grid; | ||||
| using namespace Grid::QCD; | ||||
|  | ||||
| template<class d> | ||||
| struct scal { | ||||
|   d internal; | ||||
| }; | ||||
|  | ||||
|   Gamma::Algebra Gmu [] = { | ||||
|     Gamma::Algebra::GammaX, | ||||
|     Gamma::Algebra::GammaY, | ||||
|     Gamma::Algebra::GammaZ, | ||||
|     Gamma::Algebra::GammaT | ||||
|   }; | ||||
|  | ||||
| int main (int argc, char ** argv) | ||||
| { | ||||
|   typedef typename ImprovedStaggeredFermionR::FermionField FermionField;  | ||||
|   typedef typename ImprovedStaggeredFermionR::ComplexField ComplexField;  | ||||
|   typename ImprovedStaggeredFermionR::ImplParams params;  | ||||
|  | ||||
|   Grid_init(&argc,&argv); | ||||
|  | ||||
|   std::vector<int> latt_size   = GridDefaultLatt(); | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   std::vector<int> seeds({1,2,3,4}); | ||||
|   GridParallelRNG          pRNG(&Grid);  pRNG.SeedFixedIntegers(seeds); | ||||
|  | ||||
|   FermionField src(&Grid); random(pRNG,src); | ||||
|   RealD nrm = norm2(src); | ||||
|   LatticeGaugeField Umu(&Grid); SU3::HotConfiguration(pRNG,Umu); | ||||
|  | ||||
|   double volume=1; | ||||
|   for(int mu=0;mu<Nd;mu++){ | ||||
|     volume=volume*latt_size[mu]; | ||||
|   }   | ||||
|    | ||||
|   RealD mass=0.1; | ||||
|   ImprovedStaggeredFermionR Ds(Umu,Umu,Grid,RBGrid,mass); | ||||
|  | ||||
|   FermionField res_o(&RBGrid);  | ||||
|   FermionField src_o(&RBGrid);  | ||||
|   pickCheckerboard(Odd,src_o,src); | ||||
|   res_o=zero; | ||||
|  | ||||
|   SchurDiagMooeeOperator<ImprovedStaggeredFermionR,FermionField> HermOpEO(Ds); | ||||
|   ConjugateGradient<FermionField> CG(1.0e-8,10000); | ||||
|   CG(HermOpEO,src_o,res_o); | ||||
|  | ||||
|   Grid_finalize(); | ||||
| } | ||||
| @@ -57,7 +57,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   std::vector<int> seeds({1,2,3,4}); | ||||
|   GridParallelRNG          pRNG(&Grid);  pRNG.SeedFixedIntegers(seeds); | ||||
|   | ||||
| @@ -52,7 +52,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   std::vector<int> seeds({1,2,3,4}); | ||||
|   GridParallelRNG          pRNG(&Grid);  pRNG.SeedFixedIntegers(seeds); | ||||
|   | ||||
| @@ -52,7 +52,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   std::vector<int> seeds({1,2,3,4}); | ||||
|   GridParallelRNG          pRNG(&Grid);  pRNG.SeedFixedIntegers(seeds); | ||||
|   | ||||
| @@ -52,7 +52,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   std::vector<int> seeds({1,2,3,4}); | ||||
|   GridParallelRNG          pRNG(&Grid);  pRNG.SeedFixedIntegers(seeds); | ||||
|   | ||||
| @@ -52,7 +52,7 @@ int main (int argc, char ** argv) | ||||
|   std::vector<int> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); | ||||
|   GridRedBlackCartesian     RBGrid(&Grid); | ||||
|  | ||||
|   std::vector<int> seeds({1,2,3,4}); | ||||
|   GridParallelRNG          pRNG(&Grid);  pRNG.SeedFixedIntegers(seeds); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user