17faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This file is part of Eigen, a lightweight C++ template library 27faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// for linear algebra. 37faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// 47faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr> 57faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// 67faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This Source Code Form is subject to the terms of the Mozilla 77faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Public License v. 2.0. If a copy of the MPL was not distributed 87faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 97faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#ifndef EIGEN_DGMRES_H 117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#define EIGEN_DGMRES_H 127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#include <Eigen/Eigenvalues> 147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace Eigen { 167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, 187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> > 197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezclass DGMRES; 207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace internal { 227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, typename _Preconditioner> 247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstruct traits<DGMRES<_MatrixType,_Preconditioner> > 257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef _MatrixType MatrixType; 277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef _Preconditioner Preconditioner; 287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}; 297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/** \brief Computes a permutation vector to have a sorted sequence 317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param vec The vector to reorder. 327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param perm gives the sorted sequence on output. Must be initialized with 0..n-1 337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param ncut Put the ncut smallest elements at the end of the vector 347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * WARNING This is an expensive sort, so should be used only 357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * for small size vectors 367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * TODO Use modified QuickSplit or std::nth_element to get the smallest values 377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate <typename VectorType, typename IndexType> 397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezvoid sortWithPermutation (VectorType& vec, IndexType& perm, typename IndexType::Scalar& ncut) 407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez eigen_assert(vec.size() == perm.size()); 427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef typename IndexType::Scalar Index; 437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef typename VectorType::Scalar Scalar; 447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez bool flag; 457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (Index k = 0; k < ncut; k++) 467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez flag = false; 487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (Index j = 0; j < vec.size()-1; j++) 497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if ( vec(perm(j)) < vec(perm(j+1)) ) 517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez std::swap(perm(j),perm(j+1)); 537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez flag = true; 547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!flag) break; // The vector is in sorted order 567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/** 627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \ingroup IterativeLInearSolvers_Module 637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \brief A Restarted GMRES with deflation. 647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * This class implements a modification of the GMRES solver for 657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * sparse linear systems. The basis is built with modified 667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Gram-Schmidt. At each restart, a few approximated eigenvectors 677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * corresponding to the smallest eigenvalues are used to build a 687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * preconditioner for the next cycle. This preconditioner 697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * for deflation can be combined with any other preconditioner, 707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * the IncompleteLUT for instance. The preconditioner is applied 717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * at right of the matrix and the combination is multiplicative. 727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix. 747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner 757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Typical usage : 767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \code 777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * SparseMatrix<double> A; 787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * VectorXd x, b; 797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * //Fill A and b ... 807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * DGMRES<SparseMatrix<double> > solver; 817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * solver.set_restart(30); // Set restarting value 827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * solver.setEigenv(1); // Set the number of eigenvalues to deflate 837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * solver.compute(A); 847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * x = solver.solve(b); 857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \endcode 867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * References : 887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * [1] D. NUENTSA WAKAM and F. PACULL, Memory Efficient Hybrid 897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Algebraic Solvers for Linear Systems Arising from Compressible 907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Flows, Computers and Fluids, In Press, 917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * http://dx.doi.org/10.1016/j.compfluid.2012.03.023 927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * [2] K. Burrage and J. Erhel, On the performance of various 937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * adaptive preconditioned GMRES strategies, 5(1998), 101-121. 947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * [3] J. Erhel, K. Burrage and B. Pohl, Restarted GMRES 957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * preconditioned by deflation,J. Computational and Applied 967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Mathematics, 69(1996), 303-318. 977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 1007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, typename _Preconditioner> 1017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezclass DGMRES : public IterativeSolverBase<DGMRES<_MatrixType,_Preconditioner> > 1027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef IterativeSolverBase<DGMRES> Base; 1047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez using Base::mp_matrix; 1057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez using Base::m_error; 1067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez using Base::m_iterations; 1077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez using Base::m_info; 1087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez using Base::m_isInitialized; 1097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez using Base::m_tolerance; 1107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez public: 1117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef _MatrixType MatrixType; 1127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef typename MatrixType::Scalar Scalar; 1137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef typename MatrixType::Index Index; 1147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef typename MatrixType::RealScalar RealScalar; 1157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef _Preconditioner Preconditioner; 1167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix; 1177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef Matrix<RealScalar,Dynamic,Dynamic> DenseRealMatrix; 1187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef Matrix<Scalar,Dynamic,1> DenseVector; 1197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef Matrix<RealScalar,Dynamic,1> DenseRealVector; 1207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef Matrix<std::complex<RealScalar>, Dynamic, 1> ComplexVector; 1217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** Default constructor. */ 1247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DGMRES() : Base(),m_restart(30),m_neig(0),m_r(0),m_maxNeig(5),m_isDeflAllocated(false),m_isDeflInitialized(false) {} 1257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** Initialize the solver with matrix \a A for further \c Ax=b solving. 1277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 1287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * This constructor is a shortcut for the default constructor followed 1297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * by a call to compute(). 1307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 1317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \warning this class stores a reference to the matrix A as well as some 1327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * precomputed values that depend on it. Therefore, if \a A is changed 1337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * this class becomes invalid. Call compute() to update it with the new 1347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * matrix A, or modify a copy of A. 1357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 1367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DGMRES(const MatrixType& A) : Base(A),m_restart(30),m_neig(0),m_r(0),m_maxNeig(5),m_isDeflAllocated(false),m_isDeflInitialized(false) 1377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez {} 1387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ~DGMRES() {} 1407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A 1427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \a x0 as an initial solution. 1437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 1447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \sa compute() 1457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 1467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez template<typename Rhs,typename Guess> 1477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez inline const internal::solve_retval_with_guess<DGMRES, Rhs, Guess> 1487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez solveWithGuess(const MatrixBase<Rhs>& b, const Guess& x0) const 1497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 1507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez eigen_assert(m_isInitialized && "DGMRES is not initialized."); 1517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez eigen_assert(Base::rows()==b.rows() 1527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez && "DGMRES::solve(): invalid number of rows of the right hand side matrix b"); 1537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return internal::solve_retval_with_guess 1547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez <DGMRES, Rhs, Guess>(*this, b.derived(), x0); 1557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** \internal */ 1587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez template<typename Rhs,typename Dest> 1597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez void _solveWithGuess(const Rhs& b, Dest& x) const 1607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 1617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez bool failed = false; 1627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for(int j=0; j<b.cols(); ++j) 1637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 1647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_iterations = Base::maxIterations(); 1657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_error = Base::m_tolerance; 1667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typename Dest::ColXpr xj(x,j); 1687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez dgmres(*mp_matrix, b.col(j), xj, Base::m_preconditioner); 1697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_info = failed ? NumericalIssue 1717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez : m_error <= Base::m_tolerance ? Success 1727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez : NoConvergence; 1737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_isInitialized = true; 1747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** \internal */ 1777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez template<typename Rhs,typename Dest> 1787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez void _solve(const Rhs& b, Dest& x) const 1797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 1807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez x = b; 1817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez _solveWithGuess(b,x); 1827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 1837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** 1847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Get the restart value 1857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 1867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int restart() { return m_restart; } 1877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** 1897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Set the restart value (default is 30) 1907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 1917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez void set_restart(const int restart) { m_restart=restart; } 1927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 1937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** 1947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Set the number of eigenvalues to deflate at each restart 1957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 1967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez void setEigenv(const int neig) 1977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 1987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_neig = neig; 1997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (neig+1 > m_maxNeig) m_maxNeig = neig+1; // To allow for complex conjugates 2007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** 2037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Get the size of the deflation subspace size 2047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 2057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int deflSize() {return m_r; } 2067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez /** 2087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Set the maximum size of the deflation subspace 2097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 2107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez void setMaxEigenv(const int maxNeig) { m_maxNeig = maxNeig; } 2117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez protected: 2137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // DGMRES algorithm 2147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez template<typename Rhs, typename Dest> 2157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez void dgmres(const MatrixType& mat,const Rhs& rhs, Dest& x, const Preconditioner& precond) const; 2167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Perform one cycle of GMRES 2177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez template<typename Dest> 2187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int dgmresCycle(const MatrixType& mat, const Preconditioner& precond, Dest& x, DenseVector& r0, RealScalar& beta, const RealScalar& normRhs, int& nbIts) const; 2197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Compute data to use for deflation 2207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int dgmresComputeDeflationData(const MatrixType& mat, const Preconditioner& precond, const Index& it, Index& neig) const; 2217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Apply deflation to a vector 2227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez template<typename RhsType, typename DestType> 2237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int dgmresApplyDeflation(const RhsType& In, DestType& Out) const; 2247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ComplexVector schurValues(const ComplexSchur<DenseMatrix>& schurofH) const; 2257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ComplexVector schurValues(const RealSchur<DenseMatrix>& schurofH) const; 2267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Init data for deflation 2277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez void dgmresInitDeflation(Index& rows) const; 2287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable DenseMatrix m_V; // Krylov basis vectors 2297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable DenseMatrix m_H; // Hessenberg matrix 2307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable DenseMatrix m_Hes; // Initial hessenberg matrix wihout Givens rotations applied 2317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable Index m_restart; // Maximum size of the Krylov subspace 2327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable DenseMatrix m_U; // Vectors that form the basis of the invariant subspace 2337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable DenseMatrix m_MU; // matrix operator applied to m_U (for next cycles) 2347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable DenseMatrix m_T; /* T=U^T*M^{-1}*A*U */ 2357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable PartialPivLU<DenseMatrix> m_luT; // LU factorization of m_T 2367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable int m_neig; //Number of eigenvalues to extract at each restart 2377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable int m_r; // Current number of deflated eigenvalues, size of m_U 2387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable int m_maxNeig; // Maximum number of eigenvalues to deflate 2397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable RealScalar m_lambdaN; //Modulus of the largest eigenvalue of A 2407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable bool m_isDeflAllocated; 2417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable bool m_isDeflInitialized; 2427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //Adaptive strategy 2447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable RealScalar m_smv; // Smaller multiple of the remaining number of steps allowed 2457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez mutable bool m_force; // Force the use of deflation at each restart 2467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}; 2487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/** 2497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \brief Perform several cycles of restarted GMRES with modified Gram Schmidt, 2507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 2517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * A right preconditioner is used combined with deflation. 2527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * 2537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 2547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, typename _Preconditioner> 2557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Rhs, typename Dest> 2567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezvoid DGMRES<_MatrixType, _Preconditioner>::dgmres(const MatrixType& mat,const Rhs& rhs, Dest& x, 2577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez const Preconditioner& precond) const 2587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 2597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //Initialization 2607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int n = mat.rows(); 2617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseVector r0(n); 2627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int nbIts = 0; 2637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_H.resize(m_restart+1, m_restart); 2647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_Hes.resize(m_restart, m_restart); 2657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_V.resize(n,m_restart+1); 2667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //Initial residual vector and intial norm 2677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez x = precond.solve(x); 2687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez r0 = rhs - mat * x; 2697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez RealScalar beta = r0.norm(); 2707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez RealScalar normRhs = rhs.norm(); 2717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_error = beta/normRhs; 2727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if(m_error < m_tolerance) 2737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_info = Success; 2747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez else 2757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_info = NoConvergence; 2767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Iterative process 2787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez while (nbIts < m_iterations && m_info == NoConvergence) 2797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 2807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez dgmresCycle(mat, precond, x, r0, beta, normRhs, nbIts); 2817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Compute the new residual vector for the restart 2837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (nbIts < m_iterations && m_info == NoConvergence) 2847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez r0 = rhs - mat * x; 2857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 2867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 2877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 2887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/** 2897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \brief Perform one restart cycle of DGMRES 2907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param mat The coefficient matrix 2917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param precond The preconditioner 2927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param x the new approximated solution 2937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param r0 The initial residual vector 2947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param beta The norm of the residual computed so far 2957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param normRhs The norm of the right hand side vector 2967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param nbIts The number of iterations 2977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */ 2987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, typename _Preconditioner> 2997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename Dest> 3007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezint DGMRES<_MatrixType, _Preconditioner>::dgmresCycle(const MatrixType& mat, const Preconditioner& precond, Dest& x, DenseVector& r0, RealScalar& beta, const RealScalar& normRhs, int& nbIts) const 3017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 3027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //Initialization 3037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseVector g(m_restart+1); // Right hand side of the least square problem 3047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez g.setZero(); 3057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez g(0) = Scalar(beta); 3067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_V.col(0) = r0/beta; 3077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_info = NoConvergence; 3087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez std::vector<JacobiRotation<Scalar> >gr(m_restart); // Givens rotations 3097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int it = 0; // Number of inner iterations 3107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int n = mat.rows(); 3117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseVector tv1(n), tv2(n); //Temporary vectors 3127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez while (m_info == NoConvergence && it < m_restart && nbIts < m_iterations) 3137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 3147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Apply preconditioner(s) at right 3157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (m_isDeflInitialized ) 3167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 3177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez dgmresApplyDeflation(m_V.col(it), tv1); // Deflation 3187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez tv2 = precond.solve(tv1); 3197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 3207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez else 3217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 3227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez tv2 = precond.solve(m_V.col(it)); // User's selected preconditioner 3237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 3247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez tv1 = mat * tv2; 3257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Orthogonalize it with the previous basis in the basis using modified Gram-Schmidt 3277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Scalar coef; 3287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int i = 0; i <= it; ++i) 3297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 3307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez coef = tv1.dot(m_V.col(i)); 3317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez tv1 = tv1 - coef * m_V.col(i); 3327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_H(i,it) = coef; 3337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_Hes(i,it) = coef; 3347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 3357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Normalize the vector 3367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez coef = tv1.norm(); 3377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_V.col(it+1) = tv1/coef; 3387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_H(it+1, it) = coef; 3397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// m_Hes(it+1,it) = coef; 3407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // FIXME Check for happy breakdown 3427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Update Hessenberg matrix with Givens rotations 3447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int i = 1; i <= it; ++i) 3457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 3467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_H.col(it).applyOnTheLeft(i-1,i,gr[i-1].adjoint()); 3477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 3487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Compute the new plane rotation 3497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez gr[it].makeGivens(m_H(it, it), m_H(it+1,it)); 3507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Apply the new rotation 3517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_H.col(it).applyOnTheLeft(it,it+1,gr[it].adjoint()); 3527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez g.applyOnTheLeft(it,it+1, gr[it].adjoint()); 3537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez beta = std::abs(g(it+1)); 3557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_error = beta/normRhs; 3567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez std::cerr << nbIts << " Relative Residual Norm " << m_error << std::endl; 3577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez it++; nbIts++; 3587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (m_error < m_tolerance) 3607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 3617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // The method has converged 3627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_info = Success; 3637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez break; 3647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 3657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 3667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Compute the new coefficients by solving the least square problem 3687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// it++; 3697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //FIXME Check first if the matrix is singular ... zero diagonal 3707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseVector nrs(m_restart); 3717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez nrs = m_H.topLeftCorner(it,it).template triangularView<Upper>().solve(g.head(it)); 3727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Form the new solution 3747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (m_isDeflInitialized) 3757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 3767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez tv1 = m_V.leftCols(it) * nrs; 3777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez dgmresApplyDeflation(tv1, tv2); 3787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez x = x + precond.solve(tv2); 3797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 3807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez else 3817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez x = x + precond.solve(m_V.leftCols(it) * nrs); 3827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Go for a new cycle and compute data for deflation 3847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if(nbIts < m_iterations && m_info == NoConvergence && m_neig > 0 && (m_r+m_neig) < m_maxNeig) 3857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez dgmresComputeDeflationData(mat, precond, it, m_neig); 3867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return 0; 3877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 3897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 3917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, typename _Preconditioner> 3927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezvoid DGMRES<_MatrixType, _Preconditioner>::dgmresInitDeflation(Index& rows) const 3937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 3947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_U.resize(rows, m_maxNeig); 3957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_MU.resize(rows, m_maxNeig); 3967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_T.resize(m_maxNeig, m_maxNeig); 3977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_lambdaN = 0.0; 3987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_isDeflAllocated = true; 3997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 4007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, typename _Preconditioner> 4027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezinline typename DGMRES<_MatrixType, _Preconditioner>::ComplexVector DGMRES<_MatrixType, _Preconditioner>::schurValues(const ComplexSchur<DenseMatrix>& schurofH) const 4037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 4047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return schurofH.matrixT().diagonal(); 4057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 4067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, typename _Preconditioner> 4087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezinline typename DGMRES<_MatrixType, _Preconditioner>::ComplexVector DGMRES<_MatrixType, _Preconditioner>::schurValues(const RealSchur<DenseMatrix>& schurofH) const 4097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 4107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef typename MatrixType::Index Index; 4117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez const DenseMatrix& T = schurofH.matrixT(); 4127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Index it = T.rows(); 4137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ComplexVector eig(it); 4147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Index j = 0; 4157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez while (j < it-1) 4167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (T(j+1,j) ==Scalar(0)) 4187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez eig(j) = std::complex<RealScalar>(T(j,j),RealScalar(0)); 4207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez j++; 4217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 4227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez else 4237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez eig(j) = std::complex<RealScalar>(T(j,j),T(j+1,j)); 4257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez eig(j+1) = std::complex<RealScalar>(T(j,j+1),T(j+1,j+1)); 4267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez j++; 4277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 4287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 4297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (j < it-1) eig(j) = std::complex<RealScalar>(T(j,j),RealScalar(0)); 4307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return eig; 4317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 4327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate< typename _MatrixType, typename _Preconditioner> 4347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezint DGMRES<_MatrixType, _Preconditioner>::dgmresComputeDeflationData(const MatrixType& mat, const Preconditioner& precond, const Index& it, Index& neig) const 4357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 4367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // First, find the Schur form of the Hessenberg matrix H 4377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typename internal::conditional<NumTraits<Scalar>::IsComplex, ComplexSchur<DenseMatrix>, RealSchur<DenseMatrix> >::type schurofH; 4387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez bool computeU = true; 4397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseMatrix matrixQ(it,it); 4407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez matrixQ.setIdentity(); 4417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez schurofH.computeFromHessenberg(m_Hes.topLeftCorner(it,it), matrixQ, computeU); 4427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez ComplexVector eig(it); 4447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Matrix<Index,Dynamic,1>perm(it); 4457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez eig = this->schurValues(schurofH); 4467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Reorder the absolute values of Schur values 4487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseRealVector modulEig(it); 4497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int j=0; j<it; ++j) modulEig(j) = std::abs(eig(j)); 4507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez perm.setLinSpaced(it,0,it-1); 4517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez internal::sortWithPermutation(modulEig, perm, neig); 4527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!m_lambdaN) 4547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_lambdaN = (std::max)(modulEig.maxCoeff(), m_lambdaN); 4567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 4577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //Count the real number of extracted eigenvalues (with complex conjugates) 4587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez int nbrEig = 0; 4597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez while (nbrEig < neig) 4607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if(eig(perm(it-nbrEig-1)).imag() == RealScalar(0)) nbrEig++; 4627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez else nbrEig += 2; 4637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 4647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Extract the Schur vectors corresponding to the smallest Ritz values 4657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseMatrix Sr(it, nbrEig); 4667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Sr.setZero(); 4677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int j = 0; j < nbrEig; j++) 4687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Sr.col(j) = schurofH.matrixU().col(perm(it-j-1)); 4707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 4717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Form the Schur vectors of the initial matrix using the Krylov basis 4737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseMatrix X; 4747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez X = m_V.leftCols(it) * Sr; 4757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (m_r) 4767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Orthogonalize X against m_U using modified Gram-Schmidt 4787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int j = 0; j < nbrEig; j++) 4797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int k =0; k < m_r; k++) 4807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez X.col(j) = X.col(j) - (m_U.col(k).dot(X.col(j)))*m_U.col(k); 4817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 4827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Compute m_MX = A * M^-1 * X 4847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez Index m = m_V.rows(); 4857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if (!m_isDeflAllocated) 4867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez dgmresInitDeflation(m); 4877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseMatrix MX(m, nbrEig); 4887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseVector tv1(m); 4897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int j = 0; j < nbrEig; j++) 4907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez tv1 = mat * X.col(j); 4927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez MX.col(j) = precond.solve(tv1); 4937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 4947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 4957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //Update m_T = [U'MU U'MX; X'MU X'MX] 4967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_T.block(m_r, m_r, nbrEig, nbrEig) = X.transpose() * MX; 4977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez if(m_r) 4987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 4997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_T.block(0, m_r, m_r, nbrEig) = m_U.leftCols(m_r).transpose() * MX; 5007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_T.block(m_r, 0, nbrEig, m_r) = X.transpose() * m_MU.leftCols(m_r); 5017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 5027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 5037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Save X into m_U and m_MX in m_MU 5047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int j = 0; j < nbrEig; j++) m_U.col(m_r+j) = X.col(j); 5057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez for (int j = 0; j < nbrEig; j++) m_MU.col(m_r+j) = MX.col(j); 5067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Increase the size of the invariant subspace 5077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_r += nbrEig; 5087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 5097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez // Factorize m_T into m_luT 5107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_luT.compute(m_T.topLeftCorner(m_r, m_r)); 5117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 5127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez //FIXME CHeck if the factorization was correctly done (nonsingular matrix) 5137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez m_isDeflInitialized = true; 5147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return 0; 5157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 5167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename _MatrixType, typename _Preconditioner> 5177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate<typename RhsType, typename DestType> 5187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezint DGMRES<_MatrixType, _Preconditioner>::dgmresApplyDeflation(const RhsType &x, DestType &y) const 5197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 5207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez DenseVector x1 = m_U.leftCols(m_r).transpose() * x; 5217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez y = x + m_U.leftCols(m_r) * ( m_lambdaN * m_luT.solve(x1) - x1); 5227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez return 0; 5237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} 5247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 5257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace internal { 5267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 5277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez template<typename _MatrixType, typename _Preconditioner, typename Rhs> 5287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezstruct solve_retval<DGMRES<_MatrixType, _Preconditioner>, Rhs> 5297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez : solve_retval_base<DGMRES<_MatrixType, _Preconditioner>, Rhs> 5307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{ 5317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez typedef DGMRES<_MatrixType, _Preconditioner> Dec; 5327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) 5337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 5347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez template<typename Dest> void evalTo(Dest& dst) const 5357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez { 5367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez dec()._solve(rhs(),dst); 5377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez } 5387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}; 5397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace internal 5407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez 5417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace Eigen 5427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#endif 543