mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-04 05:54:32 +00:00 
			
		
		
		
	Merge branch 'develop' of https://github.com/paboyle/Grid into feature/staggering
This commit is contained in:
		@@ -42,6 +42,10 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#include <Grid/cshift/Cshift_mpi.h>
 | 
			
		||||
#endif 
 | 
			
		||||
 | 
			
		||||
#ifdef GRID_COMMS_MPI3L
 | 
			
		||||
#include <Grid/cshift/Cshift_mpi.h>
 | 
			
		||||
#endif 
 | 
			
		||||
 | 
			
		||||
#ifdef GRID_COMMS_SHMEM
 | 
			
		||||
#include <Grid/cshift/Cshift_mpi.h> // uses same implementation of communicator
 | 
			
		||||
#endif 
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										279
									
								
								lib/FFT.h
									
									
									
									
									
								
							
							
						
						
									
										279
									
								
								lib/FFT.h
									
									
									
									
									
								
							@@ -29,9 +29,15 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#ifndef _GRID_FFT_H_
 | 
			
		||||
#define _GRID_FFT_H_
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_FFTW	
 | 
			
		||||
#ifdef HAVE_FFTW
 | 
			
		||||
#ifdef USE_MKL
 | 
			
		||||
#include <fftw/fftw3.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <fftw3.h>
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
 | 
			
		||||
  template<class scalar> struct FFTW { };
 | 
			
		||||
@@ -98,174 +104,199 @@ namespace Grid {
 | 
			
		||||
#define FFTW_BACKWARD (+1)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  class FFT { 
 | 
			
		||||
  class FFT {
 | 
			
		||||
  private:
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    GridCartesian *vgrid;
 | 
			
		||||
    GridCartesian *sgrid;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    int Nd;
 | 
			
		||||
    double flops;
 | 
			
		||||
    double flops_call;
 | 
			
		||||
    uint64_t usec;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    std::vector<int> dimensions;
 | 
			
		||||
    std::vector<int> processors;
 | 
			
		||||
    std::vector<int> processor_coor;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
  public:
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    static const int forward=FFTW_FORWARD;
 | 
			
		||||
    static const int backward=FFTW_BACKWARD;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    double Flops(void) {return flops;}
 | 
			
		||||
    double MFlops(void) {return flops/usec;}
 | 
			
		||||
    double USec(void)   {return (double)usec;}    
 | 
			
		||||
 | 
			
		||||
    FFT ( GridCartesian * grid ) : 
 | 
			
		||||
      vgrid(grid),
 | 
			
		||||
      Nd(grid->_ndimension),
 | 
			
		||||
      dimensions(grid->_fdimensions),
 | 
			
		||||
      processors(grid->_processors),
 | 
			
		||||
      processor_coor(grid->_processor_coor)
 | 
			
		||||
    FFT ( GridCartesian * grid ) :
 | 
			
		||||
    vgrid(grid),
 | 
			
		||||
    Nd(grid->_ndimension),
 | 
			
		||||
    dimensions(grid->_fdimensions),
 | 
			
		||||
    processors(grid->_processors),
 | 
			
		||||
    processor_coor(grid->_processor_coor)
 | 
			
		||||
    {
 | 
			
		||||
      flops=0;
 | 
			
		||||
      usec =0;
 | 
			
		||||
      std::vector<int> layout(Nd,1);
 | 
			
		||||
      sgrid = new GridCartesian(dimensions,layout,processors);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ~FFT ( void)  { 
 | 
			
		||||
      delete sgrid; 
 | 
			
		||||
    
 | 
			
		||||
    ~FFT ( void)  {
 | 
			
		||||
      delete sgrid;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template<class vobj>
 | 
			
		||||
    void FFT_dim(Lattice<vobj> &result,const Lattice<vobj> &source,int dim, int inverse){
 | 
			
		||||
    void FFT_dim_mask(Lattice<vobj> &result,const Lattice<vobj> &source,std::vector<int> mask,int sign){
 | 
			
		||||
 | 
			
		||||
      conformable(result._grid,vgrid);
 | 
			
		||||
      conformable(source._grid,vgrid);
 | 
			
		||||
      Lattice<vobj> tmp(vgrid);
 | 
			
		||||
      tmp = source;
 | 
			
		||||
      for(int d=0;d<Nd;d++){
 | 
			
		||||
	if( mask[d] ) {
 | 
			
		||||
	  FFT_dim(result,tmp,d,sign);
 | 
			
		||||
	  tmp=result;
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class vobj>
 | 
			
		||||
    void FFT_all_dim(Lattice<vobj> &result,const Lattice<vobj> &source,int sign){
 | 
			
		||||
      std::vector<int> mask(Nd,1);
 | 
			
		||||
      FFT_dim_mask(result,source,mask,sign);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    template<class vobj>
 | 
			
		||||
    void FFT_dim(Lattice<vobj> &result,const Lattice<vobj> &source,int dim, int sign){
 | 
			
		||||
#ifndef HAVE_FFTW
 | 
			
		||||
      assert(0);
 | 
			
		||||
#else
 | 
			
		||||
      conformable(result._grid,vgrid);
 | 
			
		||||
      conformable(source._grid,vgrid);
 | 
			
		||||
 | 
			
		||||
      int L = vgrid->_ldimensions[dim];
 | 
			
		||||
      int G = vgrid->_fdimensions[dim];
 | 
			
		||||
 | 
			
		||||
      
 | 
			
		||||
      std::vector<int> layout(Nd,1);
 | 
			
		||||
      std::vector<int> pencil_gd(vgrid->_fdimensions);
 | 
			
		||||
 | 
			
		||||
      pencil_gd[dim] = G*processors[dim];    
 | 
			
		||||
 | 
			
		||||
      
 | 
			
		||||
      pencil_gd[dim] = G*processors[dim];
 | 
			
		||||
      
 | 
			
		||||
      // Pencil global vol LxLxGxLxL per node
 | 
			
		||||
      GridCartesian pencil_g(pencil_gd,layout,processors);
 | 
			
		||||
 | 
			
		||||
      
 | 
			
		||||
      // Construct pencils
 | 
			
		||||
      typedef typename vobj::scalar_object sobj;
 | 
			
		||||
      typedef typename sobj::scalar_type   scalar;
 | 
			
		||||
      
 | 
			
		||||
      Lattice<sobj> pgbuf(&pencil_g);
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
      Lattice<vobj> ssource(vgrid); ssource =source;
 | 
			
		||||
      Lattice<sobj> pgsource(&pencil_g);
 | 
			
		||||
      Lattice<sobj> pgresult(&pencil_g); pgresult=zero;
 | 
			
		||||
 | 
			
		||||
#ifndef HAVE_FFTW	
 | 
			
		||||
      assert(0);
 | 
			
		||||
#else 
 | 
			
		||||
      typedef typename FFTW<scalar>::FFTW_scalar FFTW_scalar;
 | 
			
		||||
      typedef typename FFTW<scalar>::FFTW_plan   FFTW_plan;
 | 
			
		||||
 | 
			
		||||
      {
 | 
			
		||||
	int Ncomp = sizeof(sobj)/sizeof(scalar);
 | 
			
		||||
	int Nlow  = 1;
 | 
			
		||||
	for(int d=0;d<dim;d++){
 | 
			
		||||
	  Nlow*=vgrid->_ldimensions[d];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int rank = 1;  /* 1d transforms */
 | 
			
		||||
	int n[] = {G}; /* 1d transforms of length G */
 | 
			
		||||
	int howmany = Ncomp;
 | 
			
		||||
	int odist,idist,istride,ostride;
 | 
			
		||||
	idist   = odist   = 1;          /* Distance between consecutive FT's */
 | 
			
		||||
	istride = ostride = Ncomp*Nlow; /* distance between two elements in the same FT */
 | 
			
		||||
	int *inembed = n, *onembed = n;
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	int sign = FFTW_FORWARD;
 | 
			
		||||
	if (inverse) sign = FFTW_BACKWARD;
 | 
			
		||||
 | 
			
		||||
	FFTW_plan p;
 | 
			
		||||
	{
 | 
			
		||||
	  FFTW_scalar *in = (FFTW_scalar *)&pgsource._odata[0];
 | 
			
		||||
	  FFTW_scalar *out= (FFTW_scalar *)&pgresult._odata[0];
 | 
			
		||||
	  p = FFTW<scalar>::fftw_plan_many_dft(rank,n,howmany,
 | 
			
		||||
					       in,inembed,
 | 
			
		||||
					       istride,idist,
 | 
			
		||||
					       out,onembed,
 | 
			
		||||
					       ostride, odist,
 | 
			
		||||
					       sign,FFTW_ESTIMATE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    std::vector<int> lcoor(Nd), gcoor(Nd);
 | 
			
		||||
 | 
			
		||||
	// Barrel shift and collect global pencil
 | 
			
		||||
	for(int p=0;p<processors[dim];p++) { 
 | 
			
		||||
 | 
			
		||||
	  for(int idx=0;idx<sgrid->lSites();idx++) { 
 | 
			
		||||
 | 
			
		||||
	    
 | 
			
		||||
    	    sgrid->LocalIndexToLocalCoor(idx,lcoor);
 | 
			
		||||
 | 
			
		||||
	    sobj s;
 | 
			
		||||
 | 
			
		||||
	    peekLocalSite(s,ssource,lcoor);
 | 
			
		||||
 | 
			
		||||
	    lcoor[dim]+=p*L;
 | 
			
		||||
	   
 | 
			
		||||
	    pokeLocalSite(s,pgsource,lcoor);
 | 
			
		||||
	  }
 | 
			
		||||
 | 
			
		||||
	  ssource = Cshift(ssource,dim,L);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// Loop over orthog coords
 | 
			
		||||
	int NN=pencil_g.lSites();
 | 
			
		||||
	GridStopWatch timer;
 | 
			
		||||
	timer.Start();
 | 
			
		||||
 | 
			
		||||
//PARALLEL_FOR_LOOP
 | 
			
		||||
	for(int idx=0;idx<NN;idx++) {
 | 
			
		||||
	  pencil_g.LocalIndexToLocalCoor(idx,lcoor);
 | 
			
		||||
 | 
			
		||||
	  if ( lcoor[dim] == 0 ) {  // restricts loop to plane at lcoor[dim]==0
 | 
			
		||||
	    FFTW_scalar *in = (FFTW_scalar *)&pgsource._odata[idx];
 | 
			
		||||
	    FFTW_scalar *out= (FFTW_scalar *)&pgresult._odata[idx];
 | 
			
		||||
	    FFTW<scalar>::fftw_execute_dft(p,in,out);
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        timer.Stop();
 | 
			
		||||
 | 
			
		||||
          double add,mul,fma;
 | 
			
		||||
          FFTW<scalar>::fftw_flops(p,&add,&mul,&fma);
 | 
			
		||||
          flops_call = add+mul+2.0*fma;
 | 
			
		||||
          usec += timer.useconds();
 | 
			
		||||
          flops+= flops_call*NN;
 | 
			
		||||
        int pc = processor_coor[dim];
 | 
			
		||||
        for(int idx=0;idx<sgrid->lSites();idx++) {
 | 
			
		||||
	  sgrid->LocalIndexToLocalCoor(idx,lcoor);
 | 
			
		||||
	  gcoor = lcoor;
 | 
			
		||||
	  // extract the result
 | 
			
		||||
	  sobj s;
 | 
			
		||||
	  gcoor[dim] = lcoor[dim]+L*pc;
 | 
			
		||||
	  peekLocalSite(s,pgresult,gcoor);
 | 
			
		||||
	  pokeLocalSite(s,result,lcoor);
 | 
			
		||||
	}
 | 
			
		||||
      	  
 | 
			
		||||
	FFTW<scalar>::fftw_destroy_plan(p);
 | 
			
		||||
      
 | 
			
		||||
      int Ncomp = sizeof(sobj)/sizeof(scalar);
 | 
			
		||||
      int Nlow  = 1;
 | 
			
		||||
      for(int d=0;d<dim;d++){
 | 
			
		||||
        Nlow*=vgrid->_ldimensions[d];
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      int rank = 1;  /* 1d transforms */
 | 
			
		||||
      int n[] = {G}; /* 1d transforms of length G */
 | 
			
		||||
      int howmany = Ncomp;
 | 
			
		||||
      int odist,idist,istride,ostride;
 | 
			
		||||
      idist   = odist   = 1;          /* Distance between consecutive FT's */
 | 
			
		||||
      istride = ostride = Ncomp*Nlow; /* distance between two elements in the same FT */
 | 
			
		||||
      int *inembed = n, *onembed = n;
 | 
			
		||||
      
 | 
			
		||||
      scalar div;
 | 
			
		||||
	  if ( sign == backward ) div = 1.0/G;
 | 
			
		||||
	  else if ( sign == forward ) div = 1.0;
 | 
			
		||||
	  else assert(0);
 | 
			
		||||
      
 | 
			
		||||
      FFTW_plan p;
 | 
			
		||||
      {
 | 
			
		||||
        FFTW_scalar *in = (FFTW_scalar *)&pgbuf._odata[0];
 | 
			
		||||
        FFTW_scalar *out= (FFTW_scalar *)&pgbuf._odata[0];
 | 
			
		||||
        p = FFTW<scalar>::fftw_plan_many_dft(rank,n,howmany,
 | 
			
		||||
                                             in,inembed,
 | 
			
		||||
                                             istride,idist,
 | 
			
		||||
                                             out,onembed,
 | 
			
		||||
                                             ostride, odist,
 | 
			
		||||
                                             sign,FFTW_ESTIMATE);
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // Barrel shift and collect global pencil
 | 
			
		||||
      std::vector<int> lcoor(Nd), gcoor(Nd);
 | 
			
		||||
      result = source;
 | 
			
		||||
      for(int p=0;p<processors[dim];p++) {
 | 
			
		||||
        PARALLEL_REGION
 | 
			
		||||
        {
 | 
			
		||||
          std::vector<int> cbuf(Nd);
 | 
			
		||||
          sobj s;
 | 
			
		||||
          
 | 
			
		||||
          PARALLEL_FOR_LOOP_INTERN
 | 
			
		||||
          for(int idx=0;idx<sgrid->lSites();idx++) {
 | 
			
		||||
            sgrid->LocalIndexToLocalCoor(idx,cbuf);
 | 
			
		||||
            peekLocalSite(s,result,cbuf);
 | 
			
		||||
            cbuf[dim]+=p*L;
 | 
			
		||||
            pokeLocalSite(s,pgbuf,cbuf);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        result = Cshift(result,dim,L);
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // Loop over orthog coords
 | 
			
		||||
      int NN=pencil_g.lSites();
 | 
			
		||||
      GridStopWatch timer;
 | 
			
		||||
      timer.Start();
 | 
			
		||||
      PARALLEL_REGION
 | 
			
		||||
      {
 | 
			
		||||
        std::vector<int> cbuf(Nd);
 | 
			
		||||
        
 | 
			
		||||
        PARALLEL_FOR_LOOP_INTERN
 | 
			
		||||
        for(int idx=0;idx<NN;idx++) {
 | 
			
		||||
          pencil_g.LocalIndexToLocalCoor(idx, cbuf);
 | 
			
		||||
          if ( cbuf[dim] == 0 ) {  // restricts loop to plane at lcoor[dim]==0
 | 
			
		||||
            FFTW_scalar *in = (FFTW_scalar *)&pgbuf._odata[idx];
 | 
			
		||||
            FFTW_scalar *out= (FFTW_scalar *)&pgbuf._odata[idx];
 | 
			
		||||
            FFTW<scalar>::fftw_execute_dft(p,in,out);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      timer.Stop();
 | 
			
		||||
      
 | 
			
		||||
      // performance counting
 | 
			
		||||
      double add,mul,fma;
 | 
			
		||||
      FFTW<scalar>::fftw_flops(p,&add,&mul,&fma);
 | 
			
		||||
      flops_call = add+mul+2.0*fma;
 | 
			
		||||
      usec += timer.useconds();
 | 
			
		||||
      flops+= flops_call*NN;
 | 
			
		||||
      
 | 
			
		||||
      // writing out result
 | 
			
		||||
      int pc = processor_coor[dim];
 | 
			
		||||
      PARALLEL_REGION
 | 
			
		||||
      {
 | 
			
		||||
        std::vector<int> clbuf(Nd), cgbuf(Nd);
 | 
			
		||||
        sobj s;
 | 
			
		||||
        
 | 
			
		||||
        PARALLEL_FOR_LOOP_INTERN
 | 
			
		||||
        for(int idx=0;idx<sgrid->lSites();idx++) {
 | 
			
		||||
          sgrid->LocalIndexToLocalCoor(idx,clbuf);
 | 
			
		||||
          cgbuf = clbuf;
 | 
			
		||||
          cgbuf[dim] = clbuf[dim]+L*pc;
 | 
			
		||||
          peekLocalSite(s,pgbuf,cgbuf);
 | 
			
		||||
          s = s * div;
 | 
			
		||||
          pokeLocalSite(s,result,clbuf);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // destroying plan
 | 
			
		||||
      FFTW<scalar>::fftw_destroy_plan(p);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -77,11 +77,10 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#include <Grid/Stencil.h>      
 | 
			
		||||
#include <Grid/Algorithms.h>   
 | 
			
		||||
#include <Grid/parallelIO/BinaryIO.h>
 | 
			
		||||
#include <Grid/qcd/QCD.h>
 | 
			
		||||
#include <Grid/parallelIO/NerscIO.h>
 | 
			
		||||
 | 
			
		||||
#include <Grid/FFT.h>
 | 
			
		||||
 | 
			
		||||
#include <Grid/qcd/QCD.h>
 | 
			
		||||
#include <Grid/parallelIO/NerscIO.h>
 | 
			
		||||
#include <Grid/qcd/hmc/NerscCheckpointer.h>
 | 
			
		||||
#include <Grid/qcd/hmc/HmcRunner.h>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										193
									
								
								lib/Init.cc
									
									
									
									
									
								
							
							
						
						
									
										193
									
								
								lib/Init.cc
									
									
									
									
									
								
							@@ -44,9 +44,33 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#include <Grid.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <fenv.h>
 | 
			
		||||
#ifdef __APPLE__
 | 
			
		||||
static int
 | 
			
		||||
feenableexcept (unsigned int excepts)
 | 
			
		||||
{
 | 
			
		||||
  static fenv_t fenv;
 | 
			
		||||
  unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
 | 
			
		||||
    old_excepts;  // previous masks
 | 
			
		||||
 | 
			
		||||
  if ( fegetenv (&fenv) ) return -1;
 | 
			
		||||
  old_excepts = fenv.__control & FE_ALL_EXCEPT;
 | 
			
		||||
 | 
			
		||||
  // unmask
 | 
			
		||||
  fenv.__control &= ~new_excepts;
 | 
			
		||||
  fenv.__mxcsr   &= ~(new_excepts << 7);
 | 
			
		||||
 | 
			
		||||
  return ( fesetenv (&fenv) ? -1 : old_excepts );
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////
 | 
			
		||||
// Convenience functions to access stadard command line arg
 | 
			
		||||
// driven parallelism controls
 | 
			
		||||
@@ -123,6 +147,13 @@ void GridCmdOptionIntVector(std::string &str,std::vector<int> & vec)
 | 
			
		||||
  return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GridCmdOptionInt(std::string &str,int & val)
 | 
			
		||||
{
 | 
			
		||||
  std::stringstream ss(str);
 | 
			
		||||
  ss>>val;
 | 
			
		||||
  return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void GridParseLayout(char **argv,int argc,
 | 
			
		||||
		     std::vector<int> &latt,
 | 
			
		||||
@@ -153,14 +184,12 @@ void GridParseLayout(char **argv,int argc,
 | 
			
		||||
    assert(ompthreads.size()==1);
 | 
			
		||||
    GridThread::SetThreads(ompthreads[0]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if( GridCmdOptionExists(argv,argv+argc,"--cores") ){
 | 
			
		||||
    std::vector<int> cores(0);
 | 
			
		||||
    int cores;
 | 
			
		||||
    arg= GridCmdOptionPayload(argv,argv+argc,"--cores");
 | 
			
		||||
    GridCmdOptionIntVector(arg,cores);
 | 
			
		||||
    GridThread::SetCores(cores[0]);
 | 
			
		||||
    GridCmdOptionInt(arg,cores);
 | 
			
		||||
    GridThread::SetCores(cores);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string GridCmdVectorIntToString(const std::vector<int> & vec){
 | 
			
		||||
@@ -169,7 +198,7 @@ std::string GridCmdVectorIntToString(const std::vector<int> & vec){
 | 
			
		||||
  return oss.str();
 | 
			
		||||
}
 | 
			
		||||
/////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Reinit guard
 | 
			
		||||
/////////////////////////////////////////////////////////
 | 
			
		||||
static int Grid_is_initialised = 0;
 | 
			
		||||
 | 
			
		||||
@@ -178,27 +207,31 @@ void Grid_init(int *argc,char ***argv)
 | 
			
		||||
{
 | 
			
		||||
  GridLogger::StopWatch.Start();
 | 
			
		||||
 | 
			
		||||
  std::string arg;
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // Shared memory block size
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--shm") ){
 | 
			
		||||
    int MB;
 | 
			
		||||
    arg= GridCmdOptionPayload(*argv,*argv+*argc,"--shm");
 | 
			
		||||
    GridCmdOptionInt(arg,MB);
 | 
			
		||||
    CartesianCommunicator::MAX_MPI_SHM_BYTES = MB*1024*1024;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  CartesianCommunicator::Init(argc,argv);
 | 
			
		||||
 | 
			
		||||
  // Parse command line args.
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // Logging
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  std::string arg;
 | 
			
		||||
  std::vector<std::string> logstreams;
 | 
			
		||||
  std::string defaultLog("Error,Warning,Message,Performance");
 | 
			
		||||
 | 
			
		||||
  GridCmdOptionCSL(defaultLog,logstreams);
 | 
			
		||||
  GridLogConfigure(logstreams);
 | 
			
		||||
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--help") ){
 | 
			
		||||
    std::cout<<GridLogMessage<<"--help : this message"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"--debug-signals : catch sigsegv and print a blame report"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"--debug-stdout  : print stdout from EVERY node"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"--decomposition : report on default omp,mpi and simd decomposition"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"--mpi n.n.n.n   : default MPI decomposition"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"--threads n     : default number of OMP threads"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"--grid n.n.n.n  : default Grid size"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"--log list      : comma separted list of streams from Error,Warning,Message,Performance,Iterative,Integrator,Debug,Colours"<<std::endl;
 | 
			
		||||
    exit(EXIT_SUCCESS);
 | 
			
		||||
  if( !GridCmdOptionExists(*argv,*argv+*argc,"--debug-stdout") ){
 | 
			
		||||
    Grid_quiesce_nodes();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--log") ){
 | 
			
		||||
@@ -207,38 +240,39 @@ void Grid_init(int *argc,char ***argv)
 | 
			
		||||
    GridLogConfigure(logstreams);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--debug-signals") ){
 | 
			
		||||
    Grid_debug_handler_init();
 | 
			
		||||
  }
 | 
			
		||||
  if( !GridCmdOptionExists(*argv,*argv+*argc,"--debug-stdout") ){
 | 
			
		||||
    Grid_quiesce_nodes();
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--dslash-opt") ){
 | 
			
		||||
    QCD::WilsonKernelsStatic::HandOpt=1;
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--lebesgue") ){
 | 
			
		||||
    LebesgueOrder::UseLebesgueOrder=1;
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--cacheblocking") ){
 | 
			
		||||
    arg= GridCmdOptionPayload(*argv,*argv+*argc,"--cacheblocking");
 | 
			
		||||
    GridCmdOptionIntVector(arg,LebesgueOrder::Block);
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--timestamp") ){
 | 
			
		||||
    GridLogTimestamp(1);
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // Help message
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--help") ){
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --help : this message"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"Geometry:"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --mpi n.n.n.n   : default MPI decomposition"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --threads n     : default number of OMP threads"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --grid n.n.n.n  : default Grid size"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --shm  M        : allocate M megabytes of shared memory for comms"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"Verbose and debug:"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --log list      : comma separted list of streams from Error,Warning,Message,Performance,Iterative,Integrator,Debug,Colours"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --decomposition : report on default omp,mpi and simd decomposition"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --debug-signals : catch sigsegv and print a blame report"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --debug-stdout  : print stdout from EVERY node"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --notimestamp   : suppress millisecond resolution stamps"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"Performance:"<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --dslash-generic: Wilson kernel for generic Nc"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --dslash-unroll : Wilson kernel for Nc=3"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --dslash-asm    : Wilson kernel for AVX512"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --lebesgue      : Cache oblivious Lebesgue curve/Morton order/Z-graph stencil looping"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<"  --cacheblocking n.m.o.p : Hypercuboidal cache blocking"<<std::endl;    
 | 
			
		||||
    std::cout<<GridLogMessage<<std::endl;
 | 
			
		||||
    exit(EXIT_SUCCESS);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GridParseLayout(*argv,*argc,
 | 
			
		||||
		  Grid_default_latt,
 | 
			
		||||
		  Grid_default_mpi);
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--decomposition") ){
 | 
			
		||||
    std::cout<<GridLogMessage<<"Grid Decomposition\n";
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tOpenMP threads : "<<GridThread::GetThreads()<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tMPI tasks      : "<<GridCmdVectorIntToString(GridDefaultMpi())<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tvRealF         : "<<sizeof(vRealF)*8    <<"bits ; " <<GridCmdVectorIntToString(GridDefaultSimd(4,vRealF::Nsimd()))<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tvRealD         : "<<sizeof(vRealD)*8    <<"bits ; " <<GridCmdVectorIntToString(GridDefaultSimd(4,vRealD::Nsimd()))<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tvComplexF      : "<<sizeof(vComplexF)*8 <<"bits ; " <<GridCmdVectorIntToString(GridDefaultSimd(4,vComplexF::Nsimd()))<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tvComplexD      : "<<sizeof(vComplexD)*8 <<"bits ; " <<GridCmdVectorIntToString(GridDefaultSimd(4,vComplexD::Nsimd()))<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // Banner
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  std::string COL_RED    = GridLogColours.colour["RED"];
 | 
			
		||||
  std::string COL_PURPLE = GridLogColours.colour["PURPLE"];
 | 
			
		||||
@@ -247,7 +281,6 @@ void Grid_init(int *argc,char ***argv)
 | 
			
		||||
  std::string COL_BLUE   = GridLogColours.colour["BLUE"];
 | 
			
		||||
  std::string COL_YELLOW = GridLogColours.colour["YELLOW"];
 | 
			
		||||
  std::string COL_BACKGROUND = GridLogColours.colour["NORMAL"];
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  std::cout <<std::endl;
 | 
			
		||||
  std::cout <<COL_RED  << "__|__|__|__|__"<<             "|__|__|_"<<COL_PURPLE<<"_|__|__|"<<                "__|__|__|__|__"<<std::endl; 
 | 
			
		||||
@@ -281,13 +314,62 @@ void Grid_init(int *argc,char ***argv)
 | 
			
		||||
  std::cout << COL_BACKGROUND <<std::endl;
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
  // Debug and performance options
 | 
			
		||||
  ////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--debug-signals") ){
 | 
			
		||||
    Grid_debug_handler_init();
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--dslash-unroll") ){
 | 
			
		||||
    QCD::WilsonKernelsStatic::Opt=QCD::WilsonKernelsStatic::OptHandUnroll;
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--dslash-asm") ){
 | 
			
		||||
    QCD::WilsonKernelsStatic::Opt=QCD::WilsonKernelsStatic::OptInlineAsm;
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--dslash-generic") ){
 | 
			
		||||
    QCD::WilsonKernelsStatic::Opt=QCD::WilsonKernelsStatic::OptGeneric;
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--lebesgue") ){
 | 
			
		||||
    LebesgueOrder::UseLebesgueOrder=1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--cacheblocking") ){
 | 
			
		||||
    arg= GridCmdOptionPayload(*argv,*argv+*argc,"--cacheblocking");
 | 
			
		||||
    GridCmdOptionIntVector(arg,LebesgueOrder::Block);
 | 
			
		||||
  }
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--notimestamp") ){
 | 
			
		||||
    GridLogTimestamp(0);
 | 
			
		||||
  } else { 
 | 
			
		||||
    GridLogTimestamp(1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  GridParseLayout(*argv,*argc,
 | 
			
		||||
		  Grid_default_latt,
 | 
			
		||||
		  Grid_default_mpi);
 | 
			
		||||
 | 
			
		||||
  std::cout << GridLogMessage << "Requesting "<< CartesianCommunicator::MAX_MPI_SHM_BYTES <<" byte stencil comms buffers "<<std::endl;
 | 
			
		||||
 | 
			
		||||
  if( GridCmdOptionExists(*argv,*argv+*argc,"--decomposition") ){
 | 
			
		||||
    std::cout<<GridLogMessage<<"Grid Decomposition\n";
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tOpenMP threads : "<<GridThread::GetThreads()<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tMPI tasks      : "<<GridCmdVectorIntToString(GridDefaultMpi())<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tvRealF         : "<<sizeof(vRealF)*8    <<"bits ; " <<GridCmdVectorIntToString(GridDefaultSimd(4,vRealF::Nsimd()))<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tvRealD         : "<<sizeof(vRealD)*8    <<"bits ; " <<GridCmdVectorIntToString(GridDefaultSimd(4,vRealD::Nsimd()))<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tvComplexF      : "<<sizeof(vComplexF)*8 <<"bits ; " <<GridCmdVectorIntToString(GridDefaultSimd(4,vComplexF::Nsimd()))<<std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage<<"\tvComplexD      : "<<sizeof(vComplexD)*8 <<"bits ; " <<GridCmdVectorIntToString(GridDefaultSimd(4,vComplexD::Nsimd()))<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  Grid_is_initialised = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
void Grid_finalize(void)
 | 
			
		||||
{
 | 
			
		||||
#if defined (GRID_COMMS_MPI) || defined (GRID_COMMS_MPI3)
 | 
			
		||||
#if defined (GRID_COMMS_MPI) || defined (GRID_COMMS_MPI3) 
 | 
			
		||||
  MPI_Finalize();
 | 
			
		||||
  Grid_unquiesce_nodes();
 | 
			
		||||
#endif
 | 
			
		||||
@@ -334,10 +416,7 @@ void Grid_sa_signal_handler(int sig,siginfo_t *si,void * ptr)
 | 
			
		||||
  exit(0);
 | 
			
		||||
  return;
 | 
			
		||||
};
 | 
			
		||||
#ifdef GRID_FPE
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
#include <fenv.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void Grid_debug_handler_init(void)
 | 
			
		||||
{
 | 
			
		||||
  struct sigaction sa,osa;
 | 
			
		||||
@@ -346,9 +425,9 @@ void Grid_debug_handler_init(void)
 | 
			
		||||
  sa.sa_flags    = SA_SIGINFO;
 | 
			
		||||
  sigaction(SIGSEGV,&sa,NULL);
 | 
			
		||||
  sigaction(SIGTRAP,&sa,NULL);
 | 
			
		||||
#ifdef GRID_FPE
 | 
			
		||||
 | 
			
		||||
  feenableexcept( FE_INVALID|FE_OVERFLOW|FE_DIVBYZERO);
 | 
			
		||||
 | 
			
		||||
  sigaction(SIGFPE,&sa,NULL);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,7 @@ namespace Grid {
 | 
			
		||||
  void GridCmdOptionCSL(std::string str,std::vector<std::string> & vec);
 | 
			
		||||
  void GridCmdOptionIntVector(std::string &str,std::vector<int> & vec);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  void GridParseLayout(char **argv,int argc,
 | 
			
		||||
		       std::vector<int> &latt,
 | 
			
		||||
		       std::vector<int> &simd,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								lib/Log.cc
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								lib/Log.cc
									
									
									
									
									
								
							@@ -31,8 +31,23 @@ directory
 | 
			
		||||
/*  END LEGAL */
 | 
			
		||||
#include <Grid.h>
 | 
			
		||||
 | 
			
		||||
#include <cxxabi.h>
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
 | 
			
		||||
  std::string demangle(const char* name) {
 | 
			
		||||
    
 | 
			
		||||
    int status = -4; // some arbitrary value to eliminate the compiler warning
 | 
			
		||||
    
 | 
			
		||||
    // enable c++11 by passing the flag -std=c++11 to g++
 | 
			
		||||
    std::unique_ptr<char, void(*)(void*)> res {
 | 
			
		||||
      abi::__cxa_demangle(name, NULL, NULL, &status),
 | 
			
		||||
	std::free
 | 
			
		||||
	};
 | 
			
		||||
    
 | 
			
		||||
    return (status==0) ? res.get() : name ;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
GridStopWatch Logger::StopWatch;
 | 
			
		||||
int Logger::timestamp;
 | 
			
		||||
std::ostream Logger::devnull(0);
 | 
			
		||||
@@ -78,7 +93,7 @@ void GridLogConfigure(std::vector<std::string> &logstreams) {
 | 
			
		||||
////////////////////////////////////////////////////////////
 | 
			
		||||
void Grid_quiesce_nodes(void) {
 | 
			
		||||
  int me = 0;
 | 
			
		||||
#if defined(GRID_COMMS_MPI) || defined(GRID_COMMS_MPI3)
 | 
			
		||||
#if defined(GRID_COMMS_MPI) || defined(GRID_COMMS_MPI3) || defined(GRID_COMMS_MPI3L)
 | 
			
		||||
  MPI_Comm_rank(MPI_COMM_WORLD, &me);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef GRID_COMMS_SHMEM
 | 
			
		||||
 
 | 
			
		||||
@@ -144,6 +144,7 @@ extern GridLogger GridLogIterative  ;
 | 
			
		||||
extern GridLogger GridLogIntegrator  ;
 | 
			
		||||
extern Colours    GridLogColours;
 | 
			
		||||
 | 
			
		||||
 std::string demangle(const char* name) ;
 | 
			
		||||
 | 
			
		||||
#define _NBACKTRACE (256)
 | 
			
		||||
extern void * Grid_backtrace_buffer[_NBACKTRACE];
 | 
			
		||||
@@ -162,7 +163,7 @@ std::fclose(fp);	    \
 | 
			
		||||
int symbols    = backtrace        (Grid_backtrace_buffer,_NBACKTRACE);\
 | 
			
		||||
char **strings = backtrace_symbols(Grid_backtrace_buffer,symbols);\
 | 
			
		||||
for (int i = 0; i < symbols; i++){\
 | 
			
		||||
  std::fprintf (fp,"BackTrace Strings: %d %s\n",i, strings[i]); std::fflush(fp); \
 | 
			
		||||
  std::fprintf (fp,"BackTrace Strings: %d %s\n",i, demangle(strings[i]).c_str()); std::fflush(fp); \
 | 
			
		||||
}\
 | 
			
		||||
}
 | 
			
		||||
#else 
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,11 @@ if BUILD_COMMS_MPI3
 | 
			
		||||
  extra_sources+=communicator/Communicator_base.cc
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if BUILD_COMMS_MPI3L
 | 
			
		||||
  extra_sources+=communicator/Communicator_mpi3_leader.cc
 | 
			
		||||
  extra_sources+=communicator/Communicator_base.cc
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if BUILD_COMMS_SHMEM
 | 
			
		||||
  extra_sources+=communicator/Communicator_shmem.cc
 | 
			
		||||
  extra_sources+=communicator/Communicator_base.cc
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,9 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#else
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __x86_64__
 | 
			
		||||
#include <x86intrin.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
 | 
			
		||||
@@ -86,7 +89,6 @@ inline uint64_t cyclecount(void){
 | 
			
		||||
   return tmp;
 | 
			
		||||
}
 | 
			
		||||
#elif defined __x86_64__
 | 
			
		||||
#include <x86intrin.h>
 | 
			
		||||
inline uint64_t cyclecount(void){ 
 | 
			
		||||
  return __rdtsc();
 | 
			
		||||
  //  unsigned int dummy;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								lib/Simd.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								lib/Simd.h
									
									
									
									
									
								
							@@ -237,6 +237,18 @@ namespace Grid {
 | 
			
		||||
    stream<<">";
 | 
			
		||||
    return stream;
 | 
			
		||||
  }
 | 
			
		||||
  inline std::ostream& operator<< (std::ostream& stream, const vInteger &o){
 | 
			
		||||
    int nn=vInteger::Nsimd();
 | 
			
		||||
    std::vector<Integer,alignedAllocator<Integer> > buf(nn);
 | 
			
		||||
    vstore(o,&buf[0]);
 | 
			
		||||
    stream<<"<";
 | 
			
		||||
    for(int i=0;i<nn;i++){
 | 
			
		||||
      stream<<buf[i];
 | 
			
		||||
      if(i<nn-1) stream<<",";
 | 
			
		||||
    }
 | 
			
		||||
    stream<<">";
 | 
			
		||||
    return stream;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,14 +38,19 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#ifdef GRID_OMP
 | 
			
		||||
#include <omp.h>
 | 
			
		||||
#ifdef GRID_NUMA
 | 
			
		||||
#define PARALLEL_FOR_LOOP _Pragma("omp parallel for schedule(static)")
 | 
			
		||||
#define PARALLEL_FOR_LOOP        _Pragma("omp parallel for schedule(static)")
 | 
			
		||||
#define PARALLEL_FOR_LOOP_INTERN _Pragma("omp for schedule(static)")
 | 
			
		||||
#else
 | 
			
		||||
#define PARALLEL_FOR_LOOP _Pragma("omp parallel for schedule(runtime)")
 | 
			
		||||
#define PARALLEL_FOR_LOOP        _Pragma("omp parallel for schedule(runtime)")
 | 
			
		||||
#define PARALLEL_FOR_LOOP_INTERN _Pragma("omp for schedule(runtime)")
 | 
			
		||||
#endif
 | 
			
		||||
#define PARALLEL_NESTED_LOOP2 _Pragma("omp parallel for collapse(2)")
 | 
			
		||||
#define PARALLEL_REGION       _Pragma("omp parallel")
 | 
			
		||||
#else
 | 
			
		||||
#define PARALLEL_FOR_LOOP 
 | 
			
		||||
#define PARALLEL_FOR_LOOP
 | 
			
		||||
#define PARALLEL_FOR_LOOP_INTERN
 | 
			
		||||
#define PARALLEL_NESTED_LOOP2
 | 
			
		||||
#define PARALLEL_REGION
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
 
 | 
			
		||||
@@ -282,7 +282,7 @@ PARALLEL_FOR_LOOP
 | 
			
		||||
	  } else if(SE->_is_local) { 
 | 
			
		||||
	    nbr = in._odata[SE->_offset];
 | 
			
		||||
	  } else {
 | 
			
		||||
	    nbr = Stencil.comm_buf[SE->_offset];
 | 
			
		||||
	    nbr = Stencil.CommBuf()[SE->_offset];
 | 
			
		||||
	  }
 | 
			
		||||
	  res = res + A[point]._odata[ss]*nbr;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -154,7 +154,7 @@ class ConjugateGradient : public OperatorFunction<Field> {
 | 
			
		||||
                  << LinalgTimer.Elapsed();
 | 
			
		||||
        std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
        if (ErrorOnNoConverge) assert(true_residual / Tolerance < 1000.0);
 | 
			
		||||
        if (ErrorOnNoConverge) assert(true_residual / Tolerance < 10000.0);
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,11 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
 | 
			
		||||
#include <string.h> //memset
 | 
			
		||||
#ifdef USE_LAPACK
 | 
			
		||||
#include <lapacke.h>
 | 
			
		||||
void LAPACK_dstegr(char *jobz, char *range, int *n, double *d, double *e,
 | 
			
		||||
                   double *vl, double *vu, int *il, int *iu, double *abstol,
 | 
			
		||||
                   int *m, double *w, double *z, int *ldz, int *isuppz,
 | 
			
		||||
                   double *work, int *lwork, int *iwork, int *liwork,
 | 
			
		||||
                   int *info);
 | 
			
		||||
#endif
 | 
			
		||||
#include "DenseMatrix.h"
 | 
			
		||||
#include "EigenSort.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -31,14 +31,8 @@ namespace Grid {
 | 
			
		||||
///////////////////////////////////////////////////////////////
 | 
			
		||||
// Info that is setup once and indept of cartesian layout
 | 
			
		||||
///////////////////////////////////////////////////////////////
 | 
			
		||||
int CartesianCommunicator::ShmRank;
 | 
			
		||||
int CartesianCommunicator::ShmSize;
 | 
			
		||||
int CartesianCommunicator::GroupRank;
 | 
			
		||||
int CartesianCommunicator::GroupSize;
 | 
			
		||||
int CartesianCommunicator::WorldRank;
 | 
			
		||||
int CartesianCommunicator::WorldSize;
 | 
			
		||||
int CartesianCommunicator::Slave;
 | 
			
		||||
void *              CartesianCommunicator::ShmCommBuf;
 | 
			
		||||
uint64_t            CartesianCommunicator::MAX_MPI_SHM_BYTES   = 128*1024*1024; 
 | 
			
		||||
 | 
			
		||||
/////////////////////////////////
 | 
			
		||||
// Alloc, free shmem region
 | 
			
		||||
@@ -48,8 +42,12 @@ void *CartesianCommunicator::ShmBufferMalloc(size_t bytes){
 | 
			
		||||
  void *ptr = (void *)heap_top;
 | 
			
		||||
  heap_top  += bytes;
 | 
			
		||||
  heap_bytes+= bytes;
 | 
			
		||||
  std::cout <<"Shm alloc "<<ptr<<std::endl;
 | 
			
		||||
  assert(heap_bytes < MAX_MPI_SHM_BYTES);
 | 
			
		||||
  if (heap_bytes >= MAX_MPI_SHM_BYTES) {
 | 
			
		||||
    std::cout<< " ShmBufferMalloc exceeded shared heap size -- try increasing with --shm <MB> flag" <<std::endl;
 | 
			
		||||
    std::cout<< " Parameter specified in units of MB (megabytes) " <<std::endl;
 | 
			
		||||
    std::cout<< " Current value is " << (MAX_MPI_SHM_BYTES/(1024*1024)) <<std::endl;
 | 
			
		||||
    assert(heap_bytes<MAX_MPI_SHM_BYTES);
 | 
			
		||||
  }
 | 
			
		||||
  return ptr;
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::ShmBufferFreeAll(void) { 
 | 
			
		||||
@@ -70,12 +68,6 @@ int                      CartesianCommunicator::ProcessorCount(void)    { return
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// very VERY rarely (Log, serial RNG) we need world without a grid
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
int  CartesianCommunicator::RankWorld(void){ return WorldRank; };
 | 
			
		||||
int CartesianCommunicator::Ranks    (void) { return WorldSize; };
 | 
			
		||||
int CartesianCommunicator::Nodes    (void) { return GroupSize; };
 | 
			
		||||
int CartesianCommunicator::Cores    (void) { return ShmSize;   };
 | 
			
		||||
int CartesianCommunicator::NodeRank (void) { return GroupRank; };
 | 
			
		||||
int CartesianCommunicator::CoreRank (void) { return ShmRank;   };
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::GlobalSum(ComplexF &c)
 | 
			
		||||
{
 | 
			
		||||
@@ -94,7 +86,7 @@ void CartesianCommunicator::GlobalSumVector(ComplexD *c,int N)
 | 
			
		||||
  GlobalSumVector((double *)c,2*N);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef GRID_COMMS_MPI3
 | 
			
		||||
#if !defined( GRID_COMMS_MPI3) && !defined (GRID_COMMS_MPI3L)
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::StencilSendToRecvFromBegin(std::vector<CommsRequest_t> &list,
 | 
			
		||||
						       void *xmit,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
 | 
			
		||||
    /*************************************************************************************
 | 
			
		||||
 | 
			
		||||
    Grid physics library, www.github.com/paboyle/Grid 
 | 
			
		||||
@@ -37,6 +38,9 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#ifdef GRID_COMMS_MPI3
 | 
			
		||||
#include <mpi.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef GRID_COMMS_MPI3L
 | 
			
		||||
#include <mpi.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef GRID_COMMS_SHMEM
 | 
			
		||||
#include <mpp/shmem.h>
 | 
			
		||||
#endif
 | 
			
		||||
@@ -51,7 +55,7 @@ class CartesianCommunicator {
 | 
			
		||||
  // Give external control (command line override?) of this
 | 
			
		||||
 | 
			
		||||
  static const int      MAXLOG2RANKSPERNODE = 16;            
 | 
			
		||||
  static const uint64_t MAX_MPI_SHM_BYTES   = 128*1024*1024; 
 | 
			
		||||
  static uint64_t MAX_MPI_SHM_BYTES;
 | 
			
		||||
 | 
			
		||||
  // Communicator should know nothing of the physics grid, only processor grid.
 | 
			
		||||
  int              _Nprocessors;     // How many in all
 | 
			
		||||
@@ -60,9 +64,9 @@ class CartesianCommunicator {
 | 
			
		||||
  std::vector<int> _processor_coor;  // linear processor coordinate
 | 
			
		||||
  unsigned long _ndimension;
 | 
			
		||||
 | 
			
		||||
#if defined (GRID_COMMS_MPI) || defined (GRID_COMMS_MPI3)
 | 
			
		||||
  MPI_Comm communicator;
 | 
			
		||||
#if defined (GRID_COMMS_MPI) || defined (GRID_COMMS_MPI3) || defined (GRID_COMMS_MPI3L)
 | 
			
		||||
  static MPI_Comm communicator_world;
 | 
			
		||||
         MPI_Comm communicator;
 | 
			
		||||
  typedef MPI_Request CommsRequest_t;
 | 
			
		||||
#else 
 | 
			
		||||
  typedef int CommsRequest_t;
 | 
			
		||||
@@ -75,7 +79,15 @@ class CartesianCommunicator {
 | 
			
		||||
  // cartesian communicator on a subset of ranks, slave ranks controlled
 | 
			
		||||
  // by group leader with data xfer via shared memory
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////
 | 
			
		||||
#ifdef  GRID_COMMS_MPI3
 | 
			
		||||
#ifdef GRID_COMMS_MPI3
 | 
			
		||||
 | 
			
		||||
  static int ShmRank;
 | 
			
		||||
  static int ShmSize;
 | 
			
		||||
  static int GroupRank;
 | 
			
		||||
  static int GroupSize;
 | 
			
		||||
  static int WorldRank;
 | 
			
		||||
  static int WorldSize;
 | 
			
		||||
 | 
			
		||||
  std::vector<int>  WorldDims;
 | 
			
		||||
  std::vector<int>  GroupDims;
 | 
			
		||||
  std::vector<int>  ShmDims;
 | 
			
		||||
@@ -83,7 +95,7 @@ class CartesianCommunicator {
 | 
			
		||||
  std::vector<int> GroupCoor;
 | 
			
		||||
  std::vector<int> ShmCoor;
 | 
			
		||||
  std::vector<int> WorldCoor;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  static std::vector<int> GroupRanks; 
 | 
			
		||||
  static std::vector<int> MyGroup;
 | 
			
		||||
  static int ShmSetup;
 | 
			
		||||
@@ -93,13 +105,20 @@ class CartesianCommunicator {
 | 
			
		||||
  std::vector<int>  LexicographicToWorldRank;
 | 
			
		||||
  
 | 
			
		||||
  static std::vector<void *> ShmCommBufs;
 | 
			
		||||
 | 
			
		||||
#else 
 | 
			
		||||
  static void ShmInitGeneric(void);
 | 
			
		||||
  static commVector<uint8_t> ShmBufStorageVector;
 | 
			
		||||
#endif 
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////
 | 
			
		||||
  // Grid information and queries
 | 
			
		||||
  // Implemented in Communicator_base.C
 | 
			
		||||
  /////////////////////////////////
 | 
			
		||||
  static void * ShmCommBuf;
 | 
			
		||||
  size_t heap_top;
 | 
			
		||||
  size_t heap_bytes;
 | 
			
		||||
 | 
			
		||||
  void *ShmBufferSelf(void);
 | 
			
		||||
  void *ShmBuffer(int rank);
 | 
			
		||||
  void *ShmBufferTranslate(int rank,void * local_p);
 | 
			
		||||
@@ -123,28 +142,12 @@ class CartesianCommunicator {
 | 
			
		||||
  int  RankFromProcessorCoor(std::vector<int> &coor);
 | 
			
		||||
  void ProcessorCoorFromRank(int rank,std::vector<int> &coor);
 | 
			
		||||
  
 | 
			
		||||
  /////////////////////////////////
 | 
			
		||||
  // Grid information and queries
 | 
			
		||||
  /////////////////////////////////
 | 
			
		||||
  static int ShmRank;
 | 
			
		||||
  static int ShmSize;
 | 
			
		||||
  static int GroupSize;
 | 
			
		||||
  static int GroupRank;
 | 
			
		||||
  static int WorldRank;
 | 
			
		||||
  static int WorldSize;
 | 
			
		||||
  static int Slave;
 | 
			
		||||
  
 | 
			
		||||
  int                      IsBoss(void)            ;
 | 
			
		||||
  int                      BossRank(void)          ;
 | 
			
		||||
  int                      ThisRank(void)          ;
 | 
			
		||||
  const std::vector<int> & ThisProcessorCoor(void) ;
 | 
			
		||||
  const std::vector<int> & ProcessorGrid(void)     ;
 | 
			
		||||
  int                      ProcessorCount(void)    ;
 | 
			
		||||
  static int Ranks    (void);
 | 
			
		||||
  static int Nodes    (void);
 | 
			
		||||
  static int Cores    (void);
 | 
			
		||||
  static int NodeRank (void);
 | 
			
		||||
  static int CoreRank (void);
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // very VERY rarely (Log, serial RNG) we need world without a grid
 | 
			
		||||
 
 | 
			
		||||
@@ -44,13 +44,6 @@ void CartesianCommunicator::Init(int *argc, char ***argv) {
 | 
			
		||||
    MPI_Init(argc,argv);
 | 
			
		||||
  }
 | 
			
		||||
  MPI_Comm_dup (MPI_COMM_WORLD,&communicator_world);
 | 
			
		||||
  MPI_Comm_rank(communicator_world,&WorldRank);
 | 
			
		||||
  MPI_Comm_size(communicator_world,&WorldSize);
 | 
			
		||||
  ShmRank=0;
 | 
			
		||||
  ShmSize=1;
 | 
			
		||||
  GroupRank=WorldRank;
 | 
			
		||||
  GroupSize=WorldSize;
 | 
			
		||||
  Slave    =0;
 | 
			
		||||
  ShmInitGeneric();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -198,6 +191,11 @@ void CartesianCommunicator::Broadcast(int root,void* data, int bytes)
 | 
			
		||||
  // Should only be used prior to Grid Init finished.
 | 
			
		||||
  // Check for this?
 | 
			
		||||
  ///////////////////////////////////////////////////////
 | 
			
		||||
int CartesianCommunicator::RankWorld(void){ 
 | 
			
		||||
  int r; 
 | 
			
		||||
  MPI_Comm_rank(communicator_world,&r);
 | 
			
		||||
  return r;
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes)
 | 
			
		||||
{
 | 
			
		||||
  int ierr= MPI_Bcast(data,
 | 
			
		||||
 
 | 
			
		||||
@@ -30,12 +30,18 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Info that is setup once and indept of cartesian layout
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
int CartesianCommunicator::ShmSetup = 0;
 | 
			
		||||
 | 
			
		||||
int CartesianCommunicator::ShmRank;
 | 
			
		||||
int CartesianCommunicator::ShmSize;
 | 
			
		||||
int CartesianCommunicator::GroupRank;
 | 
			
		||||
int CartesianCommunicator::GroupSize;
 | 
			
		||||
int CartesianCommunicator::WorldRank;
 | 
			
		||||
int CartesianCommunicator::WorldSize;
 | 
			
		||||
 | 
			
		||||
MPI_Comm CartesianCommunicator::communicator_world;
 | 
			
		||||
MPI_Comm CartesianCommunicator::ShmComm;
 | 
			
		||||
MPI_Win  CartesianCommunicator::ShmWindow;
 | 
			
		||||
@@ -97,15 +103,15 @@ void CartesianCommunicator::Init(int *argc, char ***argv) {
 | 
			
		||||
  
 | 
			
		||||
  std::vector<int> world_ranks(WorldSize); 
 | 
			
		||||
  GroupRanks.resize(WorldSize); 
 | 
			
		||||
  MyGroup.resize(ShmSize);
 | 
			
		||||
  for(int r=0;r<WorldSize;r++) world_ranks[r]=r;
 | 
			
		||||
  
 | 
			
		||||
  MPI_Group_translate_ranks (WorldGroup,WorldSize,&world_ranks[0],ShmGroup, &GroupRanks[0]); 
 | 
			
		||||
 | 
			
		||||
  ///////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Identify who is in my group and noninate the leader
 | 
			
		||||
    ///////////////////////////////////////////////////////////////////
 | 
			
		||||
  ///////////////////////////////////////////////////////////////////
 | 
			
		||||
  int g=0;
 | 
			
		||||
  MyGroup.resize(ShmSize);
 | 
			
		||||
  for(int rank=0;rank<WorldSize;rank++){
 | 
			
		||||
    if(GroupRanks[rank]!=MPI_UNDEFINED){
 | 
			
		||||
      assert(g<ShmSize);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										874
									
								
								lib/communicator/Communicator_mpi3_leader.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										874
									
								
								lib/communicator/Communicator_mpi3_leader.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,874 @@
 | 
			
		||||
    /*************************************************************************************
 | 
			
		||||
 | 
			
		||||
    Grid physics library, www.github.com/paboyle/Grid 
 | 
			
		||||
 | 
			
		||||
    Source file: ./lib/communicator/Communicator_mpi.cc
 | 
			
		||||
 | 
			
		||||
    Copyright (C) 2015
 | 
			
		||||
 | 
			
		||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
    the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
    (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
    This program is distributed in the hope that it will be useful,
 | 
			
		||||
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
    GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License along
 | 
			
		||||
    with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 | 
			
		||||
    See the full license in the file "LICENSE" in the top level distribution directory
 | 
			
		||||
    *************************************************************************************/
 | 
			
		||||
    /*  END LEGAL */
 | 
			
		||||
#include "Grid.h"
 | 
			
		||||
#include <mpi.h>
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
/// Workarounds:
 | 
			
		||||
/// i) bloody mac os doesn't implement unnamed semaphores since it is "optional" posix.
 | 
			
		||||
///    darwin dispatch semaphores don't seem to be multiprocess.
 | 
			
		||||
///
 | 
			
		||||
/// ii) openmpi under --mca shmem posix works with two squadrons per node; 
 | 
			
		||||
///     openmpi under default mca settings (I think --mca shmem mmap) on MacOS makes two squadrons map the SAME
 | 
			
		||||
///     memory as each other, despite their living on different communicators. This appears to be a bug in OpenMPI.
 | 
			
		||||
///
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 | 
			
		||||
typedef sem_t *Grid_semaphore;
 | 
			
		||||
 | 
			
		||||
#define SEM_INIT(S)      S = sem_open(sem_name,0,0600,0); assert ( S != SEM_FAILED );
 | 
			
		||||
#define SEM_INIT_EXCL(S) sem_unlink(sem_name); S = sem_open(sem_name,O_CREAT|O_EXCL,0600,0); assert ( S != SEM_FAILED );
 | 
			
		||||
#define SEM_POST(S) assert ( sem_post(S) == 0 ); 
 | 
			
		||||
#define SEM_WAIT(S) assert ( sem_wait(S) == 0 );
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
 | 
			
		||||
enum { COMMAND_ISEND, COMMAND_IRECV, COMMAND_WAITALL };
 | 
			
		||||
 | 
			
		||||
struct Descriptor {
 | 
			
		||||
  uint64_t buf;
 | 
			
		||||
  size_t bytes;
 | 
			
		||||
  int rank;
 | 
			
		||||
  int tag;
 | 
			
		||||
  int command;
 | 
			
		||||
  MPI_Request request;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const int pool = 48;
 | 
			
		||||
 | 
			
		||||
class SlaveState {
 | 
			
		||||
public:
 | 
			
		||||
  volatile int head;
 | 
			
		||||
  volatile int start;
 | 
			
		||||
  volatile int tail;
 | 
			
		||||
  volatile Descriptor Descrs[pool];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Slave {
 | 
			
		||||
public:
 | 
			
		||||
  Grid_semaphore  sem_head;
 | 
			
		||||
  Grid_semaphore  sem_tail;
 | 
			
		||||
  SlaveState *state;
 | 
			
		||||
  MPI_Comm squadron;
 | 
			
		||||
  uint64_t     base;
 | 
			
		||||
  int universe_rank;
 | 
			
		||||
  int vertical_rank;
 | 
			
		||||
  char sem_name [NAME_MAX];
 | 
			
		||||
  ////////////////////////////////////////////////////////////
 | 
			
		||||
  // Descriptor circular pointers
 | 
			
		||||
  ////////////////////////////////////////////////////////////
 | 
			
		||||
  Slave() {};
 | 
			
		||||
 | 
			
		||||
  void Init(SlaveState * _state,MPI_Comm _squadron,int _universe_rank,int _vertical_rank);
 | 
			
		||||
 | 
			
		||||
  void SemInit(void) {
 | 
			
		||||
    sprintf(sem_name,"/Grid_mpi3_sem_head_%d",universe_rank);
 | 
			
		||||
    //    printf("SEM_NAME: %s \n",sem_name);
 | 
			
		||||
    SEM_INIT(sem_head);
 | 
			
		||||
    sprintf(sem_name,"/Grid_mpi3_sem_tail_%d",universe_rank);
 | 
			
		||||
    //    printf("SEM_NAME: %s \n",sem_name);
 | 
			
		||||
    SEM_INIT(sem_tail);
 | 
			
		||||
  }  
 | 
			
		||||
  void SemInitExcl(void) {
 | 
			
		||||
    sprintf(sem_name,"/Grid_mpi3_sem_head_%d",universe_rank);
 | 
			
		||||
    //    printf("SEM_INIT_EXCL: %s \n",sem_name);
 | 
			
		||||
    SEM_INIT_EXCL(sem_head);
 | 
			
		||||
    sprintf(sem_name,"/Grid_mpi3_sem_tail_%d",universe_rank);
 | 
			
		||||
    //    printf("SEM_INIT_EXCL: %s \n",sem_name);
 | 
			
		||||
    SEM_INIT_EXCL(sem_tail);
 | 
			
		||||
  }  
 | 
			
		||||
  void WakeUpDMA(void) { 
 | 
			
		||||
    SEM_POST(sem_head);
 | 
			
		||||
  };
 | 
			
		||||
  void WakeUpCompute(void) { 
 | 
			
		||||
    SEM_POST(sem_tail);
 | 
			
		||||
  };
 | 
			
		||||
  void WaitForCommand(void) { 
 | 
			
		||||
    SEM_WAIT(sem_head);
 | 
			
		||||
  };
 | 
			
		||||
  void WaitForComplete(void) { 
 | 
			
		||||
    SEM_WAIT(sem_tail);
 | 
			
		||||
  };
 | 
			
		||||
  void EventLoop (void) {
 | 
			
		||||
    //    std::cout<< " Entering event loop "<<std::endl;
 | 
			
		||||
    while(1){
 | 
			
		||||
      WaitForCommand();
 | 
			
		||||
      //      std::cout << "Getting command "<<std::endl;
 | 
			
		||||
      Event();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int Event (void) ;
 | 
			
		||||
 | 
			
		||||
  uint64_t QueueCommand(int command,void *buf, int bytes, int hashtag, MPI_Comm comm,int u_rank) ;
 | 
			
		||||
 | 
			
		||||
  void WaitAll() {
 | 
			
		||||
    //    std::cout << "Queueing WAIT command  "<<std::endl;
 | 
			
		||||
    QueueCommand(COMMAND_WAITALL,0,0,0,squadron,0);
 | 
			
		||||
    //    std::cout << "Waking up DMA "<<std::endl;
 | 
			
		||||
    WakeUpDMA();
 | 
			
		||||
    //    std::cout << "Waiting from semaphore "<<std::endl;
 | 
			
		||||
    WaitForComplete();
 | 
			
		||||
    //    std::cout << "Checking FIFO is empty "<<std::endl;
 | 
			
		||||
    assert ( state->tail == state->head );
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// One instance of a data mover.
 | 
			
		||||
// Master and Slave must agree on location in shared memory
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
class MPIoffloadEngine { 
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
  static std::vector<Slave> Slaves;
 | 
			
		||||
 | 
			
		||||
  static int ShmSetup;
 | 
			
		||||
  
 | 
			
		||||
  static int UniverseRank;
 | 
			
		||||
  static int UniverseSize;
 | 
			
		||||
  
 | 
			
		||||
  static MPI_Comm communicator_universe;
 | 
			
		||||
  static MPI_Comm communicator_cached;
 | 
			
		||||
 | 
			
		||||
  static MPI_Comm HorizontalComm;
 | 
			
		||||
  static int HorizontalRank;
 | 
			
		||||
  static int HorizontalSize;
 | 
			
		||||
  
 | 
			
		||||
  static MPI_Comm VerticalComm;
 | 
			
		||||
  static MPI_Win  VerticalWindow; 
 | 
			
		||||
  static int VerticalSize;
 | 
			
		||||
  static int VerticalRank;
 | 
			
		||||
  
 | 
			
		||||
  static std::vector<void *> VerticalShmBufs;
 | 
			
		||||
  static std::vector<std::vector<int> > UniverseRanks;
 | 
			
		||||
  static std::vector<int> UserCommunicatorToWorldRanks; 
 | 
			
		||||
  
 | 
			
		||||
  static MPI_Group WorldGroup, CachedGroup;
 | 
			
		||||
  
 | 
			
		||||
  static void CommunicatorInit (MPI_Comm &communicator_world,
 | 
			
		||||
				MPI_Comm &ShmComm,
 | 
			
		||||
				void * &ShmCommBuf);
 | 
			
		||||
 | 
			
		||||
  static void MapCommRankToWorldRank(int &hashtag, int & comm_world_peer,int tag, MPI_Comm comm,int commrank);
 | 
			
		||||
 | 
			
		||||
  /////////////////////////////////////////////////////////
 | 
			
		||||
  // routines for master proc must handle any communicator
 | 
			
		||||
  /////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  static void QueueSend(int slave,void *buf, int bytes, int tag, MPI_Comm comm,int rank) {
 | 
			
		||||
     //    std::cout<< " Queueing send  "<< bytes<< " slave "<< slave << " to comm "<<rank  <<std::endl;
 | 
			
		||||
    Slaves[slave].QueueCommand(COMMAND_ISEND,buf,bytes,tag,comm,rank);
 | 
			
		||||
    //    std::cout << "Queued send command to rank "<< rank<< " via "<<slave <<std::endl;
 | 
			
		||||
    Slaves[slave].WakeUpDMA();
 | 
			
		||||
    //    std::cout << "Waking up DMA "<< slave<<std::endl;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static void QueueRecv(int slave, void *buf, int bytes, int tag, MPI_Comm comm,int rank) {
 | 
			
		||||
    //    std::cout<< " Queueing recv "<< bytes<< " slave "<< slave << " from comm "<<rank  <<std::endl;
 | 
			
		||||
    Slaves[slave].QueueCommand(COMMAND_IRECV,buf,bytes,tag,comm,rank);
 | 
			
		||||
    //    std::cout << "Queued recv command from rank "<< rank<< " via "<<slave <<std::endl;
 | 
			
		||||
    Slaves[slave].WakeUpDMA();
 | 
			
		||||
    //    std::cout << "Waking up DMA "<< slave<<std::endl;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static void WaitAll() {
 | 
			
		||||
    for(int s=1;s<VerticalSize;s++) {
 | 
			
		||||
      //      std::cout << "Waiting for slave "<< s<<std::endl;
 | 
			
		||||
      Slaves[s].WaitAll();
 | 
			
		||||
    }
 | 
			
		||||
    //    std::cout << " Wait all Complete "<<std::endl;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static void GetWork(int nwork, int me, int & mywork, int & myoff,int units){
 | 
			
		||||
    int basework = nwork/units;
 | 
			
		||||
    int backfill = units-(nwork%units);
 | 
			
		||||
    if ( me >= units ) { 
 | 
			
		||||
      mywork = myoff = 0;
 | 
			
		||||
    } else { 
 | 
			
		||||
      mywork = (nwork+me)/units;
 | 
			
		||||
      myoff  = basework * me;
 | 
			
		||||
      if ( me > backfill ) 
 | 
			
		||||
	myoff+= (me-backfill);
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static void QueueMultiplexedSend(void *buf, int bytes, int tag, MPI_Comm comm,int rank) {
 | 
			
		||||
    uint8_t * cbuf = (uint8_t *) buf;
 | 
			
		||||
    int mywork, myoff, procs;
 | 
			
		||||
    procs = VerticalSize-1;
 | 
			
		||||
    for(int s=0;s<procs;s++) {
 | 
			
		||||
      GetWork(bytes,s,mywork,myoff,procs);
 | 
			
		||||
      QueueSend(s+1,&cbuf[myoff],mywork,tag,comm,rank);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static void QueueMultiplexedRecv(void *buf, int bytes, int tag, MPI_Comm comm,int rank) {
 | 
			
		||||
    uint8_t * cbuf = (uint8_t *) buf;
 | 
			
		||||
    int mywork, myoff, procs;
 | 
			
		||||
    procs = VerticalSize-1;
 | 
			
		||||
    for(int s=0;s<procs;s++) {
 | 
			
		||||
      GetWork(bytes,s,mywork,myoff,procs);
 | 
			
		||||
      QueueRecv(s+1,&cbuf[myoff],mywork,tag,comm,rank);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Info that is setup once and indept of cartesian layout
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
std::vector<Slave> MPIoffloadEngine::Slaves;
 | 
			
		||||
    
 | 
			
		||||
int MPIoffloadEngine::UniverseRank;
 | 
			
		||||
int MPIoffloadEngine::UniverseSize;
 | 
			
		||||
 | 
			
		||||
MPI_Comm  MPIoffloadEngine::communicator_universe;
 | 
			
		||||
MPI_Comm  MPIoffloadEngine::communicator_cached;
 | 
			
		||||
MPI_Group MPIoffloadEngine::WorldGroup;
 | 
			
		||||
MPI_Group MPIoffloadEngine::CachedGroup;
 | 
			
		||||
 | 
			
		||||
MPI_Comm MPIoffloadEngine::HorizontalComm;
 | 
			
		||||
int      MPIoffloadEngine::HorizontalRank;
 | 
			
		||||
int      MPIoffloadEngine::HorizontalSize;
 | 
			
		||||
 | 
			
		||||
MPI_Comm MPIoffloadEngine::VerticalComm;
 | 
			
		||||
int      MPIoffloadEngine::VerticalSize;
 | 
			
		||||
int      MPIoffloadEngine::VerticalRank;
 | 
			
		||||
MPI_Win  MPIoffloadEngine::VerticalWindow; 
 | 
			
		||||
std::vector<void *>            MPIoffloadEngine::VerticalShmBufs;
 | 
			
		||||
std::vector<std::vector<int> > MPIoffloadEngine::UniverseRanks;
 | 
			
		||||
std::vector<int>               MPIoffloadEngine::UserCommunicatorToWorldRanks; 
 | 
			
		||||
 | 
			
		||||
int MPIoffloadEngine::ShmSetup = 0;
 | 
			
		||||
 | 
			
		||||
void MPIoffloadEngine::CommunicatorInit (MPI_Comm &communicator_world,
 | 
			
		||||
					 MPI_Comm &ShmComm,
 | 
			
		||||
					 void * &ShmCommBuf)
 | 
			
		||||
{      
 | 
			
		||||
  int flag;
 | 
			
		||||
  assert(ShmSetup==0);  
 | 
			
		||||
  
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Universe is all nodes prior to squadron grouping
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////
 | 
			
		||||
  MPI_Comm_dup (MPI_COMM_WORLD,&communicator_universe);
 | 
			
		||||
  MPI_Comm_rank(communicator_universe,&UniverseRank);
 | 
			
		||||
  MPI_Comm_size(communicator_universe,&UniverseSize);
 | 
			
		||||
  
 | 
			
		||||
  /////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Split into groups that can share memory (Verticals)
 | 
			
		||||
  /////////////////////////////////////////////////////////////////////
 | 
			
		||||
#undef MPI_SHARED_MEM_DEBUG
 | 
			
		||||
#ifdef  MPI_SHARED_MEM_DEBUG
 | 
			
		||||
  MPI_Comm_split(communicator_universe,(UniverseRank/4),UniverseRank,&VerticalComm);
 | 
			
		||||
#else 
 | 
			
		||||
  MPI_Comm_split_type(communicator_universe, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL,&VerticalComm);
 | 
			
		||||
#endif
 | 
			
		||||
  MPI_Comm_rank(VerticalComm     ,&VerticalRank);
 | 
			
		||||
  MPI_Comm_size(VerticalComm     ,&VerticalSize);
 | 
			
		||||
  
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Split into horizontal groups by rank in squadron
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////
 | 
			
		||||
  MPI_Comm_split(communicator_universe,VerticalRank,UniverseRank,&HorizontalComm);
 | 
			
		||||
  MPI_Comm_rank(HorizontalComm,&HorizontalRank);
 | 
			
		||||
  MPI_Comm_size(HorizontalComm,&HorizontalSize);
 | 
			
		||||
  assert(HorizontalSize*VerticalSize==UniverseSize);
 | 
			
		||||
  
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // What is my place in the world
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  int WorldRank=0;
 | 
			
		||||
  if(VerticalRank==0) WorldRank = HorizontalRank;
 | 
			
		||||
  int ierr=MPI_Allreduce(MPI_IN_PLACE,&WorldRank,1,MPI_INT,MPI_SUM,VerticalComm);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
  
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Where is the world in the universe?
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  UniverseRanks = std::vector<std::vector<int> >(HorizontalSize,std::vector<int>(VerticalSize,0));
 | 
			
		||||
  UniverseRanks[WorldRank][VerticalRank] = UniverseRank;
 | 
			
		||||
  for(int w=0;w<HorizontalSize;w++){
 | 
			
		||||
    ierr=MPI_Allreduce(MPI_IN_PLACE,&UniverseRanks[w][0],VerticalSize,MPI_INT,MPI_SUM,communicator_universe);
 | 
			
		||||
    assert(ierr==0);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // allocate the shared window for our group, pass back Shm info to CartesianCommunicator
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  VerticalShmBufs.resize(VerticalSize);
 | 
			
		||||
 | 
			
		||||
#undef MPI_SHARED_MEM
 | 
			
		||||
#ifdef MPI_SHARED_MEM
 | 
			
		||||
  ierr = MPI_Win_allocate_shared(CartesianCommunicator::MAX_MPI_SHM_BYTES,1,MPI_INFO_NULL,VerticalComm,&ShmCommBuf,&VerticalWindow);
 | 
			
		||||
  ierr|= MPI_Win_lock_all (MPI_MODE_NOCHECK, VerticalWindow);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
  //  std::cout<<"SHM "<<ShmCommBuf<<std::endl;
 | 
			
		||||
 | 
			
		||||
  for(int r=0;r<VerticalSize;r++){
 | 
			
		||||
    MPI_Aint sz;
 | 
			
		||||
    int dsp_unit;
 | 
			
		||||
    MPI_Win_shared_query (VerticalWindow, r, &sz, &dsp_unit, &VerticalShmBufs[r]);
 | 
			
		||||
    //    std::cout<<"SHM "<<r<<" " <<VerticalShmBufs[r]<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
#else 
 | 
			
		||||
  char shm_name [NAME_MAX];
 | 
			
		||||
  MPI_Barrier(VerticalComm);
 | 
			
		||||
 | 
			
		||||
  if ( VerticalRank == 0 ) {
 | 
			
		||||
    for(int r=0;r<VerticalSize;r++){
 | 
			
		||||
 | 
			
		||||
      size_t size = CartesianCommunicator::MAX_MPI_SHM_BYTES;
 | 
			
		||||
      if ( r>0 ) size = sizeof(SlaveState);
 | 
			
		||||
 | 
			
		||||
      sprintf(shm_name,"/Grid_mpi3_shm_%d_%d",WorldRank,r);
 | 
			
		||||
      
 | 
			
		||||
      shm_unlink(shm_name);
 | 
			
		||||
 | 
			
		||||
      int fd=shm_open(shm_name,O_RDWR|O_CREAT,0600);
 | 
			
		||||
      if ( fd < 0 ) {
 | 
			
		||||
	perror("failed shm_open");
 | 
			
		||||
	assert(0);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      ftruncate(fd, size);
 | 
			
		||||
 | 
			
		||||
      VerticalShmBufs[r] = mmap(NULL,size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 | 
			
		||||
 | 
			
		||||
      if ( VerticalShmBufs[r] == MAP_FAILED ) { 
 | 
			
		||||
	perror("failed mmap");
 | 
			
		||||
	assert(0);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      uint64_t * check = (uint64_t *) VerticalShmBufs[r];
 | 
			
		||||
      check[0] = WorldRank;
 | 
			
		||||
      check[1] = r;
 | 
			
		||||
 | 
			
		||||
      //      std::cout<<"SHM "<<r<<" " <<VerticalShmBufs[r]<<std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  MPI_Barrier(VerticalComm);
 | 
			
		||||
 | 
			
		||||
  if ( VerticalRank != 0 ) { 
 | 
			
		||||
  for(int r=0;r<VerticalSize;r++){
 | 
			
		||||
 | 
			
		||||
    size_t size = CartesianCommunicator::MAX_MPI_SHM_BYTES ;
 | 
			
		||||
    if ( r>0 ) size = sizeof(SlaveState);
 | 
			
		||||
    
 | 
			
		||||
    sprintf(shm_name,"/Grid_mpi3_shm_%d_%d",WorldRank,r);
 | 
			
		||||
    
 | 
			
		||||
    int fd=shm_open(shm_name,O_RDWR|O_CREAT,0600);
 | 
			
		||||
    if ( fd<0 ) {
 | 
			
		||||
      perror("failed shm_open");
 | 
			
		||||
      assert(0);
 | 
			
		||||
    }
 | 
			
		||||
    VerticalShmBufs[r] = mmap(NULL,size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 | 
			
		||||
 | 
			
		||||
    uint64_t * check = (uint64_t *) VerticalShmBufs[r];
 | 
			
		||||
    assert(check[0]== WorldRank);
 | 
			
		||||
    assert(check[1]== r);
 | 
			
		||||
    std::cerr<<"SHM "<<r<<" " <<VerticalShmBufs[r]<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  MPI_Barrier(VerticalComm);
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Map rank of leader on node in their in new world, to the
 | 
			
		||||
  // rank in this vertical plane's horizontal communicator
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////
 | 
			
		||||
  communicator_world = HorizontalComm;
 | 
			
		||||
  ShmComm            = VerticalComm;
 | 
			
		||||
  ShmCommBuf         = VerticalShmBufs[0];
 | 
			
		||||
  MPI_Comm_group (communicator_world, &WorldGroup); 
 | 
			
		||||
  
 | 
			
		||||
  ///////////////////////////////////////////////////////////
 | 
			
		||||
  // Start the slave data movers
 | 
			
		||||
  ///////////////////////////////////////////////////////////
 | 
			
		||||
  if ( VerticalRank != 0 ) {
 | 
			
		||||
    Slave indentured;
 | 
			
		||||
    indentured.Init( (SlaveState *) VerticalShmBufs[VerticalRank], VerticalComm, UniverseRank,VerticalRank);
 | 
			
		||||
    indentured.SemInitExcl();// init semaphore in shared memory
 | 
			
		||||
    MPI_Barrier(VerticalComm);
 | 
			
		||||
    MPI_Barrier(VerticalComm);
 | 
			
		||||
    indentured.EventLoop();
 | 
			
		||||
    assert(0);
 | 
			
		||||
  } else {
 | 
			
		||||
    Slaves.resize(VerticalSize);
 | 
			
		||||
    for(int i=1;i<VerticalSize;i++){
 | 
			
		||||
      Slaves[i].Init((SlaveState *)VerticalShmBufs[i],VerticalComm, UniverseRanks[HorizontalRank][i],i);
 | 
			
		||||
    }
 | 
			
		||||
    MPI_Barrier(VerticalComm);
 | 
			
		||||
    for(int i=1;i<VerticalSize;i++){
 | 
			
		||||
      Slaves[i].SemInit();// init semaphore in shared memory
 | 
			
		||||
    }
 | 
			
		||||
    MPI_Barrier(VerticalComm);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  ///////////////////////////////////////////////////////////
 | 
			
		||||
  // Verbose for now
 | 
			
		||||
  ///////////////////////////////////////////////////////////
 | 
			
		||||
  
 | 
			
		||||
  ShmSetup=1;
 | 
			
		||||
  
 | 
			
		||||
  if (UniverseRank == 0){
 | 
			
		||||
      
 | 
			
		||||
    std::cout<<GridLogMessage << "Grid MPI-3 configuration: detected ";
 | 
			
		||||
    std::cout<<UniverseSize   << " Ranks " ;
 | 
			
		||||
    std::cout<<HorizontalSize << " Nodes " ;
 | 
			
		||||
    std::cout<<VerticalSize   << " with ranks-per-node "<<std::endl;
 | 
			
		||||
    
 | 
			
		||||
    std::cout<<GridLogMessage << "Grid MPI-3 configuration: using one lead process per node " << std::endl;
 | 
			
		||||
    std::cout<<GridLogMessage << "Grid MPI-3 configuration: reduced communicator has size " << HorizontalSize << std::endl;
 | 
			
		||||
    
 | 
			
		||||
    for(int g=0;g<HorizontalSize;g++){
 | 
			
		||||
      std::cout<<GridLogMessage<<" Node "<<g<<" led by MPI rank "<< UniverseRanks[g][0]<<std::endl;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    for(int g=0;g<HorizontalSize;g++){
 | 
			
		||||
      std::cout<<GridLogMessage<<" { ";
 | 
			
		||||
      for(int s=0;s<VerticalSize;s++){
 | 
			
		||||
	std::cout<< UniverseRanks[g][s];
 | 
			
		||||
	if ( s<VerticalSize-1 ) {
 | 
			
		||||
	  std::cout<<",";
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
      std::cout<<" } "<<std::endl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
  ///////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // Map the communicator into communicator_world, and find the neighbour.
 | 
			
		||||
  // Cache the mappings; cache size is 1.
 | 
			
		||||
  ///////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
void MPIoffloadEngine::MapCommRankToWorldRank(int &hashtag, int & comm_world_peer,int tag, MPI_Comm comm,int rank) {
 | 
			
		||||
 | 
			
		||||
  if ( comm == HorizontalComm ) {
 | 
			
		||||
    comm_world_peer = rank;
 | 
			
		||||
    //    std::cout << " MapCommRankToWorldRank  horiz " <<rank<<"->"<<comm_world_peer<<std::endl;
 | 
			
		||||
  } else if ( comm == communicator_cached ) {
 | 
			
		||||
    comm_world_peer = UserCommunicatorToWorldRanks[rank];
 | 
			
		||||
    //    std::cout << " MapCommRankToWorldRank  cached " <<rank<<"->"<<comm_world_peer<<std::endl;
 | 
			
		||||
  } else { 
 | 
			
		||||
    
 | 
			
		||||
    int size;
 | 
			
		||||
 | 
			
		||||
    MPI_Comm_size(comm,&size);
 | 
			
		||||
 | 
			
		||||
    UserCommunicatorToWorldRanks.resize(size);
 | 
			
		||||
 | 
			
		||||
    std::vector<int> cached_ranks(size); 
 | 
			
		||||
 | 
			
		||||
    for(int r=0;r<size;r++) {
 | 
			
		||||
      cached_ranks[r]=r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    communicator_cached=comm;
 | 
			
		||||
    
 | 
			
		||||
    MPI_Comm_group(communicator_cached, &CachedGroup);
 | 
			
		||||
    
 | 
			
		||||
    MPI_Group_translate_ranks(CachedGroup,size,&cached_ranks[0],WorldGroup, &UserCommunicatorToWorldRanks[0]); 
 | 
			
		||||
    
 | 
			
		||||
    comm_world_peer = UserCommunicatorToWorldRanks[rank];
 | 
			
		||||
    //    std::cout << " MapCommRankToWorldRank  cache miss " <<rank<<"->"<<comm_world_peer<<std::endl;
 | 
			
		||||
    
 | 
			
		||||
    assert(comm_world_peer != MPI_UNDEFINED);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  assert( (tag & (~0xFFFFL)) ==0); 
 | 
			
		||||
  
 | 
			
		||||
  uint64_t icomm = (uint64_t)comm;
 | 
			
		||||
  int comm_hash = ((icomm>>0 )&0xFFFF)^((icomm>>16)&0xFFFF)
 | 
			
		||||
                ^ ((icomm>>32)&0xFFFF)^((icomm>>48)&0xFFFF);
 | 
			
		||||
  
 | 
			
		||||
  //  hashtag = (comm_hash<<15) | tag;      
 | 
			
		||||
  hashtag = tag;      
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void Slave::Init(SlaveState * _state,MPI_Comm _squadron,int _universe_rank,int _vertical_rank)
 | 
			
		||||
{
 | 
			
		||||
  squadron=_squadron;
 | 
			
		||||
  universe_rank=_universe_rank;
 | 
			
		||||
  vertical_rank=_vertical_rank;
 | 
			
		||||
  state   =_state;
 | 
			
		||||
  //  std::cout << "state "<<_state<<" comm "<<_squadron<<" universe_rank"<<universe_rank <<std::endl;
 | 
			
		||||
  state->head = state->tail = state->start = 0;
 | 
			
		||||
  base = (uint64_t)MPIoffloadEngine::VerticalShmBufs[0];
 | 
			
		||||
  int rank; MPI_Comm_rank(_squadron,&rank);
 | 
			
		||||
}
 | 
			
		||||
#define PERI_PLUS(A) ( (A+1)%pool )
 | 
			
		||||
int Slave::Event (void) {
 | 
			
		||||
 | 
			
		||||
  static int tail_last;
 | 
			
		||||
  static int head_last;
 | 
			
		||||
  static int start_last;
 | 
			
		||||
  int ierr;
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////////////////////
 | 
			
		||||
  // Try to advance the start pointers
 | 
			
		||||
  ////////////////////////////////////////////////////
 | 
			
		||||
  int s=state->start;
 | 
			
		||||
  if ( s != state->head ) {
 | 
			
		||||
    switch ( state->Descrs[s].command ) {
 | 
			
		||||
    case COMMAND_ISEND:
 | 
			
		||||
      /*
 | 
			
		||||
            std::cout<< " Send "<<s << " ptr "<< state<<" "<< state->Descrs[s].buf<< "["<<state->Descrs[s].bytes<<"]"
 | 
			
		||||
      	       << " to " << state->Descrs[s].rank<< " tag" << state->Descrs[s].tag
 | 
			
		||||
       << " Comm " << MPIoffloadEngine::communicator_universe<< " me " <<universe_rank<< std::endl;
 | 
			
		||||
      */
 | 
			
		||||
      ierr = MPI_Isend((void *)(state->Descrs[s].buf+base), 
 | 
			
		||||
		       state->Descrs[s].bytes, 
 | 
			
		||||
		       MPI_CHAR,
 | 
			
		||||
		       state->Descrs[s].rank,
 | 
			
		||||
		       state->Descrs[s].tag,
 | 
			
		||||
		       MPIoffloadEngine::communicator_universe,
 | 
			
		||||
		       (MPI_Request *)&state->Descrs[s].request);
 | 
			
		||||
      assert(ierr==0);
 | 
			
		||||
      state->start = PERI_PLUS(s);
 | 
			
		||||
      return 1;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case COMMAND_IRECV:
 | 
			
		||||
      /*
 | 
			
		||||
      std::cout<< " Recv "<<s << " ptr "<< state<<" "<< state->Descrs[s].buf<< "["<<state->Descrs[s].bytes<<"]"
 | 
			
		||||
	       << " from " << state->Descrs[s].rank<< " tag" << state->Descrs[s].tag
 | 
			
		||||
	       << " Comm " << MPIoffloadEngine::communicator_universe<< " me "<< universe_rank<< std::endl;
 | 
			
		||||
      */
 | 
			
		||||
      ierr=MPI_Irecv((void *)(state->Descrs[s].buf+base), 
 | 
			
		||||
		     state->Descrs[s].bytes, 
 | 
			
		||||
		     MPI_CHAR,
 | 
			
		||||
		     state->Descrs[s].rank,
 | 
			
		||||
		     state->Descrs[s].tag,
 | 
			
		||||
		     MPIoffloadEngine::communicator_universe,
 | 
			
		||||
		     (MPI_Request *)&state->Descrs[s].request);
 | 
			
		||||
 | 
			
		||||
      //      std::cout<< " Request is "<<state->Descrs[s].request<<std::endl;
 | 
			
		||||
      //      std::cout<< " Request0 is "<<state->Descrs[0].request<<std::endl;
 | 
			
		||||
      assert(ierr==0);
 | 
			
		||||
      state->start = PERI_PLUS(s);
 | 
			
		||||
      return 1;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case COMMAND_WAITALL:
 | 
			
		||||
 | 
			
		||||
      for(int t=state->tail;t!=s; t=PERI_PLUS(t) ){
 | 
			
		||||
	MPI_Wait((MPI_Request *)&state->Descrs[t].request,MPI_STATUS_IGNORE);
 | 
			
		||||
      };
 | 
			
		||||
      s=PERI_PLUS(s);
 | 
			
		||||
      state->start = s;
 | 
			
		||||
      state->tail  = s;
 | 
			
		||||
 | 
			
		||||
      WakeUpCompute();
 | 
			
		||||
 | 
			
		||||
      return 1;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  // External interaction with the queue
 | 
			
		||||
  //////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
  
 | 
			
		||||
uint64_t Slave::QueueCommand(int command,void *buf, int bytes, int tag, MPI_Comm comm,int commrank) 
 | 
			
		||||
{
 | 
			
		||||
  /////////////////////////////////////////
 | 
			
		||||
  // Spin; if FIFO is full until not full
 | 
			
		||||
  /////////////////////////////////////////
 | 
			
		||||
  int head =state->head;
 | 
			
		||||
  int next = PERI_PLUS(head);
 | 
			
		||||
    
 | 
			
		||||
  // Set up descriptor
 | 
			
		||||
  int worldrank;
 | 
			
		||||
  int hashtag;
 | 
			
		||||
  MPI_Comm    communicator;
 | 
			
		||||
  MPI_Request request;
 | 
			
		||||
  
 | 
			
		||||
  MPIoffloadEngine::MapCommRankToWorldRank(hashtag,worldrank,tag,comm,commrank);
 | 
			
		||||
 | 
			
		||||
  uint64_t relative= (uint64_t)buf - base;
 | 
			
		||||
  state->Descrs[head].buf    = relative;
 | 
			
		||||
  state->Descrs[head].bytes  = bytes;
 | 
			
		||||
  state->Descrs[head].rank   = MPIoffloadEngine::UniverseRanks[worldrank][vertical_rank];
 | 
			
		||||
  state->Descrs[head].tag    = hashtag;
 | 
			
		||||
  state->Descrs[head].command= command;
 | 
			
		||||
 | 
			
		||||
  /*  
 | 
			
		||||
  if ( command == COMMAND_ISEND ) { 
 | 
			
		||||
  std::cout << "QueueSend from "<< universe_rank <<" to commrank " << commrank 
 | 
			
		||||
            << " to worldrank " << worldrank <<std::endl;
 | 
			
		||||
  std::cout << " via VerticalRank "<< vertical_rank <<" to universerank " << MPIoffloadEngine::UniverseRanks[worldrank][vertical_rank]<<std::endl;
 | 
			
		||||
  std::cout << " QueueCommand "<<buf<<"["<<bytes<<"]" << std::endl;
 | 
			
		||||
  } 
 | 
			
		||||
  if ( command == COMMAND_IRECV ) { 
 | 
			
		||||
  std::cout << "QueueRecv on "<< universe_rank <<" from commrank " << commrank 
 | 
			
		||||
            << " from worldrank " << worldrank <<std::endl;
 | 
			
		||||
  std::cout << " via VerticalRank "<< vertical_rank <<" from universerank " << MPIoffloadEngine::UniverseRanks[worldrank][vertical_rank]<<std::endl;
 | 
			
		||||
  std::cout << " QueueSend "<<buf<<"["<<bytes<<"]" << std::endl;
 | 
			
		||||
  } 
 | 
			
		||||
  */
 | 
			
		||||
  // Block until FIFO has space
 | 
			
		||||
  while( state->tail==next );
 | 
			
		||||
 | 
			
		||||
  // Msync on weak order architectures
 | 
			
		||||
  // Advance pointer
 | 
			
		||||
  state->head = next;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Info that is setup once and indept of cartesian layout
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
MPI_Comm CartesianCommunicator::communicator_world;
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::Init(int *argc, char ***argv) 
 | 
			
		||||
{
 | 
			
		||||
  int flag;
 | 
			
		||||
  MPI_Initialized(&flag); // needed to coexist with other libs apparently
 | 
			
		||||
  if ( !flag ) {
 | 
			
		||||
    MPI_Init(argc,argv);
 | 
			
		||||
  }
 | 
			
		||||
  communicator_world = MPI_COMM_WORLD;
 | 
			
		||||
  MPI_Comm ShmComm;
 | 
			
		||||
  MPIoffloadEngine::CommunicatorInit (communicator_world,ShmComm,ShmCommBuf);
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::ShiftedRanks(int dim,int shift,int &source,int &dest)
 | 
			
		||||
{
 | 
			
		||||
  int ierr=MPI_Cart_shift(communicator,dim,shift,&source,&dest);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
int CartesianCommunicator::RankFromProcessorCoor(std::vector<int> &coor)
 | 
			
		||||
{
 | 
			
		||||
  int rank;
 | 
			
		||||
  int ierr=MPI_Cart_rank  (communicator, &coor[0], &rank);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
  return rank;
 | 
			
		||||
}
 | 
			
		||||
void  CartesianCommunicator::ProcessorCoorFromRank(int rank, std::vector<int> &coor)
 | 
			
		||||
{
 | 
			
		||||
  coor.resize(_ndimension);
 | 
			
		||||
  int ierr=MPI_Cart_coords  (communicator, rank, _ndimension,&coor[0]);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors)
 | 
			
		||||
{ 
 | 
			
		||||
  _ndimension = processors.size();
 | 
			
		||||
  std::vector<int> periodic(_ndimension,1);
 | 
			
		||||
 | 
			
		||||
  _Nprocessors=1;
 | 
			
		||||
  _processors = processors;
 | 
			
		||||
 | 
			
		||||
  for(int i=0;i<_ndimension;i++){
 | 
			
		||||
    _Nprocessors*=_processors[i];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int Size; 
 | 
			
		||||
  MPI_Comm_size(communicator_world,&Size);
 | 
			
		||||
  assert(Size==_Nprocessors);
 | 
			
		||||
 | 
			
		||||
  _processor_coor.resize(_ndimension);
 | 
			
		||||
  MPI_Cart_create(communicator_world, _ndimension,&_processors[0],&periodic[0],1,&communicator);
 | 
			
		||||
  MPI_Comm_rank  (communicator,&_processor);
 | 
			
		||||
  MPI_Cart_coords(communicator,_processor,_ndimension,&_processor_coor[0]);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::GlobalSum(uint32_t &u){
 | 
			
		||||
  int ierr=MPI_Allreduce(MPI_IN_PLACE,&u,1,MPI_UINT32_T,MPI_SUM,communicator);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::GlobalSum(uint64_t &u){
 | 
			
		||||
  int ierr=MPI_Allreduce(MPI_IN_PLACE,&u,1,MPI_UINT64_T,MPI_SUM,communicator);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::GlobalSum(float &f){
 | 
			
		||||
  int ierr=MPI_Allreduce(MPI_IN_PLACE,&f,1,MPI_FLOAT,MPI_SUM,communicator);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::GlobalSumVector(float *f,int N)
 | 
			
		||||
{
 | 
			
		||||
  int ierr=MPI_Allreduce(MPI_IN_PLACE,f,N,MPI_FLOAT,MPI_SUM,communicator);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::GlobalSum(double &d)
 | 
			
		||||
{
 | 
			
		||||
  int ierr = MPI_Allreduce(MPI_IN_PLACE,&d,1,MPI_DOUBLE,MPI_SUM,communicator);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::GlobalSumVector(double *d,int N)
 | 
			
		||||
{
 | 
			
		||||
  int ierr = MPI_Allreduce(MPI_IN_PLACE,d,N,MPI_DOUBLE,MPI_SUM,communicator);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Basic Halo comms primitive
 | 
			
		||||
void CartesianCommunicator::SendToRecvFrom(void *xmit,
 | 
			
		||||
					   int dest,
 | 
			
		||||
					   void *recv,
 | 
			
		||||
					   int from,
 | 
			
		||||
					   int bytes)
 | 
			
		||||
{
 | 
			
		||||
  std::vector<CommsRequest_t> reqs(0);
 | 
			
		||||
  SendToRecvFromBegin(reqs,xmit,dest,recv,from,bytes);
 | 
			
		||||
  SendToRecvFromComplete(reqs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::SendRecvPacket(void *xmit,
 | 
			
		||||
					   void *recv,
 | 
			
		||||
					   int sender,
 | 
			
		||||
					   int receiver,
 | 
			
		||||
					   int bytes)
 | 
			
		||||
{
 | 
			
		||||
  MPI_Status stat;
 | 
			
		||||
  assert(sender != receiver);
 | 
			
		||||
  int tag = sender;
 | 
			
		||||
  if ( _processor == sender ) {
 | 
			
		||||
    MPI_Send(xmit, bytes, MPI_CHAR,receiver,tag,communicator);
 | 
			
		||||
  }
 | 
			
		||||
  if ( _processor == receiver ) { 
 | 
			
		||||
    MPI_Recv(recv, bytes, MPI_CHAR,sender,tag,communicator,&stat);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Basic Halo comms primitive
 | 
			
		||||
void CartesianCommunicator::SendToRecvFromBegin(std::vector<CommsRequest_t> &list,
 | 
			
		||||
						void *xmit,
 | 
			
		||||
						int dest,
 | 
			
		||||
						void *recv,
 | 
			
		||||
						int from,
 | 
			
		||||
						int bytes)
 | 
			
		||||
{
 | 
			
		||||
  MPI_Request xrq;
 | 
			
		||||
  MPI_Request rrq;
 | 
			
		||||
  int rank = _processor;
 | 
			
		||||
  int ierr;
 | 
			
		||||
  ierr =MPI_Isend(xmit, bytes, MPI_CHAR,dest,_processor,communicator,&xrq);
 | 
			
		||||
  ierr|=MPI_Irecv(recv, bytes, MPI_CHAR,from,from,communicator,&rrq);
 | 
			
		||||
  
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
 | 
			
		||||
  list.push_back(xrq);
 | 
			
		||||
  list.push_back(rrq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::StencilSendToRecvFromBegin(std::vector<CommsRequest_t> &list,
 | 
			
		||||
						       void *xmit,
 | 
			
		||||
						       int dest,
 | 
			
		||||
						       void *recv,
 | 
			
		||||
						       int from,
 | 
			
		||||
						       int bytes)
 | 
			
		||||
{
 | 
			
		||||
  uint64_t xmit_i = (uint64_t) xmit;
 | 
			
		||||
  uint64_t recv_i = (uint64_t) recv;
 | 
			
		||||
  uint64_t shm    = (uint64_t) ShmCommBuf;
 | 
			
		||||
  // assert xmit and recv lie in shared memory region
 | 
			
		||||
  assert( (xmit_i >= shm) && (xmit_i+bytes <= shm+MAX_MPI_SHM_BYTES) );
 | 
			
		||||
  assert( (recv_i >= shm) && (recv_i+bytes <= shm+MAX_MPI_SHM_BYTES) );
 | 
			
		||||
  assert(from!=_processor);
 | 
			
		||||
  assert(dest!=_processor);
 | 
			
		||||
  MPIoffloadEngine::QueueMultiplexedSend(xmit,bytes,_processor,communicator,dest);
 | 
			
		||||
  MPIoffloadEngine::QueueMultiplexedRecv(recv,bytes,from,communicator,from);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::StencilSendToRecvFromComplete(std::vector<CommsRequest_t> &list)
 | 
			
		||||
{
 | 
			
		||||
  MPIoffloadEngine::WaitAll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::StencilBarrier(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::SendToRecvFromComplete(std::vector<CommsRequest_t> &list)
 | 
			
		||||
{
 | 
			
		||||
  int nreq=list.size();
 | 
			
		||||
  std::vector<MPI_Status> status(nreq);
 | 
			
		||||
  int ierr = MPI_Waitall(nreq,&list[0],&status[0]);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::Barrier(void)
 | 
			
		||||
{
 | 
			
		||||
  int ierr = MPI_Barrier(communicator);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::Broadcast(int root,void* data, int bytes)
 | 
			
		||||
{
 | 
			
		||||
  int ierr=MPI_Bcast(data,
 | 
			
		||||
		     bytes,
 | 
			
		||||
		     MPI_BYTE,
 | 
			
		||||
		     root,
 | 
			
		||||
		     communicator);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes)
 | 
			
		||||
{
 | 
			
		||||
  int ierr= MPI_Bcast(data,
 | 
			
		||||
		      bytes,
 | 
			
		||||
		      MPI_BYTE,
 | 
			
		||||
		      root,
 | 
			
		||||
		      communicator_world);
 | 
			
		||||
  assert(ierr==0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *CartesianCommunicator::ShmBufferSelf(void) { return ShmCommBuf; }
 | 
			
		||||
 | 
			
		||||
void *CartesianCommunicator::ShmBuffer(int rank) {
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
void *CartesianCommunicator::ShmBufferTranslate(int rank,void * local_p) { 
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -34,13 +34,6 @@ namespace Grid {
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::Init(int *argc, char *** arv)
 | 
			
		||||
{
 | 
			
		||||
  WorldRank = 0;
 | 
			
		||||
  WorldSize = 1;
 | 
			
		||||
  ShmRank=0;
 | 
			
		||||
  ShmSize=1;
 | 
			
		||||
  GroupRank=WorldRank;
 | 
			
		||||
  GroupSize=WorldSize;
 | 
			
		||||
  Slave    =0;
 | 
			
		||||
  ShmInitGeneric();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -94,11 +87,13 @@ void CartesianCommunicator::SendToRecvFromBegin(std::vector<CommsRequest_t> &lis
 | 
			
		||||
{
 | 
			
		||||
  assert(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::SendToRecvFromComplete(std::vector<CommsRequest_t> &list)
 | 
			
		||||
{
 | 
			
		||||
  assert(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int  CartesianCommunicator::RankWorld(void){return 0;}
 | 
			
		||||
void CartesianCommunicator::Barrier(void){}
 | 
			
		||||
void CartesianCommunicator::Broadcast(int root,void* data, int bytes) {}
 | 
			
		||||
void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes) { }
 | 
			
		||||
 
 | 
			
		||||
@@ -50,11 +50,16 @@ typedef struct HandShake_t {
 | 
			
		||||
  uint64_t seq_remote;
 | 
			
		||||
} HandShake;
 | 
			
		||||
 | 
			
		||||
std::array<long,_SHMEM_REDUCE_SYNC_SIZE> make_psync_init(void) {
 | 
			
		||||
  array<long,_SHMEM_REDUCE_SYNC_SIZE> ret;
 | 
			
		||||
  ret.fill(SHMEM_SYNC_VALUE);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync_init = make_psync_init();
 | 
			
		||||
 | 
			
		||||
static Vector< HandShake > XConnections;
 | 
			
		||||
static Vector< HandShake > RConnections;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void CartesianCommunicator::Init(int *argc, char ***argv) {
 | 
			
		||||
  shmem_init();
 | 
			
		||||
  XConnections.resize(shmem_n_pes());
 | 
			
		||||
@@ -65,13 +70,6 @@ void CartesianCommunicator::Init(int *argc, char ***argv) {
 | 
			
		||||
    RConnections[pe].seq_local = 0;
 | 
			
		||||
    RConnections[pe].seq_remote= 0;
 | 
			
		||||
  }
 | 
			
		||||
  WorldSize = shmem_n_pes();
 | 
			
		||||
  WorldRank = shmem_my_pe();
 | 
			
		||||
  ShmRank=0;
 | 
			
		||||
  ShmSize=1;
 | 
			
		||||
  GroupRank=WorldRank;
 | 
			
		||||
  GroupSize=WorldSize;
 | 
			
		||||
  Slave    =0;
 | 
			
		||||
  shmem_barrier_all();
 | 
			
		||||
  ShmInitGeneric();
 | 
			
		||||
}
 | 
			
		||||
@@ -103,7 +101,7 @@ void CartesianCommunicator::GlobalSum(uint32_t &u){
 | 
			
		||||
  static long long source ;
 | 
			
		||||
  static long long dest   ;
 | 
			
		||||
  static long long llwrk[_SHMEM_REDUCE_MIN_WRKDATA_SIZE];
 | 
			
		||||
  static long      psync[_SHMEM_REDUCE_SYNC_SIZE];
 | 
			
		||||
  static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync =  psync_init;
 | 
			
		||||
 | 
			
		||||
  //  int nreduce=1;
 | 
			
		||||
  //  int pestart=0;
 | 
			
		||||
@@ -119,7 +117,7 @@ void CartesianCommunicator::GlobalSum(uint64_t &u){
 | 
			
		||||
  static long long source ;
 | 
			
		||||
  static long long dest   ;
 | 
			
		||||
  static long long llwrk[_SHMEM_REDUCE_MIN_WRKDATA_SIZE];
 | 
			
		||||
  static long      psync[_SHMEM_REDUCE_SYNC_SIZE];
 | 
			
		||||
  static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync =  psync_init;
 | 
			
		||||
 | 
			
		||||
  //  int nreduce=1;
 | 
			
		||||
  //  int pestart=0;
 | 
			
		||||
@@ -135,7 +133,7 @@ void CartesianCommunicator::GlobalSum(float &f){
 | 
			
		||||
  static float source ;
 | 
			
		||||
  static float dest   ;
 | 
			
		||||
  static float llwrk[_SHMEM_REDUCE_MIN_WRKDATA_SIZE];
 | 
			
		||||
  static long  psync[_SHMEM_REDUCE_SYNC_SIZE];
 | 
			
		||||
  static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync =  psync_init;
 | 
			
		||||
 | 
			
		||||
  source = f;
 | 
			
		||||
  dest   =0.0;
 | 
			
		||||
@@ -147,7 +145,7 @@ void CartesianCommunicator::GlobalSumVector(float *f,int N)
 | 
			
		||||
  static float source ;
 | 
			
		||||
  static float dest   = 0 ;
 | 
			
		||||
  static float llwrk[_SHMEM_REDUCE_MIN_WRKDATA_SIZE];
 | 
			
		||||
  static long  psync[_SHMEM_REDUCE_SYNC_SIZE];
 | 
			
		||||
  static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync =  psync_init;
 | 
			
		||||
 | 
			
		||||
  if ( shmem_addr_accessible(f,_processor)  ){
 | 
			
		||||
    shmem_float_sum_to_all(f,f,N,0,0,_Nprocessors,llwrk,psync);
 | 
			
		||||
@@ -166,7 +164,7 @@ void CartesianCommunicator::GlobalSum(double &d)
 | 
			
		||||
  static double source;
 | 
			
		||||
  static double dest  ;
 | 
			
		||||
  static double llwrk[_SHMEM_REDUCE_MIN_WRKDATA_SIZE];
 | 
			
		||||
  static long  psync[_SHMEM_REDUCE_SYNC_SIZE];
 | 
			
		||||
  static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync =  psync_init;
 | 
			
		||||
 | 
			
		||||
  source = d;
 | 
			
		||||
  dest   = 0;
 | 
			
		||||
@@ -178,7 +176,8 @@ void CartesianCommunicator::GlobalSumVector(double *d,int N)
 | 
			
		||||
  static double source ;
 | 
			
		||||
  static double dest   ;
 | 
			
		||||
  static double llwrk[_SHMEM_REDUCE_MIN_WRKDATA_SIZE];
 | 
			
		||||
  static long  psync[_SHMEM_REDUCE_SYNC_SIZE];
 | 
			
		||||
  static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync =  psync_init;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if ( shmem_addr_accessible(d,_processor)  ){
 | 
			
		||||
    shmem_double_sum_to_all(d,d,N,0,0,_Nprocessors,llwrk,psync);
 | 
			
		||||
@@ -295,7 +294,7 @@ void CartesianCommunicator::Barrier(void)
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::Broadcast(int root,void* data, int bytes)
 | 
			
		||||
{
 | 
			
		||||
  static long  psync[_SHMEM_REDUCE_SYNC_SIZE];
 | 
			
		||||
  static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync =  psync_init;
 | 
			
		||||
  static uint32_t word;
 | 
			
		||||
  uint32_t *array = (uint32_t *) data;
 | 
			
		||||
  assert( (bytes % 4)==0);
 | 
			
		||||
@@ -318,7 +317,7 @@ void CartesianCommunicator::Broadcast(int root,void* data, int bytes)
 | 
			
		||||
}
 | 
			
		||||
void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes)
 | 
			
		||||
{
 | 
			
		||||
  static long  psync[_SHMEM_REDUCE_SYNC_SIZE];
 | 
			
		||||
  static std::array<long,_SHMEM_REDUCE_SYNC_SIZE> psync =  psync_init;
 | 
			
		||||
  static uint32_t word;
 | 
			
		||||
  uint32_t *array = (uint32_t *) data;
 | 
			
		||||
  assert( (bytes % 4)==0);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										412
									
								
								lib/fftw/fftw3.h
									
									
									
									
									
								
							
							
						
						
									
										412
									
								
								lib/fftw/fftw3.h
									
									
									
									
									
								
							@@ -1,412 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2003, 2007-14 Matteo Frigo
 | 
			
		||||
 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
 | 
			
		||||
 *
 | 
			
		||||
 * The following statement of license applies *only* to this header file,
 | 
			
		||||
 * and *not* to the other files distributed with FFTW or derived therefrom:
 | 
			
		||||
 * 
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 | 
			
		||||
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 | 
			
		||||
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 | 
			
		||||
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | 
			
		||||
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/***************************** NOTE TO USERS *********************************
 | 
			
		||||
 *
 | 
			
		||||
 *                 THIS IS A HEADER FILE, NOT A MANUAL
 | 
			
		||||
 *
 | 
			
		||||
 *    If you want to know how to use FFTW, please read the manual,
 | 
			
		||||
 *    online at http://www.fftw.org/doc/ and also included with FFTW.
 | 
			
		||||
 *    For a quick start, see the manual's tutorial section.
 | 
			
		||||
 *
 | 
			
		||||
 *   (Reading header files to learn how to use a library is a habit
 | 
			
		||||
 *    stemming from code lacking a proper manual.  Arguably, it's a
 | 
			
		||||
 *    *bad* habit in most cases, because header files can contain
 | 
			
		||||
 *    interfaces that are not part of the public, stable API.)
 | 
			
		||||
 *
 | 
			
		||||
 ****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef FFTW3_H
 | 
			
		||||
#define FFTW3_H
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#endif /* __cplusplus */
 | 
			
		||||
 | 
			
		||||
/* If <complex.h> is included, use the C99 complex type.  Otherwise
 | 
			
		||||
   define a type bit-compatible with C99 complex */
 | 
			
		||||
#if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
 | 
			
		||||
#  define FFTW_DEFINE_COMPLEX(R, C) typedef R _Complex C
 | 
			
		||||
#else
 | 
			
		||||
#  define FFTW_DEFINE_COMPLEX(R, C) typedef R C[2]
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define FFTW_CONCAT(prefix, name) prefix ## name
 | 
			
		||||
#define FFTW_MANGLE_DOUBLE(name) FFTW_CONCAT(fftw_, name)
 | 
			
		||||
#define FFTW_MANGLE_FLOAT(name) FFTW_CONCAT(fftwf_, name)
 | 
			
		||||
#define FFTW_MANGLE_LONG_DOUBLE(name) FFTW_CONCAT(fftwl_, name)
 | 
			
		||||
#define FFTW_MANGLE_QUAD(name) FFTW_CONCAT(fftwq_, name)
 | 
			
		||||
 | 
			
		||||
/* IMPORTANT: for Windows compilers, you should add a line
 | 
			
		||||
        #define FFTW_DLL
 | 
			
		||||
   here and in kernel/ifftw.h if you are compiling/using FFTW as a
 | 
			
		||||
   DLL, in order to do the proper importing/exporting, or
 | 
			
		||||
   alternatively compile with -DFFTW_DLL or the equivalent
 | 
			
		||||
   command-line flag.  This is not necessary under MinGW/Cygwin, where
 | 
			
		||||
   libtool does the imports/exports automatically. */
 | 
			
		||||
#if defined(FFTW_DLL) && (defined(_WIN32) || defined(__WIN32__))
 | 
			
		||||
   /* annoying Windows syntax for shared-library declarations */
 | 
			
		||||
#  if defined(COMPILING_FFTW) /* defined in api.h when compiling FFTW */
 | 
			
		||||
#    define FFTW_EXTERN extern __declspec(dllexport) 
 | 
			
		||||
#  else /* user is calling FFTW; import symbol */
 | 
			
		||||
#    define FFTW_EXTERN extern __declspec(dllimport) 
 | 
			
		||||
#  endif
 | 
			
		||||
#else
 | 
			
		||||
#  define FFTW_EXTERN extern
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum fftw_r2r_kind_do_not_use_me {
 | 
			
		||||
     FFTW_R2HC=0, FFTW_HC2R=1, FFTW_DHT=2,
 | 
			
		||||
     FFTW_REDFT00=3, FFTW_REDFT01=4, FFTW_REDFT10=5, FFTW_REDFT11=6,
 | 
			
		||||
     FFTW_RODFT00=7, FFTW_RODFT01=8, FFTW_RODFT10=9, FFTW_RODFT11=10
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fftw_iodim_do_not_use_me {
 | 
			
		||||
     int n;                     /* dimension size */
 | 
			
		||||
     int is;			/* input stride */
 | 
			
		||||
     int os;			/* output stride */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#include <stddef.h> /* for ptrdiff_t */
 | 
			
		||||
struct fftw_iodim64_do_not_use_me {
 | 
			
		||||
     ptrdiff_t n;                     /* dimension size */
 | 
			
		||||
     ptrdiff_t is;			/* input stride */
 | 
			
		||||
     ptrdiff_t os;			/* output stride */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef void (*fftw_write_char_func_do_not_use_me)(char c, void *);
 | 
			
		||||
typedef int (*fftw_read_char_func_do_not_use_me)(void *);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  huge second-order macro that defines prototypes for all API
 | 
			
		||||
  functions.  We expand this macro for each supported precision
 | 
			
		||||
 
 | 
			
		||||
  X: name-mangling macro
 | 
			
		||||
  R: real data type
 | 
			
		||||
  C: complex data type
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define FFTW_DEFINE_API(X, R, C)					   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_DEFINE_COMPLEX(R, C);						   \
 | 
			
		||||
									   \
 | 
			
		||||
typedef struct X(plan_s) *X(plan);					   \
 | 
			
		||||
									   \
 | 
			
		||||
typedef struct fftw_iodim_do_not_use_me X(iodim);			   \
 | 
			
		||||
typedef struct fftw_iodim64_do_not_use_me X(iodim64);			   \
 | 
			
		||||
									   \
 | 
			
		||||
typedef enum fftw_r2r_kind_do_not_use_me X(r2r_kind);			   \
 | 
			
		||||
									   \
 | 
			
		||||
typedef fftw_write_char_func_do_not_use_me X(write_char_func);		   \
 | 
			
		||||
typedef fftw_read_char_func_do_not_use_me X(read_char_func);		   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(execute)(const X(plan) p);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft)(int rank, const int *n,			   \
 | 
			
		||||
		    C *in, C *out, int sign, unsigned flags);		   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_1d)(int n, C *in, C *out, int sign,	   \
 | 
			
		||||
		       unsigned flags);					   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_2d)(int n0, int n1,			   \
 | 
			
		||||
		       C *in, C *out, int sign, unsigned flags);	   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_3d)(int n0, int n1, int n2,		   \
 | 
			
		||||
		       C *in, C *out, int sign, unsigned flags);	   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_many_dft)(int rank, const int *n,		   \
 | 
			
		||||
                         int howmany,					   \
 | 
			
		||||
                         C *in, const int *inembed,			   \
 | 
			
		||||
                         int istride, int idist,			   \
 | 
			
		||||
                         C *out, const int *onembed,			   \
 | 
			
		||||
                         int ostride, int odist,			   \
 | 
			
		||||
                         int sign, unsigned flags);			   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru_dft)(int rank, const X(iodim) *dims,	   \
 | 
			
		||||
			 int howmany_rank,				   \
 | 
			
		||||
			 const X(iodim) *howmany_dims,			   \
 | 
			
		||||
			 C *in, C *out,					   \
 | 
			
		||||
			 int sign, unsigned flags);			   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru_split_dft)(int rank, const X(iodim) *dims, \
 | 
			
		||||
			 int howmany_rank,				   \
 | 
			
		||||
			 const X(iodim) *howmany_dims,			   \
 | 
			
		||||
			 R *ri, R *ii, R *ro, R *io,			   \
 | 
			
		||||
			 unsigned flags);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru64_dft)(int rank,			   \
 | 
			
		||||
                         const X(iodim64) *dims,			   \
 | 
			
		||||
			 int howmany_rank,				   \
 | 
			
		||||
			 const X(iodim64) *howmany_dims,		   \
 | 
			
		||||
			 C *in, C *out,					   \
 | 
			
		||||
			 int sign, unsigned flags);			   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru64_split_dft)(int rank,			   \
 | 
			
		||||
                         const X(iodim64) *dims,			   \
 | 
			
		||||
			 int howmany_rank,				   \
 | 
			
		||||
			 const X(iodim64) *howmany_dims,		   \
 | 
			
		||||
			 R *ri, R *ii, R *ro, R *io,			   \
 | 
			
		||||
			 unsigned flags);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(execute_dft)(const X(plan) p, C *in, C *out);	   \
 | 
			
		||||
FFTW_EXTERN void X(execute_split_dft)(const X(plan) p, R *ri, R *ii,	   \
 | 
			
		||||
                                      R *ro, R *io);			   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_many_dft_r2c)(int rank, const int *n,	   \
 | 
			
		||||
                             int howmany,				   \
 | 
			
		||||
                             R *in, const int *inembed,			   \
 | 
			
		||||
                             int istride, int idist,			   \
 | 
			
		||||
                             C *out, const int *onembed,		   \
 | 
			
		||||
                             int ostride, int odist,			   \
 | 
			
		||||
                             unsigned flags);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_r2c)(int rank, const int *n,		   \
 | 
			
		||||
                        R *in, C *out, unsigned flags);			   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_r2c_1d)(int n,R *in,C *out,unsigned flags); \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_r2c_2d)(int n0, int n1,			   \
 | 
			
		||||
			   R *in, C *out, unsigned flags);		   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_r2c_3d)(int n0, int n1,			   \
 | 
			
		||||
			   int n2,					   \
 | 
			
		||||
			   R *in, C *out, unsigned flags);		   \
 | 
			
		||||
									   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_many_dft_c2r)(int rank, const int *n,	   \
 | 
			
		||||
			     int howmany,				   \
 | 
			
		||||
			     C *in, const int *inembed,			   \
 | 
			
		||||
			     int istride, int idist,			   \
 | 
			
		||||
			     R *out, const int *onembed,		   \
 | 
			
		||||
			     int ostride, int odist,			   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_c2r)(int rank, const int *n,		   \
 | 
			
		||||
                        C *in, R *out, unsigned flags);			   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_c2r_1d)(int n,C *in,R *out,unsigned flags); \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_c2r_2d)(int n0, int n1,			   \
 | 
			
		||||
			   C *in, R *out, unsigned flags);		   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_dft_c2r_3d)(int n0, int n1,			   \
 | 
			
		||||
			   int n2,					   \
 | 
			
		||||
			   C *in, R *out, unsigned flags);		   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru_dft_r2c)(int rank, const X(iodim) *dims,   \
 | 
			
		||||
			     int howmany_rank,				   \
 | 
			
		||||
			     const X(iodim) *howmany_dims,		   \
 | 
			
		||||
			     R *in, C *out,				   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru_dft_c2r)(int rank, const X(iodim) *dims,   \
 | 
			
		||||
			     int howmany_rank,				   \
 | 
			
		||||
			     const X(iodim) *howmany_dims,		   \
 | 
			
		||||
			     C *in, R *out,				   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru_split_dft_r2c)(				   \
 | 
			
		||||
                             int rank, const X(iodim) *dims,		   \
 | 
			
		||||
			     int howmany_rank,				   \
 | 
			
		||||
			     const X(iodim) *howmany_dims,		   \
 | 
			
		||||
			     R *in, R *ro, R *io,			   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru_split_dft_c2r)(				   \
 | 
			
		||||
                             int rank, const X(iodim) *dims,		   \
 | 
			
		||||
			     int howmany_rank,				   \
 | 
			
		||||
			     const X(iodim) *howmany_dims,		   \
 | 
			
		||||
			     R *ri, R *ii, R *out,			   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru64_dft_r2c)(int rank,			   \
 | 
			
		||||
                             const X(iodim64) *dims,			   \
 | 
			
		||||
			     int howmany_rank,				   \
 | 
			
		||||
			     const X(iodim64) *howmany_dims,		   \
 | 
			
		||||
			     R *in, C *out,				   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru64_dft_c2r)(int rank,			   \
 | 
			
		||||
                             const X(iodim64) *dims,			   \
 | 
			
		||||
			     int howmany_rank,				   \
 | 
			
		||||
			     const X(iodim64) *howmany_dims,		   \
 | 
			
		||||
			     C *in, R *out,				   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru64_split_dft_r2c)(			   \
 | 
			
		||||
                             int rank, const X(iodim64) *dims,		   \
 | 
			
		||||
			     int howmany_rank,				   \
 | 
			
		||||
			     const X(iodim64) *howmany_dims,		   \
 | 
			
		||||
			     R *in, R *ro, R *io,			   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru64_split_dft_c2r)(			   \
 | 
			
		||||
                             int rank, const X(iodim64) *dims,		   \
 | 
			
		||||
			     int howmany_rank,				   \
 | 
			
		||||
			     const X(iodim64) *howmany_dims,		   \
 | 
			
		||||
			     R *ri, R *ii, R *out,			   \
 | 
			
		||||
			     unsigned flags);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(execute_dft_r2c)(const X(plan) p, R *in, C *out);	   \
 | 
			
		||||
FFTW_EXTERN void X(execute_dft_c2r)(const X(plan) p, C *in, R *out);	   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(execute_split_dft_r2c)(const X(plan) p,		   \
 | 
			
		||||
                                          R *in, R *ro, R *io);		   \
 | 
			
		||||
FFTW_EXTERN void X(execute_split_dft_c2r)(const X(plan) p,		   \
 | 
			
		||||
                                          R *ri, R *ii, R *out);	   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_many_r2r)(int rank, const int *n,		   \
 | 
			
		||||
                         int howmany,					   \
 | 
			
		||||
                         R *in, const int *inembed,			   \
 | 
			
		||||
                         int istride, int idist,			   \
 | 
			
		||||
                         R *out, const int *onembed,			   \
 | 
			
		||||
                         int ostride, int odist,			   \
 | 
			
		||||
                         const X(r2r_kind) *kind, unsigned flags);	   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_r2r)(int rank, const int *n, R *in, R *out,	   \
 | 
			
		||||
                    const X(r2r_kind) *kind, unsigned flags);		   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_r2r_1d)(int n, R *in, R *out,		   \
 | 
			
		||||
                       X(r2r_kind) kind, unsigned flags);		   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_r2r_2d)(int n0, int n1, R *in, R *out,	   \
 | 
			
		||||
                       X(r2r_kind) kind0, X(r2r_kind) kind1,		   \
 | 
			
		||||
                       unsigned flags);					   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_r2r_3d)(int n0, int n1, int n2,		   \
 | 
			
		||||
                       R *in, R *out, X(r2r_kind) kind0,		   \
 | 
			
		||||
                       X(r2r_kind) kind1, X(r2r_kind) kind2,		   \
 | 
			
		||||
                       unsigned flags);					   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru_r2r)(int rank, const X(iodim) *dims,	   \
 | 
			
		||||
                         int howmany_rank,				   \
 | 
			
		||||
                         const X(iodim) *howmany_dims,			   \
 | 
			
		||||
                         R *in, R *out,					   \
 | 
			
		||||
                         const X(r2r_kind) *kind, unsigned flags);	   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN X(plan) X(plan_guru64_r2r)(int rank, const X(iodim64) *dims,   \
 | 
			
		||||
                         int howmany_rank,				   \
 | 
			
		||||
                         const X(iodim64) *howmany_dims,		   \
 | 
			
		||||
                         R *in, R *out,					   \
 | 
			
		||||
                         const X(r2r_kind) *kind, unsigned flags);	   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(execute_r2r)(const X(plan) p, R *in, R *out);	   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(destroy_plan)(X(plan) p);				   \
 | 
			
		||||
FFTW_EXTERN void X(forget_wisdom)(void);				   \
 | 
			
		||||
FFTW_EXTERN void X(cleanup)(void);					   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(set_timelimit)(double t);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(plan_with_nthreads)(int nthreads);			   \
 | 
			
		||||
FFTW_EXTERN int X(init_threads)(void);					   \
 | 
			
		||||
FFTW_EXTERN void X(cleanup_threads)(void);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN int X(export_wisdom_to_filename)(const char *filename);	   \
 | 
			
		||||
FFTW_EXTERN void X(export_wisdom_to_file)(FILE *output_file);		   \
 | 
			
		||||
FFTW_EXTERN char *X(export_wisdom_to_string)(void);			   \
 | 
			
		||||
FFTW_EXTERN void X(export_wisdom)(X(write_char_func) write_char,   	   \
 | 
			
		||||
                                  void *data);				   \
 | 
			
		||||
FFTW_EXTERN int X(import_system_wisdom)(void);				   \
 | 
			
		||||
FFTW_EXTERN int X(import_wisdom_from_filename)(const char *filename);	   \
 | 
			
		||||
FFTW_EXTERN int X(import_wisdom_from_file)(FILE *input_file);		   \
 | 
			
		||||
FFTW_EXTERN int X(import_wisdom_from_string)(const char *input_string);	   \
 | 
			
		||||
FFTW_EXTERN int X(import_wisdom)(X(read_char_func) read_char, void *data); \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(fprint_plan)(const X(plan) p, FILE *output_file);	   \
 | 
			
		||||
FFTW_EXTERN void X(print_plan)(const X(plan) p);			   \
 | 
			
		||||
FFTW_EXTERN char *X(sprint_plan)(const X(plan) p);			   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void *X(malloc)(size_t n);					   \
 | 
			
		||||
FFTW_EXTERN R *X(alloc_real)(size_t n);					   \
 | 
			
		||||
FFTW_EXTERN C *X(alloc_complex)(size_t n);				   \
 | 
			
		||||
FFTW_EXTERN void X(free)(void *p);					   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN void X(flops)(const X(plan) p,				   \
 | 
			
		||||
                          double *add, double *mul, double *fmas);	   \
 | 
			
		||||
FFTW_EXTERN double X(estimate_cost)(const X(plan) p);			   \
 | 
			
		||||
FFTW_EXTERN double X(cost)(const X(plan) p);				   \
 | 
			
		||||
									   \
 | 
			
		||||
FFTW_EXTERN int X(alignment_of)(R *p);                                     \
 | 
			
		||||
FFTW_EXTERN const char X(version)[];                                       \
 | 
			
		||||
FFTW_EXTERN const char X(cc)[];						   \
 | 
			
		||||
FFTW_EXTERN const char X(codelet_optim)[];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* end of FFTW_DEFINE_API macro */
 | 
			
		||||
 | 
			
		||||
FFTW_DEFINE_API(FFTW_MANGLE_DOUBLE, double, fftw_complex)
 | 
			
		||||
FFTW_DEFINE_API(FFTW_MANGLE_FLOAT, float, fftwf_complex)
 | 
			
		||||
FFTW_DEFINE_API(FFTW_MANGLE_LONG_DOUBLE, long double, fftwl_complex)
 | 
			
		||||
 | 
			
		||||
/* __float128 (quad precision) is a gcc extension on i386, x86_64, and ia64
 | 
			
		||||
   for gcc >= 4.6 (compiled in FFTW with --enable-quad-precision) */
 | 
			
		||||
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) \
 | 
			
		||||
 && !(defined(__ICC) || defined(__INTEL_COMPILER)) \
 | 
			
		||||
 && (defined(__i386__) || defined(__x86_64__) || defined(__ia64__))
 | 
			
		||||
#  if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
 | 
			
		||||
/* note: __float128 is a typedef, which is not supported with the _Complex
 | 
			
		||||
         keyword in gcc, so instead we use this ugly __attribute__ version.
 | 
			
		||||
         However, we can't simply pass the __attribute__ version to
 | 
			
		||||
         FFTW_DEFINE_API because the __attribute__ confuses gcc in pointer
 | 
			
		||||
         types.  Hence redefining FFTW_DEFINE_COMPLEX.  Ugh. */
 | 
			
		||||
#    undef FFTW_DEFINE_COMPLEX
 | 
			
		||||
#    define FFTW_DEFINE_COMPLEX(R, C) typedef _Complex float __attribute__((mode(TC))) C
 | 
			
		||||
#  endif
 | 
			
		||||
FFTW_DEFINE_API(FFTW_MANGLE_QUAD, __float128, fftwq_complex)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define FFTW_FORWARD (-1)
 | 
			
		||||
#define FFTW_BACKWARD (+1)
 | 
			
		||||
 | 
			
		||||
#define FFTW_NO_TIMELIMIT (-1.0)
 | 
			
		||||
 | 
			
		||||
/* documented flags */
 | 
			
		||||
#define FFTW_MEASURE (0U)
 | 
			
		||||
#define FFTW_DESTROY_INPUT (1U << 0)
 | 
			
		||||
#define FFTW_UNALIGNED (1U << 1)
 | 
			
		||||
#define FFTW_CONSERVE_MEMORY (1U << 2)
 | 
			
		||||
#define FFTW_EXHAUSTIVE (1U << 3) /* NO_EXHAUSTIVE is default */
 | 
			
		||||
#define FFTW_PRESERVE_INPUT (1U << 4) /* cancels FFTW_DESTROY_INPUT */
 | 
			
		||||
#define FFTW_PATIENT (1U << 5) /* IMPATIENT is default */
 | 
			
		||||
#define FFTW_ESTIMATE (1U << 6)
 | 
			
		||||
#define FFTW_WISDOM_ONLY (1U << 21)
 | 
			
		||||
 | 
			
		||||
/* undocumented beyond-guru flags */
 | 
			
		||||
#define FFTW_ESTIMATE_PATIENT (1U << 7)
 | 
			
		||||
#define FFTW_BELIEVE_PCOST (1U << 8)
 | 
			
		||||
#define FFTW_NO_DFT_R2HC (1U << 9)
 | 
			
		||||
#define FFTW_NO_NONTHREADED (1U << 10)
 | 
			
		||||
#define FFTW_NO_BUFFERING (1U << 11)
 | 
			
		||||
#define FFTW_NO_INDIRECT_OP (1U << 12)
 | 
			
		||||
#define FFTW_ALLOW_LARGE_GENERIC (1U << 13) /* NO_LARGE_GENERIC is default */
 | 
			
		||||
#define FFTW_NO_RANK_SPLITS (1U << 14)
 | 
			
		||||
#define FFTW_NO_VRANK_SPLITS (1U << 15)
 | 
			
		||||
#define FFTW_NO_VRECURSE (1U << 16)
 | 
			
		||||
#define FFTW_NO_SIMD (1U << 17)
 | 
			
		||||
#define FFTW_NO_SLOW (1U << 18)
 | 
			
		||||
#define FFTW_NO_FIXED_RADIX_LARGE_N (1U << 19)
 | 
			
		||||
#define FFTW_ALLOW_PRUNING (1U << 20)
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  /* extern "C" */
 | 
			
		||||
#endif /* __cplusplus */
 | 
			
		||||
 | 
			
		||||
#endif /* FFTW3_H */
 | 
			
		||||
@@ -261,6 +261,7 @@ GridUnopClass(UnaryExp, exp(a));
 | 
			
		||||
GridBinOpClass(BinaryAdd, lhs + rhs);
 | 
			
		||||
GridBinOpClass(BinarySub, lhs - rhs);
 | 
			
		||||
GridBinOpClass(BinaryMul, lhs *rhs);
 | 
			
		||||
GridBinOpClass(BinaryDiv, lhs /rhs);
 | 
			
		||||
 | 
			
		||||
GridBinOpClass(BinaryAnd, lhs &rhs);
 | 
			
		||||
GridBinOpClass(BinaryOr, lhs | rhs);
 | 
			
		||||
@@ -385,6 +386,7 @@ GRID_DEF_UNOP(exp, UnaryExp);
 | 
			
		||||
GRID_DEF_BINOP(operator+, BinaryAdd);
 | 
			
		||||
GRID_DEF_BINOP(operator-, BinarySub);
 | 
			
		||||
GRID_DEF_BINOP(operator*, BinaryMul);
 | 
			
		||||
GRID_DEF_BINOP(operator/, BinaryDiv);
 | 
			
		||||
 | 
			
		||||
GRID_DEF_BINOP(operator&, BinaryAnd);
 | 
			
		||||
GRID_DEF_BINOP(operator|, BinaryOr);
 | 
			
		||||
 
 | 
			
		||||
@@ -300,17 +300,6 @@ PARALLEL_FOR_LOOP
 | 
			
		||||
        *this = (*this)+r;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    strong_inline friend Lattice<vobj> operator / (const Lattice<vobj> &lhs,const Lattice<vobj> &rhs){
 | 
			
		||||
        conformable(lhs,rhs);
 | 
			
		||||
        Lattice<vobj> ret(lhs._grid);
 | 
			
		||||
PARALLEL_FOR_LOOP
 | 
			
		||||
        for(int ss=0;ss<lhs._grid->oSites();ss++){
 | 
			
		||||
	  ret._odata[ss] = lhs._odata[ss]*pow(rhs._odata[ss],-1.0);
 | 
			
		||||
        }
 | 
			
		||||
        return ret;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 }; // class Lattice
 | 
			
		||||
 | 
			
		||||
  template<class vobj> std::ostream& operator<< (std::ostream& stream, const Lattice<vobj> &o){
 | 
			
		||||
 
 | 
			
		||||
@@ -294,7 +294,7 @@ namespace Grid {
 | 
			
		||||
	int rank,o_idx,i_idx;
 | 
			
		||||
	_grid->GlobalIndexToGlobalCoor(gidx,gcoor);
 | 
			
		||||
	_grid->GlobalCoorToRankIndex(rank,o_idx,i_idx,gcoor);
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
	int l_idx=generator_idx(o_idx,i_idx);
 | 
			
		||||
 | 
			
		||||
	const int num_rand_seed=16;
 | 
			
		||||
 
 | 
			
		||||
@@ -457,7 +457,7 @@ class BinaryIO {
 | 
			
		||||
    // available (how short sighted is that?)
 | 
			
		||||
    //////////////////////////////////////////////////////////
 | 
			
		||||
    Umu = zero;
 | 
			
		||||
    static uint32_t csum=0;
 | 
			
		||||
    static uint32_t csum; csum=0;
 | 
			
		||||
    fobj fileObj;
 | 
			
		||||
    static sobj siteObj; // Static to place in symmetric region for SHMEM
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,30 @@ namespace QCD {
 | 
			
		||||
   mass(_mass)
 | 
			
		||||
 { }
 | 
			
		||||
 | 
			
		||||
template<class Impl>  
 | 
			
		||||
void CayleyFermion5D<Impl>::Dminus(const FermionField &psi, FermionField &chi)
 | 
			
		||||
{
 | 
			
		||||
  int Ls=this->Ls;
 | 
			
		||||
  FermionField tmp(psi._grid);
 | 
			
		||||
 | 
			
		||||
  this->DW(psi,tmp,DaggerNo);
 | 
			
		||||
 | 
			
		||||
  for(int s=0;s<Ls;s++){
 | 
			
		||||
    axpby_ssp(chi,Coeff_t(1.0),psi,-cs[s],tmp,s,s);// chi = (1-c[s] D_W) psi
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
template<class Impl>  
 | 
			
		||||
void CayleyFermion5D<Impl>::DminusDag(const FermionField &psi, FermionField &chi)
 | 
			
		||||
{
 | 
			
		||||
  int Ls=this->Ls;
 | 
			
		||||
  FermionField tmp(psi._grid);
 | 
			
		||||
 | 
			
		||||
  this->DW(psi,tmp,DaggerYes);
 | 
			
		||||
 | 
			
		||||
  for(int s=0;s<Ls;s++){
 | 
			
		||||
    axpby_ssp(chi,Coeff_t(1.0),psi,-cs[s],tmp,s,s);// chi = (1-c[s] D_W) psi
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
template<class Impl>  
 | 
			
		||||
void CayleyFermion5D<Impl>::M5D   (const FermionField &psi, FermionField &chi)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -56,6 +56,9 @@ namespace Grid {
 | 
			
		||||
      virtual void   M5D   (const FermionField &psi, FermionField &chi);
 | 
			
		||||
      virtual void   M5Ddag(const FermionField &psi, FermionField &chi);
 | 
			
		||||
 | 
			
		||||
      virtual void   Dminus(const FermionField &psi, FermionField &chi);
 | 
			
		||||
      virtual void   DminusDag(const FermionField &psi, FermionField &chi);
 | 
			
		||||
 | 
			
		||||
      /////////////////////////////////////////////////////
 | 
			
		||||
      // Instantiate different versions depending on Impl
 | 
			
		||||
      /////////////////////////////////////////////////////
 | 
			
		||||
@@ -117,6 +120,7 @@ namespace Grid {
 | 
			
		||||
		      GridRedBlackCartesian &FourDimRedBlackGrid,
 | 
			
		||||
		      RealD _mass,RealD _M5,const ImplParams &p= ImplParams());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
      void SetCoefficientsZolotarev(RealD zolohi,Approx::zolotarev_data *zdata,RealD b,RealD c);
 | 
			
		||||
      void SetCoefficientsTanh(Approx::zolotarev_data *zdata,RealD b,RealD c);
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,10 @@ namespace Grid {
 | 
			
		||||
     INHERIT_IMPL_TYPES(Impl);
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
      void  MomentumSpacePropagator(FermionField &out,const FermionField &in,RealD _m) { 
 | 
			
		||||
	this->MomentumSpacePropagatorHt(out,in,_m);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      virtual void   Instantiatable(void) {};
 | 
			
		||||
      // Constructors
 | 
			
		||||
      DomainWallFermion(GaugeField &_Umu,
 | 
			
		||||
@@ -51,6 +55,7 @@ namespace Grid {
 | 
			
		||||
			GridRedBlackCartesian &FourDimRedBlackGrid,
 | 
			
		||||
			RealD _mass,RealD _M5,const ImplParams &p= ImplParams()) : 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      CayleyFermion5D<Impl>(_Umu,
 | 
			
		||||
			    FiveDimGrid,
 | 
			
		||||
			    FiveDimRedBlackGrid,
 | 
			
		||||
 
 | 
			
		||||
@@ -91,6 +91,20 @@ namespace Grid {
 | 
			
		||||
      virtual void  Mdiag  (const FermionField &in, FermionField &out) { Mooee(in,out);};   // Same as Mooee applied to both CB's
 | 
			
		||||
      virtual void  Mdir   (const FermionField &in, FermionField &out,int dir,int disp)=0;   // case by case Wilson, Clover, Cayley, ContFrac, PartFrac
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      virtual void  MomentumSpacePropagator(FermionField &out,const FermionField &in,RealD _m) { assert(0);};
 | 
			
		||||
 | 
			
		||||
      virtual void  FreePropagator(const FermionField &in,FermionField &out,RealD mass) { 
 | 
			
		||||
	FFT theFFT((GridCartesian *) in._grid);
 | 
			
		||||
 | 
			
		||||
	FermionField in_k(in._grid);
 | 
			
		||||
	FermionField prop_k(in._grid);
 | 
			
		||||
 | 
			
		||||
	theFFT.FFT_all_dim(in_k,in,FFT::forward);
 | 
			
		||||
        this->MomentumSpacePropagator(prop_k,in_k,mass);
 | 
			
		||||
	theFFT.FFT_all_dim(out,prop_k,FFT::backward);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      ///////////////////////////////////////////////
 | 
			
		||||
      // Updates gauge field during HMC
 | 
			
		||||
      ///////////////////////////////////////////////
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,11 @@ namespace Grid {
 | 
			
		||||
     INHERIT_IMPL_TYPES(Impl);
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
      // Constructors
 | 
			
		||||
     void  MomentumSpacePropagator(FermionField &out,const FermionField &in,RealD _m) { 
 | 
			
		||||
       this->MomentumSpacePropagatorHw(out,in,_m);
 | 
			
		||||
     };
 | 
			
		||||
 | 
			
		||||
     // Constructors
 | 
			
		||||
    OverlapWilsonCayleyTanhFermion(GaugeField &_Umu,
 | 
			
		||||
				   GridCartesian         &FiveDimGrid,
 | 
			
		||||
				   GridRedBlackCartesian &FiveDimRedBlackGrid,
 | 
			
		||||
 
 | 
			
		||||
@@ -100,6 +100,7 @@ void WilsonFermion<Impl>::Meooe(const FermionField &in, FermionField &out) {
 | 
			
		||||
    DhopOE(in, out, DaggerNo);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Impl>
 | 
			
		||||
void WilsonFermion<Impl>::MeooeDag(const FermionField &in, FermionField &out) {
 | 
			
		||||
  if (in.checkerboard == Odd) {
 | 
			
		||||
@@ -108,32 +109,87 @@ void WilsonFermion<Impl>::MeooeDag(const FermionField &in, FermionField &out) {
 | 
			
		||||
    DhopOE(in, out, DaggerYes);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
  template <class Impl>
 | 
			
		||||
  void WilsonFermion<Impl>::Mooee(const FermionField &in, FermionField &out) {
 | 
			
		||||
    out.checkerboard = in.checkerboard;
 | 
			
		||||
    typename FermionField::scalar_type scal(4.0 + mass);
 | 
			
		||||
    out = scal * in;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
template <class Impl>
 | 
			
		||||
void WilsonFermion<Impl>::Mooee(const FermionField &in, FermionField &out) {
 | 
			
		||||
  out.checkerboard = in.checkerboard;
 | 
			
		||||
  typename FermionField::scalar_type scal(4.0 + mass);
 | 
			
		||||
  out = scal * in;
 | 
			
		||||
}
 | 
			
		||||
  template <class Impl>
 | 
			
		||||
  void WilsonFermion<Impl>::MooeeDag(const FermionField &in, FermionField &out) {
 | 
			
		||||
    out.checkerboard = in.checkerboard;
 | 
			
		||||
    Mooee(in, out);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
template <class Impl>
 | 
			
		||||
void WilsonFermion<Impl>::MooeeDag(const FermionField &in, FermionField &out) {
 | 
			
		||||
  out.checkerboard = in.checkerboard;
 | 
			
		||||
  Mooee(in, out);
 | 
			
		||||
}
 | 
			
		||||
  template<class Impl>
 | 
			
		||||
  void WilsonFermion<Impl>::MooeeInv(const FermionField &in, FermionField &out) {
 | 
			
		||||
    out.checkerboard = in.checkerboard;
 | 
			
		||||
    out = (1.0/(4.0+mass))*in;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template<class Impl>
 | 
			
		||||
  void WilsonFermion<Impl>::MooeeInvDag(const FermionField &in, FermionField &out) {
 | 
			
		||||
    out.checkerboard = in.checkerboard;
 | 
			
		||||
    MooeeInv(in,out);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
template <class Impl>
 | 
			
		||||
void WilsonFermion<Impl>::MooeeInv(const FermionField &in, FermionField &out) {
 | 
			
		||||
  out.checkerboard = in.checkerboard;
 | 
			
		||||
  out = (1.0 / (4.0 + mass)) * in;
 | 
			
		||||
}
 | 
			
		||||
  template<class Impl>
 | 
			
		||||
  void WilsonFermion<Impl>::MomentumSpacePropagator(FermionField &out, const FermionField &in,RealD _m) {
 | 
			
		||||
 | 
			
		||||
template <class Impl>
 | 
			
		||||
void WilsonFermion<Impl>::MooeeInvDag(const FermionField &in,
 | 
			
		||||
                                      FermionField &out) {
 | 
			
		||||
  out.checkerboard = in.checkerboard;
 | 
			
		||||
  MooeeInv(in, out);
 | 
			
		||||
}
 | 
			
		||||
    // what type LatticeComplex 
 | 
			
		||||
    conformable(_grid,out._grid);
 | 
			
		||||
 | 
			
		||||
    typedef typename FermionField::vector_type vector_type;
 | 
			
		||||
    typedef typename FermionField::scalar_type ScalComplex;
 | 
			
		||||
 | 
			
		||||
    typedef Lattice<iSinglet<vector_type> > LatComplex;
 | 
			
		||||
 | 
			
		||||
    Gamma::GammaMatrix Gmu [] = {
 | 
			
		||||
      Gamma::GammaX,
 | 
			
		||||
      Gamma::GammaY,
 | 
			
		||||
      Gamma::GammaZ,
 | 
			
		||||
      Gamma::GammaT
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::vector<int> latt_size   = _grid->_fdimensions;
 | 
			
		||||
 | 
			
		||||
    FermionField   num  (_grid); num  = zero;
 | 
			
		||||
    LatComplex    wilson(_grid); wilson= zero;
 | 
			
		||||
    LatComplex     one  (_grid); one = ScalComplex(1.0,0.0);
 | 
			
		||||
 | 
			
		||||
    LatComplex denom(_grid); denom= zero;
 | 
			
		||||
    LatComplex kmu(_grid); 
 | 
			
		||||
    ScalComplex ci(0.0,1.0);
 | 
			
		||||
    // momphase = n * 2pi / L
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++) {
 | 
			
		||||
 | 
			
		||||
      LatticeCoordinate(kmu,mu);
 | 
			
		||||
 | 
			
		||||
      RealD TwoPiL =  M_PI * 2.0/ latt_size[mu];
 | 
			
		||||
 | 
			
		||||
      kmu = TwoPiL * kmu;
 | 
			
		||||
 | 
			
		||||
      wilson = wilson + 2.0*sin(kmu*0.5)*sin(kmu*0.5); // Wilson term
 | 
			
		||||
 | 
			
		||||
      num = num - sin(kmu)*ci*(Gamma(Gmu[mu])*in);    // derivative term
 | 
			
		||||
 | 
			
		||||
      denom=denom + sin(kmu)*sin(kmu);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wilson = wilson + _m;     // 2 sin^2 k/2 + m
 | 
			
		||||
 | 
			
		||||
    num   = num + wilson*in;     // -i gmu sin k + 2 sin^2 k/2 + m
 | 
			
		||||
 | 
			
		||||
    denom= denom+wilson*wilson; // sin^2 k + (2 sin^2 k/2 + m)^2
 | 
			
		||||
 | 
			
		||||
    denom= one/denom;
 | 
			
		||||
 | 
			
		||||
    out = num*denom; // [ -i gmu sin k + 2 sin^2 k/2 + m] / [ sin^2 k + (2 sin^2 k/2 + m)^2 ]
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////
 | 
			
		||||
// Internal
 | 
			
		||||
 
 | 
			
		||||
@@ -78,16 +78,15 @@ class WilsonFermion : public WilsonKernels<Impl>, public WilsonFermionStatic {
 | 
			
		||||
  virtual void MooeeInv(const FermionField &in, FermionField &out);
 | 
			
		||||
  virtual void MooeeInvDag(const FermionField &in, FermionField &out);
 | 
			
		||||
 | 
			
		||||
  virtual void  MomentumSpacePropagator(FermionField &out,const FermionField &in,RealD _mass) ;
 | 
			
		||||
 | 
			
		||||
  ////////////////////////
 | 
			
		||||
  // Derivative interface
 | 
			
		||||
  ////////////////////////
 | 
			
		||||
  // Interface calls an internal routine
 | 
			
		||||
  void DhopDeriv(GaugeField &mat, const FermionField &U, const FermionField &V,
 | 
			
		||||
                 int dag);
 | 
			
		||||
  void DhopDerivOE(GaugeField &mat, const FermionField &U,
 | 
			
		||||
                   const FermionField &V, int dag);
 | 
			
		||||
  void DhopDerivEO(GaugeField &mat, const FermionField &U,
 | 
			
		||||
                   const FermionField &V, int dag);
 | 
			
		||||
  void DhopDeriv(GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
  void DhopDerivOE(GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
  void DhopDerivEO(GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
 | 
			
		||||
  ///////////////////////////////////////////////////////////////
 | 
			
		||||
  // non-hermitian hopping term; half cb or both
 | 
			
		||||
 
 | 
			
		||||
@@ -482,6 +482,148 @@ void WilsonFermion5D<Impl>::DW(const FermionField &in, FermionField &out,int dag
 | 
			
		||||
  axpy(out,4.0-M5,in,out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class Impl>
 | 
			
		||||
void WilsonFermion5D<Impl>::MomentumSpacePropagatorHt(FermionField &out,const FermionField &in, RealD mass) 
 | 
			
		||||
{
 | 
			
		||||
  // what type LatticeComplex 
 | 
			
		||||
  GridBase *_grid = _FourDimGrid;
 | 
			
		||||
  conformable(_grid,out._grid);
 | 
			
		||||
  
 | 
			
		||||
  typedef typename FermionField::vector_type vector_type;
 | 
			
		||||
  typedef typename FermionField::scalar_type ScalComplex;
 | 
			
		||||
  typedef iSinglet<ScalComplex> Tcomplex;
 | 
			
		||||
  typedef Lattice<iSinglet<vector_type> > LatComplex;
 | 
			
		||||
  
 | 
			
		||||
  Gamma::GammaMatrix Gmu [] = {
 | 
			
		||||
    Gamma::GammaX,
 | 
			
		||||
    Gamma::GammaY,
 | 
			
		||||
    Gamma::GammaZ,
 | 
			
		||||
    Gamma::GammaT
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  std::vector<int> latt_size   = _grid->_fdimensions;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  FermionField   num  (_grid); num  = zero;
 | 
			
		||||
 | 
			
		||||
  LatComplex    sk(_grid);  sk = zero;
 | 
			
		||||
  LatComplex    sk2(_grid); sk2= zero;
 | 
			
		||||
  LatComplex    W(_grid); W= zero;
 | 
			
		||||
  LatComplex    a(_grid); a= zero;
 | 
			
		||||
  LatComplex    one  (_grid); one = ScalComplex(1.0,0.0);
 | 
			
		||||
  LatComplex denom(_grid); denom= zero;
 | 
			
		||||
  LatComplex cosha(_grid); 
 | 
			
		||||
  LatComplex kmu(_grid); 
 | 
			
		||||
  LatComplex Wea(_grid); 
 | 
			
		||||
  LatComplex Wema(_grid); 
 | 
			
		||||
 | 
			
		||||
  ScalComplex ci(0.0,1.0);
 | 
			
		||||
  
 | 
			
		||||
  for(int mu=0;mu<Nd;mu++) {
 | 
			
		||||
    
 | 
			
		||||
    LatticeCoordinate(kmu,mu);
 | 
			
		||||
    
 | 
			
		||||
    RealD TwoPiL =  M_PI * 2.0/ latt_size[mu];
 | 
			
		||||
    
 | 
			
		||||
    kmu = TwoPiL * kmu;
 | 
			
		||||
    
 | 
			
		||||
    sk2 = sk2 + 2.0*sin(kmu*0.5)*sin(kmu*0.5);
 | 
			
		||||
    sk  = sk  +     sin(kmu)    *sin(kmu); 
 | 
			
		||||
    
 | 
			
		||||
    num = num - sin(kmu)*ci*(Gamma(Gmu[mu])*in);
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  W = one - M5 + sk2;
 | 
			
		||||
 | 
			
		||||
  ////////////////////////////////////////////
 | 
			
		||||
  // Cosh alpha -> alpha
 | 
			
		||||
  ////////////////////////////////////////////
 | 
			
		||||
  cosha =  (one + W*W + sk) / (W*2.0);
 | 
			
		||||
 | 
			
		||||
  // FIXME Need a Lattice acosh
 | 
			
		||||
  for(int idx=0;idx<_grid->lSites();idx++){
 | 
			
		||||
    std::vector<int> lcoor(Nd);
 | 
			
		||||
    Tcomplex cc;
 | 
			
		||||
    RealD sgn;
 | 
			
		||||
    _grid->LocalIndexToLocalCoor(idx,lcoor);
 | 
			
		||||
    peekLocalSite(cc,cosha,lcoor);
 | 
			
		||||
    assert((double)real(cc)>=1.0);
 | 
			
		||||
    assert(fabs((double)imag(cc))<=1.0e-15);
 | 
			
		||||
    cc = ScalComplex(::acosh(real(cc)),0.0);
 | 
			
		||||
    pokeLocalSite(cc,a,lcoor);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  Wea = ( exp( a) * W  ); 
 | 
			
		||||
  Wema= ( exp(-a) * W  ); 
 | 
			
		||||
  
 | 
			
		||||
  num   = num + ( one - Wema ) * mass * in;
 | 
			
		||||
  denom= ( Wea - one ) + mass*mass * (one - Wema); 
 | 
			
		||||
  out = num/denom;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class Impl>
 | 
			
		||||
void WilsonFermion5D<Impl>::MomentumSpacePropagatorHw(FermionField &out,const FermionField &in,RealD mass) 
 | 
			
		||||
{
 | 
			
		||||
    Gamma::GammaMatrix Gmu [] = {
 | 
			
		||||
      Gamma::GammaX,
 | 
			
		||||
      Gamma::GammaY,
 | 
			
		||||
      Gamma::GammaZ,
 | 
			
		||||
      Gamma::GammaT
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    GridBase *_grid = _FourDimGrid;
 | 
			
		||||
    conformable(_grid,out._grid);
 | 
			
		||||
 | 
			
		||||
    typedef typename FermionField::vector_type vector_type;
 | 
			
		||||
    typedef typename FermionField::scalar_type ScalComplex;
 | 
			
		||||
 | 
			
		||||
    typedef Lattice<iSinglet<vector_type> > LatComplex;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    std::vector<int> latt_size   = _grid->_fdimensions;
 | 
			
		||||
 | 
			
		||||
    LatComplex    sk(_grid);  sk = zero;
 | 
			
		||||
    LatComplex    sk2(_grid); sk2= zero;
 | 
			
		||||
 | 
			
		||||
    LatComplex    w_k(_grid); w_k= zero;
 | 
			
		||||
    LatComplex    b_k(_grid); b_k= zero;
 | 
			
		||||
 | 
			
		||||
    LatComplex     one  (_grid); one = ScalComplex(1.0,0.0);
 | 
			
		||||
 | 
			
		||||
    FermionField   num  (_grid); num  = zero;
 | 
			
		||||
    LatComplex denom(_grid); denom= zero;
 | 
			
		||||
    LatComplex kmu(_grid); 
 | 
			
		||||
    ScalComplex ci(0.0,1.0);
 | 
			
		||||
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++) {
 | 
			
		||||
 | 
			
		||||
      LatticeCoordinate(kmu,mu);
 | 
			
		||||
 | 
			
		||||
      RealD TwoPiL =  M_PI * 2.0/ latt_size[mu];
 | 
			
		||||
 | 
			
		||||
      kmu = TwoPiL * kmu;
 | 
			
		||||
 | 
			
		||||
      sk2 = sk2 + 2.0*sin(kmu*0.5)*sin(kmu*0.5);
 | 
			
		||||
      sk  = sk  + sin(kmu)*sin(kmu); 
 | 
			
		||||
 | 
			
		||||
      num = num - sin(kmu)*ci*(Gamma(Gmu[mu])*in);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    num = num + mass * in ;
 | 
			
		||||
 | 
			
		||||
    b_k = sk2 - M5;
 | 
			
		||||
     
 | 
			
		||||
    w_k = sqrt(sk + b_k*b_k);
 | 
			
		||||
 | 
			
		||||
    denom= ( w_k + b_k + mass*mass) ;
 | 
			
		||||
 | 
			
		||||
    denom= one/denom;
 | 
			
		||||
    out = num*denom;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FermOpTemplateInstantiate(WilsonFermion5D);
 | 
			
		||||
GparityFermOpTemplateInstantiate(WilsonFermion5D);
 | 
			
		||||
  
 | 
			
		||||
 
 | 
			
		||||
@@ -47,68 +47,82 @@ namespace QCD {
 | 
			
		||||
  // [DIFFERS from original CPS red black implementation parity = (x+y+z+t+s)|2 ]
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
  class WilsonFermion5DStatic { 
 | 
			
		||||
  public:
 | 
			
		||||
    // S-direction is INNERMOST and takes no part in the parity.
 | 
			
		||||
    static const std::vector<int> directions;
 | 
			
		||||
    static const std::vector<int> displacements;
 | 
			
		||||
    const int npoint = 8;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  template<class Impl>
 | 
			
		||||
  class WilsonFermion5D : public WilsonKernels<Impl>, public WilsonFermion5DStatic
 | 
			
		||||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    INHERIT_IMPL_TYPES(Impl);
 | 
			
		||||
    typedef WilsonKernels<Impl> Kernels;
 | 
			
		||||
    PmuStat stat;
 | 
			
		||||
    
 | 
			
		||||
    void Report(void);
 | 
			
		||||
    void ZeroCounters(void);
 | 
			
		||||
    double DhopCalls;
 | 
			
		||||
    double DhopCommTime;
 | 
			
		||||
    double DhopComputeTime;
 | 
			
		||||
    
 | 
			
		||||
    double DerivCalls;
 | 
			
		||||
    double DerivCommTime;
 | 
			
		||||
    double DerivComputeTime;
 | 
			
		||||
    double DerivDhopComputeTime;
 | 
			
		||||
    
 | 
			
		||||
    ///////////////////////////////////////////////////////////////
 | 
			
		||||
    // Implement the abstract base
 | 
			
		||||
    ///////////////////////////////////////////////////////////////
 | 
			
		||||
    GridBase *GaugeGrid(void)              { return _FourDimGrid ;}
 | 
			
		||||
    GridBase *GaugeRedBlackGrid(void)      { return _FourDimRedBlackGrid ;}
 | 
			
		||||
    GridBase *FermionGrid(void)            { return _FiveDimGrid;}
 | 
			
		||||
    GridBase *FermionRedBlackGrid(void)    { return _FiveDimRedBlackGrid;}
 | 
			
		||||
    
 | 
			
		||||
    // full checkerboard operations; leave unimplemented as abstract for now
 | 
			
		||||
    virtual RealD  M    (const FermionField &in, FermionField &out){assert(0); return 0.0;};
 | 
			
		||||
    virtual RealD  Mdag (const FermionField &in, FermionField &out){assert(0); return 0.0;};
 | 
			
		||||
    
 | 
			
		||||
    // half checkerboard operations; leave unimplemented as abstract for now
 | 
			
		||||
    virtual void   Meooe       (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
    virtual void   Mooee       (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
    virtual void   MooeeInv    (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
    
 | 
			
		||||
    virtual void   MeooeDag    (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
    virtual void   MooeeDag    (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
    virtual void   MooeeInvDag (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
    virtual void   Mdir   (const FermionField &in, FermionField &out,int dir,int disp){assert(0);};   // case by case Wilson, Clover, Cayley, ContFrac, PartFrac
 | 
			
		||||
    
 | 
			
		||||
    // These can be overridden by fancy 5d chiral action
 | 
			
		||||
    virtual void DhopDeriv  (GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
    virtual void DhopDerivEO(GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
    virtual void DhopDerivOE(GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
    
 | 
			
		||||
    // Implement hopping term non-hermitian hopping term; half cb or both
 | 
			
		||||
    // Implement s-diagonal DW
 | 
			
		||||
    void DW    (const FermionField &in, FermionField &out,int dag);
 | 
			
		||||
    void Dhop  (const FermionField &in, FermionField &out,int dag);
 | 
			
		||||
    void DhopOE(const FermionField &in, FermionField &out,int dag);
 | 
			
		||||
    void DhopEO(const FermionField &in, FermionField &out,int dag);
 | 
			
		||||
    
 | 
			
		||||
    // add a DhopComm
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    // This is the 4d red black case appropriate to support
 | 
			
		||||
    //
 | 
			
		||||
    // parity = (x+y+z+t)|2;
 | 
			
		||||
    // generalised five dim fermions like mobius, zolotarev etc..	
 | 
			
		||||
    //
 | 
			
		||||
    // i.e. even even contains fifth dim hopping term.
 | 
			
		||||
    //
 | 
			
		||||
    // [DIFFERS from original CPS red black implementation parity = (x+y+z+t+s)|2 ]
 | 
			
		||||
    ////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
    class WilsonFermion5DStatic { 
 | 
			
		||||
    public:
 | 
			
		||||
      // S-direction is INNERMOST and takes no part in the parity.
 | 
			
		||||
      static const std::vector<int> directions;
 | 
			
		||||
      static const std::vector<int> displacements;
 | 
			
		||||
      const int npoint = 8;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template<class Impl>
 | 
			
		||||
    class WilsonFermion5D : public WilsonKernels<Impl>, public WilsonFermion5DStatic
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
     INHERIT_IMPL_TYPES(Impl);
 | 
			
		||||
     typedef WilsonKernels<Impl> Kernels;
 | 
			
		||||
     PmuStat stat;
 | 
			
		||||
 | 
			
		||||
     void Report(void);
 | 
			
		||||
     void ZeroCounters(void);
 | 
			
		||||
     double DhopCalls;
 | 
			
		||||
     double DhopCommTime;
 | 
			
		||||
     double DhopComputeTime;
 | 
			
		||||
 | 
			
		||||
     double DerivCalls;
 | 
			
		||||
     double DerivCommTime;
 | 
			
		||||
     double DerivComputeTime;
 | 
			
		||||
     double DerivDhopComputeTime;
 | 
			
		||||
 | 
			
		||||
      ///////////////////////////////////////////////////////////////
 | 
			
		||||
      // Implement the abstract base
 | 
			
		||||
      ///////////////////////////////////////////////////////////////
 | 
			
		||||
      GridBase *GaugeGrid(void)              { return _FourDimGrid ;}
 | 
			
		||||
      GridBase *GaugeRedBlackGrid(void)      { return _FourDimRedBlackGrid ;}
 | 
			
		||||
      GridBase *FermionGrid(void)            { return _FiveDimGrid;}
 | 
			
		||||
      GridBase *FermionRedBlackGrid(void)    { return _FiveDimRedBlackGrid;}
 | 
			
		||||
 | 
			
		||||
      // full checkerboard operations; leave unimplemented as abstract for now
 | 
			
		||||
      virtual RealD  M    (const FermionField &in, FermionField &out){assert(0); return 0.0;};
 | 
			
		||||
      virtual RealD  Mdag (const FermionField &in, FermionField &out){assert(0); return 0.0;};
 | 
			
		||||
 | 
			
		||||
      // half checkerboard operations; leave unimplemented as abstract for now
 | 
			
		||||
      virtual void   Meooe       (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
      virtual void   Mooee       (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
      virtual void   MooeeInv    (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
 | 
			
		||||
      virtual void   MeooeDag    (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
      virtual void   MooeeDag    (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
      virtual void   MooeeInvDag (const FermionField &in, FermionField &out){assert(0);};
 | 
			
		||||
      virtual void   Mdir   (const FermionField &in, FermionField &out,int dir,int disp){assert(0);};   // case by case Wilson, Clover, Cayley, ContFrac, PartFrac
 | 
			
		||||
 | 
			
		||||
      // These can be overridden by fancy 5d chiral action
 | 
			
		||||
      virtual void DhopDeriv  (GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
      virtual void DhopDerivEO(GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
      virtual void DhopDerivOE(GaugeField &mat,const FermionField &U,const FermionField &V,int dag);
 | 
			
		||||
 | 
			
		||||
      void MomentumSpacePropagatorHt(FermionField &out,const FermionField &in,RealD mass) ;
 | 
			
		||||
      void MomentumSpacePropagatorHw(FermionField &out,const FermionField &in,RealD mass) ;
 | 
			
		||||
 | 
			
		||||
      // Implement hopping term non-hermitian hopping term; half cb or both
 | 
			
		||||
      // Implement s-diagonal DW
 | 
			
		||||
      void DW    (const FermionField &in, FermionField &out,int dag);
 | 
			
		||||
      void Dhop  (const FermionField &in, FermionField &out,int dag);
 | 
			
		||||
      void DhopOE(const FermionField &in, FermionField &out,int dag);
 | 
			
		||||
      void DhopEO(const FermionField &in, FermionField &out,int dag);
 | 
			
		||||
 | 
			
		||||
      // add a DhopComm
 | 
			
		||||
      // -- suboptimal interface will presently trigger multiple comms.
 | 
			
		||||
    void DhopDir(const FermionField &in, FermionField &out,int dir,int disp);
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -32,8 +32,7 @@ directory
 | 
			
		||||
namespace Grid {
 | 
			
		||||
namespace QCD {
 | 
			
		||||
 | 
			
		||||
int WilsonKernelsStatic::HandOpt;
 | 
			
		||||
int WilsonKernelsStatic::AsmOpt;
 | 
			
		||||
int WilsonKernelsStatic::Opt;
 | 
			
		||||
 | 
			
		||||
template <class Impl>
 | 
			
		||||
WilsonKernels<Impl>::WilsonKernels(const ImplParams &p) : Base(p){};
 | 
			
		||||
 
 | 
			
		||||
@@ -40,9 +40,9 @@ namespace QCD {
 | 
			
		||||
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
class WilsonKernelsStatic { 
 | 
			
		||||
 public:
 | 
			
		||||
  enum { OptGeneric, OptHandUnroll, OptInlineAsm };
 | 
			
		||||
  // S-direction is INNERMOST and takes no part in the parity.
 | 
			
		||||
  static int AsmOpt;  // these are a temporary hack
 | 
			
		||||
  static int HandOpt; // these are a temporary hack
 | 
			
		||||
  static int Opt;  // these are a temporary hack
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
template<class Impl> class WilsonKernels : public FermionOperator<Impl> , public WilsonKernelsStatic { 
 | 
			
		||||
@@ -56,24 +56,34 @@ public:
 | 
			
		||||
  template <bool EnableBool = true>
 | 
			
		||||
  typename std::enable_if<Impl::Dimension == 3 && Nc == 3 &&EnableBool, void>::type
 | 
			
		||||
  DiracOptDhopSite(StencilImpl &st, LebesgueOrder &lo, DoubledGaugeField &U, SiteHalfSpinor * buf,
 | 
			
		||||
		   int sF, int sU, int Ls, int Ns, const FermionField &in, FermionField &out) {
 | 
			
		||||
		   int sF, int sU, int Ls, int Ns, const FermionField &in, FermionField &out) 
 | 
			
		||||
  {
 | 
			
		||||
    switch(Opt) {
 | 
			
		||||
#ifdef AVX512
 | 
			
		||||
    if (AsmOpt) {
 | 
			
		||||
      WilsonKernels<Impl>::DiracOptAsmDhopSite(st,lo,U,buf,sF,sU,Ls,Ns,in,out);
 | 
			
		||||
    } else {
 | 
			
		||||
#else
 | 
			
		||||
    {
 | 
			
		||||
    case OptInlineAsm:
 | 
			
		||||
       WilsonKernels<Impl>::DiracOptAsmDhopSite(st,lo,U,buf,sF,sU,Ls,Ns,in,out);
 | 
			
		||||
       break;
 | 
			
		||||
#endif
 | 
			
		||||
    case OptHandUnroll:
 | 
			
		||||
      for (int site = 0; site < Ns; site++) {
 | 
			
		||||
	for (int s = 0; s < Ls; s++) {
 | 
			
		||||
	  if (HandOpt)
 | 
			
		||||
	    WilsonKernels<Impl>::DiracOptHandDhopSite(st,lo,U,buf,sF,sU,in,out);
 | 
			
		||||
	  else
 | 
			
		||||
	    WilsonKernels<Impl>::DiracOptGenericDhopSite(st,lo,U,buf,sF,sU,in,out);
 | 
			
		||||
	  WilsonKernels<Impl>::DiracOptHandDhopSite(st,lo,U,buf,sF,sU,in,out);
 | 
			
		||||
	  sF++;
 | 
			
		||||
	}
 | 
			
		||||
	sU++;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case OptGeneric:
 | 
			
		||||
      for (int site = 0; site < Ns; site++) {
 | 
			
		||||
	for (int s = 0; s < Ls; s++) {
 | 
			
		||||
	  WilsonKernels<Impl>::DiracOptGenericDhopSite(st,lo,U,buf,sF,sU,in,out);
 | 
			
		||||
	  sF++;
 | 
			
		||||
	}
 | 
			
		||||
	sU++;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
     
 | 
			
		||||
@@ -81,7 +91,7 @@ public:
 | 
			
		||||
  typename std::enable_if<(Impl::Dimension != 3 || (Impl::Dimension == 3 && Nc != 3)) && EnableBool, void>::type
 | 
			
		||||
  DiracOptDhopSite(StencilImpl &st, LebesgueOrder &lo, DoubledGaugeField &U, SiteHalfSpinor * buf,
 | 
			
		||||
		   int sF, int sU, int Ls, int Ns, const FermionField &in, FermionField &out) {
 | 
			
		||||
     
 | 
			
		||||
    // no kernel choice  
 | 
			
		||||
    for (int site = 0; site < Ns; site++) {
 | 
			
		||||
      for (int s = 0; s < Ls; s++) {
 | 
			
		||||
	WilsonKernels<Impl>::DiracOptGenericDhopSite(st, lo, U, buf, sF, sU, in, out);
 | 
			
		||||
@@ -95,23 +105,33 @@ public:
 | 
			
		||||
  typename std::enable_if<Impl::Dimension == 3 && Nc == 3 && EnableBool,void>::type
 | 
			
		||||
  DiracOptDhopSiteDag(StencilImpl &st, LebesgueOrder &lo, DoubledGaugeField &U, SiteHalfSpinor * buf,
 | 
			
		||||
		      int sF, int sU, int Ls, int Ns, const FermionField &in, FermionField &out) {
 | 
			
		||||
 | 
			
		||||
    switch(Opt) {
 | 
			
		||||
#ifdef AVX512
 | 
			
		||||
    if (AsmOpt) {
 | 
			
		||||
    case OptInlineAsm:
 | 
			
		||||
      WilsonKernels<Impl>::DiracOptAsmDhopSiteDag(st,lo,U,buf,sF,sU,Ls,Ns,in,out);
 | 
			
		||||
    } else {
 | 
			
		||||
#else
 | 
			
		||||
    {
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
    case OptHandUnroll:
 | 
			
		||||
      for (int site = 0; site < Ns; site++) {
 | 
			
		||||
	for (int s = 0; s < Ls; s++) {
 | 
			
		||||
	  if (HandOpt)
 | 
			
		||||
	    WilsonKernels<Impl>::DiracOptHandDhopSiteDag(st,lo,U,buf,sF,sU,in,out);
 | 
			
		||||
	  else
 | 
			
		||||
	    WilsonKernels<Impl>::DiracOptGenericDhopSiteDag(st,lo,U,buf,sF,sU,in,out);
 | 
			
		||||
	  WilsonKernels<Impl>::DiracOptHandDhopSiteDag(st,lo,U,buf,sF,sU,in,out);
 | 
			
		||||
	  sF++;
 | 
			
		||||
	}
 | 
			
		||||
	sU++;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case OptGeneric:
 | 
			
		||||
      for (int site = 0; site < Ns; site++) {
 | 
			
		||||
	for (int s = 0; s < Ls; s++) {
 | 
			
		||||
	  WilsonKernels<Impl>::DiracOptGenericDhopSiteDag(st,lo,U,buf,sF,sU,in,out);
 | 
			
		||||
	  sF++;
 | 
			
		||||
	}
 | 
			
		||||
	sU++;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      assert(0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
Author: Guido Cossu <guido.cossu@ed.ac.uk>
 | 
			
		||||
 | 
			
		||||
    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU General Public License as published by
 | 
			
		||||
@@ -53,24 +54,26 @@ WilsonKernels<Impl >::DiracOptAsmDhopSiteDag(StencilImpl &st,LebesgueOrder & lo,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(AVX512) 
 | 
			
		||||
    
 | 
			
		||||
#include <simd/Intel512wilson.h>
 | 
			
		||||
 | 
			
		||||
    ///////////////////////////////////////////////////////////
 | 
			
		||||
    // If we are AVX512 specialise the single precision routine
 | 
			
		||||
    ///////////////////////////////////////////////////////////
 | 
			
		||||
    
 | 
			
		||||
#include <simd/Intel512wilson.h>
 | 
			
		||||
 | 
			
		||||
#include <simd/Intel512single.h>
 | 
			
		||||
    
 | 
			
		||||
static Vector<vComplexF> signs;
 | 
			
		||||
    
 | 
			
		||||
  int setupSigns(void ){
 | 
			
		||||
    Vector<vComplexF> bother(2);
 | 
			
		||||
static Vector<vComplexF> signsF;
 | 
			
		||||
 | 
			
		||||
  template<typename vtype>    
 | 
			
		||||
  int setupSigns(Vector<vtype>& signs ){
 | 
			
		||||
    Vector<vtype> bother(2);
 | 
			
		||||
    signs = bother;
 | 
			
		||||
    vrsign(signs[0]);
 | 
			
		||||
    visign(signs[1]);
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
  static int signInit = setupSigns();
 | 
			
		||||
 | 
			
		||||
  static int signInitF = setupSigns(signsF);
 | 
			
		||||
  
 | 
			
		||||
#define label(A)  ilabel(A)
 | 
			
		||||
#define ilabel(A) ".globl\n"  #A ":\n" 
 | 
			
		||||
@@ -78,6 +81,8 @@ static Vector<vComplexF> signs;
 | 
			
		||||
#define MAYBEPERM(A,perm) if (perm) { A ; }
 | 
			
		||||
#define MULT_2SPIN(ptr,pf) MULT_ADDSUB_2SPIN(ptr,pf)
 | 
			
		||||
#define FX(A) WILSONASM_ ##A
 | 
			
		||||
#define COMPLEX_TYPE vComplexF
 | 
			
		||||
#define signs signsF
 | 
			
		||||
  
 | 
			
		||||
#undef KERNEL_DAG
 | 
			
		||||
template<> void 
 | 
			
		||||
@@ -98,8 +103,8 @@ WilsonKernels<WilsonImplF>::DiracOptAsmDhopSiteDag(StencilImpl &st,LebesgueOrder
 | 
			
		||||
#undef FX 
 | 
			
		||||
#define FX(A) DWFASM_ ## A
 | 
			
		||||
#define MAYBEPERM(A,B) 
 | 
			
		||||
#define VMOVIDUP(A,B,C)                                  VBCASTIDUPf(A,B,C)
 | 
			
		||||
#define VMOVRDUP(A,B,C)                                  VBCASTRDUPf(A,B,C)
 | 
			
		||||
//#define VMOVIDUP(A,B,C)                                  VBCASTIDUPf(A,B,C)
 | 
			
		||||
//#define VMOVRDUP(A,B,C)                                  VBCASTRDUPf(A,B,C)
 | 
			
		||||
#define MULT_2SPIN(ptr,pf) MULT_ADDSUB_2SPIN_LS(ptr,pf)
 | 
			
		||||
				    
 | 
			
		||||
#undef KERNEL_DAG
 | 
			
		||||
@@ -113,8 +118,71 @@ template<> void
 | 
			
		||||
WilsonKernels<DomainWallVec5dImplF>::DiracOptAsmDhopSiteDag(StencilImpl &st,LebesgueOrder & lo,DoubledGaugeField &U,SiteHalfSpinor *buf,
 | 
			
		||||
							    int ss,int ssU,int Ls,int Ns,const FermionField &in, FermionField &out)
 | 
			
		||||
#include <qcd/action/fermion/WilsonKernelsAsmBody.h>
 | 
			
		||||
#undef COMPLEX_TYPE
 | 
			
		||||
#undef signs
 | 
			
		||||
#undef VMOVRDUP
 | 
			
		||||
#undef MAYBEPERM
 | 
			
		||||
#undef MULT_2SPIN
 | 
			
		||||
#undef FX 
 | 
			
		||||
	
 | 
			
		||||
///////////////////////////////////////////////////////////
 | 
			
		||||
// If we are AVX512 specialise the double precision routine
 | 
			
		||||
///////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#include <simd/Intel512double.h>
 | 
			
		||||
    
 | 
			
		||||
static Vector<vComplexD> signsD;
 | 
			
		||||
#define signs signsD
 | 
			
		||||
static int signInitD = setupSigns(signsD);
 | 
			
		||||
    
 | 
			
		||||
#define MAYBEPERM(A,perm) if (perm) { A ; }
 | 
			
		||||
#define MULT_2SPIN(ptr,pf) MULT_ADDSUB_2SPIN(ptr,pf)
 | 
			
		||||
#define FX(A) WILSONASM_ ##A
 | 
			
		||||
#define COMPLEX_TYPE vComplexD
 | 
			
		||||
  
 | 
			
		||||
#undef KERNEL_DAG
 | 
			
		||||
template<> void 
 | 
			
		||||
WilsonKernels<WilsonImplD>::DiracOptAsmDhopSite(StencilImpl &st,LebesgueOrder & lo,DoubledGaugeField &U, SiteHalfSpinor *buf,
 | 
			
		||||
						int ss,int ssU,int Ls,int Ns,const FermionField &in, FermionField &out)
 | 
			
		||||
#include <qcd/action/fermion/WilsonKernelsAsmBody.h>
 | 
			
		||||
      
 | 
			
		||||
#define KERNEL_DAG
 | 
			
		||||
template<> void 
 | 
			
		||||
WilsonKernels<WilsonImplD>::DiracOptAsmDhopSiteDag(StencilImpl &st,LebesgueOrder & lo,DoubledGaugeField &U,SiteHalfSpinor *buf,
 | 
			
		||||
						   int ss,int ssU,int Ls,int Ns,const FermionField &in, FermionField &out)
 | 
			
		||||
#include <qcd/action/fermion/WilsonKernelsAsmBody.h>
 | 
			
		||||
				    
 | 
			
		||||
#endif
 | 
			
		||||
#undef VMOVIDUP
 | 
			
		||||
#undef VMOVRDUP
 | 
			
		||||
#undef MAYBEPERM
 | 
			
		||||
#undef MULT_2SPIN
 | 
			
		||||
#undef FX 
 | 
			
		||||
#define FX(A) DWFASM_ ## A
 | 
			
		||||
#define MAYBEPERM(A,B) 
 | 
			
		||||
//#define VMOVIDUP(A,B,C)                                  VBCASTIDUPd(A,B,C)
 | 
			
		||||
//#define VMOVRDUP(A,B,C)                                  VBCASTRDUPd(A,B,C)
 | 
			
		||||
#define MULT_2SPIN(ptr,pf) MULT_ADDSUB_2SPIN_LS(ptr,pf)
 | 
			
		||||
				    
 | 
			
		||||
#undef KERNEL_DAG
 | 
			
		||||
template<> void 
 | 
			
		||||
WilsonKernels<DomainWallVec5dImplD>::DiracOptAsmDhopSite(StencilImpl &st,LebesgueOrder & lo,DoubledGaugeField &U, SiteHalfSpinor *buf,
 | 
			
		||||
							 int ss,int ssU,int Ls,int Ns,const FermionField &in, FermionField &out)
 | 
			
		||||
#include <qcd/action/fermion/WilsonKernelsAsmBody.h>
 | 
			
		||||
				    
 | 
			
		||||
#define KERNEL_DAG
 | 
			
		||||
template<> void 
 | 
			
		||||
WilsonKernels<DomainWallVec5dImplD>::DiracOptAsmDhopSiteDag(StencilImpl &st,LebesgueOrder & lo,DoubledGaugeField &U,SiteHalfSpinor *buf,
 | 
			
		||||
							    int ss,int ssU,int Ls,int Ns,const FermionField &in, FermionField &out)
 | 
			
		||||
#include <qcd/action/fermion/WilsonKernelsAsmBody.h>
 | 
			
		||||
	
 | 
			
		||||
#undef COMPLEX_TYPE
 | 
			
		||||
#undef signs
 | 
			
		||||
#undef VMOVRDUP
 | 
			
		||||
#undef MAYBEPERM
 | 
			
		||||
#undef MULT_2SPIN
 | 
			
		||||
#undef FX 
 | 
			
		||||
 | 
			
		||||
#endif //AVX512
 | 
			
		||||
 | 
			
		||||
#define INSTANTIATE_ASM(A)\
 | 
			
		||||
template void WilsonKernels<A>::DiracOptAsmDhopSite(StencilImpl &st,LebesgueOrder & lo,DoubledGaugeField &U, SiteHalfSpinor *buf,\
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,9 @@
 | 
			
		||||
  const uint64_t plocal =(uint64_t) & in._odata[0];
 | 
			
		||||
 | 
			
		||||
  //  vComplexF isigns[2] = { signs[0], signs[1] };
 | 
			
		||||
  vComplexF *isigns = &signs[0];
 | 
			
		||||
  //COMPLEX_TYPE is vComplexF of vComplexD depending 
 | 
			
		||||
  //on the chosen precision
 | 
			
		||||
  COMPLEX_TYPE *isigns = &signs[0];
 | 
			
		||||
 | 
			
		||||
  MASK_REGS;
 | 
			
		||||
  int nmax=U._grid->oSites();
 | 
			
		||||
 
 | 
			
		||||
@@ -116,7 +116,7 @@ class NerscHmcRunnerTemplate {
 | 
			
		||||
    NoSmearing<Gimpl> SmearingPolicy;
 | 
			
		||||
    typedef MinimumNorm2<GaugeField, NoSmearing<Gimpl>, RepresentationsPolicy >
 | 
			
		||||
        IntegratorType;  // change here to change the algorithm
 | 
			
		||||
    IntegratorParameters MDpar(20, 1.0);
 | 
			
		||||
    IntegratorParameters MDpar(40, 1.0);
 | 
			
		||||
    IntegratorType MDynamics(UGrid, MDpar, TheAction, SmearingPolicy);
 | 
			
		||||
 | 
			
		||||
    // Checkpoint strategy
 | 
			
		||||
 
 | 
			
		||||
@@ -39,8 +39,8 @@ namespace QCD{
 | 
			
		||||
//on the 5d (rb4d) checkerboarded lattices
 | 
			
		||||
////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
template<class vobj> 
 | 
			
		||||
void axpibg5x(Lattice<vobj> &z,const Lattice<vobj> &x,RealD a,RealD b)
 | 
			
		||||
template<class vobj,class Coeff>
 | 
			
		||||
void axpibg5x(Lattice<vobj> &z,const Lattice<vobj> &x,Coeff a,Coeff b)
 | 
			
		||||
{
 | 
			
		||||
  z.checkerboard = x.checkerboard;
 | 
			
		||||
  conformable(x,z);
 | 
			
		||||
@@ -57,8 +57,8 @@ PARALLEL_FOR_LOOP
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class vobj> 
 | 
			
		||||
void axpby_ssp(Lattice<vobj> &z, RealD a,const Lattice<vobj> &x,RealD b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
template<class vobj,class Coeff> 
 | 
			
		||||
void axpby_ssp(Lattice<vobj> &z, Coeff a,const Lattice<vobj> &x,Coeff b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
{
 | 
			
		||||
  z.checkerboard = x.checkerboard;
 | 
			
		||||
  conformable(x,y);
 | 
			
		||||
@@ -72,8 +72,8 @@ PARALLEL_FOR_LOOP
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class vobj> 
 | 
			
		||||
void ag5xpby_ssp(Lattice<vobj> &z,RealD a,const Lattice<vobj> &x,RealD b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
template<class vobj,class Coeff> 
 | 
			
		||||
void ag5xpby_ssp(Lattice<vobj> &z,Coeff a,const Lattice<vobj> &x,Coeff b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
{
 | 
			
		||||
  z.checkerboard = x.checkerboard;
 | 
			
		||||
  conformable(x,y);
 | 
			
		||||
@@ -90,8 +90,8 @@ PARALLEL_FOR_LOOP
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class vobj> 
 | 
			
		||||
void axpbg5y_ssp(Lattice<vobj> &z,RealD a,const Lattice<vobj> &x,RealD b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
template<class vobj,class Coeff> 
 | 
			
		||||
void axpbg5y_ssp(Lattice<vobj> &z,Coeff a,const Lattice<vobj> &x,Coeff b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
{
 | 
			
		||||
  z.checkerboard = x.checkerboard;
 | 
			
		||||
  conformable(x,y);
 | 
			
		||||
@@ -108,8 +108,8 @@ PARALLEL_FOR_LOOP
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class vobj> 
 | 
			
		||||
void ag5xpbg5y_ssp(Lattice<vobj> &z,RealD a,const Lattice<vobj> &x,RealD b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
template<class vobj,class Coeff> 
 | 
			
		||||
void ag5xpbg5y_ssp(Lattice<vobj> &z,Coeff a,const Lattice<vobj> &x,Coeff b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
{
 | 
			
		||||
  z.checkerboard = x.checkerboard;
 | 
			
		||||
  conformable(x,y);
 | 
			
		||||
@@ -127,8 +127,8 @@ PARALLEL_FOR_LOOP
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class vobj> 
 | 
			
		||||
void axpby_ssp_pminus(Lattice<vobj> &z,RealD a,const Lattice<vobj> &x,RealD b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
template<class vobj,class Coeff> 
 | 
			
		||||
void axpby_ssp_pminus(Lattice<vobj> &z,Coeff a,const Lattice<vobj> &x,Coeff b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
{
 | 
			
		||||
  z.checkerboard = x.checkerboard;
 | 
			
		||||
  conformable(x,y);
 | 
			
		||||
@@ -144,8 +144,8 @@ PARALLEL_FOR_LOOP
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class vobj> 
 | 
			
		||||
void axpby_ssp_pplus(Lattice<vobj> &z,RealD a,const Lattice<vobj> &x,RealD b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
template<class vobj,class Coeff> 
 | 
			
		||||
void axpby_ssp_pplus(Lattice<vobj> &z,Coeff a,const Lattice<vobj> &x,Coeff b,const Lattice<vobj> &y,int s,int sp)
 | 
			
		||||
{
 | 
			
		||||
  z.checkerboard = x.checkerboard;
 | 
			
		||||
  conformable(x,y);
 | 
			
		||||
 
 | 
			
		||||
@@ -674,6 +674,37 @@ class SU {
 | 
			
		||||
      out += la;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
/*
 | 
			
		||||
 add GaugeTrans
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
template<typename GaugeField,typename GaugeMat>
 | 
			
		||||
  static void GaugeTransform( GaugeField &Umu, GaugeMat &g){
 | 
			
		||||
    GridBase *grid = Umu._grid;
 | 
			
		||||
    conformable(grid,g._grid);
 | 
			
		||||
 | 
			
		||||
    GaugeMat U(grid);
 | 
			
		||||
    GaugeMat ag(grid); ag = adj(g);
 | 
			
		||||
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      U= PeekIndex<LorentzIndex>(Umu,mu);
 | 
			
		||||
      U = g*U*Cshift(ag, mu, 1);
 | 
			
		||||
      PokeIndex<LorentzIndex>(Umu,U,mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  template<typename GaugeMat>
 | 
			
		||||
    static void GaugeTransform( std::vector<GaugeMat> &U, GaugeMat &g){
 | 
			
		||||
    GridBase *grid = g._grid;
 | 
			
		||||
    GaugeMat ag(grid); ag = adj(g);
 | 
			
		||||
    for(int mu=0;mu<Nd;mu++){
 | 
			
		||||
      U[mu] = g*U[mu]*Cshift(ag, mu, 1);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  template<typename GaugeField,typename GaugeMat>
 | 
			
		||||
  static void RandomGaugeTransform(GridParallelRNG &pRNG, GaugeField &Umu, GaugeMat &g){
 | 
			
		||||
    LieRandomize(pRNG,g,1.0);
 | 
			
		||||
    GaugeTransform(Umu,g);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Projects the algebra components a lattice matrix (of dimension ncol*ncol -1 )
 | 
			
		||||
  // inverse operation: FundamentalLieAlgebraMatrix
 | 
			
		||||
@@ -702,23 +733,33 @@ class SU {
 | 
			
		||||
      PokeIndex<LorentzIndex>(out, Umu, mu);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  static void TepidConfiguration(GridParallelRNG &pRNG,
 | 
			
		||||
                                 LatticeGaugeField &out) {
 | 
			
		||||
    LatticeMatrix 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 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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  static void ColdConfiguration(GridParallelRNG &pRNG, LatticeGaugeField &out) {
 | 
			
		||||
    LatticeMatrix 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){
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void taProj(const LatticeMatrix &in, LatticeMatrix &out) {
 | 
			
		||||
  template<typename LatticeMatrixType>
 | 
			
		||||
  static void taProj( const LatticeMatrixType &in,  LatticeMatrixType &out){
 | 
			
		||||
    out = Ta(in);
 | 
			
		||||
  }
 | 
			
		||||
  template <typename LatticeMatrixType>
 | 
			
		||||
 
 | 
			
		||||
@@ -522,4 +522,4 @@ typedef WilsonLoops<PeriodicGimplR> SU3WilsonLoops;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -365,6 +365,18 @@ namespace Optimization {
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  struct Div{
 | 
			
		||||
    // Real float
 | 
			
		||||
    inline __m256 operator()(__m256 a, __m256 b){
 | 
			
		||||
      return _mm256_div_ps(a,b);
 | 
			
		||||
    }
 | 
			
		||||
    // Real double
 | 
			
		||||
    inline __m256d operator()(__m256d a, __m256d b){
 | 
			
		||||
      return _mm256_div_pd(a,b);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  struct Conj{
 | 
			
		||||
    // Complex single
 | 
			
		||||
    inline __m256 operator()(__m256 in){
 | 
			
		||||
@@ -437,14 +449,13 @@ namespace Optimization {
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#if defined (AVX2) || defined (AVXFMA4) 
 | 
			
		||||
#define _mm256_alignr_epi32(ret,a,b,n) ret=(__m256) _mm256_alignr_epi8((__m256i)a,(__m256i)b,(n*4)%16)
 | 
			
		||||
#define _mm256_alignr_epi64(ret,a,b,n) ret=(__m256d) _mm256_alignr_epi8((__m256i)a,(__m256i)b,(n*8)%16)
 | 
			
		||||
#if defined (AVX2)
 | 
			
		||||
#define _mm256_alignr_epi32_grid(ret,a,b,n) ret=(__m256)  _mm256_alignr_epi8((__m256i)a,(__m256i)b,(n*4)%16)
 | 
			
		||||
#define _mm256_alignr_epi64_grid(ret,a,b,n) ret=(__m256d) _mm256_alignr_epi8((__m256i)a,(__m256i)b,(n*8)%16)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined (AVX1) || defined (AVXFMA)
 | 
			
		||||
 | 
			
		||||
#define _mm256_alignr_epi32(ret,a,b,n) {	\
 | 
			
		||||
#if defined (AVX1) || defined (AVXFMA)  
 | 
			
		||||
#define _mm256_alignr_epi32_grid(ret,a,b,n) {	\
 | 
			
		||||
    __m128 aa, bb;				\
 | 
			
		||||
						\
 | 
			
		||||
    aa  = _mm256_extractf128_ps(a,1);		\
 | 
			
		||||
@@ -458,7 +469,7 @@ namespace Optimization {
 | 
			
		||||
    ret = _mm256_insertf128_ps(ret,aa,0);	\
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#define _mm256_alignr_epi64(ret,a,b,n) {	\
 | 
			
		||||
#define _mm256_alignr_epi64_grid(ret,a,b,n) {	\
 | 
			
		||||
    __m128d aa, bb;				\
 | 
			
		||||
						\
 | 
			
		||||
    aa  = _mm256_extractf128_pd(a,1);		\
 | 
			
		||||
@@ -474,19 +485,6 @@ namespace Optimization {
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    inline std::ostream & operator << (std::ostream& stream, const __m256 a)
 | 
			
		||||
    {
 | 
			
		||||
      const float *p=(const float *)&a;
 | 
			
		||||
      stream<< "{"<<p[0]<<","<<p[1]<<","<<p[2]<<","<<p[3]<<","<<p[4]<<","<<p[5]<<","<<p[6]<<","<<p[7]<<"}";
 | 
			
		||||
      return stream;
 | 
			
		||||
    };
 | 
			
		||||
    inline std::ostream & operator<< (std::ostream& stream, const __m256d a)
 | 
			
		||||
    {
 | 
			
		||||
      const double *p=(const double *)&a;
 | 
			
		||||
      stream<< "{"<<p[0]<<","<<p[1]<<","<<p[2]<<","<<p[3]<<"}";
 | 
			
		||||
      return stream;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  struct Rotate{
 | 
			
		||||
 | 
			
		||||
    static inline __m256 rotate(__m256 in,int n){ 
 | 
			
		||||
@@ -518,11 +516,10 @@ namespace Optimization {
 | 
			
		||||
      __m256 tmp = Permute::Permute0(in);
 | 
			
		||||
      __m256 ret;
 | 
			
		||||
      if ( n > 3 ) { 
 | 
			
		||||
	_mm256_alignr_epi32(ret,in,tmp,n);  
 | 
			
		||||
	_mm256_alignr_epi32_grid(ret,in,tmp,n);  
 | 
			
		||||
      } else {
 | 
			
		||||
        _mm256_alignr_epi32(ret,tmp,in,n);          
 | 
			
		||||
        _mm256_alignr_epi32_grid(ret,tmp,in,n);          
 | 
			
		||||
      }
 | 
			
		||||
      //      std::cout << " align epi32 n=" <<n<<" in "<<tmp<<in<<" -> "<< ret <<std::endl;
 | 
			
		||||
      return ret;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -531,18 +528,15 @@ namespace Optimization {
 | 
			
		||||
      __m256d tmp = Permute::Permute0(in);
 | 
			
		||||
      __m256d ret;
 | 
			
		||||
      if ( n > 1 ) {
 | 
			
		||||
	_mm256_alignr_epi64(ret,in,tmp,n);          
 | 
			
		||||
	_mm256_alignr_epi64_grid(ret,in,tmp,n);          
 | 
			
		||||
      } else {
 | 
			
		||||
        _mm256_alignr_epi64(ret,tmp,in,n);          
 | 
			
		||||
        _mm256_alignr_epi64_grid(ret,tmp,in,n);          
 | 
			
		||||
      }
 | 
			
		||||
      //      std::cout << " align epi64 n=" <<n<<" in "<<tmp<<in<<" -> "<< ret <<std::endl;
 | 
			
		||||
      return ret;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //Complex float Reduce
 | 
			
		||||
  template<>
 | 
			
		||||
    inline Grid::ComplexF Reduce<Grid::ComplexF, __m256>::operator()(__m256 in){
 | 
			
		||||
@@ -631,6 +625,7 @@ namespace Optimization {
 | 
			
		||||
  // Arithmetic operations
 | 
			
		||||
  typedef Optimization::Sum         SumSIMD;
 | 
			
		||||
  typedef Optimization::Sub         SubSIMD;
 | 
			
		||||
  typedef Optimization::Div         DivSIMD;
 | 
			
		||||
  typedef Optimization::Mult        MultSIMD;
 | 
			
		||||
  typedef Optimization::MultComplex MultComplexSIMD;
 | 
			
		||||
  typedef Optimization::Conj        ConjSIMD;
 | 
			
		||||
 
 | 
			
		||||
@@ -240,6 +240,17 @@ namespace Optimization {
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  struct Div{
 | 
			
		||||
    // Real float
 | 
			
		||||
    inline __m512 operator()(__m512 a, __m512 b){
 | 
			
		||||
      return _mm512_div_ps(a,b);
 | 
			
		||||
    }
 | 
			
		||||
    // Real double
 | 
			
		||||
    inline __m512d operator()(__m512d a, __m512d b){
 | 
			
		||||
      return _mm512_div_pd(a,b);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  struct Conj{
 | 
			
		||||
    // Complex single
 | 
			
		||||
@@ -371,14 +382,8 @@ namespace Optimization {
 | 
			
		||||
  // Some Template specialization
 | 
			
		||||
 | 
			
		||||
  // Hack for CLANG until mm512_reduce_add_ps etc... are implemented in GCC and Clang releases
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
#define GNU_CLANG_COMPILER 
 | 
			
		||||
#ifdef GNU_CLANG_COMPILER
 | 
			
		||||
=======
 | 
			
		||||
 | 
			
		||||
#ifndef __INTEL_COMPILER
 | 
			
		||||
#warning "Slow reduction due to incomplete reduce intrinsics"
 | 
			
		||||
>>>>>>> develop
 | 
			
		||||
  //Complex float Reduce
 | 
			
		||||
  template<>
 | 
			
		||||
    inline Grid::ComplexF Reduce<Grid::ComplexF, __m512>::operator()(__m512 in){
 | 
			
		||||
@@ -503,6 +508,7 @@ namespace Optimization {
 | 
			
		||||
  typedef Optimization::Sum         SumSIMD;
 | 
			
		||||
  typedef Optimization::Sub         SubSIMD;
 | 
			
		||||
  typedef Optimization::Mult        MultSIMD;
 | 
			
		||||
  typedef Optimization::Div         DivSIMD;
 | 
			
		||||
  typedef Optimization::MultComplex MultComplexSIMD;
 | 
			
		||||
  typedef Optimization::Conj        ConjSIMD;
 | 
			
		||||
  typedef Optimization::TimesMinusI TimesMinusISIMD;
 | 
			
		||||
 
 | 
			
		||||
@@ -244,6 +244,17 @@ namespace Optimization {
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  struct Div{
 | 
			
		||||
    // Real float
 | 
			
		||||
    inline __m512 operator()(__m512 a, __m512 b){
 | 
			
		||||
      return _mm512_div_ps(a,b);
 | 
			
		||||
    }
 | 
			
		||||
    // Real double
 | 
			
		||||
    inline __m512d operator()(__m512d a, __m512d b){
 | 
			
		||||
      return _mm512_div_pd(a,b);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  struct Conj{
 | 
			
		||||
    // Complex single
 | 
			
		||||
@@ -437,6 +448,7 @@ namespace Optimization {
 | 
			
		||||
  // Arithmetic operations
 | 
			
		||||
  typedef Optimization::Sum         SumSIMD;
 | 
			
		||||
  typedef Optimization::Sub         SubSIMD;
 | 
			
		||||
  typedef Optimization::Div         DivSIMD;
 | 
			
		||||
  typedef Optimization::Mult        MultSIMD;
 | 
			
		||||
  typedef Optimization::MultComplex MultComplexSIMD;
 | 
			
		||||
  typedef Optimization::Conj        ConjSIMD;
 | 
			
		||||
 
 | 
			
		||||
@@ -224,6 +224,18 @@ namespace Optimization {
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  struct Div{
 | 
			
		||||
    // Real float
 | 
			
		||||
    inline __m128 operator()(__m128 a, __m128 b){
 | 
			
		||||
      return _mm_div_ps(a,b);
 | 
			
		||||
    }
 | 
			
		||||
    // Real double
 | 
			
		||||
    inline __m128d operator()(__m128d a, __m128d b){
 | 
			
		||||
      return _mm_div_pd(a,b);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  struct Conj{
 | 
			
		||||
    // Complex single
 | 
			
		||||
    inline __m128 operator()(__m128 in){
 | 
			
		||||
@@ -372,6 +384,8 @@ namespace Optimization {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Here assign types 
 | 
			
		||||
 | 
			
		||||
@@ -398,6 +412,7 @@ namespace Optimization {
 | 
			
		||||
  // Arithmetic operations
 | 
			
		||||
  typedef Optimization::Sum         SumSIMD;
 | 
			
		||||
  typedef Optimization::Sub         SubSIMD;
 | 
			
		||||
  typedef Optimization::Div         DivSIMD;
 | 
			
		||||
  typedef Optimization::Mult        MultSIMD;
 | 
			
		||||
  typedef Optimization::MultComplex MultComplexSIMD;
 | 
			
		||||
  typedef Optimization::Conj        ConjSIMD;
 | 
			
		||||
 
 | 
			
		||||
@@ -77,38 +77,24 @@ struct RealPart<std::complex<T> > {
 | 
			
		||||
//////////////////////////////////////
 | 
			
		||||
// demote a vector to real type
 | 
			
		||||
//////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
// type alias used to simplify the syntax of std::enable_if
 | 
			
		||||
template <typename T>
 | 
			
		||||
using Invoke = typename T::type;
 | 
			
		||||
template <typename Condition, typename ReturnType>
 | 
			
		||||
using EnableIf = Invoke<std::enable_if<Condition::value, ReturnType> >;
 | 
			
		||||
template <typename Condition, typename ReturnType>
 | 
			
		||||
using NotEnableIf = Invoke<std::enable_if<!Condition::value, ReturnType> >;
 | 
			
		||||
template <typename T> using Invoke = typename T::type;
 | 
			
		||||
template <typename Condition, typename ReturnType> using EnableIf = Invoke<std::enable_if<Condition::value, ReturnType> >;
 | 
			
		||||
template <typename Condition, typename ReturnType> using NotEnableIf = Invoke<std::enable_if<!Condition::value, ReturnType> >;
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////
 | 
			
		||||
// Check for complexity with type traits
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct is_complex : public std::false_type {};
 | 
			
		||||
template <>
 | 
			
		||||
struct is_complex<std::complex<double> > : public std::true_type {};
 | 
			
		||||
template <>
 | 
			
		||||
struct is_complex<std::complex<float> > : public std::true_type {};
 | 
			
		||||
template <typename T> struct is_complex : public std::false_type {};
 | 
			
		||||
template <> struct is_complex<std::complex<double> > : public std::true_type {};
 | 
			
		||||
template <> struct is_complex<std::complex<float> > : public std::true_type {};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using IfReal = Invoke<std::enable_if<std::is_floating_point<T>::value, int> >;
 | 
			
		||||
template <typename T>
 | 
			
		||||
using IfComplex = Invoke<std::enable_if<is_complex<T>::value, int> >;
 | 
			
		||||
template <typename T>
 | 
			
		||||
using IfInteger = Invoke<std::enable_if<std::is_integral<T>::value, int> >;
 | 
			
		||||
template <typename T> using IfReal       = Invoke<std::enable_if<std::is_floating_point<T>::value, int> >;
 | 
			
		||||
template <typename T> using IfComplex    = Invoke<std::enable_if<is_complex<T>::value, int> >;
 | 
			
		||||
template <typename T> using IfInteger    = Invoke<std::enable_if<std::is_integral<T>::value, int> >;
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using IfNotReal =
 | 
			
		||||
    Invoke<std::enable_if<!std::is_floating_point<T>::value, int> >;
 | 
			
		||||
template <typename T>
 | 
			
		||||
using IfNotComplex = Invoke<std::enable_if<!is_complex<T>::value, int> >;
 | 
			
		||||
template <typename T>
 | 
			
		||||
using IfNotInteger = Invoke<std::enable_if<!std::is_integral<T>::value, int> >;
 | 
			
		||||
template <typename T> using IfNotReal    = Invoke<std::enable_if<!std::is_floating_point<T>::value, int> >;
 | 
			
		||||
template <typename T> using IfNotComplex = Invoke<std::enable_if<!is_complex<T>::value, int> >;
 | 
			
		||||
template <typename T> using IfNotInteger = Invoke<std::enable_if<!std::is_integral<T>::value, int> >;
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////
 | 
			
		||||
// Define the operation templates functors
 | 
			
		||||
@@ -285,6 +271,20 @@ class Grid_simd {
 | 
			
		||||
    return a * b;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //////////////////////////////////
 | 
			
		||||
  // Divides
 | 
			
		||||
  //////////////////////////////////
 | 
			
		||||
  friend inline Grid_simd operator/(const Scalar_type &a, Grid_simd b) {
 | 
			
		||||
    Grid_simd va;
 | 
			
		||||
    vsplat(va, a);
 | 
			
		||||
    return va / b;
 | 
			
		||||
  }
 | 
			
		||||
  friend inline Grid_simd operator/(Grid_simd b, const Scalar_type &a) {
 | 
			
		||||
    Grid_simd va;
 | 
			
		||||
    vsplat(va, a);
 | 
			
		||||
    return b / a;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ///////////////////////
 | 
			
		||||
  // Unary negation
 | 
			
		||||
  ///////////////////////
 | 
			
		||||
@@ -428,7 +428,6 @@ inline void rotate(Grid_simd<S,V> &ret,Grid_simd<S,V> b,int nrot)
 | 
			
		||||
  ret.v = Optimization::Rotate::rotate(b.v,2*nrot);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <class S, class V> 
 | 
			
		||||
inline void vbroadcast(Grid_simd<S,V> &ret,const Grid_simd<S,V> &src,int lane){
 | 
			
		||||
  S* typepun =(S*) &src;
 | 
			
		||||
@@ -512,7 +511,6 @@ template <class S, class V, IfInteger<S> = 0>
 | 
			
		||||
inline void vfalse(Grid_simd<S, V> &ret) {
 | 
			
		||||
  vsplat(ret, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class S, class V>
 | 
			
		||||
inline void zeroit(Grid_simd<S, V> &z) {
 | 
			
		||||
  vzero(z);
 | 
			
		||||
@@ -530,7 +528,6 @@ inline void vstream(Grid_simd<S, V> &out, const Grid_simd<S, V> &in) {
 | 
			
		||||
  typedef typename S::value_type T;
 | 
			
		||||
  binary<void>((T *)&out.v, in.v, VstreamSIMD());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class S, class V, IfInteger<S> = 0>
 | 
			
		||||
inline void vstream(Grid_simd<S, V> &out, const Grid_simd<S, V> &in) {
 | 
			
		||||
  out = in;
 | 
			
		||||
@@ -569,6 +566,34 @@ inline Grid_simd<S, V> operator*(Grid_simd<S, V> a, Grid_simd<S, V> b) {
 | 
			
		||||
  return ret;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Distinguish between complex types and others
 | 
			
		||||
template <class S, class V, IfComplex<S> = 0>
 | 
			
		||||
inline Grid_simd<S, V> operator/(Grid_simd<S, V> a, Grid_simd<S, V> b) {
 | 
			
		||||
  typedef Grid_simd<S, V> simd;
 | 
			
		||||
 | 
			
		||||
  simd ret;
 | 
			
		||||
  simd den;
 | 
			
		||||
  typename simd::conv_t conv;
 | 
			
		||||
 | 
			
		||||
  ret = a * conjugate(b) ;
 | 
			
		||||
  den = b * conjugate(b) ;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  auto real_den = toReal(den);
 | 
			
		||||
 | 
			
		||||
  ret.v=binary<V>(ret.v, real_den.v, DivSIMD());
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Real/Integer types
 | 
			
		||||
template <class S, class V, IfNotComplex<S> = 0>
 | 
			
		||||
inline Grid_simd<S, V> operator/(Grid_simd<S, V> a, Grid_simd<S, V> b) {
 | 
			
		||||
  Grid_simd<S, V> ret;
 | 
			
		||||
  ret.v = binary<V>(a.v, b.v, DivSIMD());
 | 
			
		||||
  return ret;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////
 | 
			
		||||
// Conjugate
 | 
			
		||||
///////////////////////
 | 
			
		||||
@@ -582,7 +607,6 @@ template <class S, class V, IfNotComplex<S> = 0>
 | 
			
		||||
inline Grid_simd<S, V> conjugate(const Grid_simd<S, V> &in) {
 | 
			
		||||
  return in;  // for real objects
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Suppress adj for integer types... // odd; why conjugate above but not adj??
 | 
			
		||||
template <class S, class V, IfNotInteger<S> = 0>
 | 
			
		||||
inline Grid_simd<S, V> adj(const Grid_simd<S, V> &in) {
 | 
			
		||||
@@ -596,14 +620,12 @@ template <class S, class V, IfComplex<S> = 0>
 | 
			
		||||
inline void timesMinusI(Grid_simd<S, V> &ret, const Grid_simd<S, V> &in) {
 | 
			
		||||
  ret.v = binary<V>(in.v, ret.v, TimesMinusISIMD());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class S, class V, IfComplex<S> = 0>
 | 
			
		||||
inline Grid_simd<S, V> timesMinusI(const Grid_simd<S, V> &in) {
 | 
			
		||||
  Grid_simd<S, V> ret;
 | 
			
		||||
  timesMinusI(ret, in);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class S, class V, IfNotComplex<S> = 0>
 | 
			
		||||
inline Grid_simd<S, V> timesMinusI(const Grid_simd<S, V> &in) {
 | 
			
		||||
  return in;
 | 
			
		||||
@@ -616,14 +638,12 @@ template <class S, class V, IfComplex<S> = 0>
 | 
			
		||||
inline void timesI(Grid_simd<S, V> &ret, const Grid_simd<S, V> &in) {
 | 
			
		||||
  ret.v = binary<V>(in.v, ret.v, TimesISIMD());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class S, class V, IfComplex<S> = 0>
 | 
			
		||||
inline Grid_simd<S, V> timesI(const Grid_simd<S, V> &in) {
 | 
			
		||||
  Grid_simd<S, V> ret;
 | 
			
		||||
  timesI(ret, in);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class S, class V, IfNotComplex<S> = 0>
 | 
			
		||||
inline Grid_simd<S, V> timesI(const Grid_simd<S, V> &in) {
 | 
			
		||||
  return in;
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
namespace Grid {
 | 
			
		||||
 | 
			
		||||
int LebesgueOrder::UseLebesgueOrder;
 | 
			
		||||
std::vector<int> LebesgueOrder::Block({2,2,2,2});
 | 
			
		||||
std::vector<int> LebesgueOrder::Block({8,2,2,2});
 | 
			
		||||
 | 
			
		||||
LebesgueOrder::IndexInteger LebesgueOrder::alignup(IndexInteger n){
 | 
			
		||||
  n--;           // 1000 0011 --> 1000 0010
 | 
			
		||||
 
 | 
			
		||||
@@ -126,6 +126,36 @@ iVector<rtype,N> operator * (const iVector<mtype,N>& lhs,const iScalar<vtype>& r
 | 
			
		||||
    mult(&ret,&lhs,&rhs);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////
 | 
			
		||||
// Divide by scalar
 | 
			
		||||
//////////////////////////////////////////////////////////////////
 | 
			
		||||
template<class rtype,class vtype> strong_inline
 | 
			
		||||
iScalar<rtype> operator / (const iScalar<rtype>& lhs,const iScalar<vtype>& rhs)
 | 
			
		||||
{
 | 
			
		||||
    iScalar<rtype> ret;
 | 
			
		||||
    ret._internal = lhs._internal/rhs._internal;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
template<class rtype,class vtype,int N> strong_inline
 | 
			
		||||
iVector<rtype,N> operator / (const iVector<rtype,N>& lhs,const iScalar<vtype>& rhs)
 | 
			
		||||
{
 | 
			
		||||
    iVector<rtype,N> ret;
 | 
			
		||||
    for(int i=0;i<N;i++){
 | 
			
		||||
      ret._internal[i] = lhs._internal[i]/rhs._internal;
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
template<class rtype,class vtype,int N> strong_inline
 | 
			
		||||
iMatrix<rtype,N> operator / (const iMatrix<rtype,N>& lhs,const iScalar<vtype>& rhs)
 | 
			
		||||
{
 | 
			
		||||
    iMatrix<rtype,N> ret;
 | 
			
		||||
    for(int i=0;i<N;i++){
 | 
			
		||||
    for(int j=0;j<N;j++){
 | 
			
		||||
      ret._internal[i][j] = lhs._internal[i][j]/rhs._internal;
 | 
			
		||||
    }}
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
    //////////////////////////////////////////////////////////////////
 | 
			
		||||
    // Glue operators to mult routines. Must resolve return type cleverly from typeof(internal)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user