Runge Kutta - Matlab
Runge Kutta - Matlab
Jakob Kibsgaard
Runge-Kutta method
The simplest method (and least accurate) for integrating such a problem is the
Euler method. The derivative at the starting point of each interval is extrapolated
to find the next function value. The method only has first-order accuracy.
yn+1 = yn + hf (xn , yn )
(1)
y(x)
2
x1
x3
x2
y(x)
Auxiliary point
2
1
x1
x3
x2
(2)
Another approach (also of second order) is first to take the full step with the
Euler method then calculate the derivative of this point k1 = f (x1 , y0 + hk0 ). The
average between k0 and k1 can now be chosen as the final k = 12 (k0 + k1 ), which
then can be used to take the step y1 = y0 + h k. The following set of equations is
therefor obtained:
k0 = f (x0 , y0 )
k1 = f (x1 , y0 + hk0 )
1
k =
(k0 + k1 )
2
y1 = y0 + h k
(3)
The two second order methods can be combined to yield a third order method,
where the k constant is given as:
4
1
1
k = k0 + k1/2 + k1
6
6
6
where k0 , k1/2 and k1 can be found in equation 2 and 3.
(4)
In principle one could now use the above equations with the same stepsize h until
the end point of the given interval is reached. A better approach when computing
time is taken into consideration is to use adaptive stepsize control. By implementing
this uninteresting parts of the function can be crossed in a few big steps, while the
interesting parts are crossed with small stepsizes. The program therefor tries to
the biggest step without exceeding a certain tolerance specified by the user. The
tolerance is given as:
s
h
tol = (eps | y | +acc)
(5)
ba
where eps is relative accuracy and acc is the absolute accuracy specified by the user.
The error of a step can be estimated by comparing the solution for a full-step and
that of two half-steps:
| y(h) y(2 h2 ) |
(6)
err =
2k 1
If the err > 2 tol the step should be rejected and a new stepsize with h = h2
should be used. If err < 2 tol the step is accepted and a new stepsize is found by:
hN ext = hCurrent (
tol P ower
)
Saf ety
err
(7)
where P ower 0.25 and Saf ety 0.95. As a further safety one could implement
the condition that if hN ext > 2 hCurrent then new stepsize should only be hN ext =
2 hCurrent .
Generalization
z = z ;
y1 = y2
y1 = z
y2 = z
y2 = y1
It is very easy to generalize the source code in MATLAB. All there needs to be
done is to replace the ys (numbers) with Y s (vectors) where:
Y =
y1
y2
..
.
yn
and
Y = F (x, Y ) =
f1 (x, Y )
f2 (x, Y )
..
.
fn (x, Y )
The initial condition is now also a column vector Y (x0 ) = Y0 . Notice that the
ks also becomes vectors. The only real (though small) adjustment in the source
code apart from changing to vectors is the estimate of the error. The error of a step
is simply the maximum value of the errors for the individual differential equations:
| Y (h) Y (2 h2 ) |
err = max
2k 1
(8)
Source Code
4.1
4.1.1
INPUT
a:
ya:
b:
h_0:
acc:
eps:
% OUTPUT:
% Res: The y-value of x=b.
% err: The calculated (over all steps) total error.
% Initialize variables
inc=1;
err=0;
x(inc)=a;
y(inc)=ya;
h=h_0;
inc=2;
% The first run of the function RKstep.m, which finds the next
% (x,y)-pairs and the error for the step by the Runge-Kutta method.
[x(inc),y(inc),y_old,err_step] = RKStep(x,y,h);
% Loop to find the following points.
while x(inc)<b
% Makes sure that the interval is not exceeded
tol=acc*sqrt(h/(b-a))+eps*y(inc)*sqrt(h/(b-a));
% The tolerance is calculated
inc=inc+1;
if err_step>2*tol
% If the error for the step is too large -> The point (x(inc),Y(inc)) is
% calculated again with h=h/2.
h=h/2;
if h > (b-x(inc-1));
% Makes sure that the interval end point is not exceeded
h = b-x(inc-1);
end
inc=inc-1;
[x(inc),y(inc),y_old,err_step] = RKStep(x(inc-1),y_old,h);
else
% The previous point is accepted and a new step is found.
err=sqrt(err^2+err_step^2);
% The total error for the entire interval is added up.
h_old=h;
h=0.95*(tol/err_step)^0.25*h; % A new step size is found.
if h>2*h_old
% If the increase in h is too large -> h=2*h.
h=2*h_old;
if h > (b-x(inc-1));
% Makes sure that the interval end-point is not exceeded.
h = b-x(inc-1);
end
[x(inc),y(inc),y_old,err_step] = RKStep(x(inc-1),y(inc-1),h); % The new (x,y) point
% and the error are found
% with RKStep.m
else
if h > (b-x(inc-1));
% Makes sure that the interval end-point is not exceeded.
h = b-x(inc-1);
end
[x(inc),y(inc),y_old,err_step] = RKStep(x(inc-1),y(inc-1),h); % The new (x,y) point
% and the error are found
% with RKStep.m
end
end
end
err=sqrt(err^2+err_step^2);
% The error for the last step is included in the total error.
plot(x,y)
% The function y(x) is plotted.
res=y(inc);
% The value of y in x=b is written out.
4.1.2
RKStep.m
4.2
4.2.1
%
%
%
%
%
%
%
%
INPUT
a:
ya:
ya_diff:
b:
h_0:
acc:
eps:
%OUTPUT:
%Res: The y-value of x=b.
%err: The calculated (over all steps) total error.
% Initialize variables
inc=1;
err=0;
x(inc)=a;
Y(:,inc)=[ya ; ya_diff];
h=h_0;
inc=2;
% The first run of the function RK2step.m, which finds the next
% (x,Y)-pairs and the error for the step by the Runge-Kutta method.
[x(inc),Y(:,inc),Y_old,err_step] = RK2Step(x,Y,h);
4.2.2
RK2Step.m