mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-04 05:54:32 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			hotfix/unw
			...
			feature/dw
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a5645a7efe | ||
| 
						 | 
					8b3e738269 | 
@@ -49,6 +49,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
				
			|||||||
#include <Grid/algorithms/iterative/BlockConjugateGradient.h>
 | 
					#include <Grid/algorithms/iterative/BlockConjugateGradient.h>
 | 
				
			||||||
#include <Grid/algorithms/iterative/ConjugateGradientReliableUpdate.h>
 | 
					#include <Grid/algorithms/iterative/ConjugateGradientReliableUpdate.h>
 | 
				
			||||||
#include <Grid/algorithms/iterative/ImplicitlyRestartedLanczos.h>
 | 
					#include <Grid/algorithms/iterative/ImplicitlyRestartedLanczos.h>
 | 
				
			||||||
 | 
					#include <Grid/algorithms/iterative/InexactPrecConjugateGradient.h>
 | 
				
			||||||
#include <Grid/algorithms/CoarsenedMatrix.h>
 | 
					#include <Grid/algorithms/CoarsenedMatrix.h>
 | 
				
			||||||
#include <Grid/algorithms/FFT.h>
 | 
					#include <Grid/algorithms/FFT.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,4 +53,10 @@ void MultiShiftFunction::csv(std::ostream &out)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  return;
 | 
					  return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RealD __InverseApproximation(RealD x)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return 1.0/x;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,5 +63,7 @@ public:
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					RealD __InverseApproximation(RealD x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										278
									
								
								lib/algorithms/iterative/InexactPrecConjugateGradient.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								lib/algorithms/iterative/InexactPrecConjugateGradient.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,278 @@
 | 
				
			|||||||
 | 
					    /*************************************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Grid physics library, www.github.com/paboyle/Grid 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Source file: ./lib/algorithms/iterative/InexactPrecConjugateGradient.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_INEXACT_PREC_CONJUGATE_GRADIENT_H_
 | 
				
			||||||
 | 
					#define GRID_INEXACT_PREC_CONJUGATE_GRADIENT_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Grid {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Inexact preconditioned CG based on Golub, Ye, SIAM J. Sci. Comput., 21(4), 13051320. 
 | 
				
			||||||
 | 
					//(https://pdfs.semanticscholar.org/d2a9/d5bab02146a7fe3a244677432d21e33a2d98.pdf)
 | 
				
			||||||
 | 
					template <class Field>
 | 
				
			||||||
 | 
					class InexactPreconditionedConjugateGradient : public OperatorFunction<Field> {
 | 
				
			||||||
 | 
					 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
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  LinearOperatorBase<Field> &Prec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  InexactPreconditionedConjugateGradient(LinearOperatorBase<Field> &_Prec, RealD tol, Integer maxit, bool err_on_no_conv = true)
 | 
				
			||||||
 | 
					    : Prec(_Prec),
 | 
				
			||||||
 | 
					    Tolerance(tol),
 | 
				
			||||||
 | 
					    MaxIterations(maxit),
 | 
				
			||||||
 | 
					    ErrorOnNoConverge(err_on_no_conv){};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void operator()(LinearOperatorBase<Field> &Linop, const Field &src, Field &psi) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    psi.checkerboard = src.checkerboard;
 | 
				
			||||||
 | 
					    conformable(psi, src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Real ssq = norm2(src);
 | 
				
			||||||
 | 
					    RealD rsq = Tolerance * Tolerance * ssq; //inner stopping condition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Field p(src);
 | 
				
			||||||
 | 
					    Field r(src);
 | 
				
			||||||
 | 
					    Field rnm1(src);
 | 
				
			||||||
 | 
					    Field mmp(src);
 | 
				
			||||||
 | 
					    Field z(src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Initialize variables
 | 
				
			||||||
 | 
					    Linop.HermOp(psi, mmp);   
 | 
				
			||||||
 | 
					    r = src - mmp;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Real cp = norm2(r);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    p = zero;
 | 
				
			||||||
 | 
					    Real alpha = 0, beta = 0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Real z_nm1_dot_r_nm1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int n;
 | 
				
			||||||
 | 
					    for(n=1; n <= MaxIterations; n++) {
 | 
				
			||||||
 | 
					      //Check stopping condition
 | 
				
			||||||
 | 
					      if (cp <= rsq) {
 | 
				
			||||||
 | 
					        Linop.HermOp(psi, mmp);
 | 
				
			||||||
 | 
					        r = mmp - src;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        RealD srcnorm = sqrt(norm2(src));
 | 
				
			||||||
 | 
					        RealD resnorm = sqrt(norm2(r));
 | 
				
			||||||
 | 
					        RealD true_residual = resnorm / srcnorm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::cout << GridLogMessage << "InexactPreconditionedConjugateGradient Converged on iteration " << n << 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (ErrorOnNoConverge) assert(true_residual / Tolerance < 10000.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  	IterationsToComplete = n;	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      std::cout << GridLogIterative << std::setprecision(8)
 | 
				
			||||||
 | 
							<< "InexactPreconditionedConjugateGradient: n=" << n << " residual " << cp << " target " << rsq << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //Apply preconditioner to current residual
 | 
				
			||||||
 | 
					      Prec.HermOp(r, z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //Update beta and store appropriate variables for next iteration
 | 
				
			||||||
 | 
					      Real z_n_dot_r_n  = sqrt(norm(innerProduct(z,r)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if(n>1){
 | 
				
			||||||
 | 
						//  z^T_n ( r_n - r_{n-1} )
 | 
				
			||||||
 | 
						//  -----------------------
 | 
				
			||||||
 | 
						//     z^T_{n-1} r_{n-1}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Real z_n_dot_r_nm1 = sqrt(norm(innerProduct(z,rnm1)));
 | 
				
			||||||
 | 
						beta = ( z_n_dot_r_n - z_n_dot_r_nm1 ) / z_nm1_dot_r_nm1;
 | 
				
			||||||
 | 
						std::cout << GridLogIterative << "beta " << beta << std::endl;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      z_nm1_dot_r_nm1 = z_n_dot_r_n; //for next iteration
 | 
				
			||||||
 | 
					      rnm1 = r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      axpy(p, beta, p, z); //p = beta * p + z
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //Compute alpha
 | 
				
			||||||
 | 
					      Linop.HermOp(p, mmp);      
 | 
				
			||||||
 | 
					      alpha = z_n_dot_r_n / sqrt(norm(innerProduct(p, mmp)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      std::cout << GridLogIterative << "alpha " << alpha << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //Update residual and solution
 | 
				
			||||||
 | 
					      cp = axpy_norm(r, -alpha, mmp, r);
 | 
				
			||||||
 | 
					      axpy(psi, alpha, p, psi);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::cout << GridLogMessage << "InexactPreconditionedConjugateGradient did NOT converge"
 | 
				
			||||||
 | 
					              << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ErrorOnNoConverge) assert(0);
 | 
				
			||||||
 | 
					    IterationsToComplete = n;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class Field>
 | 
				
			||||||
 | 
					class PolynomialPreconditioner :  public LinearOperatorBase<Field> {
 | 
				
			||||||
 | 
					  Chebyshev<Field> Cheby;
 | 
				
			||||||
 | 
					  LinearOperatorBase<Field> &linop;
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  int InnerIterations;
 | 
				
			||||||
 | 
					  int order;
 | 
				
			||||||
 | 
					  PolynomialPreconditioner(LinearOperatorBase<Field> &_linop,RealD lo, RealD hi, int _order) 
 | 
				
			||||||
 | 
					    : linop(_linop), Cheby(lo,hi,_order,__InverseApproximation) 
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      InnerIterations=0;
 | 
				
			||||||
 | 
					      order = _order;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void OpDiag (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void OpDir  (const Field &in, Field &out,int dir,int disp){ assert(0); }
 | 
				
			||||||
 | 
					  void Op     (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void AdjOp  (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){ 
 | 
				
			||||||
 | 
					    HermOp(in,out);
 | 
				
			||||||
 | 
					    n1 = 0; n2 = norm2(out); 
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  void HermOp(const Field &in, Field &out){ 
 | 
				
			||||||
 | 
					    Cheby(linop,in,out); 
 | 
				
			||||||
 | 
					    InnerIterations+=order;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class Field>
 | 
				
			||||||
 | 
					class DoNothingLinearOperator :  public LinearOperatorBase<Field> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  void OpDiag (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void OpDir  (const Field &in, Field &out,int dir,int disp){ assert(0); }
 | 
				
			||||||
 | 
					  void Op     (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void AdjOp  (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){ out = in; n1 = 0; n2 = norm2(out); }
 | 
				
			||||||
 | 
					  void HermOp(const Field &in, Field &out){ out = in; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class Field>
 | 
				
			||||||
 | 
					class FixedIterConjugateGradientPreconditioner :  public LinearOperatorBase<Field> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  LinearOperatorBase<Field> &linop;
 | 
				
			||||||
 | 
					  ConjugateGradient<Field> CG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  FixedIterConjugateGradientPreconditioner (LinearOperatorBase<Field> &_linop, Integer _iter): linop(_linop), CG(1e-20, _iter){
 | 
				
			||||||
 | 
					    CG.ErrorOnNoConverge = false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void OpDiag (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void OpDir  (const Field &in, Field &out,int dir,int disp){ assert(0); }
 | 
				
			||||||
 | 
					  void Op     (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void AdjOp  (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){ 
 | 
				
			||||||
 | 
					    out = zero;
 | 
				
			||||||
 | 
					    CG(linop,in,out);    
 | 
				
			||||||
 | 
					    n2 = norm2(out);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  void HermOp(const Field &in, Field &out){
 | 
				
			||||||
 | 
					    out = zero;
 | 
				
			||||||
 | 
					    CG(linop,in,out);    
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class Field>
 | 
				
			||||||
 | 
					class SloppyConjugateGradientPreconditioner :  public LinearOperatorBase<Field> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  LinearOperatorBase<Field> &linop;
 | 
				
			||||||
 | 
					  ConjugateGradient<Field> CG;
 | 
				
			||||||
 | 
					  int InnerIterations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SloppyConjugateGradientPreconditioner (LinearOperatorBase<Field> &_linop, Real _resid, Integer max_iter): linop(_linop), CG(_resid, max_iter), InnerIterations(0){
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void ResetCounters(){ InnerIterations = 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void OpDiag (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void OpDir  (const Field &in, Field &out,int dir,int disp){ assert(0); }
 | 
				
			||||||
 | 
					  void Op     (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void AdjOp  (const Field &in, Field &out){ assert(0); }
 | 
				
			||||||
 | 
					  void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){ 
 | 
				
			||||||
 | 
					    out = zero;
 | 
				
			||||||
 | 
					    CG(linop,in,out);    
 | 
				
			||||||
 | 
					    InnerIterations += CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    n2 = norm2(out);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  void HermOp(const Field &in, Field &out){
 | 
				
			||||||
 | 
					    out = zero;
 | 
				
			||||||
 | 
					    CG(linop,in,out);
 | 
				
			||||||
 | 
					    InnerIterations += CG.IterationsToComplete;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class FieldH, class FieldL>
 | 
				
			||||||
 | 
					class SloppyConjugateGradientLowerPrecPreconditioner :  public LinearOperatorBase<FieldH> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  LinearOperatorBase<FieldL> &linop;
 | 
				
			||||||
 | 
					  ConjugateGradient<FieldL> CG;
 | 
				
			||||||
 | 
					  GridBase* L_grid; //lower-prec Grid
 | 
				
			||||||
 | 
					  int InnerIterations;
 | 
				
			||||||
 | 
					  FieldL tmp_l1;
 | 
				
			||||||
 | 
					  FieldL tmp_l2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SloppyConjugateGradientLowerPrecPreconditioner (LinearOperatorBase<FieldL> &_linop, GridBase* _L_grid, Real _resid, Integer max_iter): linop(_linop), CG(_resid, max_iter), InnerIterations(0), L_grid(_L_grid), tmp_l1(_L_grid), tmp_l2(_L_grid){
 | 
				
			||||||
 | 
					    CG.ErrorOnNoConverge = false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void ResetCounters(){ InnerIterations = 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void OpDiag (const FieldH &in, FieldH &out){ assert(0); }
 | 
				
			||||||
 | 
					  void OpDir  (const FieldH &in, FieldH &out,int dir,int disp){ assert(0); }
 | 
				
			||||||
 | 
					  void Op     (const FieldH &in, FieldH &out){ assert(0); }
 | 
				
			||||||
 | 
					  void AdjOp  (const FieldH &in, FieldH &out){ assert(0); }
 | 
				
			||||||
 | 
					  void HermOpAndNorm(const FieldH &in, FieldH &out,RealD &n1,RealD &n2){ 
 | 
				
			||||||
 | 
					    precisionChange(tmp_l1, in);
 | 
				
			||||||
 | 
					    tmp_l2 = zero;
 | 
				
			||||||
 | 
					    CG(linop,tmp_l1,tmp_l2);    
 | 
				
			||||||
 | 
					    InnerIterations += CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    precisionChange(out, tmp_l2);
 | 
				
			||||||
 | 
					    n2 = norm2(tmp_l2);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  void HermOp(const FieldH &in, FieldH &out){
 | 
				
			||||||
 | 
					    precisionChange(tmp_l1, in);
 | 
				
			||||||
 | 
					    tmp_l2 = zero;
 | 
				
			||||||
 | 
					    CG(linop,tmp_l1,tmp_l2);    
 | 
				
			||||||
 | 
					    InnerIterations += CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    precisionChange(out, tmp_l2);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										963
									
								
								tests/solver/Test_compression.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										963
									
								
								tests/solver/Test_compression.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,963 @@
 | 
				
			|||||||
 | 
					    /*************************************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Grid physics library, www.github.com/paboyle/Grid 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Source file: ./tests/Test_dwf_cg_prec.cc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Copyright (C) 2015
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					    with this program; if not, write to the Free Software Foundation, Inc.,
 | 
				
			||||||
 | 
					    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See the full license in the file "LICENSE" in the top level distribution directory
 | 
				
			||||||
 | 
					    *************************************************************************************/
 | 
				
			||||||
 | 
					    /*  END LEGAL */
 | 
				
			||||||
 | 
					#include<bitset>
 | 
				
			||||||
 | 
					#include <Grid/Grid.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					using namespace Grid;
 | 
				
			||||||
 | 
					using namespace Grid::QCD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Preconditioning:   M psi = chi
 | 
				
			||||||
 | 
					//               =  M P^-1 P psi = chi
 | 
				
			||||||
 | 
					//               =  M P^-1 psi' = chi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Solve for psi' using M P^-1 as operator, then apply  P^-1 psi' = psi 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Inexact preconditioned CG requires slight modification because we want to avoid computing P^-1 exactly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Base classes for iterative processes based on operators
 | 
				
			||||||
 | 
					// single input vec, single output vec.
 | 
				
			||||||
 | 
					/////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//The compressor
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Basic copy of WilsonCompressor for demonstration
 | 
				
			||||||
 | 
					template<class _Hspinor,class _Spinor, class projector>
 | 
				
			||||||
 | 
					class WilsonTestCompressorTemplate
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  int mu,dag;  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void Point(int p) { mu=p; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  WilsonTestCompressorTemplate(int _dag=0){
 | 
				
			||||||
 | 
					    //printf("WilsonTestCompressorTemplate constructor\n");
 | 
				
			||||||
 | 
					    dag = _dag;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef _Spinor         SiteSpinor;
 | 
				
			||||||
 | 
					  typedef _Hspinor     SiteHalfSpinor;
 | 
				
			||||||
 | 
					  typedef _Hspinor SiteHalfCommSpinor;
 | 
				
			||||||
 | 
					  typedef typename SiteHalfSpinor::vector_type     vComplexIn;
 | 
				
			||||||
 | 
					  constexpr static int Nw=sizeof(SiteHalfSpinor)/sizeof(vComplexIn); //number of complex numbers in SiteHalfSpinor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  inline int CommDatumSize(void) {
 | 
				
			||||||
 | 
					    //printf("WilsonTestCompressorTemplate CommDatumSize\n");
 | 
				
			||||||
 | 
					    return sizeof(SiteHalfCommSpinor);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Compress includes precision change if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline void Compress(SiteHalfSpinor *buf,Integer o,const SiteSpinor &in) {
 | 
				
			||||||
 | 
					    //printf("WilsonTestCompressorTemplate Compress\n");
 | 
				
			||||||
 | 
					    projector::Proj(buf[o],in,mu,dag);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Exchange includes precision change if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline void Exchange(SiteHalfSpinor *mp,
 | 
				
			||||||
 | 
					                       SiteHalfSpinor *vp0,
 | 
				
			||||||
 | 
					                       SiteHalfSpinor *vp1,
 | 
				
			||||||
 | 
							       Integer type,Integer o){
 | 
				
			||||||
 | 
					    //printf("WilsonTestCompressorTemplate Exchange\n");
 | 
				
			||||||
 | 
					    exchange(mp[2*o],mp[2*o+1],vp0[o],vp1[o],type);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Have a decompression step if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline void Decompress(SiteHalfSpinor *out,
 | 
				
			||||||
 | 
								 SiteHalfSpinor *in, Integer o) {    
 | 
				
			||||||
 | 
					    //printf("WilsonTestCompressorTemplate Decompress\n");
 | 
				
			||||||
 | 
					    assert(0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Compress Exchange                                 */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline void CompressExchange(SiteHalfSpinor *out0,
 | 
				
			||||||
 | 
								       SiteHalfSpinor *out1,
 | 
				
			||||||
 | 
								       const SiteSpinor *in,
 | 
				
			||||||
 | 
								       Integer j,Integer k, Integer m,Integer type){
 | 
				
			||||||
 | 
					    //printf("WilsonTestCompressorTemplate CompressExchange\n");
 | 
				
			||||||
 | 
					    SiteHalfSpinor temp1, temp2,temp3,temp4;
 | 
				
			||||||
 | 
					    projector::Proj(temp1,in[k],mu,dag);
 | 
				
			||||||
 | 
					    projector::Proj(temp2,in[m],mu,dag);
 | 
				
			||||||
 | 
					    exchange(out0[j],out1[j],temp1,temp2,type);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Pass the info to the stencil */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline bool DecompressionStep(void) { return false; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#elif 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Compressor that unpacks vectorized data to scalar
 | 
				
			||||||
 | 
					template<class _Hspinor,class _Spinor, class projector>
 | 
				
			||||||
 | 
					class WilsonTestCompressorTemplate
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  int mu,dag;  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void Point(int p) { mu=p; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  WilsonTestCompressorTemplate(int _dag=0){
 | 
				
			||||||
 | 
					    dag = _dag;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef _Spinor         SiteSpinor;
 | 
				
			||||||
 | 
					  typedef _Hspinor     SiteHalfSpinor;
 | 
				
			||||||
 | 
					  typedef _Hspinor SiteHalfCommSpinor;
 | 
				
			||||||
 | 
					  typedef typename SiteHalfSpinor::vector_type     vComplexIn;
 | 
				
			||||||
 | 
					  constexpr static int Nw=sizeof(SiteHalfSpinor)/sizeof(vComplexIn); //number of complex numbers in SiteHalfSpinor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef typename SiteHalfSpinor::scalar_object ScalarSiteHalfSpinor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constexpr static int Nsimd = vComplexIn::Nsimd();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  inline int CommDatumSize(void) {
 | 
				
			||||||
 | 
					    return Nsimd*sizeof(ScalarSiteHalfSpinor);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Compress includes precision change if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline void Compress(SiteHalfSpinor *buf,Integer o,const SiteSpinor &in) {
 | 
				
			||||||
 | 
					    SiteHalfSpinor hsp;
 | 
				
			||||||
 | 
					    projector::Proj(hsp,in,mu,dag);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ScalarSiteHalfSpinor* to = (ScalarSiteHalfSpinor*)buf + o*Nsimd;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    std::vector<ScalarSiteHalfSpinor*> extract_args(Nsimd);
 | 
				
			||||||
 | 
					    for(int i=0;i<Nsimd;i++) extract_args[i] = to+i;
 | 
				
			||||||
 | 
					    extract1(hsp,extract_args,0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Exchange includes precision change if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline void Exchange(SiteHalfSpinor *mp,
 | 
				
			||||||
 | 
					                       SiteHalfSpinor *vp0,
 | 
				
			||||||
 | 
					                       SiteHalfSpinor *vp1,
 | 
				
			||||||
 | 
							       Integer type,Integer o){
 | 
				
			||||||
 | 
					    ScalarSiteHalfSpinor* vpp0 = (ScalarSiteHalfSpinor*)vp0 + o*Nsimd;
 | 
				
			||||||
 | 
					    ScalarSiteHalfSpinor* vpp1 = (ScalarSiteHalfSpinor*)vp1 + o*Nsimd;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    std::vector<ScalarSiteHalfSpinor*> merge_args0(Nsimd), merge_args1(Nsimd);
 | 
				
			||||||
 | 
					    for(int i=0;i<Nsimd;i++){
 | 
				
			||||||
 | 
					      merge_args0[i] = vpp0+i;
 | 
				
			||||||
 | 
					      merge_args1[i] = vpp1+i;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SiteHalfSpinor vt0,vt1;
 | 
				
			||||||
 | 
					    merge1(vt0,merge_args0,0);
 | 
				
			||||||
 | 
					    merge1(vt1,merge_args1,0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    exchange(mp[2*o],mp[2*o+1],vt0,vt1,type);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Have a decompression step if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline void Decompress(SiteHalfSpinor *out,
 | 
				
			||||||
 | 
								 SiteHalfSpinor *in, Integer o) {    
 | 
				
			||||||
 | 
					    ScalarSiteHalfSpinor* hin = (ScalarSiteHalfSpinor*)in + o*Nsimd;
 | 
				
			||||||
 | 
					    std::vector<ScalarSiteHalfSpinor*> merge_args(Nsimd);
 | 
				
			||||||
 | 
					    for(int i=0;i<Nsimd;i++) merge_args[i] = hin+i;
 | 
				
			||||||
 | 
					    merge1(out[o],merge_args,0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Compress Exchange                                 */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline void CompressExchange(SiteHalfSpinor *out0,
 | 
				
			||||||
 | 
								       SiteHalfSpinor *out1,
 | 
				
			||||||
 | 
								       const SiteSpinor *in,
 | 
				
			||||||
 | 
								       Integer j,Integer k, Integer m,Integer type){
 | 
				
			||||||
 | 
					    SiteHalfSpinor temp1, temp2,temp3,temp4;
 | 
				
			||||||
 | 
					    projector::Proj(temp1,in[k],mu,dag);
 | 
				
			||||||
 | 
					    projector::Proj(temp2,in[m],mu,dag);
 | 
				
			||||||
 | 
					    exchange(temp3,temp4,temp1,temp2,type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ScalarSiteHalfSpinor* hout0 = (ScalarSiteHalfSpinor*)out0 + j*Nsimd;
 | 
				
			||||||
 | 
					    ScalarSiteHalfSpinor* hout1 = (ScalarSiteHalfSpinor*)out1 + j*Nsimd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<ScalarSiteHalfSpinor*> extract_args0(Nsimd), extract_args1(Nsimd);
 | 
				
			||||||
 | 
					    for(int i=0;i<Nsimd;i++){
 | 
				
			||||||
 | 
					      extract_args0[i] = hout0+i;
 | 
				
			||||||
 | 
					      extract_args1[i] = hout1+i;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    extract1(temp3,extract_args0,0);
 | 
				
			||||||
 | 
					    extract1(temp4,extract_args1,0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Pass the info to the stencil */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline bool DecompressionStep(void) { return true; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Access elements of std::complex
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					inline T & cmplx_reim(std::complex<T> &c, const int reim){
 | 
				
			||||||
 | 
					  return reinterpret_cast<T(&)[2]>(c)[reim];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					inline const T & cmplx_reim(const std::complex<T> &c, const int reim){
 | 
				
			||||||
 | 
					  return reinterpret_cast<const T(&)[2]>(c)[reim];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Pack and unpack float/double to fixed point representation of SZ bits
 | 
				
			||||||
 | 
					template<int SZ>
 | 
				
			||||||
 | 
					struct signedIntMap{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct signedIntMap<8>{ typedef int8_t type; };
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct signedIntMap<16>{ typedef int16_t type; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, int SZ>
 | 
				
			||||||
 | 
					inline typename signedIntMap<SZ>::type packN(T val){
 | 
				
			||||||
 | 
					  return typename signedIntMap<SZ>::type( (1<<(SZ-2) ) * val );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename T, int SZ>
 | 
				
			||||||
 | 
					inline T unpackN(typename signedIntMap<SZ>::type val){
 | 
				
			||||||
 | 
					  return T(val)/(1<<(SZ-2));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct getHalfSpinorColors{
 | 
				
			||||||
 | 
					  //template <typename vtype> using iImplHalfSpinor        = iScalar<iVector<iVector<vtype, Dimension>, Nhs> >;
 | 
				
			||||||
 | 
					  enum { value = sizeof(typename T::element::element)/sizeof(typename T::element::element::element) };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Compressor that compresses to a single magnitude and Nhs*Dimension fixed point integers of size packSize bits
 | 
				
			||||||
 | 
					template<class _Hspinor,class _Spinor, class projector, int packSize = 16>
 | 
				
			||||||
 | 
					class WilsonTestCompressorTemplate
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  int mu,dag;  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void Point(int p) { mu=p; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  WilsonTestCompressorTemplate(int _dag=0){
 | 
				
			||||||
 | 
					    dag = _dag;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef _Spinor         SiteSpinor;
 | 
				
			||||||
 | 
					  typedef _Hspinor     SiteHalfSpinor;
 | 
				
			||||||
 | 
					  typedef _Hspinor SiteHalfCommSpinor;
 | 
				
			||||||
 | 
					  typedef typename SiteHalfSpinor::vector_type     vComplexIn;
 | 
				
			||||||
 | 
					  constexpr static int Nw=sizeof(SiteHalfSpinor)/sizeof(vComplexIn); //number of complex numbers in SiteHalfSpinor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef typename SiteHalfSpinor::scalar_object ScalarSiteHalfSpinor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constexpr static int Nsimd = vComplexIn::Nsimd();
 | 
				
			||||||
 | 
					  constexpr static int Dimension = getHalfSpinorColors<SiteHalfSpinor>::value;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  typedef typename ScalarSiteHalfSpinor::scalar_type stype; //std::complex
 | 
				
			||||||
 | 
					  typedef typename stype::value_type srtype; //float/double
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  //Pack and unpack *scalar* SiteHalfSpinor objects
 | 
				
			||||||
 | 
					  void packSpinor(void* tov, const ScalarSiteHalfSpinor &from){
 | 
				
			||||||
 | 
					    uint8_t* to = (uint8_t*)tov;
 | 
				
			||||||
 | 
					    typedef typename signedIntMap<packSize>::type packedType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    srtype max = 0;
 | 
				
			||||||
 | 
					    for(int s=0;s<Nhs;s++)
 | 
				
			||||||
 | 
					      for(int c=0;c<Dimension;c++)
 | 
				
			||||||
 | 
						for(int reim=0;reim<2;reim++)
 | 
				
			||||||
 | 
						  if(fabs(cmplx_reim( from()(s)(c), reim )) > max )
 | 
				
			||||||
 | 
						    max =  fabs(cmplx_reim( from()(s)(c), reim )) ;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    *( (srtype*)to ) = max; //copy the normalization to the buffer
 | 
				
			||||||
 | 
					    to += sizeof(srtype);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    packedType *top = (packedType*)to;
 | 
				
			||||||
 | 
					    packedType p;
 | 
				
			||||||
 | 
					    srtype q;
 | 
				
			||||||
 | 
					    for(int s=0;s<Nhs;s++)
 | 
				
			||||||
 | 
					      for(int c=0;c<Dimension;c++)
 | 
				
			||||||
 | 
						for(int reim=0;reim<2;reim++){
 | 
				
			||||||
 | 
						  q = cmplx_reim( from()(s)(c), reim );
 | 
				
			||||||
 | 
						  if(max != 0.) q /= max;
 | 
				
			||||||
 | 
						  *(top++) = packN<srtype,packSize>(q);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void packSpinor(void* tov, const SiteHalfSpinor &from){
 | 
				
			||||||
 | 
					    uint8_t* to = (uint8_t*)tov;
 | 
				
			||||||
 | 
					    std::vector<ScalarSiteHalfSpinor> extracted(Nsimd);
 | 
				
			||||||
 | 
					    extract(from,extracted);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static const int incr = sizeof(srtype) + Nhs*Dimension*2*sizeof(typename signedIntMap<packSize>::type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(int i=0;i<Nsimd;i++){
 | 
				
			||||||
 | 
					      packSpinor((void*)to, extracted[i]);
 | 
				
			||||||
 | 
					      to += incr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void unpackSpinor(ScalarSiteHalfSpinor &to, void* fromv){
 | 
				
			||||||
 | 
					    uint8_t* from = (uint8_t*)fromv;
 | 
				
			||||||
 | 
					    typedef typename signedIntMap<packSize>::type packedType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    srtype norm = *( (srtype*)from ); 
 | 
				
			||||||
 | 
					    from += sizeof(srtype);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    packedType *fromp = (packedType*)from;
 | 
				
			||||||
 | 
					    srtype q;
 | 
				
			||||||
 | 
					    for(int s=0;s<Nhs;s++)
 | 
				
			||||||
 | 
					      for(int c=0;c<Dimension;c++)
 | 
				
			||||||
 | 
						for(int reim=0;reim<2;reim++){
 | 
				
			||||||
 | 
						  q = unpackN<srtype,packSize>(*(fromp++) );
 | 
				
			||||||
 | 
						  if(norm != 0.) q *= norm;
 | 
				
			||||||
 | 
						  cmplx_reim( to()(s)(c), reim ) = q;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void unpackSpinor(SiteHalfSpinor &to, void* fromv){
 | 
				
			||||||
 | 
					    uint8_t* from = (uint8_t*)fromv;
 | 
				
			||||||
 | 
					    std::vector<ScalarSiteHalfSpinor> unpacked(Nsimd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static const int incr = sizeof(srtype) + Nhs*Dimension*2*sizeof(typename signedIntMap<packSize>::type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(int i=0;i<Nsimd;i++){
 | 
				
			||||||
 | 
					      unpackSpinor(unpacked[i],(void*)from);
 | 
				
			||||||
 | 
					      from += incr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    merge(to,unpacked);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  inline int CommDatumSize(void) {
 | 
				
			||||||
 | 
					    return Nsimd*(  sizeof(srtype) + Nhs*Dimension*2*sizeof(typename signedIntMap<packSize>::type) );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Compress includes precision change if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  void Compress(SiteHalfSpinor *buf,Integer o,const SiteSpinor &in) {
 | 
				
			||||||
 | 
					    SiteHalfSpinor hsp;
 | 
				
			||||||
 | 
					    projector::Proj(hsp,in,mu,dag);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    uint8_t* to = (uint8_t*)buf + o*CommDatumSize();
 | 
				
			||||||
 | 
					    packSpinor(to, hsp);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Exchange includes precision change if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  void Exchange(SiteHalfSpinor *mp,
 | 
				
			||||||
 | 
					                       SiteHalfSpinor *vp0,
 | 
				
			||||||
 | 
					                       SiteHalfSpinor *vp1,
 | 
				
			||||||
 | 
							       Integer type,Integer o){
 | 
				
			||||||
 | 
					    uint8_t* vpp0 = (uint8_t*)vp0 + o*CommDatumSize();
 | 
				
			||||||
 | 
					    uint8_t* vpp1 = (uint8_t*)vp1 + o*CommDatumSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SiteHalfSpinor vt0, vt1;
 | 
				
			||||||
 | 
					    unpackSpinor(vt0, vpp0);
 | 
				
			||||||
 | 
					    unpackSpinor(vt1, vpp1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    exchange(mp[2*o],mp[2*o+1],vt0,vt1,type);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Have a decompression step if mpi data is not same */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  void Decompress(SiteHalfSpinor *out,
 | 
				
			||||||
 | 
								 SiteHalfSpinor *in, Integer o) {    
 | 
				
			||||||
 | 
					    uint8_t* hin = (uint8_t*)in + o*CommDatumSize();
 | 
				
			||||||
 | 
					    unpackSpinor(out[o],hin);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Compress Exchange                                 */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  void CompressExchange(SiteHalfSpinor *out0,
 | 
				
			||||||
 | 
								       SiteHalfSpinor *out1,
 | 
				
			||||||
 | 
								       const SiteSpinor *in,
 | 
				
			||||||
 | 
								       Integer j,Integer k, Integer m,Integer type){
 | 
				
			||||||
 | 
					    SiteHalfSpinor temp1, temp2,temp3,temp4;
 | 
				
			||||||
 | 
					    projector::Proj(temp1,in[k],mu,dag);
 | 
				
			||||||
 | 
					    projector::Proj(temp2,in[m],mu,dag);
 | 
				
			||||||
 | 
					    exchange(temp3,temp4,temp1,temp2,type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t* hout0 = (uint8_t*)out0 + j*CommDatumSize();
 | 
				
			||||||
 | 
					    uint8_t* hout1 = (uint8_t*)out1 + j*CommDatumSize();
 | 
				
			||||||
 | 
					    packSpinor(hout0, temp3);
 | 
				
			||||||
 | 
					    packSpinor(hout1, temp4);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  /* Pass the info to the stencil */
 | 
				
			||||||
 | 
					  /*****************************************************/
 | 
				
			||||||
 | 
					  inline bool DecompressionStep(void) { return true; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename HS,typename S, int packSize> using WilsonTestCompressor = WilsonTestCompressorTemplate<HS,S,WilsonProjector,packSize>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class vobj,class cobj>
 | 
				
			||||||
 | 
					class WilsonStencilBasic : public CartesianStencil<vobj,cobj> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  double timer0;
 | 
				
			||||||
 | 
					  double timer1;
 | 
				
			||||||
 | 
					  double timer2;
 | 
				
			||||||
 | 
					  double timer3;
 | 
				
			||||||
 | 
					  double timer4;
 | 
				
			||||||
 | 
					  double timer5;
 | 
				
			||||||
 | 
					  double timer6;
 | 
				
			||||||
 | 
					  uint64_t callsi;
 | 
				
			||||||
 | 
					  void ZeroCountersi(void)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    timer0=0;
 | 
				
			||||||
 | 
					    timer1=0;
 | 
				
			||||||
 | 
					    timer2=0;
 | 
				
			||||||
 | 
					    timer3=0;
 | 
				
			||||||
 | 
					    timer4=0;
 | 
				
			||||||
 | 
					    timer5=0;
 | 
				
			||||||
 | 
					    timer6=0;
 | 
				
			||||||
 | 
					    callsi=0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  void Reporti(int calls)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    if ( timer0 ) std::cout << GridLogMessage << " timer0 (HaloGatherOpt) " <<timer0/calls <<std::endl;
 | 
				
			||||||
 | 
					    if ( timer1 ) std::cout << GridLogMessage << " timer1 (Communicate)   " <<timer1/calls <<std::endl;
 | 
				
			||||||
 | 
					    if ( timer2 ) std::cout << GridLogMessage << " timer2 (CommsMerge )   " <<timer2/calls <<std::endl;
 | 
				
			||||||
 | 
					    if ( timer3 ) std::cout << GridLogMessage << " timer3 (commsMergeShm) " <<timer3/calls <<std::endl;
 | 
				
			||||||
 | 
					    if ( timer4 ) std::cout << GridLogMessage << " timer4 " <<timer4 <<std::endl;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::vector<int> same_node;
 | 
				
			||||||
 | 
					  std::vector<int> surface_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  WilsonStencilBasic(GridBase *grid,
 | 
				
			||||||
 | 
							int npoints,
 | 
				
			||||||
 | 
							int checkerboard,
 | 
				
			||||||
 | 
							const std::vector<int> &directions,
 | 
				
			||||||
 | 
							const std::vector<int> &distances)  
 | 
				
			||||||
 | 
					    : CartesianStencil<vobj,cobj> (grid,npoints,checkerboard,directions,distances) ,
 | 
				
			||||||
 | 
					    same_node(npoints)
 | 
				
			||||||
 | 
					  { 
 | 
				
			||||||
 | 
					    ZeroCountersi();
 | 
				
			||||||
 | 
					    surface_list.resize(0);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void BuildSurfaceList(int Ls,int vol4){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // find same node for SHM
 | 
				
			||||||
 | 
					    // Here we know the distance is 1 for WilsonStencil
 | 
				
			||||||
 | 
					    for(int point=0;point<this->_npoints;point++){
 | 
				
			||||||
 | 
					      same_node[point] = this->SameNode(point);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for(int site = 0 ;site< vol4;site++){
 | 
				
			||||||
 | 
					      int local = 1;
 | 
				
			||||||
 | 
					      for(int point=0;point<this->_npoints;point++){
 | 
				
			||||||
 | 
						if( (!this->GetNodeLocal(site*Ls,point)) && (!same_node[point]) ){ 
 | 
				
			||||||
 | 
						  local = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if(local == 0) { 
 | 
				
			||||||
 | 
						surface_list.push_back(site);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  template < class compressor>
 | 
				
			||||||
 | 
					  void HaloExchangeOpt(const Lattice<vobj> &source,compressor &compress) 
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    std::vector<std::vector<CommsRequest_t> > reqs;
 | 
				
			||||||
 | 
					    this->HaloExchangeOptGather(source,compress);
 | 
				
			||||||
 | 
					    double t1=usecond();
 | 
				
			||||||
 | 
					    this->Communicate();
 | 
				
			||||||
 | 
					    double t2=usecond(); timer1 += t2-t1;
 | 
				
			||||||
 | 
					    this->CommsMerge(compress);
 | 
				
			||||||
 | 
					    double t3=usecond(); timer2 += t3-t2;
 | 
				
			||||||
 | 
					    this->CommsMergeSHM(compress);
 | 
				
			||||||
 | 
					    double t4=usecond(); timer3 += t4-t3;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  template <class compressor>
 | 
				
			||||||
 | 
					  void HaloExchangeOptGather(const Lattice<vobj> &source,compressor &compress){
 | 
				
			||||||
 | 
					    this->Prepare();
 | 
				
			||||||
 | 
					    double t0=usecond();
 | 
				
			||||||
 | 
					    this->HaloGatherOpt(source,compress);
 | 
				
			||||||
 | 
					    double t1=usecond();
 | 
				
			||||||
 | 
					    timer0 += t1-t0;
 | 
				
			||||||
 | 
					    callsi++;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  template <class compressor>
 | 
				
			||||||
 | 
					  void HaloGatherOpt(const Lattice<vobj> &source,compressor &compress)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    this->halogtime-=usecond();
 | 
				
			||||||
 | 
					    this->HaloGather(source,compress);
 | 
				
			||||||
 | 
					    this->halogtime+=usecond();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//This is hideous
 | 
				
			||||||
 | 
					template<class S, int packSize = 16>
 | 
				
			||||||
 | 
					class WilsonCompressedCommsImpl: public WilsonImpl<S,FundamentalRepresentation,CoeffReal>{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  typedef WilsonImpl<S,FundamentalRepresentation,CoeffReal> WilsonBase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define INHERIT_BASE(TYPE) typedef typename WilsonBase::TYPE TYPE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  INHERIT_BASE(Gimpl);
 | 
				
			||||||
 | 
					  INHERIT_GIMPL_TYPES(Gimpl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  INHERIT_BASE(Coeff_t);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  INHERIT_BASE(SiteSpinor);
 | 
				
			||||||
 | 
					  INHERIT_BASE(SitePropagator);
 | 
				
			||||||
 | 
					  INHERIT_BASE(SiteHalfSpinor);
 | 
				
			||||||
 | 
					  INHERIT_BASE(SiteHalfCommSpinor);    
 | 
				
			||||||
 | 
					  INHERIT_BASE(SiteDoubledGaugeField);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  INHERIT_BASE(FermionField);
 | 
				
			||||||
 | 
					  INHERIT_BASE(PropagatorField);
 | 
				
			||||||
 | 
					  INHERIT_BASE(DoubledGaugeField);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  //typedef WilsonCompressor<SiteHalfCommSpinor,SiteHalfSpinor, SiteSpinor> Compressor;
 | 
				
			||||||
 | 
					  typedef WilsonTestCompressor<SiteHalfSpinor, SiteSpinor, packSize> Compressor;  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  INHERIT_BASE(ImplParams);
 | 
				
			||||||
 | 
					  //INHERIT_BASE(StencilImpl);
 | 
				
			||||||
 | 
					  typedef WilsonStencilBasic<SiteSpinor, SiteHalfSpinor> StencilImpl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  WilsonCompressedCommsImpl(const ImplParams &p = ImplParams()) : WilsonBase(p){}
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  inline void multLink(SiteHalfSpinor &phi,
 | 
				
			||||||
 | 
							       const SiteDoubledGaugeField &U,
 | 
				
			||||||
 | 
							       const SiteHalfSpinor &chi,
 | 
				
			||||||
 | 
							       int mu,
 | 
				
			||||||
 | 
							       StencilEntry *SE,
 | 
				
			||||||
 | 
							       StencilImpl &St) {
 | 
				
			||||||
 | 
					    mult(&phi(), &U(mu), &chi());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef INHERIT_BASE
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef WilsonCompressedCommsImpl<vComplexF,8> WilsonCompressedComms8ImplF;
 | 
				
			||||||
 | 
					typedef WilsonCompressedCommsImpl<vComplexD,8> WilsonCompressedComms8ImplD;
 | 
				
			||||||
 | 
					typedef WilsonCompressedCommsImpl<vComplexF,16> WilsonCompressedComms16ImplF;
 | 
				
			||||||
 | 
					typedef WilsonCompressedCommsImpl<vComplexD,16> WilsonCompressedComms16ImplD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TO_INSTANTIATE \
 | 
				
			||||||
 | 
					  DOIT(WilsonCompressedComms8ImplF)\
 | 
				
			||||||
 | 
					  DOIT(WilsonCompressedComms8ImplD)\
 | 
				
			||||||
 | 
					  DOIT(WilsonCompressedComms16ImplF)\
 | 
				
			||||||
 | 
					  DOIT(WilsonCompressedComms16ImplD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "InstantiateImpl.impl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef TO_INSTANTIATE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef DomainWallFermion<WilsonCompressedComms8ImplD> DomainWallFermionCompressedComms8D;
 | 
				
			||||||
 | 
					typedef DomainWallFermion<WilsonCompressedComms8ImplF> DomainWallFermionCompressedComms8F;
 | 
				
			||||||
 | 
					typedef DomainWallFermion<WilsonCompressedComms16ImplD> DomainWallFermionCompressedComms16D;
 | 
				
			||||||
 | 
					typedef DomainWallFermion<WilsonCompressedComms16ImplF> DomainWallFermionCompressedComms16F;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T parse(const std::string &name, std::istream &in){
 | 
				
			||||||
 | 
					  std::string p;
 | 
				
			||||||
 | 
					  in >> p;
 | 
				
			||||||
 | 
					  assert(p==name);
 | 
				
			||||||
 | 
					  char eq;
 | 
				
			||||||
 | 
					  in >> eq;
 | 
				
			||||||
 | 
					  assert(eq == '=');
 | 
				
			||||||
 | 
					  T out;
 | 
				
			||||||
 | 
					  in >> out;
 | 
				
			||||||
 | 
					  return out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main (int argc, char ** argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Grid_init(&argc,&argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int Ls=8;
 | 
				
			||||||
 | 
					  RealD mass=0.1;
 | 
				
			||||||
 | 
					  RealD outer_tol = 1e-8;
 | 
				
			||||||
 | 
					  RealD inner_tol_full = 1e-5;
 | 
				
			||||||
 | 
					  RealD inner_tol_half = 1e-5;
 | 
				
			||||||
 | 
					  RealD inner_tol_16c = 1e-5;
 | 
				
			||||||
 | 
					  RealD inner_tol_8c = 1e-5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  RealD relup_delta_full = 0.1;
 | 
				
			||||||
 | 
					  RealD relup_delta_half = 0.1;
 | 
				
			||||||
 | 
					  RealD relup_delta_16c = 0.1;
 | 
				
			||||||
 | 
					  RealD relup_delta_8c = 0.1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::string config_file = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for(int i=1;i<argc;i++){
 | 
				
			||||||
 | 
					    if(std::string(argv[i]) == "--params"){
 | 
				
			||||||
 | 
					      std::ifstream f(argv[i+1]);
 | 
				
			||||||
 | 
					      f.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
 | 
				
			||||||
 | 
					      Ls = parse<int>("Ls", f);
 | 
				
			||||||
 | 
					#define PARSEIT(NM) NM = parse<RealD>(#NM, f)
 | 
				
			||||||
 | 
					      PARSEIT(mass);
 | 
				
			||||||
 | 
					      PARSEIT(outer_tol);
 | 
				
			||||||
 | 
					      PARSEIT(inner_tol_full);
 | 
				
			||||||
 | 
					      PARSEIT(inner_tol_half);
 | 
				
			||||||
 | 
					      PARSEIT(inner_tol_16c);
 | 
				
			||||||
 | 
					      PARSEIT(inner_tol_8c);
 | 
				
			||||||
 | 
					      PARSEIT(relup_delta_full);
 | 
				
			||||||
 | 
					      PARSEIT(relup_delta_half);
 | 
				
			||||||
 | 
					      PARSEIT(relup_delta_16c);
 | 
				
			||||||
 | 
					      PARSEIT(relup_delta_8c);
 | 
				
			||||||
 | 
					#undef PARSEIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //f >> outer_tol >> inner_tol_full >> inner_tol_half >> inner_tol_16c >> inner_tol_8c;      
 | 
				
			||||||
 | 
					    }else if(std::string(argv[i]) == "--config"){
 | 
				
			||||||
 | 
					      config_file = argv[i+1];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  GridCartesian         * UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplexD::Nsimd()),GridDefaultMpi());
 | 
				
			||||||
 | 
					  GridRedBlackCartesian * UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid);
 | 
				
			||||||
 | 
					  GridCartesian         * FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid);
 | 
				
			||||||
 | 
					  GridRedBlackCartesian * FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,UGrid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GridCartesian         * UGrid_f   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplexF::Nsimd()),GridDefaultMpi());
 | 
				
			||||||
 | 
					  GridRedBlackCartesian * UrbGrid_f = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid_f);
 | 
				
			||||||
 | 
					  GridCartesian         * FGrid_f   = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid_f);
 | 
				
			||||||
 | 
					  GridRedBlackCartesian * FrbGrid_f = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,UGrid_f);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LatticeFermionD    src(FGrid); random(RNG5,src);
 | 
				
			||||||
 | 
					  LatticeFermionD result(FGrid); result=zero;
 | 
				
			||||||
 | 
					  LatticeGaugeFieldD Umu(UGrid);
 | 
				
			||||||
 | 
					  LatticeGaugeFieldF Umu_f(UGrid_f); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(config_file.size() > 0){
 | 
				
			||||||
 | 
					    FieldMetaData header;
 | 
				
			||||||
 | 
					    NerscIO::readConfiguration(Umu,header,config_file);
 | 
				
			||||||
 | 
					  }else{
 | 
				
			||||||
 | 
					    SU3::HotConfiguration(RNG4,Umu);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  precisionChange(Umu_f,Umu);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  RealD M5=1.8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LatticeFermionD    src_o(FrbGrid);
 | 
				
			||||||
 | 
					  pickCheckerboard(Odd,src_o,src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(0){ //Test preconditioned CG
 | 
				
			||||||
 | 
					    LatticeFermionD result_o(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_2(FrbGrid);
 | 
				
			||||||
 | 
					    result_o.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o = zero;
 | 
				
			||||||
 | 
					    result_o_2.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o_2 = zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DomainWallFermionD Ddwf(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf);
 | 
				
			||||||
 | 
					    //DoNothingLinearOperator<LatticeFermionD> Prec;
 | 
				
			||||||
 | 
					    //FixedIterConjugateGradientPreconditioner<LatticeFermionD> Prec(HermOpEO, 20);
 | 
				
			||||||
 | 
					    SloppyConjugateGradientPreconditioner<LatticeFermionD> Prec(HermOpEO, 1e-2, 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Preconditioned CG" << std::endl;
 | 
				
			||||||
 | 
					    InexactPreconditionedConjugateGradient<LatticeFermionD> pCG(Prec,1.0e-8,10000);
 | 
				
			||||||
 | 
					    pCG(HermOpEO,src_o,result_o);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting regular CG" << std::endl;
 | 
				
			||||||
 | 
					    ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000);
 | 
				
			||||||
 | 
					    CG(HermOpEO,src_o,result_o_2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LatticeFermionD diff_o(FrbGrid);
 | 
				
			||||||
 | 
					    RealD diff = axpy_norm(diff_o, -1.0, result_o, result_o_2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "pCG HermOp applications " << pCG.IterationsToComplete << "(outer) + " << Prec.InnerIterations << "(inner) = " << pCG.IterationsToComplete + Prec.InnerIterations << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "CG HermOp applications " << CG.IterationsToComplete << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Diff between results: " << diff << std::endl;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(0){ //Test compressor
 | 
				
			||||||
 | 
					    LatticeFermionD result_o(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_2(FrbGrid);
 | 
				
			||||||
 | 
					    result_o.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o = zero;
 | 
				
			||||||
 | 
					    result_o_2.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o_2 = zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DomainWallFermionD Ddwf(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DomainWallFermionCompressedComms16D DdwfC(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionCompressedComms16D,LatticeFermionD> HermOpEOC(DdwfC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting regular CG with compressed operator" << std::endl;
 | 
				
			||||||
 | 
					    Integer iter1;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000);
 | 
				
			||||||
 | 
					      CG.ErrorOnNoConverge = false;
 | 
				
			||||||
 | 
					      CG(HermOpEOC,src_o,result_o);
 | 
				
			||||||
 | 
					      iter1 = CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Integer iter2;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      std::cout << "Starting regular CG" << std::endl;
 | 
				
			||||||
 | 
					      ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000);
 | 
				
			||||||
 | 
					      CG(HermOpEO,src_o,result_o_2);
 | 
				
			||||||
 | 
					      iter2 = CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LatticeFermionD diff_o(FrbGrid);
 | 
				
			||||||
 | 
					    RealD diff = axpy_norm(diff_o, -1.0, result_o, result_o_2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "CG HermOp CC applications " << iter1 << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "CG HermOp applications " << iter2 << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Diff between results: " << diff << std::endl;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if(1){ //Compare mixed prec restarted single/single internal with same but with single/compressed
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_full(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_half(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_16(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_8(FrbGrid);
 | 
				
			||||||
 | 
					    result_o_full.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o_full = zero;
 | 
				
			||||||
 | 
					    result_o_16 = result_o_8 = result_o_half = result_o_full;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Std
 | 
				
			||||||
 | 
					    DomainWallFermionD Ddwf(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DomainWallFermionF Ddwf_f(Umu_f,*FGrid_f,*FrbGrid_f,*UGrid_f,*UrbGrid_f,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionF,LatticeFermionF> HermOpEO_f(Ddwf_f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //1/2 prec
 | 
				
			||||||
 | 
					    DomainWallFermionFH Ddwfhalf_f(Umu_f,*FGrid_f,*FrbGrid_f,*UGrid_f,*UrbGrid_f,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionFH,LatticeFermionF> HermOpEOhalf_f(Ddwfhalf_f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //16
 | 
				
			||||||
 | 
					    DomainWallFermionCompressedComms16F DdwfC16_f(Umu_f,*FGrid_f,*FrbGrid_f,*UGrid_f,*UrbGrid_f,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionCompressedComms16F,LatticeFermionF> HermOpEOC16_f(DdwfC16_f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //8
 | 
				
			||||||
 | 
					    DomainWallFermionCompressedComms8F DdwfC8_f(Umu_f,*FGrid_f,*FrbGrid_f,*UGrid_f,*UrbGrid_f,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionCompressedComms8F,LatticeFermionF> HermOpEOC8_f(DdwfC8_f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #define ALGORITHM_MIXEDCG
 | 
				
			||||||
 | 
					    //#define ALGORITHM_RELUP
 | 
				
			||||||
 | 
					    //#define ALGORITHM_SLOPPY_PREC_CG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef ALGORITHM_MIXEDCG
 | 
				
			||||||
 | 
					    std::cout << "Starting mixed CG with single/compressed-16 inner\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Integer inner_16, outer_16, patchup_16;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      MixedPrecisionConjugateGradient<LatticeFermionD,LatticeFermionF> mCG(outer_tol, 10000, 50, FrbGrid_f, HermOpEOC16_f, HermOpEO);
 | 
				
			||||||
 | 
					      mCG.InnerTolerance = inner_tol_16c;
 | 
				
			||||||
 | 
					      mCG(src_o,result_o_16);
 | 
				
			||||||
 | 
					      inner_16 = mCG.TotalInnerIterations; outer_16 = mCG.TotalOuterIterations; patchup_16 = mCG.TotalFinalStepIterations;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting mixed CG with single/compressed-8 inner\n";
 | 
				
			||||||
 | 
					    Integer inner_8, outer_8, patchup_8;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      MixedPrecisionConjugateGradient<LatticeFermionD,LatticeFermionF> mCG(outer_tol, 10000, 50, FrbGrid_f, HermOpEOC8_f, HermOpEO);
 | 
				
			||||||
 | 
					      mCG.InnerTolerance = inner_tol_8c;
 | 
				
			||||||
 | 
					      mCG(src_o,result_o_8);
 | 
				
			||||||
 | 
					      inner_8 = mCG.TotalInnerIterations; outer_8 = mCG.TotalOuterIterations; patchup_8 = mCG.TotalFinalStepIterations;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting mixed CG with single/half inner\n";
 | 
				
			||||||
 | 
					    Integer inner_half, outer_half, patchup_half;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      MixedPrecisionConjugateGradient<LatticeFermionD,LatticeFermionF> mCG(outer_tol, 10000, 50, FrbGrid_f, HermOpEOhalf_f, HermOpEO);
 | 
				
			||||||
 | 
					      mCG.InnerTolerance = inner_tol_half;
 | 
				
			||||||
 | 
					      mCG(src_o,result_o_half);
 | 
				
			||||||
 | 
					      inner_half = mCG.TotalInnerIterations; outer_half = mCG.TotalOuterIterations; patchup_half = mCG.TotalFinalStepIterations;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting mixed CG with single/single inner\n";
 | 
				
			||||||
 | 
					    Integer inner_full, outer_full, patchup_full;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      MixedPrecisionConjugateGradient<LatticeFermionD,LatticeFermionF> mCG(outer_tol, 10000, 50, FrbGrid_f, HermOpEO_f, HermOpEO);
 | 
				
			||||||
 | 
					      mCG.InnerTolerance = inner_tol_full;
 | 
				
			||||||
 | 
					      mCG(src_o,result_o_full);
 | 
				
			||||||
 | 
					      inner_full = mCG.TotalInnerIterations; outer_full = mCG.TotalOuterIterations; patchup_full = mCG.TotalFinalStepIterations;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#elif defined(ALGORITHM_RELUP)
 | 
				
			||||||
 | 
					    std::cout << "Starting relup CG with single/compressed-16 inner\n";    
 | 
				
			||||||
 | 
					    Integer inner_16, outer_16, patchup_16;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ConjugateGradientReliableUpdate<LatticeFermionD,LatticeFermionF> relup(outer_tol, 2000, relup_delta_16c, FrbGrid_f, HermOpEOC16_f, HermOpEO);
 | 
				
			||||||
 | 
					      relup(src_o,result_o_16);
 | 
				
			||||||
 | 
					      inner_16 = relup.IterationsToComplete; outer_16 = relup.ReliableUpdatesPerformed; patchup_16 = relup.IterationsToCleanup;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting relup CG with single/compressed-8 inner\n";
 | 
				
			||||||
 | 
					    Integer inner_8, outer_8, patchup_8;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ConjugateGradientReliableUpdate<LatticeFermionD,LatticeFermionF> relup(outer_tol, 2000, relup_delta_8c, FrbGrid_f, HermOpEOC8_f, HermOpEO);
 | 
				
			||||||
 | 
					      relup.ErrorOnNoConverge = false;
 | 
				
			||||||
 | 
					      relup(src_o,result_o_8);
 | 
				
			||||||
 | 
					      inner_8 = relup.IterationsToComplete; outer_8 = relup.ReliableUpdatesPerformed; patchup_8 = relup.IterationsToCleanup;     
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting relup CG with single/half inner\n";
 | 
				
			||||||
 | 
					    Integer inner_half, outer_half, patchup_half;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ConjugateGradientReliableUpdate<LatticeFermionD,LatticeFermionF> relup(outer_tol, 2000, relup_delta_half, FrbGrid_f, HermOpEOhalf_f, HermOpEO);
 | 
				
			||||||
 | 
					      relup(src_o,result_o_half);
 | 
				
			||||||
 | 
					      inner_half = relup.IterationsToComplete; outer_half = relup.ReliableUpdatesPerformed; patchup_half = relup.IterationsToCleanup;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting relup CG with single/single inner\n";
 | 
				
			||||||
 | 
					    Integer inner_full, outer_full, patchup_full;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ConjugateGradientReliableUpdate<LatticeFermionD,LatticeFermionF> relup(outer_tol, 2000, relup_delta_full, FrbGrid_f, HermOpEO_f, HermOpEO);
 | 
				
			||||||
 | 
					      relup(src_o,result_o_full);
 | 
				
			||||||
 | 
					      inner_full = relup.IterationsToComplete; outer_full = relup.ReliableUpdatesPerformed; patchup_full = relup.IterationsToCleanup;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#elif defined(ALGORITHM_SLOPPY_PREC_CG)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting sloppy pCG with single/compressed-16 inner\n";    
 | 
				
			||||||
 | 
					    Integer inner_16, outer_16;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      SloppyConjugateGradientLowerPrecPreconditioner<LatticeFermionD,LatticeFermionF> prec(HermOpEOC16_f, FrbGrid_f, inner_tol_16c, 1000);
 | 
				
			||||||
 | 
					      InexactPreconditionedConjugateGradient<LatticeFermionD> CG(prec, outer_tol, 100);
 | 
				
			||||||
 | 
					      CG(HermOpEO,src_o,result_o_16);
 | 
				
			||||||
 | 
					      inner_16 = prec.InnerIterations; outer_16 = CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting sloppy pCG with single/compressed-8 inner\n";    
 | 
				
			||||||
 | 
					    Integer inner_8, outer_8;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      SloppyConjugateGradientLowerPrecPreconditioner<LatticeFermionD,LatticeFermionF> prec(HermOpEOC8_f, FrbGrid_f, inner_tol_8c, 1000);
 | 
				
			||||||
 | 
					      InexactPreconditionedConjugateGradient<LatticeFermionD> CG(prec, outer_tol, 100);
 | 
				
			||||||
 | 
					      CG(HermOpEO,src_o,result_o_8);
 | 
				
			||||||
 | 
					      inner_8 = prec.InnerIterations; outer_8 = CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting sloppy pCG with single/half inner\n";    
 | 
				
			||||||
 | 
					    Integer inner_half, outer_half;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      SloppyConjugateGradientLowerPrecPreconditioner<LatticeFermionD,LatticeFermionF> prec(HermOpEOhalf_f, FrbGrid_f, inner_tol_half, 1000);
 | 
				
			||||||
 | 
					      InexactPreconditionedConjugateGradient<LatticeFermionD> CG(prec, outer_tol, 100);
 | 
				
			||||||
 | 
					      CG(HermOpEO,src_o,result_o_half);
 | 
				
			||||||
 | 
					      inner_half = prec.InnerIterations; outer_half = CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting sloppy pCG with single/single inner\n";    
 | 
				
			||||||
 | 
					    Integer inner_full, outer_full;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      SloppyConjugateGradientLowerPrecPreconditioner<LatticeFermionD,LatticeFermionF> prec(HermOpEO_f, FrbGrid_f, inner_tol_full, 1000);
 | 
				
			||||||
 | 
					      InexactPreconditionedConjugateGradient<LatticeFermionD> CG(prec, outer_tol, 100);
 | 
				
			||||||
 | 
					      CG(HermOpEO,src_o,result_o_full);
 | 
				
			||||||
 | 
					      inner_full = prec.InnerIterations; outer_full = CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Ls " << Ls << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Mass " << mass << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Outer tolerance " << outer_tol << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(ALGORITHM_MIXEDCG) || defined(ALGORITHM_SLOPPY_PREC_CG)
 | 
				
			||||||
 | 
					    std::cout << "Inner tol full " << inner_tol_full << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Inner tol 1/2 prec " << inner_tol_half << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Inner tol compressed-16 " << inner_tol_16c << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Inner tol compressed-8 " << inner_tol_8c << std::endl;
 | 
				
			||||||
 | 
					#elif defined(ALGORITHM_RELUP)
 | 
				
			||||||
 | 
					    std::cout << "Relup delta full " << relup_delta_full << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Relup delta 1/2 prec " << relup_delta_half << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Relup delta compressed-16 " << relup_delta_16c << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Relup delta compressed-8 " << relup_delta_8c << std::endl;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    LatticeFermionD diff_o(FrbGrid);
 | 
				
			||||||
 | 
					    RealD diff = axpy_norm(diff_o, -1.0, result_o_16, result_o_full);
 | 
				
			||||||
 | 
					    std::cout << "Diff between results (s/c16): " << diff << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    diff = axpy_norm(diff_o, -1.0, result_o_8, result_o_full);
 | 
				
			||||||
 | 
					    std::cout << "Diff between results (s/c8): " << diff << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    diff = axpy_norm(diff_o, -1.0, result_o_half, result_o_full);
 | 
				
			||||||
 | 
					    std::cout << "Diff between results (s/h): " << diff << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(ALGORITHM_MIXEDCG) || defined(ALGORITHM_RELUP)
 | 
				
			||||||
 | 
					    std::cout << "Iterations (s/c16) inner: " << inner_16 << " outer: " << outer_16 << " patchup: " << patchup_16 << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Iterations (s/c8) inner: " << inner_8 << " outer: " << outer_8 << " patchup: " << patchup_8 << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Iterations (s/h) inner: " << inner_half << " outer: " << outer_half << " patchup: " << patchup_half << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Iterations (s/s) inner: " << inner_full << " outer: " << outer_full << " patchup: " << patchup_full << std::endl;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    std::cout << "Iterations (s/c16) inner: " << inner_16 << " outer: " << outer_16 << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Iterations (s/c8) inner: " << inner_8 << " outer: " << outer_8 << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Iterations (s/h) inner: " << inner_half << " outer: " << outer_half << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Iterations (s/s) inner: " << inner_full << " outer: " << outer_full << std::endl;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Grid_finalize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										247
									
								
								tests/solver/Test_pcg.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								tests/solver/Test_pcg.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,247 @@
 | 
				
			|||||||
 | 
					    /*************************************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Grid physics library, www.github.com/paboyle/Grid 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Source file: ./tests/Test_pcg.cc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Copyright (C) 2015
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					    with this program; if not, write to the Free Software Foundation, Inc.,
 | 
				
			||||||
 | 
					    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See the full license in the file "LICENSE" in the top level distribution directory
 | 
				
			||||||
 | 
					    *************************************************************************************/
 | 
				
			||||||
 | 
					    /*  END LEGAL */
 | 
				
			||||||
 | 
					#include<bitset>
 | 
				
			||||||
 | 
					#include <Grid/Grid.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					using namespace Grid;
 | 
				
			||||||
 | 
					using namespace Grid::QCD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Preconditioning:   M psi = chi
 | 
				
			||||||
 | 
					//               =  M P^-1 P psi = chi
 | 
				
			||||||
 | 
					//               =  M P^-1 psi' = chi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Solve for psi' using M P^-1 as operator, then apply  P^-1 psi' = psi 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Inexact preconditioned CG requires slight modification because we want to avoid computing P^-1 exactly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// Base classes for iterative processes based on operators
 | 
				
			||||||
 | 
					// single input vec, single output vec.
 | 
				
			||||||
 | 
					/////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T parse(const std::string &name, std::istream &in){
 | 
				
			||||||
 | 
					  std::string p;
 | 
				
			||||||
 | 
					  in >> p;
 | 
				
			||||||
 | 
					  assert(p==name);
 | 
				
			||||||
 | 
					  char eq;
 | 
				
			||||||
 | 
					  in >> eq;
 | 
				
			||||||
 | 
					  assert(eq == '=');
 | 
				
			||||||
 | 
					  T out;
 | 
				
			||||||
 | 
					  in >> out;
 | 
				
			||||||
 | 
					  return out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main (int argc, char ** argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Grid_init(&argc,&argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int Ls=12;
 | 
				
			||||||
 | 
					  RealD mass=0.01;
 | 
				
			||||||
 | 
					  RealD outer_tol = 1e-8;
 | 
				
			||||||
 | 
					  RealD inner_tol_full = 1e-5;
 | 
				
			||||||
 | 
					  RealD inner_tol_half = 1e-5;
 | 
				
			||||||
 | 
					  RealD inner_tol_16c = 1e-5;
 | 
				
			||||||
 | 
					  RealD inner_tol_8c = 1e-5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  RealD relup_delta_full = 0.1;
 | 
				
			||||||
 | 
					  RealD relup_delta_half = 0.1;
 | 
				
			||||||
 | 
					  RealD relup_delta_16c = 0.1;
 | 
				
			||||||
 | 
					  RealD relup_delta_8c = 0.1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::string config_file = "";
 | 
				
			||||||
 | 
					  RealD lo = 1.0;
 | 
				
			||||||
 | 
					  RealD hi = 64.0;
 | 
				
			||||||
 | 
					  int   order=10;
 | 
				
			||||||
 | 
					  for(int i=1;i<argc;i++){
 | 
				
			||||||
 | 
					    if(std::string(argv[i]) == "--params"){
 | 
				
			||||||
 | 
					      std::ifstream f(argv[i+1]);
 | 
				
			||||||
 | 
					      f.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
 | 
				
			||||||
 | 
					      Ls = parse<int>("Ls", f);
 | 
				
			||||||
 | 
					#define PARSEIT(NM) NM = parse<RealD>(#NM, f)
 | 
				
			||||||
 | 
					      PARSEIT(mass);
 | 
				
			||||||
 | 
					      PARSEIT(outer_tol);
 | 
				
			||||||
 | 
					      PARSEIT(inner_tol_full);
 | 
				
			||||||
 | 
					      PARSEIT(inner_tol_half);
 | 
				
			||||||
 | 
					      PARSEIT(inner_tol_16c);
 | 
				
			||||||
 | 
					      PARSEIT(inner_tol_8c);
 | 
				
			||||||
 | 
					      PARSEIT(relup_delta_full);
 | 
				
			||||||
 | 
					      PARSEIT(relup_delta_half);
 | 
				
			||||||
 | 
					      PARSEIT(relup_delta_16c);
 | 
				
			||||||
 | 
					      PARSEIT(relup_delta_8c);
 | 
				
			||||||
 | 
					#undef PARSEIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //f >> outer_tol >> inner_tol_full >> inner_tol_half >> inner_tol_16c >> inner_tol_8c;      
 | 
				
			||||||
 | 
					    }else if(std::string(argv[i]) == "--config"){
 | 
				
			||||||
 | 
					      config_file = argv[i+1];
 | 
				
			||||||
 | 
					    }else if(std::string(argv[i]) == "--order"){
 | 
				
			||||||
 | 
					      std::string ss(argv[i+1]);
 | 
				
			||||||
 | 
					      std::stringstream f(ss);
 | 
				
			||||||
 | 
					      f>>order; std::cout << " Order poly set to " <<order<<std::endl;
 | 
				
			||||||
 | 
					    }else if(std::string(argv[i]) == "--lo"){
 | 
				
			||||||
 | 
					      std::string ss(argv[i+1]);
 | 
				
			||||||
 | 
					      std::stringstream f(ss);
 | 
				
			||||||
 | 
					      f>>lo; std::cout << " Lo poly set to " <<lo<<std::endl;
 | 
				
			||||||
 | 
					    }else if(std::string(argv[i]) == "--hi"){
 | 
				
			||||||
 | 
					      std::string ss(argv[i+1]);
 | 
				
			||||||
 | 
					      std::stringstream f(ss);
 | 
				
			||||||
 | 
					      f>>hi; std::cout << " Hi poly set to " <<hi<<std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  GridCartesian         * UGrid   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplexD::Nsimd()),GridDefaultMpi());
 | 
				
			||||||
 | 
					  GridRedBlackCartesian * UrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid);
 | 
				
			||||||
 | 
					  GridCartesian         * FGrid   = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid);
 | 
				
			||||||
 | 
					  GridRedBlackCartesian * FrbGrid = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,UGrid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GridCartesian         * UGrid_f   = SpaceTimeGrid::makeFourDimGrid(GridDefaultLatt(), GridDefaultSimd(Nd,vComplexF::Nsimd()),GridDefaultMpi());
 | 
				
			||||||
 | 
					  GridRedBlackCartesian * UrbGrid_f = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid_f);
 | 
				
			||||||
 | 
					  GridCartesian         * FGrid_f   = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid_f);
 | 
				
			||||||
 | 
					  GridRedBlackCartesian * FrbGrid_f = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,UGrid_f);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LatticeFermionD    src(FGrid); random(RNG5,src);
 | 
				
			||||||
 | 
					  LatticeFermionD result(FGrid); result=zero;
 | 
				
			||||||
 | 
					  LatticeGaugeFieldD Umu(UGrid);
 | 
				
			||||||
 | 
					  LatticeGaugeFieldF Umu_f(UGrid_f); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(config_file.size() > 0){
 | 
				
			||||||
 | 
					    FieldMetaData header;
 | 
				
			||||||
 | 
					    NerscIO::readConfiguration(Umu,header,config_file);
 | 
				
			||||||
 | 
					  }else{
 | 
				
			||||||
 | 
					    SU3::HotConfiguration(RNG4,Umu);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  precisionChange(Umu_f,Umu);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  RealD M5=1.8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LatticeFermionD    src_o(FrbGrid);
 | 
				
			||||||
 | 
					  pickCheckerboard(Odd,src_o,src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  //if(0){ //Test preconditioned CG
 | 
				
			||||||
 | 
					    std::cout << "Test preconditioned CG" << std::endl;
 | 
				
			||||||
 | 
					    LatticeFermionD result_o(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_2(FrbGrid);
 | 
				
			||||||
 | 
					    result_o.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o = zero;
 | 
				
			||||||
 | 
					    result_o_2.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o_2 = zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DomainWallFermionD Ddwf(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf);
 | 
				
			||||||
 | 
					    //DoNothingLinearOperator<LatticeFermionD> Prec;
 | 
				
			||||||
 | 
					    //FixedIterConjugateGradientPreconditioner<LatticeFermionD> Prec(HermOpEO, 20);
 | 
				
			||||||
 | 
					    //    SloppyConjugateGradientPreconditioner<LatticeFermionD> Prec(HermOpEO, 1e-2, 1000);
 | 
				
			||||||
 | 
					    PolynomialPreconditioner<LatticeFermionD> Prec(HermOpEO,lo,hi,order) ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Preconditioned CG" << std::endl;
 | 
				
			||||||
 | 
					    InexactPreconditionedConjugateGradient<LatticeFermionD> pCG(Prec,1.0e-8,10000);
 | 
				
			||||||
 | 
					    pCG(HermOpEO,src_o,result_o);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting regular CG" << std::endl;
 | 
				
			||||||
 | 
					    ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000);
 | 
				
			||||||
 | 
					    CG(HermOpEO,src_o,result_o_2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LatticeFermionD diff_o(FrbGrid);
 | 
				
			||||||
 | 
					    RealD diff = axpy_norm(diff_o, -1.0, result_o, result_o_2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "pCG HermOp applications " << " Lo " << lo << " Hi " << hi << " Order " << order << " " <<  pCG.IterationsToComplete << "(outer) + " << Prec.InnerIterations << "(inner) = " << pCG.IterationsToComplete + Prec.InnerIterations << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "CG HermOp applications " << CG.IterationsToComplete << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Diff between results: " << diff << std::endl;
 | 
				
			||||||
 | 
					  //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(0){ //Test compressor
 | 
				
			||||||
 | 
					    LatticeFermionD result_o(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_2(FrbGrid);
 | 
				
			||||||
 | 
					    result_o.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o = zero;
 | 
				
			||||||
 | 
					    result_o_2.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o_2 = zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DomainWallFermionD Ddwf(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DomainWallFermionDF DdwfC(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionDF,LatticeFermionD> HermOpEOC(DdwfC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "Starting regular CG with compressed operator" << std::endl;
 | 
				
			||||||
 | 
					    Integer iter1;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000);
 | 
				
			||||||
 | 
					      CG.ErrorOnNoConverge = false;
 | 
				
			||||||
 | 
					      CG(HermOpEOC,src_o,result_o);
 | 
				
			||||||
 | 
					      iter1 = CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Integer iter2;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      std::cout << "Starting regular CG" << std::endl;
 | 
				
			||||||
 | 
					      ConjugateGradient<LatticeFermionD> CG(1.0e-8,10000);
 | 
				
			||||||
 | 
					      CG(HermOpEO,src_o,result_o_2);
 | 
				
			||||||
 | 
					      iter2 = CG.IterationsToComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LatticeFermionD diff_o(FrbGrid);
 | 
				
			||||||
 | 
					    RealD diff = axpy_norm(diff_o, -1.0, result_o, result_o_2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << "CG HermOp CC applications " << iter1 << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "CG HermOp applications " << iter2 << std::endl;
 | 
				
			||||||
 | 
					    std::cout << "Diff between results: " << diff << std::endl;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if(1){ //Compare mixed prec restarted single/single internal with same but with single/compressed
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_full(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_half(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_16(FrbGrid);
 | 
				
			||||||
 | 
					    LatticeFermionD result_o_8(FrbGrid);
 | 
				
			||||||
 | 
					    result_o_full.checkerboard = Odd;
 | 
				
			||||||
 | 
					    result_o_full = zero;
 | 
				
			||||||
 | 
					    result_o_16 = result_o_8 = result_o_half = result_o_full;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Std
 | 
				
			||||||
 | 
					    DomainWallFermionD Ddwf(Umu,*FGrid,*FrbGrid,*UGrid,*UrbGrid,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionD,LatticeFermionD> HermOpEO(Ddwf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DomainWallFermionF Ddwf_f(Umu_f,*FGrid_f,*FrbGrid_f,*UGrid_f,*UrbGrid_f,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionF,LatticeFermionF> HermOpEO_f(Ddwf_f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //1/2 prec
 | 
				
			||||||
 | 
					    DomainWallFermionFH Ddwfhalf_f(Umu_f,*FGrid_f,*FrbGrid_f,*UGrid_f,*UrbGrid_f,mass,M5);
 | 
				
			||||||
 | 
					    SchurDiagMooeeOperator<DomainWallFermionFH,LatticeFermionF> HermOpEOhalf_f(Ddwfhalf_f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Grid_finalize();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user