mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-03 21:44:33 +00:00 
			
		
		
		
	Improved the gamma quite a bit.
Serial rng's which are set on node zero and broadcaste
This commit is contained in:
		@@ -99,6 +99,8 @@ class CartesianCommunicator {
 | 
				
			|||||||
      Broadcast(root,(void *)&data,sizeof(data));
 | 
					      Broadcast(root,(void *)&data,sizeof(data));
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static void BroadcastWorld(int root,void* data, int bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}; 
 | 
					}; 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,9 @@ void CartesianCommunicator::Barrier(void)
 | 
				
			|||||||
void CartesianCommunicator::Broadcast(int root,void* data, int bytes)
 | 
					void CartesianCommunicator::Broadcast(int root,void* data, int bytes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CartesianCommunicator::ShiftedRanks(int dim,int shift,int &source,int &dest)
 | 
					void CartesianCommunicator::ShiftedRanks(int dim,int shift,int &source,int &dest)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,5 +92,14 @@ void CartesianCommunicator::Broadcast(int root,void* data, int bytes)
 | 
				
			|||||||
	    communicator);
 | 
						    communicator);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  MPI_Bcast(data,
 | 
				
			||||||
 | 
						    bytes,
 | 
				
			||||||
 | 
						    MPI_BYTE,
 | 
				
			||||||
 | 
						    root,
 | 
				
			||||||
 | 
						    MPI_COMM_WORLD);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,70 @@ namespace Grid {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  class GridRNG {
 | 
					  class GridRNGbase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   GridRNGbase() : _uniform{0,1}, _gaussian(0.0,1.0) {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int _seeded;
 | 
				
			||||||
 | 
					    // One generator per site.
 | 
				
			||||||
 | 
					    // Uniform and Gaussian distributions from these generators.
 | 
				
			||||||
 | 
					    std::vector<std::ranlux48>             _generators;
 | 
				
			||||||
 | 
					    std::uniform_real_distribution<double> _uniform;
 | 
				
			||||||
 | 
					    std::normal_distribution<double>       _gaussian;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  class GridSerialRNG : public GridRNGbase {
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // FIXME ... do we require lockstep draws of randoms 
 | 
				
			||||||
 | 
					    // from all nodes keeping seeds consistent.
 | 
				
			||||||
 | 
					    // place a barrier/broadcast in the fill routine
 | 
				
			||||||
 | 
					    template<class source> void Seed(source &src)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      typename source::result_type init = src();
 | 
				
			||||||
 | 
					      CartesianCommunicator::BroadcastWorld(0,(void *)&init,sizeof(init));
 | 
				
			||||||
 | 
					      _generators[0] = std::ranlux48(init);
 | 
				
			||||||
 | 
					      _seeded=1;
 | 
				
			||||||
 | 
					    }    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GridSerialRNG() : GridRNGbase() {
 | 
				
			||||||
 | 
					      _generators.resize(1);
 | 
				
			||||||
 | 
					      _seeded=0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template <class sobj,class distribution> inline void fill(sobj &l,distribution &dist){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      typedef typename sobj::scalar_type scalar_type;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      int words = sizeof(sobj)/sizeof(scalar_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      scalar_type *buf = (scalar_type *) & l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for(int idx=0;idx<words;idx++){
 | 
				
			||||||
 | 
						buf[idx] = dist(_generators[0]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      CartesianCommunicator::BroadcastWorld(0,(void *)&l,sizeof(l));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SeedRandomDevice(void){
 | 
				
			||||||
 | 
					      std::random_device rd;
 | 
				
			||||||
 | 
					      Seed(rd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void SeedFixedIntegers(std::vector<int> &seeds){
 | 
				
			||||||
 | 
					      fixedSeed src(seeds);
 | 
				
			||||||
 | 
					      Seed(src);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  class GridParallelRNG : public GridRNGbase {
 | 
				
			||||||
  public:
 | 
					  public:
 | 
				
			||||||
    // One generator per site.
 | 
					    // One generator per site.
 | 
				
			||||||
    std::vector<std::ranlux48>             _generators;
 | 
					    std::vector<std::ranlux48>             _generators;
 | 
				
			||||||
@@ -42,25 +105,13 @@ namespace Grid {
 | 
				
			|||||||
      return is*_grid->oSites()+os;
 | 
					      return is*_grid->oSites()+os;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GridRNG(GridBase *grid) : _uniform{0,1}, _gaussian(0.0,1.0) {
 | 
					    GridParallelRNG(GridBase *grid) : GridRNGbase() {
 | 
				
			||||||
      _grid=grid;
 | 
					      _grid=grid;
 | 
				
			||||||
      _vol =_grid->iSites()*_grid->oSites();
 | 
					      _vol =_grid->iSites()*_grid->oSites();
 | 
				
			||||||
      _generators.resize(_vol);
 | 
					      _generators.resize(_vol);
 | 
				
			||||||
      //      SeedFixedIntegers(seeds);
 | 
					      _seeded=0;
 | 
				
			||||||
      // worst case we seed properly but non-deterministically
 | 
					 | 
				
			||||||
      SeedRandomDevice();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // FIXME: drive seeding from node zero and transmit to all
 | 
					 | 
				
			||||||
    // to get unique randoms on each node
 | 
					 | 
				
			||||||
    void SeedRandomDevice(void){
 | 
					 | 
				
			||||||
      std::random_device rd;
 | 
					 | 
				
			||||||
      Seed(rd);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    void SeedFixedIntegers(std::vector<int> &seeds){
 | 
					 | 
				
			||||||
      fixedSeed src(seeds);
 | 
					 | 
				
			||||||
      Seed(src);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // This loop could be made faster to avoid the Ahmdahl by
 | 
					    // This loop could be made faster to avoid the Ahmdahl by
 | 
				
			||||||
    // i)  seed generators on each timeslice, for x=y=z=0;
 | 
					    // i)  seed generators on each timeslice, for x=y=z=0;
 | 
				
			||||||
@@ -86,6 +137,7 @@ namespace Grid {
 | 
				
			|||||||
	  _generators[l_idx] = std::ranlux48(init);
 | 
						  _generators[l_idx] = std::ranlux48(init);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      _seeded=1;
 | 
				
			||||||
    }    
 | 
					    }    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //FIXME implement generic IO and create state save/restore
 | 
					    //FIXME implement generic IO and create state save/restore
 | 
				
			||||||
@@ -122,15 +174,34 @@ namespace Grid {
 | 
				
			|||||||
	merge(l._odata[ss],pointers);
 | 
						merge(l._odata[ss],pointers);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SeedRandomDevice(void){
 | 
				
			||||||
 | 
					      std::random_device rd;
 | 
				
			||||||
 | 
					      Seed(rd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void SeedFixedIntegers(std::vector<int> &seeds){
 | 
				
			||||||
 | 
					      fixedSeed src(seeds);
 | 
				
			||||||
 | 
					      Seed(src);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // FIXME Implement a consistent seed management strategy
 | 
					
 | 
				
			||||||
  template <class vobj> inline void random(GridRNG &rng,Lattice<vobj> &l){
 | 
					  template <class vobj> inline void random(GridParallelRNG &rng,Lattice<vobj> &l){
 | 
				
			||||||
    rng.fill(l,rng._uniform);
 | 
					    rng.fill(l,rng._uniform);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  template <class vobj> inline void gaussian(GridRNG &rng,Lattice<vobj> &l){
 | 
					  template <class vobj> inline void gaussian(GridParallelRNG &rng,Lattice<vobj> &l){
 | 
				
			||||||
    rng.fill(l,rng._gaussian);
 | 
					    rng.fill(l,rng._gaussian);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  template <class sobj> inline void random(GridSerialRNG &rng,sobj &l){
 | 
				
			||||||
 | 
					    rng.fill(l,rng._uniform);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  template <class sobj> inline void gaussian(GridSerialRNG &rng,sobj &l){
 | 
				
			||||||
 | 
					    rng.fill(l,rng._gaussian);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,13 @@ namespace Grid {
 | 
				
			|||||||
    // innerProduct Vector x Vector -> Scalar
 | 
					    // innerProduct Vector x Vector -> Scalar
 | 
				
			||||||
    // innerProduct Matrix x Matrix -> Scalar
 | 
					    // innerProduct Matrix x Matrix -> Scalar
 | 
				
			||||||
    ///////////////////////////////////////////////////////////////////////////////////////
 | 
					    ///////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					    template<class sobj> inline RealD norm2l(sobj &arg){
 | 
				
			||||||
 | 
					      typedef typename sobj::scalar_type scalar;
 | 
				
			||||||
 | 
					      decltype(innerProduct(arg,arg)) nrm;
 | 
				
			||||||
 | 
					      nrm = innerProduct(arg,arg);
 | 
				
			||||||
 | 
					      return real(nrm);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<class l,class r,int N> inline
 | 
					    template<class l,class r,int N> inline
 | 
				
			||||||
    auto innerProduct (const iVector<l,N>& lhs,const iVector<r,N>& rhs) -> iScalar<decltype(innerProduct(lhs._internal[0],rhs._internal[0]))>
 | 
					    auto innerProduct (const iVector<l,N>& lhs,const iVector<r,N>& rhs) -> iScalar<decltype(innerProduct(lhs._internal[0],rhs._internal[0]))>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -76,15 +76,15 @@ namespace QCD {
 | 
				
			|||||||
	ret(i,0) = timesMinusI(rhs(i,3));
 | 
						ret(i,0) = timesMinusI(rhs(i,3));
 | 
				
			||||||
	ret(i,1) = timesMinusI(rhs(i,2));
 | 
						ret(i,1) = timesMinusI(rhs(i,2));
 | 
				
			||||||
	ret(i,2) = timesI(rhs(i,1));
 | 
						ret(i,2) = timesI(rhs(i,1));
 | 
				
			||||||
	ret(i,3) = timesI(rhs(i,1));
 | 
						ret(i,3) = timesI(rhs(i,0));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    template<class vtype> inline void multGammaX(iMatrix<vtype,Ns> &ret, const iMatrix<vtype,Ns> &rhs){
 | 
					    template<class vtype> inline void multGammaX(iMatrix<vtype,Ns> &ret, const iMatrix<vtype,Ns> &rhs){
 | 
				
			||||||
      for(int i=0;i<Ns;i++){
 | 
					      for(int i=0;i<Ns;i++){
 | 
				
			||||||
	ret(0,i) = timesI(rhs(3,i));
 | 
						ret(0,i) = timesI(rhs(3,i));
 | 
				
			||||||
	ret(1,i) = timesI(rhs._internal[2][i]);
 | 
						ret(1,i) = timesI(rhs(2,i));
 | 
				
			||||||
	ret(2,i) = timesMinusI(rhs._internal[1][i]);
 | 
						ret(2,i) = timesMinusI(rhs(1,i));
 | 
				
			||||||
	ret(3,i) = timesMinusI(rhs._internal[0][i]);
 | 
						ret(3,i) = timesMinusI(rhs(0,i));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    template<class vtype> inline void multMinusGammaX(iMatrix<vtype,Ns> &ret, const iMatrix<vtype,Ns> &rhs){
 | 
					    template<class vtype> inline void multMinusGammaX(iMatrix<vtype,Ns> &ret, const iMatrix<vtype,Ns> &rhs){
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,8 @@ int main (int argc, char ** argv)
 | 
				
			|||||||
  std::vector<int> latt_size  ({8,8,8,16});
 | 
					  std::vector<int> latt_size  ({8,8,8,16});
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
  GridCartesian     Fine(latt_size,simd_layout,mpi_layout);
 | 
					  GridCartesian     Fine(latt_size,simd_layout,mpi_layout);
 | 
				
			||||||
  GridRNG           FineRNG(&Fine);
 | 
					  GridParallelRNG           FineRNG(&Fine);
 | 
				
			||||||
 | 
					  FineRNG.SeedRandomDevice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  LatticeComplex U(&Fine);
 | 
					  LatticeComplex U(&Fine);
 | 
				
			||||||
  LatticeComplex ShiftU(&Fine);
 | 
					  LatticeComplex ShiftU(&Fine);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,9 +16,15 @@ int main (int argc, char ** argv)
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
  GridCartesian     Grid(latt_size,simd_layout,mpi_layout);
 | 
					  GridCartesian     Grid(latt_size,simd_layout,mpi_layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GridRNG           RNG(&Grid);
 | 
					  GridParallelRNG          pRNG(&Grid);
 | 
				
			||||||
 | 
					  pRNG.SeedRandomDevice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GridSerialRNG            sRNG;
 | 
				
			||||||
 | 
					  sRNG.SeedRandomDevice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpinMatrix ident=zero;
 | 
					  SpinMatrix ident=zero;
 | 
				
			||||||
 | 
					  SpinMatrix rnd  ; random(sRNG,rnd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpinMatrix ll=zero;
 | 
					  SpinMatrix ll=zero;
 | 
				
			||||||
  SpinMatrix rr=zero;
 | 
					  SpinMatrix rr=zero;
 | 
				
			||||||
  SpinMatrix result;
 | 
					  SpinMatrix result;
 | 
				
			||||||
@@ -94,6 +100,29 @@ int main (int argc, char ** argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  
 | 
					  std::cout << "Testing Gamma^2 - 1 = 0"<<std::endl;
 | 
				
			||||||
 | 
					  for(int mu=0;mu<6;mu++){
 | 
				
			||||||
 | 
					    result =  Gamma(g[mu])* ident * Gamma(g[mu]);
 | 
				
			||||||
 | 
					    result = result - ident;
 | 
				
			||||||
 | 
					    double mag = TensorRemove(norm2l(result));
 | 
				
			||||||
 | 
					    std::cout << list[mu]<<" " << mag<<std::endl;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::cout << "Testing (MinusGamma + G )M = 0"<<std::endl;
 | 
				
			||||||
 | 
					  for(int mu=0;mu<6;mu++){
 | 
				
			||||||
 | 
					    result =          rnd * Gamma(g[mu]);
 | 
				
			||||||
 | 
					    result = result + rnd * Gamma(g[mu+6]);
 | 
				
			||||||
 | 
					    double mag = TensorRemove(norm2l(result));
 | 
				
			||||||
 | 
					    std::cout << list[mu]<<" " << mag<<std::endl;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::cout << "Testing M(MinusGamma + G )  = 0"<<std::endl;
 | 
				
			||||||
 | 
					  for(int mu=0;mu<6;mu++){
 | 
				
			||||||
 | 
					    result =           Gamma(g[mu])  *rnd;
 | 
				
			||||||
 | 
					    result = result +  Gamma(g[mu+6])*rnd;
 | 
				
			||||||
 | 
					    double mag = TensorRemove(norm2l(result));
 | 
				
			||||||
 | 
					    std::cout << list[mu]<<" " << mag<<std::endl;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Grid_finalize();
 | 
					  Grid_finalize();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,8 @@ int main (int argc, char ** argv)
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    GridCartesian Fine(latt_size,simd_layout,mpi_layout);
 | 
					    GridCartesian Fine(latt_size,simd_layout,mpi_layout);
 | 
				
			||||||
    GridRedBlackCartesian rbFine(latt_size,simd_layout,mpi_layout);
 | 
					    GridRedBlackCartesian rbFine(latt_size,simd_layout,mpi_layout);
 | 
				
			||||||
    GridRNG       FineRNG(&Fine);
 | 
					    GridParallelRNG       FineRNG(&Fine);
 | 
				
			||||||
 | 
					    FineRNG.SeedRandomDevice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LatticeColourMatrix Foo(&Fine);
 | 
					    LatticeColourMatrix Foo(&Fine);
 | 
				
			||||||
    LatticeColourMatrix Bar(&Fine);
 | 
					    LatticeColourMatrix Bar(&Fine);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,6 @@ int main (int argc, char ** argv)
 | 
				
			|||||||
  GridCartesian     Fine(latt_size,simd_layout,mpi_layout);
 | 
					  GridCartesian     Fine(latt_size,simd_layout,mpi_layout);
 | 
				
			||||||
  GridCartesian     Coarse(clatt_size,simd_layout,mpi_layout);
 | 
					  GridCartesian     Coarse(clatt_size,simd_layout,mpi_layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GridRNG           FineRNG(&Fine);
 | 
					 | 
				
			||||||
  LatticeGaugeField Umu(&Fine);
 | 
					  LatticeGaugeField Umu(&Fine);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::vector<LatticeColourMatrix> U(4,&Fine);
 | 
					  std::vector<LatticeColourMatrix> U(4,&Fine);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,8 @@ int main (int argc, char ** argv)
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    GridCartesian Fine(latt_size,simd_layout,mpi_layout);
 | 
					    GridCartesian Fine(latt_size,simd_layout,mpi_layout);
 | 
				
			||||||
    GridRedBlackCartesian rbFine(latt_size,simd_layout,mpi_layout);
 | 
					    GridRedBlackCartesian rbFine(latt_size,simd_layout,mpi_layout);
 | 
				
			||||||
    GridRNG       fRNG(&Fine);
 | 
					    GridParallelRNG       fRNG(&Fine);
 | 
				
			||||||
 | 
					    fRNG.SeedRandomDevice();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LatticeColourMatrix Foo(&Fine);
 | 
					    LatticeColourMatrix Foo(&Fine);
 | 
				
			||||||
    LatticeColourMatrix Bar(&Fine);
 | 
					    LatticeColourMatrix Bar(&Fine);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user