38 #ifndef INTEGRATOR_HPP
39 #define INTEGRATOR_HPP
60 typedef std::function<vec(
const vec&,
const vec&,
const vec&,
const mat&)>
CoStateFunc;
81 template <
class ModelT>
82 mat
solve(
const ModelT& model,
const vec& x0,
const mat& ut,
double horizon)
const;
98 template <
class ModelT>
99 mat
solve(
const CoStateFunc& func,
const ModelT& model,
const vec& rhoT,
const mat& xt,
100 const mat& ut,
const mat& edx,
const mat& bdx,
double horizon)
const;
109 template <
class ModelT>
110 vec
step(
const ModelT& model,
const vec& x,
const vec& u)
const;
124 vec
step(
const CoStateFunc& func,
const vec& rho,
const vec& gdx,
const vec& dbar,
125 const mat& fdx)
const;
135 template <
class ModelT>
137 double horizon)
const
141 const auto steps =
static_cast<unsigned int>(std::abs(horizon /
dt_));
142 mat xt(x.n_rows, steps);
144 for (
unsigned int i = 0; i < steps; i++)
146 x =
step(model, x, ut.col(i));
154 template <
class ModelT>
156 const mat& xt,
const mat& ut,
const mat& edx,
const mat& bdx,
157 double horizon)
const
161 const auto steps =
static_cast<unsigned int>(std::abs(horizon /
dt_));
162 mat rhot(rho.n_rows, steps);
166 for (
unsigned int i = steps; i-- > 0;)
169 rho =
step(func, rho, edx.col(i), bdx.col(i), model.fdx(xt.col(i), ut.col(i)));
176 template <
class ModelT>
179 const vec k1 = model(x, u);
180 const vec k2 = model(x +
dt_ * (0.5 * k1), u);
181 const vec k3 = model(x +
dt_ * (0.5 * k2), u);
182 const vec k4 = model(x +
dt_ * k3, u);
183 return x + (
dt_ / 6.0) * (k1 + 2.0 * k2 + 2.0 * k3 + k4);
187 const vec& dbar,
const mat& fdx)
const
189 const vec k1 = func(rho, gdx, dbar, fdx);
190 const vec k2 = func(rho -
dt_ * (0.5 * k1), gdx, dbar, fdx);
191 const vec k3 = func(rho -
dt_ * (0.5 * k2), gdx, dbar, fdx);
192 const vec k4 = func(rho -
dt_ * k3, gdx, dbar, fdx);
193 return rho -
dt_ / 6.0 * (k1 + 2.0 * k2 + 2.0 * k3 + k4);
201 template <
class ModelT>
202 bool solve(mat& xt,
const ModelT& model,
const vec& x0,
const mat& ut,
double dt,
203 double horizon)
const;
205 template <
class ModelT>
206 bool solve(mat& rhot,
const CoStateFunc& func,
const ModelT& model,
const vec& rhoT,
207 const mat& xt,
const mat& ut,
const mat& edx,
const mat& bdx,
double dt,
208 double horizon)
const;
210 template <
class ModelT>
211 double step(vec& x_new,
const ModelT& model,
const vec& x,
const vec& u,
double h)
const;
213 double step(vec& rho_new,
const CoStateFunc& func,
const vec& rho,
const vec& gdx,
214 const vec& dbar,
const mat& fdx,
double h)
const;
223 : hmin_(hmin), hmax_(hmax), epsilon_(
epsilon), max_iter_(max_iter)
227 template <
class ModelT>
229 double dt,
double horizon)
const
237 const auto steps =
static_cast<unsigned int>(std::abs(horizon / dt));
238 const vec tvec = linspace(0.0, horizon, steps);
241 const auto max_steps =
static_cast<unsigned int>(horizon /
hmin_) + 1;
242 mat xt_max(x0.n_rows, max_steps);
243 vec tvec_max(max_steps);
251 unsigned int stored = 1;
252 unsigned int iter = 0;
256 const auto i =
static_cast<unsigned int>(
257 std::floor(std::round(
static_cast<double>(steps - 1) * std::abs(
t / horizon))));
260 const auto r =
step(x_new, model, x, ut.col(i), h);
266 xt_max.col(stored) = x;
269 tvec_max(stored) =
t;
274 h *= 0.84 * std::pow(
epsilon_ / r, 0.25);
283 else if (
t + h > horizon)
293 std::cout <<
"WARNING: max iterations reached " << std::endl;
311 xt.resize(x0.n_rows, steps);
312 for (
unsigned int i = 0; i < x0.n_rows; i++)
315 polyfit(tvec_max.rows(0, stored - 1), xt_max(span(i, i), span(0, stored - 1)), 4);
317 xt.row(i) = polyval(p, tvec).t();
323 template <
class ModelT>
327 const vec k1 = h * model(x, u);
329 const vec k2 = h * model(x + ((1.0 / 4.0) * k1), u);
331 const vec k3 = h * model(x + ((3.0 / 32.0) * k1) + ((9.0 / 32.0) * k2), u);
333 const vec k4 = h * model(x + ((1932.0 / 2197.0) * k1) - ((7200.0 / 2197.0) * k2) +
334 ((7296.0 / 2197.0) * k3),
336 const vec k5 = h * model(x + ((439.0 / 216.0) * k1) - (8.0 * k2) +
337 ((3680.0 / 513.0) * k3) - ((845.0 / 4104.0) * k4),
340 h * model(x - ((8.0 / 27.0) * k1) + (2.0 * k2) - ((3544.0 / 2565.0) * k3) +
341 ((1859.0 / 4104.0) * k4) - ((11.0 / 40.0) * k5),
344 x_new = x + ((25.0 / 216.0) * k1) + ((1408.0 / 2565.0) * k3) +
345 ((2197.0 / 4101.0) * k4) - ((1.0 / 5.0) * k5);
347 const vec z = x + ((16.0 / 135.0) * k1) + ((6656.0 / 12825.0) * k3) +
348 ((28561.0 / 56430.0) * k4) - ((9.0 / 50.0) * k5) + ((2.0 / 55.0) * k6);
353 return max(abs(z - x_new)) / h;
357 template <
class ModelT>
359 const vec& rhoT,
const mat& xt,
const mat& ut,
const mat& edx,
360 const mat& bdx,
double dt,
double horizon)
const
368 const auto steps =
static_cast<unsigned int>(std::abs(horizon / dt));
369 const vec tvec = linspace(0.0, horizon, steps);
372 const auto max_steps =
static_cast<unsigned int>(horizon /
hmin_) + 1;
373 mat rhot_max(rhoT.n_rows, max_steps);
374 vec tvec_max(max_steps);
377 rhot_max.col(0) = rhoT;
378 tvec_max(0) = horizon;
382 unsigned int stored = 1;
383 unsigned int iter = 0;
387 const auto i =
static_cast<unsigned int>(
388 std::floor(std::round(
static_cast<double>(steps - 1) * std::abs(
t / horizon))));
391 const auto r =
step(rho_new, func, rho, edx.col(i), bdx.col(i),
392 model.fdx(xt.col(i), ut.col(i)), h);
398 rhot_max.col(stored) = rho;
401 tvec_max(stored) =
t;
406 h *= 0.84 * std::pow(
epsilon_ / r, 0.25);
415 else if (
t - h < 0.0)
425 std::cout <<
"WARNING: max iterations reached " << std::endl;
443 rhot.resize(rho.n_rows, steps);
444 for (
unsigned int i = 0; i < rhoT.n_rows; i++)
446 const vec p = polyfit(tvec_max.rows(0, stored - 1),
447 rhot_max(span(i, i), span(0, stored - 1)), 4);
449 rhot.row(i) = polyval(p, tvec).t();
456 const vec& gdx,
const vec& dbar,
const mat& fdx,
double h)
const
458 const vec k1 = -h * func(rho, gdx, dbar, fdx);
460 const vec k2 = -h * func(rho + ((1.0 / 4.0) * k1), gdx, dbar, fdx);
463 -h * func(rho + ((3.0 / 32.0) * k1) + ((9.0 / 32.0) * k2), gdx, dbar, fdx);
465 const vec k4 = -h * func(rho + ((1932.0 / 2197.0) * k1) - ((7200.0 / 2197.0) * k2) +
466 ((7296.0 / 2197.0) * k3),
469 const vec k5 = -h * func(rho + ((439.0 / 216.0) * k1) - (8.0 * k2) +
470 ((3680.0 / 513.0) * k3) - ((845.0 / 4104.0) * k4),
474 -h * func(rho - ((8.0 / 27.0) * k1) + (2.0 * k2) - ((3544.0 / 2565.0) * k3) +
475 ((1859.0 / 4104.0) * k4) - ((11.0 / 40.0) * k5),
478 rho_new = rho + ((25.0 / 216.0) * k1) + ((1408.0 / 2565.0) * k3) +
479 ((2197.0 / 4101.0) * k4) - ((1.0 / 5.0) * k5);
481 const vec z = rho + ((16.0 / 135.0) * k1) + ((6656.0 / 12825.0) * k3) +
482 ((28561.0 / 56430.0) * k4) - ((9.0 / 50.0) * k5) + ((2.0 / 55.0) * k6);
487 return max(abs(z - rho_new)) / h;