runge kutta _matlab
TRANSCRIPT
-
8/10/2019 Runge Kutta _Matlab
1/6
Runge-Kutta method in MATLAB
Jakob Kibsgaard
Many physical problems can be thought of as a system of ordinary differentialequations y(x)=f(x,y) with an initial condition y(0)=y0, where y and f(x,y) aregenerally understood as column vectors. It is therefor of great importance to beable to solve such a system of equations.
1 Runge-Kutta method
The simplest method (and least accurate) for integrating such a problem is theEuler method. The derivative at the starting point of each interval is extrapolatedto find the next function value. The method only has first-order accuracy.
yn+1=yn+hf(xn, yn) (1)
1
2
x x x x1 2 3
(x)
h
Figure 1: The Euler method which advances a solution from xn to xn+1 xn+ h.
A better way of solving this kind of problem was devised by Runge and Kutta.The methods are one-step methods where the solution y is advanced by one step has y1= y0 + hk, where k is a cleverly chosen constant. The first order Runge-Kuttamethod is simply the Euler method i.e. k= f(x0, y0).
The second order Runge-Kutta method advances the solution by the use of anauxiliary evaluation of the derivative (see figure 2).
1
-
8/10/2019 Runge Kutta _Matlab
2/6
1
2
x x x x1 2 3
(x)
h
Auxiliary point
Figure 2: The second order Runge-Kutta method. Second-order accuracy is obtained byusing the initial derivative at each step to find a point halfway across the interval, then
using the midpoint derivative across the full width h of the interval.
This gives the following set of equations:
k0 = f(x0, y0)
y1/2 = y0+h
2 k0 (2)
k1/2 = f(x1/2, y1/2)
y1 = y0+h k1/2
Another approach (also of second order) is first to take the full step with theEuler method then calculate the derivative of this point k1=f(x1, y0+hk0). Theaverage between k0 and k1 can now be chosen as the final k =
1
2(k0+ k1), which
then can be used to take the step y1=y0+h k. The following set of equations istherefor obtained:
k0 = f(x0, y0)
k1 = f(x1, y0+hk0) (3)
k = 1
2(k0+k1)
y1 = y0+h k
The two second order methods can be combined to yield a third order method,where the k constant is given as:
k=1
6k0+
4
6k1/2+
1
6k1 (4)
wherek0, k1/2 and k1 can be found in equation 2 and 3.
2
-
8/10/2019 Runge Kutta _Matlab
3/6
2 Adaptive Stepsize Control
In principle one could now use the above equations with the same stepsize h untilthe end point of the given interval is reached. A better approach when computingtime 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 theinteresting parts are crossed with small stepsizes. The program therefor tries tothe biggest step without exceeding a certain tolerance specified by the user. Thetolerance is given as:
tol= (eps | y | +acc)
h
b a (5)
whereepsis relative accuracy andacc is the absolute accuracy specified by the user.The error of a step can be estimated by comparing the solution for a full-step andthat of two half-steps:
err =
| y(h) y(2 h2
) |
2k 1 (6)
If the err > 2 tol the step should be rejected and a new stepsize with h = h2
should be used. Iferr 2 hCurrent then new stepsize should only be hNext =2 hCurrent.
3 Generalization
A higher order ordinary differential equation can be replaced by at set of coupledfirst order differential equations e.g.:
z = z
y1=zy2=z
y1
=y2y2= y1
It is very easy to generalize the source code in MATLAB. All there needs to bedone is to replace the ys (numbers) with Ys (vectors) where:
Y =
y1y2...
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 theks also becomes vectors. The only real (though small) adjustment in the sourcecode apart from changing to vectors is the estimate of the error. The error of a stepis simply the maximum value of the errors for the individual differential equations:
err = max
| Y(h) Y(2 h
2) |
2k 1
(8)
3
-
8/10/2019 Runge Kutta _Matlab
4/6
4 Source Code
4.1 Solving one first order differential equation
4.1.1 RK.m
function [res,err] = RK(a,ya,b,h_0,acc,eps);
% The function RK.m solves a differential equation. This is done by the
% Runge-Kutta method, which finds the value y(b) of a function there fulfils dy/dx=f(x,y)% and the initial condition y(a)=ya. All (x,y)-pairs are saved and used in a plot finally.
% INPUT
% a: The start-point for the interval we are considering.% ya: The y-value in x=a.
% b: The end-point of the interval we are considering.
% h_0: Initial step value.
% acc: The demanded absolute accuracy.% eps: The demanded relative accuracy.
% OUTPUT:% Res: The y-value of x=b.% err: The calculated (over all steps) total error.
% Initialize variablesinc=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)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.melse
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
endend
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
-
8/10/2019 Runge Kutta _Matlab
5/6
4.1.2 RKStep.m
function [x,y,y_old,err_step] = RKStep(x,y,h);
% The current y-values are saved in y_old.y_old=y;
% The y-value in x=x+h is found with a stepsize h:
k_0=f(x,y);
k_1=f(x+h,y+h*k_0);k_half=f(x+h/2,y+h/2*k_0);
k=1/6*k_0+4/6*k_half+1/6*k_1;
y_h=y+k*h;
% The y-value in x=x+h is found in two turns, each with a stepsize h/2:
% First call:
k_0=f(x,y);k_1=f(x+h/2,y+h/2*k_0);
k_half=f(x+h/4,y+h/4*k_0);
k=1/6*k_0+4/6*k_half+1/6*k_1;
y=y+k*h/2;x=x+h/2;
% Second call:
k_0=f(x,y);
k_1=f(x+h/2,y+h/2*k_0);k_half=f(x+h/4,y+h/4*k_0);
k=1/6*k_0+4/6*k_half+1/6*k_1;
y=y+k*h/2;
x=x+h/2;
% The error estimate:
err_step=abs(y_h-y)/7;
4.2 Solving a set of first order differential equations
4.2.1 RK2.m
function [res,err] = RK2(a,ya,ya_diff,b,h_0,acc,eps);
% The function RK2.m solves a system of differential equations. This is done by the% Runge-Kutta method, which finds the value y(b) of a function there fulfils dy/dx=f(x,y)
% and the initial condition y(a)=ya. The program saves y-values in the vector Y, Y=[y,y]
% All (x,y)-pairs are saved and used in a plot finally.
% INPUT
% a: The start-point for the interval we are considering.
% ya: The y-value in x=a.
% ya_diff: The y-value in x=a.% b: The end-point of the interval we are considering.
% h_0: Initial step value.
% acc: The demanded absolute accuracy.
% eps: The demanded relative accuracy.
%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);
5
-
8/10/2019 Runge Kutta _Matlab
6/6
% Loop to find the following points.while x(inc)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] = RK2Step(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] = RK2Step(x(inc-1),Y(:,inc-1),h); % The new (x,Y) points and the error
% are found with RK2Step.melse
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] = RK2Step(x(inc-1),Y(:,inc-1),h); % The new (x,Y) points and the error
% are found with RK2Step.m
end
endend
err=sqrt(err^2+err_step^2); % The error for the last step is included in the total error.
plot(x,Y(1,:)) % The function y(x) is plotted.
res=Y(1,inc); % The value of y in x=b is written out.
4.2.2 RK2Step.mfunction [x,Y,Y_old,err_step] = RK2Step(x,Y,h);
% The current Y-values are saved in Y_old.Y_old=Y;
% The y-value in x=x+h is found with a stepsize h:
k_0=f(x,Y);k_1=f(x+h,Y+h*k_0);
k_half=f(x+h/2,Y+h/2*k_0);
k=1/6*k_0+4/6*k_half+1/6*k_1;
Y_h=Y+k*h;
% The y-value in x=x+h is found in two turns, each with a stepsize h/2:
% First call:
k_0=f(x,Y);k_1=f(x+h/2,Y+h/2*k_0);
k_half=f(x+h/4,Y+h/4*k_0);
k=1/6*k_0+4/6*k_half+1/6*k_1;Y=Y+k*h/2;
x=x+h/2;
% Second call:
k_0=f(x,Y);k_1=f(x+h/2,Y+h/2*k_0);
k_half=f(x+h/4,Y+h/4*k_0);
k=1/6*k_0+4/6*k_half+1/6*k_1;
Y=Y+k*h/2;x=x+h/2;
% The error estimate:
err_step=max(abs(Y_h-Y)/7);
6