Skip to content

Commit 754675b

Browse files
1154 integrator is handled as adaptive if using small fixed step sizes (#1155)
Add a tolerance in OdeIntegrator when detecting whether the current IntegratorCore is adaptive. Co-authored-by: reneSchm <[email protected]>
1 parent c78bafd commit 754675b

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

cpp/memilio/config.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@
3030

3131
using ScalarType = double;
3232

33+
namespace ad
34+
{
35+
namespace internal
36+
{
37+
// Forward declaration used for support of ad types in Limits.
38+
// These templates are called AD_TAPE_REAL and DATA_HANDLER internally in AD.
39+
template <class FP, class DataHandler>
40+
struct active_type;
41+
} // namespace internal
42+
} // namespace ad
43+
3344
namespace mio
3445
{
3546
/**
@@ -67,6 +78,15 @@ struct Limits<double> {
6778
return 1e-12;
6879
}
6980
};
81+
82+
template <class FP, class DataHandler>
83+
struct Limits<ad::internal::active_type<FP, DataHandler>> {
84+
/// @brief Returns the limit under which an AD value may be rounded down to zero.
85+
static constexpr FP zero_tolerance()
86+
{
87+
return Limits<FP>::zero_tolerance();
88+
}
89+
};
7090
/** @} */
7191

7292
} // namespace mio

cpp/memilio/math/integrator.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#ifndef INTEGRATOR_H
2121
#define INTEGRATOR_H
2222

23+
#include "memilio/config.h"
2324
#include "memilio/math/floating_point.h"
2425
#include "memilio/utils/time_series.h"
2526
#include "memilio/utils/logging.h"
@@ -30,7 +31,7 @@ namespace mio
3031
{
3132

3233
/**
33-
* Function template to be integrated
34+
* Function template to be integrated.
3435
*/
3536
template <typename FP = double>
3637
using DerivFunction = std::function<void(Eigen::Ref<const mio::Vector<FP>> y, FP t, Eigen::Ref<mio::Vector<FP>> dydt)>;
@@ -118,8 +119,8 @@ class IntegratorCore
118119
};
119120

120121
/**
121-
* Integrate initial value problems (IVP) of ordinary differential equations (ODE) of the form y' = f(y, t), y(t0) = y0.
122-
* tparam FP a floating point type accepted by Eigen
122+
* @brief Integrate initial value problems (IVP) of ordinary differential equations (ODE) of the form y' = f(y, t), y(t0) = y0.
123+
* @tparam FP a floating point type accepted by Eigen
123124
*/
124125
template <typename FP = double>
125126
class OdeIntegrator
@@ -141,7 +142,7 @@ class OdeIntegrator
141142
* @param[in] tmax Time end point. Must be greater than results.get_last_time().
142143
* @param[in, out] dt Initial integration step size. May be changed by the IntegratorCore.
143144
* @param[in, out] results List of results. Must contain at least one time point. The last entry is used as
144-
* intitial time and value. A new entry is added for each integration step.
145+
* initial time and value. A new entry is added for each integration step.
145146
* @return A reference to the last value in the results time series.
146147
*/
147148

@@ -168,9 +169,9 @@ class OdeIntegrator
168169
FP t = t0;
169170

170171
for (size_t i = results.get_num_time_points() - 1; fabs((tmax - t) / (tmax - t0)) > 1e-10; ++i) {
171-
//we don't make timesteps too small as the error estimator of an adaptive integrator
172+
// We don't make time steps too small as the error estimator of an adaptive integrator
172173
//may not be able to handle it. this is very conservative and maybe unnecessary,
173-
//but also unlikely to happen. may need to be reevaluated
174+
//but also unlikely to happen. may need to be reevaluated.
174175

175176
if (dt > tmax - t) {
176177
dt_restore = dt;
@@ -187,8 +188,8 @@ class OdeIntegrator
187188
step_okay &= m_core->step(f, results[i], t, dt, results[i + 1]);
188189
results.get_last_time() = t;
189190

190-
// if dt has been changed (even slighly) by step, register the current m_core as adaptive
191-
m_is_adaptive |= !floating_point_equal(dt, dt_copy);
191+
// if dt has been changed by step, register the current m_core as adaptive.
192+
m_is_adaptive |= !floating_point_equal<FP>(dt, dt_copy, Limits<FP>::zero_tolerance());
192193
}
193194
m_core->get_dt_min() = dt_min_restore; // restore dt_min
194195
// if dt was decreased to reach tmax in the last time iteration,

0 commit comments

Comments
 (0)