From 04a1ac3a768825708446ab50e4df2e17eef3a48f Mon Sep 17 00:00:00 2001 From: Peter Boyle Date: Fri, 25 Aug 2023 17:37:38 -0400 Subject: [PATCH] First cut for non-local coarsening --- Grid/algorithms/GeneralCoarsenedMatrix.h | 431 +++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 Grid/algorithms/GeneralCoarsenedMatrix.h diff --git a/Grid/algorithms/GeneralCoarsenedMatrix.h b/Grid/algorithms/GeneralCoarsenedMatrix.h new file mode 100644 index 00000000..b8527cfb --- /dev/null +++ b/Grid/algorithms/GeneralCoarsenedMatrix.h @@ -0,0 +1,431 @@ +/************************************************************************************* + + Grid physics library, www.github.com/paboyle/Grid + + Source file: ./lib/algorithms/GeneralCoarsenedMatrix.h + + Copyright (C) 2015 + +Author: Peter Boyle + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + See the full license in the file "LICENSE" in the top level distribution directory +*************************************************************************************/ +/* END LEGAL */ +#pragma once + +#include // needed for Dagger(Yes|No), Inverse(Yes|No) + +#include +#include + +NAMESPACE_BEGIN(Grid); + +template void gpermute(vobj & inout,int perm){ + vobj tmp=inout; + if (perm & 0x1 ) { permute(inout,tmp,0); tmp=inout;} + if (perm & 0x2 ) { permute(inout,tmp,1); tmp=inout;} + if (perm & 0x4 ) { permute(inout,tmp,2); tmp=inout;} + if (perm & 0x8 ) { permute(inout,tmp,3); tmp=inout;} +} + +///////////////////////////////////////////////////////////////// +// Reuse Aggregation class from CoarsenedMatrix for now +// Might think about *smoothed* Aggregation +// Equivalent of Geometry class in cartesian case +///////////////////////////////////////////////////////////////// +class NonLocalStencilGeometry { +public: + int depth; + int npoint; + std::vector shifts; + virtual void BuildShifts(void) { assert(0); } ; + int Depth(void){return depth;}; + NonLocalStencilGeometry(int _depth) : depth(_depth) + { + }; + virtual ~NonLocalStencilGeometry() {}; +}; +// Need to worry about red-black now +class NextToNearestStencilGeometry4D : public NonLocalStencilGeometry { +public: + NextToNearestStencilGeometry4D(void) : NonLocalStencilGeometry(2) + { + this->BuildShifts(); + }; + virtual ~NextToNearestStencilGeometry4D() {}; + virtual void BuildShifts(void) + { + this->shifts.resize(0); + // Like HDCG: 81 point stencil including self connection + this->shifts.push_back(Coordinate({0,0,0,0})); + // +-x, +-y, +-z, +-t : 8 + for(int s=-1;s<=1;s+=2){ + this->shifts.push_back(Coordinate({s,0,0,0})); + this->shifts.push_back(Coordinate({0,s,0,0})); + this->shifts.push_back(Coordinate({0,0,s,0})); + this->shifts.push_back(Coordinate({0,0,0,s})); + } + // +-x+-y, +-x+-z, +-x+-t, +-y+-z, +-y+-t, +-z+-t : 24 + for(int s1=-1;s1<=1;s1+=2){ + for(int s2=-1;s2<=1;s2+=2){ + this->shifts.push_back(Coordinate({s1,s2,0,0})); + this->shifts.push_back(Coordinate({s1,0,s2,0})); + this->shifts.push_back(Coordinate({s1,0,0,s2})); + this->shifts.push_back(Coordinate({0,s1,s2,0})); + this->shifts.push_back(Coordinate({0,s1,0,s2})); + this->shifts.push_back(Coordinate({0,0,s1,s2})); + }} + this->npoint = this->shifts.size(); + } +}; +// Need to worry about red-black now +class NextToNextToNextToNearestStencilGeometry4D : public NonLocalStencilGeometry { +public: + NextToNextToNextToNearestStencilGeometry4D(void) : NonLocalStencilGeometry(4) + { + this->BuildShifts(); + }; + virtual ~NextToNextToNextToNearestStencilGeometry4D() {} + virtual void BuildShifts(void) + { + this->shifts.resize(0); + // Like HDCG: 81 point stencil including self connection + this->shifts.push_back(Coordinate({0,0,0,0})); + // +-x, +-y, +-z, +-t : 8 + for(int s=-1;s<=1;s+=2){ + this->shifts.push_back(Coordinate({s,0,0,0})); + this->shifts.push_back(Coordinate({0,s,0,0})); + this->shifts.push_back(Coordinate({0,0,s,0})); + this->shifts.push_back(Coordinate({0,0,0,s})); + } + // +-x+-y, +-x+-z, +-x+-t, +-y+-z, +-y+-t, +-z+-t : 24 + for(int s1=-1;s1<=1;s1+=2){ + for(int s2=-1;s2<=1;s2+=2){ + this->shifts.push_back(Coordinate({s1,s2,0,0})); + this->shifts.push_back(Coordinate({s1,0,s2,0})); + this->shifts.push_back(Coordinate({s1,0,0,s2})); + this->shifts.push_back(Coordinate({0,s1,s2,0})); + this->shifts.push_back(Coordinate({0,s1,0,s2})); + this->shifts.push_back(Coordinate({0,0,s1,s2})); + }} + // +-x+-y+-z, +-x+-y+-z, +-x+-y+-z, + for(int s1=-1;s1<=1;s1+=2){ + for(int s2=-1;s2<=1;s2+=2){ + for(int s3=-1;s3<=1;s3+=2){ + this->shifts.push_back(Coordinate({s1,s2,s3,0})); // 8x4 = 32 + this->shifts.push_back(Coordinate({s1,s2,0,s3})); + this->shifts.push_back(Coordinate({s1,0,s2,s3})); + this->shifts.push_back(Coordinate({0,s1,s2,s3})); + }}} + for(int s1=-1;s1<=1;s1+=2){ + for(int s2=-1;s2<=1;s2+=2){ + for(int s3=-1;s3<=1;s3+=2){ + for(int s4=-1;s4<=1;s4+=2){ + this->shifts.push_back(Coordinate({s1,s2,s3,s4})); // 16 + }}}} + this->npoint = this->shifts.size(); + } +}; +class NextToNearestStencilGeometry5D : public NonLocalStencilGeometry { +public: + NextToNearestStencilGeometry5D(void) : NonLocalStencilGeometry(2) + { + this->BuildShifts(); + }; + virtual ~NextToNearestStencilGeometry5D() {}; + virtual void BuildShifts(void) + { + this->shifts.resize(0); + // Like HDCG: 81 point stencil including self connection + this->shifts.push_back(Coordinate({0,0,0,0,0})); + // +-x, +-y, +-z, +-t : 8 + for(int s=-1;s<=1;s+=2){ + this->shifts.push_back(Coordinate({0,s,0,0,0})); + this->shifts.push_back(Coordinate({0,0,s,0,0})); + this->shifts.push_back(Coordinate({0,0,0,s,0})); + this->shifts.push_back(Coordinate({0,0,0,0,s})); + } + // +-x+-y, +-x+-z, +-x+-t, +-y+-z, +-y+-t, +-z+-t : 24 + for(int s1=-1;s1<=1;s1+=2){ + for(int s2=-1;s2<=1;s2+=2){ + this->shifts.push_back(Coordinate({0,s1,s2,0,0})); + this->shifts.push_back(Coordinate({0,s1,0,s2,0})); + this->shifts.push_back(Coordinate({0,s1,0,0,s2})); + this->shifts.push_back(Coordinate({0,0,s1,s2,0})); + this->shifts.push_back(Coordinate({0,0,s1,0,s2})); + this->shifts.push_back(Coordinate({0,0,0,s1,s2})); + }} + this->npoint = this->shifts.size(); + } +}; +// Need to worry about red-black now +class NextToNextToNextToNearestStencilGeometry5D : public NonLocalStencilGeometry { +public: + NextToNextToNextToNearestStencilGeometry5D(void) : NonLocalStencilGeometry(4) + { + this->BuildShifts(); + }; + virtual ~NextToNextToNextToNearestStencilGeometry5D() {} + virtual void BuildShifts(void) + { + this->shifts.resize(0); + // Like HDCG: 81 point stencil including self connection + this->shifts.push_back(Coordinate({0,0,0,0,0})); + // +-x, +-y, +-z, +-t : 8 + for(int s=-1;s<=1;s+=2){ + this->shifts.push_back(Coordinate({0,s,0,0,0})); + this->shifts.push_back(Coordinate({0,0,s,0,0})); + this->shifts.push_back(Coordinate({0,0,0,s,0})); + this->shifts.push_back(Coordinate({0,0,0,0,s})); + } + // +-x+-y, +-x+-z, +-x+-t, +-y+-z, +-y+-t, +-z+-t : 24 + for(int s1=-1;s1<=1;s1+=2){ + for(int s2=-1;s2<=1;s2+=2){ + this->shifts.push_back(Coordinate({0,s1,s2,0,0})); + this->shifts.push_back(Coordinate({0,s1,0,s2,0})); + this->shifts.push_back(Coordinate({0,s1,0,0,s2})); + this->shifts.push_back(Coordinate({0,0,s1,s2,0})); + this->shifts.push_back(Coordinate({0,0,s1,0,s2})); + this->shifts.push_back(Coordinate({0,0,0,s1,s2})); + }} + // +-x+-y+-z, +-x+-y+-z, +-x+-y+-z, + for(int s1=-1;s1<=1;s1+=2){ + for(int s2=-1;s2<=1;s2+=2){ + for(int s3=-1;s3<=1;s3+=2){ + this->shifts.push_back(Coordinate({0,s1,s2,s3,0})); // 8x4 = 32 + this->shifts.push_back(Coordinate({0,s1,s2,0,s3})); + this->shifts.push_back(Coordinate({0,s1,0,s2,s3})); + this->shifts.push_back(Coordinate({0,0,s1,s2,s3})); + }}} + for(int s1=-1;s1<=1;s1+=2){ + for(int s2=-1;s2<=1;s2+=2){ + for(int s3=-1;s3<=1;s3+=2){ + for(int s4=-1;s4<=1;s4+=2){ + this->shifts.push_back(Coordinate({0,s1,s2,s3,s4})); // 16 + }}}} + this->npoint = this->shifts.size(); + } +}; + +// Fine Object == (per site) type of fine field +// nbasis == number of deflation vectors +template +class GeneralCoarsenedMatrix : public SparseMatrixBase > > { +public: + + typedef iVector siteVector; + typedef Lattice CoarseComplexField; + typedef Lattice CoarseVector; + typedef Lattice > CoarseMatrix; + typedef iMatrix Cobj; + typedef Lattice< CComplex > CoarseScalar; // used for inner products on fine field + typedef Lattice FineField; + typedef CoarseVector Field; + //////////////////// + // Data members + //////////////////// + int hermitian; + GridCartesian * _FineGrid; + GridCartesian * _CoarseGrid; + NonLocalStencilGeometry &geom; + PaddedCell Cell; + GeneralLocalStencil Stencil; + + std::vector _A; + std::vector _Adag; + + /////////////////////// + // Interface + /////////////////////// + GridCartesian * Grid(void) { return _FineGrid; }; // this is all the linalg routines need to know + GridCartesian * FineGrid(void) { return _FineGrid; }; // this is all the linalg routines need to know + GridCartesian * CoarseGrid(void) { return _CoarseGrid; }; // this is all the linalg routines need to know + + GeneralCoarsenedMatrix(NonLocalStencilGeometry &_geom,GridCartesian *FineGrid, GridCartesian * CoarseGrid) + : geom(_geom), + _FineGrid(FineGrid), + _CoarseGrid(CoarseGrid), + hermitian(1), + Cell(_geom.Depth(),_CoarseGrid), + Stencil(Cell.grids.back(),geom.shifts) + { + _A.resize(geom.npoint,CoarseGrid); + _Adag.resize(geom.npoint,CoarseGrid); + } + void M (const CoarseVector &in, CoarseVector &out) + { + Mult(_A,in,out); + } + void Mdag (const CoarseVector &in, CoarseVector &out) + { + Mult(_Adag,in,out); + } + void Mult (std::vector &A,const CoarseVector &in, CoarseVector &out) + { + conformable(CoarseGrid(),in.Grid()); + conformable(in.Grid(),out.Grid()); + out.Checkerboard() = in.Checkerboard(); + CoarseVector tin=in; + std::cout << "Calling Exchange"< Aview; + + Vector AcceleratorViewContainer; + + for(int p=0;poSites(); + + for(int point=0;point_offset; + + // gpermute etc.. + nbr = in_v[o]; + assert( o< osites); + gpermute(nbr,SE->_permute); + + for(int bb=0;bb > &linop, + Aggregation & Subspace) + { + // Create a random + GridCartesian *grid = FineGrid(); + FineField MbV(grid); + FineField tmp(grid); + FineField f_src(grid); + FineField f_res(grid); + FineField f_ref(grid); + CoarseVector c_src(CoarseGrid()); + CoarseVector c_res(CoarseGrid()); + CoarseVector coarseInner(CoarseGrid()); + GridParallelRNG RNG(CoarseGrid()); RNG.SeedUniqueString(std::string("Coarse RNG")); + random(RNG,c_src); + blockPromote(c_src,f_src,Subspace.subspace); + linop.op(f_src,f_ref); + this->Mult (_A,c_src,c_res); + blockPromote(c_res,f_res,Subspace.subspace); + std::cout << " GeneralCoarsenedMatrix comparison res "< > &linop, + Aggregation & Subspace) + { + std::cout << GridLogMessage<< "CoarsenMatrix "<< std::endl; + GridCartesian *grid = FineGrid(); + // Orthogonalise the subblocks over the basis + CoarseScalar InnerProd(CoarseGrid()); + for(int b=0;bgSites() ;bidx++){ + Coordinate bcoor; + CoarseGrid()->GlobalIndexToGlobalCoor(bidx,bcoor); + std::cout << GridLogMessage<< "CoarsenMatrix block "<< bcoor << std::endl; + for(int b=0;bGlobalDimensions()[mu]; + scoor[mu] = (bcoor[mu] - geom.shifts[p][mu] + L) % L; // Modulo arithmetic + } + auto ip = peekSite(coarseInner,scoor); + std::cout << "A["< &out){assert(0);}; +}; + +NAMESPACE_END(Grid);