1#ifndef DUNE_COPASI_COMMON_STEPPERS_HH
2#define DUNE_COPASI_COMMON_STEPPERS_HH
7#include <dune/pdelab/common/convergence/reason.hh>
8#include <dune/pdelab/common/trace.hh>
9#include <dune/pdelab/operator/operator.hh>
11#include <dune/common/float_cmp.hh>
12#include <dune/common/parametertree.hh>
16#include <spdlog/spdlog.h>
36template<std::copyable State,
class TimeQuantity,
class DurationQuantity>
39 std::function<TimeQuantity&(State&)> _time_mut;
40 std::function<
const TimeQuantity&(
const State&)> _time_const;
52 std::function<
const TimeQuantity&(
const State&)>
time_const)
59 template<std::same_as<
void> =
void>
63 } -> std::convertible_to<const TimeQuantity&>;
66 } -> std::convertible_to<TimeQuantity&>;
104 TimeQuantity time = _time_const(
in);
106 spdlog::info(
"Evaluating time step: {:.2e}s + {:.2e}s -> {:.2e}s",
121 spdlog::warn(
"Time step failed: {}",
error.message());
151 std::function<
void(
const State&)>
callable = [](
const State&) {},
154 TimeQuantity time = _time_const(
in);
155 spdlog::info(
"Evolving system: {:.2e}s -> {:.2e}s", time,
end_time);
160 PDELab::ErrorCondition
error;
165 spdlog::warn(
"Evolving system could not approach final time");
198 std::function<
void(
const State&)>
callable = [](
const State&) {})
const
200 spdlog::info(
"Snapping current time to {:.5e}",
snap_time);
211 PDELab::ErrorCondition
error;
212 while (FloatCmp::lt(time = _time_const(
out),
snap_time)) {
221 spdlog::info(
"Snapping step size {:.5e}s -> {:.5e}s",
dt,
new_dt);
234 spdlog::info(
"Reducing step size: {:.5e}s -> {:.5e}s",
dt,
dt * 0.5);
252template<
class State,
class TimeQuantity,
class DurationQuantity>
271 std::function<
const TimeQuantity&(
const State&)>
time_const,
274 std::optional<DurationQuantity>
min_step = {},
275 std::optional<DurationQuantity>
max_step = {})
282 if (FloatCmp::gt(_decrease_factor, 1.)) {
284 IOError{},
"Decrease factor {} must be in the range of (0,1]", _decrease_factor);
286 if (FloatCmp::lt(_decrease_factor, 0.)) {
288 IOError{},
"Decrease factor {} must be in the range of (0,1]", _decrease_factor);
290 if (FloatCmp::lt(_increase_factor, 1.)) {
292 IOError{},
"Increase factor {} must be in the range of (1,∞)", _increase_factor);
304 template<std::same_as<
void> =
void>
308 } -> std::convertible_to<const TimeQuantity&>;
311 } -> std::convertible_to<TimeQuantity&>;
315 std::optional<DurationQuantity>
min_step = {},
316 std::optional<DurationQuantity>
max_step = {})
342 PDELab::ErrorCondition
error = check_dt(
dt);
351 spdlog::warn(
"Reducing step size: {:.2e}s -> {:.2e}s",
dt,
dt * _decrease_factor);
352 error = check_dt(
dt =
dt * _decrease_factor);
362 new_step = std::clamp(
new_step, -std::abs(_max_step.value()), std::abs(_max_step.value()));
364 spdlog::info(
"Increasing step size: {:.2e}s -> {:.2e}s",
dt,
new_step);
373 if (_min_step
and Dune::FloatCmp::lt(std::abs(
dt), std::abs(*_min_step))) {
374 spdlog::warn(
"Time step '{}' lower limit '{}' was reached ",
dt, *_min_step);
377 if (_max_step
and Dune::FloatCmp::gt(std::abs(
dt), std::abs(*_max_step))) {
378 spdlog::warn(
"Time step '{}' upper limit '{}' was reached ",
dt, *_max_step);
384 std::optional<DurationQuantity> _min_step, _max_step;
385 double _decrease_factor{}, _increase_factor{};
Adapt an stepper into a simple adaptive time stepper.
Definition stepper.hh:254
SimpleAdaptiveStepper(double decrease_factor=0.5, double increase_factor=1.5, std::optional< DurationQuantity > min_step={}, std::optional< DurationQuantity > max_step={})
Construct a new simple adaptive stepper.
Definition stepper.hh:313
PDELab::ErrorCondition do_step(PDELab::OneStep< State > &one_step, const State &in, State &out, DurationQuantity &dt) const override
Perform one simple adaptive time step of the system.
Definition stepper.hh:337
SimpleAdaptiveStepper(std::function< TimeQuantity &(State &)> time_mut, std::function< const TimeQuantity &(const State &)> time_const, double decrease_factor=0.5, double increase_factor=1.5, std::optional< DurationQuantity > min_step={}, std::optional< DurationQuantity > max_step={})
Construct a new simple adaptive stepper.
Definition stepper.hh:270
Simple time stepper of one-step operators.
Definition stepper.hh:38
TimeStepper(std::function< TimeQuantity &(State &)> time_mut, std::function< const TimeQuantity &(const State &)> time_const)
Construct a new time stepper.
Definition stepper.hh:51
TimeStepper()
Construct a new time stepper.
Definition stepper.hh:68
TimeStepper(const TimeStepper &)=delete
virtual ~TimeStepper()=default
Time stepper destructor.
TimeStepper & operator=(TimeStepper &&)=delete
virtual PDELab::ErrorCondition do_step(PDELab::OneStep< State > &one_step, const State &in, State &out, DurationQuantity &dt) const
Perform one step of the system.
Definition stepper.hh:95
PDELab::ErrorCondition evolve(PDELab::OneStep< State > &one_step, const State &in, State &out, DurationQuantity &dt, TimeQuantity end_time, std::function< void(const State &)> callable=[](const State &) {}, bool snap_to_end_time=true) const
Evolve the system until end_time
Definition stepper.hh:145
TimeStepper(TimeStepper &&)=delete
TimeStepper & operator=(const TimeStepper &)=delete
PDELab::ErrorCondition snap_to_time(PDELab::OneStep< State > &one_step, const State &in, State &out, DurationQuantity &dt, TimeQuantity snap_time, std::function< void(const State &)> callable=[](const State &) {}) const
Snap the output to a specific time.
Definition stepper.hh:192
#define DUNE_COPASI_FMT_STYLED_BOLD(key)
Definition fmt_style.hh:13
Definition axis_names.hh:7
auto format_exception(Exception &&e, fmt::format_string< Args... > format, Args &&... args)
Definition exceptions.hh:23
constexpr bool is_bitflags_v
Alias for Bitflag indicator.
Definition bit_flags.hh:24