Below I will describe an algorithm for solving IVP by any explicit Runge-Kutta method of any order for any dimensionality of the system, I have not seen such an implementation anywhere. The advantage of this algorithm is that the code will look much more compact, since you will not have to create cumbersome and long expressions to compute this or that expression for each individual IVP. All you have to do is fill in the Butcher tableau for the method you want the IVP to be solved by.
- Explicit Runge—Kutta methods. Butcher tableau
- Description of the implemented algorithm
- Example
- Notes
- Planned Features
- References
Let an initial value problem be specified as follows:
where
The
where
Method coefficients are conveniently set in the form of a Butcher tableau:
In the program implementation other elements of the matrix
Of course, you can implement the algorithm described in the previous section as well, and it will work the same way as the algorithm I will describe below.
So, the algorithm is based on the application of general matrix algebra:
To begin with, at each (also take a look here) iteration we need to initialize the matrix
and the matrix
Then the formulas for filling the matrix
The ExampleOfUse.mlx file shows the obtaining of the Tamari attractor
with initial conditions
using the 6th order Runge-Kutta-Butcher method.
-
c_vector
: vector of coefficients$\mathbf{c}$ of Butcher tableau for the selected method; -
A_matrix
: matrix of coefficients$\mathbf{A}$ of Butcher tableau for the selected method; -
b_vector
: vector of coefficients$\mathbf{b}$ of Butcher tableau for the selected method; -
odefun
: functions to solve, specified as a function handle that defines the functions to be integrated; -
tspan
: interval of integration, specified as a two-element vector; -
tau
: time discretization step; -
incond
: vector of initial conditions.
t
: vector of evaluation points used to perform the integration;xsol
: solution matrix in which each row corresponds to a solution at the value returned in the corresponding row oft
.
The code from the odeExplicitGeneral.m script shows a more illustrative integration procedure, for understanding from a theoretical point of view. The optimized version of this script odeExplicitGeneral_optimized.m looks as follows:
function [t, xsol] = odeExplicitGeneral_optimized(c_vector, A_matrix, b_vector, odefun, tspan, tau, incond)
s_stages = length(c_vector);
m = length(incond);
c_vector = reshape(c_vector, [s_stages 1]);
b_vector = reshape(b_vector, [s_stages 1]);
incond = reshape(incond, [m 1]);
t = (tspan(1):tau :tspan(2))';
xsol = zeros(length(incond), length(t));
xsol(:, 1) = incond(:);
K_matrix = zeros(m, s_stages);
for n = 1:length(t)-1
K_matrix(:, 1) = odefun(t(n), xsol(:, n));
for i = 2:s_stages
K_matrix(:, i) = odefun(t(n) + tau * c_vector(i), xsol(:, n) + tau * K_matrix(:, 1:i-1) * A_matrix(i, 1:i-1)');
end
xsol(:, n+1) = xsol(:, n) + tau * K_matrix * b_vector;
end
xsol = xsol';
end
With only 23 lines for such a powerful instrument, it looks awesome, doesn't it?
Here no unnecessary variables are created, and the K_matrix
is initialized as zero matrix only once, because the algorithm allows not to fill it with zeros at each iteration, but just to overwrite the columns at this iteration without using the columns with coeficients from the previous one:
K_matrix(:, i) = odefun(t(n) + tau * c_vector(i), xsol(:, n) + tau * K_matrix(:, 1:i-1) * A_matrix(i, 1:i-1)')
- based on this script, add specific integrators, as I did here with the Runge-Kutta method of order 4.
- Butcher, J. (2016). Numerical methods for ordinary differential equations. https://doi.org/10.1002/9781119121534
- Tamari, B. (1997). Conservation and symmetry laws and stabilization programs in economics. https://www.bentamari.com/PicturesEcometry/Book3-Conservation.pdf