/
rk23.m
50 lines (43 loc) · 1.67 KB
/
rk23.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
function [t,u] = rk23(dudt,tspan,u0,tol)
% RK23 Adaptive IVP solver based on embedded RK formulas.
% Input:
% dudt defines f in u'(t)=f(t,u) (function)
% tspan endpoints of time interval (2-vector)
% u0 initial value (vector, length m)
% tol global error target (positive scalar)
% Output:
% t selected nodes (vector, length n+1)
% u solution values (array, size m by n+1)
% Initialize for the first time step.
t = tspan(1);
u(:,1) = u0(:); i = 1;
h = 0.5*tol^(1/3);
s1 = dudt(t(1), u(:,1));
% Time stepping.
while t(i) < tspan(2)
% Detect underflow of the step size.
if t(i)+h == t(i)
warning('Stepsize too small near t=%.6g.',t(i))
break % quit time stepping loop
end
% New RK stages.
s2 = dudt( t(i)+h/2, u(:,i)+(h/2)*s1 );
s3 = dudt( t(i)+3*h/4, u(:,i)+(3*h/4)*s2 );
unew2 = u(:,i) + h*(2*s1 + 3*s2 + 4*s3)/9; % 2rd order solution
s4 = dudt( t(i)+h, unew2 );
err = h*(-5*s1/72 + s2/12 + s3/9 - s4/8); % 2nd/3rd order difference
E = norm(err,inf); % error estimate
maxerr = tol*(1 + norm(u(:,i),inf)); % relative/absolute blend
% Accept the proposed step?
if E < maxerr % yes
t(i+1) = t(i) + h;
u(:,i+1) = unew2;
i = i+1;
s1 = s4; % use FSAL property
end
% Adjust step size.
q = 0.8*(maxerr/E)^(1/3); % conservative optimal step factor
q = min(q,4); % limit stepsize growth
h = min(q*h,tspan(2)-t(i)); % don't step past the end
end
t = t'; u = u.'; % conform to MATLAB output convention