Skip to content
Snippets Groups Projects
Commit 486eaeec authored by Max Jaeschke's avatar Max Jaeschke
Browse files

Apply normalization of linear rectangular equation only, if solver only supports square

parent f5546513
No related branches found
No related tags found
No related merge requests found
...@@ -496,23 +496,30 @@ EigenLinearSolver::EigenLinearSolver(std::string const& /*solver_name*/, ...@@ -496,23 +496,30 @@ EigenLinearSolver::EigenLinearSolver(std::string const& /*solver_name*/,
Eigen::SparseLU<Matrix, Eigen::COLAMDOrdering<int>>; Eigen::SparseLU<Matrix, Eigen::COLAMDOrdering<int>>;
solver_ = std::make_unique< solver_ = std::make_unique<
details::EigenDirectLinearSolver<SolverType>>(); details::EigenDirectLinearSolver<SolverType>>();
can_solve_rectangular_ = false;
return; return;
} }
case EigenOption::SolverType::BiCGSTAB: case EigenOption::SolverType::BiCGSTAB:
case EigenOption::SolverType::BiCGSTABL: case EigenOption::SolverType::BiCGSTABL:
case EigenOption::SolverType::CG: case EigenOption::SolverType::CG:
case EigenOption::SolverType::LeastSquareCG:
case EigenOption::SolverType::GMRES: case EigenOption::SolverType::GMRES:
case EigenOption::SolverType::IDRS: case EigenOption::SolverType::IDRS:
case EigenOption::SolverType::IDRSTABL: case EigenOption::SolverType::IDRSTABL:
solver_ = details::createIterativeSolver(option_.solver_type, solver_ = details::createIterativeSolver(option_.solver_type,
option_.precon_type); option_.precon_type);
can_solve_rectangular_ = false;
return;
case EigenOption::SolverType::LeastSquareCG:
solver_ = details::createIterativeSolver(option_.solver_type,
option_.precon_type);
can_solve_rectangular_ = true;
return; return;
case EigenOption::SolverType::PardisoLU: case EigenOption::SolverType::PardisoLU:
{ {
#ifdef USE_MKL #ifdef USE_MKL
using SolverType = Eigen::PardisoLU<EigenMatrix::RawMatrixType>; using SolverType = Eigen::PardisoLU<EigenMatrix::RawMatrixType>;
solver_.reset(new details::EigenDirectLinearSolver<SolverType>); solver_.reset(new details::EigenDirectLinearSolver<SolverType>);
can_solve_rectangular_ = false;
return; return;
#else #else
OGS_FATAL( OGS_FATAL(
......
...@@ -71,9 +71,13 @@ public: ...@@ -71,9 +71,13 @@ public:
MathLib::LinearSolverBehaviour const linear_solver_behaviour = MathLib::LinearSolverBehaviour const linear_solver_behaviour =
MathLib::LinearSolverBehaviour::RECOMPUTE); MathLib::LinearSolverBehaviour::RECOMPUTE);
/// Get, if the solver can handle rectangular equation systems
bool canSolveRectangular() const { return can_solve_rectangular_; }
protected: protected:
EigenOption option_; EigenOption option_;
std::unique_ptr<EigenLinearSolverBase> solver_; std::unique_ptr<EigenLinearSolverBase> solver_;
bool can_solve_rectangular_ = false;
void setRestart(); void setRestart();
void setL(); void setL();
void setS(); void setS();
......
...@@ -51,6 +51,9 @@ public: ...@@ -51,6 +51,9 @@ public:
bool solve(EigenMatrix& A, EigenVector& b, EigenVector& x); bool solve(EigenMatrix& A, EigenVector& b, EigenVector& x);
/// Get, if the solver can handle rectangular equation systems
bool canSolveRectangular() const { return false; }
private: private:
bool solve(LisMatrix& A, LisVector& b, LisVector& x); bool solve(LisMatrix& A, LisVector& b, LisVector& x);
std::string lis_options_; std::string lis_options_;
......
...@@ -40,6 +40,10 @@ PETScLinearSolver::PETScLinearSolver(std::string const& prefix, ...@@ -40,6 +40,10 @@ PETScLinearSolver::PETScLinearSolver(std::string const& prefix,
KSPSetInitialGuessNonzero(solver_, PETSC_TRUE); KSPSetInitialGuessNonzero(solver_, PETSC_TRUE);
KSPSetFromOptions(solver_); // set run-time options KSPSetFromOptions(solver_); // set run-time options
KSPType ksp_type;
KSPGetType(solver_, &ksp_type);
can_solve_rectangular_ = canSolverHandleRectangular(ksp_type);
} }
bool PETScLinearSolver::solve(PETScMatrix& A, PETScVector& b, PETScVector& x) bool PETScLinearSolver::solve(PETScMatrix& A, PETScVector& b, PETScVector& x)
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <petscksp.h> #include <petscksp.h>
#include <algorithm>
#include <array>
#include <string> #include <string>
#include "PETScMatrix.h" #include "PETScMatrix.h"
...@@ -62,10 +64,26 @@ public: ...@@ -62,10 +64,26 @@ public:
/// Get elapsed wall clock time. /// Get elapsed wall clock time.
double getElapsedTime() const { return elapsed_ctime_; } double getElapsedTime() const { return elapsed_ctime_; }
/// Get, if the solver can handle rectangular equation systems
bool canSolveRectangular() const { return can_solve_rectangular_; }
private: private:
bool canSolverHandleRectangular(std::string_view ksp_type)
{
// List of KSP types that can handle rectangular matrices
constexpr auto rectangular_solvers = std::to_array<std::string_view>(
{KSPGMRES, KSPFGMRES, KSPBCGS, KSPBCGSL, KSPTFQMR, KSPCGS});
return std::ranges::any_of(rectangular_solvers,
[&](const auto& solver)
{ return solver == ksp_type; });
}
KSP solver_; ///< Solver type. KSP solver_; ///< Solver type.
PC pc_; ///< Preconditioner type. PC pc_; ///< Preconditioner type.
bool can_solve_rectangular_ = false;
double elapsed_ctime_ = 0.0; ///< Clock time double elapsed_ctime_ = 0.0; ///< Clock time
}; };
......
...@@ -170,8 +170,18 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( ...@@ -170,8 +170,18 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve(
sys.getRhs(*x_prev[process_id], rhs); sys.getRhs(*x_prev[process_id], rhs);
// Normalize the linear equation system, if required // Normalize the linear equation system, if required
if (sys.requiresNormalization()) if (sys.requiresNormalization() &&
!_linear_solver.canSolveRectangular())
{
sys.getAandRhsNormalized(A, rhs); sys.getAandRhsNormalized(A, rhs);
WARN(
"The equation system is rectangular, but the current linear "
"solver only supports square systems. "
"The system will be normalized, which lead to a squared "
"condition number and potential numerical issues. "
"It is recommended to use a solver that supports rectangular "
"equation systems for better numerical stability.");
}
INFO("[time] Assembly took {:g} s.", time_assembly.elapsed()); INFO("[time] Assembly took {:g} s.", time_assembly.elapsed());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment