From b97a21ddee2e72010a1780cf44131cce665e487f Mon Sep 17 00:00:00 2001 From: Christoph Lehmann <christoph.lehmann@ufz.de> Date: Thu, 2 May 2024 20:55:25 +0200 Subject: [PATCH] Try to fix accelerated linear PDE assembly --- MathLib/LinAlg/Eigen/EigenLinearSolver.cpp | 26 +++++++++++++++++++++- NumLib/ODESolver/NonlinearSolver.cpp | 12 +++------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/MathLib/LinAlg/Eigen/EigenLinearSolver.cpp b/MathLib/LinAlg/Eigen/EigenLinearSolver.cpp index db3ffc563bd..1f0c394355f 100644 --- a/MathLib/LinAlg/Eigen/EigenLinearSolver.cpp +++ b/MathLib/LinAlg/Eigen/EigenLinearSolver.cpp @@ -63,8 +63,30 @@ public: } bool compute(Matrix& A, EigenOption& opt, - MathLib::LinearSolverBehaviour const linear_solver_behaviour) + MathLib::LinearSolverBehaviour linear_solver_behaviour) { + if (linear_solver_behaviour == MathLib::LinearSolverBehaviour::REUSE) + { + // Checking if this is the first compute() call should work both for + // direct solvers (that factorize the matrix A) and for iterative + // solvers (that store a reference to A in the preconditioner). + if (is_first_compute_call_) + { + // There is nothing there, yet, to be reused. Hence, we compute + // and store the result. + linear_solver_behaviour = + MathLib::LinearSolverBehaviour::RECOMPUTE_AND_STORE; + } + else + { + return true; + } + } + + // TODO (CL) That might not work under all circumstances, e.g., if the + // linear solver fails subsequently. Time will tell. + is_first_compute_call_ = false; + #ifdef USE_EIGEN_UNSUPPORTED if (opt.scaling) { @@ -89,6 +111,8 @@ private: #ifdef USE_EIGEN_UNSUPPORTED std::unique_ptr<Eigen::IterScaling<EigenMatrix::RawMatrixType>> scaling_; #endif + + bool is_first_compute_call_ = true; }; namespace details diff --git a/NumLib/ODESolver/NonlinearSolver.cpp b/NumLib/ODESolver/NonlinearSolver.cpp index 539aa469f85..a84376c2394 100644 --- a/NumLib/ODESolver/NonlinearSolver.cpp +++ b/NumLib/ODESolver/NonlinearSolver.cpp @@ -34,18 +34,12 @@ bool solvePicard(GlobalLinearSolver& linear_solver, GlobalMatrix& A, BaseLib::RunTime time_linear_solver; time_linear_solver.start(); - if (linear_solver_behaviour == MathLib::LinearSolverBehaviour::RECOMPUTE || - linear_solver_behaviour == - MathLib::LinearSolverBehaviour::RECOMPUTE_AND_STORE) + if (!linear_solver.compute(A, linear_solver_behaviour)) { - if (!linear_solver.compute(A, linear_solver_behaviour)) - { - ERR("Picard: The linear solver failed in the compute() step."); - return false; - } + ERR("Picard: The linear solver failed in the compute() step."); + return false; } - // REUSE the previously computed preconditioner or LU decomposition bool const iteration_succeeded = linear_solver.solve(rhs, x); INFO("[time] Linear solver took {:g} s.", time_linear_solver.elapsed()); -- GitLab