mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-04 05:54:32 +00:00 
			
		
		
		
	Compare commits
	
		
			90 Commits
		
	
	
		
			dirac-ITT
			...
			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 | ||
| 
						 | 
					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();
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16178
									
								
								lib/json/json.hpp
									
									
									
									
									
								
							
							
						
						
									
										16178
									
								
								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);
 | 
				
			||||||
@@ -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,33 +30,147 @@ 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 SiteSpinor & ref (in._odata[offset]); LOAD_CHIMU_BODY(F); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOAD_CHI_BODY(F)				\
 | 
				
			||||||
 | 
					    Chi_00 = ref(F)(0)(0);\
 | 
				
			||||||
 | 
					    Chi_01 = ref(F)(0)(1);\
 | 
				
			||||||
 | 
					    Chi_02 = ref(F)(0)(2);\
 | 
				
			||||||
 | 
					    Chi_10 = ref(F)(1)(0);\
 | 
				
			||||||
 | 
					    Chi_11 = ref(F)(1)(1);\
 | 
				
			||||||
 | 
					    Chi_12 = ref(F)(1)(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOAD_CHI(DIR,F,PERM)					\
 | 
				
			||||||
 | 
					  {const SiteHalfSpinor &ref(buf[offset]); LOAD_CHI_BODY(F); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//G-parity implementations using in-place intrinsic ops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//1l 1h -> 1h 1l
 | 
				
			||||||
 | 
					//0l 0h , 1h 1l -> 0l 1h 0h,1l
 | 
				
			||||||
 | 
					//0h,1l -> 1l,0h
 | 
				
			||||||
 | 
					//if( (distance == 1 && !perm_will_occur) || (distance == -1 && perm_will_occur) )
 | 
				
			||||||
 | 
					//Pulled fermion through forwards face, GPBC on upper component
 | 
				
			||||||
 | 
					//Need 0= 0l 1h   1= 1l 0h
 | 
				
			||||||
 | 
					//else if( (distance == -1 && !perm) || (distance == 1 && perm) )
 | 
				
			||||||
 | 
					//Pulled fermion through backwards face, GPBC on lower component
 | 
				
			||||||
 | 
					//Need 0= 1l 0h   1= 0l 1h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//1l 1h -> 1h 1l
 | 
				
			||||||
 | 
					//0l 0h , 1h 1l -> 0l 1h 0h,1l
 | 
				
			||||||
 | 
					#define DO_TWIST_0L_1H(INTO,S,C,F, PERM, tmp1, tmp2, tmp3)			\
 | 
				
			||||||
 | 
					  permute##PERM(tmp1, ref(1)(S)(C));				\
 | 
				
			||||||
 | 
					  exchange##PERM(tmp2,tmp3, ref(0)(S)(C), tmp1);		\
 | 
				
			||||||
 | 
					  INTO = tmp2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//0l 0h -> 0h 0l
 | 
				
			||||||
 | 
					//1l 1h, 0h 0l -> 1l 0h, 1h 0l
 | 
				
			||||||
 | 
					#define DO_TWIST_1L_0H(INTO,S,C,F, PERM, tmp1, tmp2, tmp3)			\
 | 
				
			||||||
 | 
					  permute##PERM(tmp1, ref(0)(S)(C));				\
 | 
				
			||||||
 | 
					  exchange##PERM(tmp2,tmp3, ref(1)(S)(C), tmp1);		\
 | 
				
			||||||
 | 
					  INTO = tmp2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOAD_CHI_SETUP(DIR,F)						\
 | 
				
			||||||
 | 
					  g = F;								\
 | 
				
			||||||
 | 
					  direction = st._directions[DIR];				\
 | 
				
			||||||
 | 
					  distance = st._distances[DIR];				\
 | 
				
			||||||
 | 
					  sl = st._grid->_simd_layout[direction];			\
 | 
				
			||||||
 | 
					  inplace_twist = 0;						\
 | 
				
			||||||
 | 
					  if(SE->_around_the_world && this->Params.twists[DIR % 4]){		\
 | 
				
			||||||
 | 
					    if(sl == 1){							\
 | 
				
			||||||
 | 
					      g = (F+1) % 2;							\
 | 
				
			||||||
 | 
					    }else{								\
 | 
				
			||||||
 | 
					      inplace_twist = 1;						\
 | 
				
			||||||
 | 
					    }									\
 | 
				
			||||||
 | 
					  }  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOAD_CHIMU_GPARITY_INPLACE_TWIST(DIR,F,PERM)			\
 | 
				
			||||||
 | 
					  { const SiteSpinor &ref(in._odata[offset]);				\
 | 
				
			||||||
 | 
					    LOAD_CHI_SETUP(DIR,F);						\
 | 
				
			||||||
 | 
					    if(!inplace_twist){							\
 | 
				
			||||||
 | 
					      LOAD_CHIMU_BODY(g);						\
 | 
				
			||||||
 | 
					    }else{								\
 | 
				
			||||||
 | 
					      if(  ( F==0 && ((distance == 1 && !perm) || (distance == -1 && perm)) ) || \
 | 
				
			||||||
 | 
						   ( F==1 && ((distance == -1 && !perm) || (distance == 1 && perm)) ) ){ \
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_00,0,0,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_01,0,1,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_02,0,2,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_10,1,0,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_11,1,1,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_12,1,2,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_20,2,0,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_21,2,1,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_22,2,2,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_30,3,0,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_31,3,1,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_0L_1H(Chimu_32,3,2,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
					      }else{								\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_00,0,0,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_01,0,1,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_02,0,2,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_10,1,0,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_11,1,1,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_12,1,2,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_20,2,0,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_21,2,1,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_22,2,2,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_30,3,0,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_31,3,1,F,PERM,  U_00,U_01,U_10);		\
 | 
				
			||||||
 | 
						DO_TWIST_1L_0H(Chimu_32,3,2,F,PERM,  U_11,U_20,U_21);		\
 | 
				
			||||||
 | 
					      } \
 | 
				
			||||||
 | 
					    } \
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOAD_CHI_GPARITY_INPLACE_TWIST(DIR,F,PERM)				\
 | 
				
			||||||
  { const SiteHalfSpinor &ref(buf[offset]);				\
 | 
					  { const SiteHalfSpinor &ref(buf[offset]);				\
 | 
				
			||||||
    Chi_00 = ref()(0)(0);\
 | 
					    LOAD_CHI_SETUP(DIR,F);						\
 | 
				
			||||||
    Chi_01 = ref()(0)(1);\
 | 
					    if(!inplace_twist){							\
 | 
				
			||||||
    Chi_02 = ref()(0)(2);\
 | 
					      LOAD_CHI_BODY(g);							\
 | 
				
			||||||
    Chi_10 = ref()(1)(0);\
 | 
					    }else{								\
 | 
				
			||||||
    Chi_11 = ref()(1)(1);\
 | 
					      if(  ( F==0 && ((distance == 1 && !perm) || (distance == -1 && perm)) ) || \
 | 
				
			||||||
    Chi_12 = ref()(1)(2);}
 | 
						   ( 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));	\
 | 
				
			||||||
@@ -83,7 +197,14 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
				
			|||||||
  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;
 | 
					 | 
				
			||||||
  MultiShiftFunction PowerHalf;    
 | 
					 | 
				
			||||||
  MultiShiftFunction PowerInvHalf;    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  INHERIT_GIMPL_TYPES(Impl);
 | 
					  INHERIT_IMPL_TYPES(Impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  LaplacianAdjointField(GridBase* grid, OperatorFunction<GaugeField>& S, LaplacianParams& p, const RealD k = 1.0)
 | 
					  // add a bool to smear only in the spatial directions
 | 
				
			||||||
      : U(Nd, grid), Solver(S), param(p), kappa(k){
 | 
					  Laplacian(GridBase *grid, bool spatial = false)
 | 
				
			||||||
        AlgRemez remez(param.lo,param.hi,param.precision);
 | 
					      : U(Nd, grid), spatial_laplacian(spatial){};
 | 
				
			||||||
        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 FermionField &, FermionField &, int, int) { assert(0); }
 | 
				
			||||||
 | 
					  void Mdiag(const FermionField &, FermionField &) { assert(0); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      };
 | 
					  void ImportGauge(const GaugeField &_U)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
  void Mdir(const GaugeField&, GaugeField&, int, int){ assert(0);}
 | 
					    for (int mu = 0; mu < Nd; mu++)
 | 
				
			||||||
  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 GaugeField& in, GaugeField& out) {
 | 
					  void M(const FermionField &in, FermionField &out)
 | 
				
			||||||
    // in is an antihermitian matrix
 | 
					  {
 | 
				
			||||||
    // test
 | 
					    int dims = spatial_laplacian ? (Nd - 1) : Nd;
 | 
				
			||||||
    //GaugeField herm = in + adj(in);
 | 
					 | 
				
			||||||
    //std::cout << "AHermiticity: " << norm2(herm) << std::endl;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GaugeLinkField tmp(in._grid);
 | 
					    out = -2.0 * dims * in;
 | 
				
			||||||
    GaugeLinkField tmp2(in._grid);
 | 
					    // eventually speed up with the stencil operator, if necessary
 | 
				
			||||||
    GaugeLinkField sum(in._grid);
 | 
					    for (int mu = 0; mu < dims; mu++)
 | 
				
			||||||
 | 
					      out += Impl::CovShiftForward(U[mu], mu, in) + Impl::CovShiftBackward(U[mu], mu, in);
 | 
				
			||||||
    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:
 | 
					private:
 | 
				
			||||||
  RealD kappa;
 | 
					  bool spatial_laplacian;
 | 
				
			||||||
  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,6 +192,30 @@ 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)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
@@ -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); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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