version 3.11-dev
Loading...
Searching...
No Matches
multistagetimestepper.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_TIMESTEPPING_MULTISTAGE_TIMESTEPPER_HH
13#define DUMUX_TIMESTEPPING_MULTISTAGE_TIMESTEPPER_HH
14
15#include <memory>
16#include <vector>
17#include <cmath>
18#include <iostream>
19
20#include <dumux/io/format.hh>
21
25
26namespace Dumux::Experimental {
27
29template<class Scalar>
31{
32 struct Params {
33 Scalar alpha, betaDt, timeAtStage, dtFraction;
35 };
36public:
38 MultiStageParams(const MultiStageMethod<Scalar>& m, std::size_t i, const Scalar t, const Scalar dt)
39 : size_(i+1)
40 {
41 params_.resize(size_);
42 for (std::size_t k = 0; k < size_; ++k)
43 {
44 auto& p = params_[k];
45 p.alpha = m.temporalWeight(i, k);
46 p.betaDt = m.spatialWeight(i, k)*dt;
47 p.timeAtStage = t + m.timeStepWeight(k)*dt;
48 p.dtFraction = m.timeStepWeight(k);
49
50 // decide on the dimensionless tableau coefficients; betaDt carries the
51 // time step and is small for an active stage when dt is small
52 using std::abs;
53 p.skipTemporal = (abs(m.temporalWeight(i, k)) < 1e-6);
54 p.skipSpatial = (abs(m.spatialWeight(i, k)) < 1e-6);
55 }
56 }
57
58 std::size_t size () const
59 { return size_; }
60
62 Scalar temporalWeight (std::size_t k) const
63 { return params_[k].alpha; }
64
66 Scalar spatialWeight (std::size_t k) const
67 { return params_[k].betaDt; }
68
70 Scalar timeAtStage (std::size_t k) const
71 { return params_[k].timeAtStage; }
72
74 Scalar timeStepFraction (std::size_t k) const
75 { return params_[k].dtFraction; }
76
78 bool skipTemporal (std::size_t k) const
79 { return params_[k].skipTemporal; }
80
82 bool skipSpatial (std::size_t k) const
83 { return params_[k].skipSpatial; }
84
85private:
86 std::size_t size_;
87 std::vector<Params> params_;
88};
89
96template<class PDESolver, class Scalar = double>
98{
99 using Variables = typename PDESolver::Variables;
100 using StageParams = MultiStageParams<Scalar>;
101 using Backend = VariablesBackend<Variables>;
102
103public:
104
111 MultiStageTimeStepper(std::shared_ptr<PDESolver> pdeSolver,
112 std::shared_ptr<const MultiStageMethod<Scalar>> msMethod,
113 const std::string& paramGroup = "")
114 : pdeSolver_(pdeSolver)
115 , msMethod_(msMethod)
116 {
117 initParams_(paramGroup);
118
119 if (pdeSolver_->verbosity() >= 1)
120 std::cout << "Initialize time stepper with method " << msMethod_->name()
121 << Fmt::format(" ({} stage{})", msMethod_->numStages(), (msMethod_->numStages() > 1 ? "s" : ""))
122 << std::endl;
123 }
124
132 void step(Variables& vars, const Scalar t, const Scalar dt)
133 {
134 // make sure there are no traces of previous stages
135 pdeSolver_->assembler().clearStages();
136
137 // do time integration
138 bool converged = step_(vars, t, dt);
139
140 // clear traces of previously registered stages
141 pdeSolver_->assembler().clearStages();
142
143 // if the solver didn't converge we can't recover
144 if (!converged)
145 DUNE_THROW(NumericalProblem, "Solver did not converge!");
146 }
147
154 void step(Variables& vars, TimeLoopBase<Scalar>& timeLoop)
155 {
156 // make sure there are no traces of previous stages
157 pdeSolver_->assembler().clearStages();
158
159 // try solving the non-linear system
160 for (std::size_t i = 0; i <= maxTimeStepDivisions_; ++i)
161 {
162 // try solving the non-linear system
163 bool converged = step_(vars, timeLoop.time(), timeLoop.timeStepSize());
164 if (converged)
165 {
166 // clear traces of previously registered stages
167 pdeSolver_->assembler().clearStages();
168 return;
169 }
170
171 else if (!converged && i < maxTimeStepDivisions_)
172 {
173 // set solution to previous solution & reset time step
174 Backend::update(vars, pdeSolver_->assembler().prevSol());
175 pdeSolver_->assembler().resetTimeStep(Backend::dofs(vars));
176
177 if (pdeSolver_->verbosity() >= 1)
178 {
179 const auto dt = timeLoop.timeStepSize();
180 std::cout << Fmt::format("Solver did not converge with dt = {} seconds. ", dt)
181 << Fmt::format("Retrying with time step of dt = {} seconds.\n", dt*retryTimeStepReductionFactor_);
182 }
183
184 // try again with dt = dt * retryTimeStepReductionFactor_
185 timeLoop.setTimeStepSize(timeLoop.timeStepSize() * retryTimeStepReductionFactor_);
186 }
187
188 else
189 {
190 pdeSolver_->assembler().clearStages();
191 DUNE_THROW(NumericalProblem,
192 Fmt::format("Solver didn't converge after {} time-step divisions; dt = {}.\n",
193 maxTimeStepDivisions_, timeLoop.timeStepSize()));
194 }
195 }
196
197 DUNE_THROW(Dune::InvalidStateException, "Unreachable");
198 }
199
200private:
201 bool step_(Variables& vars, const Scalar t, const Scalar dt)
202 {
203 for (auto stageIdx = 1UL; stageIdx <= msMethod_->numStages(); ++stageIdx)
204 {
205 // prepare the assembler for this stage
206 pdeSolver_->assembler().prepareStage(
207 vars,
208 std::make_shared<StageParams>(*msMethod_, stageIdx, t, dt)
209 );
210
211 // assemble & solve
212 bool converged = pdeSolver_->apply(vars);
213 if (!converged)
214 return false;
215 }
216
217 return true;
218 }
219
220 void initParams_(const std::string& group = "")
221 {
222 maxTimeStepDivisions_ = getParamFromGroup<std::size_t>(group, "TimeStepper.MaxTimeStepDivisions", 10);
223 retryTimeStepReductionFactor_ = getParamFromGroup<Scalar>(group, "TimeStepper.RetryTimeStepReductionFactor", 0.5);
224 }
225
226 std::shared_ptr<PDESolver> pdeSolver_;
227 std::shared_ptr<const MultiStageMethod<Scalar>> msMethod_;
228
229 Scalar maxTimeStepDivisions_;
230 Scalar retryTimeStepReductionFactor_;
231};
232
233} // end namespace Dumux::Experimental
234
235#endif
Abstract interface for one-step multi-stage method parameters in Shu/Osher form.
Definition multistagemethods.hh:75
virtual Scalar timeStepWeight(std::size_t k) const =0
time step weights for each stage ( )
virtual Scalar temporalWeight(std::size_t i, std::size_t k) const =0
weights of the temporal operator residual ( )
virtual Scalar spatialWeight(std::size_t i, std::size_t k) const =0
weights of the spatial operator residual ( )
Data object for the parameters of a given stage.
Definition multistagetimestepper.hh:31
Scalar timeAtStage(std::size_t k) const
the time at which we have to evaluate the operators
Definition multistagetimestepper.hh:70
bool skipSpatial(std::size_t k) const
If .
Definition multistagetimestepper.hh:82
Scalar spatialWeight(std::size_t k) const
weights of the spatial operator residual ( )
Definition multistagetimestepper.hh:66
Scalar timeStepFraction(std::size_t k) const
the fraction of a time step corresponding to the k-th stage
Definition multistagetimestepper.hh:74
std::size_t size() const
Definition multistagetimestepper.hh:58
bool skipTemporal(std::size_t k) const
If .
Definition multistagetimestepper.hh:78
Scalar temporalWeight(std::size_t k) const
weights of the temporal operator residual ( )
Definition multistagetimestepper.hh:62
MultiStageParams(const MultiStageMethod< Scalar > &m, std::size_t i, const Scalar t, const Scalar dt)
Extract params for stage i from method m.
Definition multistagetimestepper.hh:38
MultiStageTimeStepper(std::shared_ptr< PDESolver > pdeSolver, std::shared_ptr< const MultiStageMethod< Scalar > > msMethod, const std::string &paramGroup="")
The constructor.
Definition multistagetimestepper.hh:111
void step(Variables &vars, TimeLoopBase< Scalar > &timeLoop)
Advance one time step of the given time loop (adaptive time stepping on solver failure).
Definition multistagetimestepper.hh:154
void step(Variables &vars, const Scalar t, const Scalar dt)
Advance one time step of the given time loop.
Definition multistagetimestepper.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
Exception thrown if a fixable numerical problem occurs.
Definition exceptions.hh:27
Detail::PDESolver::AssemblerVariables< Assembler > Variables
export the type of variables that represent a numerical solution
Definition common/pdesolver.hh:71
Manages the handling of time dependent problems.
Definition common/timeloop.hh:84
virtual Scalar time() const =0
Return the time before the time integration. To get the time after the time integration you have to ...
virtual void setTimeStepSize(Scalar dt)=0
Set the current time step size to a given value.
virtual Scalar timeStepSize() const =0
Returns the suggested time step length .
Manages the handling of time dependent problems.
Formatting based on the fmt-library which implements std::format of C++20.
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
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:165
Parameters for different multistage time stepping methods.
typename ScalarType< X >::Type Scalar
Definition odesolver.hh:52
Definition assembly/assembler.hh:44
Backends for operations on different solution vector types or more generic variable classes to be use...