From e777bc01112240f0ceb352ae1d9f9f6903a5797e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Buchwald?= <joerg.buchwald@ufz.de> Date: Fri, 7 Jan 2022 20:33:37 +0100 Subject: [PATCH] add IDRS, BiCGSTABL and IDRSTABL iterative solvers --- MathLib/LinAlg/Eigen/EigenLinearSolver.cpp | 221 +++++++++++++++++- MathLib/LinAlg/Eigen/EigenLinearSolver.h | 5 + MathLib/LinAlg/Eigen/EigenOption.cpp | 23 ++ MathLib/LinAlg/Eigen/EigenOption.h | 8 + .../LinAlg/Eigen/LinearSolverOptionsParser.h | 55 +++++ 5 files changed, 311 insertions(+), 1 deletion(-) diff --git a/MathLib/LinAlg/Eigen/EigenLinearSolver.cpp b/MathLib/LinAlg/Eigen/EigenLinearSolver.cpp index 6154ee1393c..9e316e1e4ef 100644 --- a/MathLib/LinAlg/Eigen/EigenLinearSolver.cpp +++ b/MathLib/LinAlg/Eigen/EigenLinearSolver.cpp @@ -19,7 +19,7 @@ #endif #ifdef USE_EIGEN_UNSUPPORTED -#include <unsupported/Eigen/src/IterativeSolvers/GMRES.h> +#include <unsupported/Eigen/IterativeSolvers> #include <unsupported/Eigen/src/IterativeSolvers/Scaling.h> #endif @@ -94,6 +94,16 @@ public: solver_.setMaxIterations(opt.max_iterations); MathLib::details::EigenIterativeLinearSolver<T_SOLVER>::setRestart( opt.restart); + MathLib::details::EigenIterativeLinearSolver<T_SOLVER>::setL( + opt.l); + MathLib::details::EigenIterativeLinearSolver<T_SOLVER>::setS( + opt.s); + MathLib::details::EigenIterativeLinearSolver<T_SOLVER>::setSmoothing( + opt.smoothing); + MathLib::details::EigenIterativeLinearSolver<T_SOLVER>::setAngle( + opt.angle); + MathLib::details::EigenIterativeLinearSolver<T_SOLVER>::setResidualUpdate( + opt.residualupdate); if (!A.isCompressed()) { @@ -124,6 +134,11 @@ public: private: T_SOLVER solver_; void setRestart(int const /*restart*/) {} + void setL(int const /*l*/) {} + void setS(int const /*s*/) {} + void setAngle(double const /*angle*/) {} + void setSmoothing(bool const /*smoothing*/) {} + void setResidualUpdate(bool const /*residual update*/) {} }; /// Specialization for (all) three preconditioners separately @@ -154,6 +169,177 @@ void EigenIterativeLinearSolver< INFO("-> set restart value: {:d}", solver_.get_restart()); } +/// BiCGSTABL +template <> +void EigenIterativeLinearSolver< + Eigen::BiCGSTABL<EigenMatrix::RawMatrixType, + Eigen::IdentityPreconditioner>>::setL(int const l) +{ + solver_.setL(l); +} + +template <> +void EigenIterativeLinearSolver<Eigen::BiCGSTABL< + EigenMatrix::RawMatrixType, + Eigen::DiagonalPreconditioner<double>>>::setL(int const l) +{ + solver_.setL(l); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::BiCGSTABL<EigenMatrix::RawMatrixType, + Eigen::IncompleteLUT<double>>>::setL(int const l) +{ + solver_.setL(l); +} + +/// IDRS +template <> +void EigenIterativeLinearSolver< + Eigen::IDRS<EigenMatrix::RawMatrixType, + Eigen::IdentityPreconditioner>>::setS(int const s) +{ + solver_.setS(s); +} + +template <> +void EigenIterativeLinearSolver<Eigen::IDRS< + EigenMatrix::RawMatrixType, + Eigen::DiagonalPreconditioner<double>>>::setS(int const s) +{ + solver_.setS(s); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRS<EigenMatrix::RawMatrixType, + Eigen::IncompleteLUT<double>>>::setS(int const s) +{ + solver_.setS(s); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRS<EigenMatrix::RawMatrixType, + Eigen::IdentityPreconditioner>>::setAngle(double const angle) +{ + solver_.setAngle(angle); +} + +template <> +void EigenIterativeLinearSolver<Eigen::IDRS< + EigenMatrix::RawMatrixType, + Eigen::DiagonalPreconditioner<double>>>::setAngle(double const angle) +{ + solver_.setAngle(angle); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRS<EigenMatrix::RawMatrixType, + Eigen::IncompleteLUT<double>>>::setAngle(double const angle) +{ + solver_.setAngle(angle); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRS<EigenMatrix::RawMatrixType, + Eigen::IdentityPreconditioner>>::setSmoothing(bool const smoothing) +{ + solver_.setSmoothing(smoothing); +} + +template <> +void EigenIterativeLinearSolver<Eigen::IDRS< + EigenMatrix::RawMatrixType, + Eigen::DiagonalPreconditioner<double>>>::setSmoothing(bool const smoothing) +{ + solver_.setSmoothing(smoothing); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRS<EigenMatrix::RawMatrixType, + Eigen::IncompleteLUT<double>>>::setSmoothing(bool const smoothing) +{ + solver_.setSmoothing(smoothing); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRS<EigenMatrix::RawMatrixType, + Eigen::IdentityPreconditioner>>::setResidualUpdate(bool const residualupdate) +{ + solver_.setResidualUpdate(residualupdate); +} + +template <> +void EigenIterativeLinearSolver<Eigen::IDRS< + EigenMatrix::RawMatrixType, + Eigen::DiagonalPreconditioner<double>>>::setResidualUpdate(bool const residualupdate) +{ + solver_.setResidualUpdate(residualupdate); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRS<EigenMatrix::RawMatrixType, + Eigen::IncompleteLUT<double>>>::setResidualUpdate(bool const residualupdate) +{ + solver_.setResidualUpdate(residualupdate); +} + +/// IDRSTABL +template <> +void EigenIterativeLinearSolver< + Eigen::IDRSTABL<EigenMatrix::RawMatrixType, + Eigen::IdentityPreconditioner>>::setS(int const s) +{ + solver_.setS(s); +} + +template <> +void EigenIterativeLinearSolver<Eigen::IDRSTABL< + EigenMatrix::RawMatrixType, + Eigen::DiagonalPreconditioner<double>>>::setS(int const s) +{ + solver_.setS(s); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRSTABL<EigenMatrix::RawMatrixType, + Eigen::IncompleteLUT<double>>>::setS(int const s) +{ + solver_.setS(s); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRSTABL<EigenMatrix::RawMatrixType, + Eigen::IdentityPreconditioner>>::setL(int const l) +{ + solver_.setL(l); +} + +template <> +void EigenIterativeLinearSolver<Eigen::IDRSTABL< + EigenMatrix::RawMatrixType, + Eigen::DiagonalPreconditioner<double>>>::setL(int const l) +{ + solver_.setL(l); +} + +template <> +void EigenIterativeLinearSolver< + Eigen::IDRSTABL<EigenMatrix::RawMatrixType, + Eigen::IncompleteLUT<double>>>::setL(int const l) +{ + solver_.setL(l); +} + template <template <typename, typename> class Solver, typename Precon> std::unique_ptr<EigenLinearSolverBase> createIterativeSolver() { @@ -197,6 +383,16 @@ std::unique_ptr<EigenLinearSolverBase> createIterativeSolver( { return createIterativeSolver<Eigen::BiCGSTAB>(precon_type); } + case EigenOption::SolverType::BiCGSTABL: + { +#ifdef USE_EIGEN_UNSUPPORTED + return createIterativeSolver<Eigen::BiCGSTABL>(precon_type); +#else + OGS_FATAL( + "The code is not compiled with the Eigen unsupported modules. " + "Linear solver type BiCGSTABL is not available."); +#endif + } case EigenOption::SolverType::CG: { return createIterativeSolver<EigenCGSolver>(precon_type); @@ -209,6 +405,26 @@ std::unique_ptr<EigenLinearSolverBase> createIterativeSolver( OGS_FATAL( "The code is not compiled with the Eigen unsupported modules. " "Linear solver type GMRES is not available."); +#endif + } + case EigenOption::SolverType::IDRS: + { +#ifdef USE_EIGEN_UNSUPPORTED + return createIterativeSolver<Eigen::IDRS>(precon_type); +#else + OGS_FATAL( + "The code is not compiled with the Eigen unsupported modules. " + "Linear solver type IDRS is not available."); +#endif + } + case EigenOption::SolverType::IDRSTABL: + { +#ifdef USE_EIGEN_UNSUPPORTED + return createIterativeSolver<Eigen::IDRSTABL>(precon_type); +#else + OGS_FATAL( + "The code is not compiled with the Eigen unsupported modules. " + "Linear solver type IDRSTABL is not available."); #endif } default: @@ -235,8 +451,11 @@ EigenLinearSolver::EigenLinearSolver(std::string const& /*solver_name*/, return; } case EigenOption::SolverType::BiCGSTAB: + case EigenOption::SolverType::BiCGSTABL: case EigenOption::SolverType::CG: case EigenOption::SolverType::GMRES: + case EigenOption::SolverType::IDRS: + case EigenOption::SolverType::IDRSTABL: solver_ = details::createIterativeSolver(option_.solver_type, option_.precon_type); return; diff --git a/MathLib/LinAlg/Eigen/EigenLinearSolver.h b/MathLib/LinAlg/Eigen/EigenLinearSolver.h index 7585f9528a1..772818d9216 100644 --- a/MathLib/LinAlg/Eigen/EigenLinearSolver.h +++ b/MathLib/LinAlg/Eigen/EigenLinearSolver.h @@ -52,6 +52,11 @@ protected: EigenOption option_; std::unique_ptr<EigenLinearSolverBase> solver_; void setRestart(); + void setL(); + void setS(); + void setSmoothing(); + void setAngle(); + void setResidualUpdate(); }; } // namespace MathLib diff --git a/MathLib/LinAlg/Eigen/EigenOption.cpp b/MathLib/LinAlg/Eigen/EigenOption.cpp index b0587329f1d..15f89cd55bc 100644 --- a/MathLib/LinAlg/Eigen/EigenOption.cpp +++ b/MathLib/LinAlg/Eigen/EigenOption.cpp @@ -23,6 +23,11 @@ EigenOption::EigenOption() #ifdef USE_EIGEN_UNSUPPORTED scaling = false; restart = 30; + l = 2; + s = 4; + angle = 0.7; + smoothing = false; + residualupdate = false; #endif } @@ -37,6 +42,18 @@ EigenOption::SolverType EigenOption::getSolverType( { return SolverType::BiCGSTAB; } + if (solver_name == "BiCGSTABL") + { + return SolverType::BiCGSTABL; + } + if (solver_name == "IDRS") + { + return SolverType::IDRS; + } + if (solver_name == "IDRSTABL") + { + return SolverType::IDRSTABL; + } if (solver_name == "SparseLU") { return SolverType::SparseLU; @@ -80,6 +97,12 @@ std::string EigenOption::getSolverName(SolverType const solver_type) return "CG"; case SolverType::BiCGSTAB: return "BiCGSTAB"; + case SolverType::BiCGSTABL: + return "BiCGSTABL"; + case SolverType::IDRS: + return "IDRS"; + case SolverType::IDRSTABL: + return "IDRSTABL"; case SolverType::SparseLU: return "SparseLU"; case SolverType::PardisoLU: diff --git a/MathLib/LinAlg/Eigen/EigenOption.h b/MathLib/LinAlg/Eigen/EigenOption.h index 24ced185fad..61a88797cf9 100644 --- a/MathLib/LinAlg/Eigen/EigenOption.h +++ b/MathLib/LinAlg/Eigen/EigenOption.h @@ -22,6 +22,9 @@ struct EigenOption final { CG, BiCGSTAB, + BiCGSTABL, + IDRS, + IDRSTABL, SparseLU, PardisoLU, GMRES @@ -48,6 +51,11 @@ struct EigenOption final bool scaling; /// Restart value for the GMRES solver int restart; + int l; + int s; + double angle; + bool smoothing; + bool residualupdate; #endif /// Constructor diff --git a/MathLib/LinAlg/Eigen/LinearSolverOptionsParser.h b/MathLib/LinAlg/Eigen/LinearSolverOptionsParser.h index 775ca11ffd6..87c2ed0df17 100644 --- a/MathLib/LinAlg/Eigen/LinearSolverOptionsParser.h +++ b/MathLib/LinAlg/Eigen/LinearSolverOptionsParser.h @@ -101,6 +101,61 @@ struct LinearSolverOptionsParser<EigenLinearSolver> final OGS_FATAL( "The code is not compiled with the Eigen unsupported modules. " "GMRES/GMRES option restart is not available."); +#endif + } + if (auto l = + //! \ogs_file_param{prj__linear_solvers__linear_solver__eigen__l} + config->getConfigParameterOptional<int>("l")) + { +#ifdef USE_EIGEN_UNSUPPORTED + options.l = *l; +#else + OGS_FATAL( + "The code is not compiled with the Eigen unsupported modules."); +#endif + } + if (auto s = + //! \ogs_file_param{prj__linear_solvers__linear_solver__eigen__s} + config->getConfigParameterOptional<int>("s")) + { +#ifdef USE_EIGEN_UNSUPPORTED + options.s = *s; +#else + OGS_FATAL( + "The code is not compiled with the Eigen unsupported modules."); +#endif + } + if (auto smoothing = + //! \ogs_file_param{prj__linear_solvers__linear_solver__eigen__smoothing} + config->getConfigParameterOptional<int>("smoothing")) + { +#ifdef USE_EIGEN_UNSUPPORTED + options.smoothing = *smoothing; +#else + OGS_FATAL( + "The code is not compiled with the Eigen unsupported modules."); +#endif + } + if (auto angle = + //! \ogs_file_param{prj__linear_solvers__linear_solver__eigen__angle} + config->getConfigParameterOptional<int>("angle")) + { +#ifdef USE_EIGEN_UNSUPPORTED + options.angle = *angle; +#else + OGS_FATAL( + "The code is not compiled with the Eigen unsupported modules."); +#endif + } + if (auto residualupdate = + //! \ogs_file_param{prj__linear_solvers__linear_solver__eigen__residual_update} + config->getConfigParameterOptional<int>("residual_update")) + { +#ifdef USE_EIGEN_UNSUPPORTED + options.residualupdate = *residualupdate; +#else + OGS_FATAL( + "The code is not compiled with the Eigen unsupported modules."); #endif } return {prefix, options}; -- GitLab