Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
162 views
1
function [T, Y] = ode45octave(FUN, tspan, Y0, tol, varargin)
2
%ode45octave
3
% [T, Y] = ode45octave(FUN, tspan, Y0)
4
%
5
% Integra un sistema de ecuaciones diferenciales ordinarias usando el
6
% m�todo de Runge-Kutta en la variante Dormand-Price.
7
%
8
% [T, Y] = ode45octave(FUN, tspan, Y0, tol, par_1, par_2, ...)
9
% FUN funci�n con las derivadas
10
% tspan intervalo de integraci�n [tinicial, tfinal]
11
% Y0 magnitud inicial de las variables
12
% tol margen de error (por defecto 1e-10)
13
% par_i par�metros para FUN
14
% T puntos de integraci�n
15
% Y soluci�n del sistema de ecuaciones en cada punto
16
%
17
% Esta funci�n fue creada originalmente por Marc Compere
18
% http://users.powernet.co.uk/kienzle/octave/matcompat/scripts/ode_v1.11/ode45.m
19
% y modificada para simplificarla y garantizar la compatibilidad con
20
% Matlab. FUN debe usar la sintaxis de odefile en Matlab, de modo
21
% que dYdt = fun(t, Y, [], par_1, par_2, ...)
22
23
if nargin < 4, tol = []; end
24
if isempty(tol), tol = 1e-10; end
25
26
pow = 1/6; % see p.91 in the Ascher & Petzold reference for more infomation.
27
28
% Use the Dormand-Prince 4(5) coefficients:
29
a_(1,1)=0;
30
a_(2,1)=1/5;
31
a_(3,1)=3/40; a_(3,2)=9/40;
32
a_(4,1)=44/45; a_(4,2)=-56/15; a_(4,3)=32/9;
33
a_(5,1)=19372/6561; a_(5,2)=-25360/2187; a_(5,3)=64448/6561; a_(5,4)=-212/729;
34
a_(6,1)=9017/3168; a_(6,2)=-355/33; a_(6,3)=46732/5247; a_(6,4)=49/176; a_(6,5)=-5103/18656;
35
a_(7,1)=35/384; a_(7,2)=0; a_(7,3)=500/1113; a_(7,4)=125/192; a_(7,5)=-2187/6784; a_(7,6)=11/84;
36
% 4th order b-coefficients
37
b4_(1,1)=5179/57600; b4_(2,1)=0; b4_(3,1)=7571/16695; b4_(4,1)=393/640; b4_(5,1)=-92097/339200; b4_(6,1)=187/2100; b4_(7,1)=1/40;
38
% 5th order b-coefficients
39
b5_(1,1)=35/384; b5_(2,1)=0; b5_(3,1)=500/1113; b5_(4,1)=125/192; b5_(5,1)=-2187/6784; b5_(6,1)=11/84; b5_(7,1)=0;
40
41
for i=1:7
42
c_(i)=sum(a_(i,:));
43
end
44
45
% Initialization
46
t0 = tspan(1);
47
tfinal = tspan(2);
48
t = t0;
49
hmax = (tfinal - t) / 2.5;
50
hmin = (tfinal - t) / 1e9;
51
h = (tfinal - t)/100; % initial guess at a step size
52
x = Y0(:); % this always creates a column vector, x
53
T = t; % first output time
54
Y = x'; % first output solution
55
k_ = zeros(size(x,1), 7); % k_ needs to be initialized as an Nx7 matrix where N=number of rows in x
56
% (just for speed so octave doesn't need to allocate more memory at each stage value)
57
58
% Compute the first stage prior to the main loop. This is part of the Dormand-Prince pair caveat.
59
% Normally, during the main loop the last stage for x(k) is the first stage for computing x(k+1).
60
% So, the very first integration step requires 7 function evaluations, then each subsequent step
61
% 6 function evaluations because the first stage is simply assigned from the last step's last stage.
62
% note: you can see this by the last element in c_ is 1.0, thus t+c_(7)*h = t+h, ergo, the next step.
63
64
k_(:,1) = feval(FUN, t, x, [], varargin{1:nargin-4}); % first stage
65
66
% The main loop using Dormand-Prince 4(5) pair
67
while (t < tfinal) * (h >= hmin),
68
if t + h > tfinal, h = tfinal - t; end
69
70
% Compute the slopes by computing the k(:,j+1)'th column based on the previous k(:,1:j) columns
71
% notes: k_ needs to end up as an Nxs, a_ is 7x6, which is s by (s-1),
72
% s is the number of intermediate RK stages on [t (t+h)] (Dormand-Prince has s=7 stages)
73
for j = 1:6
74
k_(:,j+1) = feval(FUN, t+c_(j+1)*h, x+h*k_(:,1:j)*a_(j+1,1:j)', [], varargin{1:nargin-4});
75
end
76
77
% compute the 4th order estimate
78
x4 = x + h * (k_*b4_); % k_ is Nxs (or Nx7) and b4_ is a 7x1
79
80
% compute the 5th order estimate
81
x5 = x + h * (k_*b5_); % k_ is Nxs (or Nx7) and b5_ is a 7x1
82
83
% estimate the local truncation error
84
gamma1 = x5 - x4;
85
86
% Estimate the error and the acceptable error
87
delta = norm(gamma1, 'inf'); % actual error
88
tau = tol * max(norm(x, 'inf'), 1.0); % allowable error
89
90
% Update the solution only if the error is acceptable
91
if (delta <= tau)
92
t = t + h;
93
x = x5; % <-- using the higher order estimate is called 'local extrapolation'
94
T = [T; t];
95
Y = [Y; x'];
96
end
97
98
% Update the step size
99
if (delta == 0.0), delta = 1e-16; end
100
h = min(hmax, 0.8*h*(tau/delta)^pow);
101
102
% Assign the last stage for x(k) as the first stage for computing x(k+1).
103
% This is part of the Dormand-Prince pair caveat.
104
% k_(:,7) has already been computed, so use it instead of recomputing it
105
% again as k_(:,1) during the next step.
106
k_(:,1) = k_(:,7);
107
108
end
109
110
if (t < tfinal), disp('Step size grew too small.'); end
111
112
if nargout == 0
113
plot(T, Y, 'o-');
114
T = [];
115
end
116
117
118