27namespace ButcherTableau
30#pragma GCC diagnostic push
31#if !defined(__clang__)
32 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
43template<
typename Y,
typename Z,
typename Scalar,
size_t s, std::array<std::array<Scalar, s + 1>, s + 1> butcherTableau,
44 typename = std::enable_if_t<std::is_
floating_po
int_v<Scalar>>>
45inline Y
RungeKuttaExplicit(
const Y& y_n,
const std::array<Z, s> z,
const Scalar& h,
const auto& f,
const auto& constParam,
const Scalar& t_n)
47 static_assert(gcem::abs(
static_cast<Scalar
>(1.0) - std::accumulate(butcherTableau[s].begin(), butcherTableau[s].end(),
static_cast<Scalar
>(0.0))) < 1e-8,
48 "The sum of the last row in the Butcher tableau has to be 1");
49 for (
size_t r = 0; r <= s; ++r)
51 for (
size_t c = r + 1; c <= s; ++c)
53 INS_ASSERT_USER_ERROR(butcherTableau.at(r).at(c) == 0.0,
"All terms in the upper triangle have to be 0");
63 for (
size_t i = 1; i <= s; ++i)
65 auto b = butcherTableau[s].at(i);
66 auto c = butcherTableau.at(i - 1)[0];
70 for (
size_t j = 2; j <= i; ++j)
72 auto a = butcherTableau.at(i - 1).at(j - 1);
73 if (j == 2) { sum_a = a * k.at(j - 2); }
74 else { sum_a += a * k.at(j - 2); }
83 if (i < 2) { k.at(i - 1) = f(y_n, z.at(i - 1), constParam, t_n + c * h); }
84 else { k.at(i - 1) = f(y_n + sum_a * h, z.at(i - 1), constParam, t_n + c * h); }
90 if (i == 1) { sum_b = b * k.at(i - 1); }
91 else { sum_b += b * k.at(i - 1); }
103 return y_n + h * sum_b;
106#pragma GCC diagnostic pop
109template<
typename Scalar>
110constexpr std::array<std::array<Scalar, 2>, 2>
RK1 = { { { 0.0, },
115template<
typename Scalar>
116constexpr std::array<std::array<Scalar, 3>, 3>
RK2 = { { { 0.0, },
119 { 0.0, 0.0, 1.0 } } };
122template<
typename Scalar>
123constexpr std::array<std::array<Scalar, 3>, 3>
Heun2 = { { { 0.0, },
126 { 0.0, 0.5, 0.5 } } };
129template<
typename Scalar>
130constexpr std::array<std::array<Scalar, 4>, 4>
RK3 = { { { 0.0, },
134 { 0.0, 1.0 / 6.0, 4.0 / 6.0, 1.0 / 6.0 } } };
137template<
typename Scalar>
138constexpr std::array<std::array<Scalar, 4>, 4>
Heun3 = { { { 0.0, },
139 { 1.0 / 3.0, 1.0 / 3.0 },
140 { 2.0 / 3.0, 0.0, 2.0 / 3.0 },
142 { 0.0, 1.0 / 4.0, 0.0, 3.0 / 4.0 } } };
145template<
typename Scalar>
146constexpr std::array<std::array<Scalar, 5>, 5>
RK4 = { { { 0.0, },
149 { 1.0, 0.0, 0.0, 1.0 },
151 { 0.0, 1.0 / 6.0, 1.0 / 3.0, 1.0 / 3.0, 1.0 / 6.0 } } };
173template<
typename Y,
typename Z,
typename Scalar,
typename = std::enable_if_t<std::is_
floating_po
int_v<Scalar>>>
174Y
RungeKutta1(
const Y& y_n,
const std::array<Z, 1> z,
const Scalar& h,
const auto& f,
const auto& constParam,
const Scalar& t_n = 0)
176 return ButcherTableau::RungeKuttaExplicit<Y, Z, Scalar, 1, ButcherTableau::RK1<Scalar>>(y_n, z, h, f, constParam, t_n);
202template<
typename Y,
typename Z,
typename Scalar,
typename = std::enable_if_t<std::is_
floating_po
int_v<Scalar>>>
203Y
RungeKutta2(
const Y& y_n,
const std::array<Z, 2> z,
const Scalar& h,
const auto& f,
const auto& constParam,
const Scalar& t_n = 0)
205 return ButcherTableau::RungeKuttaExplicit<Y, Z, Scalar, 2, ButcherTableau::RK2<Scalar>>(y_n, z, h, f, constParam, t_n);
231template<
typename Y,
typename Z,
typename Scalar,
typename = std::enable_if_t<std::is_
floating_po
int_v<Scalar>>>
232Y Heun2(
const Y& y_n,
const std::array<Z, 2> z,
const Scalar& h,
const auto& f,
const auto& constParam,
const Scalar& t_n = 0)
234 return ButcherTableau::RungeKuttaExplicit<Y, Z, Scalar, 2, ButcherTableau::Heun2<Scalar>>(y_n, z, h, f, constParam, t_n);
262template<
typename Y,
typename Z,
typename Scalar,
typename = std::enable_if_t<std::is_
floating_po
int_v<Scalar>>>
263Y
RungeKutta3(
const Y& y_n,
const std::array<Z, 3> z,
const Scalar& h,
const auto& f,
const auto& constParam,
const Scalar& t_n = 0)
265 return ButcherTableau::RungeKuttaExplicit<Y, Z, Scalar, 3, ButcherTableau::RK3<Scalar>>(y_n, z, h, f, constParam, t_n);
293template<
typename Y,
typename Z,
typename Scalar,
typename = std::enable_if_t<std::is_
floating_po
int_v<Scalar>>>
294Y Heun3(
const Y& y_n,
const std::array<Z, 3> z,
const Scalar& h,
const auto& f,
const auto& constParam,
const Scalar& t_n = 0)
296 return ButcherTableau::RungeKuttaExplicit<Y, Z, Scalar, 3, ButcherTableau::Heun3<Scalar>>(y_n, z, h, f, constParam, t_n);
326template<
typename Y,
typename Z,
typename Scalar,
typename = std::enable_if_t<std::is_
floating_po
int_v<Scalar>>>
327Y
RungeKutta4(
const Y& y_n,
const std::array<Z, 4> z,
const Scalar& h,
const auto& f,
const auto& constParam,
const Scalar& t_n = 0)
329 return ButcherTableau::RungeKuttaExplicit<Y, Z, Scalar, 4, ButcherTableau::RK4<Scalar>>(y_n, z, h, f, constParam, t_n);
#define INS_ASSERT_USER_ERROR(_EXP, _MSG)
Assert function with message.
Definition Assert.h:21
Utility class for logging to console and file.
Y RungeKutta3(const Y &y_n, const std::array< Z, 3 > z, const Scalar &h, const auto &f, const auto &constParam, const Scalar &t_n=0)
Runge-Kutta 3rd order (explicit) / Simpson's rule .
Definition NumericalIntegration.hpp:263
constexpr std::array< std::array< Scalar, 5 >, 5 > RK4
Butcher tableau for Runge-Kutta 4th order (explicit)
Definition NumericalIntegration.hpp:146
Y RungeKutta1(const Y &y_n, const std::array< Z, 1 > z, const Scalar &h, const auto &f, const auto &constParam, const Scalar &t_n=0)
Runge-Kutta 1st order (explicit) / (Forward) Euler method .
Definition NumericalIntegration.hpp:174
Y RungeKuttaExplicit(const Y &y_n, const std::array< Z, s > z, const Scalar &h, const auto &f, const auto &constParam, const Scalar &t_n)
Calculates explicit Runge-Kutta methods. Order is defined by the Butcher tableau.
Definition NumericalIntegration.hpp:45
Y RungeKutta4(const Y &y_n, const std::array< Z, 4 > z, const Scalar &h, const auto &f, const auto &constParam, const Scalar &t_n=0)
Runge-Kutta 4th order (explicit) .
Definition NumericalIntegration.hpp:327
constexpr std::array< std::array< Scalar, 4 >, 4 > Heun3
Butcher tableau for Heun's method (3nd order) (explicit)
Definition NumericalIntegration.hpp:138
constexpr std::array< std::array< Scalar, 3 >, 3 > Heun2
Butcher tableau for Heun's method (2nd order) (explicit)
Definition NumericalIntegration.hpp:123
constexpr std::array< std::array< Scalar, 4 >, 4 > RK3
Butcher tableau for Runge-Kutta 3rd order (explicit) / Simpson's rule.
Definition NumericalIntegration.hpp:130
constexpr std::array< std::array< Scalar, 3 >, 3 > RK2
Butcher tableau for Runge-Kutta 2nd order (explicit) / Explicit midpoint method.
Definition NumericalIntegration.hpp:116
constexpr std::array< std::array< Scalar, 2 >, 2 > RK1
Butcher tableau for Runge-Kutta 1st order (explicit) / (Forward) Euler method.
Definition NumericalIntegration.hpp:110
Y RungeKutta2(const Y &y_n, const std::array< Z, 2 > z, const Scalar &h, const auto &f, const auto &constParam, const Scalar &t_n=0)
Runge-Kutta 2nd order (explicit) / Explicit midpoint method .
Definition NumericalIntegration.hpp:203