mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-10-31 03:54:33 +00:00 
			
		
		
		
	Compare commits
	
		
			91 Commits
		
	
	
		
			release/di
			...
			feature/fe
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f4e6824f22 | ||
|  | ac5cfd33a6 | ||
|  | f605230bbb | ||
|  | d54807b8c0 | ||
|  | 5625b47c7d | ||
|  | 1edcf902b7 | ||
|  | e5c19e1fd7 | ||
|  | a11d0a33d1 | ||
|  | 4f8b6f26b4 | ||
|  | 073525c5b3 | ||
|  | f7072d1ac2 | ||
|  | fddeb29d6b | ||
|  | a9ec5cf564 | ||
|  | 946a8671b9 | ||
|  | 771a1b8e79 | ||
|  | bfb68e6f02 | ||
|  | 18c335198a | ||
|  | 17c5b0f152 | ||
|  | 5918769f97 | ||
|  | bbaf1ada91 | ||
|  | 1950ac9294 | ||
|  | 13fa70ac1a | ||
|  | 7cb2b11f26 | ||
|  | 1184ed29ae | ||
|  | 203c7bf6fa | ||
|  | c709883f3f | ||
|  | aed5de4d50 | ||
|  | ba27cc6571 | ||
|  | d856327250 | ||
|  | d75369cb56 | ||
|  | 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: | 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 | 2)- Christoph's local basis expansion Lanczos | ||||||
| 3)- Precision conversion and sort out localConvert      <-- partial | -- | ||||||
|  | 3a)- RNG I/O in ILDG/SciDAC (minor) | ||||||
|   - Consistent linear solver flop count/rate -- PARTIAL, time but no flop/s yet | 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 | 4)- Physical propagator interface | ||||||
| 5)- Conserved currents | 5)- Conserved currents | ||||||
| 6)- Multigrid Wilson and DWF, compare to other Multigrid implementations | 6)- Multigrid Wilson and DWF, compare to other Multigrid implementations | ||||||
| 7)- HDCR resume | 7)- HDCR resume | ||||||
|  |  | ||||||
| Recent DONE  | Recent DONE  | ||||||
|  | -- MultiRHS with spread out extra dim -- Go through filesystem with SciDAC I/O ; <-- DONE ; bmark cori | ||||||
| -- MultiRHS with spread out extra dim -- Go through filesystem with SciDAC I/O.  <--- DONE |  | ||||||
| -- Lanczos Remove DenseVector, DenseMatrix; Use Eigen instead. <-- DONE | -- Lanczos Remove DenseVector, DenseMatrix; Use Eigen instead. <-- DONE | ||||||
| -- GaugeFix into central location                      <-- DONE | -- GaugeFix into central location                      <-- DONE | ||||||
| -- Scidac and Ildg metadata handling                   <-- DONE | -- Scidac and Ildg metadata handling                   <-- DONE | ||||||
|   | |||||||
| @@ -701,12 +701,14 @@ int main (int argc, char ** argv) | |||||||
|   if ( do_su3 ) { |   if ( do_su3 ) { | ||||||
|     // empty for now |     // empty for now | ||||||
|   } |   } | ||||||
|  | #if 1 | ||||||
|   int sel=2; |   int sel=2; | ||||||
|   std::vector<int> L_list({8,12,16,24}); |   std::vector<int> L_list({8,12,16,24}); | ||||||
|  | #else | ||||||
|   //int sel=1; |   int sel=1; | ||||||
|   //  std::vector<int> L_list({8,12}); |   std::vector<int> L_list({8,12}); | ||||||
|  | #endif | ||||||
|  |   int selm1=sel-1; | ||||||
|   std::vector<double> robust_list; |   std::vector<double> robust_list; | ||||||
|  |  | ||||||
|   std::vector<double> wilson; |   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 << "=================================================================================="<<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<<std::setprecision(3); | ||||||
|   std::cout<<GridLogMessage << " Comparison point robustness: "  << robust_list[sel] <<std::endl; |   std::cout<<GridLogMessage << " Comparison point robustness: "  << robust_list[sel] <<std::endl; | ||||||
|   std::cout<<GridLogMessage << "=================================================================================="<<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::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||||
|  |  | ||||||
|   std::vector<int> latt4 = GridDefaultLatt(); |   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()); |   GridCartesian         * UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplex::Nsimd()),GridDefaultMpi()); | ||||||
|   GridRedBlackCartesian * UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); |   GridRedBlackCartesian * UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid); | ||||||
|   GridCartesian         * FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls,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> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   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> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   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"; | 	  std::cout << latt_size.back() << "\t\t"; | ||||||
|  |  | ||||||
| 	  GridCartesian           Grid(latt_size,simd_layout,mpi_layout); | 	  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); | 	  GridParallelRNG  pRNG(&Grid); pRNG.SeedFixedIntegers(seeds); | ||||||
| 	  LatticeGaugeField Umu(&Grid); random(pRNG,Umu); | 	  LatticeGaugeField Umu(&Grid); random(pRNG,Umu); | ||||||
|   | |||||||
| @@ -1,25 +1,26 @@ | |||||||
| #include <Grid/Hadrons/Modules/MAction/DWF.hpp> | #include <Grid/Hadrons/Modules/MLoop/NoiseLoop.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MAction/Wilson.hpp> | #include <Grid/Hadrons/Modules/MFermion/GaugeProp.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MContraction/Baryon.hpp> |  | ||||||
| #include <Grid/Hadrons/Modules/MContraction/DiscLoop.hpp> |  | ||||||
| #include <Grid/Hadrons/Modules/MContraction/Gamma3pt.hpp> |  | ||||||
| #include <Grid/Hadrons/Modules/MContraction/Meson.hpp> |  | ||||||
| #include <Grid/Hadrons/Modules/MContraction/WeakHamiltonian.hpp> | #include <Grid/Hadrons/Modules/MContraction/WeakHamiltonian.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MContraction/Meson.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MContraction/DiscLoop.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MContraction/WeakHamiltonianEye.hpp> | #include <Grid/Hadrons/Modules/MContraction/WeakHamiltonianEye.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MContraction/Baryon.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MContraction/WeakHamiltonianNonEye.hpp> | #include <Grid/Hadrons/Modules/MContraction/WeakHamiltonianNonEye.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MContraction/WeakNeutral4ptDisc.hpp> | #include <Grid/Hadrons/Modules/MContraction/WeakNeutral4ptDisc.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MFermion/GaugeProp.hpp> | #include <Grid/Hadrons/Modules/MContraction/Gamma3pt.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MGauge/Load.hpp> | #include <Grid/Hadrons/Modules/MSource/Z2.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MGauge/Random.hpp> | #include <Grid/Hadrons/Modules/MSource/SeqGamma.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MGauge/StochEm.hpp> | #include <Grid/Hadrons/Modules/MSource/Point.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MGauge/Unit.hpp> | #include <Grid/Hadrons/Modules/MSource/Wall.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MLoop/NoiseLoop.hpp> | #include <Grid/Hadrons/Modules/MSource/Laplacian.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MSolver/RBPrecCG.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MScalar/ChargedProp.hpp> | #include <Grid/Hadrons/Modules/MScalar/ChargedProp.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MScalar/FreeProp.hpp> | #include <Grid/Hadrons/Modules/MScalar/FreeProp.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MScalar/Scalar.hpp> | #include <Grid/Hadrons/Modules/MScalar/Scalar.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MAction/DWF.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MAction/Wilson.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MGauge/StochEm.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MGauge/Unit.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MGauge/Random.hpp> | ||||||
|  | #include <Grid/Hadrons/Modules/MGauge/Load.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MSink/Point.hpp> | #include <Grid/Hadrons/Modules/MSink/Point.hpp> | ||||||
| #include <Grid/Hadrons/Modules/MSolver/RBPrecCG.hpp> |  | ||||||
| #include <Grid/Hadrons/Modules/MSource/Point.hpp> |  | ||||||
| #include <Grid/Hadrons/Modules/MSource/SeqGamma.hpp> |  | ||||||
| #include <Grid/Hadrons/Modules/MSource/Wall.hpp> |  | ||||||
| #include <Grid/Hadrons/Modules/MSource/Z2.hpp> |  | ||||||
|   | |||||||
							
								
								
									
										153
									
								
								extras/Hadrons/Modules/MSource/Laplacian.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								extras/Hadrons/Modules/MSource/Laplacian.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid  | ||||||
|  |  | ||||||
|  | Source file: extras/Hadrons/Modules/MSource/Laplacian.hpp | ||||||
|  |  | ||||||
|  | Copyright (C) 2017 | ||||||
|  |  | ||||||
|  | Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||||
|  |  | ||||||
|  | This program is free software; you can redistribute it and/or modify | ||||||
|  | it under the terms of the GNU General Public License as published by | ||||||
|  | the Free Software Foundation; either version 2 of the License, or | ||||||
|  | (at your option) any later version. | ||||||
|  |  | ||||||
|  | This program is distributed in the hope that it will be useful, | ||||||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | GNU General Public License for more details. | ||||||
|  |  | ||||||
|  | You should have received a copy of the GNU General Public License along | ||||||
|  | with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|  | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  |  | ||||||
|  | See the full license in the file "LICENSE" in the top level distribution directory | ||||||
|  | *************************************************************************************/ | ||||||
|  | /*  END LEGAL */ | ||||||
|  |  | ||||||
|  | #ifndef Hadrons_MSource_Laplacian_hpp_ | ||||||
|  | #define Hadrons_MSource_Laplacian_hpp_ | ||||||
|  |  | ||||||
|  | #include <Grid/Hadrons/Global.hpp> | ||||||
|  | #include <Grid/Hadrons/Module.hpp> | ||||||
|  | #include <Grid/Hadrons/ModuleFactory.hpp> | ||||||
|  |  | ||||||
|  | BEGIN_HADRONS_NAMESPACE | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |   | ||||||
|  |  Laplacian smearing source | ||||||
|  |  ----------------------------- | ||||||
|  |   | ||||||
|  |  * options: | ||||||
|  |  - source: name of source object to be smeared (string) | ||||||
|  |  - N: number of steps (integer) | ||||||
|  |  - alpha: smearing parameter (real) | ||||||
|  |   | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /****************************************************************************** | ||||||
|  |  *                          Laplace smearing operator                         * | ||||||
|  |  ******************************************************************************/ | ||||||
|  | BEGIN_MODULE_NAMESPACE(MSource) | ||||||
|  |  | ||||||
|  | class LaplacianPar : Serializable | ||||||
|  | { | ||||||
|  |   public: | ||||||
|  |     GRID_SERIALIZABLE_CLASS_MEMBERS(LaplacianPar, | ||||||
|  |                                     std::string, source, | ||||||
|  |                                     std::string, gauge, | ||||||
|  |                                     unsigned int, N, | ||||||
|  |                                     double, alpha); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename FImpl> | ||||||
|  | class TLaplacian : public Module<LaplacianPar> | ||||||
|  | { | ||||||
|  |   public: | ||||||
|  |     FERM_TYPE_ALIASES(FImpl, ); | ||||||
|  |  | ||||||
|  |   public: | ||||||
|  |     // constructor | ||||||
|  |     TLaplacian(const std::string name); | ||||||
|  |     // destructor | ||||||
|  |     virtual ~TLaplacian(void) = default; | ||||||
|  |     // dependency relation | ||||||
|  |     virtual std::vector<std::string> getInput(void); | ||||||
|  |     virtual std::vector<std::string> getOutput(void); | ||||||
|  |     // setup | ||||||
|  |     virtual void setup(void); | ||||||
|  |     // execution | ||||||
|  |     virtual void execute(void); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | MODULE_REGISTER_NS(LaplaceSmearing, TLaplacian<FIMPL>, MSource); | ||||||
|  |  | ||||||
|  | /****************************************************************************** | ||||||
|  |  *                       TLaplacian template implementation                   * | ||||||
|  |  ******************************************************************************/ | ||||||
|  | // constructor ///////////////////////////////////////////////////////////////// | ||||||
|  | template <typename FImpl> | ||||||
|  | TLaplacian<FImpl>::TLaplacian(const std::string name) | ||||||
|  |     : Module<LaplacianPar>(name) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // dependencies/products /////////////////////////////////////////////////////// | ||||||
|  | template <typename FImpl> | ||||||
|  | std::vector<std::string> TLaplacian<FImpl>::getInput(void) | ||||||
|  | { | ||||||
|  |     std::vector<std::string> in = {par().source, par().gauge}; | ||||||
|  |  | ||||||
|  |     return in; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename FImpl> | ||||||
|  | std::vector<std::string> TLaplacian<FImpl>::getOutput(void) | ||||||
|  | { | ||||||
|  |     std::vector<std::string> out = {getName()}; | ||||||
|  |  | ||||||
|  |     return out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // setup /////////////////////////////////////////////////////////////////////// | ||||||
|  | template <typename FImpl> | ||||||
|  | void TLaplacian<FImpl>::setup(void) | ||||||
|  | { | ||||||
|  |     env().template registerLattice<PropagatorField>(getName()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // execution /////////////////////////////////////////////////////////////////// | ||||||
|  | template <typename FImpl> | ||||||
|  | void TLaplacian<FImpl>::execute(void) | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     FermionField source(env().getGrid()), tmp(env().getGrid()); | ||||||
|  |     PropagatorField &SmrSrc = *env().template createLattice<PropagatorField>(getName()); | ||||||
|  |     PropagatorField &fullSrc = *env().template getObject<PropagatorField>(par().source); | ||||||
|  |     auto &U      = *env().template getObject<LatticeGaugeField>(par().gauge); | ||||||
|  |     Laplacian<FImpl> LaplaceOperator(env().getGrid()); | ||||||
|  |     LaplaceOperator.ImportGauge(U); | ||||||
|  |     double prefactor = par().alpha / (double)(par().N); | ||||||
|  |  | ||||||
|  |     for (unsigned int s = 0; s < Ns; ++s) | ||||||
|  |     { | ||||||
|  |         for (unsigned int c = 0; c < Nc; ++c) | ||||||
|  |         { | ||||||
|  |             PropToFerm(source, fullSrc, s, c); | ||||||
|  |             for (int smr = 0; smr < par().N; ++smr) | ||||||
|  |             { | ||||||
|  |                 LaplaceOperator.M(source, tmp); | ||||||
|  |                 source += prefactor * tmp; | ||||||
|  |             } | ||||||
|  |             FermToProp(SmrSrc, source, s, c); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | END_MODULE_NAMESPACE | ||||||
|  |  | ||||||
|  | END_HADRONS_NAMESPACE | ||||||
|  |  | ||||||
|  | #endif // Hadrons_MSource_Z2_hpp_ | ||||||
| @@ -1,38 +1,39 @@ | |||||||
| modules_cc =\ | modules_cc =\ | ||||||
|   Modules/MContraction/WeakHamiltonianEye.cc \ |  | ||||||
|   Modules/MContraction/WeakHamiltonianNonEye.cc \ |   Modules/MContraction/WeakHamiltonianNonEye.cc \ | ||||||
|   Modules/MContraction/WeakNeutral4ptDisc.cc \ |   Modules/MContraction/WeakNeutral4ptDisc.cc \ | ||||||
|   Modules/MGauge/Load.cc \ |   Modules/MContraction/WeakHamiltonianEye.cc \ | ||||||
|  |   Modules/MScalar/FreeProp.cc \ | ||||||
|  |   Modules/MScalar/ChargedProp.cc \ | ||||||
|  |   Modules/MGauge/Unit.cc \ | ||||||
|   Modules/MGauge/Random.cc \ |   Modules/MGauge/Random.cc \ | ||||||
|   Modules/MGauge/StochEm.cc \ |   Modules/MGauge/StochEm.cc \ | ||||||
|   Modules/MGauge/Unit.cc \ |   Modules/MGauge/Load.cc | ||||||
|   Modules/MScalar/ChargedProp.cc \ |  | ||||||
|   Modules/MScalar/FreeProp.cc |  | ||||||
|  |  | ||||||
| modules_hpp =\ | modules_hpp =\ | ||||||
|   Modules/MAction/DWF.hpp \ |   Modules/MLoop/NoiseLoop.hpp \ | ||||||
|   Modules/MAction/Wilson.hpp \ |   Modules/MFermion/GaugeProp.hpp \ | ||||||
|   Modules/MContraction/Baryon.hpp \ |  | ||||||
|   Modules/MContraction/DiscLoop.hpp \ |  | ||||||
|   Modules/MContraction/Gamma3pt.hpp \ |  | ||||||
|   Modules/MContraction/Meson.hpp \ |  | ||||||
|   Modules/MContraction/WeakHamiltonian.hpp \ |   Modules/MContraction/WeakHamiltonian.hpp \ | ||||||
|  |   Modules/MContraction/Meson.hpp \ | ||||||
|  |   Modules/MContraction/DiscLoop.hpp \ | ||||||
|   Modules/MContraction/WeakHamiltonianEye.hpp \ |   Modules/MContraction/WeakHamiltonianEye.hpp \ | ||||||
|  |   Modules/MContraction/Baryon.hpp \ | ||||||
|   Modules/MContraction/WeakHamiltonianNonEye.hpp \ |   Modules/MContraction/WeakHamiltonianNonEye.hpp \ | ||||||
|   Modules/MContraction/WeakNeutral4ptDisc.hpp \ |   Modules/MContraction/WeakNeutral4ptDisc.hpp \ | ||||||
|   Modules/MFermion/GaugeProp.hpp \ |   Modules/MContraction/Gamma3pt.hpp \ | ||||||
|   Modules/MGauge/Load.hpp \ |   Modules/MSource/Z2.hpp \ | ||||||
|   Modules/MGauge/Random.hpp \ |   Modules/MSource/SeqGamma.hpp \ | ||||||
|   Modules/MGauge/StochEm.hpp \ |   Modules/MSource/Point.hpp \ | ||||||
|   Modules/MGauge/Unit.hpp \ |   Modules/MSource/Wall.hpp \ | ||||||
|   Modules/MLoop/NoiseLoop.hpp \ |   Modules/MSource/Laplacian.hpp \ | ||||||
|  |   Modules/MSolver/RBPrecCG.hpp \ | ||||||
|   Modules/MScalar/ChargedProp.hpp \ |   Modules/MScalar/ChargedProp.hpp \ | ||||||
|   Modules/MScalar/FreeProp.hpp \ |   Modules/MScalar/FreeProp.hpp \ | ||||||
|   Modules/MScalar/Scalar.hpp \ |   Modules/MScalar/Scalar.hpp \ | ||||||
|   Modules/MSink/Point.hpp \ |   Modules/MAction/DWF.hpp \ | ||||||
|   Modules/MSolver/RBPrecCG.hpp \ |   Modules/MAction/Wilson.hpp \ | ||||||
|   Modules/MSource/Point.hpp \ |   Modules/MGauge/StochEm.hpp \ | ||||||
|   Modules/MSource/SeqGamma.hpp \ |   Modules/MGauge/Unit.hpp \ | ||||||
|   Modules/MSource/Wall.hpp \ |   Modules/MGauge/Random.hpp \ | ||||||
|   Modules/MSource/Z2.hpp |   Modules/MGauge/Load.hpp \ | ||||||
|  |   Modules/MSink/Point.hpp | ||||||
|  |  | ||||||
|   | |||||||
| @@ -37,6 +37,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | |||||||
| #include <Grid/algorithms/approx/Chebyshev.h> | #include <Grid/algorithms/approx/Chebyshev.h> | ||||||
| #include <Grid/algorithms/approx/Remez.h> | #include <Grid/algorithms/approx/Remez.h> | ||||||
| #include <Grid/algorithms/approx/MultiShiftFunction.h> | #include <Grid/algorithms/approx/MultiShiftFunction.h> | ||||||
|  | #include <Grid/algorithms/approx/Forecast.h> | ||||||
|  |  | ||||||
| #include <Grid/algorithms/iterative/ConjugateGradient.h> | #include <Grid/algorithms/iterative/ConjugateGradient.h> | ||||||
| #include <Grid/algorithms/iterative/ConjugateResidual.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/SchurRedBlack.h> | ||||||
| #include <Grid/algorithms/iterative/ConjugateGradientMultiShift.h> | #include <Grid/algorithms/iterative/ConjugateGradientMultiShift.h> | ||||||
| #include <Grid/algorithms/iterative/ConjugateGradientMixedPrec.h> | #include <Grid/algorithms/iterative/ConjugateGradientMixedPrec.h> | ||||||
|  | #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | ||||||
| // Lanczos support | #include <Grid/algorithms/iterative/ConjugateGradientReliableUpdate.h> | ||||||
| //#include <Grid/algorithms/iterative/MatrixUtils.h> |  | ||||||
| #include <Grid/algorithms/iterative/ImplicitlyRestartedLanczos.h> | #include <Grid/algorithms/iterative/ImplicitlyRestartedLanczos.h> | ||||||
| #include <Grid/algorithms/CoarsenedMatrix.h> | #include <Grid/algorithms/CoarsenedMatrix.h> | ||||||
| #include <Grid/algorithms/FFT.h> | #include <Grid/algorithms/FFT.h> | ||||||
|  |  | ||||||
| // Eigen/lanczos |  | ||||||
| // EigCg | // EigCg | ||||||
| // MCR |  | ||||||
| // Pcg | // Pcg | ||||||
| // Multishift CG |  | ||||||
| // Hdcg | // Hdcg | ||||||
| // GCR | // GCR | ||||||
| // etc.. | // etc.. | ||||||
|  |  | ||||||
| // integrator/Leapfrog |  | ||||||
| // integrator/Omelyan |  | ||||||
| // integrator/ForceGradient |  | ||||||
|  |  | ||||||
| // montecarlo/hmc |  | ||||||
| // montecarlo/rhmc |  | ||||||
| // montecarlo/metropolis |  | ||||||
| // etc... |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -230,6 +230,7 @@ namespace Grid { | |||||||
|       // Barrel shift and collect global pencil |       // Barrel shift and collect global pencil | ||||||
|       std::vector<int> lcoor(Nd), gcoor(Nd); |       std::vector<int> lcoor(Nd), gcoor(Nd); | ||||||
|       result = source; |       result = source; | ||||||
|  |       int pc = processor_coor[dim]; | ||||||
|       for(int p=0;p<processors[dim];p++) { |       for(int p=0;p<processors[dim];p++) { | ||||||
|         PARALLEL_REGION |         PARALLEL_REGION | ||||||
|         { |         { | ||||||
| @@ -240,7 +241,8 @@ namespace Grid { | |||||||
|           for(int idx=0;idx<sgrid->lSites();idx++) { |           for(int idx=0;idx<sgrid->lSites();idx++) { | ||||||
|             sgrid->LocalIndexToLocalCoor(idx,cbuf); |             sgrid->LocalIndexToLocalCoor(idx,cbuf); | ||||||
|             peekLocalSite(s,result,cbuf); |             peekLocalSite(s,result,cbuf); | ||||||
|             cbuf[dim]+=p*L; | 	    cbuf[dim]+=((pc+p) % processors[dim])*L; | ||||||
|  | 	    //            cbuf[dim]+=p*L; | ||||||
|             pokeLocalSite(s,pgbuf,cbuf); |             pokeLocalSite(s,pgbuf,cbuf); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @@ -278,7 +280,6 @@ namespace Grid { | |||||||
|       flops+= flops_call*NN; |       flops+= flops_call*NN; | ||||||
|        |        | ||||||
|       // writing out result |       // writing out result | ||||||
|       int pc = processor_coor[dim]; |  | ||||||
|       PARALLEL_REGION |       PARALLEL_REGION | ||||||
|       { |       { | ||||||
|         std::vector<int> clbuf(Nd), cgbuf(Nd); |         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); |   sliceInnerProductMatrix(m_rr,R,R,Orthog); | ||||||
|  |  | ||||||
|   //////////////////////////////////////////////////////////////////////////////////////////////////// |   // Force manifest hermitian to avoid rounding related | ||||||
|   // Cholesky from Eigen |   m_rr = 0.5*(m_rr+m_rr.adjoint()); | ||||||
|   // There exists a ldlt that is documented as more stable |  | ||||||
|   //////////////////////////////////////////////////////////////////////////////////////////////////// |  | ||||||
|   Eigen::MatrixXcd L    = m_rr.llt().matrixL();  |  | ||||||
|  |  | ||||||
|  | #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(); |   C    = L.adjoint(); | ||||||
|   Cinv = C.inverse(); |   Cinv = C.inverse(); | ||||||
|  |  | ||||||
|   //////////////////////////////////////////////////////////////////////////////////////////////////// |   //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|   // Q = R C^{-1} |   // 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 |   // 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); |   sliceMulMatrix(Q,Cinv,R,Orthog); | ||||||
| } | } | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -52,8 +52,8 @@ class ConjugateGradient : public OperatorFunction<Field> { | |||||||
|         MaxIterations(maxit), |         MaxIterations(maxit), | ||||||
|         ErrorOnNoConverge(err_on_no_conv){}; |         ErrorOnNoConverge(err_on_no_conv){}; | ||||||
|  |  | ||||||
|   void operator()(LinearOperatorBase<Field> &Linop, const Field &src, |   void operator()(LinearOperatorBase<Field> &Linop, const Field &src, Field &psi) { | ||||||
|                   Field &psi) { |  | ||||||
|     psi.checkerboard = src.checkerboard; |     psi.checkerboard = src.checkerboard; | ||||||
|     conformable(psi, src); |     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 <Grid/GridCore.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  |  | ||||||
| namespace Grid { | namespace Grid { | ||||||
|  |  | ||||||
| @@ -63,4 +61,37 @@ void *PointerCache::Lookup(size_t bytes) { | |||||||
|   return NULL; |   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. | // A lattice of something, but assume the something is SIMDized. | ||||||
| //////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -49,6 +49,8 @@ public: | |||||||
|     template<class object> friend class Lattice; |     template<class object> friend class Lattice; | ||||||
|  |  | ||||||
|     GridBase(const std::vector<int> & processor_grid) : CartesianCommunicator(processor_grid) {}; |     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. |     // Physics Grid information. | ||||||
|     std::vector<int> _simd_layout;// Which dimensions get relayed out over simd lanes. |     std::vector<int> _simd_layout;// Which dimensions get relayed out over simd lanes. | ||||||
| @@ -210,9 +212,6 @@ public: | |||||||
|       assert(lidx<lSites()); |       assert(lidx<lSites()); | ||||||
|       Lexicographic::CoorFromIndex(lcoor,lidx,_ldimensions); |       Lexicographic::CoorFromIndex(lcoor,lidx,_ldimensions); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     void GlobalCoorToGlobalIndex(const std::vector<int> & gcoor,int & gidx){ |     void GlobalCoorToGlobalIndex(const std::vector<int> & gcoor,int & gidx){ | ||||||
|       gidx=0; |       gidx=0; | ||||||
|       int mult=1; |       int mult=1; | ||||||
|   | |||||||
| @@ -61,9 +61,29 @@ public: | |||||||
|     virtual int CheckerBoardShift(int source_cb,int dim,int shift, int osite){ |     virtual int CheckerBoardShift(int source_cb,int dim,int shift, int osite){ | ||||||
|       return shift; |       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, | ||||||
|  | 		  const GridCartesian &parent) : GridBase(processor_grid,parent) | ||||||
|  |     { | ||||||
|  |       Init(dimensions,simd_layout,processor_grid); | ||||||
|  |     } | ||||||
|  |     ///////////////////////////////////////////////////////////////////////// | ||||||
|  |     // Construct from comm world | ||||||
|  |     ///////////////////////////////////////////////////////////////////////// | ||||||
|     GridCartesian(const std::vector<int> &dimensions, |     GridCartesian(const std::vector<int> &dimensions, | ||||||
| 		  const std::vector<int> &simd_layout, | 		  const std::vector<int> &simd_layout, | ||||||
| 		  const std::vector<int> &processor_grid) : GridBase(processor_grid) | 		  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 |       // 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> &simd_layout, | ||||||
| 			  const std::vector<int> &processor_grid, | 			  const std::vector<int> &processor_grid, | ||||||
| 			  const std::vector<int> &checker_dim_mask, | 			  const std::vector<int> &checker_dim_mask, | ||||||
| 			  int checker_dim | 			  int checker_dim | ||||||
| 			  ) :  GridBase(processor_grid)  | 			  ) :  GridBase(processor_grid,*base)  | ||||||
|     { |     { | ||||||
|       Init(dimensions,simd_layout,processor_grid,checker_dim_mask,checker_dim); |       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> &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); |       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, |     void Init(const std::vector<int> &dimensions, | ||||||
|               const std::vector<int> &simd_layout, |               const std::vector<int> &simd_layout, | ||||||
|               const std::vector<int> &processor_grid, |               const std::vector<int> &processor_grid, | ||||||
|   | |||||||
| @@ -96,6 +96,105 @@ void CartesianCommunicator::GlobalSumVector(ComplexD *c,int N) | |||||||
|   GlobalSumVector((double *)c,2*N); |   GlobalSumVector((double *)c,2*N); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if defined( GRID_COMMS_MPI) || defined (GRID_COMMS_MPIT) | ||||||
|  |  | ||||||
|  | CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors,const CartesianCommunicator &parent)  | ||||||
|  | { | ||||||
|  |   _ndimension = processors.size(); | ||||||
|  |   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; | ||||||
|  |   for(int i=0;i<_ndimension;i++){ | ||||||
|  |     _Nprocessors*=_processors[i]; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   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); | ||||||
|  |  | ||||||
|  | #ifdef GRID_COMMS_MPIT | ||||||
|  |   communicator_halo.resize (2*_ndimension); | ||||||
|  |   for(int i=0;i<_ndimension*2;i++){ | ||||||
|  |     MPI_Comm_dup(communicator,&communicator_halo[i]); | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |    | ||||||
|  |   assert(Size==_Nprocessors); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors)  | ||||||
|  | { | ||||||
|  |   InitFromMPICommunicator(processors,communicator_world); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #if !defined( GRID_COMMS_MPI3)  | #if !defined( GRID_COMMS_MPI3)  | ||||||
|  |  | ||||||
| int                      CartesianCommunicator::NodeCount(void)    { return ProcessorCount();}; | int                      CartesianCommunicator::NodeCount(void)    { return ProcessorCount();}; | ||||||
| @@ -147,8 +246,13 @@ void *CartesianCommunicator::ShmBufferTranslate(int rank,void * local_p) { | |||||||
| } | } | ||||||
| void CartesianCommunicator::ShmInitGeneric(void){ | void CartesianCommunicator::ShmInitGeneric(void){ | ||||||
| #if 1 | #if 1 | ||||||
|  |   int mmap_flag =0; | ||||||
|   int mmap_flag = MAP_SHARED | MAP_ANONYMOUS; | #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 | #ifdef MAP_HUGETLB | ||||||
|   if ( Hugepages ) mmap_flag |= MAP_HUGETLB; |   if ( Hugepages ) mmap_flag |= MAP_HUGETLB; | ||||||
| #endif | #endif | ||||||
| @@ -157,7 +261,9 @@ void CartesianCommunicator::ShmInitGeneric(void){ | |||||||
|     perror("mmap failed "); |     perror("mmap failed "); | ||||||
|     exit(EXIT_FAILURE);   |     exit(EXIT_FAILURE);   | ||||||
|   } |   } | ||||||
|  | #ifdef MADV_HUGEPAGE | ||||||
|   if (!Hugepages ) madvise(ShmCommBuf,MAX_MPI_SHM_BYTES,MADV_HUGEPAGE); |   if (!Hugepages ) madvise(ShmCommBuf,MAX_MPI_SHM_BYTES,MADV_HUGEPAGE); | ||||||
|  | #endif | ||||||
| #else  | #else  | ||||||
|   ShmBufStorageVector.resize(MAX_MPI_SHM_BYTES); |   ShmBufStorageVector.resize(MAX_MPI_SHM_BYTES); | ||||||
|   ShmCommBuf=(void *)&ShmBufStorageVector[0]; |   ShmCommBuf=(void *)&ShmBufStorageVector[0]; | ||||||
|   | |||||||
| @@ -83,6 +83,7 @@ class CartesianCommunicator { | |||||||
|   std::vector<MPI_Comm> communicator_halo; |   std::vector<MPI_Comm> communicator_halo; | ||||||
|  |  | ||||||
|   typedef MPI_Request CommsRequest_t; |   typedef MPI_Request CommsRequest_t; | ||||||
|  |  | ||||||
| #else  | #else  | ||||||
|   typedef int CommsRequest_t; |   typedef int CommsRequest_t; | ||||||
| #endif | #endif | ||||||
| @@ -149,10 +150,22 @@ class CartesianCommunicator { | |||||||
|   static void Init(int *argc, char ***argv); |   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); |   CartesianCommunicator(const std::vector<int> &pdimensions_in); | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  | #if defined (GRID_COMMS_MPI) || defined (GRID_COMMS_MPIT)  | ||||||
|  |   //////////////////////////////////////////////// | ||||||
|  |   // 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 |   // Wraps MPI_Cart routines, or implements equivalent on other impls | ||||||
|   //////////////////////////////////////////////////////////////////////////////////////// |   //////////////////////////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -52,29 +52,6 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | |||||||
|   MPI_Comm_dup (MPI_COMM_WORLD,&communicator_world); |   MPI_Comm_dup (MPI_COMM_WORLD,&communicator_world); | ||||||
|   ShmInitGeneric(); |   ShmInitGeneric(); | ||||||
| } | } | ||||||
|  |  | ||||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) |  | ||||||
| { |  | ||||||
|   _ndimension = processors.size(); |  | ||||||
|   std::vector<int> periodic(_ndimension,1); |  | ||||||
|  |  | ||||||
|   _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;  |  | ||||||
|   MPI_Comm_size(communicator,&Size); |  | ||||||
|    |  | ||||||
|   assert(Size==_Nprocessors); |  | ||||||
| } |  | ||||||
| void CartesianCommunicator::GlobalSum(uint32_t &u){ | void CartesianCommunicator::GlobalSum(uint32_t &u){ | ||||||
|   int ierr=MPI_Allreduce(MPI_IN_PLACE,&u,1,MPI_UINT32_T,MPI_SUM,communicator); |   int ierr=MPI_Allreduce(MPI_IN_PLACE,&u,1,MPI_UINT32_T,MPI_SUM,communicator); | ||||||
|   assert(ierr==0); |   assert(ierr==0); | ||||||
|   | |||||||
| @@ -215,8 +215,10 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | |||||||
|       perror("open hugetlbfs"); |       perror("open hugetlbfs"); | ||||||
|       exit(0); |       exit(0); | ||||||
|     } |     } | ||||||
|      |     int mmap_flag = MAP_SHARED ; | ||||||
|     int mmap_flag = MAP_SHARED |MAP_POPULATE; | #ifdef MAP_POPULATE     | ||||||
|  |     mmap_flag|=MAP_POPULATE; | ||||||
|  | #endif | ||||||
| #ifdef MAP_HUGETLB | #ifdef MAP_HUGETLB | ||||||
|     if ( Hugepages ) mmap_flag |= MAP_HUGETLB; |     if ( Hugepages ) mmap_flag |= MAP_HUGETLB; | ||||||
| #endif | #endif | ||||||
| @@ -249,7 +251,10 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | |||||||
|       if ( fd < 0 ) {	perror("failed shm_open");	assert(0);      } |       if ( fd < 0 ) {	perror("failed shm_open");	assert(0);      } | ||||||
|       ftruncate(fd, size); |       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 | #ifdef MAP_HUGETLB | ||||||
|       if (Hugepages) mmap_flag |= MAP_HUGETLB; |       if (Hugepages) mmap_flag |= MAP_HUGETLB; | ||||||
| #endif | #endif | ||||||
| @@ -445,6 +450,15 @@ void  CartesianCommunicator::ProcessorCoorFromRank(int rank, std::vector<int> &c | |||||||
|   assert(lr!=-1); |   assert(lr!=-1); | ||||||
|   Lexicographic::CoorFromIndex(coor,lr,_processors); |   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) | CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) | ||||||
| {  | {  | ||||||
|   int ierr; |   int ierr; | ||||||
|   | |||||||
| @@ -53,33 +53,6 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | |||||||
|   ShmInitGeneric(); |   ShmInitGeneric(); | ||||||
| } | } | ||||||
|  |  | ||||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) |  | ||||||
| { |  | ||||||
|   _ndimension = processors.size(); |  | ||||||
|   std::vector<int> periodic(_ndimension,1); |  | ||||||
|  |  | ||||||
|   _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]; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   communicator_halo.resize (2*_ndimension); |  | ||||||
|   for(int i=0;i<_ndimension*2;i++){ |  | ||||||
|     MPI_Comm_dup(communicator,&communicator_halo[i]); |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   int Size;  |  | ||||||
|   MPI_Comm_size(communicator,&Size); |  | ||||||
|    |  | ||||||
|   assert(Size==_Nprocessors); |  | ||||||
| } |  | ||||||
| void CartesianCommunicator::GlobalSum(uint32_t &u){ | void CartesianCommunicator::GlobalSum(uint32_t &u){ | ||||||
|   int ierr=MPI_Allreduce(MPI_IN_PLACE,&u,1,MPI_UINT32_T,MPI_SUM,communicator); |   int ierr=MPI_Allreduce(MPI_IN_PLACE,&u,1,MPI_UINT32_T,MPI_SUM,communicator); | ||||||
|   assert(ierr==0); |   assert(ierr==0); | ||||||
|   | |||||||
| @@ -38,6 +38,9 @@ void CartesianCommunicator::Init(int *argc, char *** arv) | |||||||
|   ShmInitGeneric(); |   ShmInitGeneric(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors,const CartesianCommunicator &parent)  | ||||||
|  |   : CartesianCommunicator(processors) {} | ||||||
|  |  | ||||||
| CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) | CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) | ||||||
| { | { | ||||||
|   _processors = processors; |   _processors = processors; | ||||||
|   | |||||||
| @@ -75,6 +75,11 @@ void CartesianCommunicator::Init(int *argc, char ***argv) { | |||||||
|   ShmInitGeneric(); |   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) | CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors) | ||||||
| { | { | ||||||
|   _ndimension = processors.size(); |   _ndimension = processors.size(); | ||||||
|   | |||||||
							
								
								
									
										16182
									
								
								lib/json/json.hpp
									
									
									
									
									
								
							
							
						
						
									
										16182
									
								
								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 i=0;i<Nblock;i++){ | ||||||
|       for(int j=0;j<Nblock;j++){ |       for(int j=0;j<Nblock;j++){ | ||||||
| 	auto tmp = innerProduct(Left[i],Right[j]); | 	auto tmp = innerProduct(Left[i],Right[j]); | ||||||
| 	//	vector_typeD rtmp = TensorRemove(tmp); |  | ||||||
| 	auto rtmp = TensorRemove(tmp); | 	auto rtmp = TensorRemove(tmp); | ||||||
| 	mat_thread(i,j) += Reduce(rtmp); | 	mat_thread(i,j) += Reduce(rtmp); | ||||||
|       }} |       }} | ||||||
|   | |||||||
| @@ -84,10 +84,6 @@ namespace QCD { | |||||||
|    stream << "GRID_"; |    stream << "GRID_"; | ||||||
|    stream << ScidacWordMnemonic<stype>(); |    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 ( _LorentzVector )   stream << "_LorentzVector"<<_LorentzN; | ||||||
|    if ( _LorentzMatrix )   stream << "_LorentzMatrix"<<_LorentzN; |    if ( _LorentzMatrix )   stream << "_LorentzMatrix"<<_LorentzN; | ||||||
|  |  | ||||||
| @@ -182,7 +178,7 @@ class GridLimeReader : public BinaryIO { | |||||||
|    ///////////////////////////////////////////// |    ///////////////////////////////////////////// | ||||||
|    // Open the file |    // Open the file | ||||||
|    ///////////////////////////////////////////// |    ///////////////////////////////////////////// | ||||||
|    void open(std::string &_filename)  |    void open(const std::string &_filename)  | ||||||
|    { |    { | ||||||
|      filename= _filename; |      filename= _filename; | ||||||
|      File = fopen(filename.c_str(), "r"); |      File = fopen(filename.c_str(), "r"); | ||||||
| @@ -210,19 +206,33 @@ class GridLimeReader : public BinaryIO { | |||||||
|  |  | ||||||
|     while ( limeReaderNextRecord(LimeR) == LIME_SUCCESS ) {  |     while ( limeReaderNextRecord(LimeR) == LIME_SUCCESS ) {  | ||||||
|  |  | ||||||
|       std::cout << GridLogMessage << limeReaderType(LimeR) <<std::endl; |       uint64_t file_bytes =limeReaderBytes(LimeR); | ||||||
|  |  | ||||||
|       if ( strncmp(limeReaderType(LimeR), record_name.c_str(),strlen(record_name.c_str()) )  ) { |       //      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); | 	off_t offset= ftell(File); | ||||||
|  | 	//	std::cout << " ReadLatticeObject from offset "<<offset << std::endl; | ||||||
| 	BinarySimpleMunger<sobj,sobj> munge; | 	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 | 	// Insist checksum is next record | ||||||
| 	///////////////////////////////////////////// | 	///////////////////////////////////////////// | ||||||
| 	readLimeObject(scidacChecksum_,std::string("scidacChecksum"),record_name); | 	readLimeObject(scidacChecksum_,std::string("scidacChecksum"),std::string(SCIDAC_CHECKSUM)); | ||||||
|  |  | ||||||
| 	///////////////////////////////////////////// | 	///////////////////////////////////////////// | ||||||
| 	// Verify checksums | 	// Verify checksums | ||||||
| @@ -242,11 +252,19 @@ class GridLimeReader : public BinaryIO { | |||||||
|     // should this be a do while; can we miss a first record?? |     // should this be a do while; can we miss a first record?? | ||||||
|     while ( limeReaderNextRecord(LimeR) == LIME_SUCCESS ) {  |     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) |       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'); | 	std::vector<char> xmlc(nbytes+1,'\0'); | ||||||
| 	limeReaderReadData((void *)&xmlc[0], &nbytes, LimeR);     | 	limeReaderReadData((void *)&xmlc[0], &nbytes, LimeR);     | ||||||
|  |  | ||||||
|  | 	//	std::cout << GridLogMessage<< " readLimeObject matches XML " << &xmlc[0] <<std::endl; | ||||||
|  |  | ||||||
| 	XmlReader RD(&xmlc[0],""); | 	XmlReader RD(&xmlc[0],""); | ||||||
| 	read(RD,object_name,object); | 	read(RD,object_name,object); | ||||||
| 	return; | 	return; | ||||||
| @@ -261,13 +279,14 @@ class GridLimeWriter : public BinaryIO { | |||||||
|  public: |  public: | ||||||
|    /////////////////////////////////////////////////// |    /////////////////////////////////////////////////// | ||||||
|    // FIXME: format for RNG? Now just binary out instead |    // 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; |    FILE       *File; | ||||||
|    LimeWriter *LimeW; |    LimeWriter *LimeW; | ||||||
|    std::string filename; |    std::string filename; | ||||||
|  |  | ||||||
|    void open(std::string &_filename) {  |    void open(const std::string &_filename) {  | ||||||
|      filename= _filename; |      filename= _filename; | ||||||
|      File = fopen(filename.c_str(), "w"); |      File = fopen(filename.c_str(), "w"); | ||||||
|      LimeW = limeCreateWriter(File); assert(LimeW != NULL ); |      LimeW = limeCreateWriter(File); assert(LimeW != NULL ); | ||||||
| @@ -302,14 +321,18 @@ class GridLimeWriter : public BinaryIO { | |||||||
|       write(WR,object_name,object); |       write(WR,object_name,object); | ||||||
|       xmlstring = WR.XmlString(); |       xmlstring = WR.XmlString(); | ||||||
|     } |     } | ||||||
|  |     //    std::cout << "WriteLimeObject" << record_name <<std::endl; | ||||||
|     uint64_t nbytes = xmlstring.size(); |     uint64_t nbytes = xmlstring.size(); | ||||||
|  |     //    std::cout << " xmlstring "<< nbytes<< " " << xmlstring <<std::endl; | ||||||
|     int err; |     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=limeWriteRecordHeader(h, LimeW);                    assert(err>=0); | ||||||
|     err=limeWriteRecordData(&xmlstring[0], &nbytes, LimeW); assert(err>=0); |     err=limeWriteRecordData(&xmlstring[0], &nbytes, LimeW); assert(err>=0); | ||||||
|     err=limeWriterCloseRecord(LimeW);                       assert(err>=0); |     err=limeWriterCloseRecord(LimeW);                       assert(err>=0); | ||||||
|     limeDestroyHeader(h); |     limeDestroyHeader(h); | ||||||
|  |     //    std::cout << " File offset is now"<<ftell(File) << std::endl; | ||||||
|   } |   } | ||||||
|   //////////////////////////////////////////// |   //////////////////////////////////////////// | ||||||
|   // Write a generic lattice field and csum |   // Write a generic lattice field and csum | ||||||
| @@ -326,6 +349,11 @@ class GridLimeWriter : public BinaryIO { | |||||||
|     uint64_t PayloadSize = sizeof(sobj) * field._grid->_gsites; |     uint64_t PayloadSize = sizeof(sobj) * field._grid->_gsites; | ||||||
|     createLimeRecordHeader(record_name, 0, 0, PayloadSize); |     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 |     // NB: FILE and iostream are jointly writing disjoint sequences in the | ||||||
|     // the same file through different file handles (integer units). |     // the same file through different file handles (integer units). | ||||||
| @@ -340,6 +368,7 @@ class GridLimeWriter : public BinaryIO { | |||||||
|     //  v) Continue writing scidac record. |     //  v) Continue writing scidac record. | ||||||
|     //////////////////////////////////////////////////////////////////// |     //////////////////////////////////////////////////////////////////// | ||||||
|     off_t offset = ftell(File); |     off_t offset = ftell(File); | ||||||
|  |     //    std::cout << " Writing to offset "<<offset << std::endl; | ||||||
|     std::string format = getFormatString<vobj>(); |     std::string format = getFormatString<vobj>(); | ||||||
|     BinarySimpleMunger<sobj,sobj> munge; |     BinarySimpleMunger<sobj,sobj> munge; | ||||||
|     BinaryIO::writeLatticeObject<vobj,sobj>(field, filename, munge, offset, format,nersc_csum,scidac_csuma,scidac_csumb); |     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.suma= streama.str(); | ||||||
|     checksum.sumb= streamb.str(); |     checksum.sumb= streamb.str(); | ||||||
|     std::cout << GridLogMessage<<" writing scidac checksums "<<std::hex<<scidac_csuma<<"/"<<scidac_csumb<<std::dec<<std::endl; |     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)); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -374,8 +403,6 @@ class ScidacWriter : public GridLimeWriter { | |||||||
|   template <class vobj, class userRecord> |   template <class vobj, class userRecord> | ||||||
|   void writeScidacFieldRecord(Lattice<vobj> &field,userRecord _userRecord)  |   void writeScidacFieldRecord(Lattice<vobj> &field,userRecord _userRecord)  | ||||||
|   { |   { | ||||||
|     typedef typename vobj::scalar_object sobj; |  | ||||||
|     uint64_t nbytes; |  | ||||||
|     GridBase * grid = field._grid; |     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 { | class IldgWriter : public ScidacWriter { | ||||||
|  public: |  public: | ||||||
|  |  | ||||||
| @@ -425,8 +512,6 @@ class IldgWriter : public ScidacWriter { | |||||||
|     typedef iLorentzColourMatrix<vsimd> vobj; |     typedef iLorentzColourMatrix<vsimd> vobj; | ||||||
|     typedef typename vobj::scalar_object sobj; |     typedef typename vobj::scalar_object sobj; | ||||||
|  |  | ||||||
|     uint64_t nbytes; |  | ||||||
|  |  | ||||||
|     //////////////////////////////////////// |     //////////////////////////////////////// | ||||||
|     // fill the Grid header |     // fill the Grid header | ||||||
|     //////////////////////////////////////// |     //////////////////////////////////////// | ||||||
|   | |||||||
| @@ -64,6 +64,11 @@ namespace Grid { | |||||||
| // file compatability, so should be correct to assume the undocumented but defacto file structure. | // 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 | // 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> | // <?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; | 	nd=4; | ||||||
| 	dimension.resize(4); | 	dimension.resize(4); | ||||||
| 	boundary.resize(4); | 	boundary.resize(4); | ||||||
|  | 	scidac_checksuma=0; | ||||||
|  | 	scidac_checksumb=0; | ||||||
|  | 	checksum=0; | ||||||
|       } |       } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -104,6 +107,7 @@ namespace Grid { | |||||||
|       header.nd = nd; |       header.nd = nd; | ||||||
|       header.dimension.resize(nd); |       header.dimension.resize(nd); | ||||||
|       header.boundary.resize(nd); |       header.boundary.resize(nd); | ||||||
|  |       header.data_start = 0; | ||||||
|       for(int d=0;d<nd;d++) { |       for(int d=0;d<nd;d++) { | ||||||
| 	header.dimension[d] = grid->_fdimensions[d]; | 	header.dimension[d] = grid->_fdimensions[d]; | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -47,4 +47,8 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | |||||||
| //////////////////////////////////////// | //////////////////////////////////////// | ||||||
| #include <Grid/qcd/action/pseudofermion/PseudoFermion.h> | #include <Grid/qcd/action/pseudofermion/PseudoFermion.h> | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////// | ||||||
|  | // Laplacian on fermion fields | ||||||
|  | //////////////////////////////////////////////////////////////////////// | ||||||
|  | #include <Grid/qcd/utils/CovariantLaplacian.h> | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ directory | |||||||
| // Utility functions | // Utility functions | ||||||
| //////////////////////////////////////////// | //////////////////////////////////////////// | ||||||
| #include <Grid/qcd/utils/Metric.h> | #include <Grid/qcd/utils/Metric.h> | ||||||
| #include <Grid/qcd/utils/CovariantLaplacian.h> | #include <Grid/qcd/utils/CovariantAdjointLaplacian.h> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										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 | ||||||
| @@ -77,7 +77,6 @@ void CayleyFermion5D<Impl>::DminusDag(const FermionField &psi, FermionField &chi | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| template<class Impl> void CayleyFermion5D<Impl>::CayleyReport(void) | template<class Impl> void CayleyFermion5D<Impl>::CayleyReport(void) | ||||||
| { | { | ||||||
|   this->Report(); |   this->Report(); | ||||||
| @@ -119,7 +118,6 @@ template<class Impl> void CayleyFermion5D<Impl>::CayleyZeroCounters(void) | |||||||
|   MooeeInvTime=0; |   MooeeInvTime=0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| template<class Impl>   | template<class Impl>   | ||||||
| void CayleyFermion5D<Impl>::M5D   (const FermionField &psi, FermionField &chi) | void CayleyFermion5D<Impl>::M5D   (const FermionField &psi, FermionField &chi) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -179,9 +179,9 @@ namespace Grid { | |||||||
|      double MooeeInvTime; |      double MooeeInvTime; | ||||||
|  |  | ||||||
|     protected: |     protected: | ||||||
|       void SetCoefficientsZolotarev(RealD zolohi,Approx::zolotarev_data *zdata,RealD b,RealD c); |       virtual void SetCoefficientsZolotarev(RealD zolohi,Approx::zolotarev_data *zdata,RealD b,RealD c); | ||||||
|       void SetCoefficientsTanh(Approx::zolotarev_data *zdata,RealD b,RealD c); |       virtual 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 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 | ||||||
|  |  | ||||||
|  | }} | ||||||
| @@ -38,6 +38,8 @@ Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | |||||||
| // - ContinuedFractionFermion5D.cc | // - ContinuedFractionFermion5D.cc | ||||||
| // - WilsonFermion.cc | // - WilsonFermion.cc | ||||||
| // - WilsonKernels.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 | // 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 | // 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/ImprovedStaggeredFermion5D.h> | ||||||
| #include <Grid/qcd/action/fermion/CayleyFermion5D.h>     // Cayley types | #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/DomainWallFermion.h> | #include <Grid/qcd/action/fermion/DomainWallEOFAFermion.h> | ||||||
| #include <Grid/qcd/action/fermion/MobiusFermion.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/ZMobiusFermion.h> | ||||||
| #include <Grid/qcd/action/fermion/SchurDiagTwoKappa.h> | #include <Grid/qcd/action/fermion/SchurDiagTwoKappa.h> | ||||||
| #include <Grid/qcd/action/fermion/ScaledShamirFermion.h> | #include <Grid/qcd/action/fermion/ScaledShamirFermion.h> | ||||||
| @@ -113,6 +116,14 @@ typedef DomainWallFermion<WilsonImplRL> DomainWallFermionRL; | |||||||
| typedef DomainWallFermion<WilsonImplFH> DomainWallFermionFH; | typedef DomainWallFermion<WilsonImplFH> DomainWallFermionFH; | ||||||
| typedef DomainWallFermion<WilsonImplDF> DomainWallFermionDF; | 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<WilsonImplR> MobiusFermionR; | ||||||
| typedef MobiusFermion<WilsonImplF> MobiusFermionF; | typedef MobiusFermion<WilsonImplF> MobiusFermionF; | ||||||
| typedef MobiusFermion<WilsonImplD> MobiusFermionD; | typedef MobiusFermion<WilsonImplD> MobiusFermionD; | ||||||
| @@ -121,6 +132,14 @@ typedef MobiusFermion<WilsonImplRL> MobiusFermionRL; | |||||||
| typedef MobiusFermion<WilsonImplFH> MobiusFermionFH; | typedef MobiusFermion<WilsonImplFH> MobiusFermionFH; | ||||||
| typedef MobiusFermion<WilsonImplDF> MobiusFermionDF; | 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<ZWilsonImplR> ZMobiusFermionR; | ||||||
| typedef ZMobiusFermion<ZWilsonImplF> ZMobiusFermionF; | typedef ZMobiusFermion<ZWilsonImplF> ZMobiusFermionF; | ||||||
| typedef ZMobiusFermion<ZWilsonImplD> ZMobiusFermionD; | typedef ZMobiusFermion<ZWilsonImplD> ZMobiusFermionD; | ||||||
| @@ -138,6 +157,14 @@ typedef DomainWallFermion<DomainWallVec5dImplRL> DomainWallFermionVec5dRL; | |||||||
| typedef DomainWallFermion<DomainWallVec5dImplFH> DomainWallFermionVec5dFH; | typedef DomainWallFermion<DomainWallVec5dImplFH> DomainWallFermionVec5dFH; | ||||||
| typedef DomainWallFermion<DomainWallVec5dImplDF> DomainWallFermionVec5dDF; | 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<DomainWallVec5dImplR> MobiusFermionVec5dR; | ||||||
| typedef MobiusFermion<DomainWallVec5dImplF> MobiusFermionVec5dF; | typedef MobiusFermion<DomainWallVec5dImplF> MobiusFermionVec5dF; | ||||||
| typedef MobiusFermion<DomainWallVec5dImplD> MobiusFermionVec5dD; | typedef MobiusFermion<DomainWallVec5dImplD> MobiusFermionVec5dD; | ||||||
| @@ -146,6 +173,14 @@ typedef MobiusFermion<DomainWallVec5dImplRL> MobiusFermionVec5dRL; | |||||||
| typedef MobiusFermion<DomainWallVec5dImplFH> MobiusFermionVec5dFH; | typedef MobiusFermion<DomainWallVec5dImplFH> MobiusFermionVec5dFH; | ||||||
| typedef MobiusFermion<DomainWallVec5dImplDF> MobiusFermionVec5dDF; | 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<ZDomainWallVec5dImplR> ZMobiusFermionVec5dR; | ||||||
| typedef ZMobiusFermion<ZDomainWallVec5dImplF> ZMobiusFermionVec5dF; | typedef ZMobiusFermion<ZDomainWallVec5dImplF> ZMobiusFermionVec5dF; | ||||||
| typedef ZMobiusFermion<ZDomainWallVec5dImplD> ZMobiusFermionVec5dD; | typedef ZMobiusFermion<ZDomainWallVec5dImplD> ZMobiusFermionVec5dD; | ||||||
| @@ -206,6 +241,14 @@ typedef DomainWallFermion<GparityWilsonImplRL> GparityDomainWallFermionRL; | |||||||
| typedef DomainWallFermion<GparityWilsonImplFH> GparityDomainWallFermionFH; | typedef DomainWallFermion<GparityWilsonImplFH> GparityDomainWallFermionFH; | ||||||
| typedef DomainWallFermion<GparityWilsonImplDF> GparityDomainWallFermionDF; | 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<GparityWilsonImplR> GparityWilsonTMFermionR; | ||||||
| typedef WilsonTMFermion<GparityWilsonImplF> GparityWilsonTMFermionF; | typedef WilsonTMFermion<GparityWilsonImplF> GparityWilsonTMFermionF; | ||||||
| typedef WilsonTMFermion<GparityWilsonImplD> GparityWilsonTMFermionD; | typedef WilsonTMFermion<GparityWilsonImplD> GparityWilsonTMFermionD; | ||||||
| @@ -222,6 +265,14 @@ typedef MobiusFermion<GparityWilsonImplRL> GparityMobiusFermionRL; | |||||||
| typedef MobiusFermion<GparityWilsonImplFH> GparityMobiusFermionFH; | typedef MobiusFermion<GparityWilsonImplFH> GparityMobiusFermionFH; | ||||||
| typedef MobiusFermion<GparityWilsonImplDF> GparityMobiusFermionDF; | 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<StaggeredImplR> ImprovedStaggeredFermionR; | ||||||
| typedef ImprovedStaggeredFermion<StaggeredImplF> ImprovedStaggeredFermionF; | typedef ImprovedStaggeredFermion<StaggeredImplF> ImprovedStaggeredFermionF; | ||||||
| typedef ImprovedStaggeredFermion<StaggeredImplD> ImprovedStaggeredFermionD; | 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) |  inline void DoubleStore(GridBase *GaugeGrid,DoubledGaugeField &Uds,const GaugeField &Umu) | ||||||
|  { |  { | ||||||
|    conformable(Uds._grid,GaugeGrid); |    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 REGISTER | ||||||
|  |  | ||||||
| #define LOAD_CHIMU \ | #define LOAD_CHIMU_BODY(F)			\ | ||||||
|   {const SiteSpinor & ref (in._odata[offset]);	\ |   Chimu_00=ref(F)(0)(0);			\ | ||||||
|     Chimu_00=ref()(0)(0);\ |   Chimu_01=ref(F)(0)(1);			\ | ||||||
|     Chimu_01=ref()(0)(1);\ |   Chimu_02=ref(F)(0)(2);			\ | ||||||
|     Chimu_02=ref()(0)(2);\ |   Chimu_10=ref(F)(1)(0);			\ | ||||||
|     Chimu_10=ref()(1)(0);\ |   Chimu_11=ref(F)(1)(1);			\ | ||||||
|     Chimu_11=ref()(1)(1);\ |   Chimu_12=ref(F)(1)(2);			\ | ||||||
|     Chimu_12=ref()(1)(2);\ |   Chimu_20=ref(F)(2)(0);			\ | ||||||
|     Chimu_20=ref()(2)(0);\ |   Chimu_21=ref(F)(2)(1);			\ | ||||||
|     Chimu_21=ref()(2)(1);\ |   Chimu_22=ref(F)(2)(2);			\ | ||||||
|     Chimu_22=ref()(2)(2);\ |   Chimu_30=ref(F)(3)(0);			\ | ||||||
|     Chimu_30=ref()(3)(0);\ |   Chimu_31=ref(F)(3)(1);			\ | ||||||
|     Chimu_31=ref()(3)(1);\ |   Chimu_32=ref(F)(3)(2) | ||||||
|     Chimu_32=ref()(3)(2);} |  | ||||||
|  |  | ||||||
| #define LOAD_CHI\ | #define LOAD_CHIMU(DIR,F,PERM)						\ | ||||||
|   {const SiteHalfSpinor &ref(buf[offset]);	\ |   { const SiteSpinor & ref (in._odata[offset]); LOAD_CHIMU_BODY(F); } | ||||||
|     Chi_00 = ref()(0)(0);\ |  | ||||||
|     Chi_01 = ref()(0)(1);\ | #define LOAD_CHI_BODY(F)				\ | ||||||
|     Chi_02 = ref()(0)(2);\ |     Chi_00 = ref(F)(0)(0);\ | ||||||
|     Chi_10 = ref()(1)(0);\ |     Chi_01 = ref(F)(0)(1);\ | ||||||
|     Chi_11 = ref()(1)(1);\ |     Chi_02 = ref(F)(0)(2);\ | ||||||
|     Chi_12 = ref()(1)(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 | // To splat or not to splat depends on the implementation | ||||||
| #define MULT_2SPIN(A)\ | #define MULT_2SPIN_BODY \ | ||||||
|   {auto & ref(U._odata[sU](A));			\ |  | ||||||
|   Impl::loadLinkElement(U_00,ref()(0,0));	\ |   Impl::loadLinkElement(U_00,ref()(0,0));	\ | ||||||
|   Impl::loadLinkElement(U_10,ref()(1,0));	\ |   Impl::loadLinkElement(U_10,ref()(1,0));	\ | ||||||
|   Impl::loadLinkElement(U_20,ref()(2,0));	\ |   Impl::loadLinkElement(U_20,ref()(2,0));	\ | ||||||
|   Impl::loadLinkElement(U_01,ref()(0,1));	\ |   Impl::loadLinkElement(U_01,ref()(0,1));	\ | ||||||
|   Impl::loadLinkElement(U_11,ref()(1,1));	\ |   Impl::loadLinkElement(U_11,ref()(1,1));	\ | ||||||
|   Impl::loadLinkElement(U_21,ref()(2,1));	\ |   Impl::loadLinkElement(U_21,ref()(2,1));	\ | ||||||
|     UChi_00 = U_00*Chi_00;\ |   UChi_00 = U_00*Chi_00;			\ | ||||||
|     UChi_10 = U_00*Chi_10;\ |   UChi_10 = U_00*Chi_10;			\ | ||||||
|     UChi_01 = U_10*Chi_00;\ |   UChi_01 = U_10*Chi_00;			\ | ||||||
|     UChi_11 = U_10*Chi_10;\ |   UChi_11 = U_10*Chi_10;			\ | ||||||
|     UChi_02 = U_20*Chi_00;\ |   UChi_02 = U_20*Chi_00;			\ | ||||||
|     UChi_12 = U_20*Chi_10;\ |   UChi_12 = U_20*Chi_10;			\ | ||||||
|     UChi_00+= U_01*Chi_01;\ |   UChi_00+= U_01*Chi_01;			\ | ||||||
|     UChi_10+= U_01*Chi_11;\ |   UChi_10+= U_01*Chi_11;			\ | ||||||
|     UChi_01+= U_11*Chi_01;\ |   UChi_01+= U_11*Chi_01;			\ | ||||||
|     UChi_11+= U_11*Chi_11;\ |   UChi_11+= U_11*Chi_11;			\ | ||||||
|     UChi_02+= U_21*Chi_01;\ |   UChi_02+= U_21*Chi_01;			\ | ||||||
|     UChi_12+= U_21*Chi_11;\ |   UChi_12+= U_21*Chi_11;			\ | ||||||
|   Impl::loadLinkElement(U_00,ref()(0,2));	\ |   Impl::loadLinkElement(U_00,ref()(0,2));	\ | ||||||
|   Impl::loadLinkElement(U_10,ref()(1,2));	\ |   Impl::loadLinkElement(U_10,ref()(1,2));	\ | ||||||
|   Impl::loadLinkElement(U_20,ref()(2,2));	\ |   Impl::loadLinkElement(U_20,ref()(2,2));	\ | ||||||
|     UChi_00+= U_00*Chi_02;\ |   UChi_00+= U_00*Chi_02;			\ | ||||||
|     UChi_10+= U_00*Chi_12;\ |   UChi_10+= U_00*Chi_12;			\ | ||||||
|     UChi_01+= U_10*Chi_02;\ |   UChi_01+= U_10*Chi_02;			\ | ||||||
|     UChi_11+= U_10*Chi_12;\ |   UChi_11+= U_10*Chi_12;			\ | ||||||
|     UChi_02+= U_20*Chi_02;\ |   UChi_02+= U_20*Chi_02;			\ | ||||||
|     UChi_12+= U_20*Chi_12;} |   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)			\ | #define PERMUTE_DIR(dir)			\ | ||||||
| @@ -307,84 +428,87 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | |||||||
|   result_31-= UChi_11;	\ |   result_31-= UChi_11;	\ | ||||||
|   result_32-= UChi_12; |   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);			\ |   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||||
|   offset = SE->_offset;				\ |   offset = SE->_offset;				\ | ||||||
|   local  = SE->_is_local;			\ |   local  = SE->_is_local;			\ | ||||||
|   perm   = SE->_permute;			\ |   perm   = SE->_permute;			\ | ||||||
|   if ( local ) {				\ |   if ( local ) {				\ | ||||||
|     LOAD_CHIMU;					\ |     LOAD_CHIMU_IMPL(DIR,F,PERM);			\ | ||||||
|     PROJ;					\ |     PROJ;					\ | ||||||
|     if ( perm) {				\ |     if ( perm) {				\ | ||||||
|       PERMUTE_DIR(PERM);			\ |       PERMUTE_DIR(PERM);			\ | ||||||
|     }						\ |     }						\ | ||||||
|   } else {					\ |   } else {					\ | ||||||
|     LOAD_CHI;					\ |     LOAD_CHI_IMPL(DIR,F,PERM);			\ | ||||||
|   }						\ |   }						\ | ||||||
|   MULT_2SPIN(DIR);				\ |   MULT_2SPIN_IMPL(DIR,F);			\ | ||||||
|   RECON;					 |   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);			\ |   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||||
|   offset = SE->_offset;				\ |   offset = SE->_offset;				\ | ||||||
|   local  = SE->_is_local;			\ |   local  = SE->_is_local;			\ | ||||||
|   perm   = SE->_permute;			\ |   perm   = SE->_permute;			\ | ||||||
|   if ( local ) {				\ |   if ( local ) {				\ | ||||||
|     LOAD_CHIMU;					\ |     LOAD_CHIMU_IMPL(DIR,F,PERM);			\ | ||||||
|     PROJ;					\ |     PROJ;					\ | ||||||
|     if ( perm) {				\ |     if ( perm) {				\ | ||||||
|       PERMUTE_DIR(PERM);			\ |       PERMUTE_DIR(PERM);			\ | ||||||
|     }						\ |     }						\ | ||||||
|   } else if ( st.same_node[DIR] ) {		\ |   } else if ( st.same_node[DIR] ) {		\ | ||||||
|     LOAD_CHI;					\ |     LOAD_CHI_IMPL(DIR,F,PERM);			\ | ||||||
|   }						\ |   }						\ | ||||||
|   if (local || st.same_node[DIR] ) {		\ |   if (local || st.same_node[DIR] ) {		\ | ||||||
|     MULT_2SPIN(DIR);				\ |     MULT_2SPIN_IMPL(DIR,F);			\ | ||||||
|     RECON;					\ |     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);			\ |   SE=st.GetEntry(ptype,DIR,ss);			\ | ||||||
|   offset = SE->_offset;				\ |   offset = SE->_offset;				\ | ||||||
|  |   local  = SE->_is_local;			\ | ||||||
|  |   perm   = SE->_permute;			\ | ||||||
|   if((!SE->_is_local)&&(!st.same_node[DIR]) ) {	\ |   if((!SE->_is_local)&&(!st.same_node[DIR]) ) {	\ | ||||||
|     LOAD_CHI;					\ |     LOAD_CHI_IMPL(DIR,F,PERM);			\ | ||||||
|     MULT_2SPIN(DIR);				\ |     MULT_2SPIN_IMPL(DIR,F);			\ | ||||||
|     RECON;					\ |     RECON;					\ | ||||||
|     nmu++;					\ |     nmu++;					\ | ||||||
|   } |   } | ||||||
|  |  | ||||||
| #define HAND_RESULT(ss)				\ | #define HAND_RESULT(ss,F)			\ | ||||||
|   {						\ |   {						\ | ||||||
|     SiteSpinor & ref (out._odata[ss]);		\ |     SiteSpinor & ref (out._odata[ss]);		\ | ||||||
|     vstream(ref()(0)(0),result_00);		\ |     vstream(ref(F)(0)(0),result_00);		\ | ||||||
|     vstream(ref()(0)(1),result_01);		\ |     vstream(ref(F)(0)(1),result_01);		\ | ||||||
|     vstream(ref()(0)(2),result_02);		\ |     vstream(ref(F)(0)(2),result_02);		\ | ||||||
|     vstream(ref()(1)(0),result_10);		\ |     vstream(ref(F)(1)(0),result_10);		\ | ||||||
|     vstream(ref()(1)(1),result_11);		\ |     vstream(ref(F)(1)(1),result_11);		\ | ||||||
|     vstream(ref()(1)(2),result_12);		\ |     vstream(ref(F)(1)(2),result_12);		\ | ||||||
|     vstream(ref()(2)(0),result_20);		\ |     vstream(ref(F)(2)(0),result_20);		\ | ||||||
|     vstream(ref()(2)(1),result_21);		\ |     vstream(ref(F)(2)(1),result_21);		\ | ||||||
|     vstream(ref()(2)(2),result_22);		\ |     vstream(ref(F)(2)(2),result_22);		\ | ||||||
|     vstream(ref()(3)(0),result_30);		\ |     vstream(ref(F)(3)(0),result_30);		\ | ||||||
|     vstream(ref()(3)(1),result_31);		\ |     vstream(ref(F)(3)(1),result_31);		\ | ||||||
|     vstream(ref()(3)(2),result_32);		\ |     vstream(ref(F)(3)(2),result_32);		\ | ||||||
|   } |   } | ||||||
|  |  | ||||||
| #define HAND_RESULT_EXT(ss)			\ | #define HAND_RESULT_EXT(ss,F)			\ | ||||||
|   if (nmu){					\ |   if (nmu){					\ | ||||||
|     SiteSpinor & ref (out._odata[ss]);		\ |     SiteSpinor & ref (out._odata[ss]);		\ | ||||||
|     ref()(0)(0)+=result_00;		\ |     ref(F)(0)(0)+=result_00;		\ | ||||||
|     ref()(0)(1)+=result_01;		\ |     ref(F)(0)(1)+=result_01;		\ | ||||||
|     ref()(0)(2)+=result_02;		\ |     ref(F)(0)(2)+=result_02;		\ | ||||||
|     ref()(1)(0)+=result_10;		\ |     ref(F)(1)(0)+=result_10;		\ | ||||||
|     ref()(1)(1)+=result_11;		\ |     ref(F)(1)(1)+=result_11;		\ | ||||||
|     ref()(1)(2)+=result_12;		\ |     ref(F)(1)(2)+=result_12;		\ | ||||||
|     ref()(2)(0)+=result_20;		\ |     ref(F)(2)(0)+=result_20;		\ | ||||||
|     ref()(2)(1)+=result_21;		\ |     ref(F)(2)(1)+=result_21;		\ | ||||||
|     ref()(2)(2)+=result_22;		\ |     ref(F)(2)(2)+=result_22;		\ | ||||||
|     ref()(3)(0)+=result_30;		\ |     ref(F)(3)(0)+=result_30;		\ | ||||||
|     ref()(3)(1)+=result_31;		\ |     ref(F)(3)(1)+=result_31;		\ | ||||||
|     ref()(3)(2)+=result_32;		\ |     ref(F)(3)(2)+=result_32;		\ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -463,15 +587,18 @@ WilsonKernels<Impl>::HandDhopSite(StencilImpl &st,LebesgueOrder &lo,DoubledGauge | |||||||
|   int offset,local,perm, ptype; |   int offset,local,perm, ptype; | ||||||
|   StencilEntry *SE; |   StencilEntry *SE; | ||||||
|  |  | ||||||
|   HAND_STENCIL_LEG(XM_PROJ,3,Xp,XM_RECON); | #define HAND_DOP_SITE(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||||
|   HAND_STENCIL_LEG(YM_PROJ,2,Yp,YM_RECON_ACCUM); |   HAND_STENCIL_LEG(XM_PROJ,3,Xp,XM_RECON,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(ZM_PROJ,1,Zp,ZM_RECON_ACCUM); |   HAND_STENCIL_LEG(YM_PROJ,2,Yp,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);	\ | ||||||
|   HAND_STENCIL_LEG(TM_PROJ,0,Tp,TM_RECON_ACCUM); |   HAND_STENCIL_LEG(ZM_PROJ,1,Zp,ZM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(XP_PROJ,3,Xm,XP_RECON_ACCUM); |   HAND_STENCIL_LEG(TM_PROJ,0,Tp,TM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(YP_PROJ,2,Ym,YP_RECON_ACCUM); |   HAND_STENCIL_LEG(XP_PROJ,3,Xm,XP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); |   HAND_STENCIL_LEG(YP_PROJ,2,Ym,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(TP_PROJ,0,Tm,TP_RECON_ACCUM); |   HAND_STENCIL_LEG(ZP_PROJ,1,Zm,ZP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_RESULT(ss); |   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> | template<class Impl> | ||||||
| @@ -486,15 +613,18 @@ void WilsonKernels<Impl>::HandDhopSiteDag(StencilImpl &st,LebesgueOrder &lo,Doub | |||||||
|   StencilEntry *SE; |   StencilEntry *SE; | ||||||
|   int offset,local,perm, ptype; |   int offset,local,perm, ptype; | ||||||
|  |  | ||||||
|   HAND_STENCIL_LEG(XP_PROJ,3,Xp,XP_RECON); | #define HAND_DOP_SITE_DAG(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||||
|   HAND_STENCIL_LEG(YP_PROJ,2,Yp,YP_RECON_ACCUM); |   HAND_STENCIL_LEG(XP_PROJ,3,Xp,XP_RECON,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(ZP_PROJ,1,Zp,ZP_RECON_ACCUM); |   HAND_STENCIL_LEG(YP_PROJ,2,Yp,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(TP_PROJ,0,Tp,TP_RECON_ACCUM); |   HAND_STENCIL_LEG(ZP_PROJ,1,Zp,ZP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(XM_PROJ,3,Xm,XM_RECON_ACCUM); |   HAND_STENCIL_LEG(TP_PROJ,0,Tp,TP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(YM_PROJ,2,Ym,YM_RECON_ACCUM); |   HAND_STENCIL_LEG(XM_PROJ,3,Xm,XM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); |   HAND_STENCIL_LEG(YM_PROJ,2,Ym,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_STENCIL_LEG(TM_PROJ,0,Tm,TM_RECON_ACCUM); |   HAND_STENCIL_LEG(ZM_PROJ,1,Zm,ZM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_RESULT(ss); |   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  | template<class Impl> void  | ||||||
| @@ -509,16 +639,20 @@ WilsonKernels<Impl>::HandDhopSiteInt(StencilImpl &st,LebesgueOrder &lo,DoubledGa | |||||||
|  |  | ||||||
|   int offset,local,perm, ptype; |   int offset,local,perm, ptype; | ||||||
|   StencilEntry *SE; |   StencilEntry *SE; | ||||||
|   ZERO_RESULT; |  | ||||||
|   HAND_STENCIL_LEG_INT(XM_PROJ,3,Xp,XM_RECON_ACCUM); | #define HAND_DOP_SITE_INT(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||||
|   HAND_STENCIL_LEG_INT(YM_PROJ,2,Yp,YM_RECON_ACCUM); |   ZERO_RESULT; \ | ||||||
|   HAND_STENCIL_LEG_INT(ZM_PROJ,1,Zp,ZM_RECON_ACCUM); |   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(TM_PROJ,0,Tp,TM_RECON_ACCUM); |   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(XP_PROJ,3,Xm,XP_RECON_ACCUM); |   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(YP_PROJ,2,Ym,YP_RECON_ACCUM); |   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(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); |   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(TP_PROJ,0,Tm,TP_RECON_ACCUM); |   HAND_STENCIL_LEG_INT(YP_PROJ,2,Ym,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_RESULT(ss); |   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> | template<class Impl> | ||||||
| @@ -532,16 +666,20 @@ void WilsonKernels<Impl>::HandDhopSiteDagInt(StencilImpl &st,LebesgueOrder &lo,D | |||||||
|  |  | ||||||
|   StencilEntry *SE; |   StencilEntry *SE; | ||||||
|   int offset,local,perm, ptype; |   int offset,local,perm, ptype; | ||||||
|   ZERO_RESULT; |  | ||||||
|   HAND_STENCIL_LEG_INT(XP_PROJ,3,Xp,XP_RECON_ACCUM); | #define HAND_DOP_SITE_DAG_INT(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL)				\ | ||||||
|   HAND_STENCIL_LEG_INT(YP_PROJ,2,Yp,YP_RECON_ACCUM); |   ZERO_RESULT;							\ | ||||||
|   HAND_STENCIL_LEG_INT(ZP_PROJ,1,Zp,ZP_RECON_ACCUM); |   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(TP_PROJ,0,Tp,TP_RECON_ACCUM); |   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(XM_PROJ,3,Xm,XM_RECON_ACCUM); |   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(YM_PROJ,2,Ym,YM_RECON_ACCUM); |   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(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); |   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(TM_PROJ,0,Tm,TM_RECON_ACCUM); |   HAND_STENCIL_LEG_INT(YM_PROJ,2,Ym,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL);		\ | ||||||
|   HAND_RESULT(ss); |   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  | template<class Impl> void  | ||||||
| @@ -557,16 +695,20 @@ WilsonKernels<Impl>::HandDhopSiteExt(StencilImpl &st,LebesgueOrder &lo,DoubledGa | |||||||
|   int offset,local,perm, ptype; |   int offset,local,perm, ptype; | ||||||
|   StencilEntry *SE; |   StencilEntry *SE; | ||||||
|   int nmu=0; |   int nmu=0; | ||||||
|   ZERO_RESULT; |  | ||||||
|   HAND_STENCIL_LEG_EXT(XM_PROJ,3,Xp,XM_RECON_ACCUM); | #define HAND_DOP_SITE_EXT(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||||
|   HAND_STENCIL_LEG_EXT(YM_PROJ,2,Yp,YM_RECON_ACCUM); |   ZERO_RESULT; \ | ||||||
|   HAND_STENCIL_LEG_EXT(ZM_PROJ,1,Zp,ZM_RECON_ACCUM); |   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(TM_PROJ,0,Tp,TM_RECON_ACCUM); |   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(XP_PROJ,3,Xm,XP_RECON_ACCUM); |   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(YP_PROJ,2,Ym,YP_RECON_ACCUM); |   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(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); |   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(TP_PROJ,0,Tm,TP_RECON_ACCUM); |   HAND_STENCIL_LEG_EXT(YP_PROJ,2,Ym,YP_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_RESULT_EXT(ss); |   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> | template<class Impl> | ||||||
| @@ -581,16 +723,20 @@ void WilsonKernels<Impl>::HandDhopSiteDagExt(StencilImpl &st,LebesgueOrder &lo,D | |||||||
|   StencilEntry *SE; |   StencilEntry *SE; | ||||||
|   int offset,local,perm, ptype; |   int offset,local,perm, ptype; | ||||||
|   int nmu=0; |   int nmu=0; | ||||||
|   ZERO_RESULT; |  | ||||||
|   HAND_STENCIL_LEG_EXT(XP_PROJ,3,Xp,XP_RECON_ACCUM); | #define HAND_DOP_SITE_DAG_EXT(F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL) \ | ||||||
|   HAND_STENCIL_LEG_EXT(YP_PROJ,2,Yp,YP_RECON_ACCUM); |   ZERO_RESULT; \ | ||||||
|   HAND_STENCIL_LEG_EXT(ZP_PROJ,1,Zp,ZP_RECON_ACCUM); |   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(TP_PROJ,0,Tp,TP_RECON_ACCUM); |   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(XM_PROJ,3,Xm,XM_RECON_ACCUM); |   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(YM_PROJ,2,Ym,YM_RECON_ACCUM); |   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(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); |   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(TM_PROJ,0,Tm,TM_RECON_ACCUM); |   HAND_STENCIL_LEG_EXT(YM_PROJ,2,Ym,YM_RECON_ACCUM,F,LOAD_CHI_IMPL,LOAD_CHIMU_IMPL,MULT_2SPIN_IMPL); \ | ||||||
|   HAND_RESULT_EXT(ss); |   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,10 +792,123 @@ void WilsonKernels<Impl>::HandDhopSiteDagExt(StencilImpl &st,LebesgueOrder &lo,D | |||||||
| 				    const FermionField &in,		\ | 				    const FermionField &in,		\ | ||||||
| 				    FermionField &out){ assert(0); }	\ | 				    FermionField &out){ assert(0); }	\ | ||||||
|  |  | ||||||
|   HAND_SPECIALISE_EMPTY(GparityWilsonImplF); |  | ||||||
|   HAND_SPECIALISE_EMPTY(GparityWilsonImplD); |  | ||||||
|   HAND_SPECIALISE_EMPTY(GparityWilsonImplFH); | #define HAND_SPECIALISE_GPARITY(IMPL)					\ | ||||||
|   HAND_SPECIALISE_EMPTY(GparityWilsonImplDF); |   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 ///////////////////// | ////////////// Wilson ; uses this implementation ///////////////////// | ||||||
|  |  | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ namespace Grid{ | |||||||
|     //         (Moe Moo)    (Moe Mee^-1    1 )   (0   Moo-Moe Mee^-1 Meo)  (0   1         ) |     //         (Moe Moo)    (Moe Mee^-1    1 )   (0   Moo-Moe Mee^-1 Meo)  (0   1         ) | ||||||
|     // |     // | ||||||
|     // Determinant is det of middle factor |     // Determinant is det of middle factor | ||||||
|     // This assumes Mee is indept of U. |     // NOTICE: This assumes Mee is indept of U in computing the derivative | ||||||
|     // |     // | ||||||
|     template<class Impl> |     template<class Impl> | ||||||
|     class SchurDifferentiableOperator :  public SchurDiagMooeeOperator<FermionOperator<Impl>,typename Impl::FermionField>  |     class SchurDifferentiableOperator :  public SchurDiagMooeeOperator<FermionOperator<Impl>,typename Impl::FermionField>  | ||||||
|   | |||||||
							
								
								
									
										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/OneFlavourRationalRatio.h> | ||||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRational.h> | #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRational.h> | ||||||
| #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRationalRatio.h> | #include <Grid/qcd/action/pseudofermion/OneFlavourEvenOddRationalRatio.h> | ||||||
|  | #include <Grid/qcd/action/pseudofermion/ExactOneFlavourRatio.h> | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -202,6 +202,39 @@ class DomainWallFermionModule: public FermionOperatorModule<DomainWallFermion, F | |||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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 | } // QCD | ||||||
| } // Grid | } // Grid | ||||||
|   | |||||||
							
								
								
									
										209
									
								
								lib/qcd/utils/CovariantAdjointLaplacian.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								lib/qcd/utils/CovariantAdjointLaplacian.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | |||||||
|  | /************************************************************************************* | ||||||
|  |  | ||||||
|  | Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  | Source file: ./lib/qcd/action/scalar/CovariantAdjointLaplacian.h | ||||||
|  |  | ||||||
|  | Copyright (C) 2016 | ||||||
|  |  | ||||||
|  | Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||||
|  |  | ||||||
|  | This program is free software; you can redistribute it and/or modify | ||||||
|  | it under the terms of the GNU General Public License as published by | ||||||
|  | the Free Software Foundation; either version 2 of the License, or | ||||||
|  | (at your option) any later version. | ||||||
|  |  | ||||||
|  | This program is distributed in the hope that it will be useful, | ||||||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | GNU General Public License for more details. | ||||||
|  |  | ||||||
|  | You should have received a copy of the GNU General Public License along | ||||||
|  | with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|  | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  |  | ||||||
|  | See the full license in the file "LICENSE" in the top level distribution | ||||||
|  | directory | ||||||
|  | *************************************************************************************/ | ||||||
|  | /*  END LEGAL */ | ||||||
|  |  | ||||||
|  | #ifndef COVARIANT_ADJOINT_LAPLACIAN_H | ||||||
|  | #define COVARIANT_ADJOINT_LAPLACIAN_H | ||||||
|  |  | ||||||
|  | namespace Grid | ||||||
|  | { | ||||||
|  | namespace QCD | ||||||
|  | { | ||||||
|  |  | ||||||
|  | struct LaplacianParams : Serializable | ||||||
|  | { | ||||||
|  |   GRID_SERIALIZABLE_CLASS_MEMBERS(LaplacianParams, | ||||||
|  |                                   RealD, lo, | ||||||
|  |                                   RealD, hi, | ||||||
|  |                                   int, MaxIter, | ||||||
|  |                                   RealD, tolerance, | ||||||
|  |                                   int, degree, | ||||||
|  |                                   int, precision); | ||||||
|  |  | ||||||
|  |   // constructor | ||||||
|  |   LaplacianParams(RealD lo = 0.0, | ||||||
|  |                   RealD hi = 1.0, | ||||||
|  |                   int maxit = 1000, | ||||||
|  |                   RealD tol = 1.0e-8, | ||||||
|  |                   int degree = 10, | ||||||
|  |                   int precision = 64) | ||||||
|  |       : lo(lo), | ||||||
|  |         hi(hi), | ||||||
|  |         MaxIter(maxit), | ||||||
|  |         tolerance(tol), | ||||||
|  |         degree(degree), | ||||||
|  |         precision(precision){}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////// | ||||||
|  | // Laplacian operator L on adjoint fields | ||||||
|  | // | ||||||
|  | // phi: adjoint field | ||||||
|  | // L: D_mu^dag D_mu | ||||||
|  | // | ||||||
|  | // L phi(x) = Sum_mu [ U_mu(x)phi(x+mu)U_mu(x)^dag + | ||||||
|  | //                     U_mu(x-mu)^dag phi(x-mu)U_mu(x-mu) | ||||||
|  | //                     -2phi(x)] | ||||||
|  | // | ||||||
|  | // Operator designed to be encapsulated by | ||||||
|  | // an HermitianLinearOperator<.. , ..> | ||||||
|  | //////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  | template <class Impl> | ||||||
|  | class LaplacianAdjointField : public Metric<typename Impl::Field> | ||||||
|  | { | ||||||
|  |   OperatorFunction<typename Impl::Field> &Solver; | ||||||
|  |   LaplacianParams param; | ||||||
|  |   MultiShiftFunction PowerHalf; | ||||||
|  |   MultiShiftFunction PowerInvHalf; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |   INHERIT_GIMPL_TYPES(Impl); | ||||||
|  |  | ||||||
|  |   LaplacianAdjointField(GridBase *grid, OperatorFunction<GaugeField> &S, LaplacianParams &p, const RealD k = 1.0) | ||||||
|  |       : U(Nd, grid), Solver(S), param(p), kappa(k) | ||||||
|  |   { | ||||||
|  |     AlgRemez remez(param.lo, param.hi, param.precision); | ||||||
|  |     std::cout << GridLogMessage << "Generating degree " << param.degree << " for x^(1/2)" << std::endl; | ||||||
|  |     remez.generateApprox(param.degree, 1, 2); | ||||||
|  |     PowerHalf.Init(remez, param.tolerance, false); | ||||||
|  |     PowerInvHalf.Init(remez, param.tolerance, true); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   void Mdir(const GaugeField &, GaugeField &, int, int) { assert(0); } | ||||||
|  |   void Mdiag(const GaugeField &, GaugeField &) { assert(0); } | ||||||
|  |  | ||||||
|  |   void ImportGauge(const GaugeField &_U) | ||||||
|  |   { | ||||||
|  |     for (int mu = 0; mu < Nd; mu++) | ||||||
|  |     { | ||||||
|  |       U[mu] = PeekIndex<LorentzIndex>(_U, mu); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void M(const GaugeField &in, GaugeField &out) | ||||||
|  |   { | ||||||
|  |     // in is an antihermitian matrix | ||||||
|  |     // test | ||||||
|  |     //GaugeField herm = in + adj(in); | ||||||
|  |     //std::cout << "AHermiticity: " << norm2(herm) << std::endl; | ||||||
|  |  | ||||||
|  |     GaugeLinkField tmp(in._grid); | ||||||
|  |     GaugeLinkField tmp2(in._grid); | ||||||
|  |     GaugeLinkField sum(in._grid); | ||||||
|  |  | ||||||
|  |     for (int nu = 0; nu < Nd; nu++) | ||||||
|  |     { | ||||||
|  |       sum = zero; | ||||||
|  |       GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu); | ||||||
|  |       GaugeLinkField out_nu(out._grid); | ||||||
|  |       for (int mu = 0; mu < Nd; mu++) | ||||||
|  |       { | ||||||
|  |         tmp = U[mu] * Cshift(in_nu, mu, +1) * adj(U[mu]); | ||||||
|  |         tmp2 = adj(U[mu]) * in_nu * U[mu]; | ||||||
|  |         sum += tmp + Cshift(tmp2, mu, -1) - 2.0 * in_nu; | ||||||
|  |       } | ||||||
|  |       out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum; | ||||||
|  |       PokeIndex<LorentzIndex>(out, out_nu, nu); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void MDeriv(const GaugeField &in, GaugeField &der) | ||||||
|  |   { | ||||||
|  |     // in is anti-hermitian | ||||||
|  |     RealD factor = -kappa / (double(4 * Nd)); | ||||||
|  |  | ||||||
|  |     for (int mu = 0; mu < Nd; mu++) | ||||||
|  |     { | ||||||
|  |       GaugeLinkField der_mu(der._grid); | ||||||
|  |       der_mu = zero; | ||||||
|  |       for (int nu = 0; nu < Nd; nu++) | ||||||
|  |       { | ||||||
|  |         GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu); | ||||||
|  |         der_mu += U[mu] * Cshift(in_nu, mu, 1) * adj(U[mu]) * in_nu; | ||||||
|  |       } | ||||||
|  |       // the minus sign comes by using the in_nu instead of the | ||||||
|  |       // adjoint in the last multiplication | ||||||
|  |       PokeIndex<LorentzIndex>(der, -2.0 * factor * der_mu, mu); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // separating this temporarily | ||||||
|  |   void MDeriv(const GaugeField &left, const GaugeField &right, | ||||||
|  |               GaugeField &der) | ||||||
|  |   { | ||||||
|  |     // in is anti-hermitian | ||||||
|  |     RealD factor = -kappa / (double(4 * Nd)); | ||||||
|  |  | ||||||
|  |     for (int mu = 0; mu < Nd; mu++) | ||||||
|  |     { | ||||||
|  |       GaugeLinkField der_mu(der._grid); | ||||||
|  |       der_mu = zero; | ||||||
|  |       for (int nu = 0; nu < Nd; nu++) | ||||||
|  |       { | ||||||
|  |         GaugeLinkField left_nu = PeekIndex<LorentzIndex>(left, nu); | ||||||
|  |         GaugeLinkField right_nu = PeekIndex<LorentzIndex>(right, nu); | ||||||
|  |         der_mu += U[mu] * Cshift(left_nu, mu, 1) * adj(U[mu]) * right_nu; | ||||||
|  |         der_mu += U[mu] * Cshift(right_nu, mu, 1) * adj(U[mu]) * left_nu; | ||||||
|  |       } | ||||||
|  |       PokeIndex<LorentzIndex>(der, -factor * der_mu, mu); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void Minv(const GaugeField &in, GaugeField &inverted) | ||||||
|  |   { | ||||||
|  |     HermitianLinearOperator<LaplacianAdjointField<Impl>, GaugeField> HermOp(*this); | ||||||
|  |     Solver(HermOp, in, inverted); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void MSquareRoot(GaugeField &P) | ||||||
|  |   { | ||||||
|  |     GaugeField Gp(P._grid); | ||||||
|  |     HermitianLinearOperator<LaplacianAdjointField<Impl>, GaugeField> HermOp(*this); | ||||||
|  |     ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter, PowerHalf); | ||||||
|  |     msCG(HermOp, P, Gp); | ||||||
|  |     P = Gp; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void MInvSquareRoot(GaugeField &P) | ||||||
|  |   { | ||||||
|  |     GaugeField Gp(P._grid); | ||||||
|  |     HermitianLinearOperator<LaplacianAdjointField<Impl>, GaugeField> HermOp(*this); | ||||||
|  |     ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter, PowerInvHalf); | ||||||
|  |     msCG(HermOp, P, Gp); | ||||||
|  |     P = Gp; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |   RealD kappa; | ||||||
|  |   std::vector<GaugeLinkField> U; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // QCD | ||||||
|  | } // Grid | ||||||
|  | #endif | ||||||
| @@ -4,7 +4,7 @@ Grid physics library, www.github.com/paboyle/Grid | |||||||
|  |  | ||||||
| Source file: ./lib/qcd/action/scalar/CovariantLaplacian.h | Source file: ./lib/qcd/action/scalar/CovariantLaplacian.h | ||||||
|  |  | ||||||
| Copyright (C) 2016 | Copyright (C) 2017 | ||||||
|  |  | ||||||
| Author: Guido Cossu <guido.cossu@ed.ac.uk> | Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||||
|  |  | ||||||
| @@ -30,168 +30,57 @@ directory | |||||||
| #ifndef COVARIANT_LAPLACIAN_H | #ifndef COVARIANT_LAPLACIAN_H | ||||||
| #define COVARIANT_LAPLACIAN_H | #define COVARIANT_LAPLACIAN_H | ||||||
|  |  | ||||||
| namespace Grid { | namespace Grid | ||||||
| namespace QCD { | { | ||||||
|  | namespace QCD | ||||||
| struct LaplacianParams : Serializable { | { | ||||||
|   GRID_SERIALIZABLE_CLASS_MEMBERS(LaplacianParams,  |  | ||||||
|                                   RealD, lo,  |  | ||||||
|                                   RealD, hi,  |  | ||||||
|                                   int,   MaxIter,  |  | ||||||
|                                   RealD, tolerance,  |  | ||||||
|                                   int,   degree,  |  | ||||||
|                                   int,   precision); |  | ||||||
|    |  | ||||||
|   // constructor  |  | ||||||
|   LaplacianParams(RealD lo      = 0.0,  |  | ||||||
|                   RealD hi      = 1.0,  |  | ||||||
|                   int maxit     = 1000, |  | ||||||
|                   RealD tol     = 1.0e-8,  |  | ||||||
|                   int degree    = 10, |  | ||||||
|                   int precision = 64) |  | ||||||
|     : lo(lo), |  | ||||||
|       hi(hi), |  | ||||||
|       MaxIter(maxit), |  | ||||||
|       tolerance(tol), |  | ||||||
|       degree(degree), |  | ||||||
|       precision(precision){}; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////// | ||||||
| // Laplacian operator L on adjoint fields | // Laplacian operator L on fermion fields | ||||||
| // | // | ||||||
| // phi: adjoint field | // phi: fermion field | ||||||
| // L: D_mu^dag D_mu |  | ||||||
| // | // | ||||||
| // L phi(x) = Sum_mu [ U_mu(x)phi(x+mu)U_mu(x)^dag +  | // L phi(x) = Sum_mu [ U_mu(x) phi(x+mu) + U_mu(x-mu) phi(x-mu) - 2phi(x)] | ||||||
| //                     U_mu(x-mu)^dag phi(x-mu)U_mu(x-mu) |  | ||||||
| //                     -2phi(x)] |  | ||||||
| // | // | ||||||
| // Operator designed to be encapsulated by | // Operator designed to be encapsulated by | ||||||
| // an HermitianLinearOperator<.. , ..> | // an HermitianLinearOperator<.. , ..> | ||||||
| //////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
|  | // has to inherit from a fermion implementation | ||||||
| template <class Impl> | template <class Impl> | ||||||
| class LaplacianAdjointField: public Metric<typename Impl::Field> { | class Laplacian | ||||||
|   OperatorFunction<typename Impl::Field> &Solver; | { | ||||||
|   LaplacianParams param; | public: | ||||||
|   MultiShiftFunction PowerHalf;     |   INHERIT_IMPL_TYPES(Impl); | ||||||
|   MultiShiftFunction PowerInvHalf;     |  | ||||||
|  |  | ||||||
|  public: |   // add a bool to smear only in the spatial directions | ||||||
|   INHERIT_GIMPL_TYPES(Impl); |   Laplacian(GridBase *grid, bool spatial = false) | ||||||
|  |       : U(Nd, grid), spatial_laplacian(spatial){}; | ||||||
|  |  | ||||||
|   LaplacianAdjointField(GridBase* grid, OperatorFunction<GaugeField>& S, LaplacianParams& p, const RealD k = 1.0) |   void Mdir(const FermionField &, FermionField &, int, int) { assert(0); } | ||||||
|       : U(Nd, grid), Solver(S), param(p), kappa(k){ |   void Mdiag(const FermionField &, FermionField &) { assert(0); } | ||||||
|         AlgRemez remez(param.lo,param.hi,param.precision); |  | ||||||
|         std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl; |  | ||||||
|         remez.generateApprox(param.degree,1,2); |  | ||||||
|         PowerHalf.Init(remez,param.tolerance,false); |  | ||||||
|         PowerInvHalf.Init(remez,param.tolerance,true); |  | ||||||
|  |  | ||||||
|  |   void ImportGauge(const GaugeField &_U) | ||||||
|       }; |   { | ||||||
|  |     for (int mu = 0; mu < Nd; mu++) | ||||||
|   void Mdir(const GaugeField&, GaugeField&, int, int){ assert(0);} |  | ||||||
|   void Mdiag(const GaugeField&, GaugeField&){ assert(0);} |  | ||||||
|  |  | ||||||
|   void ImportGauge(const GaugeField& _U) { |  | ||||||
|     for (int mu = 0; mu < Nd; mu++) { |  | ||||||
|       U[mu] = PeekIndex<LorentzIndex>(_U, mu); |       U[mu] = PeekIndex<LorentzIndex>(_U, mu); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void M(const FermionField &in, FermionField &out) | ||||||
|  |   { | ||||||
|  |     int dims = spatial_laplacian ? (Nd - 1) : Nd; | ||||||
|  |  | ||||||
|  |     out = -2.0 * dims * in; | ||||||
|  |     // eventually speed up with the stencil operator, if necessary | ||||||
|  |     for (int mu = 0; mu < dims; mu++) | ||||||
|  |       out += Impl::CovShiftForward(U[mu], mu, in) + Impl::CovShiftBackward(U[mu], mu, in); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void M(const GaugeField& in, GaugeField& out) { | private: | ||||||
|     // in is an antihermitian matrix |   bool spatial_laplacian; | ||||||
|     // test |  | ||||||
|     //GaugeField herm = in + adj(in); |  | ||||||
|     //std::cout << "AHermiticity: " << norm2(herm) << std::endl; |  | ||||||
|  |  | ||||||
|     GaugeLinkField tmp(in._grid); |  | ||||||
|     GaugeLinkField tmp2(in._grid); |  | ||||||
|     GaugeLinkField sum(in._grid); |  | ||||||
|  |  | ||||||
|     for (int nu = 0; nu < Nd; nu++) { |  | ||||||
|       sum = zero; |  | ||||||
|       GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu); |  | ||||||
|       GaugeLinkField out_nu(out._grid); |  | ||||||
|       for (int mu = 0; mu < Nd; mu++) { |  | ||||||
|         tmp = U[mu] * Cshift(in_nu, mu, +1) * adj(U[mu]); |  | ||||||
|         tmp2 = adj(U[mu]) * in_nu * U[mu]; |  | ||||||
|         sum += tmp + Cshift(tmp2, mu, -1) - 2.0 * in_nu; |  | ||||||
|       } |  | ||||||
|       out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum; |  | ||||||
|       PokeIndex<LorentzIndex>(out, out_nu, nu); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void MDeriv(const GaugeField& in, GaugeField& der) { |  | ||||||
|     // in is anti-hermitian |  | ||||||
|     RealD factor = -kappa / (double(4 * Nd)); |  | ||||||
|      |  | ||||||
|     for (int mu = 0; mu < Nd; mu++){ |  | ||||||
|       GaugeLinkField der_mu(der._grid); |  | ||||||
|       der_mu = zero; |  | ||||||
|       for (int nu = 0; nu < Nd; nu++){ |  | ||||||
|         GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu); |  | ||||||
|         der_mu += U[mu] * Cshift(in_nu, mu, 1) * adj(U[mu]) * in_nu; |  | ||||||
|       } |  | ||||||
|       // the minus sign comes by using the in_nu instead of the |  | ||||||
|       // adjoint in the last multiplication |  | ||||||
|       PokeIndex<LorentzIndex>(der,  -2.0 * factor * der_mu, mu); |  | ||||||
|     }  |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // separating this temporarily |  | ||||||
|   void MDeriv(const GaugeField& left, const GaugeField& right, |  | ||||||
|               GaugeField& der) { |  | ||||||
|     // in is anti-hermitian |  | ||||||
|     RealD factor = -kappa / (double(4 * Nd)); |  | ||||||
|  |  | ||||||
|     for (int mu = 0; mu < Nd; mu++) { |  | ||||||
|       GaugeLinkField der_mu(der._grid); |  | ||||||
|       der_mu = zero; |  | ||||||
|       for (int nu = 0; nu < Nd; nu++) { |  | ||||||
|         GaugeLinkField left_nu = PeekIndex<LorentzIndex>(left, nu); |  | ||||||
|         GaugeLinkField right_nu = PeekIndex<LorentzIndex>(right, nu); |  | ||||||
|         der_mu += U[mu] * Cshift(left_nu, mu, 1) * adj(U[mu]) * right_nu; |  | ||||||
|         der_mu += U[mu] * Cshift(right_nu, mu, 1) * adj(U[mu]) * left_nu; |  | ||||||
|       } |  | ||||||
|       PokeIndex<LorentzIndex>(der, -factor * der_mu, mu); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void Minv(const GaugeField& in, GaugeField& inverted){ |  | ||||||
|     HermitianLinearOperator<LaplacianAdjointField<Impl>,GaugeField> HermOp(*this); |  | ||||||
|     Solver(HermOp, in, inverted); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void MSquareRoot(GaugeField& P){ |  | ||||||
|     GaugeField Gp(P._grid); |  | ||||||
|     HermitianLinearOperator<LaplacianAdjointField<Impl>,GaugeField> HermOp(*this); |  | ||||||
|     ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerHalf); |  | ||||||
|     msCG(HermOp,P,Gp); |  | ||||||
|     P = Gp;  |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void MInvSquareRoot(GaugeField& P){ |  | ||||||
|     GaugeField Gp(P._grid); |  | ||||||
|     HermitianLinearOperator<LaplacianAdjointField<Impl>,GaugeField> HermOp(*this); |  | ||||||
|     ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerInvHalf); |  | ||||||
|     msCG(HermOp,P,Gp); |  | ||||||
|     P = Gp;  |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   RealD kappa; |  | ||||||
|   std::vector<GaugeLinkField> U; |   std::vector<GaugeLinkField> U; | ||||||
| }; | }; // Laplacian | ||||||
|  |  | ||||||
| } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | } // QCD | ||||||
|  | } // Grid | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -60,7 +60,7 @@ GridCartesian         *SpaceTimeGrid::makeFiveDimGrid(int Ls,const GridCartesian | |||||||
|     simd5.push_back(FourDimGrid->_simd_layout[d]); |     simd5.push_back(FourDimGrid->_simd_layout[d]); | ||||||
|      mpi5.push_back(FourDimGrid->_processors[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 N4=FourDimGrid->_ndimension; | ||||||
|   int cbd=1; |   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); |   std::vector<int>   cb5(1,0); | ||||||
|      |  | ||||||
|   for(int d=0;d<N4;d++){ |   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); |       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); |     simd5.push_back(1); | ||||||
|      mpi5.push_back(FourDimGrid->_processors[d]); |      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) | GridRedBlackCartesian *SpaceTimeGrid::makeFiveDimDWFRedBlackGrid(int Ls,const GridCartesian *FourDimGrid) | ||||||
| { | { | ||||||
|   int N4=FourDimGrid->_ndimension; |   int N4=FourDimGrid->_ndimension; | ||||||
|   int nsimd = FourDimGrid->Nsimd(); |  | ||||||
|   int cbd=1; |   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); |   std::vector<int>   cb5(1,0); | ||||||
|      |  | ||||||
|   for(int d=0;d<N4;d++){ |   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); |       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; |                                       or element<T>::is_number; | ||||||
|   }; |   }; | ||||||
|    |    | ||||||
|   // Vector flatening utility class //////////////////////////////////////////// |   // Vector flattening utility class //////////////////////////////////////////// | ||||||
|   // Class to flatten a multidimensional std::vector |   // Class to flatten a multidimensional std::vector | ||||||
|   template <typename V> |   template <typename V> | ||||||
|   class Flatten |   class Flatten | ||||||
|   | |||||||
| @@ -42,6 +42,7 @@ JSONWriter::~JSONWriter(void) | |||||||
|  |  | ||||||
|   // write prettified JSON to file |   // write prettified JSON to file | ||||||
|   std::ofstream os(fileName_); |   std::ofstream os(fileName_); | ||||||
|  |   //std::cout << "JSONWriter::~JSONWriter" << std::endl; | ||||||
|   os << std::setw(2) << json::parse(ss_.str()) << 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) | void JSONWriter::pop(void) | ||||||
| { | { | ||||||
|  |   //std::cout << "JSONWriter::pop" << std::endl; | ||||||
|   delete_comma(); |   delete_comma(); | ||||||
|   ss_ << "},"; |   ss_ << "},"; | ||||||
| } | } | ||||||
| @@ -67,20 +69,22 @@ void JSONWriter::delete_comma() | |||||||
|   ss_.str(dlast); |   ss_.str(dlast); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| // here we are hitting a g++ bug (Bug 56480) | // here we are hitting a g++ bug (Bug 56480) | ||||||
| // compiles fine with clang | // compiles fine with clang | ||||||
| // have to wrap in the Grid namespace | // have to wrap in the Grid namespace | ||||||
| // annoying, but necessary for TravisCI | // annoying, but necessary for TravisCI | ||||||
| namespace Grid | 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()) |     if (s.size()) | ||||||
|       ss_ << "\""<< s << "\" : \"" << x << "\" ," ;  |       ss_ << "\""<< s << "\" : \"" << os.str() << "\" ," ; | ||||||
|     else |     else | ||||||
|       ss_ << "\"" << x << "\" ," ; |      ss_ << os.str() << " ," ; | ||||||
|   } |   } | ||||||
| }// namespace Grid  | }// namespace Grid  | ||||||
|  |  | ||||||
| @@ -138,6 +142,7 @@ void JSONReader::pop(void) | |||||||
|  |  | ||||||
| bool JSONReader::nextElement(const std::string &s) | bool JSONReader::nextElement(const std::string &s) | ||||||
| { | { | ||||||
|  |   // Work in progress | ||||||
|   // JSON dictionaries do not support multiple names  |   // JSON dictionaries do not support multiple names  | ||||||
|   // Same name objects must be packed in vectors |   // Same name objects must be packed in vectors | ||||||
|   ++it_; |   ++it_; | ||||||
|   | |||||||
| @@ -58,10 +58,15 @@ namespace Grid | |||||||
|     void writeDefault(const std::string &s, const std::complex<U> &x); |     void writeDefault(const std::string &s, const std::complex<U> &x); | ||||||
|     template <typename U> |     template <typename U> | ||||||
|     void writeDefault(const std::string &s, const std::vector<U> &x); |     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> |     template<std::size_t N> | ||||||
|     void writeDefault(const std::string &s, const char(&x)[N]); |     void writeDefault(const std::string &s, const char(&x)[N]); | ||||||
|  |  | ||||||
|  |     void writeDefault(const std::string &s, const std::string &x); | ||||||
|  |  | ||||||
|  |  | ||||||
|   private: |   private: | ||||||
|     void delete_comma(); |     void delete_comma(); | ||||||
|     std::string         fileName_; |     std::string         fileName_; | ||||||
| @@ -82,6 +87,8 @@ namespace Grid | |||||||
|     void readDefault(const std::string &s, std::complex<U> &output); |     void readDefault(const std::string &s, std::complex<U> &output); | ||||||
|     template <typename U> |     template <typename U> | ||||||
|     void readDefault(const std::string &s, std::vector<U> &output); |     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: |   private: | ||||||
|     json                jobject_; // main object |     json                jobject_; // main object | ||||||
|     json                jcur_;  // current json object |     json                jcur_;  // current json object | ||||||
| @@ -106,7 +113,7 @@ namespace Grid | |||||||
|   template <typename U> |   template <typename U> | ||||||
|   void JSONWriter::writeDefault(const std::string &s, const U &x) |   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; |     std::ostringstream os; | ||||||
|     os << std::boolalpha << x; |     os << std::boolalpha << x; | ||||||
|     if (s.size()) |     if (s.size()) | ||||||
| @@ -118,7 +125,7 @@ namespace Grid | |||||||
|   template <typename U> |   template <typename U> | ||||||
|   void JSONWriter::writeDefault(const std::string &s, const std::complex<U> &x) |   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; |     std::ostringstream os; | ||||||
|     os << "["<< std::boolalpha << x.real() << ", " << x.imag() << "]"; |     os << "["<< std::boolalpha << x.real() << ", " << x.imag() << "]"; | ||||||
|     if (s.size()) |     if (s.size()) | ||||||
| @@ -127,10 +134,22 @@ namespace Grid | |||||||
|      ss_ << os.str() << " ," ; |      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> |   template <typename U> | ||||||
|   void JSONWriter::writeDefault(const std::string &s, const std::vector<U> &x) |   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()) |     if (s.size()) | ||||||
|       ss_ << " \""<<s<<"\" : ["; |       ss_ << " \""<<s<<"\" : ["; | ||||||
| @@ -146,7 +165,7 @@ namespace Grid | |||||||
|  |  | ||||||
|   template<std::size_t N> |   template<std::size_t N> | ||||||
|   void JSONWriter::writeDefault(const std::string &s, const char(&x)[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()) |     if (s.size()) | ||||||
|       ss_ << "\""<< s << "\" : \"" << x << "\" ," ; |       ss_ << "\""<< s << "\" : \"" << x << "\" ," ; | ||||||
| @@ -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> |   template <typename U> | ||||||
|   void JSONReader::readDefault(const std::string &s, std::complex<U> &output) |   void JSONReader::readDefault(const std::string &s, std::complex<U> &output) | ||||||
|   { |   { | ||||||
|     U tmp1, tmp2; |     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 j = jcur_; | ||||||
|     json::iterator it = j.begin(); |     json::iterator it = j.begin(); | ||||||
|     jcur_ = *it; |     jcur_ = *it; | ||||||
|   | |||||||
| @@ -82,11 +82,11 @@ namespace Optimization { | |||||||
|       double tmp[2]={a,b}; |       double tmp[2]={a,b}; | ||||||
|       return vld1q_f64(tmp); |       return vld1q_f64(tmp); | ||||||
|     } |     } | ||||||
|     //Real double // N:tbc |     //Real double | ||||||
|     inline float64x2_t operator()(double a){ |     inline float64x2_t operator()(double a){ | ||||||
|       return vdupq_n_f64(a); |       return vdupq_n_f64(a); | ||||||
|     } |     } | ||||||
|     //Integer // N:tbc |     //Integer | ||||||
|     inline uint32x4_t operator()(Integer a){ |     inline uint32x4_t operator()(Integer a){ | ||||||
|       return vdupq_n_u32(a); |       return vdupq_n_u32(a); | ||||||
|     } |     } | ||||||
| @@ -124,33 +124,32 @@ namespace Optimization { | |||||||
|   // Nils: Vset untested; not used currently in Grid at all; |   // Nils: Vset untested; not used currently in Grid at all; | ||||||
|   // git commit 4a8c4ccfba1d05159348d21a9698028ea847e77b |   // git commit 4a8c4ccfba1d05159348d21a9698028ea847e77b | ||||||
|   struct Vset{ |   struct Vset{ | ||||||
|     // Complex float // N:ok |     // Complex float | ||||||
|     inline float32x4_t operator()(Grid::ComplexF *a){ |     inline float32x4_t operator()(Grid::ComplexF *a){ | ||||||
|       float tmp[4]={a[1].imag(),a[1].real(),a[0].imag(),a[0].real()}; |       float tmp[4]={a[1].imag(),a[1].real(),a[0].imag(),a[0].real()}; | ||||||
|       return vld1q_f32(tmp); |       return vld1q_f32(tmp); | ||||||
|     } |     } | ||||||
|     // Complex double // N:ok |     // Complex double | ||||||
|     inline float64x2_t operator()(Grid::ComplexD *a){ |     inline float64x2_t operator()(Grid::ComplexD *a){ | ||||||
|       double tmp[2]={a[0].imag(),a[0].real()}; |       double tmp[2]={a[0].imag(),a[0].real()}; | ||||||
|       return vld1q_f64(tmp); |       return vld1q_f64(tmp); | ||||||
|     } |     } | ||||||
|     // Real float // N:ok |     // Real float | ||||||
|     inline float32x4_t operator()(float *a){ |     inline float32x4_t operator()(float *a){ | ||||||
|       float tmp[4]={a[3],a[2],a[1],a[0]}; |       float tmp[4]={a[3],a[2],a[1],a[0]}; | ||||||
|       return vld1q_f32(tmp); |       return vld1q_f32(tmp); | ||||||
|     } |     } | ||||||
|     // Real double // N:ok |     // Real double | ||||||
|     inline float64x2_t operator()(double *a){ |     inline float64x2_t operator()(double *a){ | ||||||
|       double tmp[2]={a[1],a[0]}; |       double tmp[2]={a[1],a[0]}; | ||||||
|       return vld1q_f64(tmp); |       return vld1q_f64(tmp); | ||||||
|     } |     } | ||||||
|     // Integer // N:ok |     // Integer | ||||||
|     inline uint32x4_t operator()(Integer *a){ |     inline uint32x4_t operator()(Integer *a){ | ||||||
|       return vld1q_dup_u32(a); |       return vld1q_dup_u32(a); | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   // N:leaving as is |  | ||||||
|   template <typename Out_type, typename In_type> |   template <typename Out_type, typename In_type> | ||||||
|   struct Reduce{ |   struct Reduce{ | ||||||
|     //Need templated class to overload output type |     //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 ... |       return vfmaq_f32(r4, r0, a); //  ar*br-ai*bi ai*br+ar*bi ... | ||||||
|  |  | ||||||
|       // no fma, use mul and add |       // no fma, use mul and add | ||||||
|       //float32x4_t r5; |       // float32x4_t r5; | ||||||
|       //r5 = vmulq_f32(r0, a); |       // r5 = vmulq_f32(r0, a); | ||||||
|       //return vaddq_f32(r4, r5); |       // return vaddq_f32(r4, r5); | ||||||
|     } |     } | ||||||
|     // Complex double |     // Complex double | ||||||
|     inline float64x2_t operator()(float64x2_t a, float64x2_t b){ |     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 |       return vfmaq_f64(r4, r0, a); //  ar*br-ai*bi ai*br+ar*bi | ||||||
|  |  | ||||||
|       // no fma, use mul and add |       // no fma, use mul and add | ||||||
|       //float64x2_t r5; |       // float64x2_t r5; | ||||||
|       //r5 = vmulq_f64(r0, a); |       // r5 = vmulq_f64(r0, a); | ||||||
|       //return vaddq_f64(r4, r5); |       // 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 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); }; |     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); |       sb = vcvt_high_f32_f16(h); | ||||||
|       // there is no direct conversion from lower float32x4_t to float64x2_t |       // there is no direct conversion from lower float32x4_t to float64x2_t | ||||||
|       // vextq_f16 not supported by clang 3.8 / 4.0 / arm clang |       // 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 |       // workaround for clang | ||||||
|       uint32x4_t h1u = reinterpret_cast<uint32x4_t>(h); |       uint32x4_t h1u = reinterpret_cast<uint32x4_t>(h); | ||||||
|       float16x8_t h1 = reinterpret_cast<float16x8_t>(vextq_u32(h1u, h1u, 2)); |       float16x8_t h1 = reinterpret_cast<float16x8_t>(vextq_u32(h1u, h1u, 2)); | ||||||
| @@ -547,7 +541,7 @@ namespace Optimization { | |||||||
|  |  | ||||||
|  |  | ||||||
|   //Complex double Reduce |   //Complex double Reduce | ||||||
|   template<> // N:by Boyle |   template<> | ||||||
|   inline Grid::ComplexD Reduce<Grid::ComplexD, float64x2_t>::operator()(float64x2_t in){ |   inline Grid::ComplexD Reduce<Grid::ComplexD, float64x2_t>::operator()(float64x2_t in){ | ||||||
|     u128d conv; conv.v = in; |     u128d conv; conv.v = in; | ||||||
|     return Grid::ComplexD(conv.f[0],conv.f[1]); |     return Grid::ComplexD(conv.f[0],conv.f[1]); | ||||||
| @@ -562,9 +556,7 @@ namespace Optimization { | |||||||
|   //Integer Reduce |   //Integer Reduce | ||||||
|   template<> |   template<> | ||||||
|   inline Integer Reduce<Integer, uint32x4_t>::operator()(uint32x4_t in){ |   inline Integer Reduce<Integer, uint32x4_t>::operator()(uint32x4_t in){ | ||||||
|     // FIXME unimplemented |     return vaddvq_u32(in); | ||||||
|     printf("Reduce : Missing integer implementation -> FIX\n"); |  | ||||||
|     assert(0); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -604,3 +596,4 @@ namespace Optimization { | |||||||
|   typedef Optimization::TimesI      TimesISIMD; |   typedef Optimization::TimesI      TimesISIMD; | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -376,7 +376,18 @@ class Grid_simd { | |||||||
|       Optimization::Exchange::Exchange0(out1.v,out2.v,in1.v,in2.v); |       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 |   // General permute; assumes vector length is same across | ||||||
|   // all subtypes; may not be a good assumption, but could |   // 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 ( sshift[0] == sshift[1] ) { | ||||||
| 	if (splice_dim) { | 	if (splice_dim) { | ||||||
| 	  splicetime-=usecond(); | 	  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(); | 	  splicetime+=usecond(); | ||||||
| 	} else {  | 	} else {  | ||||||
| 	  nosplicetime-=usecond(); | 	  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(); | 	  nosplicetime+=usecond(); | ||||||
| 	} | 	} | ||||||
|       } else { |       } else { | ||||||
| @@ -412,13 +414,15 @@ class CartesianStencil { // Stencil runs along coordinate axes only; NO diagonal | |||||||
| 	  splicetime-=usecond(); | 	  splicetime-=usecond(); | ||||||
| 	  // if checkerboard is unfavourable take two passes | 	  // if checkerboard is unfavourable take two passes | ||||||
| 	  // both with block stride loop iteration | 	  // both with block stride loop iteration | ||||||
| 	  same_node = same_node && GatherSimd(source,dimension,shift,0x1,compress,face_idx); | 	  auto tmp1 =  GatherSimd(source,dimension,shift,0x1,compress,face_idx); | ||||||
| 	  same_node = same_node && GatherSimd(source,dimension,shift,0x2,compress,face_idx); | 	  auto tmp2 =  GatherSimd(source,dimension,shift,0x2,compress,face_idx); | ||||||
|  | 	  same_node = same_node && tmp1 && tmp2; | ||||||
| 	  splicetime+=usecond(); | 	  splicetime+=usecond(); | ||||||
| 	} else { | 	} else { | ||||||
| 	  nosplicetime-=usecond(); | 	  nosplicetime-=usecond(); | ||||||
| 	  same_node = same_node && Gather(source,dimension,shift,0x1,compress,face_idx); | 	  auto tmp1 = Gather(source,dimension,shift,0x1,compress,face_idx); | ||||||
| 	  same_node = same_node && Gather(source,dimension,shift,0x2,compress,face_idx); | 	  auto tmp2 = Gather(source,dimension,shift,0x2,compress,face_idx); | ||||||
|  | 	  same_node = same_node && tmp1 && tmp2; | ||||||
| 	  nosplicetime+=usecond(); | 	  nosplicetime+=usecond(); | ||||||
| 	} | 	} | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -175,7 +175,7 @@ class TensorIndexRecursion { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   template<class vtype,int N> inline static  |   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++){ |       for(int ii=0;ii<N;ii++){ | ||||||
| 	TensorIndexRecursion<Level-1>::pokeIndex(ret._internal[ii],arg._internal[ii],i,j); | 	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  |   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 ii=0;ii<N;ii++){ | ||||||
|       for(int jj=0;jj<N;jj++){ |       for(int jj=0;jj<N;jj++){ | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ namespace Grid{ | |||||||
|   class Lexicographic { |   class Lexicographic { | ||||||
|   public: |   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(); |       int nd= dims.size(); | ||||||
|       coor.resize(nd); |       coor.resize(nd); | ||||||
|       for(int d=0;d<nd;d++){ |       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 nd=dims.size(); | ||||||
|       int stride=1; |       int stride=1; | ||||||
|       index=0; |       index=0; | ||||||
|   | |||||||
| @@ -29,7 +29,6 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | |||||||
|     /*  END LEGAL */ |     /*  END LEGAL */ | ||||||
| #include <Grid/Grid.h> | #include <Grid/Grid.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| using namespace Grid; | using namespace Grid; | ||||||
| using namespace Grid::QCD; | using namespace Grid::QCD; | ||||||
|  |  | ||||||
| @@ -151,6 +150,11 @@ int main(int argc,char **argv) | |||||||
|   ioTest<TextWriter, TextReader>("iotest.dat", obj, "text   (object)           "); |   ioTest<TextWriter, TextReader>("iotest.dat", obj, "text   (object)           "); | ||||||
|   ioTest<TextWriter, TextReader>("iotest.dat", vec, "text   (vector of objects)"); |   ioTest<TextWriter, TextReader>("iotest.dat", vec, "text   (vector of objects)"); | ||||||
|   ioTest<TextWriter, TextReader>("iotest.dat", pair, "text   (pair 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 |   //// HDF5 | ||||||
| #undef HAVE_HDF5 | #undef HAVE_HDF5 | ||||||
| #ifdef HAVE_HDF5 | #ifdef HAVE_HDF5 | ||||||
| @@ -201,8 +205,10 @@ int main(int argc,char **argv) | |||||||
|     JSONWriter JW("bother.json"); |     JSONWriter JW("bother.json"); | ||||||
|  |  | ||||||
|     // test basic type writing |     // test basic type writing | ||||||
|  |     myenum a = myenum::red; | ||||||
|     push(JW,"BasicTypes"); |     push(JW,"BasicTypes"); | ||||||
|     write(JW,std::string("i16"),i16); |     write(JW,std::string("i16"),i16); | ||||||
|  |     write(JW,"myenum",a); | ||||||
|     write(JW,"u16",u16); |     write(JW,"u16",u16); | ||||||
|     write(JW,"i32",i32); |     write(JW,"i32",i32); | ||||||
|     write(JW,"u32",u32); |     write(JW,"u32",u32); | ||||||
| @@ -213,13 +219,14 @@ int main(int argc,char **argv) | |||||||
|     write(JW,"b",b); |     write(JW,"b",b); | ||||||
|     pop(JW); |     pop(JW); | ||||||
|  |  | ||||||
|  |  | ||||||
|     // test serializable class writing |     // test serializable class writing | ||||||
|     myclass obj(1234); // non-trivial constructor |     myclass obj(1234); // non-trivial constructor | ||||||
|  |     std::cout << obj << std::endl; | ||||||
|     std::cout << "-- serialisable class writing to 'bother.json'..." << std::endl; |     std::cout << "-- serialisable class writing to 'bother.json'..." << std::endl; | ||||||
|     write(JW,"obj",obj); |     write(JW,"obj",obj); | ||||||
|     JW.write("obj2", obj); |     JW.write("obj2", obj); | ||||||
|  |  | ||||||
|     std::cout << obj << std::endl; |  | ||||||
|  |  | ||||||
|     std::vector<myclass> vec; |     std::vector<myclass> vec; | ||||||
|     vec.push_back(myclass(1234)); |     vec.push_back(myclass(1234)); | ||||||
| @@ -229,6 +236,7 @@ int main(int argc,char **argv) | |||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   { |   { | ||||||
|     JSONReader RD("bother.json"); |     JSONReader RD("bother.json"); | ||||||
|     myclass jcopy1; |     myclass jcopy1; | ||||||
| @@ -239,6 +247,7 @@ int main(int argc,char **argv) | |||||||
|     std::cout << jcopy1 << std::endl << jveccopy1 << std::endl; |     std::cout << jcopy1 << std::endl << jveccopy1 << std::endl; | ||||||
|   } |   } | ||||||
|   |   | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   // This is still work in progress |   // This is still work in progress | ||||||
|   { |   { | ||||||
|   | |||||||
| @@ -80,31 +80,47 @@ int main (int argc, char ** argv) | |||||||
|  |  | ||||||
|  |  | ||||||
|   LatticeFermionD    src_o(FrbGrid); |   LatticeFermionD    src_o(FrbGrid); | ||||||
|   LatticeFermionD result_o(FrbGrid); |   LatticeFermionD result_cg(FrbGrid); | ||||||
|   LatticeFermionD result_o_2(FrbGrid); |  | ||||||
|   pickCheckerboard(Odd,src_o,src); |   pickCheckerboard(Odd,src_o,src); | ||||||
|   result_o.checkerboard = Odd; |   result_cg.checkerboard = Odd; | ||||||
|   result_o = zero; |   result_cg = zero; | ||||||
|   result_o_2.checkerboard = Odd; |   LatticeFermionD result_mcg(result_cg); | ||||||
|   result_o_2 = zero; |   LatticeFermionD result_rlcg(result_cg); | ||||||
|  |  | ||||||
|   SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf); |   SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf); | ||||||
|   SchurDiagMooeeOperator<DomainWallFermionFH,LatticeFermionF> HermOpEO_f(Ddwf_f); |   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; |   std::cout << "Starting mixed CG" << std::endl; | ||||||
|   MixedPrecisionConjugateGradient<LatticeFermionD,LatticeFermionF> mCG(1.0e-8, 10000, 50, FrbGrid_f, HermOpEO_f, HermOpEO); |   MixedPrecisionConjugateGradient<LatticeFermionD,LatticeFermionF> mCG(1.0e-8, 10000, 50, FrbGrid_f, HermOpEO_f, HermOpEO); | ||||||
|   mCG.InnerTolerance = 3.0e-5; |   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; |   std::cout << "Starting regular CG" << std::endl; | ||||||
|   ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000); |   ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000); | ||||||
|   CG(HermOpEO,src_o,result_o_2); |   CG(HermOpEO,src_o,result_cg); | ||||||
|  |  | ||||||
|   LatticeFermionD diff_o(FrbGrid); | #ifdef DO_MIXED_CG | ||||||
|   RealD diff = axpy_norm(diff_o, -1.0, result_o, result_o_2); |   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: " << diff << std::endl; |   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(); |   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]; |   double volume = latt_size[0]*latt_size[1]*latt_size[2]*latt_size[3]; | ||||||
|  |  | ||||||
|   GridCartesian Fine(latt_size,simd_layout,mpi_layout); |   GridCartesian Fine(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian rbFine(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian rbFine(&Fine); | ||||||
|   GridParallelRNG       fRNG(&Fine); |   GridParallelRNG       fRNG(&Fine); | ||||||
|  |  | ||||||
|   //  fRNG.SeedFixedIntegers(std::vector<int>({45,12,81,9}); |   //  fRNG.SeedFixedIntegers(std::vector<int>({45,12,81,9}); | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ int main (int argc, char ** argv) | |||||||
|   mask[0]=0; |   mask[0]=0; | ||||||
|  |  | ||||||
|   GridCartesian         Fine  (latt_size,simd_layout,mpi_layout); |   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})); |   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; |   mask[0]=0; | ||||||
|  |  | ||||||
|   GridCartesian         Fine  (latt_size,simd_layout,mpi_layout); |   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})); |   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]; |     vol = vol * latt_size[d]; | ||||||
|   } |   } | ||||||
|   GridCartesian         GRID(latt_size,simd_layout,mpi_layout); |   GridCartesian         GRID(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian RBGRID(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian RBGRID(&GRID); | ||||||
|  |  | ||||||
|   LatticeComplexD     one(&GRID); |   LatticeComplexD     one(&GRID); | ||||||
|   LatticeComplexD      zz(&GRID); |   LatticeComplexD      zz(&GRID); | ||||||
|   | |||||||
| @@ -33,22 +33,68 @@ using namespace std; | |||||||
| using namespace Grid; | using namespace Grid; | ||||||
| using namespace Grid::QCD; | 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) | int main (int argc, char ** argv) | ||||||
| { | { | ||||||
|   const int nu = 3; |   int nu = 0; | ||||||
|  |  | ||||||
|   Grid_init(&argc,&argv); |   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 Ls=4; | ||||||
|   const int L =4; |   //const int L =4; | ||||||
|   std::vector<int> latt_2f(Nd,L); |   //std::vector<int> latt_2f(Nd,L); | ||||||
|   std::vector<int> latt_1f(Nd,L); latt_1f[nu] = 2*L; |  | ||||||
|  |   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> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); |  | ||||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); //node layout |   std::vector<int> mpi_layout  = GridDefaultMpi(); //node layout | ||||||
|  |  | ||||||
|   GridCartesian         * UGrid_1f   = SpaceTimeGrid::makeFourDimGrid(latt_1f, simd_layout, mpi_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          RNG5_2f(FGrid_2f);  RNG5_2f.SeedFixedIntegers(seeds5); | ||||||
|   GridParallelRNG          RNG4_2f(UGrid_2f);  RNG4_2f.SeedFixedIntegers(seeds4); |   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); |   SU3::HotConfiguration(RNG4_2f,Umu_2f); | ||||||
|  |  | ||||||
|   LatticeFermion    src   (FGrid_2f);  |   StandardFermionField    src   (FGrid_2f);  | ||||||
|   LatticeFermion    tmpsrc(FGrid_2f);  |   StandardFermionField    tmpsrc(FGrid_2f);  | ||||||
|   FermionField      src_2f(FGrid_2f);  |   GparityFermionField      src_2f(FGrid_2f);  | ||||||
|   LatticeFermion    src_1f(FGrid_1f);  |   StandardFermionField    src_1f(FGrid_1f);  | ||||||
|  |  | ||||||
|   // Replicate fermion source |   // Replicate fermion source | ||||||
|   random(RNG5_2f,src); |   random(RNG5_2f,src); | ||||||
| @@ -81,8 +127,8 @@ int main (int argc, char ** argv) | |||||||
|   tmpsrc=src*2.0; |   tmpsrc=src*2.0; | ||||||
|   PokeIndex<0>(src_2f,tmpsrc,1); |   PokeIndex<0>(src_2f,tmpsrc,1); | ||||||
|  |  | ||||||
|   LatticeFermion result_1f(FGrid_1f); result_1f=zero; |   StandardFermionField result_1f(FGrid_1f); result_1f=zero; | ||||||
|   LatticeGaugeField Umu_1f(UGrid_1f);  |   StandardGaugeField Umu_1f(UGrid_1f);  | ||||||
|   Replicate(Umu_2f,Umu_1f); |   Replicate(Umu_2f,Umu_1f); | ||||||
|  |  | ||||||
|   //Coordinate grid for reference |   //Coordinate grid for reference | ||||||
| @@ -92,7 +138,7 @@ int main (int argc, char ** argv) | |||||||
|   //Copy-conjugate the gauge field |   //Copy-conjugate the gauge field | ||||||
|   //First C-shift the lattice by Lx/2 |   //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 ); |     Umu_1f = where( xcoor_1f >= Integer(L), Umu_shift, Umu_1f ); | ||||||
|  |  | ||||||
|     // hack test to check the same |     // 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; |     cout << GridLogMessage << "Umu diff " << norm2(Umu_shift)<<std::endl; | ||||||
|  |  | ||||||
|     //Make the gauge field antiperiodic in nu-direction |     //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 = PeekIndex<LorentzIndex>(Umu_1f,nu); | ||||||
|     Unu = where(xcoor_1f == Integer(2*L-1), -Unu, Unu); |     Unu = where(xcoor_1f == Integer(2*L-1), -Unu, Unu); | ||||||
|     PokeIndex<LorentzIndex>(Umu_1f,Unu,nu); |     PokeIndex<LorentzIndex>(Umu_1f,Unu,nu); | ||||||
| @@ -115,33 +161,33 @@ int main (int argc, char ** argv) | |||||||
|  |  | ||||||
|   RealD mass=0.0; |   RealD mass=0.0; | ||||||
|   RealD M5=1.8; |   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); |   StandardFermionField    src_o_1f(FrbGrid_1f); | ||||||
|   LatticeFermion result_o_1f(FrbGrid_1f); |   StandardFermionField result_o_1f(FrbGrid_1f); | ||||||
|   pickCheckerboard(Odd,src_o_1f,src_1f); |   pickCheckerboard(Odd,src_o_1f,src_1f); | ||||||
|   result_o_1f=zero; |   result_o_1f=zero; | ||||||
|  |  | ||||||
|   SchurDiagMooeeOperator<DomainWallFermionR,LatticeFermion> HermOpEO(Ddwf); |   SchurDiagMooeeOperator<StandardDiracOp,StandardFermionField> HermOpEO(Ddwf); | ||||||
|   ConjugateGradient<LatticeFermion> CG(1.0e-8,10000); |   ConjugateGradient<StandardFermionField> CG(1.0e-8,10000); | ||||||
|   CG(HermOpEO,src_o_1f,result_o_1f); |   CG(HermOpEO,src_o_1f,result_o_1f); | ||||||
|    |    | ||||||
|   //  const int nu = 3; |   //  const int nu = 3; | ||||||
|   std::vector<int> twists(Nd,0); |   std::vector<int> twists(Nd,0); | ||||||
|   twists[nu] = 1; |   twists[nu] = 1; | ||||||
|   GparityDomainWallFermionR::ImplParams params; |   GparityDiracOp::ImplParams params; | ||||||
|   params.twists = twists; |   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 disp=-1;disp<=1;disp+=2) | ||||||
|   for(int mu=0;mu<5;mu++) |   for(int mu=0;mu<5;mu++) | ||||||
|   {  |   {  | ||||||
|     FermionField Dsrc_2f(FGrid_2f); |     GparityFermionField Dsrc_2f(FGrid_2f); | ||||||
|  |  | ||||||
|     LatticeFermion Dsrc_1f(FGrid_1f); |     StandardFermionField Dsrc_1f(FGrid_1f); | ||||||
|     LatticeFermion Dsrc_2freplica(FGrid_1f); |     StandardFermionField Dsrc_2freplica(FGrid_1f); | ||||||
|     LatticeFermion Dsrc_2freplica0(FGrid_1f); |     StandardFermionField Dsrc_2freplica0(FGrid_1f); | ||||||
|     LatticeFermion Dsrc_2freplica1(FGrid_1f); |     StandardFermionField Dsrc_2freplica1(FGrid_1f); | ||||||
|  |  | ||||||
|     if ( mu ==0 ) { |     if ( mu ==0 ) { | ||||||
|       std::cout << GridLogMessage<< " Cross checking entire hopping term"<<std::endl; |       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 << "S norms "<< norm2(src_2f) << " " << norm2(src_1f)  <<std::endl; | ||||||
|     std::cout << GridLogMessage << "D norms "<< norm2(Dsrc_2f)<< " " << norm2(Dsrc_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); |     StandardFermionField 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_2f1(FGrid_2f); Dsrc_2f1 = PeekIndex<0>(Dsrc_2f,1); | ||||||
|  |  | ||||||
|     //    Dsrc_2f1 = Dsrc_2f1 - Dsrc_2f0; |     //    Dsrc_2f1 = Dsrc_2f1 - Dsrc_2f0; | ||||||
|     //    std::cout << GridLogMessage << " Cross check two halves " <<norm2(Dsrc_2f1)<<std::endl; |     //    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); |     GparityFermionField chi   (FGrid_2f); gaussian(RNG5_2f,chi); | ||||||
|     FermionField phi   (FGrid_2f); gaussian(RNG5_2f,phi); |     GparityFermionField phi   (FGrid_2f); gaussian(RNG5_2f,phi); | ||||||
|    |    | ||||||
|     FermionField chi_e   (FrbGrid_2f); |     GparityFermionField chi_e   (FrbGrid_2f); | ||||||
|     FermionField chi_o   (FrbGrid_2f); |     GparityFermionField chi_o   (FrbGrid_2f); | ||||||
|      |      | ||||||
|     FermionField dchi_e  (FrbGrid_2f); |     GparityFermionField dchi_e  (FrbGrid_2f); | ||||||
|     FermionField dchi_o  (FrbGrid_2f); |     GparityFermionField dchi_o  (FrbGrid_2f); | ||||||
|      |      | ||||||
|     FermionField phi_e   (FrbGrid_2f); |     GparityFermionField phi_e   (FrbGrid_2f); | ||||||
|     FermionField phi_o   (FrbGrid_2f); |     GparityFermionField phi_o   (FrbGrid_2f); | ||||||
|      |      | ||||||
|     FermionField dphi_e  (FrbGrid_2f); |     GparityFermionField dphi_e  (FrbGrid_2f); | ||||||
|     FermionField dphi_o  (FrbGrid_2f); |     GparityFermionField dphi_o  (FrbGrid_2f); | ||||||
|  |  | ||||||
|     pickCheckerboard(Even,chi_e,chi); |     pickCheckerboard(Even,chi_e,chi); | ||||||
|     pickCheckerboard(Odd ,chi_o,chi); |     pickCheckerboard(Odd ,chi_o,chi); | ||||||
| @@ -212,14 +258,14 @@ int main (int argc, char ** argv) | |||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FermionField result_2f(FGrid_2f); result_2f=zero; |   GparityFermionField result_2f(FGrid_2f); result_2f=zero; | ||||||
|   FermionField    src_o_2f(FrbGrid_2f); |   GparityFermionField    src_o_2f(FrbGrid_2f); | ||||||
|   FermionField result_o_2f(FrbGrid_2f); |   GparityFermionField result_o_2f(FrbGrid_2f); | ||||||
|   pickCheckerboard(Odd,src_o_2f,src_2f); |   pickCheckerboard(Odd,src_o_2f,src_2f); | ||||||
|   result_o_2f=zero; |   result_o_2f=zero; | ||||||
|  |  | ||||||
|   ConjugateGradient<FermionField> CG2f(1.0e-8,10000); |   ConjugateGradient<GparityFermionField> CG2f(1.0e-8,10000); | ||||||
|   SchurDiagMooeeOperator<GparityDomainWallFermionR,FermionField> HermOpEO2f(GPDdwf); |   SchurDiagMooeeOperator<GparityDiracOp,GparityFermionField> HermOpEO2f(GPDdwf); | ||||||
|   CG2f(HermOpEO2f,src_o_2f,result_o_2f); |   CG2f(HermOpEO2f,src_o_2f,result_o_2f); | ||||||
|  |  | ||||||
|   std::cout << "2f cb "<<result_o_2f.checkerboard<<std::endl; |   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; |   std::cout << " result norms " <<norm2(result_o_2f)<<" " <<norm2(result_o_1f)<<std::endl; | ||||||
|  |  | ||||||
|   LatticeFermion    res0o  (FrbGrid_2f);  |   StandardFermionField    res0o  (FrbGrid_2f);  | ||||||
|   LatticeFermion    res1o  (FrbGrid_2f);  |   StandardFermionField    res1o  (FrbGrid_2f);  | ||||||
|   LatticeFermion    res0  (FGrid_2f);  |   StandardFermionField    res0  (FGrid_2f);  | ||||||
|   LatticeFermion    res1  (FGrid_2f);  |   StandardFermionField    res1  (FGrid_2f);  | ||||||
|  |  | ||||||
|   res0=zero; |   res0=zero; | ||||||
|   res1=zero; |   res1=zero; | ||||||
| @@ -244,9 +290,9 @@ int main (int argc, char ** argv) | |||||||
|   setCheckerboard(res0,res0o); |   setCheckerboard(res0,res0o); | ||||||
|   setCheckerboard(res1,res1o); |   setCheckerboard(res1,res1o); | ||||||
|  |  | ||||||
|   LatticeFermion replica (FGrid_1f); |   StandardFermionField replica (FGrid_1f); | ||||||
|   LatticeFermion replica0(FGrid_1f); |   StandardFermionField replica0(FGrid_1f); | ||||||
|   LatticeFermion replica1(FGrid_1f); |   StandardFermionField replica1(FGrid_1f); | ||||||
|   Replicate(res0,replica0); |   Replicate(res0,replica0); | ||||||
|   Replicate(res1,replica1); |   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> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||||
|   | |||||||
							
								
								
									
										105
									
								
								tests/core/Test_laplacian.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								tests/core/Test_laplacian.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | |||||||
|  |     /************************************************************************************* | ||||||
|  |  | ||||||
|  |     Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |  | ||||||
|  |     Source file: ./tests/Test_laplacian.cc | ||||||
|  |  | ||||||
|  |     Copyright (C) 2017 | ||||||
|  |  | ||||||
|  | Author: Guido Cossu <guido.cossu@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> | ||||||
|  |  | ||||||
|  | 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(); | ||||||
|  |   GridCartesian               Grid(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; | ||||||
|  |  | ||||||
|  |   GridParallelRNG          pRNG(&Grid); | ||||||
|  |   pRNG.SeedFixedIntegers(std::vector<int>({45,12,81,9})); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   std::vector<int> point({0,0,0,0}); | ||||||
|  |  | ||||||
|  |   LatticeFermion src   (&Grid); //random(pRNG,src); | ||||||
|  |   SpinColourVectorD Sp; | ||||||
|  |   for (unsigned int s = 0; s < Ns; ++s) | ||||||
|  |       for (unsigned int c = 0; c < Nc; ++c) | ||||||
|  |         Sp()(s)(c) = 1; | ||||||
|  |  | ||||||
|  |   src = zero; | ||||||
|  |   pokeSite(Sp,src,point); | ||||||
|  |  | ||||||
|  |   LatticeFermion result(&Grid); result=zero; | ||||||
|  |   LatticeFermion tmp(&Grid); tmp=zero; | ||||||
|  |  | ||||||
|  |   // Gauge configuration | ||||||
|  |   LatticeGaugeField Umu(&Grid); SU3::HotConfiguration(pRNG,Umu); | ||||||
|  |  | ||||||
|  |   std::cout<<GridLogMessage<<"=============================================================="<<std::endl; | ||||||
|  |   std::cout<<GridLogMessage<<"= Testing the laplacian operator on a point source            "<<std::endl; | ||||||
|  |   std::cout<<GridLogMessage<<"=============================================================="<<std::endl; | ||||||
|  |  | ||||||
|  |   Laplacian<WilsonImplR> LaplaceOperator(src._grid); | ||||||
|  |   LaplaceOperator.ImportGauge(Umu); | ||||||
|  |   LaplaceOperator.M(src, result); | ||||||
|  |  | ||||||
|  |   std::cout << "Source vector" << std::endl; | ||||||
|  |   std::cout << src << std::endl; | ||||||
|  |  | ||||||
|  |   std::cout << "Result vector" << std::endl; | ||||||
|  |   std::cout << result << std::endl; | ||||||
|  |  | ||||||
|  |   std::cout<<GridLogMessage<<"=============================================================="<<std::endl; | ||||||
|  |   std::cout<<GridLogMessage<<"= Testing the laplacian smearing operator on a point source   "<<std::endl; | ||||||
|  |   std::cout<<GridLogMessage<<"=============================================================="<<std::endl; | ||||||
|  |  | ||||||
|  |   LatticeFermion smeared  (&Grid); smeared = src; | ||||||
|  |   for (int smr = 0; smr < 10; ++smr) | ||||||
|  |   { | ||||||
|  |       LaplaceOperator.M(smeared, tmp); | ||||||
|  |       smeared += 0.1*tmp; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   std::cout << "Smeared vector" << std::endl; | ||||||
|  |   std::cout << smeared << std::endl; | ||||||
|  |  | ||||||
|  |   // Norm of vector | ||||||
|  |   LatticeComplex smr_norm(&Grid); | ||||||
|  |   smr_norm = localNorm2(smeared); | ||||||
|  |   std::cout << "Smeared vector norm" << std::endl; | ||||||
|  |   std::cout << smr_norm << std::endl; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   Grid_finalize(); | ||||||
|  | } | ||||||
| @@ -84,7 +84,7 @@ int main(int argc, char **argv) { | |||||||
|       double volume = latt_size[0] * latt_size[1] * latt_size[2] * latt_size[3]; |       double volume = latt_size[0] * latt_size[1] * latt_size[2] * latt_size[3]; | ||||||
|  |  | ||||||
|       GridCartesian Fine(latt_size, simd_layout, mpi_layout); |       GridCartesian Fine(latt_size, simd_layout, mpi_layout); | ||||||
|       GridRedBlackCartesian rbFine(latt_size, simd_layout, mpi_layout); |       GridRedBlackCartesian rbFine(&Fine); | ||||||
|       GridParallelRNG FineRNG(&Fine); |       GridParallelRNG FineRNG(&Fine); | ||||||
|       GridSerialRNG SerialRNG; |       GridSerialRNG SerialRNG; | ||||||
|       GridSerialRNG SerialRNG1; |       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> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   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> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   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> simd_layout = GridDefaultSimd(Nd,vComplex::Nsimd()); | ||||||
|   std::vector<int> mpi_layout  = GridDefaultMpi(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   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(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|  |  | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   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(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|  |  | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   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(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|  |  | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   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(); |   std::vector<int> mpi_layout  = GridDefaultMpi(); | ||||||
|  |  | ||||||
|   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); |   GridCartesian               Grid(latt_size,simd_layout,mpi_layout); | ||||||
|   GridRedBlackCartesian     RBGrid(latt_size,simd_layout,mpi_layout); |   GridRedBlackCartesian     RBGrid(&Grid); | ||||||
|  |  | ||||||
|   int threads = GridThread::GetThreads(); |   int threads = GridThread::GetThreads(); | ||||||
|   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; |   std::cout<<GridLogMessage << "Grid is setup to use "<<threads<<" threads"<<std::endl; | ||||||
|   | |||||||
							
								
								
									
										195
									
								
								tests/hadrons/Test_hadrons_meson_3pt_laplacian.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								tests/hadrons/Test_hadrons_meson_3pt_laplacian.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | |||||||
|  | /******************************************************************************* | ||||||
|  |  Grid physics library, www.github.com/paboyle/Grid | ||||||
|  |   | ||||||
|  |  Source file: tests/hadrons/Test_hadrons_meson_3pt.cc | ||||||
|  |   | ||||||
|  |  Copyright (C) 2015 | ||||||
|  |   | ||||||
|  |  Author: Antonin Portelli <antonin.portelli@me.com> | ||||||
|  |   | ||||||
|  |  This program is free software; you can redistribute it and/or modify | ||||||
|  |  it under the terms of the GNU General Public License as published by | ||||||
|  |  the Free Software Foundation; either version 2 of the License, or | ||||||
|  |  (at your option) any later version. | ||||||
|  |   | ||||||
|  |  This program is distributed in the hope that it will be useful, | ||||||
|  |  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  GNU General Public License for more details. | ||||||
|  |   | ||||||
|  |  You should have received a copy of the GNU General Public License along | ||||||
|  |  with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|  |  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  |   | ||||||
|  |  See the full license in the file "LICENSE" in the top level distribution | ||||||
|  |  directory. | ||||||
|  |  *******************************************************************************/ | ||||||
|  |  | ||||||
|  | #include <Grid/Hadrons/Application.hpp> | ||||||
|  |  | ||||||
|  | using namespace Grid; | ||||||
|  | using namespace Hadrons; | ||||||
|  |  | ||||||
|  | int main(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  |     // initialization ////////////////////////////////////////////////////////// | ||||||
|  |     Grid_init(&argc, &argv); | ||||||
|  |     HadronsLogError.Active(GridLogError.isActive()); | ||||||
|  |     HadronsLogWarning.Active(GridLogWarning.isActive()); | ||||||
|  |     HadronsLogMessage.Active(GridLogMessage.isActive()); | ||||||
|  |     HadronsLogIterative.Active(GridLogIterative.isActive()); | ||||||
|  |     HadronsLogDebug.Active(GridLogDebug.isActive()); | ||||||
|  |     LOG(Message) << "Grid initialized" << std::endl; | ||||||
|  |      | ||||||
|  |     // run setup /////////////////////////////////////////////////////////////// | ||||||
|  |     Application              application; | ||||||
|  |     std::vector<std::string> flavour = {"l", "s", "c1", "c2", "c3"}; | ||||||
|  |     std::vector<double>      mass    = {.01, .04, .2  , .25 , .3  }; | ||||||
|  |     unsigned int             nt      = GridDefaultLatt()[Tp]; | ||||||
|  |      | ||||||
|  |     // global parameters | ||||||
|  |     Application::GlobalPar globalPar; | ||||||
|  |     globalPar.trajCounter.start    = 1500; | ||||||
|  |     globalPar.trajCounter.end      = 1520; | ||||||
|  |     globalPar.trajCounter.step     = 20; | ||||||
|  |     globalPar.seed                 = "1 2 3 4"; | ||||||
|  |     globalPar.genetic.maxGen       = 1000; | ||||||
|  |     globalPar.genetic.maxCstGen    = 200; | ||||||
|  |     globalPar.genetic.popSize      = 20; | ||||||
|  |     globalPar.genetic.mutationRate = .1; | ||||||
|  |     application.setPar(globalPar); | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     // gauge field | ||||||
|  |     application.createModule<MGauge::Unit>("gauge"); | ||||||
|  |      | ||||||
|  |     // set fermion boundary conditions to be periodic space, antiperiodic time. | ||||||
|  |     std::string boundary = "1 1 1 -1"; | ||||||
|  |  | ||||||
|  |     // sink | ||||||
|  |     MSink::Point::Par sinkPar; | ||||||
|  |     sinkPar.mom = "0 0 0"; | ||||||
|  |     application.createModule<MSink::ScalarPoint>("sink", sinkPar); | ||||||
|  |     for (unsigned int i = 0; i < flavour.size(); ++i) | ||||||
|  |     { | ||||||
|  |         // actions | ||||||
|  |         MAction::DWF::Par actionPar; | ||||||
|  |         actionPar.gauge = "gauge"; | ||||||
|  |         actionPar.Ls    = 12; | ||||||
|  |         actionPar.M5    = 1.8; | ||||||
|  |         actionPar.mass  = mass[i]; | ||||||
|  |         actionPar.boundary = boundary; | ||||||
|  |         application.createModule<MAction::DWF>("DWF_" + flavour[i], actionPar); | ||||||
|  |          | ||||||
|  |         // solvers | ||||||
|  |         MSolver::RBPrecCG::Par solverPar; | ||||||
|  |         solverPar.action   = "DWF_" + flavour[i]; | ||||||
|  |         solverPar.residual = 1.0e-8; | ||||||
|  |         application.createModule<MSolver::RBPrecCG>("CG_" + flavour[i], | ||||||
|  |                                                     solverPar); | ||||||
|  |     } | ||||||
|  |     for (unsigned int t = 0; t < nt; t += 1) | ||||||
|  |     { | ||||||
|  |         std::string                           srcName; | ||||||
|  |         std::string                           lapName; | ||||||
|  |         std::vector<std::string>              qName; | ||||||
|  |         std::vector<std::vector<std::string>> seqName; | ||||||
|  |          | ||||||
|  |         // Z2 source | ||||||
|  |         MSource::Z2::Par z2Par; | ||||||
|  |         z2Par.tA = t; | ||||||
|  |         z2Par.tB = t; | ||||||
|  |         srcName  = "z2_" + std::to_string(t); | ||||||
|  |         application.createModule<MSource::Z2>(srcName, z2Par); | ||||||
|  |  | ||||||
|  |         // Example of smearing of the source  | ||||||
|  |         MSource::LaplaceSmearing::Par LapPar; | ||||||
|  |         LapPar.N = 10; | ||||||
|  |         LapPar.alpha = 0.1; | ||||||
|  |         LapPar.source = srcName; | ||||||
|  |         LapPar.gauge = "gauge"; | ||||||
|  |         lapName = "z2smr_" + std::to_string(t); | ||||||
|  |         application.createModule<MSource::LaplaceSmearing>(lapName, LapPar); | ||||||
|  |  | ||||||
|  |         for (unsigned int i = 0; i < flavour.size(); ++i) | ||||||
|  |         { | ||||||
|  |             // sequential sources | ||||||
|  |             MSource::SeqGamma::Par seqPar; | ||||||
|  |             qName.push_back("QZ2_" + flavour[i] + "_" + std::to_string(t)); | ||||||
|  |             seqPar.q   = qName[i]; | ||||||
|  |             seqPar.tA  = (t + nt/4) % nt; | ||||||
|  |             seqPar.tB  = (t + nt/4) % nt; | ||||||
|  |             seqPar.mom = "1. 0. 0. 0."; | ||||||
|  |             seqName.push_back(std::vector<std::string>(Nd)); | ||||||
|  |             for (unsigned int mu = 0; mu < Nd; ++mu) | ||||||
|  |             { | ||||||
|  |                 seqPar.gamma   = 0x1 << mu; | ||||||
|  |                 seqName[i][mu] = "G" + std::to_string(seqPar.gamma) | ||||||
|  |                                  + "_" + std::to_string(seqPar.tA) + "-" | ||||||
|  |                                  + qName[i]; | ||||||
|  |                 application.createModule<MSource::SeqGamma>(seqName[i][mu], seqPar); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             // propagators | ||||||
|  |             MFermion::GaugeProp::Par quarkPar; | ||||||
|  |             quarkPar.solver = "CG_" + flavour[i]; | ||||||
|  |             quarkPar.source = srcName; | ||||||
|  |             application.createModule<MFermion::GaugeProp>(qName[i], quarkPar); | ||||||
|  |             for (unsigned int mu = 0; mu < Nd; ++mu) | ||||||
|  |             { | ||||||
|  |                 quarkPar.source = seqName[i][mu]; | ||||||
|  |                 seqName[i][mu]  = "Q_" + flavour[i] + "-" + seqName[i][mu]; | ||||||
|  |                 application.createModule<MFermion::GaugeProp>(seqName[i][mu], quarkPar); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         // contractions | ||||||
|  |         MContraction::Meson::Par mesPar; | ||||||
|  |         for (unsigned int i = 0; i < flavour.size(); ++i) | ||||||
|  |         for (unsigned int j = i; j < flavour.size(); ++j) | ||||||
|  |         { | ||||||
|  |             mesPar.output = "mesons/Z2_" + flavour[i] + flavour[j]; | ||||||
|  |             mesPar.q1     = qName[i]; | ||||||
|  |             mesPar.q2     = qName[j]; | ||||||
|  |             mesPar.gammas = "all"; | ||||||
|  |             mesPar.sink   = "sink"; | ||||||
|  |             application.createModule<MContraction::Meson>("meson_Z2_" | ||||||
|  |                                                           + std::to_string(t) | ||||||
|  |                                                           + "_" | ||||||
|  |                                                           + flavour[i] | ||||||
|  |                                                           + flavour[j], | ||||||
|  |                                                           mesPar); | ||||||
|  |         } | ||||||
|  |         for (unsigned int i = 0; i < flavour.size(); ++i) | ||||||
|  |         for (unsigned int j = 0; j < flavour.size(); ++j) | ||||||
|  |         for (unsigned int mu = 0; mu < Nd; ++mu) | ||||||
|  |         { | ||||||
|  |             MContraction::Meson::Par mesPar; | ||||||
|  |              | ||||||
|  |             mesPar.output = "3pt/Z2_" + flavour[i] + flavour[j] + "_" | ||||||
|  |                             + std::to_string(mu); | ||||||
|  |             mesPar.q1     = qName[i]; | ||||||
|  |             mesPar.q2     = seqName[j][mu]; | ||||||
|  |             mesPar.gammas = "all"; | ||||||
|  |             mesPar.sink   = "sink"; | ||||||
|  |             application.createModule<MContraction::Meson>("3pt_Z2_" | ||||||
|  |                                                           + std::to_string(t) | ||||||
|  |                                                           + "_" | ||||||
|  |                                                           + flavour[i] | ||||||
|  |                                                           + flavour[j] | ||||||
|  |                                                           + "_" | ||||||
|  |                                                           + std::to_string(mu), | ||||||
|  |                                                           mesPar); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     // execution | ||||||
|  |     application.saveParameterFile("meson3pt.xml"); | ||||||
|  |     application.run(); | ||||||
|  |      | ||||||
|  |     // epilogue | ||||||
|  |     LOG(Message) << "Grid is finalizing now" << std::endl; | ||||||
|  |     Grid_finalize(); | ||||||
|  |      | ||||||
|  |     return EXIT_SUCCESS; | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user