diff --git a/src/TNL/Solvers/LinearSolverTypeResolver.h b/src/TNL/Solvers/LinearSolverTypeResolver.h index 18bf08039960a3929dfb07d651ce8b8f10870841..5615ea7077bad28229b21b8a45c9eb297c5aa3d6 100644 --- a/src/TNL/Solvers/LinearSolverTypeResolver.h +++ b/src/TNL/Solvers/LinearSolverTypeResolver.h @@ -12,6 +12,8 @@ #pragma once +#include <vector> +#include <string> #include <memory> #include <TNL/Solvers/Linear/SOR.h> @@ -28,54 +30,89 @@ namespace TNL { namespace Solvers { +inline std::vector<std::string> +getLinearSolverOptions() +{ + return { + "sor", + "cg", + "bicgstab", + "bicgstabl", + "gmres", + "tfqmr" +#ifdef HAVE_UMFPACK + , "umfpack" +#endif + }; +} + +inline std::vector<std::string> +getPreconditionerOptions() +{ + return { + "none", + "diagonal", + "ilu0", + "ilut" + }; +} + template< typename MatrixType > std::shared_ptr< Linear::LinearSolver< MatrixType > > -getLinearSolver( const Config::ParameterContainer& parameters ) +getLinearSolver( std::string name ) { - const String& discreteSolver = parameters.getParameter< String >( "discrete-solver" ); - - if( discreteSolver == "sor" ) + if( name == "sor" ) return std::make_shared< Linear::SOR< MatrixType > >(); - if( discreteSolver == "cg" ) + if( name == "cg" ) return std::make_shared< Linear::CG< MatrixType > >(); - if( discreteSolver == "bicgstab" ) + if( name == "bicgstab" ) return std::make_shared< Linear::BICGStab< MatrixType > >(); - if( discreteSolver == "bicgstabl" ) + if( name == "bicgstabl" ) return std::make_shared< Linear::BICGStabL< MatrixType > >(); - if( discreteSolver == "gmres" ) + if( name == "gmres" ) return std::make_shared< Linear::GMRES< MatrixType > >(); - if( discreteSolver == "tfqmr" ) + if( name == "tfqmr" ) return std::make_shared< Linear::TFQMR< MatrixType > >(); #ifdef HAVE_UMFPACK if( discreteSolver == "umfpack" ) return std::make_shared< Linear::UmfpackWrapper< MatrixType > >(); #endif - std::cerr << "Unknown semi-implicit discrete solver " << discreteSolver << ". It can be only: sor, cg, bicgstab, bicgstabl, gmres, tfqmr"; -#ifdef HAVE_UMFPACK - std::cerr << ", umfpack" -#endif - std::cerr << "." << std::endl; + std::string options; + for( auto o : getLinearSolverOptions() ) + if( options.empty() ) + options += o; + else + options += ", " + o; + + std::cerr << "Unknown semi-implicit discrete solver " << name << ". It can be only: " << options << "." << std::endl; return nullptr; } template< typename MatrixType > std::shared_ptr< Linear::Preconditioners::Preconditioner< MatrixType > > -getPreconditioner( const Config::ParameterContainer& parameters ) +getPreconditioner( std::string name ) { - const String& preconditioner = parameters.getParameter< String >( "preconditioner" ); - if( preconditioner == "none" ) + if( name == "none" ) return nullptr; - if( preconditioner == "diagonal" ) + if( name == "diagonal" ) return std::make_shared< Linear::Preconditioners::Diagonal< MatrixType > >(); - if( preconditioner == "ilu0" ) + if( name == "ilu0" ) return std::make_shared< Linear::Preconditioners::ILU0< MatrixType > >(); - if( preconditioner == "ilut" ) + if( name == "ilut" ) return std::make_shared< Linear::Preconditioners::ILUT< MatrixType > >(); - std::cerr << "Unknown preconditioner " << preconditioner << ". It can be only: none, diagonal, ilu0, ilut." << std::endl; + std::string options; + for( auto o : getPreconditionerOptions() ) + if( options.empty() ) + options += o; + else + options += ", " + o; + + std::cerr << "Unknown preconditioner " << name << ". It can be only: " << options << "." << std::endl; + return nullptr; } diff --git a/src/TNL/Solvers/PDE/SemiImplicitTimeStepper_impl.h b/src/TNL/Solvers/PDE/SemiImplicitTimeStepper_impl.h index 5faa7902e179781e413dca4715d73e06e5dffdbb..3e8d106b272cf66bf2ed867d0a0943d0b47d8944 100644 --- a/src/TNL/Solvers/PDE/SemiImplicitTimeStepper_impl.h +++ b/src/TNL/Solvers/PDE/SemiImplicitTimeStepper_impl.h @@ -33,14 +33,16 @@ setup( const Config::ParameterContainer& parameters, const String& prefix ) { // set up the linear solver - linearSystemSolver = getLinearSolver< MatrixType >( parameters ); + const String& discreteSolver = parameters.getParameter< String >( prefix + "discrete-solver" ); + linearSystemSolver = getLinearSolver< MatrixType >( discreteSolver ); if( ! linearSystemSolver ) return false; if( ! linearSystemSolver->setup( parameters ) ) return false; // set up the preconditioner - preconditioner = getPreconditioner< MatrixType >( parameters ); + const String& preconditionerName = parameters.getParameter< String >( prefix + "preconditioner" ); + preconditioner = getPreconditioner< MatrixType >( preconditionerName ); if( preconditioner ) { linearSystemSolver->setPreconditioner( preconditioner ); if( ! preconditioner->setup( parameters ) ) diff --git a/src/TNL/Solvers/SolverConfig_impl.h b/src/TNL/Solvers/SolverConfig_impl.h index e5673d5c1ed45ea9a28f8615cd4f099284bb8875..9d3515157feeac58a73b56353274524a56f6ec1a 100644 --- a/src/TNL/Solvers/SolverConfig_impl.h +++ b/src/TNL/Solvers/SolverConfig_impl.h @@ -15,16 +15,7 @@ #include <TNL/Solvers/DummyProblem.h> #include <TNL/Solvers/PDE/ExplicitTimeStepper.h> #include <TNL/Solvers/PDE/TimeDependentPDESolver.h> -#include <TNL/Solvers/Linear/SOR.h> -#include <TNL/Solvers/Linear/CG.h> -#include <TNL/Solvers/Linear/BICGStab.h> -#include <TNL/Solvers/Linear/BICGStabL.h> -#include <TNL/Solvers/Linear/GMRES.h> -#include <TNL/Solvers/Linear/TFQMR.h> -#include <TNL/Solvers/Linear/UmfpackWrapper.h> -#include <TNL/Solvers/Linear/Preconditioners/Diagonal.h> -#include <TNL/Solvers/Linear/Preconditioners/ILU0.h> -#include <TNL/Solvers/Linear/Preconditioners/ILUT.h> +#include <TNL/Solvers/LinearSolverTypeResolver.h> #include <TNL/Matrices/CSR.h> #include <TNL/Meshes/DistributedMeshes/DistributedGrid.h> @@ -124,23 +115,11 @@ bool SolverConfig< ConfigTag, ProblemConfig >::configSetup( Config::ConfigDescri } if( ConfigTagTimeDiscretisation< ConfigTag, SemiImplicitTimeDiscretisationTag >::enabled ) { - config.addEntryEnum( "cg" ); - config.addEntryEnum( "bicgstab" ); - config.addEntryEnum( "bicgstabl" ); - config.addEntryEnum( "gmres" ); - config.addEntryEnum( "tfqmr" ); - config.addEntryEnum( "sor" ); -#ifdef HAVE_UMFPACK - config.addEntryEnum( "umfpack" ); -#endif + for( auto o : getLinearSolverOptions() ) + config.addEntryEnum( String( o ) ); config.addEntry< String >( "preconditioner", "The preconditioner for the discrete solver:", "none" ); - config.addEntryEnum( "none" ); - config.addEntryEnum( "diagonal" ); - // TODO: implement parallel ILU or device-dependent build config tags for preconditioners -#ifndef HAVE_CUDA - config.addEntryEnum( "ilu0" ); - config.addEntryEnum( "ilut" ); -#endif + for( auto o : getPreconditionerOptions() ) + config.addEntryEnum( String( o ) ); } if( ConfigTagTimeDiscretisation< ConfigTag, ExplicitTimeDiscretisationTag >::enabled || ConfigTagTimeDiscretisation< ConfigTag, SemiImplicitTimeDiscretisationTag >::enabled )