From a53199e2fd814159e81c6b5175687dd630f2a676 Mon Sep 17 00:00:00 2001 From: Timo Koch <timokoch@math.uio.no> Date: Sun, 19 Mar 2023 21:14:48 +0100 Subject: [PATCH] [linearpdesolver] Add communicator and fix reuse matrix in parallel for compatible solvers --- dumux/linear/pdesolver.hh | 50 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/dumux/linear/pdesolver.hh b/dumux/linear/pdesolver.hh index ce758947cc..89f09dd132 100644 --- a/dumux/linear/pdesolver.hh +++ b/dumux/linear/pdesolver.hh @@ -51,6 +51,17 @@ #include <dumux/linear/matrixconverter.hh> +namespace Dumux::Detail::LinearPDESolver { + +template <class Solver, class Matrix> +using SetMatrixDetector = decltype(std::declval<Solver>().setMatrix(std::declval<std::shared_ptr<Matrix>>())); + +template<class Solver, class Matrix> +static constexpr bool linearSolverHasSetMatrix() +{ return Dune::Std::is_detected<SetMatrixDetector, Solver, Matrix>::value; } + +} // end namespace Dumux::Detail::LinearPDESolver + namespace Dumux { /*! @@ -63,7 +74,8 @@ namespace Dumux { * defaults of the reference solver, derive your solver from * this class and simply overload the required methods. */ -template <class Assembler, class LinearSolver> +template <class Assembler, class LinearSolver, + class Comm = Dune::Communication<Dune::MPIHelper::MPICommunicator>> class LinearPDESolver : public PDESolver<Assembler, LinearSolver> { using ParentType = PDESolver<Assembler, LinearSolver>; @@ -78,16 +90,19 @@ class LinearPDESolver : public PDESolver<Assembler, LinearSolver> public: using typename ParentType::Variables; + using Communication = Comm; /*! * \brief The Constructor */ LinearPDESolver(std::shared_ptr<Assembler> assembler, std::shared_ptr<LinearSolver> linearSolver, + const Communication& comm = Dune::MPIHelper::getCommunication(), const std::string& paramGroup = "") : ParentType(assembler, linearSolver) , paramGroup_(paramGroup) , reuseMatrix_(false) + , comm_(comm) { initParams_(paramGroup); @@ -95,6 +110,15 @@ public: this->assembler().setLinearSystem(); } + /*! + * \brief The Constructor + */ + LinearPDESolver(std::shared_ptr<Assembler> assembler, + std::shared_ptr<LinearSolver> linearSolver, + const std::string& paramGroup) + : LinearPDESolver(assembler, linearSolver, Dune::MPIHelper::getCommunication(), paramGroup) + {} + /*! * \brief Solve a linear PDE system */ @@ -219,12 +243,31 @@ public: * setting this flag to true. */ void reuseMatrix(bool reuse = true) - { reuseMatrix_ = reuse; } + { + reuseMatrix_ = reuse; + + if constexpr (Detail::LinearPDESolver::linearSolverHasSetMatrix<LinearSolver, JacobianMatrix>()) + if (reuseMatrix_) + this->linearSolver().setMatrix(this->assembler().jacobian()); + } private: virtual bool solveLinearSystem_(ResidualVector& deltaU) { + if constexpr (Detail::LinearPDESolver::linearSolverHasSetMatrix<LinearSolver, JacobianMatrix>()) + { + if (reuseMatrix_) + return this->linearSolver().solve(deltaU, this->assembler().residual()); + } + else + { + if (reuseMatrix_ && comm_.size() > 1) + DUNE_THROW(Dune::NotImplemented, + "Reuse matrix for parallel runs with a solver that doesn't support the setMatrix interface" + ); + } + return solveLinearSystemImpl_(this->linearSolver(), this->assembler().jacobian(), deltaU, @@ -333,6 +376,9 @@ private: //! check if the matrix is supposed to be reused bool reuseMatrix_; + + //! The communication object (for distributed memory parallelism) + Communication comm_; }; } // end namespace Dumux -- GitLab