/************************************************************************************* 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<