diff --git a/lib/algorithms/iterative/MinimalResidual.h b/lib/algorithms/iterative/MinimalResidual.h new file mode 100644 index 00000000..878deb24 --- /dev/null +++ b/lib/algorithms/iterative/MinimalResidual.h @@ -0,0 +1,197 @@ +/************************************************************************************* + +Grid physics library, www.github.com/paboyle/Grid + +Source file: ./lib/algorithms/iterative/MinimalResidual.h + +Copyright (C) 2015 + +Author: Azusa Yamaguchi +Author: Peter Boyle +Author: paboyle + +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_MINIMAL_RESIDUAL_H +#define GRID_MINIMAL_RESIDUAL_H + +namespace Grid { + +///////////////////////////////////////////////////////////// +// Base classes for iterative processes based on operators +// single input vec, single output vec. +///////////////////////////////////////////////////////////// + +template +class MinimalResidual : public OperatorFunction { + public: + bool ErrorOnNoConverge; // throw an assert when the MR fails to converge. + // Defaults true. + RealD Tolerance; + Integer MaxIterations; + Integer IterationsToComplete; //Number of iterations the MR took to finish. Filled in upon completion + + MinimalResidual(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) { + psi.checkerboard = src.checkerboard; // Check + conformable(psi, src); + + Field p {src}; + Field matrixTimesPsi {src}; + Field r {src}; + + RealD alpha {}; + + // Initial residual computation & set up + RealD guess = norm2(psi); + assert(std::isnan(guess) == 0); + + Linop.HermOp(psi, matrixTimesPsi); + + r = src - matrixTimesPsi; + + Linop.HermOp(r, p); + + alpha = innerProduct(p,r) / innerProduct(p,p); + psi = psi + alpha * r; + r = r - alpha * p; + + Linop.HermOp(r, p); + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + // RealD cp, c, a, d, b, ssq, qq, b_pred; + + Field p(src); + Field matrixTimesPsi(src); + // Field r(src); + + // Initial residual computation & set up + RealD guess = norm2(psi); + assert(std::isnan(guess) == 0); + + + Linop.HermOpAndNorm(psi, matrixTimesPsi, d, b); + + + r = src - matrixTimesPsi; + p = matrixTimesPsi; + + a = norm2(p); + cp = a; + ssq = norm2(src); + + std::cout << GridLogIterative << std::setprecision(4) + << "MinimalResidual: guess " << guess << std::endl; + std::cout << GridLogIterative << std::setprecision(4) + << "MinimalResidual: src " << ssq << std::endl; + std::cout << GridLogIterative << std::setprecision(4) + << "MinimalResidual: mp " << d << std::endl; + std::cout << GridLogIterative << std::setprecision(4) + << "MinimalResidual: matrixTimesPsi " << b << std::endl; + std::cout << GridLogIterative << std::setprecision(4) + << "MinimalResidual: cp,r " << cp << std::endl; + std::cout << GridLogIterative << std::setprecision(4) + << "MinimalResidual: p " << a << std::endl; + + RealD rsq = Tolerance * Tolerance * ssq; + + // Check if guess is really REALLY good :) + if (cp <= rsq) { + return; + } + + std::cout << GridLogIterative << std::setprecision(4) + << "MinimalResidual: k=0 residual " << cp << " target " << rsq + << std::endl; + + GridStopWatch LinalgTimer; + GridStopWatch MatrixTimer; + GridStopWatch SolverTimer; + + SolverTimer.Start(); + int k; + for (k = 1; k <= MaxIterations; k++) { + c = cp; + + MatrixTimer.Start(); + Linop.HermOpAndNorm(p, matrixTimesPsi, d, qq); + MatrixTimer.Stop(); + + LinalgTimer.Start(); + // RealD qqck = norm2(matrixTimesPsi); + // ComplexD dck = innerProduct(p,matrixTimesPsi); + + a = c / d; + b_pred = a * (a * qq - d) / c; + + cp = axpy_norm(r, -a, matrixTimesPsi, r); + b = cp / c; + + // Fuse these loops ; should be really easy + psi = a * p + psi; + p = p * b + r; + + LinalgTimer.Stop(); + std::cout << GridLogIterative << "MinimalResidual: Iteration " << k + << " residual " << cp << " target " << rsq << std::endl; + + // Stopping condition + if (cp <= rsq) { + SolverTimer.Stop(); + Linop.HermOpAndNorm(psi, matrixTimesPsi, d, qq); + p = matrixTimesPsi - src; + + RealD matrixTimesPsiNorm = sqrt(norm2(matrixTimesPsi)); + RealD psinorm = sqrt(norm2(psi)); + RealD srcnorm = sqrt(norm2(src)); + RealD resnorm = sqrt(norm2(p)); + RealD true_residual = resnorm / srcnorm; + + std::cout << GridLogMessage + << "MinimalResidual: Converged on iteration " << k << std::endl; + std::cout << GridLogMessage << "Computed residual " << sqrt(cp / ssq) + << " true residual " << true_residual << " target " + << Tolerance << std::endl; + std::cout << GridLogMessage << "Time elapsed: Iterations " + << SolverTimer.Elapsed() << " Matrix " + << MatrixTimer.Elapsed() << " Linalg " + << LinalgTimer.Elapsed(); + std::cout << std::endl; + + if (ErrorOnNoConverge) assert(true_residual / Tolerance < 10000.0); + IterationsToComplete = k; + return; + } + } + std::cout << GridLogMessage << "MinimalResidual did NOT converge" + << std::endl; + if (ErrorOnNoConverge) assert(0); + IterationsToComplete = k; + } +}; +} +#endif diff --git a/tests/solver/Test_wilson_ddalphaamg.cc b/tests/solver/Test_wilson_ddalphaamg.cc new file mode 100644 index 00000000..7269bf64 --- /dev/null +++ b/tests/solver/Test_wilson_ddalphaamg.cc @@ -0,0 +1,806 @@ + /************************************************************************************* + + Grid physics library, www.github.com/paboyle/Grid + + Source file: ./tests/Test_dwf_hdcr.cc + + Copyright (C) 2015 + +Author: Daniel Richtmann + + 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 +#include +//#include + +using namespace std; +using namespace Grid; +using namespace Grid::QCD; + +class myclass: Serializable { +public: + + GRID_SERIALIZABLE_CLASS_MEMBERS(myclass, + int, domaindecompose, + int, domainsize, + int, order, + int, Ls, + double, mq, + double, lo, + double, hi, + int, steps); + + myclass(){}; + +}; +myclass params; + +RealD InverseApproximation(RealD x){ + return 1.0/x; +} + +template +class MultiGridPreconditioner : public LinearFunction< Lattice > { +public: + + typedef Aggregation Aggregates; + typedef CoarsenedMatrix CoarseOperator; + + typedef typename Aggregation::siteVector siteVector; + typedef typename Aggregation::CoarseScalar CoarseScalar; + typedef typename Aggregation::CoarseVector CoarseVector; + typedef typename Aggregation::CoarseMatrix CoarseMatrix; + typedef typename Aggregation::FineField FineField; + typedef LinearOperatorBase FineOperator; + + Aggregates & _Aggregates; + CoarseOperator & _CoarseOperator; + Matrix & _FineMatrix; + FineOperator & _FineOperator; + Matrix & _SmootherMatrix; + FineOperator & _SmootherOperator; + + // Constructor + MultiGridPreconditioner(Aggregates &Agg, CoarseOperator &Coarse, + FineOperator &Fine,Matrix &FineMatrix, + FineOperator &Smooth,Matrix &SmootherMatrix) + : _Aggregates(Agg), + _CoarseOperator(Coarse), + _FineOperator(Fine), + _FineMatrix(FineMatrix), + _SmootherOperator(Smooth), + _SmootherMatrix(SmootherMatrix) + { + } + + void PowerMethod(const FineField &in) { + + FineField p1(in._grid); + FineField p2(in._grid); + + MdagMLinearOperator fMdagMOp(_FineMatrix); + + p1=in; + RealD absp2; + for(int i=0;i<20;i++){ + RealD absp1=std::sqrt(norm2(p1)); + fMdagMOp.HermOp(p1,p2);// this is the G5 herm bit + // _FineOperator.Op(p1,p2);// this is the G5 herm bit + RealD absp2=std::sqrt(norm2(p2)); + if(i%10==9) + std::cout< CG(1.0e-10,100000); + ConjugateGradient fCG(3.0e-2,1000); + + HermitianLinearOperator HermOp(_CoarseOperator); + MdagMLinearOperator MdagMOp(_CoarseOperator); + MdagMLinearOperator fMdagMOp(_FineMatrix); + + FineField tmp(in._grid); + FineField res(in._grid); + FineField Min(in._grid); + + // Monitor completeness of low mode space + _Aggregates.ProjectToSubspace (Csrc,in); + _Aggregates.PromoteFromSubspace(Csrc,out); + std::cout< CG(1.0e-10,100000); + ConjugateGradient fCG(3.0e-2,1000); + + HermitianLinearOperator HermOp(_CoarseOperator); + MdagMLinearOperator MdagMOp(_CoarseOperator); + ShiftedMdagMLinearOperator fMdagMOp(_FineMatrix,0.1); + + FineField tmp(in._grid); + FineField res(in._grid); + FineField Qin(in._grid); + + // Monitor completeness of low mode space + // _Aggregates.ProjectToSubspace (Csrc,in); + // _Aggregates.PromoteFromSubspace(Csrc,out); + // std::cout< > coor(src._grid); + Lattice > subset(src._grid); + + FineField r(src._grid); + FineField zz(src._grid); zz=zero; + FineField vec1(src._grid); + FineField vec2(src._grid); + + const Integer block=params.domainsize; + + subset=zero; + for(int mu=0;mu fMdagMOp(_SmootherMatrix,0.0); + Chebyshev Cheby (params.lo,params.hi,params.order,InverseApproximation); + + RealD resid; + for(int i=0;i fMdagMOp(_FineMatrix); + ShiftedMdagMLinearOperator fMdagMOp(_SmootherMatrix,0.0); + + RealD Ni,r; + + Ni = norm2(in); + + for(int ilo=0;ilo<3;ilo++){ + for(int ord=5;ord<50;ord*=2){ + + _SmootherOperator.AdjOp(in,vec1); + + Chebyshev Cheby (lo[ilo],70.0,ord,InverseApproximation); + Cheby(fMdagMOp,vec1,vec2); // solves MdagM = g5 M g5M + + _FineOperator.Op(vec2,vec1);// this is the G5 herm bit + vec1 = in - vec1; // tmp = in - A Min + r=norm2(vec1); + std::cout< CG(3.0e-3,100000); + // ConjugateGradient fCG(3.0e-2,1000); + + HermitianLinearOperator HermOp(_CoarseOperator); + MdagMLinearOperator MdagMOp(_CoarseOperator); + // MdagMLinearOperator fMdagMOp(_FineMatrix); + ShiftedMdagMLinearOperator fMdagMOp(_SmootherMatrix,0.0); + + FineField vec1(in._grid); + FineField vec2(in._grid); + + // Chebyshev Cheby (0.5,70.0,30,InverseApproximation); + // Chebyshev ChebyAccu(0.5,70.0,30,InverseApproximation); + Chebyshev Cheby (params.lo,params.hi,params.order,InverseApproximation); + Chebyshev ChebyAccu(params.lo,params.hi,params.order,InverseApproximation); + // Cheby.JacksonSmooth(); + // ChebyAccu.JacksonSmooth(); + + // _Aggregates.ProjectToSubspace (Csrc,in); + // _Aggregates.PromoteFromSubspace(Csrc,out); + // std::cout< CG(1.0e-3,100000); + + HermitianLinearOperator HermOp(_CoarseOperator); + MdagMLinearOperator MdagMOp(_CoarseOperator); + + FineField vec1(in._grid); + FineField vec2(in._grid); + + _Aggregates.ProjectToSubspace (Csrc,in); + _Aggregates.PromoteFromSubspace(Csrc,out); + std::cout< block ({2,2,2,2}); + const int nbasis= 32; + + std::vector clatt = GridDefaultLatt(); + for(int d=0;d seeds4({1,2,3,4}); + std::vector seeds5({5,6,7,8}); + std::vector cseeds({5,6,7,8}); + GridParallelRNG RNG5(FGrid); RNG5.SeedFixedIntegers(seeds5); + GridParallelRNG RNG4(UGrid); RNG4.SeedFixedIntegers(seeds4); + GridParallelRNG CRNG(Coarse5d);CRNG.SeedFixedIntegers(cseeds); + + Gamma g5(Gamma::Algebra::Gamma5); + + LatticeFermion src(FGrid); gaussian(RNG5,src);// src=src+g5*src; + LatticeFermion result(FGrid); result=zero; + LatticeFermion ref(FGrid); ref=zero; + LatticeFermion tmp(FGrid); + LatticeFermion err(FGrid); + LatticeGaugeField Umu(UGrid); + LatticeGaugeField UmuDD(UGrid); + LatticeColourMatrix U(UGrid); + LatticeColourMatrix zz(UGrid); + + FieldMetaData header; + std::string file("./ckpoint_lat.4000"); + NerscIO::readConfiguration(Umu,header,file); + + + if ( params.domaindecompose ) { + Lattice > coor(UGrid); + zz=zero; + for(int mu=0;mu(Umu,mu); + U = where(mod(coor,params.domainsize)==(Integer)0,zz,U); + PokeIndex(UmuDD,U,mu); + } + } else { + UmuDD = Umu; + } + // SU3::ColdConfiguration(RNG4,Umu); + // SU3::TepidConfiguration(RNG4,Umu); + // SU3::HotConfiguration(RNG4,Umu); + // Umu=zero; + + RealD mass=params.mq; + RealD M5=1.8; + + std::cout< Subspace; + typedef CoarsenedMatrix CoarseOperator; + typedef CoarseOperator::CoarseVector CoarseVector; + + std::cout< HermDefOp(Ddwf); + Subspace Aggregates(Coarse5d,FGrid); + // Aggregates.CreateSubspace(RNG5,HermDefOp,nbasis); + assert ( (nbasis & 0x1)==0); + int nb=nbasis/2; + std::cout< HermIndefOp(Ddwf); + Gamma5R5HermitianLinearOperator HermIndefOpDD(DdwfDD); + CoarsenedMatrix LDOp(*Coarse5d); + LDOp.CoarsenOperator(FGrid,HermIndefOp,Aggregates); + + std::cout< PosdefLdop(LDOp); + ConjugateGradient CG(1.0e-6,100000); + // CG(PosdefLdop,c_src,c_res); + + // std::cout< HermIndefLdop(LDOp); + // ConjugateResidual MCR(1.0e-6,100000); + //MCR(HermIndefLdop,c_src,c_res); + + std::cout< Precon (Aggregates, LDOp, + HermIndefOp,Ddwf, + HermIndefOp,Ddwf); + + MultiGridPreconditioner PreconDD(Aggregates, LDOp, + HermIndefOp,Ddwf, + HermIndefOpDD,DdwfDD); + TrivialPrecon simple; + + std::cout< simple; + // ConjugateGradient fCG(1.0e-8,100000); + // fCG(HermDefOp,src,result); + // exit(0); + + std::cout< UPGCR(1.0e-8,100000,simple,8,128); + // UPGCR(HermIndefOp,src,result); + + + /// Get themax eval + std::cout< PGCRDD(1.0e-8,100000,PreconDD,8,128); + // result=zero; + // std::cout< PGCR(1.0e-8,100000,Precon,8,8); + std::cout< HermOpEO(Ddwf); + ConjugateGradient pCG(1.0e-8,10000); + + LatticeFermion src_o(FrbGrid); + LatticeFermion result_o(FrbGrid); + pickCheckerboard(Odd,src_o,src); + result_o=zero; + + pCG(HermOpEO,src_o,result_o); + + + std::cout< block ({4,4,4,4}); + const int nbasis= 32; + + std::vector clatt = GridDefaultLatt(); + for(int d=0;d seedsFine({1,2,3,4}); + std::vector seedsCoarse({5,6,7,8}); + + GridParallelRNG pRNGFine(UGrid); pRNGFine.SeedFixedIntegers(seedsFine); + GridParallelRNG pRNGCoarse(Coarse4d); pRNGCoarse.SeedFixedIntegers(seedsCoarse); + + Gamma g5(Gamma::Algebra::Gamma5); + + LatticeFermion src(UGrid); gaussian(pRNGFine,src);// src=src+g5*src; + LatticeFermion result(UGrid); result=zero; + LatticeFermion ref(UGrid); ref=zero; + LatticeFermion tmp(UGrid); + LatticeFermion err(UGrid); + LatticeGaugeField Umu(UGrid); SU3::HotConfiguration(pRNGFine,Umu); + LatticeGaugeField UmuDD(UGrid); + LatticeColourMatrix U(UGrid); + LatticeColourMatrix zz(UGrid); + + if ( params.domaindecompose ) { + Lattice > coor(UGrid); + zz=zero; + for(int mu=0;mu(Umu,mu); + U = where(mod(coor,params.domainsize)==(Integer)0,zz,U); + PokeIndex(UmuDD,U,mu); + } + } else { + UmuDD = Umu; + } + + RealD mass=params.mq; + RealD M5=1.8; + + std::cout< Subspace; + typedef CoarsenedMatrix CoarseOperator; + typedef CoarseOperator::CoarseVector CoarseVector; + + std::cout< LDOp(*Coarse4d); + // LDOp.CoarsenOperator(UGrid,Dw,Aggregates); // problem with this line + + std::cout<