From 58a31f0763d9c5f06a4df38e47ed5919eb58c8fb Mon Sep 17 00:00:00 2001 From: Peter Boyle Date: Mon, 9 Dec 2019 02:59:13 -0500 Subject: [PATCH] QMR implemented, preserve even if not used much --- .../iterative/QuasiMinimalResidual.h | 371 ++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 Grid/algorithms/iterative/QuasiMinimalResidual.h diff --git a/Grid/algorithms/iterative/QuasiMinimalResidual.h b/Grid/algorithms/iterative/QuasiMinimalResidual.h new file mode 100644 index 00000000..ea5531b6 --- /dev/null +++ b/Grid/algorithms/iterative/QuasiMinimalResidual.h @@ -0,0 +1,371 @@ +/************************************************************************************* + +Grid physics library, www.github.com/paboyle/Grid + +Source file: ./lib/algorithmsf/iterative/QuasiMinimalResidual.h + +Copyright (C) 2019 + +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 + +NAMESPACE_BEGIN(Grid); + +template +RealD innerG5ProductReal(Field &l, Field &r) +{ + Gamma G5(Gamma::Algebra::Gamma5); + Field tmp(l.Grid()); + // tmp = G5*r; + G5R5(tmp,r); + ComplexD ip =innerProduct(l,tmp); + std::cout << "innerProductRealG5R5 "< +class QuasiMinimalResidual : public OperatorFunction { + public: + using OperatorFunction::operator(); + + bool ErrorOnNoConverge; + RealD Tolerance; + Integer MaxIterations; + Integer IterationCount; + + QuasiMinimalResidual(RealD tol, + Integer maxit, + bool err_on_no_conv = true) + : Tolerance(tol) + , MaxIterations(maxit) + , ErrorOnNoConverge(err_on_no_conv) + {}; + +#if 1 + void operator()(LinearOperatorBase &LinOp, const Field &b, Field &x) + { + RealD resid; + IterationCount=0; + + RealD rho, rho_1, xi, gamma, gamma_1, theta, theta_1; + RealD eta, delta, ep, beta; + + GridBase *Grid = b.Grid(); + Field r(Grid), d(Grid), s(Grid); + Field v(Grid), w(Grid), y(Grid), z(Grid); + Field v_tld(Grid), w_tld(Grid), y_tld(Grid), z_tld(Grid); + Field p(Grid), q(Grid), p_tld(Grid); + + Real normb = norm2(b); + + LinOp.Op(x,r); r = b - r; + + assert(normb> 0.0); + + resid = norm2(r)/normb; + if (resid <= Tolerance) { + return; + } + + v_tld = r; + y = v_tld; + rho = norm2(y); + + // Take Gamma5 conjugate + // Gamma G5(Gamma::Algebra::Gamma5); + // G5R5(w_tld,r); + // w_tld = G5* v_tld; + w_tld=v_tld; + z = w_tld; + xi = norm2(z); + + gamma = 1.0; + eta = -1.0; + theta = 0.0; + + for (int i = 1; i <= MaxIterations; i++) { + + // Breakdown tests + assert( rho != 0.0); + assert( xi != 0.0); + + v = (1. / rho) * v_tld; + y = (1. / rho) * y; + + w = (1. / xi) * w_tld; + z = (1. / xi) * z; + + ComplexD Zdelta = innerProduct(z, y); // Complex? + std::cout << "Zdelta "< 1) { + p = y_tld - (xi * delta / ep) * p; + q = z_tld - (rho * delta / ep) * q; + } else { + p = y_tld; + q = z_tld; + } + + LinOp.Op(p,p_tld); // p_tld = A * p; + ComplexD Zep = innerProduct(q, p_tld); + ep=Zep.real(); + std::cout << "Zep "<0); + + beta = ep / delta; + assert(abs(beta)>0); + + v_tld = p_tld - beta * v; + y = v_tld; + + rho_1 = rho; + rho = norm2(y); + LinOp.AdjOp(q,w_tld); + w_tld = w_tld - beta * w; + z = w_tld; + + xi = norm2(z); + + gamma_1 = gamma; + theta_1 = theta; + + theta = rho / (gamma_1 * beta); + gamma = 1.0 / sqrt(1.0 + theta * theta); + std::cout << "theta "< 0.0); + + eta = -eta * rho_1 * gamma* gamma / (beta * gamma_1 * gamma_1); + + if (i > 1) { + d = eta * p + (theta_1 * theta_1 * gamma * gamma) * d; + s = eta * p_tld + (theta_1 * theta_1 * gamma * gamma) * s; + } else { + d = eta * p; + s = eta * p_tld; + } + + x =x+d; // update approximation vector + r =r-s; // compute residual + + if ((resid = norm2(r) / normb) <= Tolerance) { + return; + } + std::cout << "Iteration "< &LinOp, const Field &b, Field &x) + { + // Real scalars + GridBase *grid = b.Grid(); + + Field r(grid); + Field p_m(grid), p_m_minus_1(grid), p_m_minus_2(grid); + Field v_m(grid), v_m_minus_1(grid), v_m_plus_1(grid); + Field tmp(grid); + + RealD w; + RealD z1, z2; + RealD delta_m, delta_m_minus_1; + RealD c_m_plus_1, c_m, c_m_minus_1; + RealD s_m_plus_1, s_m, s_m_minus_1; + RealD alpha, beta, gamma, epsilon; + RealD mu, nu, rho, theta, xi, chi; + RealD mod2r, mod2b; + RealD tau2, target2; + + mod2b=norm2(b); + + ///////////////////////// + // Initial residual + ///////////////////////// + LinOp.Op(x,tmp); + r = b - tmp; + + ///////////////////////// + // \mu = \rho = |r_0| + ///////////////////////// + mod2r = norm2(r); + rho = sqrt( mod2r); + mu=rho; + + std::cout << "QuasiMinimalResidual rho "<< rho<