/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/algorithms/iterative/BlockConjugateGradient.h Copyright (C) 2017 Author: Azusa Yamaguchi 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 */ #ifndef GRID_BLOCK_CONJUGATE_GRADIENT_H #define GRID_BLOCK_CONJUGATE_GRADIENT_H #include namespace Grid { GridBase *makeSubSliceGrid(const GridBase *BlockSolverGrid,int Orthog) { int NN = BlockSolverGrid->_ndimension; int nsimd = BlockSolverGrid->Nsimd(); std::vector latt_phys(0); std::vector simd_phys(0); std::vector mpi_phys(0); for(int d=0;d_fdimensions[d]); simd_phys.push_back(BlockSolverGrid->_simd_layout[d]); mpi_phys.push_back(BlockSolverGrid->_processors[d]); } } return (GridBase *)new GridCartesian(latt_phys,simd_phys,mpi_phys); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Need to move sliceInnerProduct, sliceAxpy, sliceNorm etc... into lattice sector along with sliceSum ////////////////////////////////////////////////////////////////////////////////////////////////////////////// template static void sliceMaddMatrix (Lattice &R,Eigen::MatrixXcd &aa,const Lattice &X,const Lattice &Y,int Orthog,RealD scale=1.0) { typedef typename vobj::scalar_object sobj; typedef typename vobj::scalar_type scalar_type; typedef typename vobj::vector_type vector_type; int Nblock = X._grid->GlobalDimensions()[Orthog]; GridBase *FullGrid = X._grid; GridBase *SliceGrid = makeSubSliceGrid(FullGrid,Orthog); Lattice Xslice(SliceGrid); Lattice Rslice(SliceGrid); // If we based this on Cshift it would work for spread out // but it would be even slower for(int i=0;i static void sliceInnerProductMatrix( Eigen::MatrixXcd &mat, const Lattice &lhs,const Lattice &rhs,int Orthog) { typedef typename vobj::scalar_object sobj; typedef typename vobj::scalar_type scalar_type; typedef typename vobj::vector_type vector_type; GridBase *FullGrid = lhs._grid; GridBase *SliceGrid = makeSubSliceGrid(FullGrid,Orthog); int Nblock = FullGrid->GlobalDimensions()[Orthog]; Lattice Lslice(SliceGrid); Lattice Rslice(SliceGrid); mat = Eigen::MatrixXcd::Zero(Nblock,Nblock); for(int i=0;i static void sliceInnerProductVector( std::vector & vec, const Lattice &lhs,const Lattice &rhs,int Orthog) { typedef typename vobj::scalar_object sobj; typedef typename vobj::scalar_type scalar_type; typedef typename vobj::vector_type vector_type; typedef typename vobj::tensor_reduced scalar; typedef typename scalar::scalar_object scomplex; int Nblock = lhs._grid->GlobalDimensions()[Orthog]; vec.resize(Nblock); std::vector sip(Nblock); Lattice IP(lhs._grid); IP=localInnerProduct(lhs,rhs); sliceSum(IP,sip,Orthog); for(int ss=0;ss static void sliceNorm (std::vector &sn,const Lattice &rhs,int Orthog) { typedef typename vobj::scalar_object sobj; typedef typename vobj::scalar_type scalar_type; typedef typename vobj::vector_type vector_type; int Nblock = rhs._grid->GlobalDimensions()[Orthog]; std::vector ip(Nblock); sn.resize(Nblock); sliceInnerProductVector(ip,rhs,rhs,Orthog); for(int ss=0;ss static void sliceInnerProductMatrixOld( Eigen::MatrixXcd &mat, const Lattice &lhs,const Lattice &rhs,int Orthog) { typedef typename vobj::scalar_object sobj; typedef typename vobj::scalar_type scalar_type; typedef typename vobj::vector_type vector_type; typedef typename vobj::tensor_reduced scalar; typedef typename scalar::scalar_object scomplex; int Nblock = lhs._grid->GlobalDimensions()[Orthog]; std::cout << " sliceInnerProductMatrix Dim "< IP(lhs._grid); std::vector sip(Nblock); mat = Eigen::MatrixXcd::Zero(Nblock,Nblock); Lattice tmp = rhs; for(int s1=0;s1 class BlockConjugateGradient : public OperatorFunction { public: typedef typename Field::scalar_type scomplex; const int blockDim = 0; int Nblock; bool ErrorOnNoConverge; // throw an assert when the CG fails to converge. // Defaults true. RealD Tolerance; Integer MaxIterations; Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion BlockConjugateGradient(RealD tol, Integer maxit, bool err_on_no_conv = true) : Tolerance(tol), MaxIterations(maxit), ErrorOnNoConverge(err_on_no_conv){}; void operator()(LinearOperatorBase &Linop, const Field &Src, Field &Psi) { int Orthog = 0; // First dimension is block dim Nblock = Src._grid->_fdimensions[Orthog]; std::cout< residuals(Nblock); std::vector ssq(Nblock); sliceNorm(ssq,Src,Orthog); RealD sssum=0; for(int b=0;b max_resid ) max_resid = rr; } if ( max_resid < Tolerance*Tolerance ) { std::cout << GridLogMessage<<" Block solver has converged in " <