// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2012, 2014 Kolja Brix <brix@igpm.rwth-aaachen.de>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_GMRES_H
#define EIGEN_GMRES_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

namespace internal {

/**
 * Generalized Minimal Residual Algorithm based on the
 * Arnoldi algorithm implemented with Householder reflections.
 *
 * Parameters:
 *  \param mat       matrix of linear system of equations
 *  \param rhs       right hand side vector of linear system of equations
 *  \param x         on input: initial guess, on output: solution
 *  \param precond   preconditioner used
 *  \param iters     on input: maximum number of iterations to perform
 *                   on output: number of iterations performed
 *  \param restart   number of iterations for a restart, capped by the problem size
 *  \param tol_error on input: relative tolerance for the preconditioned residual, normalized by the preconditioned
 *                   right-hand side
 *                   on output: relative preconditioned residual achieved
 *
 * \sa IterativeMethods::bicgstab()
 *
 *
 * For references, please see:
 *
 * Saad, Y. and Schultz, M. H.
 * GMRES: A Generalized Minimal Residual Algorithm for Solving Nonsymmetric Linear Systems.
 * SIAM J.Sci.Stat.Comp. 7, 1986, pp. 856 - 869.
 *
 * Saad, Y.
 * Iterative Methods for Sparse Linear Systems.
 * Society for Industrial and Applied Mathematics, Philadelphia, 2003.
 *
 * Walker, H. F.
 * Implementations of the GMRES method.
 * Comput.Phys.Comm. 53, 1989, pp. 311 - 320.
 *
 * Walker, H. F.
 * Implementation of the GMRES Method using Householder Transformations.
 * SIAM J.Sci.Stat.Comp. 9, 1988, pp. 152 - 163.
 *
 */
template <typename MatrixType, typename Rhs, typename Dest, typename Preconditioner>
bool gmres(const MatrixType& mat, const Rhs& rhs, Dest& x, const Preconditioner& precond, Index& iters,
           const Index& restart_, typename Dest::RealScalar& tol_error) {
  using std::abs;
  using std::sqrt;

  using RealScalar = typename Dest::RealScalar;
  using Scalar = typename Dest::Scalar;
  using VectorType = Matrix<Scalar, Dynamic, 1>;
  using FMatrixType = Matrix<Scalar, Dynamic, Dynamic, ColMajor>;

  const RealScalar considerAsZero = (std::numeric_limits<RealScalar>::min)();

  if (rhs.norm() <= considerAsZero) {
    x.setZero();
    tol_error = 0;
    return true;
  }

  RealScalar tol = tol_error;
  const Index maxIters = iters;
  iters = 0;

  const Index m = mat.rows();
  // A GMRES cycle cannot use more Krylov vectors than the problem dimension, so cap the internal workspace even if
  // the user requests a larger restart value.
  const Index restart = numext::mini(numext::maxi(restart_, Index(1)), m);

  // residual and preconditioned residual
  VectorType p0 = rhs - mat * x;
  VectorType r0 = precond.solve(p0);

  const RealScalar r0Norm = r0.norm();
  // w(k) tracks the residual norm of the left-preconditioned system. Normalize it by the matching right-hand
  // side, not by the initial residual, so solveWithGuess() uses the same relative-residual criterion as solve().
  const RealScalar rhsNorm = numext::maxi((x.squaredNorm() == 0) ? r0Norm : precond.solve(rhs).norm(), considerAsZero);
  const RealScalar threshold = numext::maxi(tol * rhsNorm, considerAsZero);

  // is initial guess already good enough?
  if (r0Norm < threshold) {
    tol_error = r0Norm / rhsNorm;
    return true;
  }

  // storage for Hessenberg matrix and Householder data
  FMatrixType H = FMatrixType::Zero(m, restart + 1);
  VectorType w = VectorType::Zero(restart + 1);
  VectorType tau = VectorType::Zero(restart + 1);

  // storage for Jacobi rotations
  std::vector<JacobiRotation<Scalar> > G(restart);

  // storage for temporaries
  VectorType t(m), v(m), workspace(m), x_new(m);

  // generate first Householder vector
  Ref<VectorType> H0_tail = H.col(0).tail(m - 1);
  RealScalar beta;
  r0.makeHouseholder(H0_tail, tau.coeffRef(0), beta);
  w(0) = Scalar(beta);

  for (Index k = 1; k <= restart; ++k) {
    ++iters;

    v = VectorType::Unit(m, k - 1);

    // apply Householder reflections H_{1} ... H_{k-1} to v
    // TODO: use a HouseholderSequence
    for (Index i = k - 1; i >= 0; --i) {
      v.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data());
    }

    // apply matrix M to v:  v = mat * v;
    t.noalias() = mat * v;
    v = precond.solve(t);

    // apply Householder reflections H_{k-1} ... H_{1} to v
    // TODO: use a HouseholderSequence
    for (Index i = 0; i < k; ++i) {
      v.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data());
    }

    if (v.tail(m - k).norm() != 0.0 && k <= restart) {
      // generate new Householder vector
      Ref<VectorType> Hk_tail = H.col(k).tail(m - k - 1);
      v.tail(m - k).makeHouseholder(Hk_tail, tau.coeffRef(k), beta);

      // apply Householder reflection H_{k} to v
      v.tail(m - k).applyHouseholderOnTheLeft(Hk_tail, tau.coeffRef(k), workspace.data());
    }

    // apply old Givens rotations to v
    for (Index i = 0; i < k - 1; ++i) {
      v.applyOnTheLeft(i, i + 1, G[i].adjoint());
    }

    if (k < m && v(k) != (Scalar)0) {
      // determine next Givens rotation
      G[k - 1].makeGivens(v(k - 1), v(k));

      // apply Givens rotation to v and w
      v.applyOnTheLeft(k - 1, k, G[k - 1].adjoint());
      w.applyOnTheLeft(k - 1, k, G[k - 1].adjoint());
    }

    // insert coefficients into upper matrix triangle
    H.col(k - 1).head(k) = v.head(k);

    tol_error = abs(w(k)) / rhsNorm;
    bool stop = (k == m || tol_error < tol || iters == maxIters);

    if (stop || k == restart) {
      // solve upper triangular system
      Ref<VectorType> y = w.head(k);
      H.topLeftCorner(k, k).template triangularView<Upper>().solveInPlace(y);

      // use Horner-like scheme to calculate solution vector
      x_new.setZero();
      for (Index i = k - 1; i >= 0; --i) {
        x_new(i) += y(i);
        // apply Householder reflection H_{i} to x_new
        x_new.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data());
      }

      x += x_new;

      if (stop) {
        return true;
      } else {
        k = 0;

        // reset data for restart
        p0.noalias() = rhs - mat * x;
        r0 = precond.solve(p0);

        // clear Hessenberg matrix and Householder data
        H.setZero();
        w.setZero();
        tau.setZero();

        // generate first Householder vector
        r0.makeHouseholder(H0_tail, tau.coeffRef(0), beta);
        w(0) = Scalar(beta);
      }
    }
  }

  return false;
}

}  // namespace internal

template <typename MatrixType_, typename Preconditioner_ = DiagonalPreconditioner<typename MatrixType_::Scalar> >
class GMRES;

namespace internal {

template <typename MatrixType_, typename Preconditioner_>
struct traits<GMRES<MatrixType_, Preconditioner_> > {
  using MatrixType = MatrixType_;
  using Preconditioner = Preconditioner_;
};

}  // namespace internal

/** \ingroup IterativeLinearSolvers_Module
 * \brief A GMRES solver for sparse square problems
 *
 * This class allows to solve for A.x = b sparse linear problems using a generalized minimal
 * residual method. The vectors x and b can be either dense or sparse.
 *
 * \tparam MatrixType_ the type of the sparse matrix A, can be a dense or a sparse matrix.
 * \tparam Preconditioner_ the type of the preconditioner. Default is DiagonalPreconditioner
 *
 * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations()
 * and setTolerance() methods. The defaults are twice the number of columns of the matrix for the maximal
 * number of iterations and NumTraits<Scalar>::epsilon() for the tolerance.
 *
 * When a left preconditioner M is used, GMRES applies the stopping criterion to the preconditioned
 * system M^{-1} A x = M^{-1} b. The reported error is therefore
 * \f$\|M^{-1}(b-Ax)\| / \|M^{-1}b\|\f$.
 *
 * This class can be used as the direct solver classes. Here is a typical usage example:
 * \code
 * int n = 10000;
 * VectorXd x(n), b(n);
 * SparseMatrix<double> A(n,n);
 * // fill A and b
 * GMRES<SparseMatrix<double> > solver(A);
 * x = solver.solve(b);
 * std::cout << "#iterations:     " << solver.iterations() << std::endl;
 * std::cout << "estimated error: " << solver.error()      << std::endl;
 * // update b, and solve again
 * x = solver.solve(b);
 * \endcode
 *
 * By default the iterations start with x=0 as an initial guess of the solution.
 * One can control the start using the solveWithGuess() method.
 *
 * GMRES can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink.
 *
 * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner
 */
template <typename MatrixType_, typename Preconditioner_>
class GMRES : public IterativeSolverBase<GMRES<MatrixType_, Preconditioner_> > {
 protected:
  using Base = IterativeSolverBase<GMRES>;
  using Base::m_error;
  using Base::m_info;
  using Base::m_isInitialized;
  using Base::m_iterations;
  using Base::matrix;

 private:
  Index m_restart = 30;

 public:
  using Base::_solve_impl;
  using MatrixType = MatrixType_;
  using Scalar = typename MatrixType::Scalar;
  using RealScalar = typename MatrixType::RealScalar;
  using Preconditioner = Preconditioner_;

 public:
  /** Default constructor. */
  GMRES() : Base(), m_restart(30) {}

  /** Initialize the solver with matrix \a A for further \c Ax=b solving.
   *
   * This constructor is a shortcut for the default constructor followed
   * by a call to compute().
   *
   * \warning this class stores a reference to the matrix A as well as some
   * precomputed values that depend on it. Therefore, if \a A is changed
   * this class becomes invalid. Call compute() to update it with the new
   * matrix A, or modify a copy of A.
   */
  template <typename MatrixDerived>
  explicit GMRES(const EigenBase<MatrixDerived>& A) : Base(A.derived()), m_restart(30) {}

  /** Get the number of iterations after that a restart is performed.
   */
  Index get_restart() const { return m_restart; }

  /** Set the number of iterations after that a restart is performed.
   *  \param restart   number of iterations for a restart, default is 30.
   */
  void set_restart(const Index restart) { m_restart = restart; }

  /** \internal */
  template <typename Rhs, typename Dest>
  void _solve_vector_with_guess_impl(const Rhs& b, Dest& x) const {
    m_iterations = Base::maxIterations();
    m_error = Base::m_tolerance;
    bool ret = internal::gmres(matrix(), b, x, Base::m_preconditioner, m_iterations, m_restart, m_error);
    m_info = (!ret) ? NumericalIssue : m_error <= Base::m_tolerance ? Success : NoConvergence;
  }

 protected:
};

}  // end namespace Eigen

#endif  // EIGEN_GMRES_H
