12#ifndef DUMUX_ODE_SOLVER_HH
13#define DUMUX_ODE_SOLVER_HH
24#include <dune/common/exceptions.hh>
25#include <dune/common/parallel/mpicommunication.hh>
26#include <dune/common/parallel/mpihelper.hh>
27#include <dune/common/typetraits.hh>
40template<class T, bool indexable = Dune::IsIndexable<T>::value>
47 using Element = std::decay_t<decltype(std::declval<T>()[0])>;
106 {
return previous_; }
114 {
return stepFraction_; }
119 Scalar stepFraction_;
150 : solution_(solution)
162 : solution_(std::move(solution))
180 {
return solution_; }
188 {
return solution_; }
196 { solution_ = solution; }
214 solution_ = solution;
227template<
class ODESystem>
231template<
class ODESystem>
232 requires requires {
typename ODESystem::Variables; }
234{
using Type =
typename ODESystem::Variables; };
236template<
class ODESystem>
245template<
class To,
class From>
248 if constexpr (std::is_assignable_v<To&, From>)
270template<
class Matrix>
273 if constexpr (Dune::IsNumber<Matrix>::value)
278 for (std::size_t i = 0; i < matrix.N(); ++i)
290template<
class Vector,
class Scalar>
302template<
class Matrix,
class Scalar>
315template<
class Matrix,
class Scalar>
318 if constexpr (Dune::IsNumber<Matrix>::value)
322 for (std::size_t row = 0; row < y.N(); ++row)
323 for (std::size_t col = 0; col < y.M(); ++col)
324 y[row][col] += factor*x[row][col];
336template<
class ODESystem,
class Vars,
class Res
idual>
337void evaluateRhs(
const ODESystem& odeSystem,
const Vars& vars, Residual& rhs)
339 if constexpr (
requires(
const ODESystem& system,
const Vars& v, Residual& r) { system.rhs(v, r); })
340 odeSystem.rhs(vars, rhs);
341 else if constexpr (
requires(
const ODESystem& system,
const Vars& v) { system.rhs(v); })
342 assign(rhs, odeSystem.rhs(vars));
345 "ODE systems must provide rhs(vars, rhs) or rhs(vars).");
357template<
class ODESystem,
class Vars,
class Res
idual>
360 if constexpr (
requires(
const ODESystem& system,
const Vars& v, Residual& result) { system.accumulation(v, result); })
361 odeSystem.accumulation(vars, value);
362 else if constexpr (
requires(
const ODESystem& system,
const Vars& v) { system.accumulation(v); })
363 assign(value, odeSystem.accumulation(vars));
376template<
class ODESystem,
class Vars,
class Jacobian>
379 if constexpr (
requires(
const ODESystem& system,
const Vars& v, Jacobian& j) { system.rhsJacobian(v, j); })
380 odeSystem.rhsJacobian(vars, jacobian);
381 else if constexpr (
requires(
const ODESystem& system,
const Vars& v) { system.rhsJacobian(v); })
382 assign(jacobian, odeSystem.rhsJacobian(vars));
384 DUNE_THROW(Dune::NotImplemented,
385 "Implicit ODE stages require rhsJacobian(vars, jacobian) or rhsJacobian(vars).");
397template<
class ODESystem,
class Vars,
class Res
idual,
class Jacobian>
400 if constexpr (
requires(
const ODESystem& system,
const Vars& v, Jacobian& j) { system.accumulationJacobian(v, j); })
401 odeSystem.accumulationJacobian(vars, jacobian);
402 else if constexpr (
requires(
const ODESystem& system,
const Vars& v) { system.accumulationJacobian(v); })
403 assign(jacobian, odeSystem.accumulationJacobian(vars));
404 else if constexpr (
requires(
const ODESystem& system,
const Vars& v, Residual& result) { system.accumulation(v, result); }
405 ||
requires(
const ODESystem& system,
const Vars& v) { system.accumulation(v); })
406 DUNE_THROW(Dune::NotImplemented,
407 "ODE systems with a custom accumulation require accumulationJacobian(vars, jacobian) or accumulationJacobian(vars).");
418template<
class Vars,
class Level>
421 if constexpr (
requires(Vars& v,
const Level& l) { v.updateIndependentVariable(l); })
422 vars.updateIndependentVariable(level);
425 "ODE variables must provide updateIndependentVariable(level) or use Dumux::Experimental::ODEVariables.");
434template<
class Vector>
437 if constexpr (Dune::IsNumber<Vector>::value)
442 else if constexpr (
requires(
const Vector& v) { v.two_norm(); })
443 return vector.two_norm();
446 using Scalar = std::decay_t<
decltype(
norm(*std::begin(vector)))>;
448 for (
const auto& entry : vector)
450 const auto entryNorm =
norm(entry);
451 result += entryNorm*entryNorm;
467template<
class Matrix,
class Vector>
468bool solve(
const Matrix& matrix, Vector& x,
const Vector& b)
470 if constexpr (Dune::IsNumber<Matrix>::value)
475 else if constexpr (
requires(
const Matrix& A, Vector& y,
const Vector& rhs) { A.solve(y, rhs); })
480 else if constexpr (
requires(Matrix A,
const Vector& rhs, Vector& y) { A.invert(); A.mv(rhs, y); })
482 auto inverse = matrix;
489 "The default ODE linear solver only supports scalars and local dense matrices.");
504template<
class JacobianMatrix,
class Res
idualVector>
524 bool solve(
const JacobianMatrix& matrix,
526 const ResidualVector& b)
const
535 auto norm(
const ResidualVector& residual)
const
557template<
class ODESystem>
561 using Scalar =
typename ODESystem::Scalar;
599 {
return jacobian_; }
607 {
return jacobian_; }
615 {
return residual_; }
623 {
return residual_; }
633 DUNE_THROW(Dune::InvalidStateException,
"No ODE stage prepared before residual assembly");
635 if (stageParams_->size() != rhsTerms_.size() || stageParams_->size() != accumulationValues_.size())
636 DUNE_THROW(Dune::InvalidStateException,
"Wrong number of ODE stage residuals");
638 evaluateTerms_(vars, accumulationValues_.back(), rhsTerms_.back());
640 residual_ = zeroResidualLike_(vars);
641 for (std::size_t k = 0; k < stageParams_->size(); ++k)
643 if (!stageParams_->skipTemporal(k))
645 if (!stageParams_->skipSpatial(k))
659 const auto curStage = stageParams_->size() - 1;
663 if (!stageParams_->skipSpatial(curStage))
665 auto rhsJacobian = jacobian_;
679 std::shared_ptr<const StageParams> params)
681 const auto curStage = params->size() - 1;
682 const auto prevStage = stageParams_ ? stageParams_->size() - 1 : 0;
683 if (curStage != prevStage + 1)
684 DUNE_THROW(Dune::InvalidStateException,
685 "Can only prepare ODE stages consecutively (current stage: " << curStage
686 <<
", previous stage: " << prevStage <<
")");
688 stageParams_ = std::move(params);
694 const auto coordinate = stageParams_->timeAtStage(0);
700 accumulationValues_.push_back(zeroResidualLike_(vars));
701 rhsTerms_.push_back(zeroResidualLike_(vars));
702 evaluateTerms_(vars, accumulationValues_.back(), rhsTerms_.back());
705 const auto coordinate = stageParams_->timeAtStage(curStage);
706 const auto previousCoordinate = stageParams_->timeAtStage(0);
707 const auto stepFraction = stageParams_->timeStepFraction(curStage);
713 accumulationValues_.push_back(zeroResidualLike_(vars));
714 rhsTerms_.push_back(zeroResidualLike_(vars));
722 accumulationValues_.clear();
724 stageParams_.reset();
733 {
return previousSolution_; }
749 {
return *odeSystem_; }
763 auto result = ResidualBackend::zeros(Backend::size(Backend::dofs(vars)));
775 void evaluateTerms_(
const Variables& vars,
785 std::shared_ptr<const ODESystem> odeSystem_;
789 std::vector<ResidualType> accumulationValues_;
790 std::vector<ResidualType> rhsTerms_;
791 std::shared_ptr<const StageParams> stageParams_;
798template<
class ODESystem,
800 class Reassembler = DefaultPartialReassembler,
801 class Comm = Dune::Communication<Dune::MPIHelper::MPICommunicator>>
821 std::shared_ptr<const Method> method,
822 const std::string& paramGroup =
"")
826 Dune::MPIHelper::getCommunication(),
839 std::shared_ptr<const Method> method,
841 const std::string& paramGroup =
"")
859 std::shared_ptr<const Method> method,
860 const std::string& paramGroup =
"")
864 Dune::MPIHelper::getCommunication(),
879 std::shared_ptr<const Method> method,
881 const std::string& paramGroup =
"")
882 : odeSystem_(std::move(odeSystem))
883 , assembler_(std::make_shared<
Assembler>(odeSystem_))
885 , nonlinearSolver_(std::make_shared<
NonlinearSolver>(assembler_, linearSolver_, comm, paramGroup,
"ODE", 0))
886 , method_(std::move(method))
887 , integrationDriver_(nonlinearSolver_, method_, paramGroup)
898 { integrationDriver_.step(vars, independentVariable, stepSize); }
909 if (!(stepSize > 0.0))
910 DUNE_THROW(Dune::InvalidStateException,
"ODE integration step size has to be positive");
912 auto startCoordinate = vars.independentVariableLevel().current();
914 if (endCoordinate < startCoordinate)
916 Dune::InvalidStateException,
917 "Backward ODE integration is not supported: end coordinate "
918 << endCoordinate <<
" is smaller than start coordinate "
922 if (endCoordinate == startCoordinate)
925 while (startCoordinate < endCoordinate)
928 const auto currentStepSize = min(stepSize, endCoordinate - startCoordinate);
929 step(vars, startCoordinate, currentStepSize);
930 startCoordinate = vars.independentVariableLevel().current();
940 {
return *assembler_; }
948 {
return *assembler_; }
956 {
return *nonlinearSolver_; }
964 {
return *nonlinearSolver_; }
972 {
return *linearSolver_; }
980 {
return *linearSolver_; }
983 std::shared_ptr<const ODESystem> odeSystem_;
984 std::shared_ptr<Assembler> assembler_;
985 std::shared_ptr<LinearSolver> linearSolver_;
986 std::shared_ptr<NonlinearSolver> nonlinearSolver_;
987 std::shared_ptr<const Method> method_;
Class providing operations with primary variable vectors.
Definition variablesbackend.hh:60
Represents a level of the independent variable during ODE integration.
Definition odesolver.hh:64
Scalar current() const
Returns the current value of the independent variable.
Definition odesolver.hh:97
IndependentVariableLevel(const Scalar current, const Scalar previous, const Scalar stepFraction)
Constructs a level occurring within an integration step.
Definition odesolver.hh:84
Scalar stepFraction() const
Returns the fraction of the integration step represented by this level.
Definition odesolver.hh:113
IndependentVariableLevel(const Scalar current)
Constructs a level at a given value of the independent variable.
Definition odesolver.hh:71
Scalar previous() const
Returns the value at the beginning of the integration step.
Definition odesolver.hh:105
Abstract interface for one-step multi-stage method parameters in Shu/Osher form.
Definition multistagemethods.hh:75
Assembler that maps an ODE right-hand-side interface to the DuMux Newton interface.
Definition odesolver.hh:559
MultiStageODEAssembler(std::shared_ptr< const ODESystem > odeSystem)
Constructs an assembler that shares ownership of an ODE system.
Definition odesolver.hh:573
void clearStages()
Discards all cached stage terms and the active stage parameters.
Definition odesolver.hh:720
void assembleResidual(const Variables &vars)
Assemble the weighted residual for the currently prepared stage.
Definition odesolver.hh:630
const ResidualType & residual() const
Returns the assembled residual vector.
Definition odesolver.hh:622
typename ODESystem::SolutionVector SolutionVector
Definition odesolver.hh:562
void assembleJacobianAndResidual(const Variables &vars)
Assemble the residual and its Jacobian for the current stage.
Definition odesolver.hh:655
typename ODESystem::ResidualType ResidualType
Definition odesolver.hh:563
void resetTimeStep(const SolutionVector &)
Resets stage-local state before repeating or starting an integration step.
Definition odesolver.hh:740
const SolutionVector & prevSol() const
Returns the solution saved at the beginning of the current integration step.
Definition odesolver.hh:732
MultiStageODEAssembler(const ODESystem &odeSystem)
Constructs an assembler with an internally owned copy of an ODE system.
Definition odesolver.hh:582
const ODESystem & odeSystem() const
Returns the ODE system assembled by this object.
Definition odesolver.hh:748
JacobianMatrix & jacobian()
Returns the assembled Jacobian matrix.
Definition odesolver.hh:598
Detail::ODE::Variables< ODESystem > Variables
Definition odesolver.hh:565
const JacobianMatrix & jacobian() const
Returns the assembled Jacobian matrix.
Definition odesolver.hh:606
typename ODESystem::Scalar Scalar
Definition odesolver.hh:561
typename ODESystem::JacobianMatrix JacobianMatrix
Definition odesolver.hh:564
MultiStageParams< Scalar > StageParams
Definition odesolver.hh:566
void setLinearSystem()
Satisfies the Newton assembler interface.
Definition odesolver.hh:591
ResidualType & residual()
Returns the assembled residual vector.
Definition odesolver.hh:614
void prepareStage(Variables &vars, std::shared_ptr< const StageParams > params)
Prepare the next consecutive stage and update its independent-variable information.
Definition odesolver.hh:678
Data object for the parameters of a given stage.
Definition multistagetimestepper.hh:31
Time stepping with a multi-stage method.
Definition multistagetimestepper.hh:98
Minimal linear solver for scalar and local dense ODE stage systems.
Definition odesolver.hh:506
void setResidualReduction(double)
Accepts the Newton residual-reduction setting.
Definition odesolver.hh:514
bool solve(const JacobianMatrix &matrix, ResidualVector &x, const ResidualVector &b) const
Solve the linearized ODE stage system.
Definition odesolver.hh:524
auto norm(const ResidualVector &residual) const
Computes the norm used by the Newton convergence check.
Definition odesolver.hh:535
void step(Variables &vars, const Scalar independentVariable, const Scalar stepSize)
Advance the variables by one integration step.
Definition odesolver.hh:897
Assembler & assembler()
Returns the ODE assembler.
Definition odesolver.hh:939
MultiStageODEAssembler< ODESystem > Assembler
Definition odesolver.hh:805
const NonlinearSolver & nonlinearSolver() const
Returns the nonlinear solver used for implicit stages.
Definition odesolver.hh:963
ODESolver(std::shared_ptr< const ODESystem > odeSystem, std::shared_ptr< LinearSolver > linearSolver, std::shared_ptr< const Method > method, const Comm &comm, const std::string ¶mGroup="")
Construct a solver with custom linear solver and communication objects.
Definition odesolver.hh:877
const LinearSolver & linearSolver() const
Returns the linear solver used by the nonlinear solver.
Definition odesolver.hh:979
void solve(Variables &vars, const Scalar endCoordinate, const Scalar stepSize)
Integrate repeatedly with a fixed maximum step size up to an end coordinate.
Definition odesolver.hh:907
MultiStageTimeStepper< NonlinearSolver, Scalar > IntegrationDriver
Definition odesolver.hh:811
typename Assembler::Scalar Scalar
Definition odesolver.hh:807
typename Assembler::Variables Variables
Definition odesolver.hh:809
ODESolver(std::shared_ptr< const ODESystem > odeSystem, std::shared_ptr< const Method > method, const Comm &comm, const std::string ¶mGroup="")
Construct a solver with a default linear solver and custom communication.
Definition odesolver.hh:838
const Assembler & assembler() const
Returns the ODE assembler.
Definition odesolver.hh:947
LinearSolver & linearSolver()
Returns the linear solver used by the nonlinear solver.
Definition odesolver.hh:971
ODESolver(std::shared_ptr< const ODESystem > odeSystem, std::shared_ptr< LinearSolver > linearSolver, std::shared_ptr< const Method > method, const std::string ¶mGroup="")
Construct a solver with a custom linear solver and MPI communication.
Definition odesolver.hh:857
NonlinearSolver & nonlinearSolver()
Returns the nonlinear solver used for implicit stages.
Definition odesolver.hh:955
ODESolver(std::shared_ptr< const ODESystem > odeSystem, std::shared_ptr< const Method > method, const std::string ¶mGroup="")
Construct a solver with a default linear solver and MPI communication.
Definition odesolver.hh:820
NewtonSolver< Assembler, LinearSolver, Reassembler, Comm > NonlinearSolver
Definition odesolver.hh:806
typename Assembler::SolutionVector SolutionVector
Definition odesolver.hh:808
MultiStageMethod< Scalar > Method
Definition odesolver.hh:810
Stores an ODE solution and its independent-variable level. Generalization of experimental/common/vari...
Definition odesolver.hh:128
void updateIndependentVariable(const Level &level)
Updates the independent-variable level.
Definition odesolver.hh:203
SolutionVector & dofs()
Returns the solution degrees of freedom.
Definition odesolver.hh:187
void update(const SolutionVector &solution)
Updates the solution.
Definition odesolver.hh:195
X SolutionVector
Definition odesolver.hh:130
Detail::ODE::Scalar< X > Scalar
Definition odesolver.hh:131
ODEVariables(SolutionVector &&solution, const Level &level=Level{0.0})
Constructs ODE variables by moving a solution.
Definition odesolver.hh:160
void update(const SolutionVector &solution, const Level &level)
Updates the solution and independent-variable level.
Definition odesolver.hh:212
const Level & independentVariableLevel() const
Returns the independent-variable level.
Definition odesolver.hh:171
ODEVariables(const SolutionVector &solution, const Level &level=Level{0.0})
Constructs ODE variables from a solution.
Definition odesolver.hh:148
ODEVariables()
Constructs default-initialized ODE variables.
Definition odesolver.hh:137
const SolutionVector & dofs() const
Returns the solution degrees of freedom.
Definition odesolver.hh:179
IndependentVariableLevel< Scalar > Level
Definition odesolver.hh:132
Class that represents the variables of a model. We assume that models are formulated on the basis of ...
Definition experimental/common/variables.hh:41
Base class for linear solvers.
Definition solver.hh:27
An implementation of a Newton solver. The comprehensive documentation is in Newton solver,...
Definition nonlinear/newtonsolver.hh:183
Some exceptions thrown in DuMux.
Detail::VariablesBackend< Vars, Dune::Std::is_detected_v< Detail::SolutionVectorType, Vars > > VariablesBackend
Class providing operations for generic variable classes that represent the state of a numerical solut...
Definition variablesbackend.hh:253
Parameters for different multistage time stepping methods.
A time stepper performing a single time step of a transient simulation.
Definition odesolver.hh:38
void scaleMatrix(Matrix &matrix, const Scalar factor)
Scales a matrix-like object in place.
Definition odesolver.hh:303
void addScaled(const Scalar factor, const Vector &x, Vector &y)
Accumulates the scaled vector .
Definition odesolver.hh:291
void evaluateRhsJacobian(const ODESystem &odeSystem, const Vars &vars, Jacobian &jacobian)
Evaluate the Jacobian of the ODE right-hand side.
Definition odesolver.hh:377
void updateIndependentVariable(Vars &vars, const Level &level)
Updates the independent-variable information stored by an ODE variables object.
Definition odesolver.hh:419
bool solve(const Matrix &matrix, Vector &x, const Vector &b)
Solve the local linear system .
Definition odesolver.hh:468
void evaluateAccumulation(const ODESystem &odeSystem, const Vars &vars, Residual &value)
Evaluate the accumulation mapping .
Definition odesolver.hh:358
void setIdentity(Matrix &matrix)
Sets a scalar or square matrix-like object to the identity.
Definition odesolver.hh:271
void addScaledMatrix(const Scalar factor, const Matrix &x, Matrix &y)
Accumulates the scaled matrix .
Definition odesolver.hh:316
auto norm(const Vector &vector)
Compute the Euclidean norm of a scalar or vector-like object.
Definition odesolver.hh:435
void setZero(Value &value)
Sets a scalar, vector, or matrix-like value to zero.
Definition odesolver.hh:260
typename VariablesChooser< ODESystem >::Type Variables
Definition odesolver.hh:237
typename ScalarType< X >::Type Scalar
Definition odesolver.hh:52
void assign(To &to, const From &from)
Assigns an ODE quantity to an output object of a potentially different type.
Definition odesolver.hh:246
void evaluateAccumulationJacobian(const ODESystem &odeSystem, const Vars &vars, Jacobian &jacobian)
Evaluate the accumulation Jacobian .
Definition odesolver.hh:398
void evaluateRhs(const ODESystem &odeSystem, const Vars &vars, Residual &rhs)
Evaluate the right-hand side of an ODE system.
Definition odesolver.hh:337
Definition assembly/assembler.hh:44
Definition common/pdesolver.hh:24
Reference implementation of a Newton solver.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Detects which entries in the Jacobian have to be recomputed.
Template which always yields a false value.
Definition common/typetraits/typetraits.hh:24
std::decay_t< decltype(std::declval< T >()[0])> Element
Definition odesolver.hh:47
typename ScalarType< Element >::Type Type
Definition odesolver.hh:48
Definition odesolver.hh:42
T Type
Definition odesolver.hh:42
typename ODESystem::Variables Type
Definition odesolver.hh:234
Definition odesolver.hh:229
Dumux::Experimental::ODEVariables< typename ODESystem::SolutionVector > Type
Definition odesolver.hh:229
Backends for operations on different solution vector types or more generic variable classes to be use...