// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2011 Gael Guennebaud // Copyright (C) 2012 Kolja Brix // // 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 #include "sparse_solver.h" #include template void test_gmres_T() { GMRES, DiagonalPreconditioner > gmres_colmajor_diag; GMRES, IdentityPreconditioner> gmres_colmajor_I; GMRES, IncompleteLUT > gmres_colmajor_ilut; // GMRES, SSORPreconditioner > gmres_colmajor_ssor; CALL_SUBTEST(check_sparse_square_solving(gmres_colmajor_diag)); // CALL_SUBTEST( check_sparse_square_solving(gmres_colmajor_I) ); CALL_SUBTEST(check_sparse_square_solving(gmres_colmajor_ilut)); // CALL_SUBTEST( check_sparse_square_solving(gmres_colmajor_ssor) ); } void test_gmres_solve_with_guess_tolerance() { const Index size = 20; SparseMatrix matrix(size, size); std::vector > triplets; for (Index i = 0; i < size; ++i) { triplets.emplace_back(i, i, 2.0 + double(i) / double(size)); if (i > 0) triplets.emplace_back(i, i - 1, -0.25); if (i + 1 < size) triplets.emplace_back(i, i + 1, 0.125); } matrix.setFromTriplets(triplets.begin(), triplets.end()); VectorXd rhs = VectorXd::Ones(size); VectorXd guess(size); for (Index i = 0; i < size; ++i) { guess[i] = ((i % 2) ? 1.0 : -1.0) * 1e8; } GMRES, DiagonalPreconditioner > gmres; gmres.compute(matrix); gmres.setTolerance(1e-6); gmres.setMaxIterations(size); gmres.set_restart(size); VectorXd x = gmres.solveWithGuess(rhs, guess); DiagonalPreconditioner preconditioner(matrix); const VectorXd residual = matrix * x - rhs; const double relativeResidual = preconditioner.solve(residual).norm() / preconditioner.solve(rhs).norm(); VERIFY(gmres.info() == Success); VERIFY(gmres.iterations() > 1); VERIFY(relativeResidual < gmres.tolerance()); VERIFY(gmres.error() < gmres.tolerance()); } void test_gmres_large_restart() { const Index size = 4; SparseMatrix matrix(size, size); std::vector > triplets; for (Index i = 0; i < size; ++i) { triplets.emplace_back(i, i, 2.0 + double(i)); } matrix.setFromTriplets(triplets.begin(), triplets.end()); const VectorXd rhs = VectorXd::LinSpaced(size, 1.0, 4.0); GMRES, IdentityPreconditioner> gmres; gmres.compute(matrix); gmres.setTolerance(1e-12); gmres.setMaxIterations(size); gmres.set_restart(1000000); VectorXd x = gmres.solve(rhs); VERIFY(gmres.info() == Success); VERIFY_IS_APPROX(matrix * x, rhs); } EIGEN_DECLARE_TEST(gmres) { CALL_SUBTEST_1(test_gmres_T()); CALL_SUBTEST_2(test_gmres_T >()); CALL_SUBTEST_3(test_gmres_solve_with_guess_tolerance()); CALL_SUBTEST_4(test_gmres_large_restart()); }