From 1fe4c205a38ee817e69a4ceb548050dd8bd6fb36 Mon Sep 17 00:00:00 2001 From: Peter Boyle Date: Tue, 27 Aug 2024 11:11:47 -0400 Subject: [PATCH] Adef --- Grid/algorithms/iterative/AdefMrhs.h | 312 ++++++++++++++++++++++++++- 1 file changed, 308 insertions(+), 4 deletions(-) diff --git a/Grid/algorithms/iterative/AdefMrhs.h b/Grid/algorithms/iterative/AdefMrhs.h index a2788138..fbefa40e 100644 --- a/Grid/algorithms/iterative/AdefMrhs.h +++ b/Grid/algorithms/iterative/AdefMrhs.h @@ -53,6 +53,7 @@ class TwoLevelCGmrhs // Fine operator, Smoother, CoarseSolver LinearOperatorBase &_FineLinop; LinearFunction &_Smoother; + MultiRHSBlockCGLinalg _BlockCGLinalg; GridStopWatch ProjectTimer; GridStopWatch PromoteTimer; @@ -79,6 +80,301 @@ class TwoLevelCGmrhs // Vector case virtual void operator() (std::vector &src, std::vector &x) + { + SolveSingleSystem(src,x); + // SolvePrecBlockCG(src,x); + } + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Thin QR factorisation (google it) +//////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////// + //Dimensions + // R_{ferm x Nblock} = Q_{ferm x Nblock} x C_{Nblock x Nblock} -> ferm x Nblock + // + // Rdag R = m_rr = Herm = L L^dag <-- Cholesky decomposition (LLT routine in Eigen) + // + // Q C = R => Q = R C^{-1} + // + // Want Ident = Q^dag Q = C^{-dag} R^dag R C^{-1} = C^{-dag} L L^dag C^{-1} = 1_{Nblock x Nblock} + // + // Set C = L^{dag}, and then Q^dag Q = ident + // + // Checks: + // Cdag C = Rdag R ; passes. + // QdagQ = 1 ; passes + //////////////////////////////////////////////////////////////////////////////////////////////////// + void ThinQRfact (Eigen::MatrixXcd &m_zz, + Eigen::MatrixXcd &C, + Eigen::MatrixXcd &Cinv, + std::vector & Q, + std::vector & MQ, + const std::vector & Z, + const std::vector & MZ) + { + RealD t0=usecond(); + _BlockCGLinalg.InnerProductMatrix(m_zz,MZ,Z); + RealD t1=usecond(); + + m_zz = 0.5*(m_zz+m_zz.adjoint()); + + Eigen::MatrixXcd L = m_zz.llt().matrixL(); + + C = L.adjoint(); + Cinv = C.inverse(); + + RealD t3=usecond(); + _BlockCGLinalg.MulMatrix( Q,Cinv,Z); + _BlockCGLinalg.MulMatrix(MQ,Cinv,MZ); + RealD t4=usecond(); + std::cout << " ThinQRfact IP :"<< t1-t0<<" us"< &src, std::vector &X) + { + std::cout << GridLogMessage<<"HDCG: mrhs fPrecBlockcg starting"<Barrier(); + int nrhs = src.size(); + // std::vector f(nrhs); + // std::vector rtzp(nrhs); + // std::vector rtz(nrhs); + // std::vector a(nrhs); + // std::vector d(nrhs); + // std::vector b(nrhs); + // std::vector rptzp(nrhs); + + //////////////////////////////////////////// + //Initial residual computation & set up + //////////////////////////////////////////// + std::vector ssq(nrhs); + for(int rhs=0;rhs Mtmp(nrhs,grid); + std::vector tmp(nrhs,grid); + std::vector Z(nrhs,grid); // Rename Z to R + std::vector MZ(nrhs,grid); // Rename MZ to Z + std::vector Q(nrhs,grid); // + std::vector MQ(nrhs,grid); // Rename to P + std::vector D(nrhs,grid); + std::vector AD(nrhs,grid); + + /************************************************************************ + * Preconditioned Block conjugate gradient rQ + * Generalise Sebastien Birk Thesis, after Dubrulle 2001. + * Introduce preconditioning following Saad Ch9 + ************************************************************************ + * Dimensions: + * + * X,B etc... ==(Nferm x nrhs) + * Matrix A==(Nferm x Nferm) + * + * Nferm = Nspin x Ncolour x Ncomplex x Nlattice_site + * QC => Thin QR factorisation (google it) + * + * R = B-AX + * Z = Mi R + * QC = Z + * D = Q + * for k: + * R = AD + * Z = Mi R + * M = [D^dag R]^{-1} + * X = X + D M C + * QS = Q - Z.M + * D = Q + D S^dag + * C = S C + */ + Eigen::MatrixXcd m_DZ = Eigen::MatrixXcd::Identity(nrhs,nrhs); + Eigen::MatrixXcd m_M = Eigen::MatrixXcd::Identity(nrhs,nrhs); + Eigen::MatrixXcd m_zz = Eigen::MatrixXcd::Zero(nrhs,nrhs); + Eigen::MatrixXcd m_rr = Eigen::MatrixXcd::Zero(nrhs,nrhs); + + Eigen::MatrixXcd m_C = Eigen::MatrixXcd::Zero(nrhs,nrhs); + Eigen::MatrixXcd m_Cinv = Eigen::MatrixXcd::Zero(nrhs,nrhs); + Eigen::MatrixXcd m_S = Eigen::MatrixXcd::Zero(nrhs,nrhs); + Eigen::MatrixXcd m_Sinv = Eigen::MatrixXcd::Zero(nrhs,nrhs); + + Eigen::MatrixXcd m_tmp = Eigen::MatrixXcd::Identity(nrhs,nrhs); + Eigen::MatrixXcd m_tmp1 = Eigen::MatrixXcd::Identity(nrhs,nrhs); + + GridStopWatch HDCGTimer; + + ////////////////////////// + // x0 = Vstart -- possibly modify guess + ////////////////////////// + Vstart(X,src); + + ////////////////////////// + // R = B-AX + ////////////////////////// + for(int rhs=0;rhs rn(nrhs); + for (int k=0;k<=MaxIterations;k++){ + + //////////////////// + // Z = AD + //////////////////// + M3Timer.Start(); + for(int b=0;b_M)^{-1} inner prod, generalising Saad derivation of Precon CG + //////////////////// + InnerProdTimer.Start(); + _BlockCGLinalg.InnerProductMatrix(m_DZ,D,Z); + InnerProdTimer.Stop(); + m_M = m_DZ.inverse(); + + /////////////////////////// + // X = X + D MC + /////////////////////////// + m_tmp = m_M * m_C; + LinalgTimer.Start(); + _BlockCGLinalg.MaddMatrix(X,m_tmp, D,X); // D are the search directions and X takes the updates + LinalgTimer.Stop(); + + /////////////////////////// + // QS = Q - M Z + // (MQ) S = MQ - M (M1Z) + /////////////////////////// + LinalgTimer.Start(); + _BlockCGLinalg.MaddMatrix(tmp ,m_M, Z, Q,-1.0); + _BlockCGLinalg.MaddMatrix(Mtmp,m_M,MZ,MQ,-1.0); + ThinQRfact (m_zz, m_S, m_Sinv, Q, MQ, tmp, Mtmp); + LinalgTimer.Stop(); + + //////////////////////////// + // D = MQ + D S^dag + //////////////////////////// + m_tmp = m_S.adjoint(); + LinalgTimer.Start(); + _BlockCGLinalg.MaddMatrix(D,m_tmp,D,MQ); + LinalgTimer.Stop(); + + //////////////////////////// + // C = S C + //////////////////////////// + m_C = m_S*m_C; + + //////////////////////////// + // convergence monitor + //////////////////////////// + m_rr = m_C.adjoint() * m_C; + + FineTimer.Stop(); + + RealD max_resid=0; + RealD rrsum=0; + RealD sssum=0; + RealD rr; + + for(int b=0;b max_resid ) max_resid = rr; + } + std::cout << GridLogMessage << + "\t Prec BlockCGrQ Iteration "< &src, std::vector &x) { std::cout << GridLogMessage<<"HDCG: mrhs fPcg starting"<Barrier(); @@ -361,15 +657,23 @@ public: CoarseField PleftProjMrhs(this->coarsegridmrhs); CoarseField PleftMss_projMrhs(this->coarsegridmrhs); +#undef SMOOTHER_BLOCK_SOLVE +#if SMOOTHER_BLOCK_SOLVE + this->SmoothTimer.Start(); + this->_Smoother(in,Min); + this->SmoothTimer.Stop(); +#else for(int rhs=0;rhsSmoothTimer.Start(); this->_Smoother(in[rhs],Min[rhs]); this->SmoothTimer.Stop(); - + } +#endif + + for(int rhs=0;rhsFineTimer.Start(); this->_FineLinop.HermOp(Min[rhs],out[rhs]); - axpy(tmp[rhs],-1.0,out[rhs],in[rhs]); // resid = in - A Min this->FineTimer.Stop(); @@ -407,7 +711,7 @@ public: this->FineTimer.Stop(); } }; - + NAMESPACE_END(Grid);