mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-02 21:14:32 +00:00 
			
		
		
		
	Compare commits
	
		
			181 Commits
		
	
	
		
			8f84bbed1b
			...
			rmhmc_merg
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					cfa0576ffd | ||
| 
						 | 
					fe98e9f555 | ||
| 
						 | 
					948d16fb06 | ||
| 
						 | 
					58fbcaa399 | ||
| 
						 | 
					9ad6836b0f | ||
| 
						 | 
					026eb8a695 | ||
| 
						 | 
					076580c232 | ||
| 
						 | 
					7af6022a2a | ||
| 
						 | 
					982a60536c | ||
| 
						 | 
					dc36d272ce | ||
| 
						 | 
					515ff6bf62 | ||
| 
						 | 
					6d0c2de399 | ||
| 
						 | 
					7786ea9921 | ||
| 
						 | 
					d93eac7b1c | ||
| 
						 | 
					afc316f501 | ||
| 
						 | 
					f14bfd5c1b | ||
| 
						 | 
					c5f1420dea | ||
| 
						 | 
					018e6da872 | ||
| 
						 | 
					b77bccfac2 | ||
| 
						 | 
					80359e0d49 | ||
| 
						 | 
					3d437c5cc4 | ||
| 
						 | 
					bd56c95a6f | ||
| 
						 | 
					dbd8bb49dc | ||
| 
						 | 
					3a29af0ce4 | ||
| 
						 | 
					f7b79cdd45 | ||
| 
						 | 
					075b9d22d0 | ||
| 
						 | 
					b92428f05f | ||
| 
						 | 
					34b11864b6 | ||
| 
						 | 
					1dfaa08afb | ||
| 
						 | 
					f44dce390f | ||
| 
						 | 
					bb71e9a96a | ||
| 
						 | 
					6f6844ccf1 | ||
| 
						 | 
					4c6613d72c | ||
| 
						 | 
					559257bbe9 | ||
| 
						 | 
					cff1f8d3b8 | ||
| 
						 | 
					f27d2083cd | ||
| 
						 | 
					36cc9c524f | ||
| 
						 | 
					2822487450 | ||
| 
						 | 
					e07fafe46a | ||
| 
						 | 
					063d290bd8 | ||
| 
						 | 
					4e6194d92a | ||
| 
						 | 
					de30c4e22a | ||
| 
						 | 
					4241c7d4a3 | ||
| 
						 | 
					7b11075102 | ||
| 
						 | 
					abc658dca5 | ||
| 
						 | 
					2372275b2c | ||
| 
						 | 
					ef736e8aa4 | ||
| 
						 | 
					5e539e2d54 | ||
| 
						 | 
					96773f5254 | ||
| 
						 | 
					d80df09f3b | ||
| 
						 | 
					621e612c30 | ||
| 
						 | 
					8c3792721b | ||
| 
						 | 
					c95bbd3948 | ||
| 
						 | 
					e28ab7a732 | ||
| 
						 | 
					c797cbe737 | ||
| 
						 | 
					e09dfbf1c2 | ||
| 
						 | 
					116d90b0ee | ||
| 
						 | 
					b0646ca187 | ||
| 
						 | 
					4895ff260e | ||
| 
						 | 
					470d93006a | ||
| 
						 | 
					2f3d03f188 | ||
| 
						 | 
					8db7c23bee | ||
| 
						 | 
					69dc5172dc | ||
| 
						 | 
					fd72eb6546 | ||
| 
						 | 
					b405767569 | ||
| 
						 | 
					fe88a0c12f | ||
| 
						 | 
					e61a9ed2b4 | ||
| 
						 | 
					de8daa3824 | ||
| 
						 | 
					3a50fb29cb | ||
| 
						 | 
					6647d2656f | ||
| 
						 | 
					a6f4dbeb6d | ||
| 
						 | 
					92a282f2d8 | ||
| 
						 | 
					ca2fd9fc7b | ||
| 
						 | 
					be1a4f5860 | ||
| 
						 | 
					5897b93dd4 | ||
| 
						 | 
					af091e0881 | ||
| 
						 | 
					3c1e5e9517 | ||
| 
						 | 
					85b2cb7a8a | ||
| 
						 | 
					b8bdc2eefb | ||
| 
						 | 
					0078826ff1 | ||
| 
						 | 
					e855c41772 | ||
| 
						 | 
					d169c275b6 | ||
| 
						 | 
					a5125e23f4 | ||
| 
						 | 
					7b83c80757 | ||
| 
						 | 
					e41821e206 | ||
| 
						 | 
					5a75ab15a2 | ||
| 
						 | 
					932c783fbf | ||
| 
						 | 
					55f9cce577 | ||
| 
						 | 
					b3533ca847 | ||
| 
						 | 
					fd2a637010 | ||
| 
						 | 
					eee27b8b30 | ||
| 
						 | 
					8522352aa3 | ||
| 
						 | 
					3beb8f4091 | ||
| 
						 | 
					12a706e9b1 | ||
| 
						 | 
					170aa7df01 | ||
| 
						 | 
					e8ad1fef53 | ||
| 
						 | 
					aa9df63a05 | ||
| 
						 | 
					3953312a93 | ||
| 
						 | 
					6e62f4f616 | ||
| 
						 | 
					6a7bdca53b | ||
| 
						 | 
					c7fba9aace | ||
| 
						 | 
					ac6c7cb8d6 | ||
| 
						 | 
					c5924833a1 | ||
| 
						 | 
					ac0a74be0d | ||
| 
						 | 
					42b0e1125d | ||
| 
						 | 
					339c4fda79 | ||
| 
						 | 
					9b85bf9402 | ||
| 
						 | 
					86b02c3cd8 | ||
| 
						 | 
					7b3b7093fa | ||
| 
						 | 
					881b08a465 | ||
| 
						 | 
					3ee5444c69 | ||
| 
						 | 
					5e28fe56d2 | ||
| 
						 | 
					5aabe074fe | ||
| 
						 | 
					dace904c10 | ||
| 
						 | 
					be98d26610 | ||
| 
						 | 
					178376f24b | ||
| 
						 | 
					6a0eb466ee | ||
| 
						 | 
					4ea29b8f0f | ||
| 
						 | 
					778291230a | ||
| 
						 | 
					026e736dfa | ||
| 
						 | 
					4275b3f431 | ||
| 
						 | 
					1b8176e2c0 | ||
| 
						 | 
					cbc053c3db | ||
| 
						 | 
					cdf3f6ef6e | ||
| 
						 | 
					ba7f9d7b70 | ||
| 
						 | 
					371fd123fb | ||
| 
						 | 
					d6ff644aab | ||
| 
						 | 
					29586f6b5e | ||
| 
						 | 
					fd057c838f | ||
| 
						 | 
					f51222086c | ||
| 
						 | 
					f73691ec47 | ||
| 
						 | 
					7ebda3e9ec | ||
| 
						 | 
					b10e1b7bc8 | ||
| 
						 | 
					d7dea44ce7 | ||
| 
						 | 
					37b6b82869 | ||
| 
						 | 
					92ad5b8f74 | ||
| 
						 | 
					8c80f1c168 | ||
| 
						 | 
					0af7d5a793 | ||
| 
						 | 
					505fa49983 | ||
| 
						 | 
					7bcf33def9 | ||
| 
						 | 
					a13820656a | ||
| 
						 | 
					fa71b46a41 | ||
| 
						 | 
					b8b3ae6ac1 | ||
| 
						 | 
					55c008da21 | ||
| 
						 | 
					2507606bd0 | ||
| 
						 | 
					7c2ad4f8c8 | ||
| 
						 | 
					54c8025aad | ||
| 
						 | 
					921e23e83c | ||
| 
						 | 
					6e750ecb0e | ||
| 
						 | 
					b8f1f5d2a3 | ||
| 
						 | 
					9273f2937c | ||
| 
						 | 
					1aa28b47ae | ||
| 
						 | 
					629cb2987a | ||
| 
						 | 
					03235d6368 | ||
| 
						 | 
					22064c7e4c | ||
| 
						 | 
					2de03e5172 | ||
| 
						 | 
					3af4929dda | ||
| 
						 | 
					1ba429345b | ||
| 
						 | 
					88bdd4344b | ||
| 
						 | 
					4044536eea | ||
| 
						 | 
					4d8ae6221c | ||
| 
						 | 
					4e31e4e094 | ||
| 
						 | 
					0d6674e489 | ||
| 
						 | 
					b145fd4f5b | ||
| 
						 | 
					8a5b794f25 | ||
| 
						 | 
					291e80f88a | ||
| 
						 | 
					1ace5850ae | ||
| 
						 | 
					283f14b7c1 | ||
| 
						 | 
					1d6e708083 | ||
| 
						 | 
					89457e25e3 | ||
| 
						 | 
					7e3b298d3d | ||
| 
						 | 
					7ff3e5eed4 | ||
| 
						 | 
					19eb51cf41 | ||
| 
						 | 
					470d4dcc6d | ||
| 
						 | 
					ed03bfd555 | ||
| 
						 | 
					8c0fbcccae | ||
| 
						 | 
					d4866157fe | ||
| 
						 | 
					b6496b6cb5 | ||
| 
						 | 
					4f5fe57920 | ||
| 
						 | 
					11fb943b1e | ||
| 
						 | 
					046a23121e | 
@@ -66,6 +66,10 @@ if BUILD_FERMION_REPS
 | 
			
		||||
  extra_sources+=$(ADJ_FERMION_FILES)
 | 
			
		||||
  extra_sources+=$(TWOIND_FERMION_FILES)
 | 
			
		||||
endif
 | 
			
		||||
if BUILD_SP
 | 
			
		||||
    extra_sources+=$(SP_FERMION_FILES)
 | 
			
		||||
    extra_sources+=$(SP_TWOIND_FERMION_FILES)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
lib_LIBRARIES = libGrid.a
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -460,6 +460,53 @@ class NonHermitianSchurDiagTwoOperator : public NonHermitianSchurOperatorBase<Fi
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class Matrix,class Field>
 | 
			
		||||
class QuadLinearOperator : public LinearOperatorBase<Field> {
 | 
			
		||||
  Matrix &_Mat;
 | 
			
		||||
public:
 | 
			
		||||
  RealD a0,a1,a2;
 | 
			
		||||
  QuadLinearOperator(Matrix &Mat): _Mat(Mat),a0(0.),a1(0.),a2(1.) {};
 | 
			
		||||
  QuadLinearOperator(Matrix &Mat, RealD _a0,RealD _a1,RealD _a2): _Mat(Mat),a0(_a0),a1(_a1),a2(_a2) {};
 | 
			
		||||
  // Support for coarsening to a multigrid
 | 
			
		||||
  void OpDiag (const Field &in, Field &out) {
 | 
			
		||||
    assert(0);
 | 
			
		||||
    _Mat.Mdiag(in,out);
 | 
			
		||||
  }
 | 
			
		||||
  void OpDir  (const Field &in, Field &out,int dir,int disp) {
 | 
			
		||||
    assert(0);
 | 
			
		||||
    _Mat.Mdir(in,out,dir,disp);
 | 
			
		||||
  }
 | 
			
		||||
  void OpDirAll  (const Field &in, std::vector<Field> &out){
 | 
			
		||||
    assert(0);
 | 
			
		||||
    _Mat.MdirAll(in,out);
 | 
			
		||||
  }
 | 
			
		||||
  void HermOp (const Field &in, Field &out){
 | 
			
		||||
//    _Mat.M(in,out);
 | 
			
		||||
    Field tmp1(in.Grid());
 | 
			
		||||
//    Linop.HermOpAndNorm(psi, mmp, d, b);
 | 
			
		||||
    _Mat.M(in,tmp1);
 | 
			
		||||
    _Mat.M(tmp1,out);
 | 
			
		||||
    out *= a2;
 | 
			
		||||
    axpy(out, a1, tmp1, out);
 | 
			
		||||
    axpy(out, a0, in, out);
 | 
			
		||||
//    d=real(innerProduct(psi,mmp));
 | 
			
		||||
//    b=norm2(mmp);
 | 
			
		||||
  }
 | 
			
		||||
  void AdjOp     (const Field &in, Field &out){
 | 
			
		||||
    assert(0);
 | 
			
		||||
    _Mat.M(in,out);
 | 
			
		||||
  }
 | 
			
		||||
  void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){
 | 
			
		||||
    HermOp(in,out);
 | 
			
		||||
    ComplexD dot= innerProduct(in,out); n1=real(dot);
 | 
			
		||||
    n2=norm2(out);
 | 
			
		||||
  }
 | 
			
		||||
  void Op(const Field &in, Field &out){
 | 
			
		||||
    assert(0);
 | 
			
		||||
    _Mat.M(in,out);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Left  handed Moo^-1 ; (Moo - Moe Mee^-1 Meo) psi = eta  -->  ( 1 - Moo^-1 Moe Mee^-1 Meo ) psi = Moo^-1 eta
 | 
			
		||||
// Right handed Moo^-1 ; (Moo - Moe Mee^-1 Meo) Moo^-1 Moo psi = eta  -->  ( 1 - Moe Mee^-1 Meo Moo^-1) phi=eta ; psi = Moo^-1 phi
 | 
			
		||||
 
 | 
			
		||||
@@ -36,11 +36,12 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
// Abstract base class.
 | 
			
		||||
// Takes a matrix (Mat), a source (phi), and a vector of Fields (chi)
 | 
			
		||||
// and returns a forecasted solution to the system D*psi = phi (psi).
 | 
			
		||||
template<class Matrix, class Field>
 | 
			
		||||
// Changing to operator
 | 
			
		||||
template<class LinearOperatorBase, class Field>
 | 
			
		||||
class Forecast
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  virtual Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& chi) = 0;
 | 
			
		||||
  virtual Field operator()(LinearOperatorBase &Mat, const Field& phi, const std::vector<Field>& chi) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Implementation of Brower et al.'s chronological inverter (arXiv:hep-lat/9509012),
 | 
			
		||||
@@ -54,13 +55,13 @@ public:
 | 
			
		||||
  Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& prev_solns)
 | 
			
		||||
  {
 | 
			
		||||
    int degree = prev_solns.size();
 | 
			
		||||
    std::cout << GridLogMessage << "ChronoForecast: degree= " << degree << std::endl;
 | 
			
		||||
    Field chi(phi); // forecasted solution
 | 
			
		||||
 | 
			
		||||
    // Trivial cases
 | 
			
		||||
    if(degree == 0){ chi = Zero(); return chi; }
 | 
			
		||||
    else if(degree == 1){ return prev_solns[0]; }
 | 
			
		||||
 | 
			
		||||
    //    RealD dot;
 | 
			
		||||
    ComplexD xp;
 | 
			
		||||
    Field r(phi); // residual
 | 
			
		||||
    Field Mv(phi);
 | 
			
		||||
@@ -83,8 +84,9 @@ public:
 | 
			
		||||
    // Perform sparse matrix multiplication and construct rhs
 | 
			
		||||
    for(int i=0; i<degree; i++){
 | 
			
		||||
      b[i] = innerProduct(v[i],phi);
 | 
			
		||||
      Mat.M(v[i],Mv);
 | 
			
		||||
      Mat.Mdag(Mv,MdagMv[i]);
 | 
			
		||||
//      Mat.M(v[i],Mv);
 | 
			
		||||
//      Mat.Mdag(Mv,MdagMv[i]);
 | 
			
		||||
      Mat.HermOp(v[i],MdagMv[i]);
 | 
			
		||||
      G[i][i] = innerProduct(v[i],MdagMv[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -604,8 +604,8 @@ void GlobalSharedMemory::SharedMemoryAllocate(uint64_t bytes, int flags)
 | 
			
		||||
#ifdef GRID_SYCL_LEVEL_ZERO_IPC
 | 
			
		||||
    typedef struct { int fd; pid_t pid ; ze_ipc_mem_handle_t ze; } clone_mem_t;
 | 
			
		||||
 | 
			
		||||
    auto zeDevice    = cl::sycl::get_native<cl::sycl::backend::level_zero>(theGridAccelerator->get_device());
 | 
			
		||||
    auto zeContext   = cl::sycl::get_native<cl::sycl::backend::level_zero>(theGridAccelerator->get_context());
 | 
			
		||||
    auto zeDevice    = cl::sycl::get_native<cl::sycl::backend::ext_oneapi_level_zero>(theGridAccelerator->get_device());
 | 
			
		||||
    auto zeContext   = cl::sycl::get_native<cl::sycl::backend::ext_oneapi_level_zero>(theGridAccelerator->get_context());
 | 
			
		||||
      
 | 
			
		||||
    ze_ipc_mem_handle_t ihandle;
 | 
			
		||||
    clone_mem_t handle;
 | 
			
		||||
 
 | 
			
		||||
@@ -47,3 +47,4 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#include <Grid/lattice/Lattice_transfer.h>
 | 
			
		||||
#include <Grid/lattice/Lattice_basis.h>
 | 
			
		||||
#include <Grid/lattice/Lattice_crc.h>
 | 
			
		||||
#include <Grid/lattice/PaddedCell.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -345,7 +345,9 @@ GridUnopClass(UnaryNot, Not(a));
 | 
			
		||||
GridUnopClass(UnaryTrace, trace(a));
 | 
			
		||||
GridUnopClass(UnaryTranspose, transpose(a));
 | 
			
		||||
GridUnopClass(UnaryTa, Ta(a));
 | 
			
		||||
GridUnopClass(UnarySpTa, SpTa(a));
 | 
			
		||||
GridUnopClass(UnaryProjectOnGroup, ProjectOnGroup(a));
 | 
			
		||||
GridUnopClass(UnaryProjectOnSpGroup, ProjectOnSpGroup(a));
 | 
			
		||||
GridUnopClass(UnaryTimesI, timesI(a));
 | 
			
		||||
GridUnopClass(UnaryTimesMinusI, timesMinusI(a));
 | 
			
		||||
GridUnopClass(UnaryAbs, abs(a));
 | 
			
		||||
@@ -456,7 +458,9 @@ GRID_DEF_UNOP(operator!, UnaryNot);
 | 
			
		||||
GRID_DEF_UNOP(trace, UnaryTrace);
 | 
			
		||||
GRID_DEF_UNOP(transpose, UnaryTranspose);
 | 
			
		||||
GRID_DEF_UNOP(Ta, UnaryTa);
 | 
			
		||||
GRID_DEF_UNOP(SpTa, UnarySpTa);
 | 
			
		||||
GRID_DEF_UNOP(ProjectOnGroup, UnaryProjectOnGroup);
 | 
			
		||||
GRID_DEF_UNOP(ProjectOnSpGroup, UnaryProjectOnSpGroup);
 | 
			
		||||
GRID_DEF_UNOP(timesI, UnaryTimesI);
 | 
			
		||||
GRID_DEF_UNOP(timesMinusI, UnaryTimesMinusI);
 | 
			
		||||
GRID_DEF_UNOP(abs, UnaryAbs);  // abs overloaded in cmath C++98; DON'T do the
 | 
			
		||||
 
 | 
			
		||||
@@ -66,6 +66,65 @@ inline auto TraceIndex(const Lattice<vobj> &lhs) -> Lattice<decltype(traceIndex<
 | 
			
		||||
  return ret;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<int N, class Vec>
 | 
			
		||||
Lattice<iScalar<iScalar<iScalar<Vec> > > > Determinant(const Lattice<iScalar<iScalar<iMatrix<Vec, N> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid=Umu.Grid();
 | 
			
		||||
  auto lvol = grid->lSites();
 | 
			
		||||
  Lattice<iScalar<iScalar<iScalar<Vec> > > > ret(grid);
 | 
			
		||||
  typedef typename Vec::scalar_type scalar;
 | 
			
		||||
  autoView(Umu_v,Umu,CpuRead);
 | 
			
		||||
  autoView(ret_v,ret,CpuWrite);
 | 
			
		||||
  thread_for(site,lvol,{
 | 
			
		||||
    Eigen::MatrixXcd EigenU = Eigen::MatrixXcd::Zero(N,N);
 | 
			
		||||
    Coordinate lcoor;
 | 
			
		||||
    grid->LocalIndexToLocalCoor(site, lcoor);
 | 
			
		||||
    iScalar<iScalar<iMatrix<scalar, N> > > Us;
 | 
			
		||||
    peekLocalSite(Us, Umu_v, lcoor);
 | 
			
		||||
    for(int i=0;i<N;i++){
 | 
			
		||||
      for(int j=0;j<N;j++){
 | 
			
		||||
	scalar tmp= Us()()(i,j);
 | 
			
		||||
	ComplexD ztmp(real(tmp),imag(tmp));
 | 
			
		||||
	EigenU(i,j)=ztmp;
 | 
			
		||||
      }}
 | 
			
		||||
    ComplexD detD  = EigenU.determinant();
 | 
			
		||||
    typename Vec::scalar_type det(detD.real(),detD.imag());
 | 
			
		||||
    pokeLocalSite(det,ret_v,lcoor);
 | 
			
		||||
  });
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int N>
 | 
			
		||||
Lattice<iScalar<iScalar<iMatrix<vComplexD, N> > > > Inverse(const Lattice<iScalar<iScalar<iMatrix<vComplexD, N> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid=Umu.Grid();
 | 
			
		||||
  auto lvol = grid->lSites();
 | 
			
		||||
  Lattice<iScalar<iScalar<iMatrix<vComplexD, N> > > > ret(grid);
 | 
			
		||||
  
 | 
			
		||||
  autoView(Umu_v,Umu,CpuRead);
 | 
			
		||||
  autoView(ret_v,ret,CpuWrite);
 | 
			
		||||
  thread_for(site,lvol,{
 | 
			
		||||
    Eigen::MatrixXcd EigenU = Eigen::MatrixXcd::Zero(N,N);
 | 
			
		||||
    Coordinate lcoor;
 | 
			
		||||
    grid->LocalIndexToLocalCoor(site, lcoor);
 | 
			
		||||
    iScalar<iScalar<iMatrix<ComplexD, N> > > Us;
 | 
			
		||||
    iScalar<iScalar<iMatrix<ComplexD, N> > > Ui;
 | 
			
		||||
    peekLocalSite(Us, Umu_v, lcoor);
 | 
			
		||||
    for(int i=0;i<N;i++){
 | 
			
		||||
      for(int j=0;j<N;j++){
 | 
			
		||||
	EigenU(i,j) = Us()()(i,j);
 | 
			
		||||
      }}
 | 
			
		||||
    Eigen::MatrixXcd EigenUinv = EigenU.inverse();
 | 
			
		||||
    for(int i=0;i<N;i++){
 | 
			
		||||
      for(int j=0;j<N;j++){
 | 
			
		||||
	Ui()()(i,j) = EigenUinv(i,j);
 | 
			
		||||
      }}
 | 
			
		||||
    pokeLocalSite(Ui,ret_v,lcoor);
 | 
			
		||||
  });
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -697,8 +697,68 @@ void localCopyRegion(const Lattice<vobj> &From,Lattice<vobj> & To,Coordinate Fro
 | 
			
		||||
  for(int d=0;d<nd;d++){
 | 
			
		||||
    assert(Fg->_processors[d]  == Tg->_processors[d]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // the above should guarantee that the operations are local
 | 
			
		||||
  
 | 
			
		||||
#if 1
 | 
			
		||||
 | 
			
		||||
  size_t nsite = 1;
 | 
			
		||||
  for(int i=0;i<nd;i++) nsite *= RegionSize[i];
 | 
			
		||||
  
 | 
			
		||||
  size_t tbytes = 4*nsite*sizeof(int);
 | 
			
		||||
  int *table = (int*)malloc(tbytes);
 | 
			
		||||
 
 | 
			
		||||
  thread_for(idx, nsite, {
 | 
			
		||||
      Coordinate from_coor, to_coor;
 | 
			
		||||
      size_t rem = idx;
 | 
			
		||||
      for(int i=0;i<nd;i++){
 | 
			
		||||
	size_t base_i  = rem % RegionSize[i]; rem /= RegionSize[i];
 | 
			
		||||
	from_coor[i] = base_i + FromLowerLeft[i];
 | 
			
		||||
	to_coor[i] = base_i + ToLowerLeft[i];
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      int foidx = Fg->oIndex(from_coor);
 | 
			
		||||
      int fiidx = Fg->iIndex(from_coor);
 | 
			
		||||
      int toidx = Tg->oIndex(to_coor);
 | 
			
		||||
      int tiidx = Tg->iIndex(to_coor);
 | 
			
		||||
      int* tt = table + 4*idx;
 | 
			
		||||
      tt[0] = foidx;
 | 
			
		||||
      tt[1] = fiidx;
 | 
			
		||||
      tt[2] = toidx;
 | 
			
		||||
      tt[3] = tiidx;
 | 
			
		||||
    });
 | 
			
		||||
  
 | 
			
		||||
  int* table_d = (int*)acceleratorAllocDevice(tbytes);
 | 
			
		||||
  acceleratorCopyToDevice(table,table_d,tbytes);
 | 
			
		||||
 | 
			
		||||
  typedef typename vobj::vector_type vector_type;
 | 
			
		||||
  typedef typename vobj::scalar_type scalar_type;
 | 
			
		||||
 | 
			
		||||
  autoView(from_v,From,AcceleratorRead);
 | 
			
		||||
  autoView(to_v,To,AcceleratorWrite);
 | 
			
		||||
  
 | 
			
		||||
  accelerator_for(idx,nsite,1,{
 | 
			
		||||
      static const int words=sizeof(vobj)/sizeof(vector_type);
 | 
			
		||||
      int* tt = table_d + 4*idx;
 | 
			
		||||
      int from_oidx = *tt++;
 | 
			
		||||
      int from_lane = *tt++;
 | 
			
		||||
      int to_oidx = *tt++;
 | 
			
		||||
      int to_lane = *tt;
 | 
			
		||||
 | 
			
		||||
      const vector_type* from = (const vector_type *)&from_v[from_oidx];
 | 
			
		||||
      vector_type* to = (vector_type *)&to_v[to_oidx];
 | 
			
		||||
      
 | 
			
		||||
      scalar_type stmp;
 | 
			
		||||
      for(int w=0;w<words;w++){
 | 
			
		||||
	stmp = getlane(from[w], from_lane);
 | 
			
		||||
	putlane(to[w], stmp, to_lane);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  
 | 
			
		||||
  acceleratorFreeDevice(table_d);    
 | 
			
		||||
  free(table);
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
#else  
 | 
			
		||||
  Coordinate ldf = Fg->_ldimensions;
 | 
			
		||||
  Coordinate rdf = Fg->_rdimensions;
 | 
			
		||||
  Coordinate isf = Fg->_istride;
 | 
			
		||||
@@ -738,6 +798,8 @@ void localCopyRegion(const Lattice<vobj> &From,Lattice<vobj> & To,Coordinate Fro
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -830,6 +892,8 @@ void ExtractSlice(Lattice<vobj> &lowDim,const Lattice<vobj> & higherDim,int slic
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Insert subvolume orthogonal to direction 'orthog' with slice index 'slice_lo' from 'lowDim' onto slice index 'slice_hi' of higherDim
 | 
			
		||||
//The local dimensions of both 'lowDim' and 'higherDim' orthogonal to 'orthog' should be the same
 | 
			
		||||
template<class vobj>
 | 
			
		||||
void InsertSliceLocal(const Lattice<vobj> &lowDim, Lattice<vobj> & higherDim,int slice_lo,int slice_hi, int orthog)
 | 
			
		||||
{
 | 
			
		||||
@@ -851,6 +915,65 @@ void InsertSliceLocal(const Lattice<vobj> &lowDim, Lattice<vobj> & higherDim,int
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
  size_t nsite = lg->lSites()/lg->LocalDimensions()[orthog];
 | 
			
		||||
  size_t tbytes = 4*nsite*sizeof(int);
 | 
			
		||||
  int *table = (int*)malloc(tbytes);
 | 
			
		||||
  
 | 
			
		||||
  thread_for(idx,nsite,{
 | 
			
		||||
    Coordinate lcoor(nl);
 | 
			
		||||
    Coordinate hcoor(nh);
 | 
			
		||||
    lcoor[orthog] = slice_lo;
 | 
			
		||||
    hcoor[orthog] = slice_hi;
 | 
			
		||||
    size_t rem = idx;
 | 
			
		||||
    for(int mu=0;mu<nl;mu++){
 | 
			
		||||
      if(mu != orthog){
 | 
			
		||||
	int xmu = rem % lg->LocalDimensions()[mu];  rem /= lg->LocalDimensions()[mu];
 | 
			
		||||
	lcoor[mu] = hcoor[mu] = xmu;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    int loidx = lg->oIndex(lcoor);
 | 
			
		||||
    int liidx = lg->iIndex(lcoor);
 | 
			
		||||
    int hoidx = hg->oIndex(hcoor);
 | 
			
		||||
    int hiidx = hg->iIndex(hcoor);
 | 
			
		||||
    int* tt = table + 4*idx;
 | 
			
		||||
    tt[0] = loidx;
 | 
			
		||||
    tt[1] = liidx;
 | 
			
		||||
    tt[2] = hoidx;
 | 
			
		||||
    tt[3] = hiidx;
 | 
			
		||||
    });
 | 
			
		||||
   
 | 
			
		||||
  int* table_d = (int*)acceleratorAllocDevice(tbytes);
 | 
			
		||||
  acceleratorCopyToDevice(table,table_d,tbytes);
 | 
			
		||||
 | 
			
		||||
  typedef typename vobj::vector_type vector_type;
 | 
			
		||||
  typedef typename vobj::scalar_type scalar_type;
 | 
			
		||||
 | 
			
		||||
  autoView(lowDim_v,lowDim,AcceleratorRead);
 | 
			
		||||
  autoView(higherDim_v,higherDim,AcceleratorWrite);
 | 
			
		||||
  
 | 
			
		||||
  accelerator_for(idx,nsite,1,{
 | 
			
		||||
      static const int words=sizeof(vobj)/sizeof(vector_type);
 | 
			
		||||
      int* tt = table_d + 4*idx;
 | 
			
		||||
      int from_oidx = *tt++;
 | 
			
		||||
      int from_lane = *tt++;
 | 
			
		||||
      int to_oidx = *tt++;
 | 
			
		||||
      int to_lane = *tt;
 | 
			
		||||
 | 
			
		||||
      const vector_type* from = (const vector_type *)&lowDim_v[from_oidx];
 | 
			
		||||
      vector_type* to = (vector_type *)&higherDim_v[to_oidx];
 | 
			
		||||
      
 | 
			
		||||
      scalar_type stmp;
 | 
			
		||||
      for(int w=0;w<words;w++){
 | 
			
		||||
	stmp = getlane(from[w], from_lane);
 | 
			
		||||
	putlane(to[w], stmp, to_lane);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  
 | 
			
		||||
  acceleratorFreeDevice(table_d);    
 | 
			
		||||
  free(table);
 | 
			
		||||
  
 | 
			
		||||
#else
 | 
			
		||||
  // the above should guarantee that the operations are local
 | 
			
		||||
  autoView(lowDimv,lowDim,CpuRead);
 | 
			
		||||
  autoView(higherDimv,higherDim,CpuWrite);
 | 
			
		||||
@@ -866,6 +989,7 @@ void InsertSliceLocal(const Lattice<vobj> &lowDim, Lattice<vobj> & higherDim,int
 | 
			
		||||
      pokeLocalSite(s,higherDimv,hcoor);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,14 +26,32 @@ Author: Peter Boyle pboyle@bnl.gov
 | 
			
		||||
/*  END LEGAL */
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include<Grid/cshift/Cshift.h>
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
//Allow the user to specify how the C-shift is performed, e.g. to respect the appropriate boundary conditions
 | 
			
		||||
template<typename vobj>
 | 
			
		||||
struct CshiftImplBase{
 | 
			
		||||
  virtual Lattice<vobj> Cshift(const Lattice<vobj> &in, int dir, int shift) const = 0;
 | 
			
		||||
  virtual ~CshiftImplBase(){}
 | 
			
		||||
};
 | 
			
		||||
template<typename vobj>
 | 
			
		||||
struct CshiftImplDefault: public CshiftImplBase<vobj>{
 | 
			
		||||
  Lattice<vobj> Cshift(const Lattice<vobj> &in, int dir, int shift) const override{ return Grid::Cshift(in,dir,shift); }
 | 
			
		||||
};
 | 
			
		||||
template<typename Gimpl>
 | 
			
		||||
struct CshiftImplGauge: public CshiftImplBase<typename Gimpl::GaugeLinkField::vector_object>{
 | 
			
		||||
  typename Gimpl::GaugeLinkField Cshift(const typename Gimpl::GaugeLinkField &in, int dir, int shift) const override{ return Gimpl::CshiftLink(in,dir,shift); }
 | 
			
		||||
};  
 | 
			
		||||
 | 
			
		||||
class PaddedCell {
 | 
			
		||||
public:
 | 
			
		||||
  GridCartesian * unpadded_grid;
 | 
			
		||||
  int dims;
 | 
			
		||||
  int depth;
 | 
			
		||||
  std::vector<GridCartesian *> grids;
 | 
			
		||||
 | 
			
		||||
  ~PaddedCell()
 | 
			
		||||
  {
 | 
			
		||||
    DeleteGrids();
 | 
			
		||||
@@ -77,7 +95,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  template<class vobj>
 | 
			
		||||
  inline Lattice<vobj> Extract(Lattice<vobj> &in)
 | 
			
		||||
  inline Lattice<vobj> Extract(const Lattice<vobj> &in) const
 | 
			
		||||
  {
 | 
			
		||||
    Lattice<vobj> out(unpadded_grid);
 | 
			
		||||
 | 
			
		||||
@@ -88,19 +106,19 @@ public:
 | 
			
		||||
    return out;
 | 
			
		||||
  }
 | 
			
		||||
  template<class vobj>
 | 
			
		||||
  inline Lattice<vobj> Exchange(Lattice<vobj> &in)
 | 
			
		||||
  inline Lattice<vobj> Exchange(const Lattice<vobj> &in, const CshiftImplBase<vobj> &cshift = CshiftImplDefault<vobj>()) const
 | 
			
		||||
  {
 | 
			
		||||
    GridBase *old_grid = in.Grid();
 | 
			
		||||
    int dims = old_grid->Nd();
 | 
			
		||||
    Lattice<vobj> tmp = in;
 | 
			
		||||
    for(int d=0;d<dims;d++){
 | 
			
		||||
      tmp = Expand(d,tmp); // rvalue && assignment
 | 
			
		||||
      tmp = Expand(d,tmp,cshift); // rvalue && assignment
 | 
			
		||||
    }
 | 
			
		||||
    return tmp;
 | 
			
		||||
  }
 | 
			
		||||
  // expand up one dim at a time
 | 
			
		||||
  template<class vobj>
 | 
			
		||||
  inline Lattice<vobj> Expand(int dim,Lattice<vobj> &in)
 | 
			
		||||
  inline Lattice<vobj> Expand(int dim, const Lattice<vobj> &in, const CshiftImplBase<vobj> &cshift = CshiftImplDefault<vobj>()) const
 | 
			
		||||
  {
 | 
			
		||||
    GridBase *old_grid = in.Grid();
 | 
			
		||||
    GridCartesian *new_grid = grids[dim];//These are new grids
 | 
			
		||||
@@ -112,20 +130,40 @@ public:
 | 
			
		||||
    else       conformable(old_grid,grids[dim-1]);
 | 
			
		||||
 | 
			
		||||
    std::cout << " dim "<<dim<<" local "<<local << " padding to "<<plocal<<std::endl;
 | 
			
		||||
 | 
			
		||||
    double tins=0, tshift=0;
 | 
			
		||||
    
 | 
			
		||||
    // Middle bit
 | 
			
		||||
    double t = usecond();
 | 
			
		||||
    for(int x=0;x<local[dim];x++){
 | 
			
		||||
      InsertSliceLocal(in,padded,x,depth+x,dim);
 | 
			
		||||
    }
 | 
			
		||||
    tins += usecond() - t;
 | 
			
		||||
    
 | 
			
		||||
    // High bit
 | 
			
		||||
    shifted = Cshift(in,dim,depth);
 | 
			
		||||
    t = usecond();
 | 
			
		||||
    shifted = cshift.Cshift(in,dim,depth);
 | 
			
		||||
    tshift += usecond() - t;
 | 
			
		||||
 | 
			
		||||
    t=usecond();
 | 
			
		||||
    for(int x=0;x<depth;x++){
 | 
			
		||||
      InsertSliceLocal(shifted,padded,local[dim]-depth+x,depth+local[dim]+x,dim);
 | 
			
		||||
    }
 | 
			
		||||
    tins += usecond() - t;
 | 
			
		||||
    
 | 
			
		||||
    // Low bit
 | 
			
		||||
    shifted = Cshift(in,dim,-depth);
 | 
			
		||||
    t = usecond();
 | 
			
		||||
    shifted = cshift.Cshift(in,dim,-depth);
 | 
			
		||||
    tshift += usecond() - t;
 | 
			
		||||
    
 | 
			
		||||
    t = usecond();
 | 
			
		||||
    for(int x=0;x<depth;x++){
 | 
			
		||||
      InsertSliceLocal(shifted,padded,x,x,dim);
 | 
			
		||||
    }
 | 
			
		||||
    tins += usecond() - t;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogPerformance << "PaddedCell::Expand timings: cshift:" << tshift/1000 << "ms, insert-slice:" << tins/1000 << "ms" << std::endl;
 | 
			
		||||
    
 | 
			
		||||
    return padded;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,7 @@ NAMESPACE_CHECK(Scalar);
 | 
			
		||||
#include <Grid/qcd/utils/Metric.h>
 | 
			
		||||
NAMESPACE_CHECK(Metric);
 | 
			
		||||
#include <Grid/qcd/utils/CovariantLaplacian.h>
 | 
			
		||||
#include <Grid/qcd/utils/CovariantLaplacianRat.h>
 | 
			
		||||
NAMESPACE_CHECK(CovariantLaplacian);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,19 @@ struct WilsonImplParams {
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct GaugeImplParams {
 | 
			
		||||
//  bool overlapCommsCompute;
 | 
			
		||||
//  AcceleratorVector<Real,Nd> twist_n_2pi_L;
 | 
			
		||||
  AcceleratorVector<Complex,Nd> boundary_phases;
 | 
			
		||||
  GaugeImplParams()  {
 | 
			
		||||
    boundary_phases.resize(Nd, 1.0);
 | 
			
		||||
//      twist_n_2pi_L.resize(Nd, 0.0);
 | 
			
		||||
  };
 | 
			
		||||
  GaugeImplParams(const AcceleratorVector<Complex,Nd> phi) : boundary_phases(phi) {
 | 
			
		||||
//    twist_n_2pi_L.resize(Nd, 0.0);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct StaggeredImplParams {
 | 
			
		||||
  Coordinate dirichlet; // Blocksize of dirichlet BCs
 | 
			
		||||
  int  partialDirichlet;
 | 
			
		||||
 
 | 
			
		||||
@@ -126,6 +126,16 @@ typedef WilsonFermion<WilsonTwoIndexSymmetricImplD> WilsonTwoIndexSymmetricFermi
 | 
			
		||||
typedef WilsonFermion<WilsonTwoIndexAntiSymmetricImplF> WilsonTwoIndexAntiSymmetricFermionF;
 | 
			
		||||
typedef WilsonFermion<WilsonTwoIndexAntiSymmetricImplD> WilsonTwoIndexAntiSymmetricFermionD;
 | 
			
		||||
 | 
			
		||||
// Sp(2n)
 | 
			
		||||
typedef WilsonFermion<SpWilsonImplF> SpWilsonFermionF;
 | 
			
		||||
typedef WilsonFermion<SpWilsonImplD> SpWilsonFermionD;
 | 
			
		||||
 | 
			
		||||
typedef WilsonFermion<SpWilsonTwoIndexAntiSymmetricImplF> SpWilsonTwoIndexAntiSymmetricFermionF;
 | 
			
		||||
typedef WilsonFermion<SpWilsonTwoIndexAntiSymmetricImplD> SpWilsonTwoIndexAntiSymmetricFermionD;
 | 
			
		||||
 | 
			
		||||
typedef WilsonFermion<SpWilsonTwoIndexSymmetricImplF> SpWilsonTwoIndexSymmetricFermionF;
 | 
			
		||||
typedef WilsonFermion<SpWilsonTwoIndexSymmetricImplD> SpWilsonTwoIndexSymmetricFermionD;
 | 
			
		||||
 | 
			
		||||
// Twisted mass fermion
 | 
			
		||||
typedef WilsonTMFermion<WilsonImplD2> WilsonTMFermionD2;
 | 
			
		||||
typedef WilsonTMFermion<WilsonImplF> WilsonTMFermionF;
 | 
			
		||||
 
 | 
			
		||||
@@ -261,6 +261,22 @@ typedef WilsonImpl<vComplex,  TwoIndexAntiSymmetricRepresentation, CoeffReal > W
 | 
			
		||||
typedef WilsonImpl<vComplexF, TwoIndexAntiSymmetricRepresentation, CoeffReal > WilsonTwoIndexAntiSymmetricImplF;  // Float
 | 
			
		||||
typedef WilsonImpl<vComplexD, TwoIndexAntiSymmetricRepresentation, CoeffReal > WilsonTwoIndexAntiSymmetricImplD;  // Double
 | 
			
		||||
 | 
			
		||||
//sp 2n
 | 
			
		||||
 | 
			
		||||
typedef WilsonImpl<vComplex,  SpFundamentalRepresentation, CoeffReal > SpWilsonImplR;  // Real.. whichever prec
 | 
			
		||||
typedef WilsonImpl<vComplexF, SpFundamentalRepresentation, CoeffReal > SpWilsonImplF;  // Float
 | 
			
		||||
typedef WilsonImpl<vComplexD, SpFundamentalRepresentation, CoeffReal > SpWilsonImplD;  // Double
 | 
			
		||||
 | 
			
		||||
typedef WilsonImpl<vComplex,  SpTwoIndexAntiSymmetricRepresentation, CoeffReal > SpWilsonTwoIndexAntiSymmetricImplR;  // Real.. whichever prec
 | 
			
		||||
typedef WilsonImpl<vComplexF, SpTwoIndexAntiSymmetricRepresentation, CoeffReal > SpWilsonTwoIndexAntiSymmetricImplF;  // Float
 | 
			
		||||
typedef WilsonImpl<vComplexD, SpTwoIndexAntiSymmetricRepresentation, CoeffReal > SpWilsonTwoIndexAntiSymmetricImplD;  // Double
 | 
			
		||||
 | 
			
		||||
typedef WilsonImpl<vComplex,  SpTwoIndexSymmetricRepresentation, CoeffReal > SpWilsonTwoIndexSymmetricImplR;  // Real.. whichever prec
 | 
			
		||||
typedef WilsonImpl<vComplexF, SpTwoIndexSymmetricRepresentation, CoeffReal > SpWilsonTwoIndexSymmetricImplF;  // Float
 | 
			
		||||
typedef WilsonImpl<vComplexD, SpTwoIndexSymmetricRepresentation, CoeffReal > SpWilsonTwoIndexSymmetricImplD;  // Double
 | 
			
		||||
 | 
			
		||||
typedef WilsonImpl<vComplex,  SpTwoIndexSymmetricRepresentation, CoeffReal > SpWilsonAdjImplR;  // Real.. whichever prec    // adj = 2indx symmetric for Sp(2N)
 | 
			
		||||
typedef WilsonImpl<vComplexF, SpTwoIndexSymmetricRepresentation, CoeffReal > SpWilsonAdjImplF;  // Float     // adj = 2indx symmetric for Sp(2N)
 | 
			
		||||
typedef WilsonImpl<vComplexD, SpTwoIndexSymmetricRepresentation, CoeffReal > SpWilsonAdjImplD;  // Double    // adj = 2indx symmetric for Sp(2N)
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonCloverFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonKernelsInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonTMFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
#define IMPLEMENTATION SpWilsonImplD
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonCloverFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonKernelsInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonTMFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
#define IMPLEMENTATION SpWilsonImplF
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonCloverFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonKernelsInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonTMFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
#define IMPLEMENTATION SpWilsonTwoIndexAntiSymmetricImplD
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonCloverFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonKernelsInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonTMFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
#define IMPLEMENTATION SpWilsonTwoIndexAntiSymmetricImplF
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonCloverFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonKernelsInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonTMFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
#define IMPLEMENTATION SpWilsonTwoIndexSymmetricImplD
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonCloverFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonKernelsInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
../WilsonTMFermionInstantiation.cc.master
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
#define IMPLEMENTATION SpWilsonTwoIndexSymmetricImplF
 | 
			
		||||
@@ -10,12 +10,18 @@ WILSON_IMPL_LIST=" \
 | 
			
		||||
	   WilsonImplF \
 | 
			
		||||
	   WilsonImplD \
 | 
			
		||||
	   WilsonImplD2 \
 | 
			
		||||
	   SpWilsonImplF \
 | 
			
		||||
	   SpWilsonImplD \
 | 
			
		||||
	   WilsonAdjImplF \
 | 
			
		||||
	   WilsonAdjImplD \
 | 
			
		||||
	   WilsonTwoIndexSymmetricImplF \
 | 
			
		||||
	   WilsonTwoIndexSymmetricImplD \
 | 
			
		||||
	   WilsonTwoIndexAntiSymmetricImplF \
 | 
			
		||||
	   WilsonTwoIndexAntiSymmetricImplD \
 | 
			
		||||
	   SpWilsonTwoIndexAntiSymmetricImplF \
 | 
			
		||||
	   SpWilsonTwoIndexAntiSymmetricImplD \
 | 
			
		||||
	   SpWilsonTwoIndexSymmetricImplF \
 | 
			
		||||
	   SpWilsonTwoIndexSymmetricImplD \
 | 
			
		||||
	   GparityWilsonImplF \
 | 
			
		||||
	   GparityWilsonImplD "
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,9 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
typedef WilsonGaugeAction<PeriodicGimplR>          WilsonGaugeActionR;
 | 
			
		||||
typedef WilsonGaugeAction<PeriodicGimplF>          WilsonGaugeActionF;
 | 
			
		||||
typedef WilsonGaugeAction<PeriodicGimplD>          WilsonGaugeActionD;
 | 
			
		||||
typedef WilsonGaugeAction<SpPeriodicGimplR>        SpWilsonGaugeActionR;
 | 
			
		||||
typedef WilsonGaugeAction<SpPeriodicGimplF>        SpWilsonGaugeActionF;
 | 
			
		||||
typedef WilsonGaugeAction<SpPeriodicGimplD>        SpWilsonGaugeActionD;
 | 
			
		||||
typedef PlaqPlusRectangleAction<PeriodicGimplR>    PlaqPlusRectangleActionR;
 | 
			
		||||
typedef PlaqPlusRectangleAction<PeriodicGimplF>    PlaqPlusRectangleActionF;
 | 
			
		||||
typedef PlaqPlusRectangleAction<PeriodicGimplD>    PlaqPlusRectangleActionD;
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ directory
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
#define CPS_MD_TIME
 | 
			
		||||
#undef CPS_MD_TIME
 | 
			
		||||
 | 
			
		||||
#ifdef CPS_MD_TIME
 | 
			
		||||
#define HMC_MOMENTUM_DENOMINATOR (2.0)
 | 
			
		||||
@@ -61,7 +61,7 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
  typedef typename Impl::Field Field;
 | 
			
		||||
 | 
			
		||||
// hardcodes the exponential approximation in the template
 | 
			
		||||
template <class S, int Nrepresentation = Nc, int Nexp = 12 > class GaugeImplTypes {
 | 
			
		||||
template <class S, int Nrepresentation = Nc, int Nexp = 12, class Group = SU<Nc> > class GaugeImplTypes {
 | 
			
		||||
public:
 | 
			
		||||
  typedef S Simd;
 | 
			
		||||
  typedef typename Simd::scalar_type scalar_type;
 | 
			
		||||
@@ -78,8 +78,6 @@ public:
 | 
			
		||||
  typedef Lattice<SiteLink>    LinkField; 
 | 
			
		||||
  typedef Lattice<SiteField>   Field;
 | 
			
		||||
 | 
			
		||||
  typedef SU<Nrepresentation> Group;
 | 
			
		||||
 | 
			
		||||
  // Guido: we can probably separate the types from the HMC functions
 | 
			
		||||
  // this will create 2 kind of implementations
 | 
			
		||||
  // probably confusing the users
 | 
			
		||||
@@ -119,6 +117,7 @@ public:
 | 
			
		||||
    //
 | 
			
		||||
    LinkField Pmu(P.Grid());
 | 
			
		||||
    Pmu = Zero();
 | 
			
		||||
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      Group::GaussianFundamentalLieAlgebraMatrix(pRNG, Pmu);
 | 
			
		||||
      RealD scale = ::sqrt(HMC_MOMENTUM_DENOMINATOR) ;
 | 
			
		||||
@@ -127,7 +126,11 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  static inline Field projectForce(Field &P) { return Ta(P); }
 | 
			
		||||
  static inline Field projectForce(Field &P) {
 | 
			
		||||
      Field ret(P.Grid());
 | 
			
		||||
      Group::taProj(P, ret);
 | 
			
		||||
      return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  static inline void update_field(Field& P, Field& U, double ep){
 | 
			
		||||
    //static std::chrono::duration<double> diff;
 | 
			
		||||
@@ -137,7 +140,8 @@ public:
 | 
			
		||||
    autoView(P_v,P,AcceleratorRead);
 | 
			
		||||
    accelerator_for(ss, P.Grid()->oSites(),1,{
 | 
			
		||||
      for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
        U_v[ss](mu) = ProjectOnGroup(Exponentiate(P_v[ss](mu), ep, Nexp) * U_v[ss](mu));
 | 
			
		||||
          U_v[ss](mu) = Exponentiate(P_v[ss](mu), ep, Nexp) * U_v[ss](mu);
 | 
			
		||||
          U_v[ss](mu) = Group::ProjectOnGeneralGroup(U_v[ss](mu));
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
   //auto end = std::chrono::high_resolution_clock::now();
 | 
			
		||||
@@ -157,7 +161,7 @@ public:
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static inline void Project(Field &U) {
 | 
			
		||||
    ProjectSUn(U);
 | 
			
		||||
    Group::ProjectOnSpecialGroup(U);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static inline void HotConfiguration(GridParallelRNG &pRNG, Field &U) {
 | 
			
		||||
@@ -171,6 +175,7 @@ public:
 | 
			
		||||
  static inline void ColdConfiguration(GridParallelRNG &pRNG, Field &U) {
 | 
			
		||||
    Group::ColdConfiguration(pRNG, U);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -178,10 +183,17 @@ typedef GaugeImplTypes<vComplex, Nc> GimplTypesR;
 | 
			
		||||
typedef GaugeImplTypes<vComplexF, Nc> GimplTypesF;
 | 
			
		||||
typedef GaugeImplTypes<vComplexD, Nc> GimplTypesD;
 | 
			
		||||
 | 
			
		||||
typedef GaugeImplTypes<vComplex, Nc, 12, Sp<Nc> > SpGimplTypesR;
 | 
			
		||||
typedef GaugeImplTypes<vComplexF, Nc, 12, Sp<Nc> > SpGimplTypesF;
 | 
			
		||||
typedef GaugeImplTypes<vComplexD, Nc, 12, Sp<Nc> > SpGimplTypesD;
 | 
			
		||||
 | 
			
		||||
typedef GaugeImplTypes<vComplex, SU<Nc>::AdjointDimension> GimplAdjointTypesR;
 | 
			
		||||
typedef GaugeImplTypes<vComplexF, SU<Nc>::AdjointDimension> GimplAdjointTypesF;
 | 
			
		||||
typedef GaugeImplTypes<vComplexD, SU<Nc>::AdjointDimension> GimplAdjointTypesD;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
#endif // GRID_GAUGE_IMPL_TYPES_H
 | 
			
		||||
 
 | 
			
		||||
@@ -176,7 +176,7 @@ public:
 | 
			
		||||
      return PeriodicBC::CshiftLink(Link,mu,shift);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static inline void       setDirections(std::vector<int> &conjDirs) { _conjDirs=conjDirs; }
 | 
			
		||||
  static inline void       setDirections(const std::vector<int> &conjDirs) { _conjDirs=conjDirs; }
 | 
			
		||||
  static inline std::vector<int> getDirections(void) { return _conjDirs; }
 | 
			
		||||
  static inline bool isPeriodicGaugeField(void) { return false; }
 | 
			
		||||
};
 | 
			
		||||
@@ -193,6 +193,11 @@ typedef ConjugateGaugeImpl<GimplTypesR> ConjugateGimplR; // Real.. whichever pre
 | 
			
		||||
typedef ConjugateGaugeImpl<GimplTypesF> ConjugateGimplF; // Float
 | 
			
		||||
typedef ConjugateGaugeImpl<GimplTypesD> ConjugateGimplD; // Double
 | 
			
		||||
 | 
			
		||||
typedef PeriodicGaugeImpl<SpGimplTypesR> SpPeriodicGimplR; // Real.. whichever prec
 | 
			
		||||
typedef PeriodicGaugeImpl<SpGimplTypesF> SpPeriodicGimplF; // Float
 | 
			
		||||
typedef PeriodicGaugeImpl<SpGimplTypesD> SpPeriodicGimplD; // Double
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ public:
 | 
			
		||||
private:
 | 
			
		||||
  RealD c_plaq;
 | 
			
		||||
  RealD c_rect;
 | 
			
		||||
 | 
			
		||||
  typename WilsonLoops<Gimpl>::StapleAndRectStapleAllWorkspace workspace;
 | 
			
		||||
public:
 | 
			
		||||
  PlaqPlusRectangleAction(RealD b,RealD c): c_plaq(b),c_rect(c){};
 | 
			
		||||
 | 
			
		||||
@@ -79,27 +79,18 @@ public:
 | 
			
		||||
    GridBase *grid = Umu.Grid();
 | 
			
		||||
 | 
			
		||||
    std::vector<GaugeLinkField> U (Nd,grid);
 | 
			
		||||
    std::vector<GaugeLinkField> U2(Nd,grid);
 | 
			
		||||
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      U[mu] = PeekIndex<LorentzIndex>(Umu,mu);
 | 
			
		||||
      WilsonLoops<Gimpl>::RectStapleDouble(U2[mu],U[mu],mu);
 | 
			
		||||
    }
 | 
			
		||||
    std::vector<GaugeLinkField> RectStaple(Nd,grid), Staple(Nd,grid);
 | 
			
		||||
    WilsonLoops<Gimpl>::StapleAndRectStapleAll(Staple, RectStaple, U, workspace);
 | 
			
		||||
 | 
			
		||||
    GaugeLinkField dSdU_mu(grid);
 | 
			
		||||
    GaugeLinkField staple(grid);
 | 
			
		||||
 | 
			
		||||
    for (int mu=0; mu < Nd; mu++){
 | 
			
		||||
 | 
			
		||||
      // Staple in direction mu
 | 
			
		||||
 | 
			
		||||
      WilsonLoops<Gimpl>::Staple(staple,Umu,mu);
 | 
			
		||||
 | 
			
		||||
      dSdU_mu = Ta(U[mu]*staple)*factor_p;
 | 
			
		||||
 | 
			
		||||
      WilsonLoops<Gimpl>::RectStaple(Umu,staple,U2,U,mu);
 | 
			
		||||
 | 
			
		||||
      dSdU_mu = dSdU_mu + Ta(U[mu]*staple)*factor_r;
 | 
			
		||||
      dSdU_mu = Ta(U[mu]*Staple[mu])*factor_p;
 | 
			
		||||
      dSdU_mu = dSdU_mu + Ta(U[mu]*RectStaple[mu])*factor_r;
 | 
			
		||||
	  
 | 
			
		||||
      PokeIndex<LorentzIndex>(dSdU, dSdU_mu, mu);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -42,9 +42,13 @@ template <class Gimpl>
 | 
			
		||||
class WilsonGaugeAction : public Action<typename Gimpl::GaugeField> {
 | 
			
		||||
public:  
 | 
			
		||||
  INHERIT_GIMPL_TYPES(Gimpl);
 | 
			
		||||
  typedef GaugeImplParams ImplParams;
 | 
			
		||||
  ImplParams Params;
 | 
			
		||||
 | 
			
		||||
  /////////////////////////// constructors
 | 
			
		||||
  explicit WilsonGaugeAction(RealD beta_):beta(beta_){};
 | 
			
		||||
  explicit WilsonGaugeAction(RealD beta_,
 | 
			
		||||
		  const ImplParams &p = ImplParams()
 | 
			
		||||
		  ):beta(beta_),Params(p){};
 | 
			
		||||
 | 
			
		||||
  virtual std::string action_name() {return "WilsonGaugeAction";}
 | 
			
		||||
 | 
			
		||||
@@ -56,14 +60,53 @@ public:
 | 
			
		||||
 | 
			
		||||
  virtual void refresh(const GaugeField &U, GridSerialRNG &sRNG, GridParallelRNG &pRNG){};  // noop as no pseudoferms
 | 
			
		||||
 | 
			
		||||
// Umu<->U maximally confusing
 | 
			
		||||
  virtual void boundary(const GaugeField &Umu, GaugeField &Ub){
 | 
			
		||||
    typedef typename Simd::scalar_type scalar_type;
 | 
			
		||||
    assert(Params.boundary_phases.size() == Nd);
 | 
			
		||||
    GridBase *GaugeGrid=Umu.Grid();
 | 
			
		||||
    GaugeLinkField U(GaugeGrid);
 | 
			
		||||
    GaugeLinkField tmp(GaugeGrid);
 | 
			
		||||
 | 
			
		||||
    Lattice<iScalar<vInteger> > coor(GaugeGrid);
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
	////////// boundary phase /////////////
 | 
			
		||||
      auto pha = Params.boundary_phases[mu];
 | 
			
		||||
      scalar_type phase( real(pha),imag(pha) );
 | 
			
		||||
      std::cout<< GridLogIterative << "[WilsonGaugeAction] boundary "<<mu<<" "<<phase<< std::endl; 
 | 
			
		||||
 | 
			
		||||
	int L   = GaugeGrid->GlobalDimensions()[mu];
 | 
			
		||||
        int Lmu = L - 1;
 | 
			
		||||
 | 
			
		||||
      LatticeCoordinate(coor, mu);
 | 
			
		||||
 | 
			
		||||
      U = PeekIndex<LorentzIndex>(Umu, mu);
 | 
			
		||||
      tmp = where(coor == Lmu, phase * U, U);
 | 
			
		||||
      PokeIndex<LorentzIndex>(Ub, tmp, mu);
 | 
			
		||||
//      PokeIndex<LorentzIndex>(Ub, U, mu);
 | 
			
		||||
//      PokeIndex<LorentzIndex>(Umu, tmp, mu);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  virtual RealD S(const GaugeField &U) {
 | 
			
		||||
    RealD plaq = WilsonLoops<Gimpl>::avgPlaquette(U);
 | 
			
		||||
    RealD vol = U.Grid()->gSites();
 | 
			
		||||
    GaugeField Ub(U.Grid());
 | 
			
		||||
    this->boundary(U,Ub);
 | 
			
		||||
    static RealD lastG=0.;
 | 
			
		||||
    RealD plaq = WilsonLoops<Gimpl>::avgPlaquette(Ub);
 | 
			
		||||
    RealD vol = Ub.Grid()->gSites();
 | 
			
		||||
    RealD action = beta * (1.0 - plaq) * (Nd * (Nd - 1.0)) * vol * 0.5;
 | 
			
		||||
    std::cout << GridLogMessage << "[WilsonGaugeAction] dH: " << action-lastG << std::endl;
 | 
			
		||||
    RealD plaq_o = WilsonLoops<Gimpl>::avgPlaquette(U);
 | 
			
		||||
    RealD action_o = beta * (1.0 - plaq_o) * (Nd * (Nd - 1.0)) * vol * 0.5;
 | 
			
		||||
    std::cout << GridLogMessage << "[WilsonGaugeAction] U: " << action_o <<" Ub: "<< action  << std::endl;
 | 
			
		||||
    lastG=action;
 | 
			
		||||
    return action;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  virtual void deriv(const GaugeField &U, GaugeField &dSdU) {
 | 
			
		||||
    GaugeField Ub(U.Grid());
 | 
			
		||||
    this->boundary(U,Ub);
 | 
			
		||||
    // not optimal implementation FIXME
 | 
			
		||||
    // extend Ta to include Lorentz indexes
 | 
			
		||||
 | 
			
		||||
@@ -73,10 +116,9 @@ public:
 | 
			
		||||
    GaugeLinkField dSdU_mu(U.Grid());
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
 | 
			
		||||
      Umu = PeekIndex<LorentzIndex>(U, mu);
 | 
			
		||||
      
 | 
			
		||||
      Umu = PeekIndex<LorentzIndex>(Ub, mu);
 | 
			
		||||
      // Staple in direction mu
 | 
			
		||||
      WilsonLoops<Gimpl>::Staple(dSdU_mu, U, mu);
 | 
			
		||||
      WilsonLoops<Gimpl>::Staple(dSdU_mu, Ub, mu);
 | 
			
		||||
      dSdU_mu = Ta(Umu * dSdU_mu) * factor;
 | 
			
		||||
      
 | 
			
		||||
      PokeIndex<LorentzIndex>(dSdU, dSdU_mu, mu);
 | 
			
		||||
 
 | 
			
		||||
@@ -86,13 +86,8 @@ public:
 | 
			
		||||
    assert(ForceE.Checkerboard()==Even);
 | 
			
		||||
    assert(ForceO.Checkerboard()==Odd);
 | 
			
		||||
 | 
			
		||||
#if defined(GRID_CUDA) || defined(GRID_HIP)  || defined(GRID_SYCL)
 | 
			
		||||
    acceleratorSetCheckerboard(Force,ForceE);
 | 
			
		||||
    acceleratorSetCheckerboard(Force,ForceO);
 | 
			
		||||
#else
 | 
			
		||||
    setCheckerboard(Force,ForceE); 
 | 
			
		||||
    setCheckerboard(Force,ForceO);
 | 
			
		||||
#endif
 | 
			
		||||
    Force=-Force;
 | 
			
		||||
 | 
			
		||||
    delete forcecb;
 | 
			
		||||
@@ -135,13 +130,8 @@ public:
 | 
			
		||||
    assert(ForceE.Checkerboard()==Even);
 | 
			
		||||
    assert(ForceO.Checkerboard()==Odd);
 | 
			
		||||
 | 
			
		||||
#if defined(GRID_CUDA) || defined(GRID_HIP)  || defined(GRID_SYCL)
 | 
			
		||||
    acceleratorSetCheckerboard(Force,ForceE);
 | 
			
		||||
    acceleratorSetCheckerboard(Force,ForceO);
 | 
			
		||||
#else
 | 
			
		||||
    setCheckerboard(Force,ForceE); 
 | 
			
		||||
    setCheckerboard(Force,ForceO);
 | 
			
		||||
#endif
 | 
			
		||||
    Force=-Force;
 | 
			
		||||
 | 
			
		||||
    delete forcecb;
 | 
			
		||||
 
 | 
			
		||||
@@ -178,7 +178,10 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
        // Use chronological inverter to forecast solutions across poles
 | 
			
		||||
        std::vector<FermionField> prev_solns;
 | 
			
		||||
        if(use_heatbath_forecasting){ prev_solns.reserve(param.degree); }
 | 
			
		||||
        ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast;
 | 
			
		||||
	MdagMLinearOperator<AbstractEOFAFermion<Impl> ,FermionField> MdagML(Lop);
 | 
			
		||||
	MdagMLinearOperator<AbstractEOFAFermion<Impl> ,FermionField> MdagMR(Rop);
 | 
			
		||||
//        ChronoForecast<AbstractEOFAFermion<Impl>, FermionField> Forecast;
 | 
			
		||||
	ChronoForecast<MdagMLinearOperator<AbstractEOFAFermion<Impl>, FermionField> , FermionField> Forecast;
 | 
			
		||||
 | 
			
		||||
        // \Phi = ( \alpha_{0} + \sum_{k=1}^{N_{p}} \alpha_{l} * \gamma_{l} ) * \eta
 | 
			
		||||
        RealD N(PowerNegHalf.norm);
 | 
			
		||||
@@ -198,7 +201,7 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
          heatbathRefreshShiftCoefficients(0, -gamma_l);
 | 
			
		||||
          if(use_heatbath_forecasting){ // Forecast CG guess using solutions from previous poles
 | 
			
		||||
            Lop.Mdag(CG_src, Forecast_src);
 | 
			
		||||
            CG_soln = Forecast(Lop, Forecast_src, prev_solns);
 | 
			
		||||
            CG_soln = Forecast(MdagML, Forecast_src, prev_solns);
 | 
			
		||||
            SolverHBL(Lop, CG_src, CG_soln);
 | 
			
		||||
            prev_solns.push_back(CG_soln);
 | 
			
		||||
          } else {
 | 
			
		||||
@@ -225,7 +228,7 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
	  heatbathRefreshShiftCoefficients(1, -gamma_l*PowerNegHalf.poles[k]);
 | 
			
		||||
          if(use_heatbath_forecasting){
 | 
			
		||||
            Rop.Mdag(CG_src, Forecast_src);
 | 
			
		||||
            CG_soln = Forecast(Rop, Forecast_src, prev_solns);
 | 
			
		||||
            CG_soln = Forecast(MdagMR, Forecast_src, prev_solns);
 | 
			
		||||
            SolverHBR(Rop, CG_src, CG_soln);
 | 
			
		||||
            prev_solns.push_back(CG_soln);
 | 
			
		||||
          } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define CPS_MD_TIME 
 | 
			
		||||
#undef CPS_MD_TIME 
 | 
			
		||||
 | 
			
		||||
#ifdef CPS_MD_TIME
 | 
			
		||||
#define HMC_MOMENTUM_DENOMINATOR (2.0)
 | 
			
		||||
 
 | 
			
		||||
@@ -121,12 +121,19 @@ public:
 | 
			
		||||
 | 
			
		||||
  template <class SmearingPolicy>
 | 
			
		||||
  void Run(SmearingPolicy &S) {
 | 
			
		||||
    Runner(S);
 | 
			
		||||
    TrivialMetric<typename Implementation::Field> Mtr;
 | 
			
		||||
    Runner(S,Mtr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class SmearingPolicy, class Metric>
 | 
			
		||||
  void Run(SmearingPolicy &S, Metric &Mtr) {
 | 
			
		||||
    Runner(S,Mtr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void Run(){
 | 
			
		||||
    NoSmearing<Implementation> S;
 | 
			
		||||
    Runner(S);
 | 
			
		||||
    TrivialMetric<typename Implementation::Field> Mtr;
 | 
			
		||||
    Runner(S,Mtr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //Use the checkpointer to initialize the RNGs and the gauge field, writing the resulting gauge field into U.
 | 
			
		||||
@@ -176,15 +183,15 @@ public:
 | 
			
		||||
  //////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  template <class SmearingPolicy>
 | 
			
		||||
  void Runner(SmearingPolicy &Smearing) {
 | 
			
		||||
  template <class SmearingPolicy, class Metric>
 | 
			
		||||
  void Runner(SmearingPolicy &Smearing, Metric &Mtr) {
 | 
			
		||||
    auto UGrid = Resources.GetCartesian();
 | 
			
		||||
    Field U(UGrid);
 | 
			
		||||
 | 
			
		||||
    initializeGaugeFieldAndRNGs(U);
 | 
			
		||||
 | 
			
		||||
    typedef IntegratorType<SmearingPolicy> TheIntegrator;
 | 
			
		||||
    TheIntegrator MDynamics(UGrid, Parameters.MD, TheAction, Smearing);
 | 
			
		||||
    TheIntegrator MDynamics(UGrid, Parameters.MD, TheAction, Smearing,Mtr);
 | 
			
		||||
 | 
			
		||||
    // Sets the momentum filter
 | 
			
		||||
    MDynamics.setMomentumFilter(*(Resources.GetMomentumFilter()));
 | 
			
		||||
@@ -225,6 +232,18 @@ template <class RepresentationsPolicy,
 | 
			
		||||
using GenericHMCRunnerHirep =
 | 
			
		||||
				     HMCWrapperTemplate<PeriodicGimplR, Integrator, RepresentationsPolicy>;
 | 
			
		||||
 | 
			
		||||
// sp2n
 | 
			
		||||
 | 
			
		||||
template <template <typename, typename, typename> class Integrator>
 | 
			
		||||
using GenericSpHMCRunner = HMCWrapperTemplate<SpPeriodicGimplR, Integrator>;
 | 
			
		||||
 | 
			
		||||
template <class RepresentationsPolicy,
 | 
			
		||||
          template <typename, typename, typename> class Integrator>
 | 
			
		||||
using GenericSpHMCRunnerHirep =
 | 
			
		||||
                     HMCWrapperTemplate<SpPeriodicGimplR, Integrator, RepresentationsPolicy>;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <class Implementation, class RepresentationsPolicy, 
 | 
			
		||||
          template <typename, typename, typename> class Integrator>
 | 
			
		||||
using GenericHMCRunnerTemplate = HMCWrapperTemplate<Implementation, Integrator, RepresentationsPolicy>;
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,8 @@ struct HMCparameters: Serializable {
 | 
			
		||||
                                  Integer, NoMetropolisUntil,
 | 
			
		||||
				  bool, PerformRandomShift, /* @brief Randomly shift the gauge configuration at the start of a trajectory */
 | 
			
		||||
                                  std::string, StartingType,
 | 
			
		||||
				  Integer, SW,
 | 
			
		||||
                                  RealD, Kappa,
 | 
			
		||||
                                  IntegratorParameters, MD)
 | 
			
		||||
 | 
			
		||||
  HMCparameters() {
 | 
			
		||||
@@ -110,6 +112,8 @@ private:
 | 
			
		||||
  IntegratorType &TheIntegrator;
 | 
			
		||||
  ObsListType Observables;
 | 
			
		||||
 | 
			
		||||
  int traj_num;
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////////
 | 
			
		||||
  // Metropolis step
 | 
			
		||||
  /////////////////////////////////////////////////////////
 | 
			
		||||
@@ -200,14 +204,14 @@ private:
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "--------------------------------------------------\n";
 | 
			
		||||
    std::cout << GridLogMessage << " Molecular Dynamics evolution ";
 | 
			
		||||
    TheIntegrator.integrate(U);
 | 
			
		||||
    TheIntegrator.integrate(U,traj_num);
 | 
			
		||||
    std::cout << GridLogMessage << "--------------------------------------------------\n";
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // updated state action
 | 
			
		||||
    //////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    std::cout << GridLogMessage << "--------------------------------------------------\n";
 | 
			
		||||
    std::cout << GridLogMessage << "Compute final action";
 | 
			
		||||
    std::cout << GridLogMessage << "Compute final action" <<std::endl;
 | 
			
		||||
    RealD H1 = TheIntegrator.S(U);  
 | 
			
		||||
    std::cout << GridLogMessage << "--------------------------------------------------\n";
 | 
			
		||||
 | 
			
		||||
@@ -242,7 +246,7 @@ public:
 | 
			
		||||
  HybridMonteCarlo(HMCparameters _Pams, IntegratorType &_Int,
 | 
			
		||||
                   GridSerialRNG &_sRNG, GridParallelRNG &_pRNG, 
 | 
			
		||||
                   ObsListType _Obs, Field &_U)
 | 
			
		||||
    : Params(_Pams), TheIntegrator(_Int), sRNG(_sRNG), pRNG(_pRNG), Observables(_Obs), Ucur(_U) {}
 | 
			
		||||
    : Params(_Pams), TheIntegrator(_Int), sRNG(_sRNG), pRNG(_pRNG), Observables(_Obs), Ucur(_U),traj_num(0) {}
 | 
			
		||||
  ~HybridMonteCarlo(){};
 | 
			
		||||
 | 
			
		||||
  void evolve(void) {
 | 
			
		||||
@@ -258,8 +262,9 @@ public:
 | 
			
		||||
 | 
			
		||||
    for (int traj = Params.StartTrajectory; traj < FinalTrajectory; ++traj) {
 | 
			
		||||
    
 | 
			
		||||
      std::cout << GridLogHMC << "-- # Trajectory = " << traj << "\n";
 | 
			
		||||
 | 
			
		||||
      std::cout << GridLogHMC << "-- # Trajectory = " << traj << "\n";
 | 
			
		||||
      traj_num=traj;
 | 
			
		||||
      if (traj < Params.StartTrajectory + Params.NoMetropolisUntil) {
 | 
			
		||||
      	std::cout << GridLogHMC << "-- Thermalization" << std::endl;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ Copyright (C) 2015
 | 
			
		||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
 | 
			
		||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
Author: Guido Cossu <cossu@post.kek.jp>
 | 
			
		||||
Author: Chulwoo Jung <chulwoo@bnl.gov>
 | 
			
		||||
 | 
			
		||||
This program is free software; you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -33,6 +34,7 @@ directory
 | 
			
		||||
#define INTEGRATOR_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <Grid/parallelIO/NerscIO.h>
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
@@ -41,10 +43,19 @@ public:
 | 
			
		||||
  GRID_SERIALIZABLE_CLASS_MEMBERS(IntegratorParameters,
 | 
			
		||||
				  std::string, name,      // name of the integrator
 | 
			
		||||
				  unsigned int, MDsteps,  // number of outer steps
 | 
			
		||||
				  RealD, RMHMCTol,
 | 
			
		||||
                                  RealD, RMHMCCGTol,
 | 
			
		||||
                                  RealD, lambda0,
 | 
			
		||||
                                  RealD, lambda1,
 | 
			
		||||
                                  RealD, lambda2,
 | 
			
		||||
				  RealD, trajL)           // trajectory length
 | 
			
		||||
 | 
			
		||||
  IntegratorParameters(int MDsteps_ = 10, RealD trajL_ = 1.0)
 | 
			
		||||
  : MDsteps(MDsteps_),
 | 
			
		||||
   lambda0(0.1931833275037836),
 | 
			
		||||
   lambda1(0.1931833275037836),
 | 
			
		||||
   lambda2(0.1931833275037836),
 | 
			
		||||
   RMHMCTol(1e-8),RMHMCCGTol(1e-8),
 | 
			
		||||
    trajL(trajL_) {};
 | 
			
		||||
 | 
			
		||||
  template <class ReaderClass, typename std::enable_if<isReader<ReaderClass>::value, int >::type = 0 >
 | 
			
		||||
@@ -75,11 +86,14 @@ public:
 | 
			
		||||
  double t_U;  // Track time passing on each level and for U and for P
 | 
			
		||||
  std::vector<double> t_P;  
 | 
			
		||||
 | 
			
		||||
  MomentaField P;
 | 
			
		||||
//  MomentaField P;
 | 
			
		||||
  GeneralisedMomenta<FieldImplementation > P;
 | 
			
		||||
  SmearingPolicy& Smearer;
 | 
			
		||||
  RepresentationPolicy Representations;
 | 
			
		||||
  IntegratorParameters Params;
 | 
			
		||||
 | 
			
		||||
  RealD Saux,Smom,Sg;
 | 
			
		||||
 | 
			
		||||
  //Filters allow the user to manipulate the conjugate momentum, for example to freeze links in DDHMC
 | 
			
		||||
  //It is applied whenever the momentum is updated / refreshed
 | 
			
		||||
  //The default filter does nothing
 | 
			
		||||
@@ -96,7 +110,16 @@ public:
 | 
			
		||||
  void update_P(Field& U, int level, double ep) 
 | 
			
		||||
  {
 | 
			
		||||
    t_P[level] += ep;
 | 
			
		||||
    update_P(P, U, level, ep);
 | 
			
		||||
    update_P(P.Mom, U, level, ep);
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogIntegrator << "[" << level << "] P " << " dt " << ep << " : t_P " << t_P[level] << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void update_P2(Field& U, int level, double ep) 
 | 
			
		||||
  {
 | 
			
		||||
    t_P[level] += ep;
 | 
			
		||||
    update_P2(P.Mom, U, level, ep);
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogIntegrator << "[" << level << "] P " << " dt " << ep << " : t_P " << t_P[level] << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -119,62 +142,174 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
  } update_P_hireps{};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
  void update_P(MomentaField& Mom, Field& U, int level, double ep) {
 | 
			
		||||
    // input U actually not used in the fundamental case
 | 
			
		||||
    // Fundamental updates, include smearing
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < as[level].actions.size(); ++a) {
 | 
			
		||||
 | 
			
		||||
      double start_full = usecond();
 | 
			
		||||
      Field force(U.Grid());
 | 
			
		||||
      conformable(U.Grid(), Mom.Grid());
 | 
			
		||||
 | 
			
		||||
      Field& Us = Smearer.get_U(as[level].actions.at(a)->is_smeared);
 | 
			
		||||
      double start_force = usecond();
 | 
			
		||||
      as[level].actions.at(a)->deriv(Us, force);  // deriv should NOT include Ta
 | 
			
		||||
 | 
			
		||||
      as[level].actions.at(a)->deriv_timer_start();
 | 
			
		||||
      as[level].actions.at(a)->deriv(Smearer, force);  // deriv should NOT include Ta
 | 
			
		||||
      as[level].actions.at(a)->deriv_timer_stop();
 | 
			
		||||
 | 
			
		||||
      auto name = as[level].actions.at(a)->action_name();
 | 
			
		||||
 | 
			
		||||
      std::cout << GridLogIntegrator << "Smearing (on/off): " << as[level].actions.at(a)->is_smeared << std::endl;
 | 
			
		||||
      if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force);
 | 
			
		||||
      force = FieldImplementation::projectForce(force); // Ta for gauge fields
 | 
			
		||||
      double end_force = usecond();
 | 
			
		||||
      
 | 
			
		||||
      MomFilter->applyFilter(force);
 | 
			
		||||
 | 
			
		||||
      std::cout << GridLogIntegrator << " update_P : Level [" << level <<"]["<<a <<"] "<<name<<" dt "<<ep<<  std::endl;
 | 
			
		||||
      
 | 
			
		||||
      Real force_abs   = std::sqrt(norm2(force)/U.Grid()->gSites()); //average per-site norm.  nb. norm2(latt) = \sum_x norm2(latt[x]) 
 | 
			
		||||
      Real impulse_abs = force_abs * ep * HMC_MOMENTUM_DENOMINATOR;    
 | 
			
		||||
 | 
			
		||||
      Real force_max   = std::sqrt(maxLocalNorm2(force));
 | 
			
		||||
      Real impulse_max = force_max * ep * HMC_MOMENTUM_DENOMINATOR;    
 | 
			
		||||
 | 
			
		||||
      as[level].actions.at(a)->deriv_log(force_abs,force_max,impulse_abs,impulse_max);
 | 
			
		||||
      
 | 
			
		||||
      std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] dt           : " << ep <<" "<<name<<std::endl;
 | 
			
		||||
      std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] Force average: " << force_abs <<" "<<name<<std::endl;
 | 
			
		||||
      std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] Force max    : " << force_max <<" "<<name<<std::endl;
 | 
			
		||||
      std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] Fdt average  : " << impulse_abs <<" "<<name<<std::endl;
 | 
			
		||||
      std::cout << GridLogIntegrator<< "["<<level<<"]["<<a<<"] Fdt max      : " << impulse_max <<" "<<name<<std::endl;
 | 
			
		||||
 | 
			
		||||
      Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites());
 | 
			
		||||
      std::cout << GridLogIntegrator << "["<<level<<"]["<<a<<"] Force average: " << force_abs << std::endl;
 | 
			
		||||
      Mom -= force * ep* HMC_MOMENTUM_DENOMINATOR;; 
 | 
			
		||||
      double end_full = usecond();
 | 
			
		||||
      double time_full  = (end_full - start_full) / 1e3;
 | 
			
		||||
      double time_force = (end_force - start_force) / 1e3;
 | 
			
		||||
      std::cout << GridLogMessage << "["<<level<<"]["<<a<<"] P update elapsed time: " << time_full << " ms (force: " << time_force << " ms)"  << std::endl;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Force from the other representations
 | 
			
		||||
    as[level].apply(update_P_hireps, Representations, Mom, U, ep);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void update_P2(MomentaField& Mom, Field& U, int level, double ep) {
 | 
			
		||||
    // input U actually not used in the fundamental case
 | 
			
		||||
    // Fundamental updates, include smearing
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogIntegrator << "U before update_P2: " << std::sqrt(norm2(U)) << std::endl;
 | 
			
		||||
    // Generalised momenta  
 | 
			
		||||
    // Derivative of the kinetic term must be computed before
 | 
			
		||||
    // Mom is the momenta and gets updated by the 
 | 
			
		||||
    // actions derivatives
 | 
			
		||||
    MomentaField MomDer(P.Mom.Grid());
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    P.DerivativeU(P.Mom, MomDer);
 | 
			
		||||
    std::cout << GridLogIntegrator << "MomDer update_P2: " << std::sqrt(norm2(MomDer)) << std::endl;
 | 
			
		||||
//    Mom -= MomDer * ep;
 | 
			
		||||
    Mom -= MomDer * ep * HMC_MOMENTUM_DENOMINATOR;
 | 
			
		||||
    std::cout << GridLogIntegrator << "Mom update_P2: " << std::sqrt(norm2(Mom)) << std::endl;
 | 
			
		||||
 | 
			
		||||
    // Auxiliary fields
 | 
			
		||||
    P.update_auxiliary_momenta(ep*0.5 );
 | 
			
		||||
    P.AuxiliaryFieldsDerivative(MomDer);
 | 
			
		||||
    std::cout << GridLogIntegrator << "MomDer(Aux) update_P2: " << std::sqrt(norm2(Mom)) << std::endl;
 | 
			
		||||
//    Mom -= MomDer * ep;
 | 
			
		||||
    Mom -= MomDer * ep * HMC_MOMENTUM_DENOMINATOR;
 | 
			
		||||
    P.update_auxiliary_momenta(ep*0.5 );
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < as[level].actions.size(); ++a) {
 | 
			
		||||
      double start_full = usecond();
 | 
			
		||||
      Field force(U.Grid());
 | 
			
		||||
      conformable(U.Grid(), Mom.Grid());
 | 
			
		||||
 | 
			
		||||
      Field& Us = Smearer.get_U(as[level].actions.at(a)->is_smeared);
 | 
			
		||||
      double start_force = usecond();
 | 
			
		||||
      as[level].actions.at(a)->deriv(Us, force);  // deriv should NOT include Ta
 | 
			
		||||
 | 
			
		||||
      std::cout << GridLogIntegrator << "Smearing (on/off): " << as[level].actions.at(a)->is_smeared << std::endl;
 | 
			
		||||
      if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force);
 | 
			
		||||
      force = FieldImplementation::projectForce(force); // Ta for gauge fields
 | 
			
		||||
      double end_force = usecond();
 | 
			
		||||
      Real force_abs = std::sqrt(norm2(force)/U.Grid()->gSites());
 | 
			
		||||
      std::cout << GridLogIntegrator << "["<<level<<"]["<<a<<"] Force average: " << force_abs << std::endl;
 | 
			
		||||
      Mom -= force * ep* HMC_MOMENTUM_DENOMINATOR;; 
 | 
			
		||||
      double end_full = usecond();
 | 
			
		||||
      double time_full  = (end_full - start_full) / 1e3;
 | 
			
		||||
      double time_force = (end_force - start_force) / 1e3;
 | 
			
		||||
      std::cout << GridLogMessage << "["<<level<<"]["<<a<<"] P update elapsed time: " << time_full << " ms (force: " << time_force << " ms)"  << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Force from the other representations
 | 
			
		||||
    as[level].apply(update_P_hireps, Representations, Mom, U, ep);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void implicit_update_P(Field& U, int level, double ep, double ep1, bool intermediate = false) {
 | 
			
		||||
    t_P[level] += ep;
 | 
			
		||||
 | 
			
		||||
    double ep2= ep-ep1;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogIntegrator << "[" << level << "] P "
 | 
			
		||||
              << " dt " << ep << " : t_P " << t_P[level] << std::endl;
 | 
			
		||||
    std::cout << GridLogIntegrator << "U before implicit_update_P: " << std::sqrt(norm2(U)) << std::endl;
 | 
			
		||||
    // Fundamental updates, include smearing
 | 
			
		||||
    MomentaField Msum(P.Mom.Grid());
 | 
			
		||||
    Msum = Zero();
 | 
			
		||||
    for (int a = 0; a < as[level].actions.size(); ++a) {
 | 
			
		||||
      // Compute the force terms for the lagrangian part
 | 
			
		||||
      // We need to compute the derivative of the actions
 | 
			
		||||
      // only once
 | 
			
		||||
      Field force(U.Grid());
 | 
			
		||||
      conformable(U.Grid(), P.Mom.Grid());
 | 
			
		||||
      Field& Us = Smearer.get_U(as[level].actions.at(a)->is_smeared);
 | 
			
		||||
      as[level].actions.at(a)->deriv(Us, force);  // deriv should NOT include Ta
 | 
			
		||||
 | 
			
		||||
      std::cout << GridLogIntegrator << "Smearing (on/off): " << as[level].actions.at(a)->is_smeared << std::endl;
 | 
			
		||||
      if (as[level].actions.at(a)->is_smeared) Smearer.smeared_force(force);
 | 
			
		||||
      force = FieldImplementation::projectForce(force);  // Ta for gauge fields
 | 
			
		||||
      Real force_abs = std::sqrt(norm2(force) / U.Grid()->gSites());
 | 
			
		||||
      std::cout << GridLogIntegrator << "|Force| site average: " << force_abs
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      Msum += force;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MomentaField NewMom = P.Mom;
 | 
			
		||||
    MomentaField OldMom = P.Mom;
 | 
			
		||||
    double threshold = Params.RMHMCTol;
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    MomentaField MomDer(P.Mom.Grid());
 | 
			
		||||
    MomentaField MomDer1(P.Mom.Grid());
 | 
			
		||||
    MomentaField AuxDer(P.Mom.Grid());
 | 
			
		||||
    MomDer1 = Zero();
 | 
			
		||||
    MomentaField diff(P.Mom.Grid());
 | 
			
		||||
    double factor = 2.0;
 | 
			
		||||
    if (intermediate){
 | 
			
		||||
      P.DerivativeU(P.Mom, MomDer1);
 | 
			
		||||
      factor = 1.0;
 | 
			
		||||
    }
 | 
			
		||||
//    std::cout << GridLogIntegrator << "MomDer1 implicit_update_P: " << std::sqrt(norm2(MomDer1)) << std::endl;
 | 
			
		||||
 | 
			
		||||
    // Auxiliary fields
 | 
			
		||||
    P.update_auxiliary_momenta(ep1);
 | 
			
		||||
    P.AuxiliaryFieldsDerivative(AuxDer);
 | 
			
		||||
    Msum += AuxDer;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // Here run recursively
 | 
			
		||||
    int counter = 1;
 | 
			
		||||
    RealD RelativeError;
 | 
			
		||||
    do {
 | 
			
		||||
      std::cout << GridLogIntegrator << "UpdateP implicit step "<< counter << std::endl;
 | 
			
		||||
 | 
			
		||||
      // Compute the derivative of the kinetic term
 | 
			
		||||
      // with respect to the gauge field
 | 
			
		||||
      P.DerivativeU(NewMom, MomDer);
 | 
			
		||||
      Real force_abs = std::sqrt(norm2(MomDer) / U.Grid()->gSites());
 | 
			
		||||
      std::cout << GridLogIntegrator << "|Force| laplacian site average: " << force_abs
 | 
			
		||||
                << std::endl;
 | 
			
		||||
 | 
			
		||||
//      NewMom = P.Mom - ep* 0.5 * HMC_MOMENTUM_DENOMINATOR * (2.0*Msum + factor*MomDer + MomDer1);// simplify
 | 
			
		||||
      NewMom = P.Mom -  HMC_MOMENTUM_DENOMINATOR * (ep*Msum + ep1* factor*MomDer + ep2* MomDer1);// simplify
 | 
			
		||||
      diff = NewMom - OldMom;
 | 
			
		||||
      counter++;
 | 
			
		||||
      RelativeError = std::sqrt(norm2(diff))/std::sqrt(norm2(NewMom));
 | 
			
		||||
      std::cout << GridLogIntegrator << "UpdateP RelativeError: " << RelativeError << std::endl;
 | 
			
		||||
      OldMom = NewMom;
 | 
			
		||||
    } while (RelativeError > threshold);
 | 
			
		||||
 | 
			
		||||
    P.Mom = NewMom;
 | 
			
		||||
    std::cout << GridLogIntegrator << "NewMom implicit_update_P: " << std::sqrt(norm2(NewMom)) << std::endl;
 | 
			
		||||
 | 
			
		||||
    // update the auxiliary fields momenta    
 | 
			
		||||
    P.update_auxiliary_momenta(ep2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void implicit_update_P(Field& U, int level, double ep, bool intermediate = false) {
 | 
			
		||||
      implicit_update_P( U, level, ep, ep*0.5, intermediate ); 
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void update_U(Field& U, double ep) 
 | 
			
		||||
  {
 | 
			
		||||
    update_U(P, U, ep);
 | 
			
		||||
    update_U(P.Mom, U, ep);
 | 
			
		||||
 | 
			
		||||
    t_U += ep;
 | 
			
		||||
    int fl = levels - 1;
 | 
			
		||||
@@ -183,12 +318,8 @@ public:
 | 
			
		||||
  
 | 
			
		||||
  void update_U(MomentaField& Mom, Field& U, double ep) 
 | 
			
		||||
  {
 | 
			
		||||
    MomentaField MomFiltered(Mom.Grid());
 | 
			
		||||
    MomFiltered = Mom;
 | 
			
		||||
    MomFilter->applyFilter(MomFiltered);
 | 
			
		||||
 | 
			
		||||
    // exponential of Mom*U in the gauge fields case
 | 
			
		||||
    FieldImplementation::update_field(MomFiltered, U, ep);
 | 
			
		||||
    FieldImplementation::update_field(Mom, U, ep);
 | 
			
		||||
 | 
			
		||||
    // Update the smeared fields, can be implemented as observer
 | 
			
		||||
    Smearer.set_Field(U);
 | 
			
		||||
@@ -197,18 +328,74 @@ public:
 | 
			
		||||
    Representations.update(U);  // void functions if fundamental representation
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void implicit_update_U(Field&U, double ep, double ep1 ){
 | 
			
		||||
    double ep2=ep-ep1;
 | 
			
		||||
    t_U += ep;
 | 
			
		||||
    int fl = levels - 1;
 | 
			
		||||
    std::cout << GridLogIntegrator << "   " << "[" << fl << "] U " << " dt " << ep << " : t_U " << t_U << std::endl;
 | 
			
		||||
    std::cout << GridLogIntegrator << "U before implicit_update_U: " << std::sqrt(norm2(U)) << std::endl;
 | 
			
		||||
 | 
			
		||||
    MomentaField Mom1(P.Mom.Grid());
 | 
			
		||||
    MomentaField Mom2(P.Mom.Grid());
 | 
			
		||||
    RealD RelativeError;
 | 
			
		||||
    Field diff(U.Grid());
 | 
			
		||||
    Real threshold =  Params.RMHMCTol;
 | 
			
		||||
    int counter = 1;
 | 
			
		||||
    int MaxCounter = 100;
 | 
			
		||||
 | 
			
		||||
    Field OldU = U;
 | 
			
		||||
    Field NewU = U;
 | 
			
		||||
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    P.DerivativeP(Mom1); // first term in the derivative 
 | 
			
		||||
    std::cout << GridLogIntegrator << "implicit_update_U: Mom1: " << std::sqrt(norm2(Mom1)) << std::endl;
 | 
			
		||||
 | 
			
		||||
    P.update_auxiliary_fields(ep1);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    MomentaField sum=Mom1;
 | 
			
		||||
    do {
 | 
			
		||||
      std::cout << GridLogIntegrator << "UpdateU implicit step "<< counter << std::endl;
 | 
			
		||||
      
 | 
			
		||||
      P.DerivativeP(Mom2); // second term in the derivative, on the updated U
 | 
			
		||||
      std::cout << GridLogIntegrator << "implicit_update_U: Mom1: " << std::sqrt(norm2(Mom1)) << std::endl;
 | 
			
		||||
      sum = (Mom1*ep1 + Mom2*ep2);
 | 
			
		||||
 | 
			
		||||
      for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
        auto Umu = PeekIndex<LorentzIndex>(U, mu);
 | 
			
		||||
        auto Pmu = PeekIndex<LorentzIndex>(sum, mu);
 | 
			
		||||
        Umu = expMat(Pmu, 1, 12) * Umu;
 | 
			
		||||
        PokeIndex<LorentzIndex>(NewU, ProjectOnGroup(Umu), mu);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      diff = NewU - OldU;
 | 
			
		||||
      RelativeError = std::sqrt(norm2(diff))/std::sqrt(norm2(NewU));
 | 
			
		||||
      std::cout << GridLogIntegrator << "UpdateU RelativeError: " << RelativeError << std::endl;
 | 
			
		||||
      
 | 
			
		||||
      P.M.ImportGauge(NewU);
 | 
			
		||||
      OldU = NewU; // some redundancy to be eliminated
 | 
			
		||||
      counter++;
 | 
			
		||||
    } while (RelativeError > threshold && counter < MaxCounter);
 | 
			
		||||
 | 
			
		||||
    U = NewU;
 | 
			
		||||
    std::cout << GridLogIntegrator << "NewU implicit_update_U: " << std::sqrt(norm2(U)) << std::endl;
 | 
			
		||||
    P.update_auxiliary_fields(ep2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  virtual void step(Field& U, int level, int first, int last) = 0;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  Integrator(GridBase* grid, IntegratorParameters Par,
 | 
			
		||||
             ActionSet<Field, RepresentationPolicy>& Aset,
 | 
			
		||||
             SmearingPolicy& Sm)
 | 
			
		||||
             SmearingPolicy& Sm, Metric<MomentaField>& M)
 | 
			
		||||
    : Params(Par),
 | 
			
		||||
      as(Aset),
 | 
			
		||||
      P(grid),
 | 
			
		||||
      P(grid, M),
 | 
			
		||||
      levels(Aset.size()),
 | 
			
		||||
      Smearer(Sm),
 | 
			
		||||
      Representations(grid) 
 | 
			
		||||
      Representations(grid),
 | 
			
		||||
      Saux(0.),Smom(0.),Sg(0.)
 | 
			
		||||
  {
 | 
			
		||||
    t_P.resize(levels, 0.0);
 | 
			
		||||
    t_U = 0.0;
 | 
			
		||||
@@ -324,7 +511,8 @@ public:
 | 
			
		||||
 | 
			
		||||
  void reverse_momenta()
 | 
			
		||||
  {
 | 
			
		||||
    P *= -1.0;
 | 
			
		||||
    P.Mom *= -1.0;
 | 
			
		||||
    P.AuxMom *= -1.0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // to be used by the actionlevel class to iterate
 | 
			
		||||
@@ -343,11 +531,14 @@ public:
 | 
			
		||||
  // Initialization of momenta and actions
 | 
			
		||||
  void refresh(Field& U,  GridSerialRNG & sRNG, GridParallelRNG& pRNG) 
 | 
			
		||||
  {
 | 
			
		||||
    assert(P.Grid() == U.Grid());
 | 
			
		||||
    assert(P.Mom.Grid() == U.Grid());
 | 
			
		||||
    std::cout << GridLogIntegrator << "Integrator refresh" << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogIntegrator << "Generating momentum" << std::endl;
 | 
			
		||||
    FieldImplementation::generate_momenta(P, sRNG, pRNG);
 | 
			
		||||
//    FieldImplementation::generate_momenta(P.Mom, sRNG, pRNG);
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    P.MomentaDistribution(sRNG,pRNG);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Update the smeared fields, can be implemented as observer
 | 
			
		||||
    // necessary to keep the fields updated even after a reject
 | 
			
		||||
@@ -402,9 +593,22 @@ public:
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogIntegrator << "Integrator action\n";
 | 
			
		||||
 | 
			
		||||
    RealD H = - FieldImplementation::FieldSquareNorm(P)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
//    RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
//    RealD Hterm;
 | 
			
		||||
 | 
			
		||||
//    static RealD Saux=0.,Smom=0.,Sg=0.;
 | 
			
		||||
 | 
			
		||||
    RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
    std::cout << GridLogMessage << "S:FieldSquareNorm H_p = " << H << "\n";
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSField = " << H-Smom << "\n";
 | 
			
		||||
    Smom=H;
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    RealD Hterm = - P.MomentaAction();
 | 
			
		||||
    std::cout << GridLogMessage << "S:Momentum action H_p = " << Hterm << "\n";
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSMom = " << Hterm-Saux << "\n";
 | 
			
		||||
    Saux=Hterm;
 | 
			
		||||
    H = Hterm;
 | 
			
		||||
 | 
			
		||||
    RealD Hterm;
 | 
			
		||||
 | 
			
		||||
    // Actions
 | 
			
		||||
    for (int level = 0; level < as.size(); ++level) {
 | 
			
		||||
@@ -446,9 +650,18 @@ public:
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogIntegrator << "Integrator initial action\n";
 | 
			
		||||
 | 
			
		||||
    RealD H = - FieldImplementation::FieldSquareNorm(P)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
 | 
			
		||||
    RealD Hterm;
 | 
			
		||||
//    RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
//    RealD Hterm;
 | 
			
		||||
    RealD H = - FieldImplementation::FieldSquareNorm(P.Mom)/HMC_MOMENTUM_DENOMINATOR; // - trace (P*P)/denom
 | 
			
		||||
    std::cout << GridLogMessage << "S:FieldSquareNorm H_p = " << H << "\n";
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSField = " << H-Smom << "\n";
 | 
			
		||||
    Smom=H;
 | 
			
		||||
    P.M.ImportGauge(U);
 | 
			
		||||
    RealD Hterm = - P.MomentaAction();
 | 
			
		||||
    std::cout << GridLogMessage << "S:Momentum action H_p = " << Hterm << "\n";
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSMom = " << Hterm-Saux << "\n";
 | 
			
		||||
    Saux=Hterm;
 | 
			
		||||
    H = Hterm;
 | 
			
		||||
 | 
			
		||||
    // Actions
 | 
			
		||||
    for (int level = 0; level < as.size(); ++level) {
 | 
			
		||||
@@ -471,7 +684,7 @@ public:
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  void integrate(Field& U) 
 | 
			
		||||
  void integrate(Field& U, int traj=-1 ) 
 | 
			
		||||
  {
 | 
			
		||||
    // reset the clocks
 | 
			
		||||
    t_U = 0;
 | 
			
		||||
@@ -483,6 +696,12 @@ public:
 | 
			
		||||
      int first_step = (stp == 0);
 | 
			
		||||
      int last_step = (stp == Params.MDsteps - 1);
 | 
			
		||||
      this->step(U, 0, first_step, last_step);
 | 
			
		||||
      if (traj>=0){
 | 
			
		||||
        std::string file("./config."+std::to_string(traj)+"_"+std::to_string(stp+1) );
 | 
			
		||||
        int precision32 = 0;
 | 
			
		||||
        int tworow      = 0;
 | 
			
		||||
        NerscIO::writeConfiguration(U,file,tworow,precision32);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check the clocks all match on all levels
 | 
			
		||||
@@ -492,7 +711,6 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FieldImplementation::Project(U);
 | 
			
		||||
 | 
			
		||||
    // and that we indeed got to the end of the trajectory
 | 
			
		||||
    assert(fabs(t_U - Params.trajL) < 1.0e-6);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -102,8 +102,8 @@ public:
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "LeapFrog";}
 | 
			
		||||
 | 
			
		||||
  LeapFrog(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm){};
 | 
			
		||||
  LeapFrog(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm,M){};
 | 
			
		||||
 | 
			
		||||
  void step(Field& U, int level, int _first, int _last) {
 | 
			
		||||
    int fl = this->as.size() - 1;
 | 
			
		||||
@@ -140,14 +140,14 @@ template <class FieldImplementation_, class SmearingPolicy, class Representation
 | 
			
		||||
class MinimumNorm2 : public Integrator<FieldImplementation_, SmearingPolicy, RepresentationPolicy> 
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
  const RealD lambda = 0.1931833275037836;
 | 
			
		||||
//  const RealD lambda = 0.1931833275037836;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  typedef FieldImplementation_ FieldImplementation;
 | 
			
		||||
  INHERIT_FIELD_TYPES(FieldImplementation);
 | 
			
		||||
 | 
			
		||||
  MinimumNorm2(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm){};
 | 
			
		||||
  MinimumNorm2(GridBase* grid, IntegratorParameters Par, ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(grid, Par, Aset, Sm,M){};
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "MininumNorm2";}
 | 
			
		||||
 | 
			
		||||
@@ -155,6 +155,11 @@ public:
 | 
			
		||||
    // level  : current level
 | 
			
		||||
    // fl     : final level
 | 
			
		||||
    // eps    : current step size
 | 
			
		||||
    assert(level<3);
 | 
			
		||||
    RealD lambda= this->Params.lambda0;
 | 
			
		||||
    if (level>0) lambda= this->Params.lambda1;
 | 
			
		||||
    if (level>1) lambda= this->Params.lambda2;
 | 
			
		||||
    std::cout << GridLogMessage << "level: "<<level<< "lambda: "<<lambda<<std::endl;
 | 
			
		||||
 | 
			
		||||
    int fl = this->as.size() - 1;
 | 
			
		||||
 | 
			
		||||
@@ -210,9 +215,9 @@ public:
 | 
			
		||||
  // Looks like dH scales as dt^4. tested wilson/wilson 2 level.
 | 
			
		||||
  ForceGradient(GridBase* grid, IntegratorParameters Par,
 | 
			
		||||
                ActionSet<Field, RepresentationPolicy>& Aset,
 | 
			
		||||
                SmearingPolicy& Sm)
 | 
			
		||||
                SmearingPolicy& Sm, Metric<Field>& M)
 | 
			
		||||
    : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
 | 
			
		||||
									    grid, Par, Aset, Sm){};
 | 
			
		||||
									    grid, Par, Aset, Sm,M){};
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "ForceGradient";}
 | 
			
		||||
  
 | 
			
		||||
@@ -275,6 +280,255 @@ public:
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
////////////////////////////////
 | 
			
		||||
// Riemannian Manifold HMC
 | 
			
		||||
// Girolami et al
 | 
			
		||||
////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// correct
 | 
			
		||||
template <class FieldImplementation, class SmearingPolicy,
 | 
			
		||||
          class RepresentationPolicy =
 | 
			
		||||
              Representations<FundamentalRepresentation> >
 | 
			
		||||
class ImplicitLeapFrog : public Integrator<FieldImplementation, SmearingPolicy,
 | 
			
		||||
                                           RepresentationPolicy> {
 | 
			
		||||
 public:
 | 
			
		||||
  typedef ImplicitLeapFrog<FieldImplementation, SmearingPolicy, RepresentationPolicy>
 | 
			
		||||
      Algorithm;
 | 
			
		||||
  INHERIT_FIELD_TYPES(FieldImplementation);
 | 
			
		||||
 | 
			
		||||
  // Riemannian manifold metric operator
 | 
			
		||||
  // Hermitian operator Fisher
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "ImplicitLeapFrog";}
 | 
			
		||||
 | 
			
		||||
  ImplicitLeapFrog(GridBase* grid, IntegratorParameters Par,
 | 
			
		||||
           ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
 | 
			
		||||
      : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
 | 
			
		||||
            grid, Par, Aset, Sm, M){};
 | 
			
		||||
 | 
			
		||||
  void step(Field& U, int level, int _first, int _last) {
 | 
			
		||||
    int fl = this->as.size() - 1;
 | 
			
		||||
    // level  : current level
 | 
			
		||||
    // fl     : final level
 | 
			
		||||
    // eps    : current step size
 | 
			
		||||
 | 
			
		||||
    // Get current level step size
 | 
			
		||||
    RealD eps = this->Params.trajL/this->Params.MDsteps;
 | 
			
		||||
    for (int l = 0; l <= level; ++l) eps /= this->as[l].multiplier;
 | 
			
		||||
 | 
			
		||||
    int multiplier = this->as[level].multiplier;
 | 
			
		||||
    for (int e = 0; e < multiplier; ++e) {
 | 
			
		||||
      int first_step = _first && (e == 0);
 | 
			
		||||
      int last_step = _last && (e == multiplier - 1);
 | 
			
		||||
 | 
			
		||||
      if (first_step) {  // initial half step
 | 
			
		||||
       this->implicit_update_P(U, level, eps / 2.0);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (level == fl) {  // lowest level
 | 
			
		||||
        this->implicit_update_U(U, eps,eps/2.);
 | 
			
		||||
      } else {  // recursive function call
 | 
			
		||||
        this->step(U, level + 1, first_step, last_step);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //int mm = last_step ? 1 : 2;
 | 
			
		||||
      if (last_step){
 | 
			
		||||
        this->update_P2(U, level, eps / 2.0);
 | 
			
		||||
      } else {
 | 
			
		||||
      this->implicit_update_P(U, level, eps, true);// works intermediate step
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <class FieldImplementation, class SmearingPolicy,
 | 
			
		||||
          class RepresentationPolicy =
 | 
			
		||||
              Representations<FundamentalRepresentation> >
 | 
			
		||||
class ImplicitMinimumNorm2 : public Integrator<FieldImplementation, SmearingPolicy,
 | 
			
		||||
                                       RepresentationPolicy> {
 | 
			
		||||
 private:
 | 
			
		||||
//  const RealD lambda = 0.1931833275037836;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  INHERIT_FIELD_TYPES(FieldImplementation);
 | 
			
		||||
 | 
			
		||||
  ImplicitMinimumNorm2(GridBase* grid, IntegratorParameters Par,
 | 
			
		||||
               ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
 | 
			
		||||
      : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
 | 
			
		||||
            grid, Par, Aset, Sm, M){};
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "ImplicitMininumNorm2";}
 | 
			
		||||
 | 
			
		||||
  void step(Field& U, int level, int _first, int _last) {
 | 
			
		||||
    // level  : current level
 | 
			
		||||
    // fl     : final level
 | 
			
		||||
    // eps    : current step size
 | 
			
		||||
 | 
			
		||||
    int fl = this->as.size() - 1;
 | 
			
		||||
//    assert(Params.lambda.size()>level);
 | 
			
		||||
//    RealD lambda= Params.lambda[level];
 | 
			
		||||
    assert(level<3);
 | 
			
		||||
    RealD lambda= this->Params.lambda0;
 | 
			
		||||
    if (level>0) lambda= this->Params.lambda1;
 | 
			
		||||
    if (level>1) lambda= this->Params.lambda2;
 | 
			
		||||
    std::cout << GridLogMessage << "level: "<<level<< "lambda: "<<lambda<<std::endl;
 | 
			
		||||
 | 
			
		||||
  if(level<fl){
 | 
			
		||||
 | 
			
		||||
    RealD eps = this->Params.trajL/this->Params.MDsteps * 2.0;
 | 
			
		||||
    for (int l = 0; l <= level; ++l) eps /= 2.0 * this->as[l].multiplier;
 | 
			
		||||
 | 
			
		||||
    // Nesting:  2xupdate_U of size eps/2
 | 
			
		||||
    // Next level is eps/2/multiplier
 | 
			
		||||
 | 
			
		||||
    int multiplier = this->as[level].multiplier;
 | 
			
		||||
    for (int e = 0; e < multiplier; ++e) {  // steps per step
 | 
			
		||||
 | 
			
		||||
      int first_step = _first && (e == 0);
 | 
			
		||||
      int last_step = _last && (e == multiplier - 1);
 | 
			
		||||
 | 
			
		||||
      if (first_step) {  // initial half step
 | 
			
		||||
        this->update_P(U, level, lambda * eps);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        this->step(U, level + 1, first_step, 0);
 | 
			
		||||
 | 
			
		||||
      this->update_P(U, level, (1.0 - 2.0 * lambda) * eps);
 | 
			
		||||
 | 
			
		||||
        this->step(U, level + 1, 0, last_step);
 | 
			
		||||
 | 
			
		||||
      int mm = (last_step) ? 1 : 2;
 | 
			
		||||
      this->update_P(U, level, lambda * eps * mm);
 | 
			
		||||
    }
 | 
			
		||||
  } 
 | 
			
		||||
  else 
 | 
			
		||||
  { // last level
 | 
			
		||||
    RealD eps = this->Params.trajL/this->Params.MDsteps * 2.0;
 | 
			
		||||
    for (int l = 0; l <= level; ++l) eps /= 2.0 * this->as[l].multiplier;
 | 
			
		||||
 | 
			
		||||
    // Nesting:  2xupdate_U of size eps/2
 | 
			
		||||
    // Next level is eps/2/multiplier
 | 
			
		||||
 | 
			
		||||
    int multiplier = this->as[level].multiplier;
 | 
			
		||||
    for (int e = 0; e < multiplier; ++e) {  // steps per step
 | 
			
		||||
 | 
			
		||||
      int first_step = _first && (e == 0);
 | 
			
		||||
      int last_step = _last && (e == multiplier - 1);
 | 
			
		||||
 | 
			
		||||
      if (first_step) {  // initial half step
 | 
			
		||||
        this->implicit_update_P(U, level, lambda * eps);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this->implicit_update_U(U, 0.5 * eps,lambda*eps);
 | 
			
		||||
 | 
			
		||||
      this->implicit_update_P(U, level, (1.0 - 2.0 * lambda) * eps, true);
 | 
			
		||||
 | 
			
		||||
      this->implicit_update_U(U, 0.5 * eps, (0.5-lambda)*eps);
 | 
			
		||||
 | 
			
		||||
      if (last_step) {
 | 
			
		||||
        this->update_P2(U, level, eps * lambda);
 | 
			
		||||
      } else {
 | 
			
		||||
        this->implicit_update_P(U, level, lambda * eps*2.0, true);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class FieldImplementation, class SmearingPolicy,
 | 
			
		||||
          class RepresentationPolicy =
 | 
			
		||||
              Representations<FundamentalRepresentation> >
 | 
			
		||||
class ImplicitCampostrini : public Integrator<FieldImplementation, SmearingPolicy,
 | 
			
		||||
                                       RepresentationPolicy> {
 | 
			
		||||
 private:
 | 
			
		||||
//  const RealD lambda = 0.1931833275037836;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  INHERIT_FIELD_TYPES(FieldImplementation);
 | 
			
		||||
 | 
			
		||||
  ImplicitCampostrini(GridBase* grid, IntegratorParameters Par,
 | 
			
		||||
               ActionSet<Field, RepresentationPolicy>& Aset, SmearingPolicy& Sm, Metric<Field>& M)
 | 
			
		||||
      : Integrator<FieldImplementation, SmearingPolicy, RepresentationPolicy>(
 | 
			
		||||
            grid, Par, Aset, Sm, M){};
 | 
			
		||||
 | 
			
		||||
  std::string integrator_name(){return "ImplicitCampostrini";}
 | 
			
		||||
 | 
			
		||||
  void step(Field& U, int level, int _first, int _last) {
 | 
			
		||||
    // level  : current level
 | 
			
		||||
    // fl     : final level
 | 
			
		||||
    // eps    : current step size
 | 
			
		||||
 | 
			
		||||
    int fl = this->as.size() - 1;
 | 
			
		||||
//    assert(Params.lambda.size()>level);
 | 
			
		||||
//    RealD lambda= Params.lambda[level];
 | 
			
		||||
    assert(level<3);
 | 
			
		||||
    RealD lambda= this->Params.lambda0;
 | 
			
		||||
    if (level>0) lambda= this->Params.lambda1;
 | 
			
		||||
    if (level>1) lambda= this->Params.lambda2;
 | 
			
		||||
    std::cout << GridLogMessage << "level: "<<level<< "lambda: "<<lambda<<std::endl;
 | 
			
		||||
    
 | 
			
		||||
    RealD sigma=pow(2.0,1./3.);
 | 
			
		||||
 | 
			
		||||
  if(level<fl){
 | 
			
		||||
//Still Omelyan. Needs to change step() to accept variable stepsize
 | 
			
		||||
    RealD eps = this->Params.trajL/this->Params.MDsteps * 2.0;
 | 
			
		||||
    for (int l = 0; l <= level; ++l) eps /= 2.0 * this->as[l].multiplier;
 | 
			
		||||
 | 
			
		||||
    // Nesting:  2xupdate_U of size eps/2
 | 
			
		||||
    // Next level is eps/2/multiplier
 | 
			
		||||
 | 
			
		||||
    int multiplier = this->as[level].multiplier;
 | 
			
		||||
    for (int e = 0; e < multiplier; ++e) {  // steps per step
 | 
			
		||||
 | 
			
		||||
      int first_step = _first && (e == 0);
 | 
			
		||||
      int last_step = _last && (e == multiplier - 1);
 | 
			
		||||
 | 
			
		||||
      if (first_step) {  // initial half step
 | 
			
		||||
        this->update_P(U, level, lambda * eps);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        this->step(U, level + 1, first_step, 0);
 | 
			
		||||
 | 
			
		||||
      this->update_P(U, level, (1.0 - 2.0 * lambda) * eps);
 | 
			
		||||
 | 
			
		||||
        this->step(U, level + 1, 0, last_step);
 | 
			
		||||
 | 
			
		||||
      int mm = (last_step) ? 1 : 2;
 | 
			
		||||
      this->update_P(U, level, lambda * eps * mm);
 | 
			
		||||
    }
 | 
			
		||||
  } 
 | 
			
		||||
  else 
 | 
			
		||||
  { // last level
 | 
			
		||||
    RealD dt = this->Params.trajL/this->Params.MDsteps * 2.0;
 | 
			
		||||
    for (int l = 0; l <= level; ++l) dt /= 2.0 * this->as[l].multiplier;
 | 
			
		||||
 | 
			
		||||
    RealD epsilon = dt/(2.0 - sigma);
 | 
			
		||||
 | 
			
		||||
    int multiplier = this->as[level].multiplier;
 | 
			
		||||
    for (int e = 0; e < multiplier; ++e) {  // steps per step
 | 
			
		||||
 | 
			
		||||
      int first_step = _first && (e == 0);
 | 
			
		||||
      int last_step = _last && (e == multiplier - 1);
 | 
			
		||||
      // initial half step
 | 
			
		||||
      if (first_step) {  this->implicit_update_P(U, level, epsilon*0.5); }
 | 
			
		||||
      this->implicit_update_U(U, epsilon,epsilon*0.5);
 | 
			
		||||
      this->implicit_update_P(U, level, (1.0 - sigma) * epsilon *0.5, epsilon*0.5, true);
 | 
			
		||||
      this->implicit_update_U(U, -epsilon*sigma, -epsilon*sigma*0.5);
 | 
			
		||||
      this->implicit_update_P(U, level, (1.0 - sigma) * epsilon *0.5, -epsilon*sigma*0.5, true);
 | 
			
		||||
      this->implicit_update_U(U, epsilon,epsilon*0.5);
 | 
			
		||||
      if (last_step) { this->update_P2(U, level, epsilon*0.5 ); } 
 | 
			
		||||
      else
 | 
			
		||||
      this->implicit_update_P(U, level, epsilon,epsilon*0.5);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
#endif  // INTEGRATOR_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 * Empty since HMC updates already the fundamental representation 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
template <int ncolour>
 | 
			
		||||
template <int ncolour, class group_name>
 | 
			
		||||
class FundamentalRep {
 | 
			
		||||
public:
 | 
			
		||||
  static const int Dimension = ncolour;
 | 
			
		||||
@@ -21,7 +21,7 @@ public:
 | 
			
		||||
 | 
			
		||||
  // typdef to be used by the Representations class in HMC to get the
 | 
			
		||||
  // types for the higher representation fields
 | 
			
		||||
  typedef typename SU<ncolour>::LatticeMatrix LatticeMatrix;
 | 
			
		||||
  typedef typename GaugeGroup<ncolour,group_name>::LatticeMatrix LatticeMatrix;
 | 
			
		||||
  typedef LatticeGaugeField LatticeField;
 | 
			
		||||
  
 | 
			
		||||
  explicit FundamentalRep(GridBase* grid) {} //do nothing
 | 
			
		||||
@@ -45,7 +45,8 @@ public:
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
typedef	 FundamentalRep<Nc> FundamentalRepresentation;
 | 
			
		||||
typedef	 FundamentalRep<Nc,GroupName::SU> FundamentalRepresentation;
 | 
			
		||||
typedef	 FundamentalRep<Nc,GroupName::Sp> SpFundamentalRepresentation;
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);  
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,14 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 * in the SUnTwoIndex.h file
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
template <int ncolour, TwoIndexSymmetry S>
 | 
			
		||||
template <int ncolour, TwoIndexSymmetry S, class group_name = GroupName::SU>
 | 
			
		||||
class TwoIndexRep {
 | 
			
		||||
public:
 | 
			
		||||
  // typdef to be used by the Representations class in HMC to get the
 | 
			
		||||
  // types for the higher representation fields
 | 
			
		||||
  typedef typename SU_TwoIndex<ncolour, S>::LatticeTwoIndexMatrix LatticeMatrix;
 | 
			
		||||
  typedef typename SU_TwoIndex<ncolour, S>::LatticeTwoIndexField LatticeField;
 | 
			
		||||
  static const int Dimension = ncolour * (ncolour + S) / 2;
 | 
			
		||||
  typedef typename GaugeGroupTwoIndex<ncolour, S, group_name>::LatticeTwoIndexMatrix LatticeMatrix;
 | 
			
		||||
  typedef typename GaugeGroupTwoIndex<ncolour, S, group_name>::LatticeTwoIndexField LatticeField;
 | 
			
		||||
  static const int Dimension = GaugeGroupTwoIndex<ncolour,S,group_name>::Dimension;
 | 
			
		||||
  static const bool isFundamental = false;
 | 
			
		||||
 | 
			
		||||
  LatticeField U;
 | 
			
		||||
@@ -43,10 +43,10 @@ public:
 | 
			
		||||
    U = Zero();
 | 
			
		||||
    LatticeColourMatrix tmp(Uin.Grid());
 | 
			
		||||
 | 
			
		||||
    Vector<typename SU<ncolour>::Matrix> eij(Dimension);
 | 
			
		||||
    Vector<typename GaugeGroup<ncolour,group_name>::Matrix> eij(Dimension);
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < Dimension; a++)
 | 
			
		||||
      SU_TwoIndex<ncolour, S>::base(a, eij[a]);
 | 
			
		||||
      GaugeGroupTwoIndex<ncolour, S, group_name>::base(a, eij[a]);
 | 
			
		||||
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      auto Uin_mu = peekLorentz(Uin, mu);
 | 
			
		||||
@@ -71,7 +71,7 @@ public:
 | 
			
		||||
 | 
			
		||||
      out_mu = Zero();
 | 
			
		||||
 | 
			
		||||
      typename SU<ncolour>::LatticeAlgebraVector h(in.Grid());
 | 
			
		||||
      typename GaugeGroup<ncolour, group_name>::LatticeAlgebraVector h(in.Grid());
 | 
			
		||||
      projectOnAlgebra(h, in_mu, double(Nc + 2 * S));  // factor T(r)/T(fund)
 | 
			
		||||
      FundamentalLieAlgebraMatrix(h, out_mu);          // apply scale only once
 | 
			
		||||
      pokeLorentz(out, out_mu, mu);
 | 
			
		||||
@@ -80,20 +80,23 @@ public:
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  void projectOnAlgebra(typename SU<ncolour>::LatticeAlgebraVector &h_out,
 | 
			
		||||
  void projectOnAlgebra(typename GaugeGroup<ncolour, group_name>::LatticeAlgebraVector &h_out,
 | 
			
		||||
                        const LatticeMatrix &in, Real scale = 1.0) const {
 | 
			
		||||
    SU_TwoIndex<ncolour, S>::projectOnAlgebra(h_out, in, scale);
 | 
			
		||||
    GaugeGroupTwoIndex<ncolour, S,group_name>::projectOnAlgebra(h_out, in, scale);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void FundamentalLieAlgebraMatrix(
 | 
			
		||||
				   typename SU<ncolour>::LatticeAlgebraVector &h,
 | 
			
		||||
				   typename SU<ncolour>::LatticeMatrix &out, Real scale = 1.0) const {
 | 
			
		||||
    SU<ncolour>::FundamentalLieAlgebraMatrix(h, out, scale);
 | 
			
		||||
				   typename GaugeGroup<ncolour, group_name>::LatticeAlgebraVector &h,
 | 
			
		||||
				   typename GaugeGroup<ncolour, group_name>::LatticeMatrix &out, Real scale = 1.0) const {
 | 
			
		||||
    GaugeGroup<ncolour,group_name>::FundamentalLieAlgebraMatrix(h, out, scale);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef TwoIndexRep<Nc, Symmetric> TwoIndexSymmetricRepresentation;
 | 
			
		||||
typedef TwoIndexRep<Nc, AntiSymmetric> TwoIndexAntiSymmetricRepresentation;
 | 
			
		||||
typedef TwoIndexRep<Nc, Symmetric, GroupName::SU> TwoIndexSymmetricRepresentation;
 | 
			
		||||
typedef TwoIndexRep<Nc, AntiSymmetric, GroupName::SU> TwoIndexAntiSymmetricRepresentation;
 | 
			
		||||
 | 
			
		||||
typedef TwoIndexRep<Nc, Symmetric, GroupName::Sp> SpTwoIndexSymmetricRepresentation;
 | 
			
		||||
typedef TwoIndexRep<Nc, AntiSymmetric, GroupName::Sp> SpTwoIndexAntiSymmetricRepresentation;
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,13 +37,14 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
// Make these members of an Impl class for BC's.
 | 
			
		||||
 | 
			
		||||
namespace PeriodicBC { 
 | 
			
		||||
 | 
			
		||||
  //Out(x) = Link(x)*field(x+mu)
 | 
			
		||||
  template<class covariant,class gauge> Lattice<covariant> CovShiftForward(const Lattice<gauge> &Link, 
 | 
			
		||||
									   int mu,
 | 
			
		||||
									   const Lattice<covariant> &field)
 | 
			
		||||
  {
 | 
			
		||||
    return Link*Cshift(field,mu,1);// moves towards negative mu
 | 
			
		||||
  }
 | 
			
		||||
  //Out(x) = Link^dag(x-mu)*field(x-mu)
 | 
			
		||||
  template<class covariant,class gauge> Lattice<covariant> CovShiftBackward(const Lattice<gauge> &Link, 
 | 
			
		||||
									    int mu,
 | 
			
		||||
									    const Lattice<covariant> &field)
 | 
			
		||||
@@ -52,19 +53,19 @@ namespace PeriodicBC {
 | 
			
		||||
    tmp = adj(Link)*field;
 | 
			
		||||
    return Cshift(tmp,mu,-1);// moves towards positive mu
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //Out(x) = Link^dag(x-mu)
 | 
			
		||||
  template<class gauge> Lattice<gauge>
 | 
			
		||||
  CovShiftIdentityBackward(const Lattice<gauge> &Link, int mu) 
 | 
			
		||||
  {
 | 
			
		||||
    return Cshift(adj(Link), mu, -1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //Out(x) = Link(x)
 | 
			
		||||
  template<class gauge> Lattice<gauge>
 | 
			
		||||
  CovShiftIdentityForward(const Lattice<gauge> &Link, int mu)
 | 
			
		||||
  {
 | 
			
		||||
    return Link;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //Link(x) = Link(x+mu)
 | 
			
		||||
  template<class gauge> Lattice<gauge>
 | 
			
		||||
  ShiftStaple(const Lattice<gauge> &Link, int mu)
 | 
			
		||||
  {
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,361 @@ struct LaplacianParams : Serializable {
 | 
			
		||||
      precision(precision){};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define LEG_LOAD(Dir)						 \
 | 
			
		||||
  SE = st.GetEntry(ptype, Dir, ss);				 \
 | 
			
		||||
  if (SE->_is_local ) {						 \
 | 
			
		||||
    int perm= SE->_permute;					 \
 | 
			
		||||
    chi = coalescedReadPermute(in[SE->_offset],ptype,perm,lane); \
 | 
			
		||||
  } else {							 \
 | 
			
		||||
    chi = coalescedRead(buf[SE->_offset],lane);			 \
 | 
			
		||||
  }								 \
 | 
			
		||||
  acceleratorSynchronise();
 | 
			
		||||
 | 
			
		||||
const std::vector<int> directions4D   ({Xdir,Ydir,Zdir,Tdir,Xdir,Ydir,Zdir,Tdir});
 | 
			
		||||
const std::vector<int> displacements4D({1,1,1,1,-1,-1,-1,-1});
 | 
			
		||||
 | 
			
		||||
template<class Gimpl,class Field> class CovariantAdjointLaplacianStencil : public SparseMatrixBase<Field>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  INHERIT_GIMPL_TYPES(Gimpl);
 | 
			
		||||
//  RealD kappa;
 | 
			
		||||
 | 
			
		||||
  typedef typename Field::vector_object siteObject;
 | 
			
		||||
 | 
			
		||||
  template <typename vtype> using iImplDoubledGaugeField = iVector<iScalar<iMatrix<vtype, Nc> >, Nds>;
 | 
			
		||||
  typedef iImplDoubledGaugeField<Simd> SiteDoubledGaugeField;
 | 
			
		||||
  typedef Lattice<SiteDoubledGaugeField> DoubledGaugeField;
 | 
			
		||||
  typedef CartesianStencil<siteObject, siteObject, DefaultImplParams> StencilImpl;
 | 
			
		||||
 | 
			
		||||
  GridBase *grid;
 | 
			
		||||
  StencilImpl Stencil;
 | 
			
		||||
  SimpleCompressor<siteObject> Compressor;
 | 
			
		||||
  DoubledGaugeField Uds;
 | 
			
		||||
 | 
			
		||||
  CovariantAdjointLaplacianStencil( GridBase *_grid)
 | 
			
		||||
    : grid(_grid),
 | 
			
		||||
      Stencil    (grid,8,Even,directions4D,displacements4D),
 | 
			
		||||
      Uds(grid){}
 | 
			
		||||
 | 
			
		||||
  CovariantAdjointLaplacianStencil(GaugeField &Umu)
 | 
			
		||||
    :
 | 
			
		||||
      grid(Umu.Grid()),
 | 
			
		||||
      Stencil    (grid,8,Even,directions4D,displacements4D),
 | 
			
		||||
      Uds(grid)
 | 
			
		||||
  { GaugeImport(Umu); }
 | 
			
		||||
 | 
			
		||||
  void GaugeImport (const GaugeField &Umu)
 | 
			
		||||
  {
 | 
			
		||||
    assert(grid == Umu.Grid());
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      auto U = PeekIndex<LorentzIndex>(Umu, mu);
 | 
			
		||||
      PokeIndex<LorentzIndex>(Uds, U, mu );
 | 
			
		||||
      U = adj(Cshift(U, mu, -1));
 | 
			
		||||
      PokeIndex<LorentzIndex>(Uds, U, mu + 4);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  virtual GridBase *Grid(void) { return grid; };
 | 
			
		||||
//broken
 | 
			
		||||
#if 0
 | 
			
		||||
  virtual void  MDeriv(const Field &_left, Field &_right,Field &_der, int mu)
 | 
			
		||||
  {
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    // Halo exchange for this geometry of stencil
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    Stencil.HaloExchange(_lef, Compressor);
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
    // Arithmetic expressions
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
    autoView( st     , Stencil    , AcceleratorRead);
 | 
			
		||||
    auto buf = st.CommBuf();
 | 
			
		||||
 | 
			
		||||
    autoView( in     , _left    , AcceleratorRead);
 | 
			
		||||
    autoView( right    , _right   , AcceleratorRead);
 | 
			
		||||
    autoView( der    , _der   , AcceleratorWrite);
 | 
			
		||||
    autoView( U     , Uds    , AcceleratorRead);
 | 
			
		||||
 | 
			
		||||
    typedef typename Field::vector_object        vobj;
 | 
			
		||||
    typedef decltype(coalescedRead(left[0]))    calcObj;
 | 
			
		||||
    typedef decltype(coalescedRead(U[0](0))) calcLink;
 | 
			
		||||
 | 
			
		||||
    const int      Nsimd = vobj::Nsimd();
 | 
			
		||||
    const uint64_t NN = grid->oSites();
 | 
			
		||||
 | 
			
		||||
    accelerator_for( ss, NN, Nsimd, {
 | 
			
		||||
 | 
			
		||||
	StencilEntry *SE;
 | 
			
		||||
	
 | 
			
		||||
	const int lane=acceleratorSIMTlane(Nsimd);
 | 
			
		||||
 | 
			
		||||
	calcObj chi;
 | 
			
		||||
	calcObj phi;
 | 
			
		||||
	calcObj res;
 | 
			
		||||
	calcObj Uchi;
 | 
			
		||||
	calcObj Utmp;
 | 
			
		||||
	calcObj Utmp2;
 | 
			
		||||
	calcLink UU;
 | 
			
		||||
	calcLink Udag;
 | 
			
		||||
	int ptype;
 | 
			
		||||
 | 
			
		||||
	res                 = coalescedRead(def[ss]);
 | 
			
		||||
	phi                 = coalescedRead(right[ss]);
 | 
			
		||||
 | 
			
		||||
#define LEG_LOAD_MULT_LINK(leg,polarisation)			\
 | 
			
		||||
	UU = coalescedRead(U[ss](polarisation));	\
 | 
			
		||||
	Udag = adj(UU);					\
 | 
			
		||||
	LEG_LOAD(leg);					\
 | 
			
		||||
	mult(&Utmp(), &UU, &chi());			\
 | 
			
		||||
	Utmp2 = adj(Utmp);				\
 | 
			
		||||
	mult(&Utmp(), &UU, &Utmp2());			\
 | 
			
		||||
	Utmp2 = adj(Utmp);				\
 | 
			
		||||
	mult(&Uchi(), &phi(), &Utmp2());			\
 | 
			
		||||
	res = res + Uchi;
 | 
			
		||||
	
 | 
			
		||||
	LEG_LOAD_MULT_LINK(0,Xp);
 | 
			
		||||
	LEG_LOAD_MULT_LINK(1,Yp);
 | 
			
		||||
	LEG_LOAD_MULT_LINK(2,Zp);
 | 
			
		||||
	LEG_LOAD_MULT_LINK(3,Tp);
 | 
			
		||||
 | 
			
		||||
	coalescedWrite(der[ss], res,lane);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  virtual void  Morig(const Field &_in, Field &_out)
 | 
			
		||||
  {
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    // Halo exchange for this geometry of stencil
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    Stencil.HaloExchange(_in, Compressor);
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
    // Arithmetic expressions
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
//    auto st = Stencil.View(AcceleratorRead);
 | 
			
		||||
    autoView( st     , Stencil    , AcceleratorRead);
 | 
			
		||||
    auto buf = st.CommBuf();
 | 
			
		||||
 | 
			
		||||
    autoView( in     , _in    , AcceleratorRead);
 | 
			
		||||
    autoView( out    , _out   , AcceleratorWrite);
 | 
			
		||||
    autoView( U     , Uds    , AcceleratorRead);
 | 
			
		||||
 | 
			
		||||
    typedef typename Field::vector_object        vobj;
 | 
			
		||||
    typedef decltype(coalescedRead(in[0]))    calcObj;
 | 
			
		||||
    typedef decltype(coalescedRead(U[0](0))) calcLink;
 | 
			
		||||
 | 
			
		||||
    const int      Nsimd = vobj::Nsimd();
 | 
			
		||||
    const uint64_t NN = grid->oSites();
 | 
			
		||||
 | 
			
		||||
    accelerator_for( ss, NN, Nsimd, {
 | 
			
		||||
 | 
			
		||||
	StencilEntry *SE;
 | 
			
		||||
	
 | 
			
		||||
	const int lane=acceleratorSIMTlane(Nsimd);
 | 
			
		||||
 | 
			
		||||
	calcObj chi;
 | 
			
		||||
	calcObj res;
 | 
			
		||||
	calcObj Uchi;
 | 
			
		||||
	calcObj Utmp;
 | 
			
		||||
	calcObj Utmp2;
 | 
			
		||||
	calcLink UU;
 | 
			
		||||
	calcLink Udag;
 | 
			
		||||
	int ptype;
 | 
			
		||||
 | 
			
		||||
	res                 = coalescedRead(in[ss])*(-8.0);
 | 
			
		||||
 | 
			
		||||
#define LEG_LOAD_MULT(leg,polarisation)			\
 | 
			
		||||
	UU = coalescedRead(U[ss](polarisation));	\
 | 
			
		||||
	Udag = adj(UU);					\
 | 
			
		||||
	LEG_LOAD(leg);					\
 | 
			
		||||
	mult(&Utmp(), &UU, &chi());			\
 | 
			
		||||
	Utmp2 = adj(Utmp);				\
 | 
			
		||||
	mult(&Utmp(), &UU, &Utmp2());			\
 | 
			
		||||
	Uchi = adj(Utmp);				\
 | 
			
		||||
	res = res + Uchi;
 | 
			
		||||
	
 | 
			
		||||
	LEG_LOAD_MULT(0,Xp);
 | 
			
		||||
	LEG_LOAD_MULT(1,Yp);
 | 
			
		||||
	LEG_LOAD_MULT(2,Zp);
 | 
			
		||||
	LEG_LOAD_MULT(3,Tp);
 | 
			
		||||
	LEG_LOAD_MULT(4,Xm);
 | 
			
		||||
	LEG_LOAD_MULT(5,Ym);
 | 
			
		||||
	LEG_LOAD_MULT(6,Zm);
 | 
			
		||||
	LEG_LOAD_MULT(7,Tm);
 | 
			
		||||
 | 
			
		||||
	coalescedWrite(out[ss], res,lane);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
  virtual void  Mnew (const Field &_in, Field &_out)
 | 
			
		||||
  {
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
    // Halo exchange for this geometry of stencil
 | 
			
		||||
    ///////////////////////////////////////////////
 | 
			
		||||
//    Stencil.HaloExchange(_in, Compressor);
 | 
			
		||||
      std::vector<std::vector<CommsRequest_t> > requests;
 | 
			
		||||
      Stencil.Prepare();
 | 
			
		||||
  {
 | 
			
		||||
    GRID_TRACE("Laplace Gather");
 | 
			
		||||
    Stencil.HaloGather(_in,Compressor);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  tracePush("Laplace Communication");
 | 
			
		||||
  Stencil.CommunicateBegin(requests);
 | 
			
		||||
  {
 | 
			
		||||
    GRID_TRACE("MergeSHM");
 | 
			
		||||
    Stencil.CommsMergeSHM(Compressor);
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
    // Arithmetic expressions
 | 
			
		||||
    ///////////////////////////////////
 | 
			
		||||
//    auto st = Stencil.View(AcceleratorRead);
 | 
			
		||||
    autoView( st     , Stencil    , AcceleratorRead);
 | 
			
		||||
    auto buf = st.CommBuf();
 | 
			
		||||
 | 
			
		||||
    autoView( in     , _in    , AcceleratorRead);
 | 
			
		||||
    autoView( out    , _out   , AcceleratorWrite);
 | 
			
		||||
    autoView( U     , Uds    , AcceleratorRead);
 | 
			
		||||
 | 
			
		||||
    typedef typename Field::vector_object        vobj;
 | 
			
		||||
    typedef decltype(coalescedRead(in[0]))    calcObj;
 | 
			
		||||
    typedef decltype(coalescedRead(U[0](0))) calcLink;
 | 
			
		||||
 | 
			
		||||
    const int      Nsimd = vobj::Nsimd();
 | 
			
		||||
    const uint64_t NN = grid->oSites();
 | 
			
		||||
 | 
			
		||||
    accelerator_for( ss, NN, Nsimd, {
 | 
			
		||||
 | 
			
		||||
	StencilEntry *SE;
 | 
			
		||||
	
 | 
			
		||||
	const int lane=acceleratorSIMTlane(Nsimd);
 | 
			
		||||
 | 
			
		||||
	calcObj chi;
 | 
			
		||||
	calcObj res;
 | 
			
		||||
	calcObj Uchi;
 | 
			
		||||
	calcObj Utmp;
 | 
			
		||||
	calcObj Utmp2;
 | 
			
		||||
	calcLink UU;
 | 
			
		||||
	calcLink Udag;
 | 
			
		||||
	int ptype;
 | 
			
		||||
 | 
			
		||||
	res                 = coalescedRead(in[ss])*(-8.0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        SE = st.GetEntry(ptype, 0, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(0,Xp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 1, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(1,Yp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 2, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(2,Zp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 3, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(3,Tp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 4, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(4,Xm);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 5, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(5,Ym);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 6, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(6,Zm);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 7, ss);				 
 | 
			
		||||
        if (SE->_is_local ) {
 | 
			
		||||
	LEG_LOAD_MULT(7,Tm);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	coalescedWrite(out[ss], res,lane);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    Stencil.CommunicateComplete(requests);
 | 
			
		||||
  tracePop("Communication");
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    GRID_TRACE("Merge");
 | 
			
		||||
    Stencil.CommsMerge(Compressor);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    accelerator_for( ss, NN, Nsimd, {
 | 
			
		||||
 | 
			
		||||
	StencilEntry *SE;
 | 
			
		||||
	
 | 
			
		||||
	const int lane=acceleratorSIMTlane(Nsimd);
 | 
			
		||||
 | 
			
		||||
	calcObj chi;
 | 
			
		||||
	calcObj res;
 | 
			
		||||
	calcObj Uchi;
 | 
			
		||||
	calcObj Utmp;
 | 
			
		||||
	calcObj Utmp2;
 | 
			
		||||
	calcLink UU;
 | 
			
		||||
	calcLink Udag;
 | 
			
		||||
	int ptype;
 | 
			
		||||
 | 
			
		||||
//	res                 = coalescedRead(in[ss])*(-8.0);
 | 
			
		||||
	res                 = coalescedRead(out[ss]);
 | 
			
		||||
 | 
			
		||||
        SE = st.GetEntry(ptype, 0, ss);				 
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(0,Xp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 1, ss);				 
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(1,Yp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 2, ss);				 
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(2,Zp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 3, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(3,Tp);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 4, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(4,Xm);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 5, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(5,Ym);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 6, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(6,Zm);
 | 
			
		||||
	}
 | 
			
		||||
        SE = st.GetEntry(ptype, 7, ss);
 | 
			
		||||
        if ((SE->_is_local )==0){
 | 
			
		||||
	LEG_LOAD_MULT(7,Tm);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	coalescedWrite(out[ss], res,lane);
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  virtual void  M(const Field &in, Field &out) {Mnew(in,out);};
 | 
			
		||||
  virtual void  Mdag (const Field &in, Field &out) { M(in,out);}; // Laplacian is hermitian
 | 
			
		||||
  virtual  void Mdiag    (const Field &in, Field &out)                  {assert(0);}; // Unimplemented need only for multigrid
 | 
			
		||||
  virtual  void Mdir     (const Field &in, Field &out,int dir, int disp){assert(0);}; // Unimplemented need only for multigrid
 | 
			
		||||
  virtual  void MdirAll  (const Field &in, std::vector<Field> &out)     {assert(0);}; // Unimplemented need only for multigrid
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#undef LEG_LOAD_MULT
 | 
			
		||||
#undef LEG_LOAD_MULT_LINK
 | 
			
		||||
#undef LEG_LOAD
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////
 | 
			
		||||
// Laplacian operator L on adjoint fields
 | 
			
		||||
@@ -76,29 +430,40 @@ class LaplacianAdjointField: public Metric<typename Impl::Field> {
 | 
			
		||||
  LaplacianParams param;
 | 
			
		||||
  MultiShiftFunction PowerHalf;    
 | 
			
		||||
  MultiShiftFunction PowerInvHalf;    
 | 
			
		||||
//template<class Gimpl,class Field> class CovariantAdjointLaplacianStencil : public SparseMatrixBase<Field>
 | 
			
		||||
  CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField> LapStencil;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  INHERIT_GIMPL_TYPES(Impl);
 | 
			
		||||
 | 
			
		||||
  LaplacianAdjointField(GridBase* grid, OperatorFunction<GaugeField>& S, LaplacianParams& p, const RealD k = 1.0)
 | 
			
		||||
    : U(Nd, grid), Solver(S), param(p), kappa(k){
 | 
			
		||||
  LaplacianAdjointField(GridBase* grid, OperatorFunction<GaugeField>& S, LaplacianParams& p, const RealD k = 1.0, bool if_remez=true)
 | 
			
		||||
    : U(Nd, grid), Solver(S), param(p), kappa(k)
 | 
			
		||||
	,LapStencil(grid){
 | 
			
		||||
    AlgRemez remez(param.lo,param.hi,param.precision);
 | 
			
		||||
    std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
 | 
			
		||||
    if(if_remez){
 | 
			
		||||
    remez.generateApprox(param.degree,1,2);
 | 
			
		||||
    PowerHalf.Init(remez,param.tolerance,false);
 | 
			
		||||
    PowerInvHalf.Init(remez,param.tolerance,true);
 | 
			
		||||
    }
 | 
			
		||||
    this->triv=0;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  LaplacianAdjointField(){this->triv=0; printf("triv=%d\n",this->Trivial());}
 | 
			
		||||
  void Mdir(const GaugeField&, GaugeField&, int, int){ assert(0);}
 | 
			
		||||
  void MdirAll(const GaugeField&, std::vector<GaugeField> &){ assert(0);}
 | 
			
		||||
  void Mdiag(const GaugeField&, GaugeField&){ assert(0);}
 | 
			
		||||
 | 
			
		||||
  void ImportGauge(const GaugeField& _U) {
 | 
			
		||||
    RealD total=0.;
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      U[mu] = PeekIndex<LorentzIndex>(_U, mu);
 | 
			
		||||
      total += norm2(U[mu]);
 | 
			
		||||
    }
 | 
			
		||||
    LapStencil.GaugeImport (_U);
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogDebug <<"ImportGauge:norm2(U _U) = "<<total<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void M(const GaugeField& in, GaugeField& out) {
 | 
			
		||||
@@ -106,10 +471,12 @@ public:
 | 
			
		||||
    // test
 | 
			
		||||
    //GaugeField herm = in + adj(in);
 | 
			
		||||
    //std::cout << "AHermiticity: " << norm2(herm) << std::endl;
 | 
			
		||||
//    std::cout << GridLogDebug <<"M:Kappa = "<<kappa<<std::endl;
 | 
			
		||||
 | 
			
		||||
    GaugeLinkField sum(in.Grid());
 | 
			
		||||
#if 0
 | 
			
		||||
    GaugeLinkField tmp(in.Grid());
 | 
			
		||||
    GaugeLinkField tmp2(in.Grid());
 | 
			
		||||
    GaugeLinkField sum(in.Grid());
 | 
			
		||||
 | 
			
		||||
    for (int nu = 0; nu < Nd; nu++) {
 | 
			
		||||
      sum = Zero();
 | 
			
		||||
@@ -123,10 +490,22 @@ public:
 | 
			
		||||
      out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum;
 | 
			
		||||
      PokeIndex<LorentzIndex>(out, out_nu, nu);
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    for (int nu = 0; nu < Nd; nu++) {
 | 
			
		||||
      GaugeLinkField in_nu = PeekIndex<LorentzIndex>(in, nu);
 | 
			
		||||
      GaugeLinkField out_nu(out.Grid());
 | 
			
		||||
      LapStencil.M(in_nu,sum);
 | 
			
		||||
      out_nu = (1.0 - kappa) * in_nu - kappa / (double(4 * Nd)) * sum;
 | 
			
		||||
      PokeIndex<LorentzIndex>(out, out_nu, nu);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
//    std::cout << GridLogDebug <<"M:norm2(out) = "<<norm2(out)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  void MDeriv(const GaugeField& in, GaugeField& der) {
 | 
			
		||||
    // in is anti-hermitian
 | 
			
		||||
//    std::cout << GridLogDebug <<"MDeriv:Kappa = "<<kappa<<std::endl;
 | 
			
		||||
    RealD factor = -kappa / (double(4 * Nd));
 | 
			
		||||
    
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++){
 | 
			
		||||
@@ -140,6 +519,7 @@ public:
 | 
			
		||||
      // adjoint in the last multiplication
 | 
			
		||||
      PokeIndex<LorentzIndex>(der,  -2.0 * factor * der_mu, mu);
 | 
			
		||||
    } 
 | 
			
		||||
    std::cout << GridLogDebug <<"MDeriv: Kappa= "<< kappa << " norm2(der) = "<<norm2(der)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // separating this temporarily
 | 
			
		||||
@@ -159,11 +539,22 @@ public:
 | 
			
		||||
      }
 | 
			
		||||
      PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogDebug <<"MDeriv: Kappa= "<< kappa << " norm2(der) = "<<norm2(der)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void Minv(const GaugeField& in, GaugeField& inverted){
 | 
			
		||||
    HermitianLinearOperator<LaplacianAdjointField<Impl>,GaugeField> HermOp(*this);
 | 
			
		||||
    Solver(HermOp, in, inverted);
 | 
			
		||||
    std::cout << GridLogDebug <<"Minv:norm2(inverted) = "<<norm2(inverted)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  void MinvDeriv(const GaugeField& in, GaugeField& der) {
 | 
			
		||||
    GaugeField X(in.Grid());
 | 
			
		||||
    Minv(in,X);
 | 
			
		||||
    MDeriv(X,der);
 | 
			
		||||
    der *=-1.0;
 | 
			
		||||
    std::cout << GridLogDebug <<"MinvDeriv:norm2(der) = "<<norm2(der)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MSquareRoot(GaugeField& P){
 | 
			
		||||
@@ -172,6 +563,7 @@ public:
 | 
			
		||||
    ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerHalf);
 | 
			
		||||
    msCG(HermOp,P,Gp);
 | 
			
		||||
    P = Gp; 
 | 
			
		||||
    std::cout << GridLogDebug <<"MSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MInvSquareRoot(GaugeField& P){
 | 
			
		||||
@@ -180,6 +572,7 @@ public:
 | 
			
		||||
    ConjugateGradientMultiShift<GaugeField> msCG(param.MaxIter,PowerInvHalf);
 | 
			
		||||
    msCG(HermOp,P,Gp);
 | 
			
		||||
    P = Gp; 
 | 
			
		||||
    std::cout << GridLogDebug <<"MInvSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										403
									
								
								Grid/qcd/utils/CovariantLaplacianRat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										403
									
								
								Grid/qcd/utils/CovariantLaplacianRat.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,403 @@
 | 
			
		||||
/*************************************************************************************
 | 
			
		||||
 | 
			
		||||
Grid physics library, www.github.com/paboyle/Grid
 | 
			
		||||
 | 
			
		||||
Source file: ./lib/qcd/action/scalar/CovariantLaplacianRat.h
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2021
 | 
			
		||||
 | 
			
		||||
Author: Chulwoo Jung <chulwoo@bnl.gov>
 | 
			
		||||
 | 
			
		||||
This program is free software; you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License along
 | 
			
		||||
with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 | 
			
		||||
See the full license in the file "LICENSE" in the top level distribution
 | 
			
		||||
directory
 | 
			
		||||
*************************************************************************************/
 | 
			
		||||
			   /*  END LEGAL */
 | 
			
		||||
#pragma once 
 | 
			
		||||
#define MIXED_CG
 | 
			
		||||
//enable/disable push_back
 | 
			
		||||
#undef USE_CHRONO 
 | 
			
		||||
 | 
			
		||||
//#include <roctracer/roctx.h>
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
struct LaplacianRatParams {
 | 
			
		||||
 | 
			
		||||
  RealD offset;
 | 
			
		||||
  int order;
 | 
			
		||||
  std::vector<RealD> a0;
 | 
			
		||||
  std::vector<RealD> a1;
 | 
			
		||||
  std::vector<RealD> b0;
 | 
			
		||||
  std::vector<RealD> b1;
 | 
			
		||||
  RealD b2; //for debugging
 | 
			
		||||
  int   MaxIter;
 | 
			
		||||
  RealD tolerance;
 | 
			
		||||
  int   precision;
 | 
			
		||||
  
 | 
			
		||||
  // constructor 
 | 
			
		||||
  LaplacianRatParams(int ord = 1,
 | 
			
		||||
                  int maxit     = 1000,
 | 
			
		||||
                  RealD tol     = 1.0e-8, 
 | 
			
		||||
                  int precision = 64)
 | 
			
		||||
    : offset(1.), order(ord),b2(1.),
 | 
			
		||||
      MaxIter(maxit),
 | 
			
		||||
      tolerance(tol),
 | 
			
		||||
      precision(precision){ 
 | 
			
		||||
      a0.resize(ord,0.);
 | 
			
		||||
      a1.resize(ord,0.);
 | 
			
		||||
      b0.resize(ord,0.);
 | 
			
		||||
      b1.resize(ord,0.);
 | 
			
		||||
      };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////
 | 
			
		||||
// Laplacian operator L on adjoint fields
 | 
			
		||||
//
 | 
			
		||||
// phi: adjoint field
 | 
			
		||||
// L: D_mu^dag D_mu
 | 
			
		||||
//
 | 
			
		||||
// L phi(x) = Sum_mu [ U_mu(x)phi(x+mu)U_mu(x)^dag + 
 | 
			
		||||
//                     U_mu(x-mu)^dag phi(x-mu)U_mu(x-mu)
 | 
			
		||||
//                     -2phi(x)]
 | 
			
		||||
//
 | 
			
		||||
// Operator designed to be encapsulated by
 | 
			
		||||
// an HermitianLinearOperator<.. , ..>
 | 
			
		||||
////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
template <class Impl, class ImplF>
 | 
			
		||||
class LaplacianAdjointRat: public Metric<typename Impl::Field> {
 | 
			
		||||
  OperatorFunction<typename Impl::Field> &Solver;
 | 
			
		||||
  LaplacianRatParams Gparam;
 | 
			
		||||
  LaplacianRatParams Mparam;
 | 
			
		||||
  GridBase *grid;
 | 
			
		||||
  GridBase *grid_f;
 | 
			
		||||
  CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField> LapStencil;
 | 
			
		||||
  CovariantAdjointLaplacianStencil<ImplF,typename ImplF::LinkField> LapStencilF;
 | 
			
		||||
public:
 | 
			
		||||
  INHERIT_GIMPL_TYPES(Impl);
 | 
			
		||||
//   typedef typename GImpl::LinkField GaugeLinkField; \
 | 
			
		||||
//  typedef typename GImpl::Field GaugeField;         
 | 
			
		||||
  typedef typename ImplF::Field GaugeFieldF;
 | 
			
		||||
  typedef typename ImplF::LinkField GaugeLinkFieldF; \
 | 
			
		||||
  GaugeField Usav;
 | 
			
		||||
  GaugeFieldF UsavF;
 | 
			
		||||
  std::vector< std::vector<GaugeLinkField> > prev_solnsM;
 | 
			
		||||
  std::vector< std::vector<GaugeLinkField> > prev_solnsMinv;
 | 
			
		||||
  std::vector< std::vector<GaugeLinkField> > prev_solnsMDeriv;
 | 
			
		||||
  std::vector< std::vector<GaugeLinkField> > prev_solnsMinvDeriv;
 | 
			
		||||
 | 
			
		||||
	  LaplacianAdjointRat(GridBase* _grid, GridBase* _grid_f, OperatorFunction<GaugeField>& S, LaplacianRatParams& gpar, LaplacianRatParams& mpar)
 | 
			
		||||
    : grid(_grid),grid_f(_grid_f), LapStencil(_grid), LapStencilF(_grid_f), U(Nd, _grid), Solver(S), Gparam(gpar), Mparam(mpar),Usav(_grid), UsavF(_grid_f),
 | 
			
		||||
      prev_solnsM(4),prev_solnsMinv(4),prev_solnsMDeriv(4),prev_solnsMinvDeriv(4) {
 | 
			
		||||
//    std::cout<<GridLogMessage << "Generating degree "<<param.degree<<" for x^(1/2)"<<std::endl;
 | 
			
		||||
    this->triv=0;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
  LaplacianAdjointRat(){this->triv=0; printf("triv=%d\n",this->Trivial());}
 | 
			
		||||
  void Mdir(const GaugeField&, GaugeField&, int, int){ assert(0);}
 | 
			
		||||
  void MdirAll(const GaugeField&, std::vector<GaugeField> &){ assert(0);}
 | 
			
		||||
  void Mdiag(const GaugeField&, GaugeField&){ assert(0);}
 | 
			
		||||
 | 
			
		||||
  void ImportGauge(const GaugeField& _U) {
 | 
			
		||||
    RealD total=0.;
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      U[mu] = PeekIndex<LorentzIndex>(_U, mu);
 | 
			
		||||
      total += norm2(U[mu]);
 | 
			
		||||
    }
 | 
			
		||||
    Usav = _U;
 | 
			
		||||
    precisionChange(UsavF,Usav);
 | 
			
		||||
    std::cout <<GridLogDebug << "ImportGauge:norm2(_U) = "<<" "<<total<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MDerivLink(const GaugeLinkField& left, const GaugeLinkField& right,
 | 
			
		||||
              GaugeField& der) {
 | 
			
		||||
    std::cout<<GridLogMessage << "MDerivLink start "<< std::endl;
 | 
			
		||||
    RealD factor = -1. / (double(4 * Nd));
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      GaugeLinkField der_mu(der.Grid());
 | 
			
		||||
      der_mu = Zero();
 | 
			
		||||
//      for (int nu = 0; nu < Nd; nu++) {
 | 
			
		||||
//        GaugeLinkField left_nu = PeekIndex<LorentzIndex>(left, nu);
 | 
			
		||||
//        GaugeLinkField right_nu = PeekIndex<LorentzIndex>(right, nu);
 | 
			
		||||
        der_mu += U[mu] * Cshift(left, mu, 1) * adj(U[mu]) * right;
 | 
			
		||||
        der_mu += U[mu] * Cshift(right, mu, 1) * adj(U[mu]) * left;
 | 
			
		||||
//      }
 | 
			
		||||
      PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
 | 
			
		||||
    }
 | 
			
		||||
//    std::cout << GridLogDebug <<"MDerivLink:  norm2(der) = "<<norm2(der)<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "MDerivLink end "<< std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MDerivLink(const GaugeLinkField& left, const GaugeLinkField& right,
 | 
			
		||||
              std::vector<GaugeLinkField> & der) {
 | 
			
		||||
//    std::cout<<GridLogMessage << "MDerivLink "<< std::endl;
 | 
			
		||||
    RealD factor = -1. / (double(4 * Nd));
 | 
			
		||||
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      GaugeLinkField der_mu(left.Grid());
 | 
			
		||||
      der_mu = Zero();
 | 
			
		||||
        der_mu += U[mu] * Cshift(left, mu, 1) * adj(U[mu]) * right;
 | 
			
		||||
        der_mu += U[mu] * Cshift(right, mu, 1) * adj(U[mu]) * left;
 | 
			
		||||
//      PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
 | 
			
		||||
      der[mu] = -factor*der_mu;
 | 
			
		||||
//      std::cout << GridLogDebug <<"MDerivLink:  norm2(der) = "<<norm2(der[mu])<<std::endl;
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
//    std::cout<<GridLogMessage << "MDerivLink end "<< std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MDerivInt(LaplacianRatParams &par, const GaugeField& left, const GaugeField& right,
 | 
			
		||||
              GaugeField& der ,  std::vector< std::vector<GaugeLinkField> >& prev_solns ) {
 | 
			
		||||
 | 
			
		||||
// get rid of this please
 | 
			
		||||
    std::cout<<GridLogMessage << "LaplaceStart " <<std::endl;
 | 
			
		||||
    RealD fac =  - 1. / (double(4 * Nd)) ;
 | 
			
		||||
    RealD coef=0.5;
 | 
			
		||||
    LapStencil.GaugeImport(Usav);
 | 
			
		||||
    LapStencilF.GaugeImport(UsavF);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    for (int nu=0;nu<Nd;nu++){
 | 
			
		||||
        GaugeLinkField right_nu = PeekIndex<LorentzIndex>(right, nu);
 | 
			
		||||
        GaugeLinkField left_nu = PeekIndex<LorentzIndex>(left, nu);
 | 
			
		||||
        GaugeLinkField LMinvMom(left.Grid());
 | 
			
		||||
    
 | 
			
		||||
        GaugeLinkField GMom(left.Grid());
 | 
			
		||||
        GaugeLinkField LMinvGMom(left.Grid());
 | 
			
		||||
    
 | 
			
		||||
        GaugeLinkField AGMom(left.Grid());
 | 
			
		||||
        GaugeLinkField MinvAGMom(left.Grid());
 | 
			
		||||
        GaugeLinkField LMinvAGMom(left.Grid());
 | 
			
		||||
    
 | 
			
		||||
        GaugeLinkField AMinvMom(left.Grid());
 | 
			
		||||
        GaugeLinkField LMinvAMom(left.Grid());
 | 
			
		||||
        GaugeLinkField temp(left.Grid());
 | 
			
		||||
        GaugeLinkField temp2(left.Grid());
 | 
			
		||||
    
 | 
			
		||||
        std::vector<GaugeLinkField> MinvMom(par.order,left.Grid());
 | 
			
		||||
    
 | 
			
		||||
        GaugeLinkField MinvGMom(left.Grid());
 | 
			
		||||
        GaugeLinkField Gtemp(left.Grid());
 | 
			
		||||
        GaugeLinkField Gtemp2(left.Grid());
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
        ConjugateGradient<GaugeLinkField> CG(par.tolerance,10000,false);
 | 
			
		||||
    //    ConjugateGradient<GaugeFieldF> CG_f(par.tolerance,10000,false);
 | 
			
		||||
        LaplacianParams LapPar(0.0001, 1.0, 10000, 1e-8, 12, 64);
 | 
			
		||||
    
 | 
			
		||||
        ChronoForecast< QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,GaugeLinkField>,GaugeLinkField> , GaugeLinkField> Forecast;
 | 
			
		||||
    
 | 
			
		||||
        GMom = par.offset * right_nu;
 | 
			
		||||
    
 | 
			
		||||
        for(int i =0;i<par.order;i++){
 | 
			
		||||
        QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField>,GaugeLinkField> QuadOp(LapStencil,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
#if USE_CHRONO
 | 
			
		||||
        MinvMom[i] = Forecast(QuadOp, right_nu, prev_solns[nu]);
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MIXED_CG
 | 
			
		||||
        CG(QuadOp,right_nu,MinvMom[i]);
 | 
			
		||||
#else
 | 
			
		||||
        QuadLinearOperator<CovariantAdjointLaplacianStencil<ImplF,typename ImplF::LinkField>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
    //    QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],par.b1[i],par.b2);
 | 
			
		||||
        MixedPrecisionConjugateGradient<GaugeLinkField,GaugeLinkFieldF> MixedCG(par.tolerance,10000,10000,grid_f,QuadOpF,QuadOp);
 | 
			
		||||
        MixedCG.InnerTolerance=par.tolerance;
 | 
			
		||||
        MixedCG(right_nu,MinvMom[i]);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if USE_CHRONO
 | 
			
		||||
        prev_solns[nu].push_back(MinvMom[i]);
 | 
			
		||||
    #endif
 | 
			
		||||
        
 | 
			
		||||
        GMom += par.a0[i]*MinvMom[i]; 
 | 
			
		||||
        LapStencil.M(MinvMom[i],Gtemp2);
 | 
			
		||||
        GMom += par.a1[i]*fac*Gtemp2; 
 | 
			
		||||
        }
 | 
			
		||||
        for(int i =0;i<par.order;i++){
 | 
			
		||||
        QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField>,GaugeLinkField> QuadOp(LapStencil,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
    
 | 
			
		||||
        MinvGMom = Forecast(QuadOp, GMom, prev_solns[nu]);
 | 
			
		||||
    #ifndef MIXED_CG
 | 
			
		||||
        CG(QuadOp,GMom,MinvGMom);
 | 
			
		||||
        LapStencil.M(MinvGMom, Gtemp2); LMinvGMom=fac*Gtemp2;
 | 
			
		||||
        CG(QuadOp,right_nu,MinvMom[i]);
 | 
			
		||||
    #else
 | 
			
		||||
        QuadLinearOperator<CovariantAdjointLaplacianStencil<ImplF,typename ImplF::LinkField>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
    //    QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],par.b1[i],par.b2);
 | 
			
		||||
        MixedPrecisionConjugateGradient<GaugeLinkField,GaugeLinkFieldF> MixedCG(par.tolerance,10000,10000,grid_f,QuadOpF,QuadOp);
 | 
			
		||||
        MixedCG.InnerTolerance=par.tolerance;
 | 
			
		||||
        MixedCG(GMom,MinvGMom);
 | 
			
		||||
        LapStencil.M(MinvGMom, Gtemp2); LMinvGMom=fac*Gtemp2;
 | 
			
		||||
    //    Laplacian.M(MinvGMom, LMinvGMom);
 | 
			
		||||
        MixedCG(right_nu,MinvMom[i]);
 | 
			
		||||
    #endif
 | 
			
		||||
#if USE_CHRONO
 | 
			
		||||
        prev_solns[nu].push_back(MinvGMom);
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
        LapStencil.M(MinvMom[i], Gtemp2); LMinvMom=fac*Gtemp2;
 | 
			
		||||
        AMinvMom = par.a1[i]*LMinvMom;
 | 
			
		||||
        AMinvMom += par.a0[i]*MinvMom[i];
 | 
			
		||||
    
 | 
			
		||||
        LapStencil.M(AMinvMom, Gtemp2); LMinvAMom=fac*Gtemp2;
 | 
			
		||||
        LapStencil.M(MinvGMom, Gtemp2); temp=fac*Gtemp2;
 | 
			
		||||
        MinvAGMom = par.a1[i]*temp;
 | 
			
		||||
        MinvAGMom += par.a0[i]*MinvGMom;
 | 
			
		||||
        LapStencil.M(MinvAGMom, Gtemp2); LMinvAGMom=fac*Gtemp2;
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
        GaugeField tempDer(left.Grid());
 | 
			
		||||
        std::vector<GaugeLinkField> DerLink(Nd,left.Grid());
 | 
			
		||||
        std::vector<GaugeLinkField> tempDerLink(Nd,left.Grid());
 | 
			
		||||
 | 
			
		||||
        std::cout<<GridLogMessage << "force contraction "<< i <<std::endl;
 | 
			
		||||
    //    roctxRangePushA("RMHMC force contraction");
 | 
			
		||||
 #if 0
 | 
			
		||||
        MDerivLink(GMom,MinvMom[i],tempDer); der += coef*2*par.a1[i]*tempDer;
 | 
			
		||||
        MDerivLink(left_nu,MinvGMom,tempDer); der += coef*2*par.a1[i]*tempDer;
 | 
			
		||||
        MDerivLink(LMinvAGMom,MinvMom[i],tempDer); der += coef*-2.*par.b2*tempDer;
 | 
			
		||||
        MDerivLink(LMinvAMom,MinvGMom,tempDer); der += coef*-2.*par.b2*tempDer;
 | 
			
		||||
        MDerivLink(MinvAGMom,LMinvMom,tempDer); der += coef*-2.*par.b2*tempDer;
 | 
			
		||||
        MDerivLink(AMinvMom,LMinvGMom,tempDer); der += coef*-2.*par.b2*tempDer;
 | 
			
		||||
        MDerivLink(MinvAGMom,MinvMom[i],tempDer); der += coef*-2.*par.b1[i]*tempDer;
 | 
			
		||||
        MDerivLink(AMinvMom,MinvGMom,tempDer); der += coef*-2.*par.b1[i]*tempDer;
 | 
			
		||||
#else
 | 
			
		||||
	for (int mu=0;mu<Nd;mu++) DerLink[mu]=Zero();
 | 
			
		||||
        MDerivLink(GMom,MinvMom[i],tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*2*par.a1[i]*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(left_nu,MinvGMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*2*par.a1[i]*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(LMinvAGMom,MinvMom[i],tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b2*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(LMinvAMom,MinvGMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b2*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(MinvAGMom,LMinvMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b2*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(AMinvMom,LMinvGMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b2*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(MinvAGMom,MinvMom[i],tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b1[i]*tempDerLink[mu];
 | 
			
		||||
        MDerivLink(AMinvMom,MinvGMom,tempDerLink); 	for (int mu=0;mu<Nd;mu++) DerLink[mu] += coef*-2.*par.b1[i]*tempDerLink[mu];
 | 
			
		||||
//      PokeIndex<LorentzIndex>(der, -factor * der_mu, mu);
 | 
			
		||||
        for (int mu=0;mu<Nd;mu++) PokeIndex<LorentzIndex>(tempDer, tempDerLink[mu], mu);
 | 
			
		||||
 | 
			
		||||
	der += tempDer;
 | 
			
		||||
#endif
 | 
			
		||||
        std::cout<<GridLogMessage << "coef =  force contraction "<< i << "done "<< coef <<std::endl;
 | 
			
		||||
    //    roctxRangePop();
 | 
			
		||||
    
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<GridLogMessage << "LaplaceEnd " <<std::endl;
 | 
			
		||||
//  exit(-42);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MDeriv(const GaugeField& in, GaugeField& der) {
 | 
			
		||||
    MDeriv(in,in, der);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MDeriv(const GaugeField& left, const GaugeField& right,
 | 
			
		||||
              GaugeField& der) {
 | 
			
		||||
 | 
			
		||||
    der=Zero();
 | 
			
		||||
    MDerivInt(Mparam, left, right, der,prev_solnsMDeriv );
 | 
			
		||||
    std::cout <<GridLogDebug << "MDeriv:norm2(der) = "<<norm2(der)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MinvDeriv(const GaugeField& in, GaugeField& der) {
 | 
			
		||||
    std::vector< std::vector<GaugeLinkField> > prev_solns(4);
 | 
			
		||||
    der=Zero();
 | 
			
		||||
    MDerivInt(Gparam, in, in, der,prev_solnsMinvDeriv);
 | 
			
		||||
    std::cout <<GridLogDebug << "MinvDeriv:norm2(der) = "<<norm2(der)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  void MSquareRootInt(LaplacianRatParams &par, GaugeField& P, std::vector< std::vector<GaugeLinkField> > & prev_solns ){
 | 
			
		||||
 | 
			
		||||
    std::cout<<GridLogMessage << "LaplaceStart " <<std::endl;
 | 
			
		||||
    RealD fac = -1. / (double(4 * Nd));
 | 
			
		||||
    LapStencil.GaugeImport(Usav);
 | 
			
		||||
    LapStencilF.GaugeImport(UsavF);
 | 
			
		||||
    for(int nu=0; nu<Nd;nu++){
 | 
			
		||||
        GaugeLinkField P_nu = PeekIndex<LorentzIndex>(P, nu);
 | 
			
		||||
        GaugeLinkField Gp(P.Grid());
 | 
			
		||||
        Gp = par.offset * P_nu;
 | 
			
		||||
        ConjugateGradient<GaugeLinkField> CG(par.tolerance,10000);
 | 
			
		||||
    //    ConjugateGradient<GaugeLinkFieldF> CG_f(1.0e-8,10000);
 | 
			
		||||
    
 | 
			
		||||
        ChronoForecast< QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField>,GaugeLinkField> , GaugeLinkField> Forecast;
 | 
			
		||||
    
 | 
			
		||||
        GaugeLinkField Gtemp(P.Grid());
 | 
			
		||||
        GaugeLinkField Gtemp2(P.Grid());
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
        for(int i =0;i<par.order;i++){
 | 
			
		||||
        QuadLinearOperator<CovariantAdjointLaplacianStencil<Impl,typename Impl::LinkField>,GaugeLinkField> QuadOp(LapStencil,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
    
 | 
			
		||||
        Gtemp = Forecast(QuadOp, P_nu, prev_solns[nu]);
 | 
			
		||||
    #ifndef MIXED_CG
 | 
			
		||||
        CG(QuadOp,P_nu,Gtemp);
 | 
			
		||||
    #else
 | 
			
		||||
        QuadLinearOperator<CovariantAdjointLaplacianStencil<ImplF,typename ImplF::LinkField>,GaugeLinkFieldF> QuadOpF(LapStencilF,par.b0[i],fac*par.b1[i],fac*fac*par.b2);
 | 
			
		||||
    //    QuadLinearOperator<LaplacianAdjointField<ImplF>,GaugeFieldF> QuadOpF(LapStencilF,par.b0[i],par.b1[i],par.b2);
 | 
			
		||||
        MixedPrecisionConjugateGradient<GaugeLinkField,GaugeLinkFieldF> MixedCG(par.tolerance,10000,10000,grid_f,QuadOpF,QuadOp);
 | 
			
		||||
        MixedCG.InnerTolerance=par.tolerance;
 | 
			
		||||
        MixedCG(P_nu,Gtemp);
 | 
			
		||||
    #endif
 | 
			
		||||
    #if USE_CHRONO
 | 
			
		||||
        prev_solns[nu].push_back(Gtemp);
 | 
			
		||||
    #endif
 | 
			
		||||
    
 | 
			
		||||
        Gp += par.a0[i]*Gtemp; 
 | 
			
		||||
        LapStencil.M(Gtemp,Gtemp2);
 | 
			
		||||
        Gp += par.a1[i]*fac*Gtemp2; 
 | 
			
		||||
        }
 | 
			
		||||
        PokeIndex<LorentzIndex>(P, Gp, nu);
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<GridLogMessage << "LaplaceEnd " <<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MSquareRoot(GaugeField& P){
 | 
			
		||||
    std::vector< std::vector<GaugeLinkField> > prev_solns(4);
 | 
			
		||||
    MSquareRootInt(Mparam,P,prev_solns);
 | 
			
		||||
    std::cout <<GridLogDebug << "MSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MInvSquareRoot(GaugeField& P){
 | 
			
		||||
    std::vector< std::vector<GaugeLinkField> > prev_solns(4);
 | 
			
		||||
    MSquareRootInt(Gparam,P,prev_solns);
 | 
			
		||||
    std::cout <<GridLogDebug << "MInvSquareRoot:norm2(P) = "<<norm2(P)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void M(const GaugeField& in, GaugeField& out) {
 | 
			
		||||
      out = in;
 | 
			
		||||
      std::vector< std::vector<GaugeLinkField> > prev_solns(4);
 | 
			
		||||
      MSquareRootInt(Mparam,out,prev_solns);
 | 
			
		||||
      MSquareRootInt(Mparam,out,prev_solns);
 | 
			
		||||
      std::cout <<GridLogDebug << "M:norm2(out) = "<<norm2(out)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void Minv(const GaugeField& in, GaugeField& inverted){
 | 
			
		||||
      inverted = in;
 | 
			
		||||
      std::vector< std::vector<GaugeLinkField> > prev_solns(4);
 | 
			
		||||
      MSquareRootInt(Gparam,inverted,prev_solns);
 | 
			
		||||
      MSquareRootInt(Gparam,inverted,prev_solns);
 | 
			
		||||
      std::cout <<GridLogDebug << "Minv:norm2(inverted) = "<<norm2(inverted)<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  std::vector<GaugeLinkField> U;
 | 
			
		||||
};
 | 
			
		||||
#undef MIXED_CG
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
							
								
								
									
										470
									
								
								Grid/qcd/utils/GaugeGroup.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										470
									
								
								Grid/qcd/utils/GaugeGroup.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,470 @@
 | 
			
		||||
/*************************************************************************************
 | 
			
		||||
 | 
			
		||||
Grid physics library, www.github.com/paboyle/Grid
 | 
			
		||||
 | 
			
		||||
Source file: ./lib/qcd/utils/GaugeGroup.h
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2015
 | 
			
		||||
 | 
			
		||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
 | 
			
		||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
Author: neo <cossu@post.kek.jp>
 | 
			
		||||
Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
 | 
			
		||||
This program is free software; you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License along
 | 
			
		||||
with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 | 
			
		||||
See the full license in the file "LICENSE" in the top level distribution
 | 
			
		||||
directory
 | 
			
		||||
*************************************************************************************/
 | 
			
		||||
/*  END LEGAL */
 | 
			
		||||
#ifndef QCD_UTIL_GAUGEGROUP_H
 | 
			
		||||
#define QCD_UTIL_GAUGEGROUP_H
 | 
			
		||||
 | 
			
		||||
// Important detail: nvcc requires all template parameters to have names.
 | 
			
		||||
// This is the only reason why the second template parameter has a name.
 | 
			
		||||
#define ONLY_IF_SU                                                       \
 | 
			
		||||
  typename dummy_name = group_name,                                      \
 | 
			
		||||
           typename named_dummy = std::enable_if_t <                                 \
 | 
			
		||||
                          std::is_same<dummy_name, group_name>::value && \
 | 
			
		||||
                      is_su<dummy_name>::value >
 | 
			
		||||
 | 
			
		||||
#define ONLY_IF_Sp                                                       \
 | 
			
		||||
  typename dummy_name = group_name,                                      \
 | 
			
		||||
           typename named_dummy = std::enable_if_t <                                 \
 | 
			
		||||
                          std::is_same<dummy_name, group_name>::value && \
 | 
			
		||||
                      is_sp<dummy_name>::value >
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
namespace GroupName {
 | 
			
		||||
class SU {};
 | 
			
		||||
class Sp {};
 | 
			
		||||
}  // namespace GroupName
 | 
			
		||||
 | 
			
		||||
template <typename group_name>
 | 
			
		||||
struct is_su {
 | 
			
		||||
  static const bool value = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct is_su<GroupName::SU> {
 | 
			
		||||
  static const bool value = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename group_name>
 | 
			
		||||
struct is_sp {
 | 
			
		||||
  static const bool value = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct is_sp<GroupName::Sp> {
 | 
			
		||||
  static const bool value = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename group_name>
 | 
			
		||||
constexpr int compute_adjoint_dimension(int ncolour);
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
constexpr int compute_adjoint_dimension<GroupName::SU>(int ncolour) {
 | 
			
		||||
  return ncolour * ncolour - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
constexpr int compute_adjoint_dimension<GroupName::Sp>(int ncolour) {
 | 
			
		||||
  return ncolour / 2 * (ncolour + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <int ncolour, class group_name>
 | 
			
		||||
class GaugeGroup {
 | 
			
		||||
 public:
 | 
			
		||||
  static const int Dimension = ncolour;
 | 
			
		||||
  static const int AdjointDimension =
 | 
			
		||||
      compute_adjoint_dimension<group_name>(ncolour);
 | 
			
		||||
  static const int AlgebraDimension =
 | 
			
		||||
      compute_adjoint_dimension<group_name>(ncolour);
 | 
			
		||||
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iSU2Matrix = iScalar<iScalar<iMatrix<vtype, 2> > >;
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iGroupMatrix = iScalar<iScalar<iMatrix<vtype, ncolour> > >;
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iAlgebraVector = iScalar<iScalar<iVector<vtype, AdjointDimension> > >;
 | 
			
		||||
  static int su2subgroups(void) { return su2subgroups(group_name()); }
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Types can be accessed as SU<2>::Matrix , SU<2>::vSUnMatrix,
 | 
			
		||||
  // SU<2>::LatticeMatrix etc...
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  typedef iGroupMatrix<Complex> Matrix;
 | 
			
		||||
  typedef iGroupMatrix<ComplexF> MatrixF;
 | 
			
		||||
  typedef iGroupMatrix<ComplexD> MatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef iGroupMatrix<vComplex> vMatrix;
 | 
			
		||||
  typedef iGroupMatrix<vComplexF> vMatrixF;
 | 
			
		||||
  typedef iGroupMatrix<vComplexD> vMatrixD;
 | 
			
		||||
 | 
			
		||||
  // For the projectors to the algebra
 | 
			
		||||
  // these should be real...
 | 
			
		||||
  // keeping complex for consistency with the SIMD vector types
 | 
			
		||||
  typedef iAlgebraVector<Complex> AlgebraVector;
 | 
			
		||||
  typedef iAlgebraVector<ComplexF> AlgebraVectorF;
 | 
			
		||||
  typedef iAlgebraVector<ComplexD> AlgebraVectorD;
 | 
			
		||||
 | 
			
		||||
  typedef iAlgebraVector<vComplex> vAlgebraVector;
 | 
			
		||||
  typedef iAlgebraVector<vComplexF> vAlgebraVectorF;
 | 
			
		||||
  typedef iAlgebraVector<vComplexD> vAlgebraVectorD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<vMatrix> LatticeMatrix;
 | 
			
		||||
  typedef Lattice<vMatrixF> LatticeMatrixF;
 | 
			
		||||
  typedef Lattice<vMatrixD> LatticeMatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<vAlgebraVector> LatticeAlgebraVector;
 | 
			
		||||
  typedef Lattice<vAlgebraVectorF> LatticeAlgebraVectorF;
 | 
			
		||||
  typedef Lattice<vAlgebraVectorD> LatticeAlgebraVectorD;
 | 
			
		||||
 | 
			
		||||
  typedef iSU2Matrix<Complex> SU2Matrix;
 | 
			
		||||
  typedef iSU2Matrix<ComplexF> SU2MatrixF;
 | 
			
		||||
  typedef iSU2Matrix<ComplexD> SU2MatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef iSU2Matrix<vComplex> vSU2Matrix;
 | 
			
		||||
  typedef iSU2Matrix<vComplexF> vSU2MatrixF;
 | 
			
		||||
  typedef iSU2Matrix<vComplexD> vSU2MatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<vSU2Matrix> LatticeSU2Matrix;
 | 
			
		||||
  typedef Lattice<vSU2MatrixF> LatticeSU2MatrixF;
 | 
			
		||||
  typedef Lattice<vSU2MatrixD> LatticeSU2MatrixD;
 | 
			
		||||
 | 
			
		||||
  // Private implementation details are specified in the following files:
 | 
			
		||||
  // Grid/qcd/utils/SUn.impl
 | 
			
		||||
  // Grid/qcd/utils/SUn.impl
 | 
			
		||||
  // The public part of the interface follows below and refers to these
 | 
			
		||||
  // private member functions.
 | 
			
		||||
 | 
			
		||||
#include <Grid/qcd/utils/SUn.impl.h>
 | 
			
		||||
#include <Grid/qcd/utils/Sp2n.impl.h>
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void generator(int lieIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
    return generator(lieIndex, ta, group_name());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void su2SubGroupIndex(int &i1, int &i2, int su2_index) {
 | 
			
		||||
    return su2SubGroupIndex(i1, i2, su2_index, group_name());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void testGenerators(void) { testGenerators(group_name()); }
 | 
			
		||||
 | 
			
		||||
  static void printGenerators(void) {
 | 
			
		||||
    for (int gen = 0; gen < AlgebraDimension; gen++) {
 | 
			
		||||
      Matrix ta;
 | 
			
		||||
      generator(gen, ta);
 | 
			
		||||
      std::cout << GridLogMessage << "Nc = " << ncolour << " t_" << gen
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << ta << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename LatticeMatrixType>
 | 
			
		||||
  static void LieRandomize(GridParallelRNG &pRNG, LatticeMatrixType &out,
 | 
			
		||||
                           double scale = 1.0) {
 | 
			
		||||
    GridBase *grid = out.Grid();
 | 
			
		||||
 | 
			
		||||
    typedef typename LatticeMatrixType::vector_type vector_type;
 | 
			
		||||
 | 
			
		||||
    typedef iSinglet<vector_type> vTComplexType;
 | 
			
		||||
 | 
			
		||||
    typedef Lattice<vTComplexType> LatticeComplexType;
 | 
			
		||||
    typedef typename GridTypeMapper<
 | 
			
		||||
        typename LatticeMatrixType::vector_object>::scalar_object MatrixType;
 | 
			
		||||
 | 
			
		||||
    LatticeComplexType ca(grid);
 | 
			
		||||
    LatticeMatrixType lie(grid);
 | 
			
		||||
    LatticeMatrixType la(grid);
 | 
			
		||||
    ComplexD ci(0.0, scale);
 | 
			
		||||
    MatrixType ta;
 | 
			
		||||
 | 
			
		||||
    lie = Zero();
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < AlgebraDimension; a++) {
 | 
			
		||||
      random(pRNG, ca);
 | 
			
		||||
 | 
			
		||||
      ca = (ca + conjugate(ca)) * 0.5;
 | 
			
		||||
      ca = ca - 0.5;
 | 
			
		||||
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
 | 
			
		||||
      la = ci * ca * ta;
 | 
			
		||||
 | 
			
		||||
      lie = lie + la;  // e^{i la ta}
 | 
			
		||||
    }
 | 
			
		||||
    taExp(lie, out);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void GaussianFundamentalLieAlgebraMatrix(GridParallelRNG &pRNG,
 | 
			
		||||
                                                  LatticeMatrix &out,
 | 
			
		||||
                                                  Real scale = 1.0) {
 | 
			
		||||
    GridBase *grid = out.Grid();
 | 
			
		||||
    LatticeReal ca(grid);
 | 
			
		||||
    LatticeMatrix la(grid);
 | 
			
		||||
    Complex ci(0.0, scale);
 | 
			
		||||
    Matrix ta;
 | 
			
		||||
 | 
			
		||||
    out = Zero();
 | 
			
		||||
    for (int a = 0; a < AlgebraDimension; a++) {
 | 
			
		||||
      gaussian(pRNG, ca);
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
      la = toComplex(ca) * ta;
 | 
			
		||||
      out += la;
 | 
			
		||||
    }
 | 
			
		||||
    out *= ci;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void FundamentalLieAlgebraMatrix(const LatticeAlgebraVector &h,
 | 
			
		||||
                                          LatticeMatrix &out,
 | 
			
		||||
                                          Real scale = 1.0) {
 | 
			
		||||
    conformable(h, out);
 | 
			
		||||
    GridBase *grid = out.Grid();
 | 
			
		||||
    LatticeMatrix la(grid);
 | 
			
		||||
    Matrix ta;
 | 
			
		||||
 | 
			
		||||
    out = Zero();
 | 
			
		||||
    for (int a = 0; a < AlgebraDimension; a++) {
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
      la = peekColour(h, a) * timesI(ta) * scale;
 | 
			
		||||
      out += la;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Projects the algebra components a lattice matrix (of dimension ncol*ncol -1
 | 
			
		||||
  // ) inverse operation: FundamentalLieAlgebraMatrix
 | 
			
		||||
  static void projectOnAlgebra(LatticeAlgebraVector &h_out,
 | 
			
		||||
                               const LatticeMatrix &in, Real scale = 1.0) {
 | 
			
		||||
    conformable(h_out, in);
 | 
			
		||||
    h_out = Zero();
 | 
			
		||||
    Matrix Ta;
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < AlgebraDimension; a++) {
 | 
			
		||||
      generator(a, Ta);
 | 
			
		||||
      pokeColour(h_out, -2.0 * (trace(timesI(Ta) * in)) * scale, a);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||
  template <class vtype>
 | 
			
		||||
  accelerator_inline static iScalar<vtype> ProjectOnGeneralGroup(const iScalar<vtype> &r) {
 | 
			
		||||
    return ProjectOnGeneralGroup(r, group_name());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class vtype, int N>
 | 
			
		||||
  accelerator_inline static iVector<vtype,N> ProjectOnGeneralGroup(const iVector<vtype,N> &r) {
 | 
			
		||||
    return ProjectOnGeneralGroup(r, group_name());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class vtype,int N, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0 >::type * =nullptr>
 | 
			
		||||
  accelerator_inline static iMatrix<vtype,N> ProjectOnGeneralGroup(const iMatrix<vtype,N> &arg) {
 | 
			
		||||
    return ProjectOnGeneralGroup(arg, group_name());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <int N,class vComplex_t>                  // Projects on the general groups U(N), Sp(2N)xZ2 i.e. determinant is allowed a complex phase.
 | 
			
		||||
  static void ProjectOnGeneralGroup(Lattice<iVector<iScalar<iMatrix<vComplex_t, N> >, Nd> > &U) {
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      auto Umu = PeekIndex<LorentzIndex>(U, mu);
 | 
			
		||||
      Umu = ProjectOnGeneralGroup(Umu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  template <int N,class vComplex_t>
 | 
			
		||||
  static Lattice<iScalar<iScalar<iMatrix<vComplex_t, N> > > > ProjectOnGeneralGroup(const Lattice<iScalar<iScalar<iMatrix<vComplex_t, N> > > > &Umu) {
 | 
			
		||||
    return ProjectOnGeneralGroup(Umu, group_name());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <int N,class vComplex_t>       // Projects on SU(N), Sp(2N), with unit determinant, by first projecting on general group and then enforcing unit determinant
 | 
			
		||||
  static void ProjectOnSpecialGroup(Lattice<iScalar<iScalar<iMatrix<vComplex_t, N> > > > &Umu) {
 | 
			
		||||
       Umu = ProjectOnGeneralGroup(Umu);
 | 
			
		||||
       auto det = Determinant(Umu);
 | 
			
		||||
 | 
			
		||||
       det = conjugate(det);
 | 
			
		||||
 | 
			
		||||
       for (int i = 0; i < N; i++) {
 | 
			
		||||
           auto element = PeekIndex<ColourIndex>(Umu, N - 1, i);
 | 
			
		||||
           element = element * det;
 | 
			
		||||
           PokeIndex<ColourIndex>(Umu, element, Nc - 1, i);
 | 
			
		||||
       }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  template <int N,class vComplex_t>    // reunitarise, resimplectify... previously ProjectSUn
 | 
			
		||||
    static void ProjectOnSpecialGroup(Lattice<iVector<iScalar<iMatrix<vComplex_t, N> >, Nd> > &U) {
 | 
			
		||||
      // Reunitarise
 | 
			
		||||
      for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
        auto Umu = PeekIndex<LorentzIndex>(U, mu);
 | 
			
		||||
        ProjectOnSpecialGroup(Umu);
 | 
			
		||||
        PokeIndex<LorentzIndex>(U, Umu, mu);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
  template <typename GaugeField>
 | 
			
		||||
  static void HotConfiguration(GridParallelRNG &pRNG, GaugeField &out) {
 | 
			
		||||
    typedef typename GaugeField::vector_type vector_type;
 | 
			
		||||
    typedef iGroupMatrix<vector_type> vMatrixType;
 | 
			
		||||
    typedef Lattice<vMatrixType> LatticeMatrixType;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrixType Umu(out.Grid());
 | 
			
		||||
    LatticeMatrixType tmp(out.Grid());
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      //      LieRandomize(pRNG, Umu, 1.0);
 | 
			
		||||
      //      PokeIndex<LorentzIndex>(out, Umu, mu);
 | 
			
		||||
      gaussian(pRNG,Umu);
 | 
			
		||||
      tmp = Ta(Umu);
 | 
			
		||||
      taExp(tmp,Umu);
 | 
			
		||||
      ProjectOnSpecialGroup(Umu);
 | 
			
		||||
      //      ProjectSUn(Umu);
 | 
			
		||||
      PokeIndex<LorentzIndex>(out, Umu, mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  template <typename GaugeField>
 | 
			
		||||
  static void TepidConfiguration(GridParallelRNG &pRNG, GaugeField &out) {
 | 
			
		||||
    typedef typename GaugeField::vector_type vector_type;
 | 
			
		||||
    typedef iGroupMatrix<vector_type> vMatrixType;
 | 
			
		||||
    typedef Lattice<vMatrixType> LatticeMatrixType;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrixType Umu(out.Grid());
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      LieRandomize(pRNG, Umu, 0.01);
 | 
			
		||||
      PokeIndex<LorentzIndex>(out, Umu, mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  template <typename GaugeField>
 | 
			
		||||
  static void ColdConfiguration(GaugeField &out) {
 | 
			
		||||
    typedef typename GaugeField::vector_type vector_type;
 | 
			
		||||
    typedef iGroupMatrix<vector_type> vMatrixType;
 | 
			
		||||
    typedef Lattice<vMatrixType> LatticeMatrixType;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrixType Umu(out.Grid());
 | 
			
		||||
    Umu = 1.0;
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      PokeIndex<LorentzIndex>(out, Umu, mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  template <typename GaugeField>
 | 
			
		||||
  static void ColdConfiguration(GridParallelRNG &pRNG, GaugeField &out) {
 | 
			
		||||
    ColdConfiguration(out);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename LatticeMatrixType>
 | 
			
		||||
  static void taProj(const LatticeMatrixType &in, LatticeMatrixType &out) {
 | 
			
		||||
    taProj(in, out, group_name());
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  template <typename LatticeMatrixType>
 | 
			
		||||
  static void taExp(const LatticeMatrixType &x, LatticeMatrixType &ex) {
 | 
			
		||||
    typedef typename LatticeMatrixType::scalar_type ComplexType;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrixType xn(x.Grid());
 | 
			
		||||
    RealD nfac = 1.0;
 | 
			
		||||
 | 
			
		||||
    xn = x;
 | 
			
		||||
    ex = xn + ComplexType(1.0);  // 1+x
 | 
			
		||||
 | 
			
		||||
    // Do a 12th order exponentiation
 | 
			
		||||
    for (int i = 2; i <= 12; ++i) {
 | 
			
		||||
      nfac = nfac / RealD(i);  // 1/2, 1/2.3 ...
 | 
			
		||||
      xn = xn * x;             // x2, x3,x4....
 | 
			
		||||
      ex = ex + xn * nfac;     // x2/2!, x3/3!....
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
    
 | 
			
		||||
template <int ncolour>
 | 
			
		||||
using SU = GaugeGroup<ncolour, GroupName::SU>;
 | 
			
		||||
 | 
			
		||||
template <int ncolour>
 | 
			
		||||
using Sp = GaugeGroup<ncolour, GroupName::Sp>;
 | 
			
		||||
 | 
			
		||||
typedef SU<2> SU2;
 | 
			
		||||
typedef SU<3> SU3;
 | 
			
		||||
typedef SU<4> SU4;
 | 
			
		||||
typedef SU<5> SU5;
 | 
			
		||||
 | 
			
		||||
typedef SU<Nc> FundamentalMatrices;
 | 
			
		||||
    
 | 
			
		||||
typedef Sp<2> Sp2;
 | 
			
		||||
typedef Sp<4> Sp4;
 | 
			
		||||
typedef Sp<6> Sp6;
 | 
			
		||||
typedef Sp<8> Sp8;
 | 
			
		||||
 | 
			
		||||
template <int N,class vComplex_t>
 | 
			
		||||
static void ProjectSUn(Lattice<iScalar<iScalar<iMatrix<vComplex_t, N> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
    GaugeGroup<N,GroupName::SU>::ProjectOnSpecialGroup(Umu);
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
template <int N,class vComplex_t>
 | 
			
		||||
static void ProjectSUn(Lattice<iVector<iScalar<iMatrix<vComplex_t, N> >,Nd> > &U)
 | 
			
		||||
{
 | 
			
		||||
    GaugeGroup<N,GroupName::SU>::ProjectOnSpecialGroup(U);
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
template <int N,class vComplex_t>
 | 
			
		||||
static void ProjectSpn(Lattice<iScalar<iScalar<iMatrix<vComplex_t, N> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
    GaugeGroup<N,GroupName::Sp>::ProjectOnSpecialGroup(Umu);
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
template <int N,class vComplex_t>
 | 
			
		||||
static void ProjectSpn(Lattice<iVector<iScalar<iMatrix<vComplex_t, N> >,Nd> > &U)
 | 
			
		||||
{
 | 
			
		||||
    GaugeGroup<N,GroupName::Sp>::ProjectOnSpecialGroup(U);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Explicit specialisation for SU(3).
 | 
			
		||||
static void ProjectSU3(Lattice<iScalar<iScalar<iMatrix<vComplexD, 3> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid = Umu.Grid();
 | 
			
		||||
  const int x = 0;
 | 
			
		||||
  const int y = 1;
 | 
			
		||||
  const int z = 2;
 | 
			
		||||
  // Reunitarise
 | 
			
		||||
  Umu = ProjectOnGroup(Umu);
 | 
			
		||||
  autoView(Umu_v, Umu, CpuWrite);
 | 
			
		||||
  thread_for(ss, grid->oSites(), {
 | 
			
		||||
    auto cm = Umu_v[ss];
 | 
			
		||||
    cm()()(2, x) = adj(cm()()(0, y) * cm()()(1, z) -
 | 
			
		||||
                       cm()()(0, z) * cm()()(1, y));  // x= yz-zy
 | 
			
		||||
    cm()()(2, y) = adj(cm()()(0, z) * cm()()(1, x) -
 | 
			
		||||
                       cm()()(0, x) * cm()()(1, z));  // y= zx-xz
 | 
			
		||||
    cm()()(2, z) = adj(cm()()(0, x) * cm()()(1, y) -
 | 
			
		||||
                       cm()()(0, y) * cm()()(1, x));  // z= xy-yx
 | 
			
		||||
    Umu_v[ss] = cm;
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
static void ProjectSU3(Lattice<iVector<iScalar<iMatrix<vComplexD, 3> >, Nd> > &U)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid = U.Grid();
 | 
			
		||||
  // Reunitarise
 | 
			
		||||
  for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
    auto Umu = PeekIndex<LorentzIndex>(U, mu);
 | 
			
		||||
    Umu = ProjectOnGroup(Umu);
 | 
			
		||||
    ProjectSU3(Umu);
 | 
			
		||||
    PokeIndex<LorentzIndex>(U, Umu, mu);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										371
									
								
								Grid/qcd/utils/GaugeGroupTwoIndex.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								Grid/qcd/utils/GaugeGroupTwoIndex.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,371 @@
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// * Two index representation generators
 | 
			
		||||
//
 | 
			
		||||
// * Normalisation for the fundamental generators:
 | 
			
		||||
//   trace ta tb = 1/2 delta_ab = T_F delta_ab
 | 
			
		||||
//   T_F = 1/2  for SU(N) groups
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//   base for NxN two index (anti-symmetric) matrices
 | 
			
		||||
//   normalized to 1 (d_ij is the kroenecker delta)
 | 
			
		||||
//
 | 
			
		||||
//   (e^(ij)_{kl} = 1 / sqrt(2) (d_ik d_jl +/- d_jk d_il)
 | 
			
		||||
//
 | 
			
		||||
//   Then the generators are written as
 | 
			
		||||
//
 | 
			
		||||
//   (iT_a)^(ij)(lk) = i * ( tr[e^(ij)^dag e^(lk) T^trasp_a] +
 | 
			
		||||
//   tr[e^(lk)e^(ij)^dag T_a] )  //
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
// Authors: David Preti, Guido Cossu
 | 
			
		||||
 | 
			
		||||
#ifndef QCD_UTIL_GAUGEGROUPTWOINDEX_H
 | 
			
		||||
#define QCD_UTIL_GAUGEGROUPTWOINDEX_H
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
enum TwoIndexSymmetry { Symmetric = 1, AntiSymmetric = -1 };
 | 
			
		||||
 | 
			
		||||
constexpr inline Real delta(int a, int b) { return (a == b) ? 1.0 : 0.0; }
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <class cplx, int nc, TwoIndexSymmetry S>
 | 
			
		||||
struct baseOffDiagonalSpHelper;
 | 
			
		||||
 | 
			
		||||
template <class cplx, int nc>
 | 
			
		||||
struct baseOffDiagonalSpHelper<cplx, nc, AntiSymmetric> {
 | 
			
		||||
  static const int ngroup = nc / 2;
 | 
			
		||||
  static void baseOffDiagonalSp(int i, int j, iScalar<iScalar<iMatrix<cplx, nc> > > &eij) {
 | 
			
		||||
    eij = Zero();
 | 
			
		||||
    RealD tmp;
 | 
			
		||||
 | 
			
		||||
    if ((i == ngroup + j) && (1 <= j) && (j < ngroup)) {
 | 
			
		||||
      for (int k = 0; k < j+1; k++) {
 | 
			
		||||
        if (k < j) {
 | 
			
		||||
          tmp = 1 / sqrt(j * (j + 1));
 | 
			
		||||
          eij()()(k, k + ngroup) = tmp;
 | 
			
		||||
          eij()()(k + ngroup, k) = -tmp;
 | 
			
		||||
        }
 | 
			
		||||
        if (k == j) {
 | 
			
		||||
          tmp = -j / sqrt(j * (j + 1));
 | 
			
		||||
          eij()()(k, k + ngroup) = tmp;
 | 
			
		||||
          eij()()(k + ngroup, k) = -tmp;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (i != ngroup + j) {
 | 
			
		||||
      for (int k = 0; k < nc; k++)
 | 
			
		||||
        for (int l = 0; l < nc; l++) {
 | 
			
		||||
          eij()()(l, k) =
 | 
			
		||||
              delta(i, k) * delta(j, l) - delta(j, k) * delta(i, l);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    RealD nrm = 1. / std::sqrt(2.0);
 | 
			
		||||
    eij = eij * nrm;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class cplx, int nc>
 | 
			
		||||
struct baseOffDiagonalSpHelper<cplx, nc, Symmetric> {
 | 
			
		||||
  static void baseOffDiagonalSp(int i, int j, iScalar<iScalar<iMatrix<cplx, nc> > > &eij) {
 | 
			
		||||
    eij = Zero();
 | 
			
		||||
    for (int k = 0; k < nc; k++)
 | 
			
		||||
      for (int l = 0; l < nc; l++)
 | 
			
		||||
        eij()()(l, k) =
 | 
			
		||||
            delta(i, k) * delta(j, l) + delta(j, k) * delta(i, l);
 | 
			
		||||
 | 
			
		||||
    RealD nrm = 1. / std::sqrt(2.0);
 | 
			
		||||
    eij = eij * nrm;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}   // closing detail namespace
 | 
			
		||||
 | 
			
		||||
template <int ncolour, TwoIndexSymmetry S, class group_name>
 | 
			
		||||
class GaugeGroupTwoIndex : public GaugeGroup<ncolour, group_name> {
 | 
			
		||||
 public:
 | 
			
		||||
  // The chosen convention is that we are taking ncolour to be N in SU<N> but 2N
 | 
			
		||||
  // in Sp(2N). ngroup is equal to N for SU but 2N/2 = N for Sp(2N).
 | 
			
		||||
  static_assert(std::is_same<group_name, GroupName::SU>::value or
 | 
			
		||||
                    std::is_same<group_name, GroupName::Sp>::value,
 | 
			
		||||
                "ngroup is only implemented for SU and Sp currently.");
 | 
			
		||||
  static const int ngroup =
 | 
			
		||||
      std::is_same<group_name, GroupName::SU>::value ? ncolour : ncolour / 2;
 | 
			
		||||
  static const int Dimension =
 | 
			
		||||
      (ncolour * (ncolour + S) / 2) + (std::is_same<group_name, GroupName::Sp>::value ? (S - 1) / 2 : 0);
 | 
			
		||||
  static const int DimensionAS =
 | 
			
		||||
      (ncolour * (ncolour - 1) / 2) + (std::is_same<group_name, GroupName::Sp>::value ? (- 1) : 0);
 | 
			
		||||
  static const int DimensionS =
 | 
			
		||||
      ncolour * (ncolour + 1) / 2;
 | 
			
		||||
  static const int NumGenerators =
 | 
			
		||||
      GaugeGroup<ncolour, group_name>::AlgebraDimension;
 | 
			
		||||
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iGroupTwoIndexMatrix = iScalar<iScalar<iMatrix<vtype, Dimension> > >;
 | 
			
		||||
 | 
			
		||||
  typedef iGroupTwoIndexMatrix<Complex> TIMatrix;
 | 
			
		||||
  typedef iGroupTwoIndexMatrix<ComplexF> TIMatrixF;
 | 
			
		||||
  typedef iGroupTwoIndexMatrix<ComplexD> TIMatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef iGroupTwoIndexMatrix<vComplex> vTIMatrix;
 | 
			
		||||
  typedef iGroupTwoIndexMatrix<vComplexF> vTIMatrixF;
 | 
			
		||||
  typedef iGroupTwoIndexMatrix<vComplexD> vTIMatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<vTIMatrix> LatticeTwoIndexMatrix;
 | 
			
		||||
  typedef Lattice<vTIMatrixF> LatticeTwoIndexMatrixF;
 | 
			
		||||
  typedef Lattice<vTIMatrixD> LatticeTwoIndexMatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<iVector<iScalar<iMatrix<vComplex, Dimension> >, Nd> >
 | 
			
		||||
      LatticeTwoIndexField;
 | 
			
		||||
  typedef Lattice<iVector<iScalar<iMatrix<vComplexF, Dimension> >, Nd> >
 | 
			
		||||
      LatticeTwoIndexFieldF;
 | 
			
		||||
  typedef Lattice<iVector<iScalar<iMatrix<vComplexD, Dimension> >, Nd> >
 | 
			
		||||
      LatticeTwoIndexFieldD;
 | 
			
		||||
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iGroupMatrix = iScalar<iScalar<iMatrix<vtype, ncolour> > >;
 | 
			
		||||
 | 
			
		||||
  typedef iGroupMatrix<Complex> Matrix;
 | 
			
		||||
  typedef iGroupMatrix<ComplexF> MatrixF;
 | 
			
		||||
  typedef iGroupMatrix<ComplexD> MatrixD;
 | 
			
		||||
    
 | 
			
		||||
private:
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void baseDiagonal(int Index, iGroupMatrix<cplx> &eij) {
 | 
			
		||||
    eij = Zero();
 | 
			
		||||
    eij()()(Index - ncolour * (ncolour - 1) / 2,
 | 
			
		||||
            Index - ncolour * (ncolour - 1) / 2) = 1.0;
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void baseOffDiagonal(int i, int j, iGroupMatrix<cplx> &eij, GroupName::SU) {
 | 
			
		||||
    eij = Zero();
 | 
			
		||||
    for (int k = 0; k < ncolour; k++)
 | 
			
		||||
      for (int l = 0; l < ncolour; l++)
 | 
			
		||||
        eij()()(l, k) =
 | 
			
		||||
            delta(i, k) * delta(j, l) + S * delta(j, k) * delta(i, l);
 | 
			
		||||
 | 
			
		||||
    RealD nrm = 1. / std::sqrt(2.0);
 | 
			
		||||
    eij = eij * nrm;
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void baseOffDiagonal(int i, int j, iGroupMatrix<cplx> &eij, GroupName::Sp) {
 | 
			
		||||
    detail::baseOffDiagonalSpHelper<cplx, ncolour, S>::baseOffDiagonalSp(i, j, eij);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void base(int Index, iGroupMatrix<cplx> &eij) {
 | 
			
		||||
  // returns (e)^(ij)_{kl} necessary for change of base U_F -> U_R
 | 
			
		||||
    assert(Index < Dimension);
 | 
			
		||||
    eij = Zero();
 | 
			
		||||
  // for the linearisation of the 2 indexes
 | 
			
		||||
    static int a[ncolour * (ncolour - 1) / 2][2];  // store the a <-> i,j
 | 
			
		||||
    static bool filled = false;
 | 
			
		||||
    if (!filled) {
 | 
			
		||||
      int counter = 0;
 | 
			
		||||
      for (int i = 1; i < ncolour; i++) {
 | 
			
		||||
      for (int j = 0; j < i; j++) {
 | 
			
		||||
        if (std::is_same<group_name, GroupName::Sp>::value)
 | 
			
		||||
          {
 | 
			
		||||
            if (j==0 && i==ngroup+j && S==-1) {
 | 
			
		||||
            //std::cout << "skipping" << std::endl; // for Sp2n this vanishes identically.
 | 
			
		||||
              j = j+1;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          a[counter][0] = i;
 | 
			
		||||
          a[counter][1] = j;
 | 
			
		||||
          counter++;
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
      filled = true;
 | 
			
		||||
    }
 | 
			
		||||
    if (Index < ncolour*ncolour - DimensionS)
 | 
			
		||||
    {
 | 
			
		||||
      baseOffDiagonal(a[Index][0], a[Index][1], eij, group_name());
 | 
			
		||||
    } else {
 | 
			
		||||
      baseDiagonal(Index, eij);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  static void printBase(void) {
 | 
			
		||||
    for (int gen = 0; gen < Dimension; gen++) {
 | 
			
		||||
      Matrix tmp;
 | 
			
		||||
      base(gen, tmp);
 | 
			
		||||
      std::cout << GridLogMessage << "Nc = " << ncolour << " t_" << gen
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << tmp << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void generator(int Index, iGroupTwoIndexMatrix<cplx> &i2indTa) {
 | 
			
		||||
    Vector<iGroupMatrix<cplx> > ta(NumGenerators);
 | 
			
		||||
    Vector<iGroupMatrix<cplx> > eij(Dimension);
 | 
			
		||||
    iGroupMatrix<cplx> tmp;
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < NumGenerators; a++)
 | 
			
		||||
      GaugeGroup<ncolour, group_name>::generator(a, ta[a]);
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < Dimension; a++) base(a, eij[a]);
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < Dimension; a++) {
 | 
			
		||||
      tmp = transpose(eij[a]*ta[Index]) + transpose(eij[a]) * ta[Index];
 | 
			
		||||
      for (int b = 0; b < Dimension; b++) {
 | 
			
		||||
        Complex iTr = TensorRemove(timesI(trace(tmp * eij[b])));
 | 
			
		||||
        i2indTa()()(a, b) = iTr;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void printGenerators(void) {
 | 
			
		||||
    for (int gen = 0; gen < NumGenerators; gen++) {
 | 
			
		||||
      TIMatrix i2indTa;
 | 
			
		||||
      generator(gen, i2indTa);
 | 
			
		||||
      std::cout << GridLogMessage << "Nc = " << ncolour << " t_" << gen
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << i2indTa << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void testGenerators(void) {
 | 
			
		||||
    TIMatrix i2indTa, i2indTb;
 | 
			
		||||
    std::cout << GridLogMessage << "2IndexRep - Checking if traceless"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < NumGenerators; a++) {
 | 
			
		||||
      generator(a, i2indTa);
 | 
			
		||||
      std::cout << GridLogMessage << a << std::endl;
 | 
			
		||||
      assert(norm2(trace(i2indTa)) < 1.0e-6);
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "2IndexRep - Checking if antihermitean"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < NumGenerators; a++) {
 | 
			
		||||
      generator(a, i2indTa);
 | 
			
		||||
      std::cout << GridLogMessage << a << std::endl;
 | 
			
		||||
      assert(norm2(adj(i2indTa) + i2indTa) < 1.0e-6);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
    std::cout << GridLogMessage
 | 
			
		||||
              << "2IndexRep - Checking Tr[Ta*Tb]=delta(a,b)*(N +- 2)/2"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < NumGenerators; a++) {
 | 
			
		||||
      for (int b = 0; b < NumGenerators; b++) {
 | 
			
		||||
        generator(a, i2indTa);
 | 
			
		||||
        generator(b, i2indTb);
 | 
			
		||||
 | 
			
		||||
        // generator returns iTa, so we need a minus sign here
 | 
			
		||||
        Complex Tr = -TensorRemove(trace(i2indTa * i2indTb));
 | 
			
		||||
        std::cout << GridLogMessage << "a=" << a << "b=" << b << "Tr=" << Tr
 | 
			
		||||
                  << std::endl;
 | 
			
		||||
        if (a == b) {
 | 
			
		||||
          assert(real(Tr) - ((ncolour + S * 2) * 0.5) < 1e-8);
 | 
			
		||||
        } else {
 | 
			
		||||
          assert(real(Tr) < 1e-8);
 | 
			
		||||
        }
 | 
			
		||||
        assert(imag(Tr) < 1e-8);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void TwoIndexLieAlgebraMatrix(
 | 
			
		||||
      const typename GaugeGroup<ncolour, group_name>::LatticeAlgebraVector &h,
 | 
			
		||||
      LatticeTwoIndexMatrix &out, Real scale = 1.0) {
 | 
			
		||||
    conformable(h, out);
 | 
			
		||||
    GridBase *grid = out.Grid();
 | 
			
		||||
    LatticeTwoIndexMatrix la(grid);
 | 
			
		||||
    TIMatrix i2indTa;
 | 
			
		||||
 | 
			
		||||
    out = Zero();
 | 
			
		||||
    for (int a = 0; a < NumGenerators; a++) {
 | 
			
		||||
      generator(a, i2indTa);
 | 
			
		||||
      la = peekColour(h, a) * i2indTa;
 | 
			
		||||
      out += la;
 | 
			
		||||
    }
 | 
			
		||||
    out *= scale;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Projects the algebra components
 | 
			
		||||
  // of a lattice matrix ( of dimension ncol*ncol -1 )
 | 
			
		||||
  static void projectOnAlgebra(
 | 
			
		||||
      typename GaugeGroup<ncolour, group_name>::LatticeAlgebraVector &h_out,
 | 
			
		||||
      const LatticeTwoIndexMatrix &in, Real scale = 1.0) {
 | 
			
		||||
    conformable(h_out, in);
 | 
			
		||||
    h_out = Zero();
 | 
			
		||||
    TIMatrix i2indTa;
 | 
			
		||||
    Real coefficient = -2.0 / (ncolour + 2 * S) * scale;
 | 
			
		||||
    // 2/(Nc +/- 2) for the normalization of the trace in the two index rep
 | 
			
		||||
    for (int a = 0; a < NumGenerators; a++) {
 | 
			
		||||
      generator(a, i2indTa);
 | 
			
		||||
      pokeColour(h_out, real(trace(i2indTa * in)) * coefficient, a);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // a projector that keeps the generators stored to avoid the overhead of
 | 
			
		||||
  // recomputing them
 | 
			
		||||
  static void projector(
 | 
			
		||||
      typename GaugeGroup<ncolour, group_name>::LatticeAlgebraVector &h_out,
 | 
			
		||||
      const LatticeTwoIndexMatrix &in, Real scale = 1.0) {
 | 
			
		||||
    conformable(h_out, in);
 | 
			
		||||
    // to store the generators
 | 
			
		||||
    static std::vector<TIMatrix> i2indTa(NumGenerators);
 | 
			
		||||
    h_out = Zero();
 | 
			
		||||
    static bool precalculated = false;
 | 
			
		||||
    if (!precalculated) {
 | 
			
		||||
      precalculated = true;
 | 
			
		||||
      for (int a = 0; a < NumGenerators; a++) generator(a, i2indTa[a]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Real coefficient =
 | 
			
		||||
        -2.0 / (ncolour + 2 * S) * scale;  // 2/(Nc +/- 2) for the normalization
 | 
			
		||||
    // of the trace in the two index rep
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < NumGenerators; a++) {
 | 
			
		||||
      auto tmp = real(trace(i2indTa[a] * in)) * coefficient;
 | 
			
		||||
      pokeColour(h_out, tmp, a);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <int ncolour, TwoIndexSymmetry S>
 | 
			
		||||
using SU_TwoIndex = GaugeGroupTwoIndex<ncolour, S, GroupName::SU>;
 | 
			
		||||
 | 
			
		||||
// Some useful type names
 | 
			
		||||
typedef SU_TwoIndex<Nc, Symmetric> TwoIndexSymmMatrices;
 | 
			
		||||
typedef SU_TwoIndex<Nc, AntiSymmetric> TwoIndexAntiSymmMatrices;
 | 
			
		||||
 | 
			
		||||
typedef SU_TwoIndex<2, Symmetric> SU2TwoIndexSymm;
 | 
			
		||||
typedef SU_TwoIndex<3, Symmetric> SU3TwoIndexSymm;
 | 
			
		||||
typedef SU_TwoIndex<4, Symmetric> SU4TwoIndexSymm;
 | 
			
		||||
typedef SU_TwoIndex<5, Symmetric> SU5TwoIndexSymm;
 | 
			
		||||
 | 
			
		||||
typedef SU_TwoIndex<2, AntiSymmetric> SU2TwoIndexAntiSymm;
 | 
			
		||||
typedef SU_TwoIndex<3, AntiSymmetric> SU3TwoIndexAntiSymm;
 | 
			
		||||
typedef SU_TwoIndex<4, AntiSymmetric> SU4TwoIndexAntiSymm;
 | 
			
		||||
typedef SU_TwoIndex<5, AntiSymmetric> SU5TwoIndexAntiSymm;
 | 
			
		||||
 | 
			
		||||
template <int ncolour, TwoIndexSymmetry S>
 | 
			
		||||
using Sp_TwoIndex = GaugeGroupTwoIndex<ncolour, S, GroupName::Sp>;
 | 
			
		||||
 | 
			
		||||
typedef Sp_TwoIndex<Nc, Symmetric> SpTwoIndexSymmMatrices;
 | 
			
		||||
typedef Sp_TwoIndex<Nc, AntiSymmetric> SpTwoIndexAntiSymmMatrices;
 | 
			
		||||
 | 
			
		||||
typedef Sp_TwoIndex<2, Symmetric> Sp2TwoIndexSymm;
 | 
			
		||||
typedef Sp_TwoIndex<4, Symmetric> Sp4TwoIndexSymm;
 | 
			
		||||
 | 
			
		||||
typedef Sp_TwoIndex<4, AntiSymmetric> Sp4TwoIndexAntiSymm;
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -7,6 +7,7 @@ Source file: ./lib/qcd/hmc/integrators/Integrator.h
 | 
			
		||||
Copyright (C) 2015
 | 
			
		||||
 | 
			
		||||
Author: Guido Cossu <guido.cossu@ed.ac.uk>
 | 
			
		||||
Author: Chulwoo Jung <chulwoo@bnl.gov>
 | 
			
		||||
 | 
			
		||||
This program is free software; you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -33,7 +34,12 @@ NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
template <typename Field> 
 | 
			
		||||
class Metric{
 | 
			
		||||
protected:
 | 
			
		||||
  int triv;
 | 
			
		||||
public:
 | 
			
		||||
  Metric(){this->triv=1;}
 | 
			
		||||
  int Trivial(){ return triv;}
 | 
			
		||||
//printf("Metric::Trivial=%d\n",triv); ;
 | 
			
		||||
  virtual void ImportGauge(const Field&)   = 0;
 | 
			
		||||
  virtual void M(const Field&, Field&)     = 0;
 | 
			
		||||
  virtual void Minv(const Field&, Field&)  = 0;
 | 
			
		||||
@@ -41,6 +47,8 @@ public:
 | 
			
		||||
  virtual void MInvSquareRoot(Field&) = 0;
 | 
			
		||||
  virtual void MDeriv(const Field&, Field&) = 0;
 | 
			
		||||
  virtual void MDeriv(const Field&, const Field&, Field&) = 0;
 | 
			
		||||
  virtual void MinvDeriv(const Field&, Field&) = 0;
 | 
			
		||||
//  virtual void MinvDeriv(const Field&, const Field&, Field&) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -48,23 +56,36 @@ public:
 | 
			
		||||
template <typename Field>
 | 
			
		||||
class TrivialMetric : public Metric<Field>{
 | 
			
		||||
public:
 | 
			
		||||
//  TrivialMetric(){this->triv=1;printf("TrivialMetric::triv=%d\n",this->Trivial());}
 | 
			
		||||
  virtual void ImportGauge(const Field&){};
 | 
			
		||||
  virtual void M(const Field& in, Field& out){
 | 
			
		||||
//    printf("M:norm=%0.15e\n",norm2(in));
 | 
			
		||||
    std::cout << GridLogIntegrator << " M:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
 | 
			
		||||
    out = in;
 | 
			
		||||
  }
 | 
			
		||||
  virtual void Minv(const Field& in, Field& out){
 | 
			
		||||
    std::cout << GridLogIntegrator << " Minv:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
 | 
			
		||||
    out = in;
 | 
			
		||||
  }
 | 
			
		||||
  virtual void MSquareRoot(Field& P){
 | 
			
		||||
    std::cout << GridLogIntegrator << " MSquareRoot:norm(P)= " << std::sqrt(norm2(P)) << std::endl;
 | 
			
		||||
    // do nothing
 | 
			
		||||
  }
 | 
			
		||||
  virtual void MInvSquareRoot(Field& P){
 | 
			
		||||
    std::cout << GridLogIntegrator << " MInvSquareRoot:norm(P)= " << std::sqrt(norm2(P)) << std::endl;
 | 
			
		||||
    // do nothing
 | 
			
		||||
  }
 | 
			
		||||
  virtual void MDeriv(const Field& in, Field& out){
 | 
			
		||||
    std::cout << GridLogIntegrator << " MDeriv:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
 | 
			
		||||
    out = Zero();
 | 
			
		||||
  }
 | 
			
		||||
  virtual void MinvDeriv(const Field& in, Field& out){
 | 
			
		||||
    std::cout << GridLogIntegrator << " MinvDeriv:norm(in)= " << std::sqrt(norm2(in)) << std::endl;
 | 
			
		||||
    out = Zero();
 | 
			
		||||
  }
 | 
			
		||||
  virtual void MDeriv(const Field& left, const Field& right, Field& out){
 | 
			
		||||
    std::cout << GridLogIntegrator << " MDeriv:norm(left)= " << std::sqrt(norm2(left)) << std::endl;
 | 
			
		||||
    std::cout << GridLogIntegrator << " MDeriv:norm(right)= " << std::sqrt(norm2(right)) << std::endl;
 | 
			
		||||
    out = Zero();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -101,14 +122,15 @@ public:
 | 
			
		||||
    // Generate gaussian momenta
 | 
			
		||||
    Implementation::generate_momenta(Mom, sRNG, pRNG);
 | 
			
		||||
    // Modify the distribution with the metric
 | 
			
		||||
//    if(M.Trivial()) return;
 | 
			
		||||
    M.MSquareRoot(Mom);
 | 
			
		||||
 | 
			
		||||
    if (1) {
 | 
			
		||||
      // Auxiliary momenta
 | 
			
		||||
      // do nothing if trivial, so hide in the metric
 | 
			
		||||
      MomentaField AuxMomTemp(Mom.Grid());
 | 
			
		||||
      Implementation::generate_momenta(AuxMom, sRNG, pRNG);
 | 
			
		||||
      Implementation::generate_momenta(AuxField, sRNG, pRNG);
 | 
			
		||||
      Implementation::generate_momenta(AuxMom, sRNG,pRNG);
 | 
			
		||||
      Implementation::generate_momenta(AuxField, sRNG,pRNG);
 | 
			
		||||
      // Modify the distribution with the metric
 | 
			
		||||
      // Aux^dag M Aux
 | 
			
		||||
      M.MInvSquareRoot(AuxMom);  // AuxMom = M^{-1/2} AuxMomTemp
 | 
			
		||||
@@ -117,11 +139,12 @@ public:
 | 
			
		||||
 | 
			
		||||
  // Correct
 | 
			
		||||
  RealD MomentaAction(){
 | 
			
		||||
    static RealD Saux=0.,Smom=0.;
 | 
			
		||||
    MomentaField inv(Mom.Grid());
 | 
			
		||||
    inv = Zero();
 | 
			
		||||
    M.Minv(Mom, inv);
 | 
			
		||||
    LatticeComplex Hloc(Mom.Grid());
 | 
			
		||||
    Hloc = Zero();
 | 
			
		||||
    LatticeComplex Hloc(Mom.Grid()); Hloc = Zero();
 | 
			
		||||
    LatticeComplex Hloc2(Mom.Grid()); Hloc2 = Zero();
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      // This is not very general
 | 
			
		||||
      // hide in the metric
 | 
			
		||||
@@ -129,8 +152,15 @@ public:
 | 
			
		||||
      auto inv_mu = PeekIndex<LorentzIndex>(inv, mu);
 | 
			
		||||
      Hloc += trace(Mom_mu * inv_mu);
 | 
			
		||||
    }
 | 
			
		||||
    auto Htmp1 = TensorRemove(sum(Hloc));
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSmom = " << Htmp1.real()-Smom << "\n";
 | 
			
		||||
    Smom=Htmp1.real()/HMC_MOMENTUM_DENOMINATOR;
 | 
			
		||||
    
 | 
			
		||||
    if (1) {
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
//    if(!M.Trivial()) 
 | 
			
		||||
    {
 | 
			
		||||
      // Auxiliary Fields
 | 
			
		||||
      // hide in the metric
 | 
			
		||||
      M.M(AuxMom, inv);
 | 
			
		||||
@@ -140,13 +170,18 @@ public:
 | 
			
		||||
        auto inv_mu = PeekIndex<LorentzIndex>(inv, mu);
 | 
			
		||||
        auto am_mu = PeekIndex<LorentzIndex>(AuxMom, mu);
 | 
			
		||||
        auto af_mu = PeekIndex<LorentzIndex>(AuxField, mu);
 | 
			
		||||
        Hloc += trace(am_mu * inv_mu);// p M p
 | 
			
		||||
        Hloc += trace(af_mu * af_mu);
 | 
			
		||||
        Hloc += trace(am_mu * inv_mu);
 | 
			
		||||
        Hloc2 += trace(af_mu * af_mu);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    auto Htmp2 = TensorRemove(sum(Hloc))-Htmp1;
 | 
			
		||||
    std::cout << GridLogMessage << "S:dSaux = " << Htmp2.real()-Saux << "\n";
 | 
			
		||||
    Saux=Htmp2.real();
 | 
			
		||||
 | 
			
		||||
    auto Hsum = TensorRemove(sum(Hloc));
 | 
			
		||||
    return Hsum.real();
 | 
			
		||||
    auto Hsum = TensorRemove(sum(Hloc))/HMC_MOMENTUM_DENOMINATOR;
 | 
			
		||||
    auto Hsum2 = TensorRemove(sum(Hloc2));
 | 
			
		||||
    std::cout << GridLogIntegrator << "MomentaAction: " <<  Hsum.real()+Hsum2.real() << std::endl;
 | 
			
		||||
    return Hsum.real()+Hsum2.real();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Correct
 | 
			
		||||
@@ -157,15 +192,17 @@ public:
 | 
			
		||||
    MomentaField MDer(in.Grid());
 | 
			
		||||
    MomentaField X(in.Grid());
 | 
			
		||||
    X = Zero();
 | 
			
		||||
    M.Minv(in, X);  // X = G in
 | 
			
		||||
    M.MDeriv(X, MDer);  // MDer = U * dS/dU
 | 
			
		||||
    der = Implementation::projectForce(MDer);  // Ta if gauge fields
 | 
			
		||||
    M.MinvDeriv(in, MDer);  // MDer = U * dS/dU
 | 
			
		||||
    der = -1.0* Implementation::projectForce(MDer);  // Ta if gauge fields
 | 
			
		||||
//    std::cout << GridLogIntegrator << " DerivativeU: norm(in)= " << std::sqrt(norm2(in)) << std::endl;
 | 
			
		||||
//    std::cout << GridLogIntegrator << " DerivativeU: norm(der)= " << std::sqrt(norm2(der)) << std::endl;
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void AuxiliaryFieldsDerivative(MomentaField& der){
 | 
			
		||||
    der = Zero();
 | 
			
		||||
    if (1){
 | 
			
		||||
//    if(!M.Trivial()) 
 | 
			
		||||
    {
 | 
			
		||||
      // Auxiliary fields
 | 
			
		||||
      MomentaField der_temp(der.Grid());
 | 
			
		||||
      MomentaField X(der.Grid());
 | 
			
		||||
@@ -173,6 +210,7 @@ public:
 | 
			
		||||
      //M.M(AuxMom, X); // X = M Aux
 | 
			
		||||
      // Two derivative terms
 | 
			
		||||
      // the Mderiv need separation of left and right terms
 | 
			
		||||
    std::cout << GridLogIntegrator << " AuxiliaryFieldsDerivative:norm(AuxMom)= " << std::sqrt(norm2(AuxMom)) << std::endl;
 | 
			
		||||
      M.MDeriv(AuxMom, der); 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -180,6 +218,7 @@ public:
 | 
			
		||||
      //M.MDeriv(X, AuxMom, der_temp); der += der_temp;
 | 
			
		||||
 | 
			
		||||
      der = -1.0*Implementation::projectForce(der);
 | 
			
		||||
      std::cout << GridLogIntegrator << " AuxiliaryFieldsDerivative:norm(der)= " << std::sqrt(norm2(der)) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -189,22 +228,28 @@ public:
 | 
			
		||||
    // is the projection necessary here?
 | 
			
		||||
    // no for fields in the algebra
 | 
			
		||||
    der = Implementation::projectForce(der); 
 | 
			
		||||
    std::cout << GridLogIntegrator << " DerivativeP:norm(der)= " << std::sqrt(norm2(der)) << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void update_auxiliary_momenta(RealD ep){
 | 
			
		||||
    if(1){
 | 
			
		||||
      AuxMom -= ep * AuxField;
 | 
			
		||||
      std::cout << GridLogIntegrator << "AuxMom update_auxiliary_fields: " << std::sqrt(norm2(AuxMom)) << std::endl;
 | 
			
		||||
      std::cout << GridLogIntegrator << "AuxField update_auxiliary_fields: " << std::sqrt(norm2(AuxField)) << std::endl;
 | 
			
		||||
    {
 | 
			
		||||
      AuxMom -= ep * AuxField * HMC_MOMENTUM_DENOMINATOR;
 | 
			
		||||
      std::cout << GridLogIntegrator << "AuxMom update_auxiliary_fields: " << std::sqrt(norm2(AuxMom)) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void update_auxiliary_fields(RealD ep){
 | 
			
		||||
    if (1) {
 | 
			
		||||
//    if(!M.Trivial()) 
 | 
			
		||||
    {
 | 
			
		||||
      MomentaField tmp(AuxMom.Grid());
 | 
			
		||||
      MomentaField tmp2(AuxMom.Grid());
 | 
			
		||||
      M.M(AuxMom, tmp);
 | 
			
		||||
      // M.M(tmp, tmp2);
 | 
			
		||||
      AuxField += ep * tmp;  // M^2 AuxMom
 | 
			
		||||
      // factor of 2?
 | 
			
		||||
      std::cout << GridLogIntegrator << "AuxField update_auxiliary_fields: " << std::sqrt(norm2(AuxField)) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,932 +0,0 @@
 | 
			
		||||
/*************************************************************************************
 | 
			
		||||
 | 
			
		||||
Grid physics library, www.github.com/paboyle/Grid
 | 
			
		||||
 | 
			
		||||
Source file: ./lib/qcd/utils/SUn.h
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2015
 | 
			
		||||
 | 
			
		||||
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
 | 
			
		||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
Author: neo <cossu@post.kek.jp>
 | 
			
		||||
Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
 | 
			
		||||
This program is free software; you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License along
 | 
			
		||||
with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 | 
			
		||||
See the full license in the file "LICENSE" in the top level distribution
 | 
			
		||||
directory
 | 
			
		||||
*************************************************************************************/
 | 
			
		||||
			   /*  END LEGAL */
 | 
			
		||||
#ifndef QCD_UTIL_SUN_H
 | 
			
		||||
#define QCD_UTIL_SUN_H
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
template<int N, class Vec>
 | 
			
		||||
Lattice<iScalar<iScalar<iScalar<Vec> > > > Determinant(const Lattice<iScalar<iScalar<iMatrix<Vec, N> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid=Umu.Grid();
 | 
			
		||||
  auto lvol = grid->lSites();
 | 
			
		||||
  Lattice<iScalar<iScalar<iScalar<Vec> > > > ret(grid);
 | 
			
		||||
  typedef typename Vec::scalar_type scalar;
 | 
			
		||||
  autoView(Umu_v,Umu,CpuRead);
 | 
			
		||||
  autoView(ret_v,ret,CpuWrite);
 | 
			
		||||
  thread_for(site,lvol,{
 | 
			
		||||
    Eigen::MatrixXcd EigenU = Eigen::MatrixXcd::Zero(N,N);
 | 
			
		||||
    Coordinate lcoor;
 | 
			
		||||
    grid->LocalIndexToLocalCoor(site, lcoor);
 | 
			
		||||
    iScalar<iScalar<iMatrix<scalar, N> > > Us;
 | 
			
		||||
    peekLocalSite(Us, Umu_v, lcoor);
 | 
			
		||||
    for(int i=0;i<N;i++){
 | 
			
		||||
      for(int j=0;j<N;j++){
 | 
			
		||||
	scalar tmp= Us()()(i,j);
 | 
			
		||||
	ComplexD ztmp(real(tmp),imag(tmp));
 | 
			
		||||
	EigenU(i,j)=ztmp;
 | 
			
		||||
      }}
 | 
			
		||||
    ComplexD detD  = EigenU.determinant();
 | 
			
		||||
    typename Vec::scalar_type det(detD.real(),detD.imag());
 | 
			
		||||
    pokeLocalSite(det,ret_v,lcoor);
 | 
			
		||||
  });
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<int N, class Vec>
 | 
			
		||||
static void ProjectSUn(Lattice<iScalar<iScalar<iMatrix<Vec, N> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
  Umu      = ProjectOnGroup(Umu);
 | 
			
		||||
  auto det = Determinant(Umu);
 | 
			
		||||
 | 
			
		||||
  det = conjugate(det);
 | 
			
		||||
 | 
			
		||||
  for(int i=0;i<N;i++){
 | 
			
		||||
    auto element = PeekIndex<ColourIndex>(Umu,N-1,i);
 | 
			
		||||
    element = element * det;
 | 
			
		||||
    PokeIndex<ColourIndex>(Umu,element,Nc-1,i);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
template<int N,class Vec>
 | 
			
		||||
static void ProjectSUn(Lattice<iVector<iScalar<iMatrix<Vec, N> >,Nd> > &U)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid=U.Grid();
 | 
			
		||||
  // Reunitarise
 | 
			
		||||
  for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
    auto Umu = PeekIndex<LorentzIndex>(U,mu);
 | 
			
		||||
    Umu      = ProjectOnGroup(Umu);
 | 
			
		||||
    ProjectSUn(Umu);
 | 
			
		||||
    PokeIndex<LorentzIndex>(U,Umu,mu);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <int ncolour>
 | 
			
		||||
class SU {
 | 
			
		||||
public:
 | 
			
		||||
  static const int Dimension = ncolour;
 | 
			
		||||
  static const int AdjointDimension = ncolour * ncolour - 1;
 | 
			
		||||
  static int su2subgroups(void) { return (ncolour * (ncolour - 1)) / 2; }
 | 
			
		||||
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iSUnMatrix = iScalar<iScalar<iMatrix<vtype, ncolour> > >;
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iSU2Matrix = iScalar<iScalar<iMatrix<vtype, 2> > >;
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iSUnAlgebraVector =
 | 
			
		||||
    iScalar<iScalar<iVector<vtype, AdjointDimension> > >;
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Types can be accessed as SU<2>::Matrix , SU<2>::vSUnMatrix,
 | 
			
		||||
  // SU<2>::LatticeMatrix etc...
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  typedef iSUnMatrix<Complex> Matrix;
 | 
			
		||||
  typedef iSUnMatrix<ComplexF> MatrixF;
 | 
			
		||||
  typedef iSUnMatrix<ComplexD> MatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef iSUnMatrix<vComplex> vMatrix;
 | 
			
		||||
  typedef iSUnMatrix<vComplexF> vMatrixF;
 | 
			
		||||
  typedef iSUnMatrix<vComplexD> vMatrixD;
 | 
			
		||||
 | 
			
		||||
  // For the projectors to the algebra
 | 
			
		||||
  // these should be real...
 | 
			
		||||
  // keeping complex for consistency with the SIMD vector types
 | 
			
		||||
  typedef iSUnAlgebraVector<Complex> AlgebraVector;
 | 
			
		||||
  typedef iSUnAlgebraVector<ComplexF> AlgebraVectorF;
 | 
			
		||||
  typedef iSUnAlgebraVector<ComplexD> AlgebraVectorD;
 | 
			
		||||
 | 
			
		||||
  typedef iSUnAlgebraVector<vComplex> vAlgebraVector;
 | 
			
		||||
  typedef iSUnAlgebraVector<vComplexF> vAlgebraVectorF;
 | 
			
		||||
  typedef iSUnAlgebraVector<vComplexD> vAlgebraVectorD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<vMatrix> LatticeMatrix;
 | 
			
		||||
  typedef Lattice<vMatrixF> LatticeMatrixF;
 | 
			
		||||
  typedef Lattice<vMatrixD> LatticeMatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<vAlgebraVector> LatticeAlgebraVector;
 | 
			
		||||
  typedef Lattice<vAlgebraVectorF> LatticeAlgebraVectorF;
 | 
			
		||||
  typedef Lattice<vAlgebraVectorD> LatticeAlgebraVectorD;
 | 
			
		||||
 | 
			
		||||
  typedef iSU2Matrix<Complex> SU2Matrix;
 | 
			
		||||
  typedef iSU2Matrix<ComplexF> SU2MatrixF;
 | 
			
		||||
  typedef iSU2Matrix<ComplexD> SU2MatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef iSU2Matrix<vComplex> vSU2Matrix;
 | 
			
		||||
  typedef iSU2Matrix<vComplexF> vSU2MatrixF;
 | 
			
		||||
  typedef iSU2Matrix<vComplexD> vSU2MatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<vSU2Matrix> LatticeSU2Matrix;
 | 
			
		||||
  typedef Lattice<vSU2MatrixF> LatticeSU2MatrixF;
 | 
			
		||||
  typedef Lattice<vSU2MatrixD> LatticeSU2MatrixD;
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // There are N^2-1 generators for SU(N).
 | 
			
		||||
  //
 | 
			
		||||
  // We take a traceless hermitian generator basis as follows
 | 
			
		||||
  //
 | 
			
		||||
  // * Normalisation: trace ta tb = 1/2 delta_ab = T_F delta_ab
 | 
			
		||||
  //   T_F = 1/2  for SU(N) groups
 | 
			
		||||
  //
 | 
			
		||||
  // * Off diagonal
 | 
			
		||||
  //    - pairs of rows i1,i2 behaving like pauli matrices signma_x, sigma_y
 | 
			
		||||
  //
 | 
			
		||||
  //    - there are (Nc-1-i1) slots for i2 on each row [ x  0  x ]
 | 
			
		||||
  //      direct count off each row
 | 
			
		||||
  //
 | 
			
		||||
  //    - Sum of all pairs is Nc(Nc-1)/2: proof arithmetic series
 | 
			
		||||
  //
 | 
			
		||||
  //      (Nc-1) + (Nc-2)+...  1      ==> Nc*(Nc-1)/2
 | 
			
		||||
  //      1+ 2+          +   + Nc-1
 | 
			
		||||
  //
 | 
			
		||||
  //    - There are 2 x Nc (Nc-1)/ 2 of these = Nc^2 - Nc
 | 
			
		||||
  //
 | 
			
		||||
  //    - We enumerate the row-col pairs.
 | 
			
		||||
  //    - for each row col pair there is a (sigma_x) and a (sigma_y) like
 | 
			
		||||
  //    generator
 | 
			
		||||
  //
 | 
			
		||||
  //
 | 
			
		||||
  //   t^a_ij = { in 0.. Nc(Nc-1)/2 -1} =>  1/2(delta_{i,i1} delta_{j,i2} +
 | 
			
		||||
  //   delta_{i,i1} delta_{j,i2})
 | 
			
		||||
  //   t^a_ij = { in Nc(Nc-1)/2 ... Nc(Nc-1) - 1} =>  i/2( delta_{i,i1}
 | 
			
		||||
  //   delta_{j,i2} - i delta_{i,i1} delta_{j,i2})
 | 
			
		||||
  //
 | 
			
		||||
  // * Diagonal; must be traceless and normalised
 | 
			
		||||
  //   - Sequence is
 | 
			
		||||
  //   N  (1,-1,0,0...)
 | 
			
		||||
  //   N  (1, 1,-2,0...)
 | 
			
		||||
  //   N  (1, 1, 1,-3,0...)
 | 
			
		||||
  //   N  (1, 1, 1, 1,-4,0...)
 | 
			
		||||
  //
 | 
			
		||||
  //   where 1/2 = N^2 (1+.. m^2)etc.... for the m-th diagonal generator
 | 
			
		||||
  //   NB this gives the famous SU3 result for su2 index 8
 | 
			
		||||
  //
 | 
			
		||||
  //   N= sqrt(1/2 . 1/6 ) = 1/2 . 1/sqrt(3)
 | 
			
		||||
  //
 | 
			
		||||
  //   ( 1      )
 | 
			
		||||
  //   (    1   ) / sqrt(3) /2  = 1/2 lambda_8
 | 
			
		||||
  //   (      -2)
 | 
			
		||||
  //
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void generator(int lieIndex, iSUnMatrix<cplx> &ta) {
 | 
			
		||||
    // map lie index to which type of generator
 | 
			
		||||
    int diagIndex;
 | 
			
		||||
    int su2Index;
 | 
			
		||||
    int sigxy;
 | 
			
		||||
    int NNm1 = ncolour * (ncolour - 1);
 | 
			
		||||
    if (lieIndex >= NNm1) {
 | 
			
		||||
      diagIndex = lieIndex - NNm1;
 | 
			
		||||
      generatorDiagonal(diagIndex, ta);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    sigxy = lieIndex & 0x1;  // even or odd
 | 
			
		||||
    su2Index = lieIndex >> 1;
 | 
			
		||||
    if (sigxy)
 | 
			
		||||
      generatorSigmaY(su2Index, ta);
 | 
			
		||||
    else
 | 
			
		||||
      generatorSigmaX(su2Index, ta);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void generatorSigmaY(int su2Index, iSUnMatrix<cplx> &ta) {
 | 
			
		||||
    ta = Zero();
 | 
			
		||||
    int i1, i2;
 | 
			
		||||
    su2SubGroupIndex(i1, i2, su2Index);
 | 
			
		||||
    ta()()(i1, i2) = 1.0;
 | 
			
		||||
    ta()()(i2, i1) = 1.0;
 | 
			
		||||
    ta = ta * 0.5;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void generatorSigmaX(int su2Index, iSUnMatrix<cplx> &ta) {
 | 
			
		||||
    ta = Zero();
 | 
			
		||||
    cplx i(0.0, 1.0);
 | 
			
		||||
    int i1, i2;
 | 
			
		||||
    su2SubGroupIndex(i1, i2, su2Index);
 | 
			
		||||
    ta()()(i1, i2) = i;
 | 
			
		||||
    ta()()(i2, i1) = -i;
 | 
			
		||||
    ta = ta * 0.5;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void generatorDiagonal(int diagIndex, iSUnMatrix<cplx> &ta) {
 | 
			
		||||
    // diag ({1, 1, ..., 1}(k-times), -k, 0, 0, ...)
 | 
			
		||||
    ta = Zero();
 | 
			
		||||
    int k = diagIndex + 1;                  // diagIndex starts from 0
 | 
			
		||||
    for (int i = 0; i <= diagIndex; i++) {  // k iterations
 | 
			
		||||
      ta()()(i, i) = 1.0;
 | 
			
		||||
    }
 | 
			
		||||
    ta()()(k, k) = -k;  // indexing starts from 0
 | 
			
		||||
    RealD nrm = 1.0 / std::sqrt(2.0 * k * (k + 1));
 | 
			
		||||
    ta = ta * nrm;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Map a su2 subgroup number to the pair of rows that are non zero
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  static void su2SubGroupIndex(int &i1, int &i2, int su2_index) {
 | 
			
		||||
    assert((su2_index >= 0) && (su2_index < (ncolour * (ncolour - 1)) / 2));
 | 
			
		||||
 | 
			
		||||
    int spare = su2_index;
 | 
			
		||||
    for (i1 = 0; spare >= (ncolour - 1 - i1); i1++) {
 | 
			
		||||
      spare = spare - (ncolour - 1 - i1);  // remove the Nc-1-i1 terms
 | 
			
		||||
    }
 | 
			
		||||
    i2 = i1 + 1 + spare;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Pull out a subgroup and project on to real coeffs x pauli basis
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  template <class vcplx>
 | 
			
		||||
  static void su2Extract(Lattice<iSinglet<vcplx> > &Determinant,
 | 
			
		||||
                         Lattice<iSU2Matrix<vcplx> > &subgroup,
 | 
			
		||||
                         const Lattice<iSUnMatrix<vcplx> > &source,
 | 
			
		||||
                         int su2_index) {
 | 
			
		||||
    GridBase *grid(source.Grid());
 | 
			
		||||
    conformable(subgroup, source);
 | 
			
		||||
    conformable(subgroup, Determinant);
 | 
			
		||||
    int i0, i1;
 | 
			
		||||
    su2SubGroupIndex(i0, i1, su2_index);
 | 
			
		||||
 | 
			
		||||
    autoView( subgroup_v , subgroup,AcceleratorWrite);
 | 
			
		||||
    autoView( source_v   , source,AcceleratorRead);
 | 
			
		||||
    autoView( Determinant_v , Determinant,AcceleratorWrite);
 | 
			
		||||
    accelerator_for(ss, grid->oSites(), 1, {
 | 
			
		||||
 | 
			
		||||
      subgroup_v[ss]()()(0, 0) = source_v[ss]()()(i0, i0);
 | 
			
		||||
      subgroup_v[ss]()()(0, 1) = source_v[ss]()()(i0, i1);
 | 
			
		||||
      subgroup_v[ss]()()(1, 0) = source_v[ss]()()(i1, i0);
 | 
			
		||||
      subgroup_v[ss]()()(1, 1) = source_v[ss]()()(i1, i1);
 | 
			
		||||
 | 
			
		||||
      iSU2Matrix<vcplx> Sigma = subgroup_v[ss];
 | 
			
		||||
 | 
			
		||||
      Sigma = Sigma - adj(Sigma) + trace(adj(Sigma));
 | 
			
		||||
 | 
			
		||||
      subgroup_v[ss] = Sigma;
 | 
			
		||||
 | 
			
		||||
      // this should be purely real
 | 
			
		||||
      Determinant_v[ss] =
 | 
			
		||||
	Sigma()()(0, 0) * Sigma()()(1, 1) - Sigma()()(0, 1) * Sigma()()(1, 0);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Set matrix to one and insert a pauli subgroup
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  template <class vcplx>
 | 
			
		||||
  static void su2Insert(const Lattice<iSU2Matrix<vcplx> > &subgroup,
 | 
			
		||||
                        Lattice<iSUnMatrix<vcplx> > &dest, int su2_index) {
 | 
			
		||||
    GridBase *grid(dest.Grid());
 | 
			
		||||
    conformable(subgroup, dest);
 | 
			
		||||
    int i0, i1;
 | 
			
		||||
    su2SubGroupIndex(i0, i1, su2_index);
 | 
			
		||||
 | 
			
		||||
    dest = 1.0;  // start out with identity
 | 
			
		||||
    autoView( dest_v , dest, AcceleratorWrite);
 | 
			
		||||
    autoView( subgroup_v, subgroup, AcceleratorRead);
 | 
			
		||||
    accelerator_for(ss, grid->oSites(),1,
 | 
			
		||||
    {
 | 
			
		||||
      dest_v[ss]()()(i0, i0) = subgroup_v[ss]()()(0, 0);
 | 
			
		||||
      dest_v[ss]()()(i0, i1) = subgroup_v[ss]()()(0, 1);
 | 
			
		||||
      dest_v[ss]()()(i1, i0) = subgroup_v[ss]()()(1, 0);
 | 
			
		||||
      dest_v[ss]()()(i1, i1) = subgroup_v[ss]()()(1, 1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ///////////////////////////////////////////////
 | 
			
		||||
  // Generate e^{ Re Tr Staple Link} dlink
 | 
			
		||||
  //
 | 
			
		||||
  // *** Note Staple should be appropriate linear compbination between all
 | 
			
		||||
  // staples.
 | 
			
		||||
  // *** If already by beta pass coefficient 1.0.
 | 
			
		||||
  // *** This routine applies the additional 1/Nc factor that comes after trace
 | 
			
		||||
  // in action.
 | 
			
		||||
  //
 | 
			
		||||
  ///////////////////////////////////////////////
 | 
			
		||||
  static void SubGroupHeatBath(GridSerialRNG &sRNG, GridParallelRNG &pRNG,
 | 
			
		||||
			       RealD beta,  // coeff multiplying staple in action (with no 1/Nc)
 | 
			
		||||
			       LatticeMatrix &link,
 | 
			
		||||
			       const LatticeMatrix &barestaple,  // multiplied by action coeffs so th
 | 
			
		||||
			       int su2_subgroup, int nheatbath, LatticeInteger &wheremask) 
 | 
			
		||||
  {
 | 
			
		||||
    GridBase *grid = link.Grid();
 | 
			
		||||
 | 
			
		||||
    const RealD twopi = 2.0 * M_PI;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrix staple(grid);
 | 
			
		||||
 | 
			
		||||
    staple = barestaple * (beta / ncolour);
 | 
			
		||||
 | 
			
		||||
    LatticeMatrix V(grid);
 | 
			
		||||
    V = link * staple;
 | 
			
		||||
 | 
			
		||||
    // Subgroup manipulation in the lie algebra space
 | 
			
		||||
    LatticeSU2Matrix u(grid);  // Kennedy pendleton "u" real projected normalised Sigma
 | 
			
		||||
    LatticeSU2Matrix uinv(grid);
 | 
			
		||||
    LatticeSU2Matrix ua(grid);  // a in pauli form
 | 
			
		||||
    LatticeSU2Matrix b(grid);   // rotated matrix after hb
 | 
			
		||||
 | 
			
		||||
    // Some handy constant fields
 | 
			
		||||
    LatticeComplex ones(grid);
 | 
			
		||||
    ones = 1.0;
 | 
			
		||||
    LatticeComplex zeros(grid);
 | 
			
		||||
    zeros = Zero();
 | 
			
		||||
    LatticeReal rones(grid);
 | 
			
		||||
    rones = 1.0;
 | 
			
		||||
    LatticeReal rzeros(grid);
 | 
			
		||||
    rzeros = Zero();
 | 
			
		||||
    LatticeComplex udet(grid);  // determinant of real(staple)
 | 
			
		||||
    LatticeInteger mask_true(grid);
 | 
			
		||||
    mask_true = 1;
 | 
			
		||||
    LatticeInteger mask_false(grid);
 | 
			
		||||
    mask_false = 0;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
      PLB 156 P393 (1985) (Kennedy and Pendleton)
 | 
			
		||||
 | 
			
		||||
      Note: absorb "beta" into the def of sigma compared to KP paper; staple
 | 
			
		||||
      passed to this routine has "beta" already multiplied in
 | 
			
		||||
 | 
			
		||||
      Action linear in links h and of form:
 | 
			
		||||
 | 
			
		||||
      beta S = beta  Sum_p (1 - 1/Nc Re Tr Plaq )
 | 
			
		||||
 | 
			
		||||
      Writing Sigma = 1/Nc (beta Sigma') where sum over staples is "Sigma' "
 | 
			
		||||
 | 
			
		||||
      beta S = const - beta/Nc Re Tr h Sigma'
 | 
			
		||||
      = const - Re Tr h Sigma
 | 
			
		||||
 | 
			
		||||
      Decompose h and Sigma into (1, sigma_j) ; h_i real, h^2=1, Sigma_i complex
 | 
			
		||||
      arbitrary.
 | 
			
		||||
 | 
			
		||||
      Tr h Sigma = h_i Sigma_j Tr (sigma_i sigma_j)  = h_i Sigma_j 2 delta_ij
 | 
			
		||||
      Re Tr h Sigma = 2 h_j Re Sigma_j
 | 
			
		||||
 | 
			
		||||
      Normalised re Sigma_j = xi u_j
 | 
			
		||||
 | 
			
		||||
      With u_j a unit vector and U can be in SU(2);
 | 
			
		||||
 | 
			
		||||
      Re Tr h Sigma = 2 h_j Re Sigma_j = 2 xi (h.u)
 | 
			
		||||
 | 
			
		||||
      4xi^2 = Det [ Sig - Sig^dag  + 1 Tr Sigdag]
 | 
			
		||||
      u   = 1/2xi [ Sig - Sig^dag  + 1 Tr Sigdag]
 | 
			
		||||
 | 
			
		||||
      xi = sqrt(Det)/2;
 | 
			
		||||
 | 
			
		||||
      Write a= u h in SU(2); a has pauli decomp a_j;
 | 
			
		||||
 | 
			
		||||
      Note: Product b' xi is unvariant because scaling Sigma leaves
 | 
			
		||||
      normalised vector "u" fixed; Can rescale Sigma so b' = 1.
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    ////////////////////////////////////////////////////////
 | 
			
		||||
    // Real part of Pauli decomposition
 | 
			
		||||
    // Note a subgroup can project to zero in cold start
 | 
			
		||||
    ////////////////////////////////////////////////////////
 | 
			
		||||
    su2Extract(udet, u, V, su2_subgroup);
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////////////////////////////
 | 
			
		||||
    // Normalising this vector if possible; else identity
 | 
			
		||||
    //////////////////////////////////////////////////////
 | 
			
		||||
    LatticeComplex xi(grid);
 | 
			
		||||
 | 
			
		||||
    LatticeSU2Matrix lident(grid);
 | 
			
		||||
 | 
			
		||||
    SU2Matrix ident = Complex(1.0);
 | 
			
		||||
    SU2Matrix pauli1;
 | 
			
		||||
    SU<2>::generator(0, pauli1);
 | 
			
		||||
    SU2Matrix pauli2;
 | 
			
		||||
    SU<2>::generator(1, pauli2);
 | 
			
		||||
    SU2Matrix pauli3;
 | 
			
		||||
    SU<2>::generator(2, pauli3);
 | 
			
		||||
    pauli1 = timesI(pauli1) * 2.0;
 | 
			
		||||
    pauli2 = timesI(pauli2) * 2.0;
 | 
			
		||||
    pauli3 = timesI(pauli3) * 2.0;
 | 
			
		||||
 | 
			
		||||
    LatticeComplex cone(grid);
 | 
			
		||||
    LatticeReal adet(grid);
 | 
			
		||||
    adet = abs(toReal(udet));
 | 
			
		||||
    lident = Complex(1.0);
 | 
			
		||||
    cone = Complex(1.0);
 | 
			
		||||
    Real machine_epsilon = 1.0e-7;
 | 
			
		||||
    u = where(adet > machine_epsilon, u, lident);
 | 
			
		||||
    udet = where(adet > machine_epsilon, udet, cone);
 | 
			
		||||
 | 
			
		||||
    xi = 0.5 * sqrt(udet);  // 4xi^2 = Det [ Sig - Sig^dag  + 1 Tr Sigdag]
 | 
			
		||||
    u = 0.5 * u *
 | 
			
		||||
      pow(xi, -1.0);  //  u   = 1/2xi [ Sig - Sig^dag  + 1 Tr Sigdag]
 | 
			
		||||
 | 
			
		||||
    // Debug test for sanity
 | 
			
		||||
    uinv = adj(u);
 | 
			
		||||
    b = u * uinv - 1.0;
 | 
			
		||||
    assert(norm2(b) < 1.0e-4);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
      Measure: Haar measure dh has d^4a delta(1-|a^2|)
 | 
			
		||||
      In polars:
 | 
			
		||||
      da = da0 r^2 sin theta dr dtheta dphi delta( 1 - r^2 -a0^2)
 | 
			
		||||
      = da0 r^2 sin theta dr dtheta dphi delta( (sqrt(1-a0^) - r)(sqrt(1-a0^) +
 | 
			
		||||
      r) )
 | 
			
		||||
      = da0 r/2 sin theta dr dtheta dphi delta( (sqrt(1-a0^) - r) )
 | 
			
		||||
 | 
			
		||||
      Action factor Q(h) dh  = e^-S[h]  dh =  e^{  xi Tr uh} dh    // beta enters
 | 
			
		||||
      through xi
 | 
			
		||||
      =  e^{2 xi (h.u)} dh
 | 
			
		||||
      =  e^{2 xi h0u0}.e^{2 xi h1u1}.e^{2 xi
 | 
			
		||||
      h2u2}.e^{2 xi h3u3} dh
 | 
			
		||||
 | 
			
		||||
      Therefore for each site, take xi for that site
 | 
			
		||||
      i) generate  |a0|<1 with dist
 | 
			
		||||
      (1-a0^2)^0.5 e^{2 xi a0 } da0
 | 
			
		||||
 | 
			
		||||
      Take alpha = 2 xi  = 2 xi [ recall 2 beta/Nc unmod staple norm]; hence 2.0/Nc
 | 
			
		||||
      factor in Chroma ]
 | 
			
		||||
      A. Generate two uniformly distributed pseudo-random numbers R and R', R'',
 | 
			
		||||
      R''' in the unit interval;
 | 
			
		||||
      B. Set X = -(ln R)/alpha, X' =-(ln R')/alpha;
 | 
			
		||||
      C. Set C = cos^2(2pi R"), with R" another uniform random number in [0,1] ;
 | 
			
		||||
      D. Set A = XC;
 | 
			
		||||
      E. Let d  = X'+A;
 | 
			
		||||
      F. If R'''^2 :> 1 - 0.5 d,  go back to A;
 | 
			
		||||
      G. Set a0 = 1 - d;
 | 
			
		||||
 | 
			
		||||
      Note that in step D setting B ~ X - A and using B in place of A in step E will
 | 
			
		||||
      generate a second independent a 0 value.
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    /////////////////////////////////////////////////////////
 | 
			
		||||
    // count the number of sites by picking "1"'s out of hat
 | 
			
		||||
    /////////////////////////////////////////////////////////
 | 
			
		||||
    Integer hit = 0;
 | 
			
		||||
    LatticeReal rtmp(grid);
 | 
			
		||||
    rtmp = where(wheremask, rones, rzeros);
 | 
			
		||||
    RealD numSites = sum(rtmp);
 | 
			
		||||
    RealD numAccepted;
 | 
			
		||||
    LatticeInteger Accepted(grid);
 | 
			
		||||
    Accepted = Zero();
 | 
			
		||||
    LatticeInteger newlyAccepted(grid);
 | 
			
		||||
 | 
			
		||||
    std::vector<LatticeReal> xr(4, grid);
 | 
			
		||||
    std::vector<LatticeReal> a(4, grid);
 | 
			
		||||
    LatticeReal d(grid);
 | 
			
		||||
    d = Zero();
 | 
			
		||||
    LatticeReal alpha(grid);
 | 
			
		||||
 | 
			
		||||
    //    std::cout<<GridLogMessage<<"xi "<<xi <<std::endl;
 | 
			
		||||
    xi = 2.0 *xi;
 | 
			
		||||
    alpha = toReal(xi);
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
      // A. Generate two uniformly distributed pseudo-random numbers R and R',
 | 
			
		||||
      // R'', R''' in the unit interval;
 | 
			
		||||
      random(pRNG, xr[0]);
 | 
			
		||||
      random(pRNG, xr[1]);
 | 
			
		||||
      random(pRNG, xr[2]);
 | 
			
		||||
      random(pRNG, xr[3]);
 | 
			
		||||
 | 
			
		||||
      // B. Set X = - ln R/alpha, X' = -ln R'/alpha
 | 
			
		||||
      xr[1] = -log(xr[1]) / alpha;
 | 
			
		||||
      xr[2] = -log(xr[2]) / alpha;
 | 
			
		||||
 | 
			
		||||
      // C. Set C = cos^2(2piR'')
 | 
			
		||||
      xr[3] = cos(xr[3] * twopi);
 | 
			
		||||
      xr[3] = xr[3] * xr[3];
 | 
			
		||||
 | 
			
		||||
      LatticeReal xrsq(grid);
 | 
			
		||||
 | 
			
		||||
      // D. Set A = XC;
 | 
			
		||||
      // E. Let d  = X'+A;
 | 
			
		||||
      xrsq = xr[2] + xr[1] * xr[3];
 | 
			
		||||
 | 
			
		||||
      d = where(Accepted, d, xr[2] + xr[1] * xr[3]);
 | 
			
		||||
 | 
			
		||||
      // F. If R'''^2 :> 1 - 0.5 d,  go back to A;
 | 
			
		||||
      LatticeReal thresh(grid);
 | 
			
		||||
      thresh = 1.0 - d * 0.5;
 | 
			
		||||
      xrsq = xr[0] * xr[0];
 | 
			
		||||
      LatticeInteger ione(grid);
 | 
			
		||||
      ione = 1;
 | 
			
		||||
      LatticeInteger izero(grid);
 | 
			
		||||
      izero = Zero();
 | 
			
		||||
 | 
			
		||||
      newlyAccepted = where(xrsq < thresh, ione, izero);
 | 
			
		||||
      Accepted = where(newlyAccepted, newlyAccepted, Accepted);
 | 
			
		||||
      Accepted = where(wheremask, Accepted, izero);
 | 
			
		||||
 | 
			
		||||
      // FIXME need an iSum for integer to avoid overload on return type??
 | 
			
		||||
      rtmp = where(Accepted, rones, rzeros);
 | 
			
		||||
      numAccepted = sum(rtmp);
 | 
			
		||||
 | 
			
		||||
      hit++;
 | 
			
		||||
 | 
			
		||||
    } while ((numAccepted < numSites) && (hit < nheatbath));
 | 
			
		||||
 | 
			
		||||
    // G. Set a0 = 1 - d;
 | 
			
		||||
    a[0] = Zero();
 | 
			
		||||
    a[0] = where(wheremask, 1.0 - d, a[0]);
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////////////////
 | 
			
		||||
    //    ii) generate a_i uniform on two sphere radius (1-a0^2)^0.5
 | 
			
		||||
    //////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    LatticeReal a123mag(grid);
 | 
			
		||||
    a123mag = sqrt(abs(1.0 - a[0] * a[0]));
 | 
			
		||||
 | 
			
		||||
    LatticeReal cos_theta(grid);
 | 
			
		||||
    LatticeReal sin_theta(grid);
 | 
			
		||||
    LatticeReal phi(grid);
 | 
			
		||||
 | 
			
		||||
    random(pRNG, phi);
 | 
			
		||||
    phi = phi * twopi;  // uniform in [0,2pi]
 | 
			
		||||
    random(pRNG, cos_theta);
 | 
			
		||||
    cos_theta = (cos_theta * 2.0) - 1.0;  // uniform in [-1,1]
 | 
			
		||||
    sin_theta = sqrt(abs(1.0 - cos_theta * cos_theta));
 | 
			
		||||
 | 
			
		||||
    a[1] = a123mag * sin_theta * cos(phi);
 | 
			
		||||
    a[2] = a123mag * sin_theta * sin(phi);
 | 
			
		||||
    a[3] = a123mag * cos_theta;
 | 
			
		||||
 | 
			
		||||
    ua = toComplex(a[0]) * ident  + toComplex(a[1]) * pauli1 +
 | 
			
		||||
         toComplex(a[2]) * pauli2 + toComplex(a[3]) * pauli3;
 | 
			
		||||
 | 
			
		||||
    b = 1.0;
 | 
			
		||||
    b = where(wheremask, uinv * ua, b);
 | 
			
		||||
    su2Insert(b, V, su2_subgroup);
 | 
			
		||||
 | 
			
		||||
    // mask the assignment back based on Accptance
 | 
			
		||||
    link = where(Accepted, V * link, link);
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////
 | 
			
		||||
    // Debug Checks
 | 
			
		||||
    // SU2 check
 | 
			
		||||
    LatticeSU2Matrix check(grid);  // rotated matrix after hb
 | 
			
		||||
    u = Zero();
 | 
			
		||||
    check = ua * adj(ua) - 1.0;
 | 
			
		||||
    check = where(Accepted, check, u);
 | 
			
		||||
    assert(norm2(check) < 1.0e-4);
 | 
			
		||||
 | 
			
		||||
    check = b * adj(b) - 1.0;
 | 
			
		||||
    check = where(Accepted, check, u);
 | 
			
		||||
    assert(norm2(check) < 1.0e-4);
 | 
			
		||||
 | 
			
		||||
    LatticeMatrix Vcheck(grid);
 | 
			
		||||
    Vcheck = Zero();
 | 
			
		||||
    Vcheck = where(Accepted, V * adj(V) - 1.0, Vcheck);
 | 
			
		||||
    //    std::cout<<GridLogMessage << "SU3 check " <<norm2(Vcheck)<<std::endl;
 | 
			
		||||
    assert(norm2(Vcheck) < 1.0e-4);
 | 
			
		||||
 | 
			
		||||
    // Verify the link stays in SU(3)
 | 
			
		||||
    //    std::cout<<GridLogMessage <<"Checking the modified link"<<std::endl;
 | 
			
		||||
    Vcheck = link * adj(link) - 1.0;
 | 
			
		||||
    assert(norm2(Vcheck) < 1.0e-4);
 | 
			
		||||
    /////////////////////////////////
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void printGenerators(void) {
 | 
			
		||||
    for (int gen = 0; gen < AdjointDimension; gen++) {
 | 
			
		||||
      Matrix ta;
 | 
			
		||||
      generator(gen, ta);
 | 
			
		||||
      std::cout << GridLogMessage << "Nc = " << ncolour << " t_" << gen
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << ta << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  static void testGenerators(void) {
 | 
			
		||||
    Matrix ta;
 | 
			
		||||
    Matrix tb;
 | 
			
		||||
    std::cout << GridLogMessage
 | 
			
		||||
              << "Fundamental - Checking trace ta tb is 0.5 delta_ab"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
      for (int b = 0; b < AdjointDimension; b++) {
 | 
			
		||||
        generator(a, ta);
 | 
			
		||||
        generator(b, tb);
 | 
			
		||||
        Complex tr = TensorRemove(trace(ta * tb));
 | 
			
		||||
        std::cout << GridLogMessage << "(" << a << "," << b << ") =  " << tr
 | 
			
		||||
                  << std::endl;
 | 
			
		||||
        if (a == b) assert(abs(tr - Complex(0.5)) < 1.0e-6);
 | 
			
		||||
        if (a != b) assert(abs(tr) < 1.0e-6);
 | 
			
		||||
      }
 | 
			
		||||
      std::cout << GridLogMessage << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogMessage << "Fundamental - Checking if hermitian"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
      std::cout << GridLogMessage << a << std::endl;
 | 
			
		||||
      assert(norm2(ta - adj(ta)) < 1.0e-6);
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "Fundamental - Checking if traceless"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
      Complex tr = TensorRemove(trace(ta));
 | 
			
		||||
      std::cout << GridLogMessage << a << " " << std::endl;
 | 
			
		||||
      assert(abs(tr) < 1.0e-6);
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // reunitarise??
 | 
			
		||||
  template <typename LatticeMatrixType>
 | 
			
		||||
  static void LieRandomize(GridParallelRNG &pRNG, LatticeMatrixType &out, double scale = 1.0) 
 | 
			
		||||
  {
 | 
			
		||||
    GridBase *grid = out.Grid();
 | 
			
		||||
 | 
			
		||||
    typedef typename LatticeMatrixType::vector_type vector_type;
 | 
			
		||||
 | 
			
		||||
    typedef iSinglet<vector_type> vTComplexType;
 | 
			
		||||
 | 
			
		||||
    typedef Lattice<vTComplexType> LatticeComplexType;
 | 
			
		||||
    typedef typename GridTypeMapper<typename LatticeMatrixType::vector_object>::scalar_object MatrixType;
 | 
			
		||||
 | 
			
		||||
    LatticeComplexType ca(grid);
 | 
			
		||||
    LatticeMatrixType lie(grid);
 | 
			
		||||
    LatticeMatrixType la(grid);
 | 
			
		||||
    ComplexD ci(0.0, scale);
 | 
			
		||||
    //    ComplexD cone(1.0, 0.0);
 | 
			
		||||
    MatrixType ta;
 | 
			
		||||
 | 
			
		||||
    lie = Zero();
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
      random(pRNG, ca);
 | 
			
		||||
 | 
			
		||||
      ca = (ca + conjugate(ca)) * 0.5;
 | 
			
		||||
      ca = ca - 0.5;
 | 
			
		||||
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
 | 
			
		||||
      la = ci * ca * ta;
 | 
			
		||||
 | 
			
		||||
      lie = lie + la;  // e^{i la ta}
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    taExp(lie, out);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void GaussianFundamentalLieAlgebraMatrix(GridParallelRNG &pRNG,
 | 
			
		||||
                                                  LatticeMatrix &out,
 | 
			
		||||
                                                  Real scale = 1.0) {
 | 
			
		||||
    GridBase *grid = out.Grid();
 | 
			
		||||
    LatticeReal ca(grid);
 | 
			
		||||
    LatticeMatrix la(grid);
 | 
			
		||||
    Complex ci(0.0, scale);
 | 
			
		||||
    Matrix ta;
 | 
			
		||||
 | 
			
		||||
    out = Zero();
 | 
			
		||||
    for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
      gaussian(pRNG, ca);
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
      la = toComplex(ca) * ta;
 | 
			
		||||
      out += la;
 | 
			
		||||
    }
 | 
			
		||||
    out *= ci;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void FundamentalLieAlgebraMatrix(const LatticeAlgebraVector &h,
 | 
			
		||||
                                          LatticeMatrix &out,
 | 
			
		||||
                                          Real scale = 1.0) {
 | 
			
		||||
    conformable(h, out);
 | 
			
		||||
    GridBase *grid = out.Grid();
 | 
			
		||||
    LatticeMatrix la(grid);
 | 
			
		||||
    Matrix ta;
 | 
			
		||||
 | 
			
		||||
    out = Zero();
 | 
			
		||||
    for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
      la = peekColour(h, a) * timesI(ta) * scale;
 | 
			
		||||
      out += la;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
/*
 | 
			
		||||
 * Fundamental rep gauge xform
 | 
			
		||||
 */
 | 
			
		||||
  template<typename Fundamental,typename GaugeMat>
 | 
			
		||||
  static void GaugeTransformFundamental( Fundamental &ferm, GaugeMat &g){
 | 
			
		||||
    GridBase *grid = ferm._grid;
 | 
			
		||||
    conformable(grid,g._grid);
 | 
			
		||||
    ferm = g*ferm;
 | 
			
		||||
  }
 | 
			
		||||
/*
 | 
			
		||||
 * Adjoint rep gauge xform
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
  template<typename Gimpl>
 | 
			
		||||
  static void GaugeTransform(typename Gimpl::GaugeField &Umu, typename Gimpl::GaugeLinkField &g){
 | 
			
		||||
    GridBase *grid = Umu.Grid();
 | 
			
		||||
    conformable(grid,g.Grid());
 | 
			
		||||
 | 
			
		||||
    typename Gimpl::GaugeLinkField U(grid);
 | 
			
		||||
    typename Gimpl::GaugeLinkField ag(grid); ag = adj(g);
 | 
			
		||||
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      U= PeekIndex<LorentzIndex>(Umu,mu);
 | 
			
		||||
      U = g*U*Gimpl::CshiftLink(ag, mu, 1); //BC-aware
 | 
			
		||||
      PokeIndex<LorentzIndex>(Umu,U,mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  template<typename Gimpl>
 | 
			
		||||
  static void GaugeTransform( std::vector<typename Gimpl::GaugeLinkField> &U, typename Gimpl::GaugeLinkField &g){
 | 
			
		||||
    GridBase *grid = g.Grid();
 | 
			
		||||
    typename Gimpl::GaugeLinkField ag(grid); ag = adj(g);
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      U[mu] = g*U[mu]*Gimpl::CshiftLink(ag, mu, 1); //BC-aware
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  template<typename Gimpl>
 | 
			
		||||
  static void RandomGaugeTransform(GridParallelRNG &pRNG, typename Gimpl::GaugeField &Umu, typename Gimpl::GaugeLinkField &g){
 | 
			
		||||
    LieRandomize(pRNG,g,1.0);
 | 
			
		||||
    GaugeTransform<Gimpl>(Umu,g);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Projects the algebra components a lattice matrix (of dimension ncol*ncol -1 )
 | 
			
		||||
  // inverse operation: FundamentalLieAlgebraMatrix
 | 
			
		||||
  static void projectOnAlgebra(LatticeAlgebraVector &h_out, const LatticeMatrix &in, Real scale = 1.0) {
 | 
			
		||||
    conformable(h_out, in);
 | 
			
		||||
    h_out = Zero();
 | 
			
		||||
    Matrix Ta;
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
      generator(a, Ta);
 | 
			
		||||
      pokeColour(h_out, - 2.0 * (trace(timesI(Ta) * in)) * scale, a);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename GaugeField>
 | 
			
		||||
  static void HotConfiguration(GridParallelRNG &pRNG, GaugeField &out) {
 | 
			
		||||
    typedef typename GaugeField::vector_type vector_type;
 | 
			
		||||
    typedef iSUnMatrix<vector_type> vMatrixType;
 | 
			
		||||
    typedef Lattice<vMatrixType> LatticeMatrixType;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrixType Umu(out.Grid());
 | 
			
		||||
    LatticeMatrixType tmp(out.Grid());
 | 
			
		||||
    for (int mu = 0; mu < Nd; mu++) {
 | 
			
		||||
      //      LieRandomize(pRNG, Umu, 1.0);
 | 
			
		||||
      //      PokeIndex<LorentzIndex>(out, Umu, mu);
 | 
			
		||||
      gaussian(pRNG,Umu);
 | 
			
		||||
      tmp = Ta(Umu);
 | 
			
		||||
      taExp(tmp,Umu);
 | 
			
		||||
      ProjectSUn(Umu);
 | 
			
		||||
      PokeIndex<LorentzIndex>(out, Umu, mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  template<typename GaugeField>
 | 
			
		||||
  static void TepidConfiguration(GridParallelRNG &pRNG,GaugeField &out){
 | 
			
		||||
    typedef typename GaugeField::vector_type vector_type;
 | 
			
		||||
    typedef iSUnMatrix<vector_type> vMatrixType;
 | 
			
		||||
    typedef Lattice<vMatrixType> LatticeMatrixType;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrixType Umu(out.Grid());
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      LieRandomize(pRNG,Umu,0.01);
 | 
			
		||||
      PokeIndex<LorentzIndex>(out,Umu,mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  template<typename GaugeField>
 | 
			
		||||
  static void ColdConfiguration(GaugeField &out){
 | 
			
		||||
    typedef typename GaugeField::vector_type vector_type;
 | 
			
		||||
    typedef iSUnMatrix<vector_type> vMatrixType;
 | 
			
		||||
    typedef Lattice<vMatrixType> LatticeMatrixType;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrixType Umu(out.Grid());
 | 
			
		||||
    Umu=1.0;
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      PokeIndex<LorentzIndex>(out,Umu,mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  template<typename GaugeField>
 | 
			
		||||
  static void ColdConfiguration(GridParallelRNG &pRNG,GaugeField &out){
 | 
			
		||||
    ColdConfiguration(out);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template<typename LatticeMatrixType>
 | 
			
		||||
  static void taProj( const LatticeMatrixType &in,  LatticeMatrixType &out){
 | 
			
		||||
    out = Ta(in);
 | 
			
		||||
  }
 | 
			
		||||
  template <typename LatticeMatrixType>
 | 
			
		||||
  static void taExp(const LatticeMatrixType &x, LatticeMatrixType &ex) {
 | 
			
		||||
    typedef typename LatticeMatrixType::scalar_type ComplexType;
 | 
			
		||||
 | 
			
		||||
    LatticeMatrixType xn(x.Grid());
 | 
			
		||||
    RealD nfac = 1.0;
 | 
			
		||||
 | 
			
		||||
    xn = x;
 | 
			
		||||
    ex = xn + ComplexType(1.0);  // 1+x
 | 
			
		||||
 | 
			
		||||
    // Do a 12th order exponentiation
 | 
			
		||||
    for (int i = 2; i <= 12; ++i) {
 | 
			
		||||
      nfac = nfac / RealD(i);  // 1/2, 1/2.3 ...
 | 
			
		||||
      xn = xn * x;             // x2, x3,x4....
 | 
			
		||||
      ex = ex + xn * nfac;     // x2/2!, x3/3!....
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<int N>
 | 
			
		||||
Lattice<iScalar<iScalar<iMatrix<vComplexD, N> > > > Inverse(const Lattice<iScalar<iScalar<iMatrix<vComplexD, N> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid=Umu.Grid();
 | 
			
		||||
  auto lvol = grid->lSites();
 | 
			
		||||
  Lattice<iScalar<iScalar<iMatrix<vComplexD, N> > > > ret(grid);
 | 
			
		||||
  
 | 
			
		||||
  autoView(Umu_v,Umu,CpuRead);
 | 
			
		||||
  autoView(ret_v,ret,CpuWrite);
 | 
			
		||||
  thread_for(site,lvol,{
 | 
			
		||||
    Eigen::MatrixXcd EigenU = Eigen::MatrixXcd::Zero(N,N);
 | 
			
		||||
    Coordinate lcoor;
 | 
			
		||||
    grid->LocalIndexToLocalCoor(site, lcoor);
 | 
			
		||||
    iScalar<iScalar<iMatrix<ComplexD, N> > > Us;
 | 
			
		||||
    iScalar<iScalar<iMatrix<ComplexD, N> > > Ui;
 | 
			
		||||
    peekLocalSite(Us, Umu_v, lcoor);
 | 
			
		||||
    for(int i=0;i<N;i++){
 | 
			
		||||
      for(int j=0;j<N;j++){
 | 
			
		||||
	EigenU(i,j) = Us()()(i,j);
 | 
			
		||||
      }}
 | 
			
		||||
    Eigen::MatrixXcd EigenUinv = EigenU.inverse();
 | 
			
		||||
    for(int i=0;i<N;i++){
 | 
			
		||||
      for(int j=0;j<N;j++){
 | 
			
		||||
	Ui()()(i,j) = EigenUinv(i,j);
 | 
			
		||||
      }}
 | 
			
		||||
    pokeLocalSite(Ui,ret_v,lcoor);
 | 
			
		||||
  });
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
// Explicit specialisation for SU(3).
 | 
			
		||||
// Explicit specialisation for SU(3).
 | 
			
		||||
static void
 | 
			
		||||
ProjectSU3 (Lattice<iScalar<iScalar<iMatrix<vComplexD, 3> > > > &Umu)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid=Umu.Grid();
 | 
			
		||||
  const int x=0;
 | 
			
		||||
  const int y=1;
 | 
			
		||||
  const int z=2;
 | 
			
		||||
  // Reunitarise
 | 
			
		||||
  Umu = ProjectOnGroup(Umu);
 | 
			
		||||
  autoView(Umu_v,Umu,CpuWrite);
 | 
			
		||||
  thread_for(ss,grid->oSites(),{
 | 
			
		||||
      auto cm = Umu_v[ss];
 | 
			
		||||
      cm()()(2,x) = adj(cm()()(0,y)*cm()()(1,z)-cm()()(0,z)*cm()()(1,y)); //x= yz-zy
 | 
			
		||||
      cm()()(2,y) = adj(cm()()(0,z)*cm()()(1,x)-cm()()(0,x)*cm()()(1,z)); //y= zx-xz
 | 
			
		||||
      cm()()(2,z) = adj(cm()()(0,x)*cm()()(1,y)-cm()()(0,y)*cm()()(1,x)); //z= xy-yx
 | 
			
		||||
      Umu_v[ss]=cm;
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
static void ProjectSU3(Lattice<iVector<iScalar<iMatrix<vComplexD, 3> >,Nd> > &U)
 | 
			
		||||
{
 | 
			
		||||
  GridBase *grid=U.Grid();
 | 
			
		||||
  // Reunitarise
 | 
			
		||||
  for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
    auto Umu = PeekIndex<LorentzIndex>(U,mu);
 | 
			
		||||
    Umu      = ProjectOnGroup(Umu);
 | 
			
		||||
    ProjectSU3(Umu);
 | 
			
		||||
    PokeIndex<LorentzIndex>(U,Umu,mu);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef SU<2> SU2;
 | 
			
		||||
typedef SU<3> SU3;
 | 
			
		||||
typedef SU<4> SU4;
 | 
			
		||||
typedef SU<5> SU5;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef SU<Nc> FundamentalMatrices;
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										578
									
								
								Grid/qcd/utils/SUn.impl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										578
									
								
								Grid/qcd/utils/SUn.impl.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,578 @@
 | 
			
		||||
// This file is #included into the body of the class template definition of
 | 
			
		||||
// GaugeGroup. So, image there to be
 | 
			
		||||
//
 | 
			
		||||
// template <int ncolour, class group_name>
 | 
			
		||||
// class GaugeGroup {
 | 
			
		||||
//
 | 
			
		||||
// around it.
 | 
			
		||||
//
 | 
			
		||||
// Please note that the unconventional file extension makes sure that it
 | 
			
		||||
// doesn't get found by the scripts/filelist during bootstrapping.
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
template <ONLY_IF_SU>
 | 
			
		||||
static int su2subgroups(GroupName::SU) { return (ncolour * (ncolour - 1)) / 2; }
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// There are N^2-1 generators for SU(N).
 | 
			
		||||
//
 | 
			
		||||
// We take a traceless hermitian generator basis as follows
 | 
			
		||||
//
 | 
			
		||||
// * Normalisation: trace ta tb = 1/2 delta_ab = T_F delta_ab
 | 
			
		||||
//   T_F = 1/2  for SU(N) groups
 | 
			
		||||
//
 | 
			
		||||
// * Off diagonal
 | 
			
		||||
//    - pairs of rows i1,i2 behaving like pauli matrices signma_x, sigma_y
 | 
			
		||||
//
 | 
			
		||||
//    - there are (Nc-1-i1) slots for i2 on each row [ x  0  x ]
 | 
			
		||||
//      direct count off each row
 | 
			
		||||
//
 | 
			
		||||
//    - Sum of all pairs is Nc(Nc-1)/2: proof arithmetic series
 | 
			
		||||
//
 | 
			
		||||
//      (Nc-1) + (Nc-2)+...  1      ==> Nc*(Nc-1)/2
 | 
			
		||||
//      1+ 2+          +   + Nc-1
 | 
			
		||||
//
 | 
			
		||||
//    - There are 2 x Nc (Nc-1)/ 2 of these = Nc^2 - Nc
 | 
			
		||||
//
 | 
			
		||||
//    - We enumerate the row-col pairs.
 | 
			
		||||
//    - for each row col pair there is a (sigma_x) and a (sigma_y) like
 | 
			
		||||
//    generator
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//   t^a_ij = { in 0.. Nc(Nc-1)/2 -1} =>  1/2(delta_{i,i1} delta_{j,i2} +
 | 
			
		||||
//   delta_{i,i1} delta_{j,i2})
 | 
			
		||||
//   t^a_ij = { in Nc(Nc-1)/2 ... Nc(Nc-1) - 1} =>  i/2( delta_{i,i1}
 | 
			
		||||
//   delta_{j,i2} - i delta_{i,i1} delta_{j,i2})
 | 
			
		||||
//
 | 
			
		||||
// * Diagonal; must be traceless and normalised
 | 
			
		||||
//   - Sequence is
 | 
			
		||||
//   N  (1,-1,0,0...)
 | 
			
		||||
//   N  (1, 1,-2,0...)
 | 
			
		||||
//   N  (1, 1, 1,-3,0...)
 | 
			
		||||
//   N  (1, 1, 1, 1,-4,0...)
 | 
			
		||||
//
 | 
			
		||||
//   where 1/2 = N^2 (1+.. m^2)etc.... for the m-th diagonal generator
 | 
			
		||||
//   NB this gives the famous SU3 result for su2 index 8
 | 
			
		||||
//
 | 
			
		||||
//   N= sqrt(1/2 . 1/6 ) = 1/2 . 1/sqrt(3)
 | 
			
		||||
//
 | 
			
		||||
//   ( 1      )
 | 
			
		||||
//   (    1   ) / sqrt(3) /2  = 1/2 lambda_8
 | 
			
		||||
//   (      -2)
 | 
			
		||||
//
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
template <class cplx, ONLY_IF_SU>
 | 
			
		||||
static void generator(int lieIndex, iGroupMatrix<cplx> &ta, GroupName::SU) {
 | 
			
		||||
  // map lie index to which type of generator
 | 
			
		||||
  int diagIndex;
 | 
			
		||||
  int su2Index;
 | 
			
		||||
  int sigxy;
 | 
			
		||||
  int NNm1 = ncolour * (ncolour - 1);
 | 
			
		||||
  if (lieIndex >= NNm1) {
 | 
			
		||||
    diagIndex = lieIndex - NNm1;
 | 
			
		||||
    generatorDiagonal(diagIndex, ta);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  sigxy = lieIndex & 0x1;  // even or odd
 | 
			
		||||
  su2Index = lieIndex >> 1;
 | 
			
		||||
  if (sigxy)
 | 
			
		||||
    generatorSigmaY(su2Index, ta);
 | 
			
		||||
  else
 | 
			
		||||
    generatorSigmaX(su2Index, ta);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_SU>
 | 
			
		||||
static void generatorSigmaY(int su2Index, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  int i1, i2;
 | 
			
		||||
  su2SubGroupIndex(i1, i2, su2Index);
 | 
			
		||||
  ta()()(i1, i2) = 1.0;
 | 
			
		||||
  ta()()(i2, i1) = 1.0;
 | 
			
		||||
  ta = ta * 0.5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_SU>
 | 
			
		||||
static void generatorSigmaX(int su2Index, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  cplx i(0.0, 1.0);
 | 
			
		||||
  int i1, i2;
 | 
			
		||||
  su2SubGroupIndex(i1, i2, su2Index);
 | 
			
		||||
  ta()()(i1, i2) = i;
 | 
			
		||||
  ta()()(i2, i1) = -i;
 | 
			
		||||
  ta = ta * 0.5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_SU>
 | 
			
		||||
static void generatorDiagonal(int diagIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  // diag ({1, 1, ..., 1}(k-times), -k, 0, 0, ...)
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  int k = diagIndex + 1;                  // diagIndex starts from 0
 | 
			
		||||
  for (int i = 0; i <= diagIndex; i++) {  // k iterations
 | 
			
		||||
    ta()()(i, i) = 1.0;
 | 
			
		||||
  }
 | 
			
		||||
  ta()()(k, k) = -k;  // indexing starts from 0
 | 
			
		||||
  RealD nrm = 1.0 / std::sqrt(2.0 * k * (k + 1));
 | 
			
		||||
  ta = ta * nrm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Map a su2 subgroup number to the pair of rows that are non zero
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
static void su2SubGroupIndex(int &i1, int &i2, int su2_index, GroupName::SU) {
 | 
			
		||||
  assert((su2_index >= 0) && (su2_index < (ncolour * (ncolour - 1)) / 2));
 | 
			
		||||
 | 
			
		||||
  int spare = su2_index;
 | 
			
		||||
  for (i1 = 0; spare >= (ncolour - 1 - i1); i1++) {
 | 
			
		||||
    spare = spare - (ncolour - 1 - i1);  // remove the Nc-1-i1 terms
 | 
			
		||||
  }
 | 
			
		||||
  i2 = i1 + 1 + spare;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Pull out a subgroup and project on to real coeffs x pauli basis
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
template <class vcplx, ONLY_IF_SU>
 | 
			
		||||
static void su2Extract(Lattice<iSinglet<vcplx> > &Determinant,
 | 
			
		||||
                       Lattice<iSU2Matrix<vcplx> > &subgroup,
 | 
			
		||||
                       const Lattice<iGroupMatrix<vcplx> > &source,
 | 
			
		||||
                       int su2_index) {
 | 
			
		||||
  GridBase *grid(source.Grid());
 | 
			
		||||
  conformable(subgroup, source);
 | 
			
		||||
  conformable(subgroup, Determinant);
 | 
			
		||||
  int i0, i1;
 | 
			
		||||
  su2SubGroupIndex(i0, i1, su2_index);
 | 
			
		||||
 | 
			
		||||
  autoView(subgroup_v, subgroup, AcceleratorWrite);
 | 
			
		||||
  autoView(source_v, source, AcceleratorRead);
 | 
			
		||||
  autoView(Determinant_v, Determinant, AcceleratorWrite);
 | 
			
		||||
  accelerator_for(ss, grid->oSites(), 1, {
 | 
			
		||||
    subgroup_v[ss]()()(0, 0) = source_v[ss]()()(i0, i0);
 | 
			
		||||
    subgroup_v[ss]()()(0, 1) = source_v[ss]()()(i0, i1);
 | 
			
		||||
    subgroup_v[ss]()()(1, 0) = source_v[ss]()()(i1, i0);
 | 
			
		||||
    subgroup_v[ss]()()(1, 1) = source_v[ss]()()(i1, i1);
 | 
			
		||||
 | 
			
		||||
    iSU2Matrix<vcplx> Sigma = subgroup_v[ss];
 | 
			
		||||
 | 
			
		||||
    Sigma = Sigma - adj(Sigma) + trace(adj(Sigma));
 | 
			
		||||
 | 
			
		||||
    subgroup_v[ss] = Sigma;
 | 
			
		||||
 | 
			
		||||
    // this should be purely real
 | 
			
		||||
    Determinant_v[ss] =
 | 
			
		||||
        Sigma()()(0, 0) * Sigma()()(1, 1) - Sigma()()(0, 1) * Sigma()()(1, 0);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Set matrix to one and insert a pauli subgroup
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
template <class vcplx, ONLY_IF_SU>
 | 
			
		||||
static void su2Insert(const Lattice<iSU2Matrix<vcplx> > &subgroup,
 | 
			
		||||
                      Lattice<iGroupMatrix<vcplx> > &dest, int su2_index) {
 | 
			
		||||
  GridBase *grid(dest.Grid());
 | 
			
		||||
  conformable(subgroup, dest);
 | 
			
		||||
  int i0, i1;
 | 
			
		||||
  su2SubGroupIndex(i0, i1, su2_index);
 | 
			
		||||
 | 
			
		||||
  dest = 1.0;  // start out with identity
 | 
			
		||||
  autoView(dest_v, dest, AcceleratorWrite);
 | 
			
		||||
  autoView(subgroup_v, subgroup, AcceleratorRead);
 | 
			
		||||
  accelerator_for(ss, grid->oSites(), 1, {
 | 
			
		||||
    dest_v[ss]()()(i0, i0) = subgroup_v[ss]()()(0, 0);
 | 
			
		||||
    dest_v[ss]()()(i0, i1) = subgroup_v[ss]()()(0, 1);
 | 
			
		||||
    dest_v[ss]()()(i1, i0) = subgroup_v[ss]()()(1, 0);
 | 
			
		||||
    dest_v[ss]()()(i1, i1) = subgroup_v[ss]()()(1, 1);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////
 | 
			
		||||
// Generate e^{ Re Tr Staple Link} dlink
 | 
			
		||||
//
 | 
			
		||||
// *** Note Staple should be appropriate linear compbination between all
 | 
			
		||||
// staples.
 | 
			
		||||
// *** If already by beta pass coefficient 1.0.
 | 
			
		||||
// *** This routine applies the additional 1/Nc factor that comes after trace
 | 
			
		||||
// in action.
 | 
			
		||||
//
 | 
			
		||||
///////////////////////////////////////////////
 | 
			
		||||
template <ONLY_IF_SU>
 | 
			
		||||
static void SubGroupHeatBath(
 | 
			
		||||
    GridSerialRNG &sRNG, GridParallelRNG &pRNG,
 | 
			
		||||
    RealD beta,  // coeff multiplying staple in action (with no 1/Nc)
 | 
			
		||||
    LatticeMatrix &link,
 | 
			
		||||
    const LatticeMatrix &barestaple,  // multiplied by action coeffs so th
 | 
			
		||||
    int su2_subgroup, int nheatbath, LatticeInteger &wheremask) {
 | 
			
		||||
  GridBase *grid = link.Grid();
 | 
			
		||||
 | 
			
		||||
  const RealD twopi = 2.0 * M_PI;
 | 
			
		||||
 | 
			
		||||
  LatticeMatrix staple(grid);
 | 
			
		||||
 | 
			
		||||
  staple = barestaple * (beta / ncolour);
 | 
			
		||||
 | 
			
		||||
  LatticeMatrix V(grid);
 | 
			
		||||
  V = link * staple;
 | 
			
		||||
 | 
			
		||||
  // Subgroup manipulation in the lie algebra space
 | 
			
		||||
  LatticeSU2Matrix u(
 | 
			
		||||
      grid);  // Kennedy pendleton "u" real projected normalised Sigma
 | 
			
		||||
  LatticeSU2Matrix uinv(grid);
 | 
			
		||||
  LatticeSU2Matrix ua(grid);  // a in pauli form
 | 
			
		||||
  LatticeSU2Matrix b(grid);   // rotated matrix after hb
 | 
			
		||||
 | 
			
		||||
  // Some handy constant fields
 | 
			
		||||
  LatticeComplex ones(grid);
 | 
			
		||||
  ones = 1.0;
 | 
			
		||||
  LatticeComplex zeros(grid);
 | 
			
		||||
  zeros = Zero();
 | 
			
		||||
  LatticeReal rones(grid);
 | 
			
		||||
  rones = 1.0;
 | 
			
		||||
  LatticeReal rzeros(grid);
 | 
			
		||||
  rzeros = Zero();
 | 
			
		||||
  LatticeComplex udet(grid);  // determinant of real(staple)
 | 
			
		||||
  LatticeInteger mask_true(grid);
 | 
			
		||||
  mask_true = 1;
 | 
			
		||||
  LatticeInteger mask_false(grid);
 | 
			
		||||
  mask_false = 0;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
    PLB 156 P393 (1985) (Kennedy and Pendleton)
 | 
			
		||||
 | 
			
		||||
    Note: absorb "beta" into the def of sigma compared to KP paper; staple
 | 
			
		||||
    passed to this routine has "beta" already multiplied in
 | 
			
		||||
 | 
			
		||||
    Action linear in links h and of form:
 | 
			
		||||
 | 
			
		||||
    beta S = beta  Sum_p (1 - 1/Nc Re Tr Plaq )
 | 
			
		||||
 | 
			
		||||
    Writing Sigma = 1/Nc (beta Sigma') where sum over staples is "Sigma' "
 | 
			
		||||
 | 
			
		||||
    beta S = const - beta/Nc Re Tr h Sigma'
 | 
			
		||||
    = const - Re Tr h Sigma
 | 
			
		||||
 | 
			
		||||
    Decompose h and Sigma into (1, sigma_j) ; h_i real, h^2=1, Sigma_i complex
 | 
			
		||||
    arbitrary.
 | 
			
		||||
 | 
			
		||||
    Tr h Sigma = h_i Sigma_j Tr (sigma_i sigma_j)  = h_i Sigma_j 2 delta_ij
 | 
			
		||||
    Re Tr h Sigma = 2 h_j Re Sigma_j
 | 
			
		||||
 | 
			
		||||
    Normalised re Sigma_j = xi u_j
 | 
			
		||||
 | 
			
		||||
    With u_j a unit vector and U can be in SU(2);
 | 
			
		||||
 | 
			
		||||
    Re Tr h Sigma = 2 h_j Re Sigma_j = 2 xi (h.u)
 | 
			
		||||
 | 
			
		||||
    4xi^2 = Det [ Sig - Sig^dag  + 1 Tr Sigdag]
 | 
			
		||||
    u   = 1/2xi [ Sig - Sig^dag  + 1 Tr Sigdag]
 | 
			
		||||
 | 
			
		||||
    xi = sqrt(Det)/2;
 | 
			
		||||
 | 
			
		||||
    Write a= u h in SU(2); a has pauli decomp a_j;
 | 
			
		||||
 | 
			
		||||
    Note: Product b' xi is unvariant because scaling Sigma leaves
 | 
			
		||||
    normalised vector "u" fixed; Can rescale Sigma so b' = 1.
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////////////////////////
 | 
			
		||||
  // Real part of Pauli decomposition
 | 
			
		||||
  // Note a subgroup can project to zero in cold start
 | 
			
		||||
  ////////////////////////////////////////////////////////
 | 
			
		||||
  su2Extract(udet, u, V, su2_subgroup);
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////
 | 
			
		||||
  // Normalising this vector if possible; else identity
 | 
			
		||||
  //////////////////////////////////////////////////////
 | 
			
		||||
  LatticeComplex xi(grid);
 | 
			
		||||
 | 
			
		||||
  LatticeSU2Matrix lident(grid);
 | 
			
		||||
 | 
			
		||||
  SU2Matrix ident = Complex(1.0);
 | 
			
		||||
  SU2Matrix pauli1;
 | 
			
		||||
  GaugeGroup<2, GroupName::SU>::generator(0, pauli1);
 | 
			
		||||
  SU2Matrix pauli2;
 | 
			
		||||
  GaugeGroup<2, GroupName::SU>::generator(1, pauli2);
 | 
			
		||||
  SU2Matrix pauli3;
 | 
			
		||||
  GaugeGroup<2, GroupName::SU>::generator(2, pauli3);
 | 
			
		||||
  pauli1 = timesI(pauli1) * 2.0;
 | 
			
		||||
  pauli2 = timesI(pauli2) * 2.0;
 | 
			
		||||
  pauli3 = timesI(pauli3) * 2.0;
 | 
			
		||||
 | 
			
		||||
  LatticeComplex cone(grid);
 | 
			
		||||
  LatticeReal adet(grid);
 | 
			
		||||
  adet = abs(toReal(udet));
 | 
			
		||||
  lident = Complex(1.0);
 | 
			
		||||
  cone = Complex(1.0);
 | 
			
		||||
  Real machine_epsilon = 1.0e-7;
 | 
			
		||||
  u = where(adet > machine_epsilon, u, lident);
 | 
			
		||||
  udet = where(adet > machine_epsilon, udet, cone);
 | 
			
		||||
 | 
			
		||||
  xi = 0.5 * sqrt(udet);        // 4xi^2 = Det [ Sig - Sig^dag  + 1 Tr Sigdag]
 | 
			
		||||
  u = 0.5 * u * pow(xi, -1.0);  //  u   = 1/2xi [ Sig - Sig^dag  + 1 Tr Sigdag]
 | 
			
		||||
 | 
			
		||||
  // Debug test for sanity
 | 
			
		||||
  uinv = adj(u);
 | 
			
		||||
  b = u * uinv - 1.0;
 | 
			
		||||
  assert(norm2(b) < 1.0e-4);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
    Measure: Haar measure dh has d^4a delta(1-|a^2|)
 | 
			
		||||
    In polars:
 | 
			
		||||
    da = da0 r^2 sin theta dr dtheta dphi delta( 1 - r^2 -a0^2)
 | 
			
		||||
    = da0 r^2 sin theta dr dtheta dphi delta( (sqrt(1-a0^) - r)(sqrt(1-a0^) +
 | 
			
		||||
    r) )
 | 
			
		||||
    = da0 r/2 sin theta dr dtheta dphi delta( (sqrt(1-a0^) - r) )
 | 
			
		||||
 | 
			
		||||
    Action factor Q(h) dh  = e^-S[h]  dh =  e^{  xi Tr uh} dh    // beta
 | 
			
		||||
    enters through xi =  e^{2 xi (h.u)} dh =  e^{2 xi h0u0}.e^{2 xi h1u1}.e^{2
 | 
			
		||||
    xi h2u2}.e^{2 xi h3u3} dh
 | 
			
		||||
 | 
			
		||||
    Therefore for each site, take xi for that site
 | 
			
		||||
    i) generate  |a0|<1 with dist
 | 
			
		||||
    (1-a0^2)^0.5 e^{2 xi a0 } da0
 | 
			
		||||
 | 
			
		||||
    Take alpha = 2 xi  = 2 xi [ recall 2 beta/Nc unmod staple norm];
 | 
			
		||||
    hence 2.0/Nc factor in Chroma ] A. Generate two uniformly distributed
 | 
			
		||||
    pseudo-random numbers R and R', R'', R''' in the unit interval; B. Set X =
 | 
			
		||||
    -(ln R)/alpha, X' =-(ln R')/alpha; C. Set C = cos^2(2pi R"), with R"
 | 
			
		||||
    another uniform random number in [0,1] ; D. Set A = XC; E. Let d  = X'+A;
 | 
			
		||||
    F. If R'''^2 :> 1 - 0.5 d,  go back to A;
 | 
			
		||||
    G. Set a0 = 1 - d;
 | 
			
		||||
 | 
			
		||||
    Note that in step D setting B ~ X - A and using B in place of A in step E
 | 
			
		||||
    will generate a second independent a 0 value.
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////////
 | 
			
		||||
  // count the number of sites by picking "1"'s out of hat
 | 
			
		||||
  /////////////////////////////////////////////////////////
 | 
			
		||||
  Integer hit = 0;
 | 
			
		||||
  LatticeReal rtmp(grid);
 | 
			
		||||
  rtmp = where(wheremask, rones, rzeros);
 | 
			
		||||
  RealD numSites = sum(rtmp);
 | 
			
		||||
  RealD numAccepted;
 | 
			
		||||
  LatticeInteger Accepted(grid);
 | 
			
		||||
  Accepted = Zero();
 | 
			
		||||
  LatticeInteger newlyAccepted(grid);
 | 
			
		||||
 | 
			
		||||
  std::vector<LatticeReal> xr(4, grid);
 | 
			
		||||
  std::vector<LatticeReal> a(4, grid);
 | 
			
		||||
  LatticeReal d(grid);
 | 
			
		||||
  d = Zero();
 | 
			
		||||
  LatticeReal alpha(grid);
 | 
			
		||||
 | 
			
		||||
  //    std::cout<<GridLogMessage<<"xi "<<xi <<std::endl;
 | 
			
		||||
  xi = 2.0 * xi;
 | 
			
		||||
  alpha = toReal(xi);
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
    // A. Generate two uniformly distributed pseudo-random numbers R and R',
 | 
			
		||||
    // R'', R''' in the unit interval;
 | 
			
		||||
    random(pRNG, xr[0]);
 | 
			
		||||
    random(pRNG, xr[1]);
 | 
			
		||||
    random(pRNG, xr[2]);
 | 
			
		||||
    random(pRNG, xr[3]);
 | 
			
		||||
 | 
			
		||||
    // B. Set X = - ln R/alpha, X' = -ln R'/alpha
 | 
			
		||||
    xr[1] = -log(xr[1]) / alpha;
 | 
			
		||||
    xr[2] = -log(xr[2]) / alpha;
 | 
			
		||||
 | 
			
		||||
    // C. Set C = cos^2(2piR'')
 | 
			
		||||
    xr[3] = cos(xr[3] * twopi);
 | 
			
		||||
    xr[3] = xr[3] * xr[3];
 | 
			
		||||
 | 
			
		||||
    LatticeReal xrsq(grid);
 | 
			
		||||
 | 
			
		||||
    // D. Set A = XC;
 | 
			
		||||
    // E. Let d  = X'+A;
 | 
			
		||||
    xrsq = xr[2] + xr[1] * xr[3];
 | 
			
		||||
 | 
			
		||||
    d = where(Accepted, d, xr[2] + xr[1] * xr[3]);
 | 
			
		||||
 | 
			
		||||
    // F. If R'''^2 :> 1 - 0.5 d,  go back to A;
 | 
			
		||||
    LatticeReal thresh(grid);
 | 
			
		||||
    thresh = 1.0 - d * 0.5;
 | 
			
		||||
    xrsq = xr[0] * xr[0];
 | 
			
		||||
    LatticeInteger ione(grid);
 | 
			
		||||
    ione = 1;
 | 
			
		||||
    LatticeInteger izero(grid);
 | 
			
		||||
    izero = Zero();
 | 
			
		||||
 | 
			
		||||
    newlyAccepted = where(xrsq < thresh, ione, izero);
 | 
			
		||||
    Accepted = where(newlyAccepted, newlyAccepted, Accepted);
 | 
			
		||||
    Accepted = where(wheremask, Accepted, izero);
 | 
			
		||||
 | 
			
		||||
    // FIXME need an iSum for integer to avoid overload on return type??
 | 
			
		||||
    rtmp = where(Accepted, rones, rzeros);
 | 
			
		||||
    numAccepted = sum(rtmp);
 | 
			
		||||
 | 
			
		||||
    hit++;
 | 
			
		||||
 | 
			
		||||
  } while ((numAccepted < numSites) && (hit < nheatbath));
 | 
			
		||||
 | 
			
		||||
  // G. Set a0 = 1 - d;
 | 
			
		||||
  a[0] = Zero();
 | 
			
		||||
  a[0] = where(wheremask, 1.0 - d, a[0]);
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////
 | 
			
		||||
  //    ii) generate a_i uniform on two sphere radius (1-a0^2)^0.5
 | 
			
		||||
  //////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  LatticeReal a123mag(grid);
 | 
			
		||||
  a123mag = sqrt(abs(1.0 - a[0] * a[0]));
 | 
			
		||||
 | 
			
		||||
  LatticeReal cos_theta(grid);
 | 
			
		||||
  LatticeReal sin_theta(grid);
 | 
			
		||||
  LatticeReal phi(grid);
 | 
			
		||||
 | 
			
		||||
  random(pRNG, phi);
 | 
			
		||||
  phi = phi * twopi;  // uniform in [0,2pi]
 | 
			
		||||
  random(pRNG, cos_theta);
 | 
			
		||||
  cos_theta = (cos_theta * 2.0) - 1.0;  // uniform in [-1,1]
 | 
			
		||||
  sin_theta = sqrt(abs(1.0 - cos_theta * cos_theta));
 | 
			
		||||
 | 
			
		||||
  a[1] = a123mag * sin_theta * cos(phi);
 | 
			
		||||
  a[2] = a123mag * sin_theta * sin(phi);
 | 
			
		||||
  a[3] = a123mag * cos_theta;
 | 
			
		||||
 | 
			
		||||
  ua = toComplex(a[0]) * ident + toComplex(a[1]) * pauli1 +
 | 
			
		||||
       toComplex(a[2]) * pauli2 + toComplex(a[3]) * pauli3;
 | 
			
		||||
 | 
			
		||||
  b = 1.0;
 | 
			
		||||
  b = where(wheremask, uinv * ua, b);
 | 
			
		||||
  su2Insert(b, V, su2_subgroup);
 | 
			
		||||
 | 
			
		||||
  // mask the assignment back based on Accptance
 | 
			
		||||
  link = where(Accepted, V * link, link);
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////
 | 
			
		||||
  // Debug Checks
 | 
			
		||||
  // SU2 check
 | 
			
		||||
  LatticeSU2Matrix check(grid);  // rotated matrix after hb
 | 
			
		||||
  u = Zero();
 | 
			
		||||
  check = ua * adj(ua) - 1.0;
 | 
			
		||||
  check = where(Accepted, check, u);
 | 
			
		||||
  assert(norm2(check) < 1.0e-4);
 | 
			
		||||
 | 
			
		||||
  check = b * adj(b) - 1.0;
 | 
			
		||||
  check = where(Accepted, check, u);
 | 
			
		||||
  assert(norm2(check) < 1.0e-4);
 | 
			
		||||
 | 
			
		||||
  LatticeMatrix Vcheck(grid);
 | 
			
		||||
  Vcheck = Zero();
 | 
			
		||||
  Vcheck = where(Accepted, V * adj(V) - 1.0, Vcheck);
 | 
			
		||||
  //    std::cout<<GridLogMessage << "SU3 check " <<norm2(Vcheck)<<std::endl;
 | 
			
		||||
  assert(norm2(Vcheck) < 1.0e-4);
 | 
			
		||||
 | 
			
		||||
  // Verify the link stays in SU(3)
 | 
			
		||||
  //    std::cout<<GridLogMessage <<"Checking the modified link"<<std::endl;
 | 
			
		||||
  Vcheck = link * adj(link) - 1.0;
 | 
			
		||||
  assert(norm2(Vcheck) < 1.0e-4);
 | 
			
		||||
  /////////////////////////////////
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <ONLY_IF_SU>
 | 
			
		||||
static void testGenerators(GroupName::SU) {
 | 
			
		||||
  Matrix ta;
 | 
			
		||||
  Matrix tb;
 | 
			
		||||
  std::cout << GridLogMessage
 | 
			
		||||
            << "Fundamental - Checking trace ta tb is 0.5 delta_ab"
 | 
			
		||||
            << std::endl;
 | 
			
		||||
  for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
    for (int b = 0; b < AdjointDimension; b++) {
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
      generator(b, tb);
 | 
			
		||||
      Complex tr = TensorRemove(trace(ta * tb));
 | 
			
		||||
      std::cout << GridLogMessage << "(" << a << "," << b << ") =  " << tr
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      if (a == b) assert(abs(tr - Complex(0.5)) < 1.0e-6);
 | 
			
		||||
      if (a != b) assert(abs(tr) < 1.0e-6);
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
  std::cout << GridLogMessage << "Fundamental - Checking if hermitian"
 | 
			
		||||
            << std::endl;
 | 
			
		||||
  for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
    generator(a, ta);
 | 
			
		||||
    std::cout << GridLogMessage << a << std::endl;
 | 
			
		||||
    assert(norm2(ta - adj(ta)) < 1.0e-6);
 | 
			
		||||
  }
 | 
			
		||||
  std::cout << GridLogMessage << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::cout << GridLogMessage << "Fundamental - Checking if traceless"
 | 
			
		||||
            << std::endl;
 | 
			
		||||
  for (int a = 0; a < AdjointDimension; a++) {
 | 
			
		||||
    generator(a, ta);
 | 
			
		||||
    Complex tr = TensorRemove(trace(ta));
 | 
			
		||||
    std::cout << GridLogMessage << a << " " << std::endl;
 | 
			
		||||
    assert(abs(tr) < 1.0e-6);
 | 
			
		||||
  }
 | 
			
		||||
  std::cout << GridLogMessage << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <int N, class vtype>
 | 
			
		||||
static Lattice<iScalar<iScalar<iMatrix<vtype, N> > > >
 | 
			
		||||
ProjectOnGeneralGroup(const Lattice<iScalar<iScalar<iMatrix<vtype, N> > > > &Umu, GroupName::SU) {
 | 
			
		||||
  return ProjectOnGroup(Umu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class vtype>
 | 
			
		||||
accelerator_inline static iScalar<vtype> ProjectOnGeneralGroup(const iScalar<vtype> &r, GroupName::SU) {
 | 
			
		||||
  return ProjectOnGroup(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class vtype, int N>
 | 
			
		||||
accelerator_inline static iVector<vtype,N> ProjectOnGeneralGroup(const iVector<vtype,N> &r, GroupName::SU) {
 | 
			
		||||
  return ProjectOnGroup(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class vtype,int N, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0 >::type * =nullptr>
 | 
			
		||||
accelerator_inline static iMatrix<vtype,N> ProjectOnGeneralGroup(const iMatrix<vtype,N> &arg, GroupName::SU) {
 | 
			
		||||
  return ProjectOnGroup(arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename LatticeMatrixType>
 | 
			
		||||
static void taProj(const LatticeMatrixType &in, LatticeMatrixType &out, GroupName::SU) {
 | 
			
		||||
  out = Ta(in);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Fundamental rep gauge xform
 | 
			
		||||
 */
 | 
			
		||||
template<typename Fundamental,typename GaugeMat>
 | 
			
		||||
static void GaugeTransformFundamental( Fundamental &ferm, GaugeMat &g){
 | 
			
		||||
  GridBase *grid = ferm._grid;
 | 
			
		||||
  conformable(grid,g._grid);
 | 
			
		||||
  ferm = g*ferm;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Adjoint rep gauge xform
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
template<typename Gimpl>
 | 
			
		||||
static void GaugeTransform(typename Gimpl::GaugeField &Umu, typename Gimpl::GaugeLinkField &g){
 | 
			
		||||
  GridBase *grid = Umu.Grid();
 | 
			
		||||
  conformable(grid,g.Grid());
 | 
			
		||||
 | 
			
		||||
  typename Gimpl::GaugeLinkField U(grid);
 | 
			
		||||
  typename Gimpl::GaugeLinkField ag(grid); ag = adj(g);
 | 
			
		||||
 | 
			
		||||
  for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
    U= PeekIndex<LorentzIndex>(Umu,mu);
 | 
			
		||||
    U = g*U*Gimpl::CshiftLink(ag, mu, 1); //BC-aware
 | 
			
		||||
    PokeIndex<LorentzIndex>(Umu,U,mu);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
template<typename Gimpl>
 | 
			
		||||
static void GaugeTransform( std::vector<typename Gimpl::GaugeLinkField> &U, typename Gimpl::GaugeLinkField &g){
 | 
			
		||||
  GridBase *grid = g.Grid();
 | 
			
		||||
  typename Gimpl::GaugeLinkField ag(grid); ag = adj(g);
 | 
			
		||||
  for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
    U[mu] = g*U[mu]*Gimpl::CshiftLink(ag, mu, 1); //BC-aware
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
template<typename Gimpl>
 | 
			
		||||
static void RandomGaugeTransform(GridParallelRNG &pRNG, typename Gimpl::GaugeField &Umu, typename Gimpl::GaugeLinkField &g){
 | 
			
		||||
  LieRandomize(pRNG,g,1.0);
 | 
			
		||||
  GaugeTransform<Gimpl>(Umu,g);
 | 
			
		||||
}
 | 
			
		||||
@@ -51,6 +51,10 @@ public:
 | 
			
		||||
  typedef Lattice<iVector<iScalar<iMatrix<vComplexF, Dimension> >, Nd> > LatticeAdjFieldF;
 | 
			
		||||
  typedef Lattice<iVector<iScalar<iMatrix<vComplexD, Dimension> >, Nd> > LatticeAdjFieldD;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iSUnMatrix = iScalar<iScalar<iMatrix<vtype, ncolour> > >;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<iScalar<iScalar<iVector<vComplex, Dimension> > > >  LatticeAdjVector;
 | 
			
		||||
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
@@ -58,8 +62,8 @@ public:
 | 
			
		||||
    // returns i(T_Adj)^index necessary for the projectors
 | 
			
		||||
    // see definitions above
 | 
			
		||||
    iAdjTa = Zero();
 | 
			
		||||
    Vector<typename SU<ncolour>::template iSUnMatrix<cplx> > ta(ncolour * ncolour - 1);
 | 
			
		||||
    typename SU<ncolour>::template iSUnMatrix<cplx> tmp;
 | 
			
		||||
    Vector<iSUnMatrix<cplx> > ta(ncolour * ncolour - 1);
 | 
			
		||||
    iSUnMatrix<cplx> tmp;
 | 
			
		||||
 | 
			
		||||
    // FIXME not very efficient to get all the generators everytime
 | 
			
		||||
    for (int a = 0; a < Dimension; a++) SU<ncolour>::generator(a, ta[a]);
 | 
			
		||||
@@ -67,8 +71,7 @@ public:
 | 
			
		||||
    for (int a = 0; a < Dimension; a++) {
 | 
			
		||||
      tmp = ta[a] * ta[Index] - ta[Index] * ta[a];
 | 
			
		||||
      for (int b = 0; b < (ncolour * ncolour - 1); b++) {
 | 
			
		||||
        typename SU<ncolour>::template iSUnMatrix<cplx> tmp1 =
 | 
			
		||||
	  2.0 * tmp * ta[b];  // 2.0 from the normalization
 | 
			
		||||
        iSUnMatrix<cplx> tmp1 = 2.0 * tmp * ta[b];  // 2.0 from the normalization
 | 
			
		||||
        Complex iTr = TensorRemove(timesI(trace(tmp1)));
 | 
			
		||||
        //iAdjTa()()(b, a) = iTr;
 | 
			
		||||
        iAdjTa()()(a, b) = iTr;
 | 
			
		||||
@@ -134,8 +137,7 @@ public:
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < Dimension; a++) {
 | 
			
		||||
      generator(a, iTa);
 | 
			
		||||
      LatticeComplex tmp = real(trace(iTa * in)) * coefficient;
 | 
			
		||||
      pokeColour(h_out, tmp, a);
 | 
			
		||||
      pokeColour(h_out, real(trace(iTa * in)) * coefficient, a);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,273 +0,0 @@
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// * Two index representation generators
 | 
			
		||||
//
 | 
			
		||||
// * Normalisation for the fundamental generators:
 | 
			
		||||
//   trace ta tb = 1/2 delta_ab = T_F delta_ab
 | 
			
		||||
//   T_F = 1/2  for SU(N) groups
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
//   base for NxN two index (anti-symmetric) matrices
 | 
			
		||||
//   normalized to 1 (d_ij is the kroenecker delta)
 | 
			
		||||
//
 | 
			
		||||
//   (e^(ij)_{kl} = 1 / sqrt(2) (d_ik d_jl +/- d_jk d_il)
 | 
			
		||||
//
 | 
			
		||||
//   Then the generators are written as
 | 
			
		||||
//
 | 
			
		||||
//   (iT_a)^(ij)(lk) = i * ( tr[e^(ij)^dag e^(lk) T^trasp_a] +
 | 
			
		||||
//   tr[e^(lk)e^(ij)^dag T_a] )  //
 | 
			
		||||
//   
 | 
			
		||||
//
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
// Authors: David Preti, Guido Cossu
 | 
			
		||||
 | 
			
		||||
#ifndef QCD_UTIL_SUN2INDEX_H
 | 
			
		||||
#define QCD_UTIL_SUN2INDEX_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
enum TwoIndexSymmetry { Symmetric = 1, AntiSymmetric = -1 };
 | 
			
		||||
 | 
			
		||||
inline Real delta(int a, int b) { return (a == b) ? 1.0 : 0.0; }
 | 
			
		||||
 | 
			
		||||
template <int ncolour, TwoIndexSymmetry S>
 | 
			
		||||
class SU_TwoIndex : public SU<ncolour> {
 | 
			
		||||
public:
 | 
			
		||||
  static const int Dimension = ncolour * (ncolour + S) / 2;
 | 
			
		||||
  static const int NumGenerators = SU<ncolour>::AdjointDimension;
 | 
			
		||||
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iSUnTwoIndexMatrix = iScalar<iScalar<iMatrix<vtype, Dimension> > >;
 | 
			
		||||
 | 
			
		||||
  typedef iSUnTwoIndexMatrix<Complex> TIMatrix;
 | 
			
		||||
  typedef iSUnTwoIndexMatrix<ComplexF> TIMatrixF;
 | 
			
		||||
  typedef iSUnTwoIndexMatrix<ComplexD> TIMatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef iSUnTwoIndexMatrix<vComplex> vTIMatrix;
 | 
			
		||||
  typedef iSUnTwoIndexMatrix<vComplexF> vTIMatrixF;
 | 
			
		||||
  typedef iSUnTwoIndexMatrix<vComplexD> vTIMatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<vTIMatrix> LatticeTwoIndexMatrix;
 | 
			
		||||
  typedef Lattice<vTIMatrixF> LatticeTwoIndexMatrixF;
 | 
			
		||||
  typedef Lattice<vTIMatrixD> LatticeTwoIndexMatrixD;
 | 
			
		||||
 | 
			
		||||
  typedef Lattice<iVector<iScalar<iMatrix<vComplex, Dimension> >, Nd> >
 | 
			
		||||
  LatticeTwoIndexField;
 | 
			
		||||
  typedef Lattice<iVector<iScalar<iMatrix<vComplexF, Dimension> >, Nd> >
 | 
			
		||||
  LatticeTwoIndexFieldF;
 | 
			
		||||
  typedef Lattice<iVector<iScalar<iMatrix<vComplexD, Dimension> >, Nd> >
 | 
			
		||||
  LatticeTwoIndexFieldD;
 | 
			
		||||
 | 
			
		||||
  template <typename vtype>
 | 
			
		||||
  using iSUnMatrix = iScalar<iScalar<iMatrix<vtype, ncolour> > >;
 | 
			
		||||
 | 
			
		||||
  typedef iSUnMatrix<Complex> Matrix;
 | 
			
		||||
  typedef iSUnMatrix<ComplexF> MatrixF;
 | 
			
		||||
  typedef iSUnMatrix<ComplexD> MatrixD;
 | 
			
		||||
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void base(int Index, iSUnMatrix<cplx> &eij) {
 | 
			
		||||
    // returns (e)^(ij)_{kl} necessary for change of base U_F -> U_R
 | 
			
		||||
    assert(Index < NumGenerators);
 | 
			
		||||
    eij = Zero();
 | 
			
		||||
 | 
			
		||||
    // for the linearisation of the 2 indexes 
 | 
			
		||||
    static int a[ncolour * (ncolour - 1) / 2][2]; // store the a <-> i,j
 | 
			
		||||
    static bool filled = false;
 | 
			
		||||
    if (!filled) {
 | 
			
		||||
      int counter = 0;
 | 
			
		||||
      for (int i = 1; i < ncolour; i++) {
 | 
			
		||||
        for (int j = 0; j < i; j++) {
 | 
			
		||||
          a[counter][0] = i;
 | 
			
		||||
          a[counter][1] = j;
 | 
			
		||||
          counter++;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      filled = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Index < ncolour * (ncolour - 1) / 2) {
 | 
			
		||||
      baseOffDiagonal(a[Index][0], a[Index][1], eij);
 | 
			
		||||
    } else {
 | 
			
		||||
      baseDiagonal(Index, eij);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void baseDiagonal(int Index, iSUnMatrix<cplx> &eij) {
 | 
			
		||||
    eij = Zero();
 | 
			
		||||
    eij()()(Index - ncolour * (ncolour - 1) / 2,
 | 
			
		||||
            Index - ncolour * (ncolour - 1) / 2) = 1.0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void baseOffDiagonal(int i, int j, iSUnMatrix<cplx> &eij) {
 | 
			
		||||
    eij = Zero();
 | 
			
		||||
    for (int k = 0; k < ncolour; k++)
 | 
			
		||||
      for (int l = 0; l < ncolour; l++)
 | 
			
		||||
        eij()()(l, k) = delta(i, k) * delta(j, l) +
 | 
			
		||||
	  S * delta(j, k) * delta(i, l);
 | 
			
		||||
 | 
			
		||||
    RealD nrm = 1. / std::sqrt(2.0);
 | 
			
		||||
    eij = eij * nrm;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void printBase(void) {
 | 
			
		||||
    for (int gen = 0; gen < Dimension; gen++) {
 | 
			
		||||
      Matrix tmp;
 | 
			
		||||
      base(gen, tmp);
 | 
			
		||||
      std::cout << GridLogMessage << "Nc = " << ncolour << " t_" << gen
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << tmp << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class cplx>
 | 
			
		||||
  static void generator(int Index, iSUnTwoIndexMatrix<cplx> &i2indTa) {
 | 
			
		||||
    Vector<typename SU<ncolour>::template iSUnMatrix<cplx> > ta(
 | 
			
		||||
								ncolour * ncolour - 1);
 | 
			
		||||
    Vector<typename SU<ncolour>::template iSUnMatrix<cplx> > eij(Dimension);
 | 
			
		||||
    typename SU<ncolour>::template iSUnMatrix<cplx> tmp;
 | 
			
		||||
    i2indTa = Zero();
 | 
			
		||||
    
 | 
			
		||||
    for (int a = 0; a < ncolour * ncolour - 1; a++)
 | 
			
		||||
      SU<ncolour>::generator(a, ta[a]);
 | 
			
		||||
    
 | 
			
		||||
    for (int a = 0; a < Dimension; a++) base(a, eij[a]);
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < Dimension; a++) {
 | 
			
		||||
      tmp = transpose(ta[Index]) * adj(eij[a]) + adj(eij[a]) * ta[Index];
 | 
			
		||||
      for (int b = 0; b < Dimension; b++) {
 | 
			
		||||
        typename SU<ncolour>::template iSUnMatrix<cplx> tmp1 =
 | 
			
		||||
	  tmp * eij[b]; 
 | 
			
		||||
        Complex iTr = TensorRemove(timesI(trace(tmp1)));
 | 
			
		||||
        i2indTa()()(a, b) = iTr;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void printGenerators(void) {
 | 
			
		||||
    for (int gen = 0; gen < ncolour * ncolour - 1; gen++) {
 | 
			
		||||
      TIMatrix i2indTa;
 | 
			
		||||
      generator(gen, i2indTa);
 | 
			
		||||
      std::cout << GridLogMessage << "Nc = " << ncolour << " t_" << gen
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << i2indTa << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void testGenerators(void) {
 | 
			
		||||
    TIMatrix i2indTa, i2indTb;
 | 
			
		||||
    std::cout << GridLogMessage << "2IndexRep - Checking if traceless"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < ncolour * ncolour - 1; a++) {
 | 
			
		||||
      generator(a, i2indTa);
 | 
			
		||||
      std::cout << GridLogMessage << a << std::endl;
 | 
			
		||||
      assert(norm2(trace(i2indTa)) < 1.0e-6);
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "2IndexRep - Checking if antihermitean"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < ncolour * ncolour - 1; a++) {
 | 
			
		||||
      generator(a, i2indTa);
 | 
			
		||||
      std::cout << GridLogMessage << a << std::endl;
 | 
			
		||||
      assert(norm2(adj(i2indTa) + i2indTa) < 1.0e-6);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
    std::cout << GridLogMessage
 | 
			
		||||
              << "2IndexRep - Checking Tr[Ta*Tb]=delta(a,b)*(N +- 2)/2"
 | 
			
		||||
              << std::endl;
 | 
			
		||||
    for (int a = 0; a < ncolour * ncolour - 1; a++) {
 | 
			
		||||
      for (int b = 0; b < ncolour * ncolour - 1; b++) {
 | 
			
		||||
        generator(a, i2indTa);
 | 
			
		||||
        generator(b, i2indTb);
 | 
			
		||||
 | 
			
		||||
        // generator returns iTa, so we need a minus sign here
 | 
			
		||||
        Complex Tr = -TensorRemove(trace(i2indTa * i2indTb));
 | 
			
		||||
        std::cout << GridLogMessage << "a=" << a << "b=" << b << "Tr=" << Tr
 | 
			
		||||
                  << std::endl;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << GridLogMessage << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void TwoIndexLieAlgebraMatrix(
 | 
			
		||||
				       const typename SU<ncolour>::LatticeAlgebraVector &h,
 | 
			
		||||
				       LatticeTwoIndexMatrix &out, Real scale = 1.0) {
 | 
			
		||||
    conformable(h, out);
 | 
			
		||||
    GridBase *grid = out.Grid();
 | 
			
		||||
    LatticeTwoIndexMatrix la(grid);
 | 
			
		||||
    TIMatrix i2indTa;
 | 
			
		||||
 | 
			
		||||
    out = Zero();
 | 
			
		||||
    for (int a = 0; a < ncolour * ncolour - 1; a++) {
 | 
			
		||||
      generator(a, i2indTa);
 | 
			
		||||
      la = peekColour(h, a) * i2indTa;
 | 
			
		||||
      out += la;
 | 
			
		||||
    }
 | 
			
		||||
    out *= scale;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Projects the algebra components 
 | 
			
		||||
  // of a lattice matrix ( of dimension ncol*ncol -1 )
 | 
			
		||||
  static void projectOnAlgebra(
 | 
			
		||||
			       typename SU<ncolour>::LatticeAlgebraVector &h_out,
 | 
			
		||||
			       const LatticeTwoIndexMatrix &in, Real scale = 1.0) {
 | 
			
		||||
    conformable(h_out, in);
 | 
			
		||||
    h_out = Zero();
 | 
			
		||||
    TIMatrix i2indTa;
 | 
			
		||||
    Real coefficient = -2.0 / (ncolour + 2 * S) * scale;
 | 
			
		||||
    // 2/(Nc +/- 2) for the normalization of the trace in the two index rep
 | 
			
		||||
    for (int a = 0; a < ncolour * ncolour - 1; a++) {
 | 
			
		||||
      generator(a, i2indTa);
 | 
			
		||||
      auto tmp = real(trace(i2indTa * in)) * coefficient;
 | 
			
		||||
      pokeColour(h_out, tmp, a);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // a projector that keeps the generators stored to avoid the overhead of
 | 
			
		||||
  // recomputing them
 | 
			
		||||
  static void projector(typename SU<ncolour>::LatticeAlgebraVector &h_out,
 | 
			
		||||
                        const LatticeTwoIndexMatrix &in, Real scale = 1.0) {
 | 
			
		||||
    conformable(h_out, in);
 | 
			
		||||
    // to store the generators
 | 
			
		||||
    static std::vector<TIMatrix> i2indTa(ncolour * ncolour -1); 
 | 
			
		||||
    h_out = Zero();
 | 
			
		||||
    static bool precalculated = false;
 | 
			
		||||
    if (!precalculated) {
 | 
			
		||||
      precalculated = true;
 | 
			
		||||
      for (int a = 0; a < ncolour * ncolour - 1; a++) generator(a, i2indTa[a]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Real coefficient =
 | 
			
		||||
      -2.0 / (ncolour + 2 * S) * scale;  // 2/(Nc +/- 2) for the normalization
 | 
			
		||||
    // of the trace in the two index rep
 | 
			
		||||
 | 
			
		||||
    for (int a = 0; a < ncolour * ncolour - 1; a++) {
 | 
			
		||||
      auto tmp = real(trace(i2indTa[a] * in)) * coefficient;
 | 
			
		||||
      pokeColour(h_out, tmp, a);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Some useful type names
 | 
			
		||||
typedef SU_TwoIndex<Nc, Symmetric> TwoIndexSymmMatrices;
 | 
			
		||||
typedef SU_TwoIndex<Nc, AntiSymmetric> TwoIndexAntiSymmMatrices;
 | 
			
		||||
 | 
			
		||||
typedef SU_TwoIndex<2, Symmetric> SU2TwoIndexSymm;
 | 
			
		||||
typedef SU_TwoIndex<3, Symmetric> SU3TwoIndexSymm;
 | 
			
		||||
typedef SU_TwoIndex<4, Symmetric> SU4TwoIndexSymm;
 | 
			
		||||
typedef SU_TwoIndex<5, Symmetric> SU5TwoIndexSymm;
 | 
			
		||||
 | 
			
		||||
typedef SU_TwoIndex<2, AntiSymmetric> SU2TwoIndexAntiSymm;
 | 
			
		||||
typedef SU_TwoIndex<3, AntiSymmetric> SU3TwoIndexAntiSymm;
 | 
			
		||||
typedef SU_TwoIndex<4, AntiSymmetric> SU4TwoIndexAntiSymm;
 | 
			
		||||
typedef SU_TwoIndex<5, AntiSymmetric> SU5TwoIndexAntiSymm;
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										317
									
								
								Grid/qcd/utils/Sp2n.impl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								Grid/qcd/utils/Sp2n.impl.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,317 @@
 | 
			
		||||
// This file is #included into the body of the class template definition of
 | 
			
		||||
// GaugeGroup. So, image there to be
 | 
			
		||||
//
 | 
			
		||||
// template <int ncolour, class group_name>
 | 
			
		||||
// class GaugeGroup {
 | 
			
		||||
//
 | 
			
		||||
// around it.
 | 
			
		||||
//
 | 
			
		||||
// Please note that the unconventional file extension makes sure that it
 | 
			
		||||
// doesn't get found by the scripts/filelist during bootstrapping.
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
template <ONLY_IF_Sp>
 | 
			
		||||
static int su2subgroups(GroupName::Sp) { return (ncolour/2 * (ncolour/2 - 1)) / 2; }
 | 
			
		||||
 | 
			
		||||
// Sp(2N) has N(2N+1) = 2N^2+N generators
 | 
			
		||||
//
 | 
			
		||||
// normalise the generators such that
 | 
			
		||||
// Trace ( Ta Tb) = 1/2 delta_ab
 | 
			
		||||
//
 | 
			
		||||
// N generators in the cartan, 2N^2 off
 | 
			
		||||
// off diagonal:
 | 
			
		||||
//     there are 6 types named a,b,c,d and w,z
 | 
			
		||||
//     abcd are N(N-1)/2 each while wz are N each
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_Sp>
 | 
			
		||||
static void generator(int lieIndex, iGroupMatrix<cplx> &ta, GroupName::Sp) {
 | 
			
		||||
  // map lie index into type of generators: diagonal, abcd type, wz type
 | 
			
		||||
 | 
			
		||||
  const int nsp = ncolour/2;
 | 
			
		||||
  int diagIndex;
 | 
			
		||||
  int aIndex, bIndex, cIndex, dIndex;
 | 
			
		||||
  int wIndex, zIndex;  // a,b,c,d are N(N-1)/2 and w,z are N
 | 
			
		||||
  const int mod = nsp * (nsp - 1) * 0.5;
 | 
			
		||||
  const int offdiag =
 | 
			
		||||
      2 * nsp * nsp;  // number of generators not in the cartan subalgebra
 | 
			
		||||
  const int wmod = 4 * mod;
 | 
			
		||||
  const int zmod = wmod + nsp;
 | 
			
		||||
  if (lieIndex >= offdiag) {
 | 
			
		||||
    diagIndex = lieIndex - offdiag;  // 0, ... ,N-1
 | 
			
		||||
    // std::cout << GridLogMessage << "diag type " << std::endl;
 | 
			
		||||
    generatorDiagtype(diagIndex, ta);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if ((lieIndex >= wmod) && (lieIndex < zmod)) {
 | 
			
		||||
    // std::cout << GridLogMessage << "w type " << std::endl;
 | 
			
		||||
    wIndex = lieIndex - wmod;  // 0, ... ,N-1
 | 
			
		||||
    generatorWtype(wIndex, ta);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if ((lieIndex >= zmod) && (lieIndex < offdiag)) {
 | 
			
		||||
    // std::cout << GridLogMessage << "z type " << std::endl;
 | 
			
		||||
    // std::cout << GridLogMessage << "lie index " << lieIndex << std::endl;
 | 
			
		||||
    // std::cout << GridLogMessage << "z mod " << zmod << std::endl;
 | 
			
		||||
    zIndex = lieIndex - zmod;  // 0, ... ,N-1
 | 
			
		||||
    generatorZtype(zIndex, ta);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (lieIndex < mod) {  // atype 0, ... , N(N-1)/2=mod
 | 
			
		||||
    // std::cout << GridLogMessage << "a type " << std::endl;
 | 
			
		||||
    aIndex = lieIndex;
 | 
			
		||||
    // std::cout << GridLogMessage << "a indx " << aIndex << std::endl;
 | 
			
		||||
    generatorAtype(aIndex, ta);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if ((lieIndex >= mod) && lieIndex < 2 * mod) {  // btype mod, ... , 2mod-1
 | 
			
		||||
    // std::cout << GridLogMessage << "b type " << std::endl;
 | 
			
		||||
    bIndex = lieIndex - mod;
 | 
			
		||||
    generatorBtype(bIndex, ta);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if ((lieIndex >= 2 * mod) &&
 | 
			
		||||
      lieIndex < 3 * mod) {  // ctype 2mod, ... , 3mod-1
 | 
			
		||||
    // std::cout << GridLogMessage << "c type " << std::endl;
 | 
			
		||||
    cIndex = lieIndex - 2 * mod;
 | 
			
		||||
    generatorCtype(cIndex, ta);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if ((lieIndex >= 3 * mod) &&
 | 
			
		||||
      lieIndex < wmod) {  // ctype 3mod, ... , 4mod-1 = wmod-1
 | 
			
		||||
    // std::cout << GridLogMessage << "d type " << std::endl;
 | 
			
		||||
    dIndex = lieIndex - 3 * mod;
 | 
			
		||||
    generatorDtype(dIndex, ta);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}  // end of generator
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_Sp>
 | 
			
		||||
static void generatorDiagtype(int diagIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  // ta(i,i) = - ta(i+N,i+N) = 1/2 for each i index of the cartan subalgebra
 | 
			
		||||
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  RealD nrm = 1.0 / 2;
 | 
			
		||||
 | 
			
		||||
  ta()()(diagIndex, diagIndex) = nrm;
 | 
			
		||||
  ta()()(diagIndex + nsp, diagIndex + nsp) = -nrm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_Sp>
 | 
			
		||||
static void generatorAtype(int aIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  // ta(i,j) = ta(j,i) = -ta(i+N,j+N) = -ta(j+N,i+N) = 1 / 2 sqrt(2)
 | 
			
		||||
  // with i<j and i=0,...,N-2
 | 
			
		||||
  // follows that j=i+1, ... , N
 | 
			
		||||
  int i1, i2;
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  RealD nrm = 1 / (2 * std::sqrt(2));
 | 
			
		||||
 | 
			
		||||
  su2SubGroupIndex(i1, i2, aIndex);
 | 
			
		||||
  ta()()(i1, i2) = 1;
 | 
			
		||||
  ta()()(i2, i1) = 1;
 | 
			
		||||
  ta()()(i1 + nsp, i2 + nsp) = -1;
 | 
			
		||||
  ta()()(i2 + nsp, i1 + nsp) = -1;
 | 
			
		||||
 | 
			
		||||
  ta = ta * nrm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_Sp>
 | 
			
		||||
static void generatorBtype(int bIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  // ta(i,j) = -ta(j,i) = ta(i+N,j+N) = -ta(j+N,i+N) = i / 1/ 2 sqrt(2)
 | 
			
		||||
  // with i<j and i=0,...,N-2
 | 
			
		||||
  // follows that j=i+1, ... , N-1
 | 
			
		||||
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  int i1, i2;
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  cplx i(0.0, 1.0);
 | 
			
		||||
  RealD nrm = 1 / (2 * std::sqrt(2));
 | 
			
		||||
  su2SubGroupIndex(i1, i2, bIndex);
 | 
			
		||||
 | 
			
		||||
  ta()()(i1, i2) = i;
 | 
			
		||||
  ta()()(i2, i1) = -i;
 | 
			
		||||
  ta()()(i1 + nsp, i2 + nsp) = i;
 | 
			
		||||
  ta()()(i2 + nsp, i1 + nsp) = -i;
 | 
			
		||||
 | 
			
		||||
  ta = ta * nrm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_Sp>
 | 
			
		||||
static void generatorCtype(int cIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  // ta(i,j+N) = ta(j,i+N) = ta(i+N,j) = ta(j+N,i) = 1 / 2 sqrt(2)
 | 
			
		||||
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  int i1, i2;
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  RealD nrm = 1 / (2 * std::sqrt(2));
 | 
			
		||||
  su2SubGroupIndex(i1, i2, cIndex);
 | 
			
		||||
 | 
			
		||||
  ta()()(i1, i2 + nsp) = 1;
 | 
			
		||||
  ta()()(i2, i1 + nsp) = 1;
 | 
			
		||||
  ta()()(i1 + nsp, i2) = 1;
 | 
			
		||||
  ta()()(i2 + nsp, i1) = 1;
 | 
			
		||||
 | 
			
		||||
  ta = ta * nrm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_Sp>
 | 
			
		||||
static void generatorDtype(int dIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  // ta(i,j+N) = ta(j,i+N) = -ta(i+N,j) = -ta(j+N,i) = i /  2 sqrt(2)
 | 
			
		||||
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  int i1, i2;
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  cplx i(0.0, 1.0);
 | 
			
		||||
  RealD nrm = 1 / (2 * std::sqrt(2));
 | 
			
		||||
  su2SubGroupIndex(i1, i2, dIndex);
 | 
			
		||||
 | 
			
		||||
  ta()()(i1, i2 + nsp) = i;
 | 
			
		||||
  ta()()(i2, i1 + nsp) = i;
 | 
			
		||||
  ta()()(i1 + nsp, i2) = -i;
 | 
			
		||||
  ta()()(i2 + nsp, i1) = -i;
 | 
			
		||||
 | 
			
		||||
  ta = ta * nrm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_Sp>
 | 
			
		||||
static void generatorWtype(int wIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  // ta(i,i+N) =  ta(i+N,i) = 1/2
 | 
			
		||||
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  RealD nrm = 1.0 / 2;  // check
 | 
			
		||||
 | 
			
		||||
  ta()()(wIndex, wIndex + nsp) = 1;
 | 
			
		||||
  ta()()(wIndex + nsp, wIndex) = 1;
 | 
			
		||||
 | 
			
		||||
  ta = ta * nrm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class cplx, ONLY_IF_Sp>
 | 
			
		||||
static void generatorZtype(int zIndex, iGroupMatrix<cplx> &ta) {
 | 
			
		||||
  // ta(i,i+N) = - ta(i+N,i) = i/2
 | 
			
		||||
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  ta = Zero();
 | 
			
		||||
  RealD nrm = 1.0 / 2;  // check
 | 
			
		||||
  cplx i(0.0, 1.0);
 | 
			
		||||
  ta()()(zIndex, zIndex + nsp) = i;
 | 
			
		||||
  ta()()(zIndex + nsp, zIndex) = -i;
 | 
			
		||||
 | 
			
		||||
  ta = ta * nrm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Map a su2 subgroup number to the pair of rows that are non zero
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
template <ONLY_IF_Sp>
 | 
			
		||||
static void su2SubGroupIndex(int &i1, int &i2, int su2_index, GroupName::Sp) {
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  assert((su2_index >= 0) && (su2_index < (nsp * (nsp - 1)) / 2));
 | 
			
		||||
 | 
			
		||||
  int spare = su2_index;
 | 
			
		||||
  for (i1 = 0; spare >= (nsp - 1 - i1); i1++) {
 | 
			
		||||
    spare = spare - (nsp - 1 - i1);  // remove the Nc-1-i1 terms
 | 
			
		||||
  }
 | 
			
		||||
  i2 = i1 + 1 + spare;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void testGenerators(GroupName::Sp) {
 | 
			
		||||
  Matrix ta;
 | 
			
		||||
  Matrix tb;
 | 
			
		||||
  std::cout << GridLogMessage
 | 
			
		||||
            << "Fundamental - Checking trace ta tb is 0.5 delta_ab "
 | 
			
		||||
            << std::endl;
 | 
			
		||||
  for (int a = 0; a < AlgebraDimension; a++) {
 | 
			
		||||
    for (int b = 0; b < AlgebraDimension; b++) {
 | 
			
		||||
      generator(a, ta);
 | 
			
		||||
      generator(b, tb);
 | 
			
		||||
      Complex tr = TensorRemove(trace(ta * tb));
 | 
			
		||||
      std::cout << GridLogMessage << "(" << a << "," << b << ") =  " << tr
 | 
			
		||||
                << std::endl;
 | 
			
		||||
      if (a == b) assert(abs(tr - Complex(0.5)) < 1.0e-6);
 | 
			
		||||
      if (a != b) assert(abs(tr) < 1.0e-6);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  std::cout << GridLogMessage << std::endl;
 | 
			
		||||
  std::cout << GridLogMessage << "Fundamental - Checking if hermitian"
 | 
			
		||||
            << std::endl;
 | 
			
		||||
  for (int a = 0; a < AlgebraDimension; a++) {
 | 
			
		||||
    generator(a, ta);
 | 
			
		||||
    std::cout << GridLogMessage << a << std::endl;
 | 
			
		||||
    assert(norm2(ta - adj(ta)) < 1.0e-6);
 | 
			
		||||
  }
 | 
			
		||||
  std::cout << GridLogMessage << std::endl;
 | 
			
		||||
  std::cout << GridLogMessage << "Fundamental - Checking if traceless"
 | 
			
		||||
            << std::endl;
 | 
			
		||||
  for (int a = 0; a < AlgebraDimension; a++) {
 | 
			
		||||
    generator(a, ta);
 | 
			
		||||
    Complex tr = TensorRemove(trace(ta));
 | 
			
		||||
    std::cout << GridLogMessage << a << std::endl;
 | 
			
		||||
    assert(abs(tr) < 1.0e-6);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <int N>
 | 
			
		||||
static Lattice<iScalar<iScalar<iMatrix<vComplexD, N> > > >
 | 
			
		||||
ProjectOnGeneralGroup(const Lattice<iScalar<iScalar<iMatrix<vComplexD, N> > > > &Umu, GroupName::Sp) {
 | 
			
		||||
  return ProjectOnSpGroup(Umu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class vtype>
 | 
			
		||||
accelerator_inline static iScalar<vtype> ProjectOnGeneralGroup(const iScalar<vtype> &r, GroupName::Sp) {
 | 
			
		||||
  return ProjectOnSpGroup(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class vtype, int N>
 | 
			
		||||
accelerator_inline static iVector<vtype,N> ProjectOnGeneralGroup(const iVector<vtype,N> &r, GroupName::Sp) {
 | 
			
		||||
  return ProjectOnSpGroup(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class vtype,int N, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0 >::type * =nullptr>
 | 
			
		||||
accelerator_inline static iMatrix<vtype,N> ProjectOnGeneralGroup(const iMatrix<vtype,N> &arg, GroupName::Sp) {
 | 
			
		||||
  return ProjectOnSpGroup(arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename LatticeMatrixType>   
 | 
			
		||||
static void taProj(const LatticeMatrixType &in, LatticeMatrixType &out, GroupName::Sp) {
 | 
			
		||||
  out = SpTa(in);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
template <ONLY_IF_Sp>
 | 
			
		||||
static void Omega(LatticeColourMatrixD &in) {
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
  LatticeColourMatrixD OmegaLatt(in.Grid());
 | 
			
		||||
  LatticeColourMatrixD identity(in.Grid());
 | 
			
		||||
  ColourMatrix Omega;
 | 
			
		||||
 | 
			
		||||
  OmegaLatt = Zero();
 | 
			
		||||
  Omega = Zero();
 | 
			
		||||
  identity = 1.;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < nsp; i++) {
 | 
			
		||||
    Omega()()(i, nsp + i) = 1.;
 | 
			
		||||
    Omega()()(nsp + i, i) = -1;
 | 
			
		||||
  }
 | 
			
		||||
  OmegaLatt = OmegaLatt + (identity * Omega);
 | 
			
		||||
  in = OmegaLatt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <ONLY_IF_Sp, class vtype, int N>
 | 
			
		||||
static void Omega(iScalar<iScalar<iMatrix<vtype, N> > > &in) {
 | 
			
		||||
  const int nsp=ncolour/2;
 | 
			
		||||
    
 | 
			
		||||
  iScalar<iScalar<iMatrix<vtype, N> > > Omega;
 | 
			
		||||
  Omega = Zero();
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < nsp; i++) {
 | 
			
		||||
    Omega()()(i, nsp + i) = 1.;
 | 
			
		||||
    Omega()()(nsp + i, i) = -1;
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  in = Omega;
 | 
			
		||||
}
 | 
			
		||||
@@ -8,9 +8,9 @@
 | 
			
		||||
#include <Grid/qcd/utils/ScalarObjs.h>
 | 
			
		||||
 | 
			
		||||
// Include representations
 | 
			
		||||
#include <Grid/qcd/utils/SUn.h>
 | 
			
		||||
#include <Grid/qcd/utils/GaugeGroup.h>
 | 
			
		||||
#include <Grid/qcd/utils/SUnAdjoint.h>
 | 
			
		||||
#include <Grid/qcd/utils/SUnTwoIndex.h>
 | 
			
		||||
#include <Grid/qcd/utils/GaugeGroupTwoIndex.h>
 | 
			
		||||
 | 
			
		||||
// All-to-all contraction kernels that touch the 
 | 
			
		||||
// internal lattice structure
 | 
			
		||||
 
 | 
			
		||||
@@ -290,7 +290,7 @@ public:
 | 
			
		||||
  }
 | 
			
		||||
*/
 | 
			
		||||
  //////////////////////////////////////////////////
 | 
			
		||||
  // the sum over all staples on each site
 | 
			
		||||
  // the sum over all nu-oriented staples for nu != mu on each site
 | 
			
		||||
  //////////////////////////////////////////////////
 | 
			
		||||
  static void Staple(GaugeMat &staple, const GaugeLorentz &Umu, int mu) {
 | 
			
		||||
 | 
			
		||||
@@ -300,6 +300,10 @@ public:
 | 
			
		||||
    for (int d = 0; d < Nd; d++) {
 | 
			
		||||
      U[d] = PeekIndex<LorentzIndex>(Umu, d);
 | 
			
		||||
    }
 | 
			
		||||
    Staple(staple, U, mu);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void Staple(GaugeMat &staple, const std::vector<GaugeMat> &U, int mu) {
 | 
			
		||||
    staple = Zero();
 | 
			
		||||
 | 
			
		||||
    for (int nu = 0; nu < Nd; nu++) {
 | 
			
		||||
@@ -335,6 +339,203 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /////////////
 | 
			
		||||
  //Staples for each direction mu, summed over nu != mu
 | 
			
		||||
  //staple: output staples for each mu (Nd)
 | 
			
		||||
  //U: link array (Nd)
 | 
			
		||||
  /////////////
 | 
			
		||||
  static void StapleAll(std::vector<GaugeMat> &staple, const std::vector<GaugeMat> &U) {
 | 
			
		||||
    assert(staple.size() == Nd); assert(U.size() == Nd);
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++) Staple(staple[mu], U, mu);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //A workspace class allowing reuse of the stencil
 | 
			
		||||
  class WilsonLoopPaddedStencilWorkspace{
 | 
			
		||||
    std::unique_ptr<GeneralLocalStencil> stencil;
 | 
			
		||||
    size_t nshift;
 | 
			
		||||
 | 
			
		||||
    void generateStencil(GridBase* padded_grid){
 | 
			
		||||
      double t0 = usecond();
 | 
			
		||||
      
 | 
			
		||||
      //Generate shift arrays
 | 
			
		||||
      std::vector<Coordinate> shifts = this->getShifts();
 | 
			
		||||
      nshift = shifts.size();
 | 
			
		||||
      
 | 
			
		||||
      double t1 = usecond();
 | 
			
		||||
      //Generate local stencil
 | 
			
		||||
      stencil.reset(new GeneralLocalStencil(padded_grid,shifts));
 | 
			
		||||
      double t2 = usecond();
 | 
			
		||||
      std::cout << GridLogPerformance << " WilsonLoopPaddedWorkspace timings: coord:" << (t1-t0)/1000 << "ms, stencil:" << (t2-t1)/1000 << "ms" << std::endl;   
 | 
			
		||||
    }
 | 
			
		||||
  public:
 | 
			
		||||
    //Get the stencil. If not already generated, or if generated using a different Grid than in PaddedCell, it will be created on-the-fly
 | 
			
		||||
    const GeneralLocalStencil & getStencil(const PaddedCell &pcell){
 | 
			
		||||
      assert(pcell.depth >= this->paddingDepth());
 | 
			
		||||
      if(!stencil || stencil->Grid() != (GridBase*)pcell.grids.back() ) generateStencil((GridBase*)pcell.grids.back());
 | 
			
		||||
      return *stencil;
 | 
			
		||||
    }
 | 
			
		||||
    size_t Nshift() const{ return nshift; }
 | 
			
		||||
    
 | 
			
		||||
    virtual std::vector<Coordinate> getShifts() const = 0;
 | 
			
		||||
    virtual int paddingDepth() const = 0; //padding depth required
 | 
			
		||||
    
 | 
			
		||||
    virtual ~WilsonLoopPaddedStencilWorkspace(){}
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  //This workspace allows the sharing of a common PaddedCell object between multiple stencil workspaces
 | 
			
		||||
  class WilsonLoopPaddedWorkspace{
 | 
			
		||||
    std::vector<WilsonLoopPaddedStencilWorkspace*> stencil_wk;
 | 
			
		||||
    std::unique_ptr<PaddedCell> pcell;
 | 
			
		||||
 | 
			
		||||
    void generatePcell(GridBase* unpadded_grid){
 | 
			
		||||
      assert(stencil_wk.size());
 | 
			
		||||
      int max_depth = 0;
 | 
			
		||||
      for(auto const &s : stencil_wk) max_depth=std::max(max_depth, s->paddingDepth());
 | 
			
		||||
      
 | 
			
		||||
      pcell.reset(new PaddedCell(max_depth, dynamic_cast<GridCartesian*>(unpadded_grid)));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
  public:
 | 
			
		||||
    //Add a stencil definition. This should be done before the first call to retrieve a stencil object.
 | 
			
		||||
    //Takes ownership of the pointer
 | 
			
		||||
    void addStencil(WilsonLoopPaddedStencilWorkspace *stencil){
 | 
			
		||||
      assert(!pcell);
 | 
			
		||||
      stencil_wk.push_back(stencil);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const GeneralLocalStencil & getStencil(const size_t stencil_idx, GridBase* unpadded_grid){
 | 
			
		||||
      if(!pcell || pcell->unpadded_grid != unpadded_grid) generatePcell(unpadded_grid);
 | 
			
		||||
      return stencil_wk[stencil_idx]->getStencil(*pcell);
 | 
			
		||||
    }      
 | 
			
		||||
    const PaddedCell & getPaddedCell(GridBase* unpadded_grid){
 | 
			
		||||
      if(!pcell || pcell->unpadded_grid != unpadded_grid) generatePcell(unpadded_grid);
 | 
			
		||||
      return *pcell;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    ~WilsonLoopPaddedWorkspace(){
 | 
			
		||||
      for(auto &s : stencil_wk) delete s;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  //A workspace class allowing reuse of the stencil
 | 
			
		||||
  class StaplePaddedAllWorkspace: public WilsonLoopPaddedStencilWorkspace{
 | 
			
		||||
  public:
 | 
			
		||||
    std::vector<Coordinate> getShifts() const override{
 | 
			
		||||
      std::vector<Coordinate> shifts;
 | 
			
		||||
      for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
	for(int nu=0;nu<Nd;nu++){
 | 
			
		||||
	  if(nu != mu){
 | 
			
		||||
	    Coordinate shift_0(Nd,0);
 | 
			
		||||
	    Coordinate shift_mu(Nd,0); shift_mu[mu]=1;
 | 
			
		||||
	    Coordinate shift_nu(Nd,0); shift_nu[nu]=1;
 | 
			
		||||
	    Coordinate shift_mnu(Nd,0); shift_mnu[nu]=-1;
 | 
			
		||||
	    Coordinate shift_mnu_pmu(Nd,0); shift_mnu_pmu[nu]=-1; shift_mnu_pmu[mu]=1;
 | 
			
		||||
      
 | 
			
		||||
	    //U_nu(x+mu)U^dag_mu(x+nu) U^dag_nu(x)
 | 
			
		||||
	    shifts.push_back(shift_0);
 | 
			
		||||
	    shifts.push_back(shift_nu);
 | 
			
		||||
	    shifts.push_back(shift_mu);
 | 
			
		||||
      
 | 
			
		||||
	    //U_nu^dag(x-nu+mu) U_mu^dag(x-nu) U_nu(x-nu)
 | 
			
		||||
	    shifts.push_back(shift_mnu);
 | 
			
		||||
	    shifts.push_back(shift_mnu);
 | 
			
		||||
	    shifts.push_back(shift_mnu_pmu);
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
      return shifts;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int paddingDepth() const override{ return 1; }
 | 
			
		||||
  }; 
 | 
			
		||||
 | 
			
		||||
  //Padded cell implementation of the staple method for all mu, summed over nu != mu
 | 
			
		||||
  //staple: output staple for each mu, summed over nu != mu (Nd)
 | 
			
		||||
  //U_padded: the gauge link fields padded out using the PaddedCell class
 | 
			
		||||
  //Cell: the padded cell class
 | 
			
		||||
  static void StaplePaddedAll(std::vector<GaugeMat> &staple, const std::vector<GaugeMat> &U_padded, const PaddedCell &Cell) {
 | 
			
		||||
    StaplePaddedAllWorkspace wk;
 | 
			
		||||
    StaplePaddedAll(staple,U_padded,Cell,wk.getStencil(Cell));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  //Padded cell implementation of the staple method for all mu, summed over nu != mu
 | 
			
		||||
  //staple: output staple for each mu, summed over nu != mu (Nd)
 | 
			
		||||
  //U_padded: the gauge link fields padded out using the PaddedCell class
 | 
			
		||||
  //Cell: the padded cell class
 | 
			
		||||
  //gStencil: the precomputed generalized local stencil for the staple
 | 
			
		||||
  static void StaplePaddedAll(std::vector<GaugeMat> &staple, const std::vector<GaugeMat> &U_padded, const PaddedCell &Cell, const GeneralLocalStencil &gStencil)
 | 
			
		||||
  {
 | 
			
		||||
    double t0 = usecond();
 | 
			
		||||
    assert(U_padded.size() == Nd); assert(staple.size() == Nd);
 | 
			
		||||
    assert(U_padded[0].Grid() == (GridBase*)Cell.grids.back());
 | 
			
		||||
    assert(Cell.depth >= 1);
 | 
			
		||||
    GridBase *ggrid = U_padded[0].Grid(); //padded cell grid
 | 
			
		||||
 | 
			
		||||
    int shift_mu_off = gStencil._npoints/Nd;
 | 
			
		||||
    
 | 
			
		||||
    //Open views to padded gauge links and keep open over mu loop
 | 
			
		||||
    typedef LatticeView<typename GaugeMat::vector_object> GaugeViewType;
 | 
			
		||||
    size_t vsize = Nd*sizeof(GaugeViewType);
 | 
			
		||||
    GaugeViewType* Ug_dirs_v_host = (GaugeViewType*)malloc(vsize);
 | 
			
		||||
    for(int i=0;i<Nd;i++) Ug_dirs_v_host[i] = U_padded[i].View(AcceleratorRead);
 | 
			
		||||
    GaugeViewType* Ug_dirs_v = (GaugeViewType*)acceleratorAllocDevice(vsize);
 | 
			
		||||
    acceleratorCopyToDevice(Ug_dirs_v_host,Ug_dirs_v,vsize);
 | 
			
		||||
    
 | 
			
		||||
    GaugeMat gStaple(ggrid);
 | 
			
		||||
 | 
			
		||||
    int outer_off = 0;
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      { //view scope
 | 
			
		||||
	autoView( gStaple_v , gStaple, AcceleratorWrite);
 | 
			
		||||
	auto gStencil_v = gStencil.View();
 | 
			
		||||
	
 | 
			
		||||
	accelerator_for(ss, ggrid->oSites(), (size_t)ggrid->Nsimd(), {
 | 
			
		||||
	    decltype(coalescedRead(Ug_dirs_v[0][0])) stencil_ss;
 | 
			
		||||
	    stencil_ss = Zero();
 | 
			
		||||
	    int off = outer_off;
 | 
			
		||||
	    
 | 
			
		||||
	    for(int nu=0;nu<Nd;nu++){
 | 
			
		||||
	      if(nu != mu){	  
 | 
			
		||||
		GeneralStencilEntry const* e = gStencil_v.GetEntry(off++,ss);
 | 
			
		||||
		auto U0 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(off++,ss);
 | 
			
		||||
		auto U1 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(off++,ss);
 | 
			
		||||
		auto U2 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
      
 | 
			
		||||
		stencil_ss = stencil_ss + U2 * U1 * U0;
 | 
			
		||||
 | 
			
		||||
		e = gStencil_v.GetEntry(off++,ss);
 | 
			
		||||
		U0 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(off++,ss);
 | 
			
		||||
		U1 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(off++,ss);
 | 
			
		||||
		U2 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
 | 
			
		||||
		stencil_ss = stencil_ss + U2 * U1 * U0;
 | 
			
		||||
	      }
 | 
			
		||||
	    }
 | 
			
		||||
		
 | 
			
		||||
	    coalescedWrite(gStaple_v[ss],stencil_ss);
 | 
			
		||||
	  }
 | 
			
		||||
	  );
 | 
			
		||||
      } //ensure views are all closed!
 | 
			
		||||
      
 | 
			
		||||
      staple[mu] = Cell.Extract(gStaple);
 | 
			
		||||
      outer_off += shift_mu_off;
 | 
			
		||||
    }//mu loop
 | 
			
		||||
 | 
			
		||||
    for(int i=0;i<Nd;i++) Ug_dirs_v_host[i].ViewClose();
 | 
			
		||||
    free(Ug_dirs_v_host);
 | 
			
		||||
    acceleratorFreeDevice(Ug_dirs_v);
 | 
			
		||||
    
 | 
			
		||||
    double t1=usecond();
 | 
			
		||||
    
 | 
			
		||||
    std::cout << GridLogPerformance << "StaplePaddedAll timing:" << (t1-t0)/1000 << "ms" << std::endl;   
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||
  //////////////////////////////////////////////////
 | 
			
		||||
  // the sum over all staples on each site in direction mu,nu, upper part
 | 
			
		||||
  //////////////////////////////////////////////////
 | 
			
		||||
@@ -707,18 +908,14 @@ public:
 | 
			
		||||
  // the sum over all staples on each site
 | 
			
		||||
  //////////////////////////////////////////////////
 | 
			
		||||
  static void RectStapleDouble(GaugeMat &U2, const GaugeMat &U, int mu) {
 | 
			
		||||
    U2 = U * Cshift(U, mu, 1);
 | 
			
		||||
    U2 = U * Gimpl::CshiftLink(U, mu, 1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Hop by two optimisation strategy does not work nicely with Gparity. (could
 | 
			
		||||
  // do,
 | 
			
		||||
  // but need to track two deep where cross boundary and apply a conjugation).
 | 
			
		||||
  // Must differentiate this in Gimpl, and use Gimpl::isPeriodicGaugeField to do
 | 
			
		||||
  // so .
 | 
			
		||||
  // Hop by two optimisation strategy. Use RectStapleDouble to obtain 'U2'
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  static void RectStapleOptimised(GaugeMat &Stap, std::vector<GaugeMat> &U2,
 | 
			
		||||
                                  std::vector<GaugeMat> &U, int mu) {
 | 
			
		||||
  static void RectStapleOptimised(GaugeMat &Stap, const std::vector<GaugeMat> &U2,
 | 
			
		||||
                                  const std::vector<GaugeMat> &U, int mu) {
 | 
			
		||||
 | 
			
		||||
    Stap = Zero();
 | 
			
		||||
 | 
			
		||||
@@ -732,9 +929,9 @@ public:
 | 
			
		||||
 | 
			
		||||
        // Up staple    ___ ___
 | 
			
		||||
        //             |       |
 | 
			
		||||
        tmp = Cshift(adj(U[nu]), nu, -1);
 | 
			
		||||
        tmp = Gimpl::CshiftLink(adj(U[nu]), nu, -1);
 | 
			
		||||
        tmp = adj(U2[mu]) * tmp;
 | 
			
		||||
        tmp = Cshift(tmp, mu, -2);
 | 
			
		||||
        tmp = Gimpl::CshiftLink(tmp, mu, -2);
 | 
			
		||||
 | 
			
		||||
        Staple2x1 = Gimpl::CovShiftForward(U[nu], nu, tmp);
 | 
			
		||||
 | 
			
		||||
@@ -742,14 +939,14 @@ public:
 | 
			
		||||
        //             |___ ___|
 | 
			
		||||
        //
 | 
			
		||||
        tmp = adj(U2[mu]) * U[nu];
 | 
			
		||||
        Staple2x1 += Gimpl::CovShiftBackward(U[nu], nu, Cshift(tmp, mu, -2));
 | 
			
		||||
        Staple2x1 += Gimpl::CovShiftBackward(U[nu], nu, Gimpl::CshiftLink(tmp, mu, -2));
 | 
			
		||||
 | 
			
		||||
        //              ___ ___
 | 
			
		||||
        //             |    ___|
 | 
			
		||||
        //             |___ ___|
 | 
			
		||||
        //
 | 
			
		||||
 | 
			
		||||
        Stap += Cshift(Gimpl::CovShiftForward(U[mu], mu, Staple2x1), mu, 1);
 | 
			
		||||
        Stap += Gimpl::CshiftLink(Gimpl::CovShiftForward(U[mu], mu, Staple2x1), mu, 1);
 | 
			
		||||
 | 
			
		||||
        //              ___ ___
 | 
			
		||||
        //             |___    |
 | 
			
		||||
@@ -758,7 +955,7 @@ public:
 | 
			
		||||
 | 
			
		||||
        //  tmp= Staple2x1* Cshift(U[mu],mu,-2);
 | 
			
		||||
        //  Stap+= Cshift(tmp,mu,1) ;
 | 
			
		||||
        Stap += Cshift(Staple2x1, mu, 1) * Cshift(U[mu], mu, -1);
 | 
			
		||||
        Stap += Gimpl::CshiftLink(Staple2x1, mu, 1) * Gimpl::CshiftLink(U[mu], mu, -1);
 | 
			
		||||
        ;
 | 
			
		||||
 | 
			
		||||
        //       --
 | 
			
		||||
@@ -766,10 +963,10 @@ public:
 | 
			
		||||
        //
 | 
			
		||||
        //      |  |
 | 
			
		||||
 | 
			
		||||
        tmp = Cshift(adj(U2[nu]), nu, -2);
 | 
			
		||||
        tmp = Gimpl::CshiftLink(adj(U2[nu]), nu, -2);
 | 
			
		||||
        tmp = Gimpl::CovShiftBackward(U[mu], mu, tmp);
 | 
			
		||||
        tmp = U2[nu] * Cshift(tmp, nu, 2);
 | 
			
		||||
        Stap += Cshift(tmp, mu, 1);
 | 
			
		||||
        tmp = U2[nu] * Gimpl::CshiftLink(tmp, nu, 2);
 | 
			
		||||
        Stap += Gimpl::CshiftLink(tmp, mu, 1);
 | 
			
		||||
 | 
			
		||||
        //      |  |
 | 
			
		||||
        //
 | 
			
		||||
@@ -778,25 +975,12 @@ public:
 | 
			
		||||
 | 
			
		||||
        tmp = Gimpl::CovShiftBackward(U[mu], mu, U2[nu]);
 | 
			
		||||
        tmp = adj(U2[nu]) * tmp;
 | 
			
		||||
        tmp = Cshift(tmp, nu, -2);
 | 
			
		||||
        Stap += Cshift(tmp, mu, 1);
 | 
			
		||||
        tmp = Gimpl::CshiftLink(tmp, nu, -2);
 | 
			
		||||
        Stap += Gimpl::CshiftLink(tmp, mu, 1);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void RectStaple(GaugeMat &Stap, const GaugeLorentz &Umu, int mu) {
 | 
			
		||||
    RectStapleUnoptimised(Stap, Umu, mu);
 | 
			
		||||
  }
 | 
			
		||||
  static void RectStaple(const GaugeLorentz &Umu, GaugeMat &Stap,
 | 
			
		||||
                         std::vector<GaugeMat> &U2, std::vector<GaugeMat> &U,
 | 
			
		||||
                         int mu) {
 | 
			
		||||
    if (Gimpl::isPeriodicGaugeField()) {
 | 
			
		||||
      RectStapleOptimised(Stap, U2, U, mu);
 | 
			
		||||
    } else {
 | 
			
		||||
      RectStapleUnoptimised(Stap, Umu, mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void RectStapleUnoptimised(GaugeMat &Stap, const GaugeLorentz &Umu,
 | 
			
		||||
                                    int mu) {
 | 
			
		||||
    GridBase *grid = Umu.Grid();
 | 
			
		||||
@@ -895,6 +1079,288 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void RectStaple(GaugeMat &Stap, const GaugeLorentz &Umu, int mu) {
 | 
			
		||||
    RectStapleUnoptimised(Stap, Umu, mu);
 | 
			
		||||
  }
 | 
			
		||||
  static void RectStaple(const GaugeLorentz &Umu, GaugeMat &Stap,
 | 
			
		||||
                         std::vector<GaugeMat> &U2, std::vector<GaugeMat> &U,
 | 
			
		||||
                         int mu) {
 | 
			
		||||
    RectStapleOptimised(Stap, U2, U, mu);
 | 
			
		||||
  }
 | 
			
		||||
  //////////////////////////////////////////////////////
 | 
			
		||||
  //Compute the rectangular staples for all orientations
 | 
			
		||||
  //Stap : Array of staples (Nd)
 | 
			
		||||
  //U: Gauge links in each direction (Nd)
 | 
			
		||||
  /////////////////////////////////////////////////////
 | 
			
		||||
  static void RectStapleAll(std::vector<GaugeMat> &Stap, const std::vector<GaugeMat> &U){
 | 
			
		||||
    assert(Stap.size() == Nd); assert(U.size() == Nd);
 | 
			
		||||
    std::vector<GaugeMat> U2(Nd,U[0].Grid());
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++) RectStapleDouble(U2[mu], U[mu], mu);
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++) RectStapleOptimised(Stap[mu], U2, U, mu);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //A workspace class allowing reuse of the stencil
 | 
			
		||||
  class RectStaplePaddedAllWorkspace: public WilsonLoopPaddedStencilWorkspace{
 | 
			
		||||
  public:
 | 
			
		||||
    std::vector<Coordinate> getShifts() const override{
 | 
			
		||||
      std::vector<Coordinate> shifts;
 | 
			
		||||
      for (int mu = 0; mu < Nd; mu++){
 | 
			
		||||
	for (int nu = 0; nu < Nd; nu++) {
 | 
			
		||||
	  if (nu != mu) {
 | 
			
		||||
	    auto genShift = [&](int mushift,int nushift){
 | 
			
		||||
	      Coordinate out(Nd,0); out[mu]=mushift; out[nu]=nushift; return out;
 | 
			
		||||
	    };
 | 
			
		||||
 | 
			
		||||
	    //tmp6 = tmp5(x+mu) = U_mu(x+mu)U_nu(x+2mu)U_mu^dag(x+nu+mu) U_mu^dag(x+nu) U_nu^dag(x)
 | 
			
		||||
	    shifts.push_back(genShift(0,0));
 | 
			
		||||
	    shifts.push_back(genShift(0,+1));
 | 
			
		||||
	    shifts.push_back(genShift(+1,+1));
 | 
			
		||||
	    shifts.push_back(genShift(+2,0));
 | 
			
		||||
	    shifts.push_back(genShift(+1,0));
 | 
			
		||||
 | 
			
		||||
	    //tmp5 = tmp4(x+mu) = U_mu(x+mu)U^dag_nu(x-nu+2mu)U^dag_mu(x-nu+mu)U^dag_mu(x-nu)U_nu(x-nu)
 | 
			
		||||
	    shifts.push_back(genShift(0,-1));
 | 
			
		||||
	    shifts.push_back(genShift(0,-1));
 | 
			
		||||
	    shifts.push_back(genShift(+1,-1));
 | 
			
		||||
	    shifts.push_back(genShift(+2,-1));
 | 
			
		||||
	    shifts.push_back(genShift(+1,0));
 | 
			
		||||
 | 
			
		||||
	    //tmp5 = tmp4(x+mu) = U^dag_nu(x-nu+mu)U^dag_mu(x-nu)U^dag_mu(x-mu-nu)U_nu(x-mu-nu)U_mu(x-mu)
 | 
			
		||||
	    shifts.push_back(genShift(-1,0));
 | 
			
		||||
	    shifts.push_back(genShift(-1,-1));
 | 
			
		||||
	    shifts.push_back(genShift(-1,-1));
 | 
			
		||||
	    shifts.push_back(genShift(0,-1));
 | 
			
		||||
	    shifts.push_back(genShift(+1,-1));
 | 
			
		||||
 | 
			
		||||
	    //tmp5 = tmp4(x+mu) = U_nu(x+mu)U_mu^dag(x+nu)U_mu^dag(x-mu+nu)U_nu^dag(x-mu)U_mu(x-mu)
 | 
			
		||||
	    shifts.push_back(genShift(-1,0));
 | 
			
		||||
	    shifts.push_back(genShift(-1,0));
 | 
			
		||||
	    shifts.push_back(genShift(-1,+1));
 | 
			
		||||
	    shifts.push_back(genShift(0,+1));
 | 
			
		||||
	    shifts.push_back(genShift(+1,0));
 | 
			
		||||
 | 
			
		||||
	    //tmp6 = tmp5(x+mu) = U_nu(x+mu)U_nu(x+mu+nu)U_mu^dag(x+2nu)U_nu^dag(x+nu)U_nu^dag(x)
 | 
			
		||||
	    shifts.push_back(genShift(0,0));
 | 
			
		||||
	    shifts.push_back(genShift(0,+1));
 | 
			
		||||
	    shifts.push_back(genShift(0,+2));
 | 
			
		||||
	    shifts.push_back(genShift(+1,+1));
 | 
			
		||||
	    shifts.push_back(genShift(+1,0));
 | 
			
		||||
 | 
			
		||||
	    //tmp5 = tmp4(x+mu) = U_nu^dag(x+mu-nu)U_nu^dag(x+mu-2nu)U_mu^dag(x-2nu)U_nu(x-2nu)U_nu(x-nu)
 | 
			
		||||
	    shifts.push_back(genShift(0,-1));
 | 
			
		||||
	    shifts.push_back(genShift(0,-2));
 | 
			
		||||
	    shifts.push_back(genShift(0,-2));
 | 
			
		||||
	    shifts.push_back(genShift(+1,-2));
 | 
			
		||||
	    shifts.push_back(genShift(+1,-1));
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
      return shifts;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int paddingDepth() const override{ return 2; }
 | 
			
		||||
  }; 
 | 
			
		||||
 | 
			
		||||
  //Padded cell implementation of the rectangular staple method for all mu, summed over nu != mu
 | 
			
		||||
  //staple: output staple for each mu, summed over nu != mu (Nd)
 | 
			
		||||
  //U_padded: the gauge link fields padded out using the PaddedCell class
 | 
			
		||||
  //Cell: the padded cell class
 | 
			
		||||
  static void RectStaplePaddedAll(std::vector<GaugeMat> &staple, const std::vector<GaugeMat> &U_padded, const PaddedCell &Cell) {
 | 
			
		||||
    RectStaplePaddedAllWorkspace wk;
 | 
			
		||||
    RectStaplePaddedAll(staple,U_padded,Cell,wk.getStencil(Cell));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  //Padded cell implementation of the rectangular staple method for all mu, summed over nu != mu
 | 
			
		||||
  //staple: output staple for each mu, summed over nu != mu (Nd)
 | 
			
		||||
  //U_padded: the gauge link fields padded out using the PaddedCell class
 | 
			
		||||
  //Cell: the padded cell class
 | 
			
		||||
  //gStencil: the stencil
 | 
			
		||||
  static void RectStaplePaddedAll(std::vector<GaugeMat> &staple, const std::vector<GaugeMat> &U_padded, const PaddedCell &Cell, const GeneralLocalStencil &gStencil) {
 | 
			
		||||
    double t0 = usecond();
 | 
			
		||||
    assert(U_padded.size() == Nd); assert(staple.size() == Nd);
 | 
			
		||||
    assert(U_padded[0].Grid() == (GridBase*)Cell.grids.back());
 | 
			
		||||
    assert(Cell.depth >= 2);
 | 
			
		||||
    GridBase *ggrid = U_padded[0].Grid(); //padded cell grid
 | 
			
		||||
 | 
			
		||||
    size_t nshift = gStencil._npoints;
 | 
			
		||||
    int mu_off_delta = nshift / Nd;
 | 
			
		||||
    
 | 
			
		||||
    //Open views to padded gauge links and keep open over mu loop
 | 
			
		||||
    typedef LatticeView<typename GaugeMat::vector_object> GaugeViewType;
 | 
			
		||||
    size_t vsize = Nd*sizeof(GaugeViewType);
 | 
			
		||||
    GaugeViewType* Ug_dirs_v_host = (GaugeViewType*)malloc(vsize);
 | 
			
		||||
    for(int i=0;i<Nd;i++) Ug_dirs_v_host[i] = U_padded[i].View(AcceleratorRead);
 | 
			
		||||
    GaugeViewType* Ug_dirs_v = (GaugeViewType*)acceleratorAllocDevice(vsize);
 | 
			
		||||
    acceleratorCopyToDevice(Ug_dirs_v_host,Ug_dirs_v,vsize);
 | 
			
		||||
 | 
			
		||||
    GaugeMat gStaple(ggrid); //temp staple object on padded grid
 | 
			
		||||
 | 
			
		||||
    int offset = 0;
 | 
			
		||||
    for(int mu=0; mu<Nd; mu++){
 | 
			
		||||
 | 
			
		||||
      { //view scope
 | 
			
		||||
	autoView( gStaple_v , gStaple, AcceleratorWrite);
 | 
			
		||||
	auto gStencil_v = gStencil.View();
 | 
			
		||||
 | 
			
		||||
	accelerator_for(ss, ggrid->oSites(), (size_t)ggrid->Nsimd(), {
 | 
			
		||||
	    decltype(coalescedRead(Ug_dirs_v[0][0])) stencil_ss;
 | 
			
		||||
	    stencil_ss = Zero();
 | 
			
		||||
	    int s=offset;
 | 
			
		||||
	    for(int nu=0;nu<Nd;nu++){
 | 
			
		||||
	      if(nu != mu){
 | 
			
		||||
		//tmp6 = tmp5(x+mu) = U_mu(x+mu)U_nu(x+2mu)U_mu^dag(x+nu+mu) U_mu^dag(x+nu) U_nu^dag(x)
 | 
			
		||||
		GeneralStencilEntry const* e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		auto U0 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		auto U1 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		auto U2 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		auto U3 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		auto U4 = coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd);
 | 
			
		||||
	    
 | 
			
		||||
		stencil_ss = stencil_ss + U4*U3*U2*U1*U0;
 | 
			
		||||
 | 
			
		||||
		//tmp5 = tmp4(x+mu) = U_mu(x+mu)U^dag_nu(x-nu+2mu)U^dag_mu(x-nu+mu)U^dag_mu(x-nu)U_nu(x-nu)
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U0 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U1 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U2 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U3 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U4 = coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd);
 | 
			
		||||
 | 
			
		||||
		stencil_ss = stencil_ss + U4*U3*U2*U1*U0;
 | 
			
		||||
 | 
			
		||||
		//tmp5 = tmp4(x+mu) = U^dag_nu(x-nu+mu)U^dag_mu(x-nu)U^dag_mu(x-mu-nu)U_nu(x-mu-nu)U_mu(x-mu)
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U0 = coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U1 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U2 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U3 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U4 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
 | 
			
		||||
		stencil_ss = stencil_ss + U4*U3*U2*U1*U0;
 | 
			
		||||
 | 
			
		||||
		//tmp5 = tmp4(x+mu) = U_nu(x+mu)U_mu^dag(x+nu)U_mu^dag(x-mu+nu)U_nu^dag(x-mu)U_mu(x-mu)
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U0 = coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U1 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U2 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U3 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U4 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
 | 
			
		||||
		stencil_ss = stencil_ss + U4*U3*U2*U1*U0;
 | 
			
		||||
 | 
			
		||||
		//tmp6 = tmp5(x+mu) = U_nu(x+mu)U_nu(x+mu+nu)U_mu^dag(x+2nu)U_nu^dag(x+nu)U_nu^dag(x)
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U0 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U1 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U2 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U3 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U4 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
 | 
			
		||||
		stencil_ss = stencil_ss + U4*U3*U2*U1*U0;   
 | 
			
		||||
 | 
			
		||||
		//tmp5 = tmp4(x+mu) = U_nu^dag(x+mu-nu)U_nu^dag(x+mu-2nu)U_mu^dag(x-2nu)U_nu(x-2nu)U_nu(x-nu)
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U0 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U1 = coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd);
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U2 = adj(coalescedReadGeneralPermute(Ug_dirs_v[mu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U3 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
		e = gStencil_v.GetEntry(s++,ss);
 | 
			
		||||
		U4 = adj(coalescedReadGeneralPermute(Ug_dirs_v[nu][e->_offset], e->_permute, Nd));
 | 
			
		||||
 | 
			
		||||
		stencil_ss = stencil_ss + U4*U3*U2*U1*U0;   
 | 
			
		||||
 | 
			
		||||
	      }
 | 
			
		||||
	    }
 | 
			
		||||
	    coalescedWrite(gStaple_v[ss],stencil_ss);
 | 
			
		||||
	  }
 | 
			
		||||
	  );
 | 
			
		||||
	offset += mu_off_delta;
 | 
			
		||||
      }//kernel/view scope
 | 
			
		||||
 | 
			
		||||
      staple[mu] = Cell.Extract(gStaple);    
 | 
			
		||||
    }//mu loop
 | 
			
		||||
  
 | 
			
		||||
    for(int i=0;i<Nd;i++) Ug_dirs_v_host[i].ViewClose();
 | 
			
		||||
    free(Ug_dirs_v_host);
 | 
			
		||||
    acceleratorFreeDevice(Ug_dirs_v);
 | 
			
		||||
    
 | 
			
		||||
    double t1 = usecond();
 | 
			
		||||
    
 | 
			
		||||
    std::cout << GridLogPerformance << "RectStaplePaddedAll timings:" << (t1-t0)/1000 << "ms" << std::endl;   
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //A workspace for reusing the PaddedCell and GeneralLocalStencil objects
 | 
			
		||||
  class StapleAndRectStapleAllWorkspace: public WilsonLoopPaddedWorkspace{
 | 
			
		||||
  public:
 | 
			
		||||
    StapleAndRectStapleAllWorkspace(){
 | 
			
		||||
      this->addStencil(new StaplePaddedAllWorkspace);
 | 
			
		||||
      this->addStencil(new RectStaplePaddedAllWorkspace);
 | 
			
		||||
    }
 | 
			
		||||
  };     
 | 
			
		||||
    
 | 
			
		||||
  //////////////////////////////////////////////////////
 | 
			
		||||
  //Compute the 1x1 and 1x2 staples for all orientations
 | 
			
		||||
  //Stap : Array of staples (Nd)
 | 
			
		||||
  //RectStap: Array of rectangular staples (Nd)
 | 
			
		||||
  //U: Gauge links in each direction (Nd)
 | 
			
		||||
  /////////////////////////////////////////////////////
 | 
			
		||||
  static void StapleAndRectStapleAll(std::vector<GaugeMat> &Stap, std::vector<GaugeMat> &RectStap, const std::vector<GaugeMat> &U){
 | 
			
		||||
    StapleAndRectStapleAllWorkspace wk;
 | 
			
		||||
    StapleAndRectStapleAll(Stap,RectStap,U,wk);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  //////////////////////////////////////////////////////
 | 
			
		||||
  //Compute the 1x1 and 1x2 staples for all orientations
 | 
			
		||||
  //Stap : Array of staples (Nd)
 | 
			
		||||
  //RectStap: Array of rectangular staples (Nd)
 | 
			
		||||
  //U: Gauge links in each direction (Nd)
 | 
			
		||||
  //wk: a workspace containing stored PaddedCell and GeneralLocalStencil objects to maximize reuse
 | 
			
		||||
  /////////////////////////////////////////////////////
 | 
			
		||||
  static void StapleAndRectStapleAll(std::vector<GaugeMat> &Stap, std::vector<GaugeMat> &RectStap, const std::vector<GaugeMat> &U, StapleAndRectStapleAllWorkspace &wk){
 | 
			
		||||
#if 0
 | 
			
		||||
    StapleAll(Stap, U);
 | 
			
		||||
    RectStapleAll(RectStap, U);
 | 
			
		||||
#else
 | 
			
		||||
    double t0 = usecond();
 | 
			
		||||
 | 
			
		||||
    GridCartesian* unpadded_grid = dynamic_cast<GridCartesian*>(U[0].Grid());
 | 
			
		||||
    const PaddedCell &Ghost = wk.getPaddedCell(unpadded_grid);
 | 
			
		||||
        
 | 
			
		||||
    CshiftImplGauge<Gimpl> cshift_impl;
 | 
			
		||||
    std::vector<GaugeMat> U_pad(Nd, Ghost.grids.back());
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++) U_pad[mu] = Ghost.Exchange(U[mu], cshift_impl);
 | 
			
		||||
    double t1 = usecond();
 | 
			
		||||
    StaplePaddedAll(Stap, U_pad, Ghost, wk.getStencil(0,unpadded_grid) );
 | 
			
		||||
    double t2 = usecond();
 | 
			
		||||
    RectStaplePaddedAll(RectStap, U_pad, Ghost, wk.getStencil(1,unpadded_grid));
 | 
			
		||||
    double t3 = usecond();
 | 
			
		||||
    std::cout << GridLogPerformance << "StapleAndRectStapleAll timings: pad:" << (t1-t0)/1000 << "ms, staple:" << (t2-t1)/1000 << "ms, rect-staple:" << (t3-t2)/1000 << "ms" << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////
 | 
			
		||||
  // Wilson loop of size (R1, R2), oriented in mu,nu plane
 | 
			
		||||
  //////////////////////////////////////////////////
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ class GeneralLocalStencilView {
 | 
			
		||||
  int                               _npoints; // Move to template param?
 | 
			
		||||
  GeneralStencilEntry*  _entries_p;
 | 
			
		||||
 | 
			
		||||
  accelerator_inline GeneralStencilEntry * GetEntry(int point,int osite) { 
 | 
			
		||||
  accelerator_inline GeneralStencilEntry * GetEntry(int point,int osite) const { 
 | 
			
		||||
    return & this->_entries_p[point+this->_npoints*osite]; 
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -79,60 +79,60 @@ public:
 | 
			
		||||
    this->_entries.resize(npoints* osites);
 | 
			
		||||
    this->_entries_p = &_entries[0];
 | 
			
		||||
 | 
			
		||||
    thread_for(site, osites, {
 | 
			
		||||
	Coordinate Coor;
 | 
			
		||||
	Coordinate NbrCoor;
 | 
			
		||||
 | 
			
		||||
    Coordinate Coor;
 | 
			
		||||
    Coordinate NbrCoor;
 | 
			
		||||
    for(Integer site=0;site<osites;site++){
 | 
			
		||||
      for(Integer ii=0;ii<npoints;ii++){
 | 
			
		||||
	Integer lex = site*npoints+ii;
 | 
			
		||||
	GeneralStencilEntry SE;
 | 
			
		||||
	////////////////////////////////////////////////
 | 
			
		||||
	// Outer index of neighbour Offset calculation
 | 
			
		||||
	////////////////////////////////////////////////
 | 
			
		||||
	grid->oCoorFromOindex(Coor,site);
 | 
			
		||||
	for(int d=0;d<Coor.size();d++){
 | 
			
		||||
	  int rd = grid->_rdimensions[d];
 | 
			
		||||
	  NbrCoor[d] = (Coor[d] + shifts[ii][d] + rd )%rd;
 | 
			
		||||
	}
 | 
			
		||||
	SE._offset      = grid->oIndexReduced(NbrCoor);
 | 
			
		||||
 | 
			
		||||
	////////////////////////////////////////////////
 | 
			
		||||
	// Inner index permute calculation
 | 
			
		||||
	// Simpler version using icoor calculation
 | 
			
		||||
	////////////////////////////////////////////////
 | 
			
		||||
	SE._permute =0;
 | 
			
		||||
	for(int d=0;d<Coor.size();d++){
 | 
			
		||||
 | 
			
		||||
	  int fd = grid->_fdimensions[d];
 | 
			
		||||
	  int rd = grid->_rdimensions[d];
 | 
			
		||||
	  int ly = grid->_simd_layout[d];
 | 
			
		||||
 | 
			
		||||
	  assert((ly==1)||(ly==2));
 | 
			
		||||
 | 
			
		||||
	  int shift = (shifts[ii][d]+fd)%fd;  // make it strictly positive 0.. L-1
 | 
			
		||||
	  int x = Coor[d];                // x in [0... rd-1] as an oSite 
 | 
			
		||||
 | 
			
		||||
	  int permute_dim  = grid->PermuteDim(d);
 | 
			
		||||
	  int permute_slice=0;
 | 
			
		||||
	  if(permute_dim){    
 | 
			
		||||
	    int  num = shift%rd; // Slice within dest osite cell of slice zero
 | 
			
		||||
	    int wrap = shift/rd; // Number of osite local volume cells crossed through
 | 
			
		||||
                                  // x+num < rd dictates whether we are in same permute state as slice 0
 | 
			
		||||
	    if ( x< rd-num ) permute_slice=wrap;
 | 
			
		||||
	    else             permute_slice=(wrap+1)%ly;
 | 
			
		||||
	for(Integer ii=0;ii<npoints;ii++){
 | 
			
		||||
	  Integer lex = site*npoints+ii;
 | 
			
		||||
	  GeneralStencilEntry SE;
 | 
			
		||||
	  ////////////////////////////////////////////////
 | 
			
		||||
	  // Outer index of neighbour Offset calculation
 | 
			
		||||
	  ////////////////////////////////////////////////
 | 
			
		||||
	  grid->oCoorFromOindex(Coor,site);
 | 
			
		||||
	  for(int d=0;d<Coor.size();d++){
 | 
			
		||||
	    int rd = grid->_rdimensions[d];
 | 
			
		||||
	    NbrCoor[d] = (Coor[d] + shifts[ii][d] + rd )%rd;
 | 
			
		||||
	  }
 | 
			
		||||
	  if ( permute_slice ) {
 | 
			
		||||
	    int ptype       =grid->PermuteType(d);
 | 
			
		||||
	    uint8_t mask    =0x1<<ptype;
 | 
			
		||||
	    SE._permute    |= mask;
 | 
			
		||||
	  SE._offset      = grid->oIndexReduced(NbrCoor);
 | 
			
		||||
 | 
			
		||||
	  ////////////////////////////////////////////////
 | 
			
		||||
	  // Inner index permute calculation
 | 
			
		||||
	  // Simpler version using icoor calculation
 | 
			
		||||
	  ////////////////////////////////////////////////
 | 
			
		||||
	  SE._permute =0;
 | 
			
		||||
	  for(int d=0;d<Coor.size();d++){
 | 
			
		||||
 | 
			
		||||
	    int fd = grid->_fdimensions[d];
 | 
			
		||||
	    int rd = grid->_rdimensions[d];
 | 
			
		||||
	    int ly = grid->_simd_layout[d];
 | 
			
		||||
 | 
			
		||||
	    assert((ly==1)||(ly==2));
 | 
			
		||||
 | 
			
		||||
	    int shift = (shifts[ii][d]+fd)%fd;  // make it strictly positive 0.. L-1
 | 
			
		||||
	    int x = Coor[d];                // x in [0... rd-1] as an oSite 
 | 
			
		||||
 | 
			
		||||
	    int permute_dim  = grid->PermuteDim(d);
 | 
			
		||||
	    int permute_slice=0;
 | 
			
		||||
	    if(permute_dim){    
 | 
			
		||||
	      int  num = shift%rd; // Slice within dest osite cell of slice zero
 | 
			
		||||
	      int wrap = shift/rd; // Number of osite local volume cells crossed through
 | 
			
		||||
	      // x+num < rd dictates whether we are in same permute state as slice 0
 | 
			
		||||
	      if ( x< rd-num ) permute_slice=wrap;
 | 
			
		||||
	      else             permute_slice=(wrap+1)%ly;
 | 
			
		||||
	    }
 | 
			
		||||
	    if ( permute_slice ) {
 | 
			
		||||
	      int ptype       =grid->PermuteType(d);
 | 
			
		||||
	      uint8_t mask    =0x1<<ptype;
 | 
			
		||||
	      SE._permute    |= mask;
 | 
			
		||||
	    }
 | 
			
		||||
	  }	
 | 
			
		||||
	  ////////////////////////////////////////////////
 | 
			
		||||
	  // Store in look up table
 | 
			
		||||
	  ////////////////////////////////////////////////
 | 
			
		||||
	  this->_entries[lex] = SE;
 | 
			
		||||
	}
 | 
			
		||||
	////////////////////////////////////////////////
 | 
			
		||||
	// Store in look up table
 | 
			
		||||
	////////////////////////////////////////////////
 | 
			
		||||
	this->_entries[lex] = SE;
 | 
			
		||||
      }
 | 
			
		||||
    }      
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
 | 
			
		||||
#include <Grid/stencil/SimpleCompressor.h>   // subdir aggregate
 | 
			
		||||
#include <Grid/stencil/Lebesgue.h>   // subdir aggregate
 | 
			
		||||
#include <Grid/stencil/GeneralLocalStencil.h>
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Must not lose sight that goal is to be able to construct really efficient
 | 
			
		||||
 
 | 
			
		||||
@@ -73,6 +73,16 @@ vobj coalescedReadPermute(const vobj & __restrict__ vec,int ptype,int doperm,int
 | 
			
		||||
    return vec;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
//'perm_mask' acts as a bitmask
 | 
			
		||||
template<class vobj> accelerator_inline
 | 
			
		||||
vobj coalescedReadGeneralPermute(const vobj & __restrict__ vec,int perm_mask,int nd,int lane=0)
 | 
			
		||||
{
 | 
			
		||||
  auto obj = vec, tmp = vec;
 | 
			
		||||
  for (int d=0;d<nd;d++)
 | 
			
		||||
    if (perm_mask & (0x1 << d)) { permute(obj,tmp,d); tmp=obj;}
 | 
			
		||||
  return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class vobj> accelerator_inline
 | 
			
		||||
void coalescedWrite(vobj & __restrict__ vec,const vobj & __restrict__ extracted,int lane=0)
 | 
			
		||||
{
 | 
			
		||||
@@ -83,7 +93,7 @@ void coalescedWriteNonTemporal(vobj & __restrict__ vec,const vobj & __restrict__
 | 
			
		||||
{
 | 
			
		||||
  vstream(vec, extracted);
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#else //==GRID_SIMT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//#ifndef GRID_SYCL
 | 
			
		||||
@@ -166,6 +176,14 @@ typename vobj::scalar_object coalescedReadPermute(const vobj & __restrict__ vec,
 | 
			
		||||
  return extractLane(plane,vec);
 | 
			
		||||
}
 | 
			
		||||
template<class vobj> accelerator_inline
 | 
			
		||||
typename vobj::scalar_object coalescedReadGeneralPermute(const vobj & __restrict__ vec,int perm_mask,int nd,int lane=acceleratorSIMTlane(vobj::Nsimd()))
 | 
			
		||||
{
 | 
			
		||||
  int plane = lane;
 | 
			
		||||
  for (int d=0;d<nd;d++)
 | 
			
		||||
    plane = (perm_mask & (0x1 << d)) ? plane ^ (vobj::Nsimd() >> (d + 1)) : plane;
 | 
			
		||||
  return extractLane(plane,vec);
 | 
			
		||||
}
 | 
			
		||||
template<class vobj> accelerator_inline
 | 
			
		||||
void coalescedWrite(vobj & __restrict__ vec,const typename vobj::scalar_object & __restrict__ extracted,int lane=acceleratorSIMTlane(vobj::Nsimd()))
 | 
			
		||||
{
 | 
			
		||||
  insertLane(lane,vec,extracted);
 | 
			
		||||
 
 | 
			
		||||
@@ -66,13 +66,61 @@ template<class vtype,int N> accelerator_inline iMatrix<vtype,N> Ta(const iMatrix
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class vtype> accelerator_inline iScalar<vtype> SpTa(const iScalar<vtype>&r)
 | 
			
		||||
{
 | 
			
		||||
  iScalar<vtype> ret;
 | 
			
		||||
  ret._internal = SpTa(r._internal);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
template<class vtype,int N> accelerator_inline iVector<vtype,N> SpTa(const iVector<vtype,N>&r)
 | 
			
		||||
{
 | 
			
		||||
  iVector<vtype,N> ret;
 | 
			
		||||
  for(int i=0;i<N;i++){
 | 
			
		||||
    ret._internal[i] = SpTa(r._internal[i]);
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
template<class vtype,int N, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0 >::type * =nullptr>
 | 
			
		||||
accelerator_inline iMatrix<vtype,N> SpTa(const iMatrix<vtype,N> &arg)
 | 
			
		||||
{
 | 
			
		||||
  // Generalises Ta to Sp2n
 | 
			
		||||
  // Applies the following projections
 | 
			
		||||
  // P_{antihermitian} P_{antihermitian-Sp-algebra} P_{traceless}
 | 
			
		||||
  // where the ordering matters
 | 
			
		||||
  // P_{traceless} subtracts the trace
 | 
			
		||||
  // P_{antihermitian-Sp-algebra} provides the block structure of the algebra based on U = exp(T) i.e. anti-hermitian generators
 | 
			
		||||
  // P_{antihermitian} does in-adj(in) / 2
 | 
			
		||||
  iMatrix<vtype,N> ret(arg);
 | 
			
		||||
  double factor = (1.0/(double)N);
 | 
			
		||||
  vtype nrm;
 | 
			
		||||
  nrm = 0.5;
 | 
			
		||||
    
 | 
			
		||||
  ret = arg - (trace(arg)*factor);
 | 
			
		||||
    
 | 
			
		||||
  for(int c1=0;c1<N/2;c1++)
 | 
			
		||||
  {
 | 
			
		||||
      for(int c2=0;c2<N/2;c2++)
 | 
			
		||||
      {
 | 
			
		||||
          ret._internal[c1][c2] = nrm*(conjugate(ret._internal[c1+N/2][c2+N/2]) + ret._internal[c1][c2]); // new[up-left] = old[up-left]+old*[down-right]
 | 
			
		||||
          ret._internal[c1][c2+N/2] = nrm*(ret._internal[c1][c2+N/2] - conjugate(ret._internal[c1+N/2][c2])); // new[up-right] = old[up-right]-old*[down-left]
 | 
			
		||||
      }
 | 
			
		||||
      for(int c2=N/2;c2<N;c2++)
 | 
			
		||||
      {
 | 
			
		||||
          ret._internal[c1+N/2][c2-N/2] = -conjugate(ret._internal[c1][c2]);  //  reconstructs lower blocks
 | 
			
		||||
          ret._internal[c1+N/2][c2] = conjugate(ret._internal[c1][c2-N/2]);   //  from upper blocks
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  ret = (ret - adj(ret))*0.5;
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/////////////////////////////////////////////// 
 | 
			
		||||
// ProjectOnGroup function for scalar, vector, matrix 
 | 
			
		||||
// Projects on orthogonal, unitary group
 | 
			
		||||
/////////////////////////////////////////////// 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<class vtype> accelerator_inline iScalar<vtype> ProjectOnGroup(const iScalar<vtype>&r)
 | 
			
		||||
{
 | 
			
		||||
  iScalar<vtype> ret;
 | 
			
		||||
@@ -90,10 +138,12 @@ template<class vtype,int N> accelerator_inline iVector<vtype,N> ProjectOnGroup(c
 | 
			
		||||
template<class vtype,int N, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0 >::type * =nullptr> 
 | 
			
		||||
accelerator_inline iMatrix<vtype,N> ProjectOnGroup(const iMatrix<vtype,N> &arg)
 | 
			
		||||
{
 | 
			
		||||
  typedef typename iMatrix<vtype,N>::scalar_type scalar;
 | 
			
		||||
  // need a check for the group type?
 | 
			
		||||
  iMatrix<vtype,N> ret(arg);
 | 
			
		||||
  vtype nrm;
 | 
			
		||||
  vtype inner;
 | 
			
		||||
  scalar one(1.0);
 | 
			
		||||
  for(int c1=0;c1<N;c1++){
 | 
			
		||||
 | 
			
		||||
    // Normalises row c1
 | 
			
		||||
@@ -102,7 +152,7 @@ accelerator_inline iMatrix<vtype,N> ProjectOnGroup(const iMatrix<vtype,N> &arg)
 | 
			
		||||
      inner += innerProduct(ret._internal[c1][c2],ret._internal[c1][c2]);
 | 
			
		||||
 | 
			
		||||
    nrm = sqrt(inner);
 | 
			
		||||
    nrm = 1.0/nrm;
 | 
			
		||||
    nrm = one/nrm;
 | 
			
		||||
    for(int c2=0;c2<N;c2++)
 | 
			
		||||
      ret._internal[c1][c2]*= nrm;
 | 
			
		||||
      
 | 
			
		||||
@@ -127,7 +177,7 @@ accelerator_inline iMatrix<vtype,N> ProjectOnGroup(const iMatrix<vtype,N> &arg)
 | 
			
		||||
      inner += innerProduct(ret._internal[c1][c2],ret._internal[c1][c2]);
 | 
			
		||||
 | 
			
		||||
    nrm = sqrt(inner);
 | 
			
		||||
    nrm = 1.0/nrm;
 | 
			
		||||
    nrm = one/nrm;
 | 
			
		||||
    for(int c2=0;c2<N;c2++)
 | 
			
		||||
      ret._internal[c1][c2]*= nrm;
 | 
			
		||||
  }
 | 
			
		||||
@@ -135,6 +185,85 @@ accelerator_inline iMatrix<vtype,N> ProjectOnGroup(const iMatrix<vtype,N> &arg)
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// re-do for sp2n
 | 
			
		||||
 | 
			
		||||
// Ta cannot be defined here for Sp2n because I need the generators from the Sp class
 | 
			
		||||
// It is defined in gauge impl types
 | 
			
		||||
 | 
			
		||||
template<class vtype> accelerator_inline iScalar<vtype> ProjectOnSpGroup(const iScalar<vtype>&r)
 | 
			
		||||
{
 | 
			
		||||
  iScalar<vtype> ret;
 | 
			
		||||
  ret._internal = ProjectOnSpGroup(r._internal);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
template<class vtype,int N> accelerator_inline iVector<vtype,N> ProjectOnSpGroup(const iVector<vtype,N>&r)
 | 
			
		||||
{
 | 
			
		||||
  iVector<vtype,N> ret;
 | 
			
		||||
  for(int i=0;i<N;i++){
 | 
			
		||||
    ret._internal[i] = ProjectOnSpGroup(r._internal[i]);
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// int N is 2n in Sp(2n)
 | 
			
		||||
template<class vtype,int N, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0 >::type * =nullptr>
 | 
			
		||||
accelerator_inline iMatrix<vtype,N> ProjectOnSpGroup(const iMatrix<vtype,N> &arg)
 | 
			
		||||
{
 | 
			
		||||
  // need a check for the group type?
 | 
			
		||||
  iMatrix<vtype,N> ret(arg);
 | 
			
		||||
  vtype nrm;
 | 
			
		||||
  vtype inner;
 | 
			
		||||
  
 | 
			
		||||
  for(int c1=0;c1<N/2;c1++)
 | 
			
		||||
  {
 | 
			
		||||
      
 | 
			
		||||
    for (int b=0; b<c1; b++)                  // remove the b-rows from U_c1
 | 
			
		||||
    {
 | 
			
		||||
      decltype(ret._internal[b][b]*ret._internal[b][b]) pr;
 | 
			
		||||
      decltype(ret._internal[b][b]*ret._internal[b][b]) prn;
 | 
			
		||||
      zeroit(pr);
 | 
			
		||||
      zeroit(prn);
 | 
			
		||||
          
 | 
			
		||||
      for(int c=0; c<N; c++)
 | 
			
		||||
      {
 | 
			
		||||
        pr += conjugate(ret._internal[c1][c])*ret._internal[b][c];        // <U_c1 | U_b >
 | 
			
		||||
        prn += conjugate(ret._internal[c1][c])*ret._internal[b+N/2][c];   // <U_c1 | U_{b+N} >
 | 
			
		||||
      }
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
      for(int c=0; c<N; c++)
 | 
			
		||||
      {
 | 
			
		||||
        ret._internal[c1][c] -= (conjugate(pr) * ret._internal[b][c] + conjugate(prn) * ret._internal[b+N/2][c] );    //  U_c1 -= (  <U_c1 | U_b > U_b + <U_c1 | U_{b+N} > U_{b+N}  )
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    zeroit(inner);
 | 
			
		||||
    for(int c2=0;c2<N;c2++)
 | 
			
		||||
    {
 | 
			
		||||
      inner += innerProduct(ret._internal[c1][c2],ret._internal[c1][c2]);
 | 
			
		||||
    }
 | 
			
		||||
      
 | 
			
		||||
    nrm = sqrt(inner);
 | 
			
		||||
    nrm = 1.0/nrm;
 | 
			
		||||
    for(int c2=0;c2<N;c2++)
 | 
			
		||||
    {
 | 
			
		||||
      ret._internal[c1][c2]*= nrm;
 | 
			
		||||
    }
 | 
			
		||||
      
 | 
			
		||||
    for(int c2=0;c2<N/2;c2++)
 | 
			
		||||
    {
 | 
			
		||||
      ret._internal[c1+N/2][c2+N/2] = conjugate(ret._internal[c1][c2]);          // down right in the new matrix = (up-left)* of the old matrix
 | 
			
		||||
    }
 | 
			
		||||
      
 | 
			
		||||
    for(int c2=N/2;c2<N;c2++)
 | 
			
		||||
    {
 | 
			
		||||
      ret._internal[c1+N/2][c2-N/2] = -conjugate(ret._internal[c1][c2]);;     // down left in the new matrix = -(up-right)* of the old
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,6 @@ template<class vtype, int N> accelerator_inline iVector<vtype, N> Exponentiate(c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Specialisation: Cayley-Hamilton exponential for SU(3)
 | 
			
		||||
#if 0
 | 
			
		||||
template<class vtype, typename std::enable_if< GridTypeMapper<vtype>::TensorLevel == 0>::type * =nullptr> 
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										637
									
								
								HMC/Mobius2p1p1fEOFA_4Gev.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										637
									
								
								HMC/Mobius2p1p1fEOFA_4Gev.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,637 @@
 | 
			
		||||
/*************************************************************************************
 | 
			
		||||
 | 
			
		||||
Grid physics library, www.github.com/paboyle/Grid
 | 
			
		||||
 | 
			
		||||
Source file: 
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2015-2016
 | 
			
		||||
 | 
			
		||||
Author: Peter Boyle <pabobyle@ph.ed.ac.uk>
 | 
			
		||||
Author: Guido Cossu
 | 
			
		||||
Author: David Murphy
 | 
			
		||||
Author: Chulwoo Jung <chulwoo@bnl.gov>
 | 
			
		||||
 | 
			
		||||
This program is free software; you can redistribute it and/or modify
 | 
			
		||||
it under the terms of the GNU General Public License as published by
 | 
			
		||||
the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
This program is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You should have received a copy of the GNU General Public License along
 | 
			
		||||
with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 | 
			
		||||
See the full license in the file "LICENSE" in the top level distribution
 | 
			
		||||
directory
 | 
			
		||||
*************************************************************************************/
 | 
			
		||||
/*  END LEGAL */
 | 
			
		||||
#include <Grid/Grid.h>
 | 
			
		||||
 | 
			
		||||
#ifdef GRID_DEFAULT_PRECISION_DOUBLE
 | 
			
		||||
#define MIXED_PRECISION
 | 
			
		||||
#endif
 | 
			
		||||
// second level EOFA
 | 
			
		||||
#undef EOFA_H
 | 
			
		||||
#undef USE_OBC
 | 
			
		||||
#define DO_IMPLICIT
 | 
			
		||||
 | 
			
		||||
NAMESPACE_BEGIN(Grid);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Need a plan for gauge field update for mixed precision in HMC                      (2x speed up)
 | 
			
		||||
   *    -- Store the single prec action operator.
 | 
			
		||||
   *    -- Clone the gauge field from the operator function argument.
 | 
			
		||||
   *    -- Build the mixed precision operator dynamically from the passed operator and single prec clone.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  template<class FermionOperatorD, class FermionOperatorF, class SchurOperatorD, class  SchurOperatorF> 
 | 
			
		||||
  class MixedPrecisionConjugateGradientOperatorFunction : public OperatorFunction<typename FermionOperatorD::FermionField> {
 | 
			
		||||
  public:
 | 
			
		||||
    typedef typename FermionOperatorD::FermionField FieldD;
 | 
			
		||||
    typedef typename FermionOperatorF::FermionField FieldF;
 | 
			
		||||
 | 
			
		||||
    using OperatorFunction<FieldD>::operator();
 | 
			
		||||
 | 
			
		||||
    RealD   Tolerance;
 | 
			
		||||
    RealD   InnerTolerance; //Initial tolerance for inner CG. Defaults to Tolerance but can be changed
 | 
			
		||||
    Integer MaxInnerIterations;
 | 
			
		||||
    Integer MaxOuterIterations;
 | 
			
		||||
    GridBase* SinglePrecGrid4; //Grid for single-precision fields
 | 
			
		||||
    GridBase* SinglePrecGrid5; //Grid for single-precision fields
 | 
			
		||||
    RealD OuterLoopNormMult; //Stop the outer loop and move to a final double prec solve when the residual is OuterLoopNormMult * Tolerance
 | 
			
		||||
 | 
			
		||||
    FermionOperatorF &FermOpF;
 | 
			
		||||
    FermionOperatorD &FermOpD;;
 | 
			
		||||
    SchurOperatorF &LinOpF;
 | 
			
		||||
    SchurOperatorD &LinOpD;
 | 
			
		||||
 | 
			
		||||
    Integer TotalInnerIterations; //Number of inner CG iterations
 | 
			
		||||
    Integer TotalOuterIterations; //Number of restarts
 | 
			
		||||
    Integer TotalFinalStepIterations; //Number of CG iterations in final patch-up step
 | 
			
		||||
 | 
			
		||||
    MixedPrecisionConjugateGradientOperatorFunction(RealD tol, 
 | 
			
		||||
						    Integer maxinnerit, 
 | 
			
		||||
						    Integer maxouterit, 
 | 
			
		||||
						    GridBase* _sp_grid4, 
 | 
			
		||||
						    GridBase* _sp_grid5, 
 | 
			
		||||
						    FermionOperatorF &_FermOpF,
 | 
			
		||||
						    FermionOperatorD &_FermOpD,
 | 
			
		||||
						    SchurOperatorF   &_LinOpF,
 | 
			
		||||
						    SchurOperatorD   &_LinOpD): 
 | 
			
		||||
      LinOpF(_LinOpF),
 | 
			
		||||
      LinOpD(_LinOpD),
 | 
			
		||||
      FermOpF(_FermOpF),
 | 
			
		||||
      FermOpD(_FermOpD),
 | 
			
		||||
      Tolerance(tol), 
 | 
			
		||||
      InnerTolerance(tol), 
 | 
			
		||||
      MaxInnerIterations(maxinnerit), 
 | 
			
		||||
      MaxOuterIterations(maxouterit), 
 | 
			
		||||
      SinglePrecGrid4(_sp_grid4),
 | 
			
		||||
      SinglePrecGrid5(_sp_grid5),
 | 
			
		||||
      OuterLoopNormMult(100.) 
 | 
			
		||||
    { 
 | 
			
		||||
      /* Debugging instances of objects; references are stored
 | 
			
		||||
      std::cout << GridLogMessage << " Mixed precision CG wrapper LinOpF " <<std::hex<< &LinOpF<<std::dec <<std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << " Mixed precision CG wrapper LinOpD " <<std::hex<< &LinOpD<<std::dec <<std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << " Mixed precision CG wrapper FermOpF " <<std::hex<< &FermOpF<<std::dec <<std::endl;
 | 
			
		||||
      std::cout << GridLogMessage << " Mixed precision CG wrapper FermOpD " <<std::hex<< &FermOpD<<std::dec <<std::endl;
 | 
			
		||||
      */
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    void operator()(LinearOperatorBase<FieldD> &LinOpU, const FieldD &src, FieldD &psi) {
 | 
			
		||||
 | 
			
		||||
      std::cout << GridLogMessage << " Mixed precision CG wrapper operator() "<<std::endl;
 | 
			
		||||
 | 
			
		||||
      SchurOperatorD * SchurOpU = static_cast<SchurOperatorD *>(&LinOpU);
 | 
			
		||||
      
 | 
			
		||||
      //      std::cout << GridLogMessage << " Mixed precision CG wrapper operator() FermOpU " <<std::hex<< &(SchurOpU->_Mat)<<std::dec <<std::endl;
 | 
			
		||||
      //      std::cout << GridLogMessage << " Mixed precision CG wrapper operator() FermOpD " <<std::hex<< &(LinOpD._Mat) <<std::dec <<std::endl;
 | 
			
		||||
      // Assumption made in code to extract gauge field
 | 
			
		||||
      // We could avoid storing LinopD reference alltogether ?
 | 
			
		||||
      assert(&(SchurOpU->_Mat)==&(LinOpD._Mat));
 | 
			
		||||
 | 
			
		||||
      ////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
      // Must snarf a single precision copy of the gauge field in Linop_d argument
 | 
			
		||||
      ////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
      typedef typename FermionOperatorF::GaugeField GaugeFieldF;
 | 
			
		||||
      typedef typename FermionOperatorF::GaugeLinkField GaugeLinkFieldF;
 | 
			
		||||
      typedef typename FermionOperatorD::GaugeField GaugeFieldD;
 | 
			
		||||
      typedef typename FermionOperatorD::GaugeLinkField GaugeLinkFieldD;
 | 
			
		||||
 | 
			
		||||
      GridBase * GridPtrF = SinglePrecGrid4;
 | 
			
		||||
      GridBase * GridPtrD = FermOpD.Umu.Grid();
 | 
			
		||||
      GaugeFieldF     U_f  (GridPtrF);
 | 
			
		||||
      GaugeLinkFieldF Umu_f(GridPtrF);
 | 
			
		||||
      //      std::cout << " Dim gauge field "<<GridPtrF->Nd()<<std::endl; // 4d
 | 
			
		||||
      //      std::cout << " Dim gauge field "<<GridPtrD->Nd()<<std::endl; // 4d
 | 
			
		||||
 | 
			
		||||
      ////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
      // Moving this to a Clone method of fermion operator would allow to duplicate the 
 | 
			
		||||
      // physics parameters and decrease gauge field copies
 | 
			
		||||
      ////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
      GaugeLinkFieldD Umu_d(GridPtrD);
 | 
			
		||||
      for(int mu=0;mu<Nd*2;mu++){ 
 | 
			
		||||
	Umu_d = PeekIndex<LorentzIndex>(FermOpD.Umu, mu);
 | 
			
		||||
	precisionChange(Umu_f,Umu_d);
 | 
			
		||||
	PokeIndex<LorentzIndex>(FermOpF.Umu, Umu_f, mu);
 | 
			
		||||
      }
 | 
			
		||||
      pickCheckerboard(Even,FermOpF.UmuEven,FermOpF.Umu);
 | 
			
		||||
      pickCheckerboard(Odd ,FermOpF.UmuOdd ,FermOpF.Umu);
 | 
			
		||||
 | 
			
		||||
      ////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
      // Make a mixed precision conjugate gradient
 | 
			
		||||
      ////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
      MixedPrecisionConjugateGradient<FieldD,FieldF> MPCG(Tolerance,MaxInnerIterations,MaxOuterIterations,SinglePrecGrid5,LinOpF,LinOpD);
 | 
			
		||||
      std::cout << GridLogMessage << "Calling mixed precision Conjugate Gradient" <<std::endl;
 | 
			
		||||
      MPCG(src,psi);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
NAMESPACE_END(Grid);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
  using namespace Grid;
 | 
			
		||||
 | 
			
		||||
  Grid_init(&argc, &argv);
 | 
			
		||||
  int threads = GridThread::GetThreads();
 | 
			
		||||
  // here make a routine to print all the relevant information on the run
 | 
			
		||||
  std::cout << GridLogMessage << "Grid is setup to use " << threads << " threads" << std::endl;
 | 
			
		||||
 | 
			
		||||
   // Typedefs to simplify notation
 | 
			
		||||
  typedef WilsonImplR FermionImplPolicy;
 | 
			
		||||
  typedef MobiusFermionD FermionAction;
 | 
			
		||||
  typedef MobiusFermionF FermionActionF;
 | 
			
		||||
  typedef MobiusEOFAFermionD FermionEOFAAction;
 | 
			
		||||
  typedef MobiusEOFAFermionF FermionEOFAActionF;
 | 
			
		||||
  typedef typename FermionAction::FermionField FermionField;
 | 
			
		||||
  typedef typename FermionActionF::FermionField FermionFieldF;
 | 
			
		||||
 | 
			
		||||
  typedef Grid::XmlReader       Serialiser;
 | 
			
		||||
  
 | 
			
		||||
  //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 | 
			
		||||
 | 
			
		||||
  HMCparameters HMCparams;
 | 
			
		||||
#if 1
 | 
			
		||||
  {
 | 
			
		||||
    XmlReader  HMCrd("HMCparameters.xml");
 | 
			
		||||
    read(HMCrd,"HMCparameters",HMCparams);
 | 
			
		||||
  }
 | 
			
		||||
#else
 | 
			
		||||
  {
 | 
			
		||||
//    HMCparameters HMCparams;
 | 
			
		||||
  //  "[HotStart, ColdStart, TepidStart, CheckpointStart]\n";
 | 
			
		||||
  //  HMCparams.StartingType     =std::string("ColdStart");
 | 
			
		||||
    HMCparams.StartingType     =std::string("CheckpointStart");
 | 
			
		||||
    HMCparams.StartTrajectory  =7;
 | 
			
		||||
    HMCparams.SW  =4;
 | 
			
		||||
    HMCparams.Trajectories     =1000;
 | 
			
		||||
    HMCparams.NoMetropolisUntil=0;
 | 
			
		||||
    HMCparams.MD.name          =std::string("Force Gradient");
 | 
			
		||||
    HMCparams.MD.MDsteps       = 10;
 | 
			
		||||
    HMCparams.MD.trajL         = 1.0;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DO_IMPLICIT
 | 
			
		||||
//    typedef GenericHMCRunner<ImplicitLeapFrog> HMCWrapper; 
 | 
			
		||||
  typedef GenericHMCRunner<ImplicitMinimumNorm2> HMCWrapper; 
 | 
			
		||||
  HMCparams.MD.name          =std::string("ImplicitMinimumNorm2");
 | 
			
		||||
#else
 | 
			
		||||
//  typedef GenericHMCRunner<LeapFrog> HMCWrapper; 
 | 
			
		||||
  typedef GenericHMCRunner<ForceGradient> HMCWrapper; 
 | 
			
		||||
//  typedef GenericHMCRunner<MinimumNorm2> HMCWrapper; 
 | 
			
		||||
  HMCparams.MD.name          =std::string("ForceGradient");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  std::cout << GridLogMessage<< HMCparams <<std::endl;
 | 
			
		||||
  HMCWrapper TheHMC(HMCparams);
 | 
			
		||||
  TheHMC.ReadCommandLine(argc, argv);
 | 
			
		||||
  { 
 | 
			
		||||
    XmlWriter HMCwr("HMCparameters.xml.out");
 | 
			
		||||
    write(HMCwr,"HMCparameters",TheHMC.Parameters);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Grid from the command line arguments --grid and --mpi
 | 
			
		||||
  TheHMC.Resources.AddFourDimGrid("gauge"); // use default simd lanes decomposition
 | 
			
		||||
  
 | 
			
		||||
  CheckpointerParameters CPparams;
 | 
			
		||||
  CPparams.config_prefix = "ckpoint_lat";
 | 
			
		||||
  CPparams.rng_prefix    = "ckpoint_rng";
 | 
			
		||||
  CPparams.saveInterval  = 1;
 | 
			
		||||
  CPparams.format        = "IEEE64BIG";
 | 
			
		||||
  TheHMC.Resources.LoadNerscCheckpointer(CPparams);
 | 
			
		||||
 | 
			
		||||
  RNGModuleParameters RNGpar;
 | 
			
		||||
  RNGpar.serial_seeds = "1 2 3 4 5";
 | 
			
		||||
  RNGpar.parallel_seeds = "6 7 8 9 10";
 | 
			
		||||
  TheHMC.Resources.SetRNGSeeds(RNGpar);
 | 
			
		||||
 | 
			
		||||
  // Construct observables
 | 
			
		||||
  // here there is too much indirection 
 | 
			
		||||
  typedef PlaquetteMod<HMCWrapper::ImplPolicy> PlaqObs;
 | 
			
		||||
  TheHMC.Resources.AddObservable<PlaqObs>();
 | 
			
		||||
  //////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  const int Ls      = 12;
 | 
			
		||||
  Real beta         = 5.983;
 | 
			
		||||
  std::cout << GridLogMessage << " beta  "<< beta << std::endl;
 | 
			
		||||
  Real light_mass   = 0.00049;
 | 
			
		||||
  Real strange_mass = 0.0158;
 | 
			
		||||
  Real charm_mass = 0.191;
 | 
			
		||||
  Real pv_mass    = 1.0;
 | 
			
		||||
  RealD M5  = 1.4;
 | 
			
		||||
  RealD b   = 2.0; 
 | 
			
		||||
  RealD c   = 1.0;
 | 
			
		||||
 | 
			
		||||
  // Copied from paper
 | 
			
		||||
//  std::vector<Real> hasenbusch({ 0.045 }); // Paper values from F1 incorrect run
 | 
			
		||||
  std::vector<Real> hasenbusch({ 0.0038, 0.0145, 0.045, 0.108 , 0.25, 0.51 }); // Paper values from F1 incorrect run
 | 
			
		||||
  std::vector<Real> hasenbusch2({ 0.4 }); // Paper values from F1 incorrect run
 | 
			
		||||
 | 
			
		||||
//  RealD eofa_mass=0.05 ;
 | 
			
		||||
 | 
			
		||||
  ///////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  //Bad choices with large dH. Equalising force L2 norm was not wise.
 | 
			
		||||
  ///////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  //std::vector<Real> hasenbusch({ 0.03, 0.2, 0.3, 0.5, 0.8 }); 
 | 
			
		||||
 | 
			
		||||
  auto GridPtr   = TheHMC.Resources.GetCartesian();
 | 
			
		||||
  auto GridRBPtr = TheHMC.Resources.GetRBCartesian();
 | 
			
		||||
  auto FGrid     = SpaceTimeGrid::makeFiveDimGrid(Ls,GridPtr);
 | 
			
		||||
  auto FrbGrid   = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,GridPtr);
 | 
			
		||||
 | 
			
		||||
  Coordinate latt  = GridDefaultLatt();
 | 
			
		||||
  Coordinate mpi   = GridDefaultMpi();
 | 
			
		||||
  Coordinate simdF = GridDefaultSimd(Nd,vComplexF::Nsimd());
 | 
			
		||||
  Coordinate simdD = GridDefaultSimd(Nd,vComplexD::Nsimd());
 | 
			
		||||
//  auto GridPtrF   = SpaceTimeGrid::makeFourDimGrid(latt,simdF,mpi);
 | 
			
		||||
  auto UGrid_f    = SpaceTimeGrid::makeFourDimGrid(latt,simdF,mpi);
 | 
			
		||||
  auto GridRBPtrF = SpaceTimeGrid::makeFourDimRedBlackGrid(UGrid_f);
 | 
			
		||||
  auto FGridF     = SpaceTimeGrid::makeFiveDimGrid(Ls,UGrid_f);
 | 
			
		||||
  auto FrbGridF   = SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls,UGrid_f);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef USE_OBC
 | 
			
		||||
//  IwasakiGaugeActionR GaugeAction(beta);
 | 
			
		||||
  WilsonGaugeActionR GaugeAction(beta);
 | 
			
		||||
#else
 | 
			
		||||
  std::vector<Complex> boundaryG = {1,1,1,0};
 | 
			
		||||
  WilsonGaugeActionR::ImplParams ParamsG(boundaryG);
 | 
			
		||||
  WilsonGaugeActionR GaugeAction(beta,ParamsG);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // temporarily need a gauge field
 | 
			
		||||
  LatticeGaugeField U(GridPtr);
 | 
			
		||||
  LatticeGaugeFieldF UF(UGrid_f);
 | 
			
		||||
 | 
			
		||||
  // These lines are unecessary if BC are all periodic
 | 
			
		||||
#ifndef USE_OBC
 | 
			
		||||
  std::vector<Complex> boundary = {1,1,1,-1};
 | 
			
		||||
#else
 | 
			
		||||
  std::vector<Complex> boundary = {1,1,1,0};
 | 
			
		||||
#endif
 | 
			
		||||
  FermionAction::ImplParams Params(boundary);
 | 
			
		||||
  FermionActionF::ImplParams ParamsF(boundary);
 | 
			
		||||
  
 | 
			
		||||
  double ActionStoppingCondition     = 1e-8;
 | 
			
		||||
  double DerivativeStoppingCondition = 1e-8;
 | 
			
		||||
  double MaxCGIterations =  100000;
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // Collect actions
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  ActionLevel<HMCWrapper::Field> Level1(1);
 | 
			
		||||
  ActionLevel<HMCWrapper::Field> Level2(HMCparams.SW);
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // Strange action
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  typedef SchurDiagMooeeOperator<FermionActionF,FermionFieldF> LinearOperatorF;
 | 
			
		||||
  typedef SchurDiagMooeeOperator<FermionAction ,FermionField > LinearOperatorD;
 | 
			
		||||
  typedef SchurDiagMooeeOperator<FermionEOFAActionF,FermionFieldF> LinearOperatorEOFAF;
 | 
			
		||||
  typedef SchurDiagMooeeOperator<FermionEOFAAction ,FermionField > LinearOperatorEOFAD;
 | 
			
		||||
 | 
			
		||||
  typedef MixedPrecisionConjugateGradientOperatorFunction<MobiusFermionD,MobiusFermionF,LinearOperatorD,LinearOperatorF> MxPCG;
 | 
			
		||||
  typedef MixedPrecisionConjugateGradientOperatorFunction<MobiusEOFAFermionD,MobiusEOFAFermionF,LinearOperatorEOFAD,LinearOperatorEOFAF> MxPCG_EOFA;
 | 
			
		||||
 | 
			
		||||
  // DJM: setup for EOFA ratio (Mobius)
 | 
			
		||||
  OneFlavourRationalParams OFRp;
 | 
			
		||||
  OFRp.lo       = 0.99; // How do I know this on F1?
 | 
			
		||||
  OFRp.hi       = 20;
 | 
			
		||||
  OFRp.MaxIter  = 100000;
 | 
			
		||||
  OFRp.tolerance= 1.0e-12;
 | 
			
		||||
  OFRp.degree   = 12;
 | 
			
		||||
  OFRp.precision= 50;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  MobiusEOFAFermionD Strange_Op_L (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , strange_mass, strange_mass, charm_mass, 0.0, -1, M5, b, c);
 | 
			
		||||
  MobiusEOFAFermionF Strange_Op_LF(UF, *FGridF, *FrbGridF, *UGrid_f, *GridRBPtrF, strange_mass, strange_mass, charm_mass, 0.0, -1, M5, b, c);
 | 
			
		||||
  MobiusEOFAFermionD Strange_Op_R (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , charm_mass, strange_mass,      charm_mass, -1.0, 1, M5, b, c);
 | 
			
		||||
  MobiusEOFAFermionF Strange_Op_RF(UF, *FGridF, *FrbGridF, *UGrid_f, *GridRBPtrF, charm_mass, strange_mass,      charm_mass, -1.0, 1, M5, b, c);
 | 
			
		||||
  
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MobiusEOFAFermionD Strange2_Op_L (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , eofa_mass, eofa_mass, charm_mass , 0.0, -1, M5, b, c);
 | 
			
		||||
  MobiusEOFAFermionF Strange2_Op_LF(UF, *FGridF, *FrbGridF, *UGrid_f, *GridRBPtrF, eofa_mass, eofa_mass, charm_mass , 0.0, -1, M5, b, c);
 | 
			
		||||
  MobiusEOFAFermionD Strange2_Op_R (U , *FGrid , *FrbGrid , *GridPtr , *GridRBPtr , charm_mass , eofa_mass,      charm_mass , -1.0, 1, M5, b, c);
 | 
			
		||||
  MobiusEOFAFermionF Strange2_Op_RF(UF, *FGridF, *FrbGridF, *UGrid_f, *GridRBPtrF, charm_mass , eofa_mass,      charm_mass , -1.0, 1, M5, b, c);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  ConjugateGradient<FermionField>      ActionCG(ActionStoppingCondition,MaxCGIterations);
 | 
			
		||||
  ConjugateGradient<FermionField>  DerivativeCG(DerivativeStoppingCondition,MaxCGIterations);
 | 
			
		||||
#ifdef MIXED_PRECISION
 | 
			
		||||
  const int MX_inner = 50000;
 | 
			
		||||
 | 
			
		||||
  // Mixed precision EOFA
 | 
			
		||||
  LinearOperatorEOFAD Strange_LinOp_L (Strange_Op_L);
 | 
			
		||||
  LinearOperatorEOFAD Strange_LinOp_R (Strange_Op_R);
 | 
			
		||||
  LinearOperatorEOFAF Strange_LinOp_LF(Strange_Op_LF);
 | 
			
		||||
  LinearOperatorEOFAF Strange_LinOp_RF(Strange_Op_RF);
 | 
			
		||||
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  // Mixed precision EOFA
 | 
			
		||||
  LinearOperatorEOFAD Strange2_LinOp_L (Strange2_Op_L);
 | 
			
		||||
  LinearOperatorEOFAD Strange2_LinOp_R (Strange2_Op_R);
 | 
			
		||||
  LinearOperatorEOFAF Strange2_LinOp_LF(Strange2_Op_LF);
 | 
			
		||||
  LinearOperatorEOFAF Strange2_LinOp_RF(Strange2_Op_RF);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  MxPCG_EOFA ActionCGL(ActionStoppingCondition,
 | 
			
		||||
		       MX_inner,
 | 
			
		||||
		       MaxCGIterations,
 | 
			
		||||
		       UGrid_f,
 | 
			
		||||
		       FrbGridF,
 | 
			
		||||
		       Strange_Op_LF,Strange_Op_L,
 | 
			
		||||
		       Strange_LinOp_LF,Strange_LinOp_L);
 | 
			
		||||
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MxPCG_EOFA ActionCGL2(ActionStoppingCondition,
 | 
			
		||||
		       MX_inner,
 | 
			
		||||
		       MaxCGIterations,
 | 
			
		||||
		       UGrid_f,
 | 
			
		||||
		       FrbGridF,
 | 
			
		||||
		       Strange2_Op_LF,Strange2_Op_L,
 | 
			
		||||
		       Strange2_LinOp_LF,Strange2_LinOp_L);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  MxPCG_EOFA DerivativeCGL(DerivativeStoppingCondition,
 | 
			
		||||
			   MX_inner,
 | 
			
		||||
			   MaxCGIterations,
 | 
			
		||||
			   UGrid_f,
 | 
			
		||||
			   FrbGridF,
 | 
			
		||||
			   Strange_Op_LF,Strange_Op_L,
 | 
			
		||||
			   Strange_LinOp_LF,Strange_LinOp_L);
 | 
			
		||||
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MxPCG_EOFA DerivativeCGL2(DerivativeStoppingCondition,
 | 
			
		||||
			   MX_inner,
 | 
			
		||||
			   MaxCGIterations,
 | 
			
		||||
			   UGrid_f,
 | 
			
		||||
			   FrbGridF,
 | 
			
		||||
			   Strange2_Op_LF,Strange2_Op_L,
 | 
			
		||||
			   Strange2_LinOp_LF,Strange2_LinOp_L);
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
  MxPCG_EOFA ActionCGR(ActionStoppingCondition,
 | 
			
		||||
		       MX_inner,
 | 
			
		||||
		       MaxCGIterations,
 | 
			
		||||
		       UGrid_f,
 | 
			
		||||
		       FrbGridF,
 | 
			
		||||
		       Strange_Op_RF,Strange_Op_R,
 | 
			
		||||
		       Strange_LinOp_RF,Strange_LinOp_R);
 | 
			
		||||
  
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MxPCG_EOFA ActionCGR2(ActionStoppingCondition,
 | 
			
		||||
		       MX_inner,
 | 
			
		||||
		       MaxCGIterations,
 | 
			
		||||
		       UGrid_f,
 | 
			
		||||
		       FrbGridF,
 | 
			
		||||
		       Strange2_Op_RF,Strange2_Op_R,
 | 
			
		||||
		       Strange2_LinOp_RF,Strange2_LinOp_R);
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
  MxPCG_EOFA DerivativeCGR(DerivativeStoppingCondition,
 | 
			
		||||
			   MX_inner,
 | 
			
		||||
			   MaxCGIterations,
 | 
			
		||||
			   UGrid_f,
 | 
			
		||||
			   FrbGridF,
 | 
			
		||||
			   Strange_Op_RF,Strange_Op_R,
 | 
			
		||||
			   Strange_LinOp_RF,Strange_LinOp_R);
 | 
			
		||||
  
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  MxPCG_EOFA DerivativeCGR2(DerivativeStoppingCondition,
 | 
			
		||||
			   MX_inner,
 | 
			
		||||
			   MaxCGIterations,
 | 
			
		||||
			   UGrid_f,
 | 
			
		||||
			   FrbGridF,
 | 
			
		||||
			   Strange2_Op_RF,Strange2_Op_R,
 | 
			
		||||
			   Strange2_LinOp_RF,Strange2_LinOp_R);
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
  ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> 
 | 
			
		||||
    EOFA(Strange_Op_L, Strange_Op_R, 
 | 
			
		||||
	 ActionCG, 
 | 
			
		||||
	 ActionCGL, ActionCGR,
 | 
			
		||||
	 DerivativeCGL, DerivativeCGR,
 | 
			
		||||
	 OFRp, true);
 | 
			
		||||
  
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> 
 | 
			
		||||
    EOFA2(Strange2_Op_L, Strange2_Op_R, 
 | 
			
		||||
	 ActionCG, 
 | 
			
		||||
	 ActionCGL2, ActionCGR2,
 | 
			
		||||
	 DerivativeCGL2, DerivativeCGR2,
 | 
			
		||||
	 OFRp, true);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  Level1.push_back(&EOFA);
 | 
			
		||||
#ifdef EOFA_H
 | 
			
		||||
  Level1.push_back(&EOFA2);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
  ExactOneFlavourRatioPseudoFermionAction<FermionImplPolicy> 
 | 
			
		||||
    EOFA(Strange_Op_L, Strange_Op_R, 
 | 
			
		||||
	 ActionCG, 
 | 
			
		||||
	 ActionCG, ActionCG,
 | 
			
		||||
	 ActionCG, ActionCG,
 | 
			
		||||
	 //         DerivativeCG, DerivativeCG,
 | 
			
		||||
	 OFRp, true);
 | 
			
		||||
  Level1.push_back(&EOFA);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // up down action
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  std::vector<Real> light_den;
 | 
			
		||||
  std::vector<Real> light_num;
 | 
			
		||||
 | 
			
		||||
  int n_hasenbusch = hasenbusch.size();
 | 
			
		||||
  light_den.push_back(light_mass);
 | 
			
		||||
  for(int h=0;h<n_hasenbusch;h++){
 | 
			
		||||
    light_den.push_back(hasenbusch[h]);
 | 
			
		||||
    light_num.push_back(hasenbusch[h]);
 | 
			
		||||
  }
 | 
			
		||||
  light_num.push_back(pv_mass);
 | 
			
		||||
 | 
			
		||||
  int n_hasenbusch2 = hasenbusch2.size();
 | 
			
		||||
  light_den.push_back(charm_mass);
 | 
			
		||||
  for(int h=0;h<n_hasenbusch2;h++){
 | 
			
		||||
    light_den.push_back(hasenbusch2[h]);
 | 
			
		||||
    light_num.push_back(hasenbusch2[h]);
 | 
			
		||||
  }
 | 
			
		||||
  light_num.push_back(pv_mass);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////
 | 
			
		||||
  // Forced to replicate the MxPCG and DenominatorsF etc.. because
 | 
			
		||||
  // there is no convenient way to "Clone" physics params from double op
 | 
			
		||||
  // into single op for any operator pair.
 | 
			
		||||
  // Same issue prevents using MxPCG in the Heatbath step
 | 
			
		||||
  //////////////////////////////////////////////////////////////
 | 
			
		||||
  std::vector<FermionAction *> Numerators;
 | 
			
		||||
  std::vector<FermionAction *> Denominators;
 | 
			
		||||
  std::vector<TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy> *> Quotients;
 | 
			
		||||
  std::vector<MxPCG *> ActionMPCG;
 | 
			
		||||
  std::vector<MxPCG *> MPCG;
 | 
			
		||||
  std::vector<FermionActionF *> DenominatorsF;
 | 
			
		||||
  std::vector<LinearOperatorD *> LinOpD;
 | 
			
		||||
  std::vector<LinearOperatorF *> LinOpF; 
 | 
			
		||||
 | 
			
		||||
  for(int h=0;h<light_den.size();h++){
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << " 2f quotient Action  "<< light_num[h] << " / " << light_den[h]<< std::endl;
 | 
			
		||||
 | 
			
		||||
    Numerators.push_back  (new FermionAction(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_num[h],M5,b,c, Params));
 | 
			
		||||
    Denominators.push_back(new FermionAction(U,*FGrid,*FrbGrid,*GridPtr,*GridRBPtr,light_den[h],M5,b,c, Params));
 | 
			
		||||
 | 
			
		||||
#ifdef MIXED_PRECISION
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // Mixed precision CG for 2f force
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    double DerivativeStoppingConditionLoose = 1e-8;
 | 
			
		||||
 | 
			
		||||
    DenominatorsF.push_back(new FermionActionF(UF,*FGridF,*FrbGridF,*UGrid_f,*GridRBPtrF,light_den[h],M5,b,c, ParamsF));
 | 
			
		||||
    LinOpD.push_back(new LinearOperatorD(*Denominators[h]));
 | 
			
		||||
    LinOpF.push_back(new LinearOperatorF(*DenominatorsF[h]));
 | 
			
		||||
 | 
			
		||||
    double conv  = DerivativeStoppingCondition;
 | 
			
		||||
    if (h<3) conv= DerivativeStoppingConditionLoose; // Relax on first two hasenbusch factors
 | 
			
		||||
    MPCG.push_back(new MxPCG(conv,
 | 
			
		||||
			     MX_inner,
 | 
			
		||||
			     MaxCGIterations,
 | 
			
		||||
			     UGrid_f,
 | 
			
		||||
			     FrbGridF,
 | 
			
		||||
			     *DenominatorsF[h],*Denominators[h],
 | 
			
		||||
			     *LinOpF[h], *LinOpD[h]) );
 | 
			
		||||
 | 
			
		||||
    ActionMPCG.push_back(new MxPCG(ActionStoppingCondition,
 | 
			
		||||
				   MX_inner,
 | 
			
		||||
				   MaxCGIterations,
 | 
			
		||||
				   UGrid_f,
 | 
			
		||||
				   FrbGridF,
 | 
			
		||||
				   *DenominatorsF[h],*Denominators[h],
 | 
			
		||||
				   *LinOpF[h], *LinOpD[h]) );
 | 
			
		||||
 | 
			
		||||
    // Heatbath not mixed yet. As inverts numerators not so important as raised mass.
 | 
			
		||||
    Quotients.push_back (new TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy>(*Numerators[h],*Denominators[h],*MPCG[h],*ActionMPCG[h],ActionCG));
 | 
			
		||||
#else
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // Standard CG for 2f force
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    Quotients.push_back   (new TwoFlavourEvenOddRatioPseudoFermionAction<FermionImplPolicy>(*Numerators[h],*Denominators[h],DerivativeCG,ActionCG));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for(int h=0;h<n_hasenbusch+1;h++){
 | 
			
		||||
    Level1.push_back(Quotients[h]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////////////
 | 
			
		||||
  // Gauge action
 | 
			
		||||
  /////////////////////////////////////////////////////////////
 | 
			
		||||
  Level2.push_back(&GaugeAction);
 | 
			
		||||
  TheHMC.TheAction.push_back(Level1);
 | 
			
		||||
  TheHMC.TheAction.push_back(Level2);
 | 
			
		||||
  std::cout << GridLogMessage << " Action complete "<< std::endl;
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////////////
 | 
			
		||||
  // HMC parameters are serialisable
 | 
			
		||||
 | 
			
		||||
  NoSmearing<HMCWrapper::ImplPolicy> S;
 | 
			
		||||
#ifndef DO_IMPLICIT
 | 
			
		||||
  TrivialMetric<HMCWrapper::ImplPolicy::Field> Mtr;
 | 
			
		||||
#else
 | 
			
		||||
    LaplacianRatParams gpar(2),mpar(2);
 | 
			
		||||
    gpar.offset = 1.;
 | 
			
		||||
    gpar.a0[0] = 500.;
 | 
			
		||||
    gpar.a1[0] = 0.;
 | 
			
		||||
    gpar.b0[0] = 0.25;
 | 
			
		||||
    gpar.b1[0] = 1.;
 | 
			
		||||
    gpar.a0[1] = -500.;
 | 
			
		||||
    gpar.a1[1] = 0.;
 | 
			
		||||
    gpar.b0[1] = 0.36;
 | 
			
		||||
    gpar.b1[1] = 1.2;
 | 
			
		||||
    gpar.b2=1.;
 | 
			
		||||
 | 
			
		||||
    mpar.offset = 1.;
 | 
			
		||||
    mpar.a0[0] =  -0.850891906532;
 | 
			
		||||
    mpar.a1[0] = -1.54707654538;
 | 
			
		||||
    mpar. b0[0] = 2.85557166137;
 | 
			
		||||
    mpar. b1[0] = 5.74194794773;
 | 
			
		||||
    mpar.a0[1] = -13.5120056831218384729709214298;
 | 
			
		||||
    mpar.a1[1] = 1.54707654538396877086370295729;
 | 
			
		||||
    mpar.b0[1] = 19.2921090880640520026645390317;
 | 
			
		||||
    mpar.b1[1] = -3.54194794773029020262811172870;
 | 
			
		||||
    mpar.b2=1.;
 | 
			
		||||
    for(int i=0;i<2;i++){
 | 
			
		||||
       gpar.a1[i] *=16.;
 | 
			
		||||
       gpar.b1[i] *=16.;
 | 
			
		||||
       mpar.a1[i] *=16.;
 | 
			
		||||
       mpar.b1[i] *=16.;
 | 
			
		||||
    }
 | 
			
		||||
    gpar.b2 *= 16.*16.;
 | 
			
		||||
    mpar.b2 *= 16.*16.;
 | 
			
		||||
 | 
			
		||||
    ConjugateGradient<LatticeGaugeField> CG(1.0e-8,10000);
 | 
			
		||||
    LaplacianParams LapPar(0.0001, 1.0, 10000, 1e-8, 12, 64);
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "LaplacianRat " << std::endl;
 | 
			
		||||
    gpar.tolerance=HMCparams.MD.RMHMCCGTol;
 | 
			
		||||
    mpar.tolerance=HMCparams.MD.RMHMCCGTol;
 | 
			
		||||
    std::cout << GridLogMessage << "gpar offset= " << gpar.offset <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a0= " << gpar.a0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a1= " << gpar.a1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b0= " << gpar.b0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b1= " << gpar.b1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b2= " << gpar.b2 <<std::endl ;;
 | 
			
		||||
 | 
			
		||||
    std::cout << GridLogMessage << "mpar offset= " << mpar.offset <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a0= " << mpar.a0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " a1= " << mpar.a1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b0= " << mpar.b0 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b1= " << mpar.b1 <<std::endl;
 | 
			
		||||
    std::cout << GridLogMessage << " b2= " << mpar.b2 <<std::endl;
 | 
			
		||||
//  Assumes PeriodicGimplR or D at the moment
 | 
			
		||||
    auto UGrid = TheHMC.Resources.GetCartesian("gauge");
 | 
			
		||||
//    auto UGrid_f   = GridPtrF;
 | 
			
		||||
//  auto GridPtrF   = SpaceTimeGrid::makeFourDimGrid(latt,simdF,mpi);
 | 
			
		||||
//    std::cout << GridLogMessage << " UGrid= " << UGrid <<std::endl;
 | 
			
		||||
//    std::cout << GridLogMessage << " UGrid_f= " << UGrid_f <<std::endl;
 | 
			
		||||
 | 
			
		||||
    LaplacianAdjointRat<HMCWrapper::ImplPolicy, PeriodicGimplF> Mtr(UGrid, UGrid_f ,CG, gpar, mpar);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  std::cout << GridLogMessage << " Running the HMC "<< std::endl;
 | 
			
		||||
  TheHMC.Run(S,Mtr);  // no smearing
 | 
			
		||||
 | 
			
		||||
  Grid_finalize();
 | 
			
		||||
} // main
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -365,9 +365,15 @@ public:
 | 
			
		||||
    GridParallelRNG          RNG5(FGrid);  RNG5.SeedFixedIntegers(seeds5);
 | 
			
		||||
    std::cout << GridLogMessage << "Initialised RNGs" << std::endl;
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
    typedef DomainWallFermionF Action;
 | 
			
		||||
    typedef typename Action::FermionField Fermion;
 | 
			
		||||
    typedef LatticeGaugeFieldF Gauge;
 | 
			
		||||
#else
 | 
			
		||||
    typedef GparityDomainWallFermionF Action;
 | 
			
		||||
    typedef typename Action::FermionField Fermion;
 | 
			
		||||
    typedef LatticeGaugeFieldF Gauge;
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    ///////// Source preparation ////////////
 | 
			
		||||
    Gauge Umu(UGrid);  SU<Nc>::HotConfiguration(RNG4,Umu); 
 | 
			
		||||
@@ -635,6 +641,170 @@ public:
 | 
			
		||||
    std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
    return mflops_best;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static double Laplace(int L)
 | 
			
		||||
  {
 | 
			
		||||
    double mflops;
 | 
			
		||||
    double mflops_best = 0;
 | 
			
		||||
    double mflops_worst= 0;
 | 
			
		||||
    std::vector<double> mflops_all;
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////
 | 
			
		||||
    // Set/Get the layout & grid size
 | 
			
		||||
    ///////////////////////////////////////////////////////
 | 
			
		||||
    int threads = GridThread::GetThreads();
 | 
			
		||||
    Coordinate mpi = GridDefaultMpi(); assert(mpi.size()==4);
 | 
			
		||||
    Coordinate local({L,L,L,L});
 | 
			
		||||
    Coordinate latt4({local[0]*mpi[0],local[1]*mpi[1],local[2]*mpi[2],local[3]*mpi[3]});
 | 
			
		||||
    
 | 
			
		||||
    GridCartesian         * TmpGrid   = SpaceTimeGrid::makeFourDimGrid(latt4,
 | 
			
		||||
								       GridDefaultSimd(Nd,vComplex::Nsimd()),
 | 
			
		||||
								       GridDefaultMpi());
 | 
			
		||||
    uint64_t NP = TmpGrid->RankCount();
 | 
			
		||||
    uint64_t NN = TmpGrid->NodeCount();
 | 
			
		||||
    NN_global=NN;
 | 
			
		||||
    uint64_t SHM=NP/NN;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    ///////// Welcome message ////////////
 | 
			
		||||
    std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "Benchmark Laplace on "<<L<<"^4 local volume "<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* Global volume  : "<<GridCmdVectorIntToString(latt4)<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* ranks          : "<<NP  <<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* nodes          : "<<NN  <<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* ranks/node     : "<<SHM <<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* ranks geom     : "<<GridCmdVectorIntToString(mpi)<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "* Using "<<threads<<" threads"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
 | 
			
		||||
    ///////// Lattice Init ////////////
 | 
			
		||||
    GridCartesian         * FGrid   = SpaceTimeGrid::makeFourDimGrid(latt4, GridDefaultSimd(Nd,vComplexF::Nsimd()),GridDefaultMpi());
 | 
			
		||||
    GridRedBlackCartesian * FrbGrid = SpaceTimeGrid::makeFourDimRedBlackGrid(FGrid);
 | 
			
		||||
    
 | 
			
		||||
    ///////// RNG Init ////////////
 | 
			
		||||
    std::vector<int> seeds4({1,2,3,4});
 | 
			
		||||
    GridParallelRNG          RNG4(FGrid);  RNG4.SeedFixedIntegers(seeds4);
 | 
			
		||||
    std::cout << GridLogMessage << "Initialised RNGs" << std::endl;
 | 
			
		||||
 | 
			
		||||
    RealD mass=0.1;
 | 
			
		||||
    RealD c1=9.0/8.0;
 | 
			
		||||
    RealD c2=-1.0/24.0;
 | 
			
		||||
    RealD u0=1.0;
 | 
			
		||||
 | 
			
		||||
//    typedef ImprovedStaggeredFermionF Action;
 | 
			
		||||
//    typedef typename Action::FermionField Fermion; 
 | 
			
		||||
    typedef LatticeGaugeFieldF Gauge;
 | 
			
		||||
    
 | 
			
		||||
    Gauge Umu(FGrid);  SU<Nc>::HotConfiguration(RNG4,Umu); 
 | 
			
		||||
 | 
			
		||||
//    typename Action::ImplParams params;
 | 
			
		||||
//    Action Ds(Umu,Umu,*FGrid,*FrbGrid,mass,c1,c2,u0,params);
 | 
			
		||||
 | 
			
		||||
//  PeriodicGimplF
 | 
			
		||||
    typedef typename PeriodicGimplF::LinkField GaugeLinkFieldF;
 | 
			
		||||
 | 
			
		||||
    ///////// Source preparation ////////////
 | 
			
		||||
    GaugeLinkFieldF src   (FGrid); random(RNG4,src);
 | 
			
		||||
//    GaugeLinkFieldF src_e (FrbGrid);
 | 
			
		||||
//    GaugeLinkFieldF src_o (FrbGrid);
 | 
			
		||||
//    GaugeLinkFieldF r_e   (FrbGrid);
 | 
			
		||||
//    GaugeLinkFieldF r_o   (FrbGrid);
 | 
			
		||||
    GaugeLinkFieldF r_eo  (FGrid);
 | 
			
		||||
  
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
 //     pickCheckerboard(Even,src_e,src);
 | 
			
		||||
 //     pickCheckerboard(Odd,src_o,src);
 | 
			
		||||
    
 | 
			
		||||
      const int num_cases = 1;
 | 
			
		||||
      std::string fmt("G/O/C  ");
 | 
			
		||||
      
 | 
			
		||||
      controls Cases [] = {
 | 
			
		||||
	{  StaggeredKernelsStatic::OptGeneric   ,  StaggeredKernelsStatic::CommsAndCompute  ,CartesianCommunicator::CommunicatorPolicyConcurrent  },
 | 
			
		||||
      }; 
 | 
			
		||||
 | 
			
		||||
      for(int c=0;c<num_cases;c++) {
 | 
			
		||||
        CovariantAdjointLaplacianStencil<PeriodicGimplF,typename PeriodicGimplF::LinkField> LapStencilF(FGrid);
 | 
			
		||||
        QuadLinearOperator<CovariantAdjointLaplacianStencil<PeriodicGimplF,typename PeriodicGimplF::LinkField>,PeriodicGimplF::LinkField> QuadOpF(LapStencilF,c2,c1,1.);
 | 
			
		||||
        LapStencilF.GaugeImport(Umu);
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	StaggeredKernelsStatic::Comms = Cases[c].CommsOverlap;
 | 
			
		||||
	StaggeredKernelsStatic::Opt   = Cases[c].Opt;
 | 
			
		||||
	CartesianCommunicator::SetCommunicatorPolicy(Cases[c].CommsAsynch);
 | 
			
		||||
      
 | 
			
		||||
	std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
	if ( StaggeredKernelsStatic::Opt == StaggeredKernelsStatic::OptGeneric   ) std::cout << GridLogMessage<< "* Using Stencil Nc Laplace" <<std::endl;
 | 
			
		||||
	if ( StaggeredKernelsStatic::Comms == StaggeredKernelsStatic::CommsAndCompute ) std::cout << GridLogMessage<< "* Using Overlapped Comms/Compute" <<std::endl;
 | 
			
		||||
	if ( StaggeredKernelsStatic::Comms == StaggeredKernelsStatic::CommsThenCompute) std::cout << GridLogMessage<< "* Using sequential Comms/Compute" <<std::endl;
 | 
			
		||||
	std::cout << GridLogMessage<< "* SINGLE precision "<<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
	
 | 
			
		||||
	int nwarm = 10;
 | 
			
		||||
	double t0=usecond();
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
	for(int i=0;i<nwarm;i++){
 | 
			
		||||
//	  Ds.DhopEO(src_o,r_e,DaggerNo);
 | 
			
		||||
          QuadOpF.HermOp(src,r_eo);
 | 
			
		||||
	}
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
	double t1=usecond();
 | 
			
		||||
	uint64_t ncall = 500;
 | 
			
		||||
 | 
			
		||||
	FGrid->Broadcast(0,&ncall,sizeof(ncall));
 | 
			
		||||
 | 
			
		||||
	//	std::cout << GridLogMessage << " Estimate " << ncall << " calls per second"<<std::endl;
 | 
			
		||||
 | 
			
		||||
	time_statistics timestat;
 | 
			
		||||
	std::vector<double> t_time(ncall);
 | 
			
		||||
	for(uint64_t i=0;i<ncall;i++){
 | 
			
		||||
	  t0=usecond();
 | 
			
		||||
//	  Ds.DhopEO(src_o,r_e,DaggerNo);
 | 
			
		||||
          QuadOpF.HermOp(src,r_eo);
 | 
			
		||||
	  t1=usecond();
 | 
			
		||||
	  t_time[i] = t1-t0;
 | 
			
		||||
	}
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
	
 | 
			
		||||
	double volume=1;  for(int mu=0;mu<Nd;mu++) volume=volume*latt4[mu];
 | 
			
		||||
//	double flops=(1146.0*volume)/2;
 | 
			
		||||
	double flops=(2*2*8*216.0*volume);
 | 
			
		||||
	double mf_hi, mf_lo, mf_err;
 | 
			
		||||
	
 | 
			
		||||
	timestat.statistics(t_time);
 | 
			
		||||
	mf_hi = flops/timestat.min;
 | 
			
		||||
	mf_lo = flops/timestat.max;
 | 
			
		||||
	mf_err= flops/timestat.min * timestat.err/timestat.mean;
 | 
			
		||||
 | 
			
		||||
	mflops = flops/timestat.mean;
 | 
			
		||||
	mflops_all.push_back(mflops);
 | 
			
		||||
	if ( mflops_best == 0   ) mflops_best = mflops;
 | 
			
		||||
	if ( mflops_worst== 0   ) mflops_worst= mflops;
 | 
			
		||||
	if ( mflops>mflops_best ) mflops_best = mflops;
 | 
			
		||||
	if ( mflops<mflops_worst) mflops_worst= mflops;
 | 
			
		||||
	
 | 
			
		||||
	std::cout<<GridLogMessage << std::fixed << std::setprecision(1)<<"Quad mflop/s =   "<< mflops << " ("<<mf_err<<") " << mf_lo<<"-"<<mf_hi <<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << std::fixed << std::setprecision(1)<<"Quad mflop/s per rank   "<< mflops/NP<<std::endl;
 | 
			
		||||
	std::cout<<GridLogMessage << std::fixed << std::setprecision(1)<<"Quad mflop/s per node   "<< mflops/NN<<std::endl;
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
      
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
      std::cout<<GridLogMessage << L<<"^4  Quad Best  mflop/s        =   "<< mflops_best << " ; " << mflops_best/NN<<" per node " <<std::endl;
 | 
			
		||||
      std::cout<<GridLogMessage << L<<"^4  Quad Worst mflop/s        =   "<< mflops_worst<< " ; " << mflops_worst/NN<<" per node " <<std::endl;
 | 
			
		||||
      std::cout<<GridLogMessage <<fmt << std::endl;
 | 
			
		||||
      std::cout<<GridLogMessage ;
 | 
			
		||||
	FGrid->Barrier();
 | 
			
		||||
 | 
			
		||||
      for(int i=0;i<mflops_all.size();i++){
 | 
			
		||||
	std::cout<<mflops_all[i]/NN<<" ; " ;
 | 
			
		||||
      }
 | 
			
		||||
      std::cout<<std::endl;
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
    return mflops_best;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -662,6 +832,7 @@ int main (int argc, char ** argv)
 | 
			
		||||
  std::vector<double> wilson;
 | 
			
		||||
  std::vector<double> dwf4;
 | 
			
		||||
  std::vector<double> staggered;
 | 
			
		||||
  std::vector<double> lap;
 | 
			
		||||
 | 
			
		||||
  int Ls=1;
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
@@ -688,12 +859,20 @@ int main (int argc, char ** argv)
 | 
			
		||||
    staggered.push_back(result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << " Laplace QuadOp 4D " <<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
  for(int l=0;l<L_list.size();l++){
 | 
			
		||||
    double result = Benchmark::Laplace(L_list[l]) ;
 | 
			
		||||
    lap.push_back(result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << " Summary table Ls="<<Ls <<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << "L \t\t Wilson \t\t DWF4 \t\t Staggered" <<std::endl;
 | 
			
		||||
  std::cout<<GridLogMessage << "L \t\t Wilson \t\t DWF4 \t\t Staggered \t\t Quad Laplace" <<std::endl;
 | 
			
		||||
  for(int l=0;l<L_list.size();l++){
 | 
			
		||||
    std::cout<<GridLogMessage << L_list[l] <<" \t\t "<< wilson[l]<<" \t\t "<<dwf4[l] << " \t\t "<< staggered[l]<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << L_list[l] <<" \t\t "<< wilson[l]<<" \t\t "<<dwf4[l] << " \t\t "<< staggered[l]<< " \t\t "<< lap[l]<< std::endl;
 | 
			
		||||
  }
 | 
			
		||||
  std::cout<<GridLogMessage << "=================================================================================="<<std::endl;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								configure.ac
									
									
									
									
									
								
							@@ -41,7 +41,7 @@ AC_PROG_RANLIB
 | 
			
		||||
 | 
			
		||||
############### Get compiler informations
 | 
			
		||||
AC_LANG([C++])
 | 
			
		||||
AX_CXX_COMPILE_STDCXX_11([noext],[mandatory])
 | 
			
		||||
AX_CXX_COMPILE_STDCXX(17,noext,mandatory)
 | 
			
		||||
AX_COMPILER_VENDOR
 | 
			
		||||
AC_DEFINE_UNQUOTED([CXX_COMP_VENDOR],["$ax_cv_cxx_compiler_vendor"],
 | 
			
		||||
      [vendor of C++ compiler that will compile the code])
 | 
			
		||||
@@ -191,10 +191,28 @@ case ${ac_Nc} in
 | 
			
		||||
        AC_DEFINE([Config_Nc],[4],[Gauge group Nc]);;
 | 
			
		||||
    5)
 | 
			
		||||
        AC_DEFINE([Config_Nc],[5],[Gauge group Nc]);;
 | 
			
		||||
    8)
 | 
			
		||||
        AC_DEFINE([Config_Nc],[8],[Gauge group Nc]);;
 | 
			
		||||
    *)
 | 
			
		||||
      AC_MSG_ERROR(["Unsupport gauge group choice Nc = ${ac_Nc}"]);;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
############### Symplectic group
 | 
			
		||||
AC_ARG_ENABLE([Sp],
 | 
			
		||||
    [AC_HELP_STRING([--enable-Sp=yes|no], [enable gauge group Sp2n])],
 | 
			
		||||
    [ac_ENABLE_SP=${enable_Sp}], [ac_ENABLE_SP=no])
 | 
			
		||||
 | 
			
		||||
AM_CONDITIONAL(BUILD_SP, [ test "${ac_ENABLE_SP}X" == "yesX" ])
 | 
			
		||||
 | 
			
		||||
case ${ac_ENABLE_SP} in
 | 
			
		||||
   yes)
 | 
			
		||||
        AC_DEFINE([Sp2n_config],[1],[gauge group Sp2n], [have_sp2n=true]);;
 | 
			
		||||
   no)
 | 
			
		||||
        AC_DEFINE([Sp2n_config],[0],[gauge group SUn], [have_sp2n=false]);;
 | 
			
		||||
    *)
 | 
			
		||||
        AC_MSG_ERROR(["--enable-Sp is either yes or no"]);;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
############### FP16 conversions
 | 
			
		||||
AC_ARG_ENABLE([sfw-fp16],
 | 
			
		||||
    [AS_HELP_STRING([--enable-sfw-fp16=yes|no],[enable software fp16 comms])],
 | 
			
		||||
@@ -737,7 +755,7 @@ case ${ac_TIMERS} in
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
############### Chroma regression test
 | 
			
		||||
AC_ARG_ENABLE([chroma],[AS_HELP_STRING([--enable-chroma],[Expect chroma compiled under c++11 ])],ac_CHROMA=yes,ac_CHROMA=no)
 | 
			
		||||
AC_ARG_ENABLE([chroma],[AS_HELP_STRING([--enable-chroma],[Expect chroma compiled under c++14 ])],ac_CHROMA=yes,ac_CHROMA=no)
 | 
			
		||||
 | 
			
		||||
case ${ac_CHROMA} in
 | 
			
		||||
     yes|no)
 | 
			
		||||
@@ -819,6 +837,7 @@ FFTW                        : `if test "x$have_fftw" = xtrue; then echo yes; els
 | 
			
		||||
LIME (ILDG support)         : `if test "x$have_lime" = xtrue; then echo yes; else echo no; fi`
 | 
			
		||||
HDF5                        : `if test "x$have_hdf5" = xtrue; then echo yes; else echo no; fi`
 | 
			
		||||
build DOXYGEN documentation : `if test "$DX_FLAG_doc" = '1'; then echo yes; else echo no; fi`
 | 
			
		||||
Sp2n                        : ${ac_ENABLE_SP}
 | 
			
		||||
----- BUILD FLAGS -------------------------------------
 | 
			
		||||
CXXFLAGS:
 | 
			
		||||
`echo ${AM_CXXFLAGS} ${CXXFLAGS} | tr ' ' '\n' | sed 's/^-/    -/g'`
 | 
			
		||||
@@ -847,6 +866,7 @@ AC_CONFIG_FILES(tests/lanczos/Makefile)
 | 
			
		||||
AC_CONFIG_FILES(tests/smearing/Makefile)
 | 
			
		||||
AC_CONFIG_FILES(tests/qdpxx/Makefile)
 | 
			
		||||
AC_CONFIG_FILES(tests/testu01/Makefile)
 | 
			
		||||
AC_CONFIG_FILES(tests/sp2n/Makefile)
 | 
			
		||||
AC_CONFIG_FILES(benchmarks/Makefile)
 | 
			
		||||
AC_CONFIG_FILES(examples/Makefile)
 | 
			
		||||
AC_OUTPUT
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -10,9 +10,8 @@ For first time setup of the Xcode and Grid build environment on Mac OS, you will
 | 
			
		||||
 | 
			
		||||
1. Install Xcode and the Xcode command-line utilities
 | 
			
		||||
2. Set Grid environment variables
 | 
			
		||||
3. Install and build Open MPI ***optional***
 | 
			
		||||
4. Install and build Grid pre-requisites
 | 
			
		||||
5. Install, Configure and Build Grid
 | 
			
		||||
3. Install and build Grid pre-requisites
 | 
			
		||||
4. Install, Configure and Build Grid
 | 
			
		||||
 | 
			
		||||
Apple's [Xcode website][Xcode] is the go-to reference for 1, and the definitive reference for 4 and 5 is the [Grid Documentation][GridDoc].
 | 
			
		||||
 | 
			
		||||
@@ -92,60 +91,33 @@ launchctl setenv GridPkg /opt/local</string>
 | 
			
		||||
</plist>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## 3. Install and build Open MPI -- ***optional***
 | 
			
		||||
 | 
			
		||||
Download the latest version of [Open MPI][OMPI] version 3.1 (I used 3.1.5) and build it like so:
 | 
			
		||||
 | 
			
		||||
[OMPI]: https://www.open-mpi.org/software/ompi/v3.1/
 | 
			
		||||
 | 
			
		||||
    ../configure CC=clang CXX=clang++ CXXFLAGS=-g --prefix=$GridPre/bin
 | 
			
		||||
    make -j 4 all install
 | 
			
		||||
 | 
			
		||||
***Note the `/bin` at the end of the prefix - this is required. As a quirk of the OpenMPI installer, `--prefix` must point to the `bin` subdirectory, with other files installed in `$GridPre/include`, `$GridPre/lib`, `$GridPre/share`, etc.***
 | 
			
		||||
 | 
			
		||||
Grid does not have any dependencies on fortran, however many standard scientific packages do, so you may wish to download GNU fortran (e.g. MacPorts ``gfortran`` package) and add the following to your configure invocation:
 | 
			
		||||
 | 
			
		||||
    F77=gfortran FC=gfortran
 | 
			
		||||
 | 
			
		||||
## 4. Install and build Grid pre-requisites
 | 
			
		||||
## 3. Install and build Grid pre-requisites
 | 
			
		||||
 | 
			
		||||
To simplify the installation of **Grid pre-requisites**, you can use your favourite package manager, e.g.:
 | 
			
		||||
 | 
			
		||||
### 1. [MacPorts][MacPorts]
 | 
			
		||||
### 3.1. [MacPorts][MacPorts]
 | 
			
		||||
 | 
			
		||||
[MacPorts]: https://www.macports.org "MacPorts package manager"
 | 
			
		||||
 | 
			
		||||
Install [MacPorts][MacPorts] if you haven't done so already, and then install packages with:
 | 
			
		||||
 | 
			
		||||
    sudo port install <portname>
 | 
			
		||||
    sudo port install openmpi git-flow-avh gmp hdf5 mpfr fftw-3-single lapack wget autoconf automake bison cmake gawk libomp
 | 
			
		||||
 | 
			
		||||
These are the `portname`s for mandatory Grid libraries:
 | 
			
		||||
On a Mac without GPUs:
 | 
			
		||||
 | 
			
		||||
* git-flow-avh
 | 
			
		||||
* gmp
 | 
			
		||||
* hdf5
 | 
			
		||||
* mpfr
 | 
			
		||||
    sudo port install OpenBLAS +native
 | 
			
		||||
 | 
			
		||||
and these are the `portname`s for optional Grid libraries:
 | 
			
		||||
To use `Gnu sha256sum`:
 | 
			
		||||
 | 
			
		||||
* fftw-3-single
 | 
			
		||||
* lapack
 | 
			
		||||
* doxygen
 | 
			
		||||
* OpenBLAS
 | 
			
		||||
    pushd /opt/local/bin; sudo ln -s gsha256sum sha256sum; popd 
 | 
			
		||||
 | 
			
		||||
***Please update this list with any packages I've missed! ... and double-check whether OpenBLAS is really for Grid. NB: lapack doesn't seem to work. Should it be scalapack?***
 | 
			
		||||
These `port`s are not strictly necessary, but they are helpful:
 | 
			
		||||
 | 
			
		||||
### 2. [Homebrew][Homebrew]
 | 
			
		||||
    sudo port install gnuplot gsl h5utils nasm rclone texinfo tree xorg-server
 | 
			
		||||
 | 
			
		||||
[Homebrew]: https://brew.sh "Homebrew package manager"
 | 
			
		||||
***Please update this list with any packages I've missed!***
 | 
			
		||||
 | 
			
		||||
Install [Homebrew][Homebrew] if you haven't done so already, and then install packages with:
 | 
			
		||||
 | 
			
		||||
    sudo brew install <packagename>
 | 
			
		||||
 | 
			
		||||
The same packages are available as from MacPorts.
 | 
			
		||||
 | 
			
		||||
### Install LIME ***optional***
 | 
			
		||||
#### Install LIME
 | 
			
		||||
 | 
			
		||||
There isn't currently a port for [C-LIME][C-LIME], so download the source and then build it:
 | 
			
		||||
 | 
			
		||||
@@ -154,9 +126,19 @@ There isn't currently a port for [C-LIME][C-LIME], so download the source and th
 | 
			
		||||
    ../configure CC=clang --prefix=$GridPre
 | 
			
		||||
    make -j 4 all install
 | 
			
		||||
 | 
			
		||||
## 5. Install, Configure and Build Grid
 | 
			
		||||
### 3.2. [Homebrew][Homebrew]
 | 
			
		||||
 | 
			
		||||
### 5.1 Install Grid
 | 
			
		||||
[Homebrew]: https://brew.sh "Homebrew package manager"
 | 
			
		||||
 | 
			
		||||
Install [Homebrew][Homebrew] if you haven't done so already, and then install packages with:
 | 
			
		||||
 | 
			
		||||
    sudo brew install <packagename>
 | 
			
		||||
 | 
			
		||||
I don't use Homebrew, so I'm not sure what the Brew package name equivalents are. ** Please update if you know **
 | 
			
		||||
 | 
			
		||||
## 4. Install, Configure and Build Grid
 | 
			
		||||
 | 
			
		||||
### 4.1 Install Grid
 | 
			
		||||
 | 
			
		||||
[Grid]: https://github.com/paboyle/Grid
 | 
			
		||||
 | 
			
		||||
@@ -174,7 +156,7 @@ or
 | 
			
		||||
 | 
			
		||||
depending on how many times you like to enter your password.
 | 
			
		||||
 | 
			
		||||
### 5.2 Configure Grid
 | 
			
		||||
### 4.2 Configure Grid
 | 
			
		||||
 | 
			
		||||
The Xcode build system supports multiple configurations for each project, by default: `Debug` and `Release`, but more configurations can be defined. We will create separate Grid build directories for each configuration, using the Grid **Autoconf** build system to make each configuration. NB: it is **not** necessary to run `make install` on them once they are built (IDE features such as *jump to definition* will work better of you don't).
 | 
			
		||||
 | 
			
		||||
@@ -198,7 +180,7 @@ Debug configuration with MPI:
 | 
			
		||||
 | 
			
		||||
    ../configure CXX=clang++ CXXFLAGS="-I$GridPkg/include/libomp -Xpreprocessor -fopenmp -std=c++11" LDFLAGS="-L$GridPkg/lib/libomp" LIBS="-lomp" --with-hdf5=$GridPkg --with-gmp=$GridPkg --with-mpfr=$GridPkg --with-fftw=$GridPkg --with-lime=$GridPre --enable-simd=GEN --enable-comms=mpi-auto MPICXX=$GridPre/bin/mpicxx --prefix=$GridPre/MPIDebug
 | 
			
		||||
 | 
			
		||||
### 5.3 Build Grid
 | 
			
		||||
### 4.3 Build Grid
 | 
			
		||||
 | 
			
		||||
Each configuration must be built before they can be used. You can either:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2778,47 +2778,81 @@ and there are associated reconstruction routines for assembling four spinors fro
 | 
			
		||||
 | 
			
		||||
These ca
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SU(N)
 | 
			
		||||
Gauge Group
 | 
			
		||||
--------
 | 
			
		||||
A generic Nc qcd/utils/GaugeGroup.h is provided. This defines a template class that can be specialised to different gauge groups::
 | 
			
		||||
 | 
			
		||||
A generic Nc qcd/utils/SUn.h is provided. This defines a template class::
 | 
			
		||||
  template <int ncolour, class group_name>
 | 
			
		||||
  class GaugeGroup {...}
 | 
			
		||||
 | 
			
		||||
  template <int ncolour> class SU ;
 | 
			
		||||
Supported groups are SU(N) and Sp(2N). The group can be specified through the GroupName namespace::
 | 
			
		||||
 | 
			
		||||
The most important external methods are::
 | 
			
		||||
  namespace GroupName {
 | 
			
		||||
  class SU {};
 | 
			
		||||
  class Sp {};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
A simpler interface is achieved by aliasing the GaugeGroup class with a specific group::
 | 
			
		||||
 | 
			
		||||
  template <int ncolour>
 | 
			
		||||
  using SU = GaugeGroup<ncolour, GroupName::SU>;
 | 
			
		||||
 | 
			
		||||
  template <int ncolour>
 | 
			
		||||
  using Sp = GaugeGroup<ncolour, GroupName::Sp>;
 | 
			
		||||
  
 | 
			
		||||
Specific aliases are then defined::
 | 
			
		||||
 | 
			
		||||
  typedef SU<2> SU2;
 | 
			
		||||
  typedef SU<3> SU3;
 | 
			
		||||
  typedef SU<4> SU4;
 | 
			
		||||
  typedef SU<5> SU5;
 | 
			
		||||
  typedef Sp<2> Sp2;
 | 
			
		||||
  typedef Sp<4> Sp4;
 | 
			
		||||
  typedef Sp<6> Sp6;
 | 
			
		||||
  typedef Sp<8> Sp8;
 | 
			
		||||
 | 
			
		||||
Some methods are common to both gauge groups. Common external methods are::
 | 
			
		||||
 | 
			
		||||
  static void printGenerators(void) ;
 | 
			
		||||
  template <class cplx>  static void generator(int lieIndex, iSUnMatrix<cplx> &ta) ;
 | 
			
		||||
  static void GaussianFundamentalLieAlgebraMatrix(GridParallelRNG &pRNG, LatticeMatrix &out, Real scale = 1.0) ;
 | 
			
		||||
  static void HotConfiguration(GridParallelRNG &pRNG, GaugeField &out) ;
 | 
			
		||||
  static void TepidConfiguration(GridParallelRNG &pRNG,GaugeField &out);
 | 
			
		||||
  static void ColdConfiguration(GaugeField &out);
 | 
			
		||||
  static void taProj( const LatticeMatrixType &in,  LatticeMatrixType &out);
 | 
			
		||||
  static void taExp(const LatticeMatrixType &x, LatticeMatrixType &ex) ;
 | 
			
		||||
  static void printGenerators(void) ;
 | 
			
		||||
   
 | 
			
		||||
Whenever needed, a different implementation of these methods for the gauge groups is achieved by overloading. For example,::
 | 
			
		||||
 | 
			
		||||
  template <typename LatticeMatrixType> //  shared interface for the traceless-antihermitian projection
 | 
			
		||||
  static void taProj(const LatticeMatrixType &in, LatticeMatrixType &out) {
 | 
			
		||||
    taProj(in, out, group_name());
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename LatticeMatrixType> //  overloaded function to SU(N) simply perform Ta
 | 
			
		||||
  static void taProj(const LatticeMatrixType &in, LatticeMatrixType &out, GroupName::SU) {
 | 
			
		||||
    out = Ta(in);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename LatticeMatrixType> //  overloaded function to Sp(2N) must use a modified Ta function
 | 
			
		||||
  static void taProj(const LatticeMatrixType &in, LatticeMatrixType &out, GroupName::Sp) {
 | 
			
		||||
    out = SpTa(in);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
Gauge Group: SU(N)
 | 
			
		||||
--------
 | 
			
		||||
The specialisation of GaugeGroup to SU(N), formally part of qcd/utils/GaugeGroup.h, is found in the file qcd/utils/SUn.impl
 | 
			
		||||
It contains methods that are only implemented for SU(N), and specialisations of shared methods to the special unitary group
 | 
			
		||||
 | 
			
		||||
Public methods are::
 | 
			
		||||
 | 
			
		||||
  static void SubGroupHeatBath(GridSerialRNG &sRNG, GridParallelRNG &pRNG, RealD beta,  // coeff multiplying staple in action (with no 1/Nc)
 | 
			
		||||
                               LatticeMatrix &link,
 | 
			
		||||
			       const LatticeMatrix &barestaple,  // multiplied by action coeffs so th
 | 
			
		||||
			       int su2_subgroup, int nheatbath, LatticeInteger &wheremask);
 | 
			
		||||
 | 
			
		||||
  static void GaussianFundamentalLieAlgebraMatrix(GridParallelRNG &pRNG,
 | 
			
		||||
                                                  LatticeMatrix &out,
 | 
			
		||||
                                                  Real scale = 1.0) ;
 | 
			
		||||
  static void GaugeTransform( GaugeField &Umu, GaugeMat &g)
 | 
			
		||||
  static void RandomGaugeTransform(GridParallelRNG &pRNG, GaugeField &Umu, GaugeMat &g);
 | 
			
		||||
 | 
			
		||||
  static void HotConfiguration(GridParallelRNG &pRNG, GaugeField &out) ;
 | 
			
		||||
  static void TepidConfiguration(GridParallelRNG &pRNG,GaugeField &out);
 | 
			
		||||
  static void ColdConfiguration(GaugeField &out);
 | 
			
		||||
 | 
			
		||||
  static void taProj( const LatticeMatrixType &in,  LatticeMatrixType &out);
 | 
			
		||||
  static void taExp(const LatticeMatrixType &x, LatticeMatrixType &ex) ;
 | 
			
		||||
 | 
			
		||||
  static int su2subgroups(void) ; // returns how many subgroups
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Specific instantiations are defined::
 | 
			
		||||
 | 
			
		||||
	 typedef SU<2> SU2;
 | 
			
		||||
	 typedef SU<3> SU3;
 | 
			
		||||
	 typedef SU<4> SU4;
 | 
			
		||||
	 typedef SU<5> SU5;
 | 
			
		||||
 | 
			
		||||
For example, Quenched QCD updating may be run as (tests/core/Test_quenched_update.cc)::
 | 
			
		||||
 | 
			
		||||
  for(int sweep=0;sweep<1000;sweep++){
 | 
			
		||||
@@ -2857,6 +2891,16 @@ For example, Quenched QCD updating may be run as (tests/core/Test_quenched_updat
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
Gauge Group: Sp(2N)
 | 
			
		||||
--------
 | 
			
		||||
The specialisation of GaugeGroup to Sp(2N), formally part of qcd/utils/GaugeGroup.h, is found in the file qcd/utils/Sp(2N).impl
 | 
			
		||||
It contains methods that are only implemented for Sp(2N), and specialisations of shared methods to the special unitary group
 | 
			
		||||
 | 
			
		||||
External methods are::
 | 
			
		||||
 | 
			
		||||
  static void Omega(LatticeColourMatrixD &in) // Symplectic matrix left invariant by Sp(2N)
 | 
			
		||||
 | 
			
		||||
Generation of Sp(2N) gauge fields is only supported via HMC.
 | 
			
		||||
 | 
			
		||||
Space time grids
 | 
			
		||||
----------------
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1018
									
								
								m4/ax_cxx_compile_stdcxx.m4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1018
									
								
								m4/ax_cxx_compile_stdcxx.m4
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										34
									
								
								m4/ax_cxx_compile_stdcxx_14.m4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								m4/ax_cxx_compile_stdcxx_14.m4
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
# =============================================================================
 | 
			
		||||
#  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_14.html
 | 
			
		||||
# =============================================================================
 | 
			
		||||
#
 | 
			
		||||
# SYNOPSIS
 | 
			
		||||
#
 | 
			
		||||
#   AX_CXX_COMPILE_STDCXX_14([ext|noext], [mandatory|optional])
 | 
			
		||||
#
 | 
			
		||||
# DESCRIPTION
 | 
			
		||||
#
 | 
			
		||||
#   Check for baseline language coverage in the compiler for the C++14
 | 
			
		||||
#   standard; if necessary, add switches to CXX and CXXCPP to enable
 | 
			
		||||
#   support.
 | 
			
		||||
#
 | 
			
		||||
#   This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX
 | 
			
		||||
#   macro with the version set to C++14.  The two optional arguments are
 | 
			
		||||
#   forwarded literally as the second and third argument respectively.
 | 
			
		||||
#   Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for
 | 
			
		||||
#   more information.  If you want to use this macro, you also need to
 | 
			
		||||
#   download the ax_cxx_compile_stdcxx.m4 file.
 | 
			
		||||
#
 | 
			
		||||
# LICENSE
 | 
			
		||||
#
 | 
			
		||||
#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
 | 
			
		||||
#
 | 
			
		||||
#   Copying and distribution of this file, with or without modification, are
 | 
			
		||||
#   permitted in any medium without royalty provided the copyright notice
 | 
			
		||||
#   and this notice are preserved. This file is offered as-is, without any
 | 
			
		||||
#   warranty.
 | 
			
		||||
 | 
			
		||||
#serial 5
 | 
			
		||||
 | 
			
		||||
AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
 | 
			
		||||
AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [AX_CXX_COMPILE_STDCXX([14], [$1], [$2])])
 | 
			
		||||
@@ -15,6 +15,8 @@ STAG_FERMION_FILES=`  find . -name '*.cc' -path '*/instantiation/*' -path '*/ins
 | 
			
		||||
GP_FERMION_FILES=`    find . -name '*.cc' -path '*/instantiation/*' -path '*/instantiation/Gparity*' `
 | 
			
		||||
ADJ_FERMION_FILES=`   find . -name '*.cc' -path '*/instantiation/*' -path '*/instantiation/WilsonAdj*' `
 | 
			
		||||
TWOIND_FERMION_FILES=`find . -name '*.cc' -path '*/instantiation/*' -path '*/instantiation/WilsonTwoIndex*'`
 | 
			
		||||
SP_FERMION_FILES=`find . -name '*.cc' -path '*/instantiation/*' -path '*/instantiation/SpWilsonImpl*'`
 | 
			
		||||
SP_TWOIND_FERMION_FILES=`find . -name '*.cc' -path '*/instantiation/*' -path '*/instantiation/SpWilsonTwo*'`
 | 
			
		||||
 | 
			
		||||
HPPFILES=`find . -type f -name '*.hpp'`
 | 
			
		||||
echo HFILES=$HFILES $HPPFILES > Make.inc
 | 
			
		||||
@@ -27,13 +29,14 @@ echo STAG_FERMION_FILES=$STAG_FERMION_FILES   >> Make.inc
 | 
			
		||||
echo GP_FERMION_FILES=$GP_FERMION_FILES   >> Make.inc
 | 
			
		||||
echo ADJ_FERMION_FILES=$ADJ_FERMION_FILES   >> Make.inc
 | 
			
		||||
echo TWOIND_FERMION_FILES=$TWOIND_FERMION_FILES   >> Make.inc
 | 
			
		||||
echo SP_FERMION_FILES=$SP_FERMION_FILES >> Make.inc
 | 
			
		||||
echo SP_TWOIND_FERMION_FILES=$SP_TWOIND_FERMION_FILES >> Make.inc
 | 
			
		||||
 | 
			
		||||
# tests Make.inc
 | 
			
		||||
cd $home/tests
 | 
			
		||||
dirs=`find . -type d -not -path '*/\.*'`
 | 
			
		||||
for subdir in $dirs; do
 | 
			
		||||
    cd $home/tests/$subdir
 | 
			
		||||
    pwd
 | 
			
		||||
    TESTS=`ls T*.cc`
 | 
			
		||||
    TESTLIST=`echo ${TESTS} | sed s/.cc//g `
 | 
			
		||||
    PREF=`[ $subdir = '.' ] && echo noinst || echo EXTRA`
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								systems/PVC-OEM/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								systems/PVC-OEM/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
1. Prerequisites:
 | 
			
		||||
===================
 | 
			
		||||
Make sure you have the latest Intel ipcx release loaded (via modules or similar)
 | 
			
		||||
Make sure you have SYCL aware MPICH or Intel MPI loaded (assumed as mpicxx)
 | 
			
		||||
 | 
			
		||||
2. Obtain Grid:
 | 
			
		||||
===================
 | 
			
		||||
 | 
			
		||||
bash$
 | 
			
		||||
git clone https://github.com/paboyle/Grid
 | 
			
		||||
cd Grid
 | 
			
		||||
./bootstrap.sh
 | 
			
		||||
cd systems/PVC
 | 
			
		||||
 | 
			
		||||
3. Build Grid:
 | 
			
		||||
===================
 | 
			
		||||
 | 
			
		||||
Here, configure command is stored in file config-command:
 | 
			
		||||
 | 
			
		||||
bash$
 | 
			
		||||
../../configure \
 | 
			
		||||
	--enable-simd=GPU \
 | 
			
		||||
	--enable-gen-simd-width=64 \
 | 
			
		||||
	--enable-comms=mpi-auto \
 | 
			
		||||
	--enable-accelerator-cshift \
 | 
			
		||||
	--disable-gparity \
 | 
			
		||||
	--disable-fermion-reps \
 | 
			
		||||
	--enable-shm=nvlink \
 | 
			
		||||
	--enable-accelerator=sycl \
 | 
			
		||||
	--enable-unified=no \
 | 
			
		||||
	MPICXX=mpicxx \
 | 
			
		||||
	CXX=icpx \
 | 
			
		||||
	LDFLAGS="-fiopenmp  -fsycl -fsycl-device-code-split=per_kernel -fsycl-device-lib=all -lze_loader " \
 | 
			
		||||
	CXXFLAGS="-fiopenmp -fsycl-unnamed-lambda -fsycl -Wno-tautological-compare "
 | 
			
		||||
 | 
			
		||||
make all
 | 
			
		||||
 | 
			
		||||
4. Run a benchmark:
 | 
			
		||||
===================
 | 
			
		||||
 | 
			
		||||
*** Assumes interactive access to node. ***
 | 
			
		||||
 | 
			
		||||
run Benchmark_dwf_fp32 using benchmarks/bench.sh
 | 
			
		||||
 | 
			
		||||
bash$
 | 
			
		||||
cd benchmarks
 | 
			
		||||
./bench.sh
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								systems/PVC-OEM/benchmarks/bench.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								systems/PVC-OEM/benchmarks/bench.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
export EnableImplicitScaling=0
 | 
			
		||||
export ZE_ENABLE_PCI_ID_DEVICE_ORDER=1
 | 
			
		||||
export ZE_AFFINITY_MASK=$gpu_id.$tile_id
 | 
			
		||||
export ONEAPI_DEVICE_FILTER=gpu,level_zero
 | 
			
		||||
export SYCL_PI_LEVEL_ZERO_DEVICE_SCOPE_EVENTS=0
 | 
			
		||||
export SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=1
 | 
			
		||||
export SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE=0:2
 | 
			
		||||
export SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_D2D_COPY=1
 | 
			
		||||
 | 
			
		||||
mpiexec -launcher ssh -n 1 -host localhost ./select_gpu.sh ./Benchmark_dwf_fp32 --mpi 1.1.1.1 --grid 32.32.32.32 --accelerator-threads 16 --shm-mpi 1 --shm 2048 --device-mem 32768 | tee 1tile.log
 | 
			
		||||
mpiexec -launcher ssh -n 2 -host localhost ./select_gpu.sh ./Benchmark_dwf_fp32 --mpi 1.1.1.2 --grid 32.32.32.64 --accelerator-threads 16 --shm-mpi 1 --shm 2048 --device-mem 32768 | tee 2tile.log
 | 
			
		||||
 | 
			
		||||
#mpiexec -launcher ssh -n 4 -host localhost ./select_gpu.sh ./Benchmark_dwf_fp32 --mpi 1.1.2.2 --grid 16.16.64.64 --accelerator-threads 16 --shm-mpi 0 --shm 2048 --device-mem 32768 | tee 4tile.log
 | 
			
		||||
#mpiexec -launcher ssh -n 8 -host localhost ./select_gpu.sh ./Benchmark_dwf_fp32 --mpi 1.1.2.4 --grid 16.16.64.128 --accelerator-threads 16 --shm-mpi 0 --shm 2048 --device-mem 32768 | tee 8tile.log
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								systems/PVC-OEM/benchmarks/select_gpu.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								systems/PVC-OEM/benchmarks/select_gpu.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
num_tile=2
 | 
			
		||||
gpu_id=$(( (MPI_LOCALRANKID / num_tile ) ))
 | 
			
		||||
tile_id=$((MPI_LOCALRANKID % num_tile))
 | 
			
		||||
 | 
			
		||||
export ZE_AFFINITY_MASK=$gpu_id.$tile_id
 | 
			
		||||
 | 
			
		||||
echo "local rank $MPI_LOCALRANKID ; ZE_AFFINITY_MASK=$ZE_AFFINITY_MASK"
 | 
			
		||||
 | 
			
		||||
"$@"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								systems/PVC-OEM/config-command
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								systems/PVC-OEM/config-command
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
../../configure \
 | 
			
		||||
	--enable-simd=GPU \
 | 
			
		||||
	--enable-gen-simd-width=64 \
 | 
			
		||||
	--enable-comms=mpi-auto \
 | 
			
		||||
	--enable-accelerator-cshift \
 | 
			
		||||
	--disable-gparity \
 | 
			
		||||
	--disable-fermion-reps \
 | 
			
		||||
	--enable-shm=nvlink \
 | 
			
		||||
	--enable-accelerator=sycl \
 | 
			
		||||
	--enable-unified=no \
 | 
			
		||||
	MPICXX=mpicxx \
 | 
			
		||||
	CXX=icpx \
 | 
			
		||||
	LDFLAGS="-fiopenmp  -fsycl -fsycl-device-code-split=per_kernel -fsycl-device-lib=all -lze_loader " \
 | 
			
		||||
	CXXFLAGS="-fiopenmp -fsycl-unnamed-lambda -fsycl -Wno-tautological-compare "
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								systems/PVC-OEM/setup.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								systems/PVC-OEM/setup.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
export https_proxy=http://proxy-chain.intel.com:911
 | 
			
		||||
module load intel-release
 | 
			
		||||
module load intel/mpich
 | 
			
		||||
@@ -1,62 +0,0 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
##SBATCH -p PVC-SPR-QZEH 
 | 
			
		||||
##SBATCH -p PVC-ICX-QZNW
 | 
			
		||||
#SBATCH -p QZ1J-ICX-PVC
 | 
			
		||||
##SBATCH -p QZ1J-SPR-PVC-2C
 | 
			
		||||
 | 
			
		||||
#source /nfs/site/home/paboylex/ATS/GridNew/Grid/systems/PVC-nightly/setup.sh
 | 
			
		||||
 | 
			
		||||
export NT=8
 | 
			
		||||
 | 
			
		||||
export I_MPI_OFFLOAD=1
 | 
			
		||||
export I_MPI_OFFLOAD_TOPOLIB=level_zero
 | 
			
		||||
export I_MPI_OFFLOAD_DOMAIN_SIZE=-1
 | 
			
		||||
 | 
			
		||||
# export IGC_EnableLSCFenceUGMBeforeEOT=0
 | 
			
		||||
# export SYCL_PROGRAM_COMPILE_OPTIONS="-ze-opt-large-register-file=False"
 | 
			
		||||
export SYCL_DEVICE_FILTER=gpu,level_zero
 | 
			
		||||
#export IGC_ShaderDumpEnable=1 
 | 
			
		||||
#export IGC_DumpToCurrentDir=1
 | 
			
		||||
export I_MPI_OFFLOAD_CELL=tile
 | 
			
		||||
export EnableImplicitScaling=0
 | 
			
		||||
export EnableWalkerPartition=0
 | 
			
		||||
export ZE_AFFINITY_MASK=0.0
 | 
			
		||||
mpiexec -launcher ssh -n 1 -host localhost  ./Benchmark_dwf_fp32 --mpi 1.1.1.1 --grid 32.32.32.32 --accelerator-threads $NT --comms-sequential --shm-mpi 1 --device-mem 32768
 | 
			
		||||
 | 
			
		||||
export ZE_AFFINITY_MASK=0
 | 
			
		||||
export I_MPI_OFFLOAD_CELL=device
 | 
			
		||||
export EnableImplicitScaling=1
 | 
			
		||||
export EnableWalkerPartition=1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#mpiexec -launcher ssh -n 2 -host localhost  vtune -collect gpu-hotspots -knob gpu-sampling-interval=1 -data-limit=0 -r ./vtune_run4 -- ./wrap.sh ./Benchmark_dwf_fp32 --mpi 2.1.1.1 --grid 64.32.32.32 --accelerator-threads $NT --comms-overlap --shm-mpi 1
 | 
			
		||||
 | 
			
		||||
#mpiexec  -launcher ssh -n 1 -host localhost ./wrap.sh ./Benchmark_dwf_fp32 --mpi 1.1.1.1 --grid 64.32.32.32 --accelerator-threads $NT --comms-overlap --shm-mpi 1
 | 
			
		||||
 | 
			
		||||
#mpiexec  -launcher ssh -n 2 -host localhost ./wrap.sh ./Benchmark_dwf_fp32 --mpi 2.1.1.1 --grid 64.32.32.32 --accelerator-threads $NT --comms-sequential --shm-mpi 1
 | 
			
		||||
 | 
			
		||||
#mpiexec  -launcher ssh -n 2 -host localhost ./wrap.sh ./Benchmark_dwf_fp32 --mpi 2.1.1.1 --grid 64.32.32.32 --accelerator-threads $NT --comms-overlap --shm-mpi 1
 | 
			
		||||
 | 
			
		||||
#mpiexec  -launcher ssh -n 2 -host localhost ./wrap.sh ./Benchmark_dwf_fp32 --mpi 2.1.1.1 --grid 64.32.32.32 --accelerator-threads $NT --comms-sequential --shm-mpi 0
 | 
			
		||||
 | 
			
		||||
#mpirun -np 2 ./wrap.sh ./Benchmark_dwf_fp32 --mpi 1.1.1.2 --grid 16.32.32.64 --accelerator-threads $NT --comms-sequential --shm-mpi 0
 | 
			
		||||
#mpirun -np 2 ./wrap.sh ./Benchmark_dwf_fp32 --mpi 1.1.1.2 --grid 32.32.32.64 --accelerator-threads $NT --comms-sequential --shm-mpi 1
 | 
			
		||||
 | 
			
		||||
@@ -1,33 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
##SBATCH -p PVC-SPR-QZEH 
 | 
			
		||||
##SBATCH -p PVC-ICX-QZNW
 | 
			
		||||
 | 
			
		||||
#SBATCH -p QZ1J-ICX-PVC
 | 
			
		||||
 | 
			
		||||
#source /nfs/site/home/paboylex/ATS/GridNew/Grid/systems/PVC-nightly/setup.sh
 | 
			
		||||
 | 
			
		||||
export NT=16
 | 
			
		||||
 | 
			
		||||
# export IGC_EnableLSCFenceUGMBeforeEOT=0
 | 
			
		||||
# export SYCL_PROGRAM_COMPILE_OPTIONS="-ze-opt-large-register-file=False"
 | 
			
		||||
#export IGC_ShaderDumpEnable=1 
 | 
			
		||||
#export IGC_DumpToCurrentDir=1
 | 
			
		||||
export I_MPI_OFFLOAD=1
 | 
			
		||||
export I_MPI_OFFLOAD_TOPOLIB=level_zero
 | 
			
		||||
export I_MPI_OFFLOAD_DOMAIN_SIZE=-1
 | 
			
		||||
export SYCL_DEVICE_FILTER=gpu,level_zero
 | 
			
		||||
export I_MPI_OFFLOAD_CELL=tile
 | 
			
		||||
export EnableImplicitScaling=0
 | 
			
		||||
export EnableWalkerPartition=0
 | 
			
		||||
#export SYCL_PI_LEVEL_ZERO_DEVICE_SCOPE_EVENTS=1
 | 
			
		||||
#export SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=1
 | 
			
		||||
export SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE=0
 | 
			
		||||
 | 
			
		||||
for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 | 
			
		||||
do
 | 
			
		||||
mpiexec -launcher ssh -n 2 -host localhost  ./wrap.sh ./Benchmark_dwf_fp32 --mpi 1.1.1.2 --grid 32.32.32.64 --accelerator-threads $NT  --shm-mpi 0  --device-mem 32768 > 1.1.1.2.log$i
 | 
			
		||||
mpiexec -launcher ssh -n 2 -host localhost  ./wrap.sh ./Benchmark_dwf_fp32 --mpi 2.1.1.1 --grid 64.32.32.32 --accelerator-threads $NT  --shm-mpi 0  --device-mem 32768 > 2.1.1.1.log$i 
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
mpiexec -launcher ssh -n 2 -host localhost  ./wrap.sh ./Benchmark_dwf_fp32 --mpi 2.1.1.1 --grid 64.32.32.32 --accelerator-threads $NT --comms-sequential --shm-mpi 0
 | 
			
		||||
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
export ZE_AFFINITY_MASK=0.$MPI_LOCALRANKID
 | 
			
		||||
 | 
			
		||||
echo Ranke $MPI_LOCALRANKID ZE_AFFINITY_MASK is $ZE_AFFINITY_MASK
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  $@
 | 
			
		||||
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
INSTALL=/nfs/site/home/paboylx/prereqs/
 | 
			
		||||
../../configure \
 | 
			
		||||
	--enable-simd=GPU \
 | 
			
		||||
	--enable-gen-simd-width=64 \
 | 
			
		||||
	--enable-comms=mpi-auto \
 | 
			
		||||
	--disable-accelerator-cshift \
 | 
			
		||||
	--disable-gparity \
 | 
			
		||||
	--disable-fermion-reps \
 | 
			
		||||
	--enable-shm=nvlink \
 | 
			
		||||
	--enable-accelerator=sycl \
 | 
			
		||||
	--enable-unified=no \
 | 
			
		||||
	MPICXX=mpicxx \
 | 
			
		||||
	CXX=dpcpp \
 | 
			
		||||
	LDFLAGS="-fsycl-device-code-split=per_kernel -fsycl-device-lib=all -lze_loader -L$INSTALL/lib" \
 | 
			
		||||
	CXXFLAGS="-fsycl-unnamed-lambda -fsycl -no-fma -I$INSTALL/include -Wno-tautological-compare"
 | 
			
		||||
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
export https_proxy=http://proxy-chain.intel.com:911
 | 
			
		||||
#export LD_LIBRARY_PATH=/nfs/site/home/azusayax/install/lib:$LD_LIBRARY_PATH
 | 
			
		||||
export LD_LIBRARY_PATH=$HOME/prereqs/lib/:$LD_LIBRARY_PATH
 | 
			
		||||
 | 
			
		||||
module load intel-release
 | 
			
		||||
module load intel-comp-rt/embargo-ci-neo
 | 
			
		||||
 | 
			
		||||
#source /opt/intel/oneapi/PVC_setup.sh
 | 
			
		||||
#source /opt/intel/oneapi/ATS_setup.sh
 | 
			
		||||
#module load intel-nightly/20230331
 | 
			
		||||
#module load intel-comp-rt/ci-neo-master/026093
 | 
			
		||||
 | 
			
		||||
#module load intel/mpich
 | 
			
		||||
module load intel/mpich/pvc45.3
 | 
			
		||||
export PATH=~/ATS/pti-gpu/tools/onetrace/:$PATH
 | 
			
		||||
 | 
			
		||||
#clsh embargo-ci-neo-022845
 | 
			
		||||
#source /opt/intel/vtune_amplifier/amplxe-vars.sh
 | 
			
		||||
@@ -20,7 +20,7 @@ unset OMP_PLACES
 | 
			
		||||
 | 
			
		||||
cd $PBS_O_WORKDIR
 | 
			
		||||
 | 
			
		||||
qsub jobscript.pbs
 | 
			
		||||
#qsub jobscript.pbs
 | 
			
		||||
 | 
			
		||||
echo Jobid: $PBS_JOBID
 | 
			
		||||
echo Running on host `hostname`
 | 
			
		||||
@@ -44,3 +44,4 @@ CMD="mpiexec -np ${NTOTRANKS} -ppn ${NRANKS} -d ${NDEPTH} --cpu-bind=depth -enva
 | 
			
		||||
	./Benchmark_dwf_fp32 --mpi 1.1.2.6 --grid 16.32.64.192 --comms-overlap \
 | 
			
		||||
	--shm-mpi 0 --shm 2048 --device-mem 32000 --accelerator-threads 32"
 | 
			
		||||
 | 
			
		||||
$CMD
 | 
			
		||||
 
 | 
			
		||||
@@ -45,8 +45,8 @@ echo "rank $PALS_RANKID ; local rank $PALS_LOCAL_RANKID ; ZE_AFFINITY_MASK=$ZE_A
 | 
			
		||||
 | 
			
		||||
if [ $PALS_LOCAL_RANKID = 0 ]
 | 
			
		||||
then
 | 
			
		||||
    onetrace --chrome-device-timeline "$@"
 | 
			
		||||
#    "$@"
 | 
			
		||||
#    onetrace --chrome-device-timeline "$@"
 | 
			
		||||
    "$@"
 | 
			
		||||
else
 | 
			
		||||
"$@"
 | 
			
		||||
fi
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,6 @@ TOOLS=$HOME/tools
 | 
			
		||||
	--enable-unified=no \
 | 
			
		||||
	MPICXX=mpicxx \
 | 
			
		||||
	CXX=icpx \
 | 
			
		||||
	LDFLAGS="-fiopenmp -fsycl -fsycl-device-code-split=per_kernel -fsycl-device-lib=all -lze_loader -lapmidg -L$TOOLS/lib64/" \
 | 
			
		||||
	LDFLAGS="-fiopenmp -fsycl -fsycl-device-code-split=per_kernel -fsycl-device-lib=all -lze_loader -L$TOOLS/lib64/" \
 | 
			
		||||
	CXXFLAGS="-fiopenmp -fsycl-unnamed-lambda -fsycl -I$INSTALL/include -Wno-tautological-compare -I$HOME/ -I$TOOLS/include"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
BREW=/opt/local/
 | 
			
		||||
MPICXX=mpicxx CXX=c++-12 ../../configure --enable-simd=GEN --enable-comms=mpi-auto --enable-unified=yes --prefix $HOME/QCD/GridInstall --with-lime=/Users/peterboyle/QCD/SciDAC/install/ --with-openssl=$BREW --disable-fermion-reps --disable-gparity --disable-debug
 | 
			
		||||
MPICXX=mpicxx ../../configure --enable-simd=GEN --enable-comms=mpi-auto --enable-unified=yes --prefix $HOME/QCD/GridInstall --with-lime=/Users/peterboyle/QCD/SciDAC/install/ --with-openssl=$BREW --disable-fermion-reps --disable-gparity --disable-debug
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
SUBDIRS = . core forces hmc solver debug smearing IO lanczos
 | 
			
		||||
SUBDIRS = . core forces hmc solver debug smearing IO lanczos sp2n
 | 
			
		||||
 | 
			
		||||
if BUILD_CHROMA_REGRESSION
 | 
			
		||||
  SUBDIRS+= qdpxx
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user