diff --git a/cpp/benchmarks/graph_simulation.cpp b/cpp/benchmarks/graph_simulation.cpp index 9ecb156d85..595e0a5f57 100644 --- a/cpp/benchmarks/graph_simulation.cpp +++ b/cpp/benchmarks/graph_simulation.cpp @@ -169,8 +169,8 @@ BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::EulerIntegratorCore)->Name("Graph Si BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Graph Simulation - adapt_rk"); BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::ControlledStepperWrapper) ->Name("Graph Simulation - rk_ck54 (boost)"); -BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::ControlledStepperWrapper) - ->Name("Graph Simulation - rk_dopri5 (boost)"); +// BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::ControlledStepperWrapper) +// ->Name("Graph Simulation - rk_dopri5 (boost)"); // TODO: reenable once boost bug is fixed BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::ControlledStepperWrapper) ->Name("Graph Simulation - rkf78 (boost)"); // run all benchmarks diff --git a/cpp/benchmarks/integrator_step.config b/cpp/benchmarks/integrator_step.config index e4a8d8b236..99aaa76922 100755 --- a/cpp/benchmarks/integrator_step.config +++ b/cpp/benchmarks/integrator_step.config @@ -11,7 +11,9 @@ 6377.873644, 35.24915600, 30.02961100, + 0.000000000, 182.1458650, + 0.000000000, 66.15305900, 79.53062100, 3069.383604, diff --git a/cpp/benchmarks/integrator_step.cpp b/cpp/benchmarks/integrator_step.cpp index f57d868bed..edccd893fd 100644 --- a/cpp/benchmarks/integrator_step.cpp +++ b/cpp/benchmarks/integrator_step.cpp @@ -58,8 +58,8 @@ BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("Dummy 3/3"); BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("simulate SecirModel adapt_rk"); BENCHMARK_TEMPLATE(integrator_step, mio::ControlledStepperWrapper) ->Name("simulate SecirModel boost rk_ck54"); -BENCHMARK_TEMPLATE(integrator_step, mio::ControlledStepperWrapper) - ->Name("simulate SecirModel boost rk_dopri5"); +// BENCHMARK_TEMPLATE(integrator_step, mio::ControlledStepperWrapper) +// ->Name("simulate SecirModel boost rk_dopri5"); // TODO: reenable once boost bug is fixed BENCHMARK_TEMPLATE(integrator_step, mio::ControlledStepperWrapper) ->Name("simulate SecirModel boost rkf78"); // run all benchmarks diff --git a/cpp/benchmarks/simulation.cpp b/cpp/benchmarks/simulation.cpp index 3e8c0d6047..988a0df1b6 100644 --- a/cpp/benchmarks/simulation.cpp +++ b/cpp/benchmarks/simulation.cpp @@ -49,8 +49,8 @@ BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("Dummy 3/3"); BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("simulate SecirModel adapt_rk"); BENCHMARK_TEMPLATE(simulation, mio::ControlledStepperWrapper) ->Name("simulate SecirModel boost rk_ck54"); -BENCHMARK_TEMPLATE(simulation, mio::ControlledStepperWrapper) - ->Name("simulate SecirModel boost rk_dopri5"); +// BENCHMARK_TEMPLATE(simulation, mio::ControlledStepperWrapper) +// ->Name("simulate SecirModel boost rk_dopri5"); // TODO: reenable once boost bug is fixed BENCHMARK_TEMPLATE(simulation, mio::ControlledStepperWrapper) ->Name("simulate SecirModel boost rkf78"); // run all benchmarks diff --git a/cpp/memilio/math/adapt_rk.cpp b/cpp/memilio/math/adapt_rk.cpp index 3255fc599f..88af7a25b3 100644 --- a/cpp/memilio/math/adapt_rk.cpp +++ b/cpp/memilio/math/adapt_rk.cpp @@ -18,6 +18,7 @@ * limitations under the License. */ #include "memilio/math/adapt_rk.h" +#include "memilio/utils/logging.h" namespace mio { @@ -73,11 +74,20 @@ Tableau::Tableau() bool RKIntegratorCore::step(const DerivFunction& f, Eigen::Ref yt, double& t, double& dt, Eigen::Ref ytp1) const { + assert(0 <= m_dt_min); + assert(m_dt_min <= m_dt_max); + + if (dt < m_dt_min || dt > m_dt_max) { + mio::log_warning("IntegratorCore: Restricting given step size dt = {} to [{}, {}].", dt, m_dt_min, m_dt_max); + } + + dt = std::min(dt, m_dt_max); + double t_eval; // shifted time for evaluating yt double dt_new; // updated dt - bool converged = false; // carry for convergence criterion - bool failed_step_size_adapt = false; + bool converged = false; // carry for convergence criterion + bool dt_is_invalid = false; if (m_yt_eval.size() != yt.size()) { m_yt_eval.resize(yt.size()); @@ -86,7 +96,11 @@ bool RKIntegratorCore::step(const DerivFunction& f, Eigen::Ref dt for step decreases when |error_estimate - eps| -> 0 dt_new *= 0.9; // check if updated dt stays within desired bounds and update dt for next step - if (m_dt_min < dt_new) { - dt = std::min(dt_new, m_dt_max); - } - else { - failed_step_size_adapt = true; - } + dt = std::min(dt_new, m_dt_max); } - return !failed_step_size_adapt; + dt = std::max(dt, m_dt_min); + // return 'converged' in favor of '!dt_is_invalid', as these values only differ if step sizing failed, + // but the step with size dt_min was accepted. + return converged; } } // namespace mio diff --git a/cpp/memilio/math/integrator.cpp b/cpp/memilio/math/integrator.cpp index 58f623bcf6..ad5388974e 100644 --- a/cpp/memilio/math/integrator.cpp +++ b/cpp/memilio/math/integrator.cpp @@ -58,7 +58,7 @@ Eigen::Ref OdeIntegrator::advance(const DerivFunction& f, const } if (!step_okay) { - log_warning("Adaptive step sizing failed."); + log_warning("Adaptive step sizing failed. Forcing an integration step of size dt_min."); } else if (std::abs((tmax - t) / (tmax - t0)) > 1e-14) { log_warning("Last time step too small. Could not reach tmax exactly."); diff --git a/cpp/memilio/math/integrator.h b/cpp/memilio/math/integrator.h index 37a23ae1ad..e1ca89a849 100644 --- a/cpp/memilio/math/integrator.h +++ b/cpp/memilio/math/integrator.h @@ -22,11 +22,8 @@ #include "memilio/utils/time_series.h" -#include "memilio/math/eigen.h" #include -#include #include -#include namespace mio { @@ -43,13 +40,27 @@ class IntegratorCore virtual ~IntegratorCore(){}; /** - * @brief Step of the integration with possible adaptive with + * @brief Make a single integration step. * - * @param[in] f Right hand side of ODE - * @param[in] yt value of y at t, y(t) - * @param[in,out] t current time step h=dt - * @param[in,out] dt current time step h=dt - * @param[out] ytp1 approximated value y(t+1) + * The behaviour of this method changes when the integration scheme has adaptive step sizing. + * These changes are noted in the parentheses (...) below. + * Adaptive integrators must have bounds dt_min and dt_max for dt. + * The adaptive step sizing is considered to be successful, if a step of at least size dt_min sufficed tolerances. + * Tolerances are defined in each implementation, usually using a criterion with absolute and relative tolerances. + * Even if the step sizing failed, the integrator will make a step of at least size dt_min. + * + * @param[in] f Right hand side of the ODE. May be called multiple times with different arguments. + * @param[in] yt The known value of y at time t. + * @param[in,out] t The current time. It will be increased by dt. + * (If adaptive, the increment is instead within [dt_min, dt].) + * @param[in,out] dt The current step size h=dt. Will not be changed. + * (If adaptive, the given dt is used as the maximum step size, and must be within [dt_min, dt_max]. + * During integration, dt is adjusted in [dt_min, dt_max] to have an optimal size for the next step.) + * @param[out] ytp1 Set to the approximated value of y at time t + dt. + * (If adaptive, this time may be smaller, but it is at least t + dt_min, at most t + dt_max. + * Note that the increment on t may be different from the returned value of dt.) + * @return Always true for nonadaptive methods. + * (If adaptive, returns whether the adaptive step sizing was successful.) */ virtual bool step(const DerivFunction& f, Eigen::Ref yt, double& t, double& dt, Eigen::Ref ytp1) const = 0; diff --git a/cpp/memilio/math/stepper_wrapper.h b/cpp/memilio/math/stepper_wrapper.h index 5d5e03f083..d0517b3df7 100644 --- a/cpp/memilio/math/stepper_wrapper.h +++ b/cpp/memilio/math/stepper_wrapper.h @@ -22,6 +22,7 @@ #include "memilio/utils/compiler_diagnostics.h" #include "memilio/math/integrator.h" +#include "memilio/utils/logging.h" GCC_CLANG_DIAGNOSTIC(push) GCC_CLANG_DIAGNOSTIC(ignored "-Wshadow") @@ -32,7 +33,7 @@ MSVC_WARNING_DISABLE_PUSH(4127) #include "boost/numeric/odeint/stepper/runge_kutta4.hpp" #include "boost/numeric/odeint/stepper/runge_kutta_fehlberg78.hpp" #include "boost/numeric/odeint/stepper/runge_kutta_cash_karp54.hpp" -#include "boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp" +// #include "boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp" // TODO: reenable once boost bug is fixed MSVC_WARNING_POP() GCC_CLANG_DIAGNOSTIC(pop) @@ -50,6 +51,12 @@ template