11.5. Numerical Differential Equations¶
Reading Assignment
Please read chapter 8 of Physical Modeling in MATLAB, by Allen B. Downey [DOWNEY11].
An ordinary differential equation (ODE) is an equation of the form
We are given the rate of change (the derivative function ) of from which we solve for . Because we are also given the initial value , this class of ODE problem is called an initial value problem (IVP). We will consider cases of the function that represents a single equation and also a system of equations.
Differential equations are important to engineers and scientists because changes to the state of dynamic systems are described by differential equations. Examples of these dynamic systems include objects that move; wires carrying fluctuating electrical current; reservoirs of fluid with measurable pressure, temperature, and volume; or anything where the state of the system can be quantified numerically.
Numerical methods are especially needed to solve higher order and nonlinear ODEs. As is the case with integration, our ability to properly evaluate some ODEs using analytic methods is less than satisfying [STRANG14]. So numerical methods for solving ODEs is an important tool in the engineer’s computational toolbox.
This is our third encounter with ODEs. In Throwing a Ball Up, we used MATLAB’s Symbolic Math Toolbox to find the algebraic equations from the differential equations associated with the effect of gravity on a ball thrown upwards. Then in Systems of Linear ODEs we considered systems of first order linear ODEs that may be solved analytically with eigenvalues and eigenvectors. Now, we will consider numerical methods to find and plot the solutions to ODEs. We will cover the basic algorithmic concepts of how numerical ODE solvers work and review the efficient suite of ODE solver provided by MATLAB.
Recall the definition of a derivative:
Considered in terms of discrete samples of , the derivative becomes
where is the distance between sample points, .
Rearranged to find from the previous value, , and the slope of the function at , we have
(11.1)¶
This equation is the basis for the simplest ODE solver, Euler’s method. However, due to concerns about excessive computation and round-off errors, we are limited on how small can be. So the accuracy of (11.1) is not acceptable for most applications.
Since differential equations are given in terms of an equation for the derivative of , , and the initial value, , the general discrete solution comes from the fundamental theorem of calculus, which applies the antiderivative of a function to a definite integral.
(11.2)¶
Then the numerical approximation comes from the algorithm used to calculate the definite integral.
(11.3)¶
At each step, the ODE solver uses a straight line with a slope of to advance to .
11.5.1. Euler’s Method¶
Euler’s method uses a Reimann integral to approximate (11.3) with constant height rectangular subintervals. It is a reasonable solution if is constant or nearly constant. However, the results from Euler’s methods applied to most ODEs are not accurate enough for most applications unless the step size is small enough relative to the rate of change of the function.
Euler’s method is a perfect match if we let , then
Then by induction,
The eulerODE
function listed below is an implementation of Euler’s method.
The first three arguments passed to eulerODE
are the same as is used with
the MATLAB ODE solvers. An additional argument for the number of values to find is
also passed to eulerODE
. First, define a function or function handle.
The function defines the derivative of the solution. It
should take two arguments, and . Although in many cases,
the function only operates on one variable—usually the second, y
,
variable. The function should accept and return vector variables.
Next, specify a tspan
argument, which is a row vector of the initial and
final values ([t_0 t_final]
). Then, the value of at the
initial time is specified . The final argument is , the
number of values to find. The returned data from all of the ODE solvers are the
evaluation points and the solution.
>> f = @(t, y) 5
>> [t, y] = eulerODE(f, [0 10], 5, 4)
t =
0 3.3333 6.6667 10.0000
y =
5.0000 21.6667 38.3333 55.0000
Fig. 11.18 shows a plot comparing the relative accuracy of Euler’s method to other fixed step size algorithms.
function [t, y] = eulerODE(f, tspan, y0, n)
% EULERODE - ODE solver using Euler's method.
%
% f - vectorized derivative function, y' = f(t, y)
% tspan - row vector [t0 tf] for initial and final time
% y0 - initial value of y
% n - number of y values to find
h = (tspan(2) - tspan(1))/(n-1);
t = linspace(tspan(1), tspan(2), n);
y = zeros(1, n);
y(1) = y0;
for k = 1:n-1
y(k+1) = y(k) + h*f(t(k), y(k));
end
11.5.2. Heun’s Method¶
Heun’s method uses trapezoid rule integration to approximate (11.3).
(11.4)¶
However, (11.4) makes use of , which is not yet know. So Euler’s method is first used to make an initial estimate of . Because the algorithm makes an initial prediction of and then updates the estimate with a later equation, Heun’s method belongs to a class of algorithms called predictor–corrector methods.
The complete Heun method approximation equation is given by (11.5).
(11.5)¶
The heunODE
function listed below is called with the same arguments
as the eulerODE
function.
function [t, y] = heunODE(f, tspan, y0, n)
% HEUNODE - ODE solver using Heun's method.
%
% f - vectorized derivative function, y' = f(t, y)
% tspan - row vector [t0 tf] for initial and final time
% y0 - initial value of y
% n - number of y values to find
h = (tspan(2) - tspan(1))/(n-1);
t = linspace(tspan(1), tspan(2), n);
y = zeros(1, n);
y(1) = y0;
for k = 1:n-1
fk = f(t(k), y(k));
yk1 = y(k) + h*fk;
y(k+1) = y(k) + (h/2)*(fk + f(t(k+1), yk1));
end
11.5.3. Runge-Kutta Method¶
The Runge-Kutta method uses Simpson’s rule integration to approximate (11.3). There are actually several algorithms that are considered to be part of the Runge-Kutta family of algorithms. The so called classic algorithm used here is an order–4 algorithm with a comparatively simple expression. Runge-Kutta algorithms are weighted sums of coefficients calculated from evaluations of (the derivative function). Later coefficients make use of previous coefficients, so the coefficients at each evaluation point are first calculated sequentially before the solution value can be determined.
Runge-Kutta algorithms are the most accurate of the fixed step size algorithms. They are only surpassed by adaptive step size algorithms, which typically make use of Runge-Kutta equations.
The rk4ODE
function listed below is called with the same arguments
as the eulerODE
and heunODE
functions.
function [t, y] = rk4ODE(f, tspan, y0, n)
% RK4ODE - ODE solver using the classic Runge-Kutta method.
%
% f - vectorized derivative function, y' = f(t, y)
% tspan - row vector [t0 tf] for initial and final time
% y0 - initial value of y
% n - number of y values to find
h = (tspan(2) - tspan(1))/(n - 1);
t = linspace(tspan(1), tspan(2), n);
y = zeros(1, n);
y(1) = y0;
for k = 1:n-1
s1 = f(t(k), y(k));
s2 = f(t(k)+h/2, y(k)+s1*h/2);
s3 = f(t(k)+h/2, y(k)+s2*h/2);
s4 = f(t(k+1), y(k)+s3*h/2);
y(k+1) = y(k) + (h/6)*(s1 + 2*s2 + 2*s3 + s4);
end
11.5.4. Algorithm Comparison¶
We will use the well known decaying exponential ODE to compare the three methods that use a fixed step size. We will also reference this simple ODE when considering stability constraints on the step size in Stability Constraints.
The ODE
has the solution .
For our comparison, , and .
We can see in Fig. 11.18 that, as expected, the classic Runge-Kutta method preforms the best followed by Heun’s method and then Euler’s method.
>> f = @(t, y) -y;
>> [t, y_euler] = eulerODE(f, [0 4], 1, 8);
>> y_exact = exp(-t);
>> [t, y_heun] = heunODE(f, [0 4], 1, 8);
>> [t, y_rk4] = rk4ODE(f, [0 4], 1, 8);
Note
All of the algorithms shown in Fig. 11.18 have very good performance if is significantly reduced. Finding noticeable differences in the plot is only achieved by using a larger step size.
11.5.5. Stability Constraints¶
Stability and stability constraints are important to us because we do not want our numerical solution to give unstable and wrong answers. A user without knowledge of the stability constraints could specify a step size for the fixed step size algorithm that is too large to get a stable numerical solution. The stability constraint is especially concerning with stiff systems where one term in the solution may place a much higher constraint on the step size than other terms in the solution.
We return to the Euler method and an exponentially decaying ODE to find a stability constraint related to , the distance between consecutive evaluation points of ODE solvers [SHEN15]. With , where , , the exact solution is . A property of that needs to be preserved is that as .
Referring to Euler’s Method, The forward Euler solution is , or .
By induction,
A stability constraint is needed to ensure that the property of as is preserved.
In the following example , but and the results are unstable.
>> fexp = @(t, y) -0.5*y;
>> [t, y_unstable] = eulerODE(fexp, [0 20], 1, 5)
t =
0 5 10 15 20
y_unstable =
1.0000 -1.5000 2.2500 -3.3750 5.0625
The other ODE solvers evaluate the function at points between the set evaluation points, so the stability constraint for Euler’s method is a sufficient constraint for them.
11.5.6. Implicit Backward Euler Method¶
Implicit ODE solvers look at (11.2) from the perspective of finding from the yet unknown . So the terms of (11.2) are reordered and the limits of the integral are reversed. The resulting algorithm removes the stability constraint on the step size.
(11.6)¶
Again, we will use the ODE , where , and . The exact solution is . As before, we want to find any stability constraints that are required to ensure that as . We can solve the decaying exponential ODE problem numerically by applying Euler’s method to (11.6).
(11.7)¶
To satisfy the stability constraint, we require that
which always holds because both and are positive numbers. So the implicit backward Euler method is unconditionally stable.
11.5.7. Adaptive Algorithms¶
Numerical ODE solvers need to use appropriate step sizes between evaluation points to achieve high levels of accuracy while also quickly finding solutions across the evaluation interval. Adaptive ODE solvers reduce the step size, , where needed to meet the accuracy requirements. To improve performance, they also increase the step size when the accuracy requirements can be satisfied with a larger step size.
One of two strategies can be used to determine the step size adjustments. As was done with adaptive numerical methods for computing integrals in Recursive Adaptive Integral, the solution from two half steps could be compared to the solution from a full step. Based on the comparison, the step size can be reduced, left the same, or increased. However, points of an ODE solution are found sequentially, so the strategy of splitting a wide region into successively smaller regions would be computationally slow. Instead, the current step size is used to find the next solution () using two algorithms where one algorithm is regarded as more accurate than the other. The guiding principle is that if the solutions computed by the two algorithms are close to the same, then the step size is small enough or could even be increased. But if the difference between the solutions is larger than a threshold, then the step size should be reduced. If the solutions differ significantly, then the current evaluations are recalculated with a smaller step size. The algorithm advances to the next evaluation point only when the differences between the solutions is less than a specified tolerance.
11.5.7.1. The RKF45 Method¶
The Runge-Kutta-Fehlberg method (denoted as RKF45) uses fourth and fifth order
Runge-Kutta ODE solvers to adjust the step size at each evaluation point. The
fourth order equation is more complex than is used by the fourth order classic
Runge-Kutta algorithm. But the computed coefficients for the fourth order
equation are also used for the fifth order equation, which only requires one
additional coefficient. The coefficient is used in finding later
coefficients, but is not part of either the fourth or fifth order solution
equations. In the rkf45ODE
function, the fourth order solution values
(RK4) are stored in the z
array, and the fifth order solution values
(RKF45) are stored in the y
array, which is returned from the function.
The coefficients and solution values are calculated using the following
equations.
There are variances in the literature on the implementation details of the
RKF45 method. The rkf45ODE
function listed below is adapted from the
description of the algorithm in the numerical methods text by Mathews and
Fink [MATHEWS05].
Some adaptive ODE algorithms make course changes to the step size such as
either cutting it in half or doubling it. The rkf45ODE
function first finds
a scalar value, , from a tolerance value and the difference between
the solutions from the two algorithms. The new step size comes from multiplying
the current step size by the scalar. The scalar will be one if the difference
between the solutions is half of the tolerance. The algorithm advances to the
next step if the difference between the two solutions is less than the
tolerance value, which occurs when the scalar is greater than 0.84. Otherwise,
the current evaluation is recalculated with a smaller step size. The
multiplier is restricted to not be more than two. So the step size will never
increase to more than twice its current size. The tolerance and the threshold
for advancing to the next point are tunable parameters.
The initial value () passed to the rkf45ODE
function can be
either a scalar for a single equation ODE or a column vector for a system of
ODEs. Since the number of steps to be taken is not known in advance, the
initial step size is a function argument instead of the number of
solution values to find.
function [t, y] = rkf45ODE(f, tspan, y0, h0)
% rk5ODE - Adaptive interval ODE solver using the
% Runge-Kutta-Fehlberg method.
%
% f - vectorized derivative function, y' = f(t, y)
% tspan - row vector [t0 tf] for initial and final time
% y0 - initial value of y, scalar or column vector
% h0 - intial step size
tol = 2e-5;
h = h0;
nEst = ceil((tspan(2) - tspan(1))/h);
m = size(y0, 1);
t = zeros(1, 2*nEst); % estimated preallocation
y = zeros(m, 2*nEst);
z = zeros(m, 2*nEst);
t(1) = tspan(1);
y(:,1) = y0; % RKF45 results
z(:,1) = y0; % RK4 results
k = 1;
while t(k) < tspan(2)
s1 = h*f(t(k), y(:,k));
s2 = h*f(t(k) + h/4, y(:,k) + s1/4);
s3 = h*f(t(k) + h*3/8, y(:,k) + s1*3/32 + s2*9/32);
s4 = h*f(t(k) + h*12/13, y(:,k) + s1*1932/2197 ...
- s2*7200/2197 + s3*7296/2197);
s5 = h*f(t(k) + h, y(:,k) + s1*439/216 - s2*8 ...
+ s3*3680/513 - s4*845/4104);
s6 = h*f(t(k) + h/2, y(:,k) - s1*8/27 + s2*2 ...
- s3*3544/2565 + s4*1859/4104 - s5*11/40);
z(:,k+1) = y(:,k) + s1*25/216 + s3*1408/2565 ...
+ s4*2197/4101 - s5/5; % RK4
y(:,k+1) = y(:,k) + s1*16/135 + s3*6656/12825 ...
+ s4*28561/56430 - s5*9/50 + s6*2/55; % RKF5
% no divide by 0, h at most doubles
algDiff = max(tol/32, norm(z(:,k+1) - y(:,k+1)));
s = (tol/(2*algDiff))^0.25;
h = h*s;
if s > 0.84
t(k+1) = t(k) + h;
k = k + 1;
end
end
% delete unused preallocated memory
t(k+1:end) = []; y(:,k+1:end) = [];
Fig. 11.19 shows that the adaptive Runge-Kutta-Fehlberg (RKF45) method is more accurate than the classic Runge-Kutta method (RK4) with the initial step size of RKF45 being the same as the fixed step size used by RK4. For most ODEs, the ability of RKF45 to reduce the step size where needed likely contributes more to its improved accuracy than can be attributed to using a higher order equation.
>> f = @(t,y)-y;
>> [t, y_rkf45] = rkf45ODE(f, [0 4], 1, 0.5);
>> y_exact = exp(-t);
>> hold on
>> plot(t, y_exact)
>> plot(t, y_rkf45, ':')
>> [t, y_rk4] = rk4ODE(f, [0 4], 1, 8);
>> plot(t, y_rk4, '--')
>> hold off, axis tight, xlabel('t')
>> ylabel('y(t)'), legend('exact', 'RKF45', 'RK4')
11.5.7.2. MATLAB’s ode45
¶
Although the adaptive rkf45ODE
function has good results, it is not as
accurate as the MATLAB ode45
function. Using the same comparison test shown in
Fig. 11.19, the ode45
function had a maximum error of
, and a plot of its solution appears to be directly on
top of the exact solution plot. MATLAB’s ode45
is the ODE solver that should
be tried first for most problems. It has good accuracy and performance for
non-stiff ODEs. Like the RKF45 method, it uses an adaptive step size algorithm
based on the fourth and fifth order Runge-Kutta formula.
The ode45
function is called with the same arguments as the ODE solvers
previously described, except neither the initial step size nor the number of
evaluation points is given. The MATLAB ODE solvers also offer additional
flexibility regarding the evaluation points. If the tspan
argument contains
more than two values, then tspan
is taken to be a vector listing the
evaluation points to use.
As before, we often save two return values from ode45
, [t, y] = ode45(f,
tspan, y0)
. The return values in are column vectors rather than
row vectors as was the case with the simple functions previously used. If no
return values are specified, ode45
will make a plot of the values
against the –axis.
The MATLAB ODE solvers have several additional options and tunable parameters.
Rather than passing those individually to the solver, a data structure holding
the options is passed as an optional argument. The data structure is created,
and modified using the odeset
command with name–value pairs. Refer to the
MATLAB documentation for odeset
for a full list of the options and their
descriptions.
>> options = odeset('RelTol', 1e-5); % create
>> options = odeset(options, 'AbsTol',1e-7); % modify
>> [t, y] = ode45(f, tspan, y0, options); % use
11.5.8. The Logistic Equation¶
This example problem is a model of growth slowed down by competition. The competition is within the population for limited resources. The growth gives a term in the ODE—the growth is proportional to the population size. The competition ( against ) adds a term.
The solution is modeled with positive and negative values for . The analytic solution is: ([STRANG14] page 55)
Where, .
In the distant past, (), the population size is modeled as zero. The steady state () population size is , which is the sustainable population size.
The half way point, can be modeled as .
We will compute the positive half of the solution and then reflect the values to get the negative time values.
% File: logistic_diffEq.m
% Logistic Equation: a = 1, b = 1
f = @(t, y) y - y.^2;
tspan = [0 5];
y0 = 1/2;
[t, y] = ode45(f, tspan, y0);
figure, plot(t,y)
t1 = flip(-t);
y1 = flip(1-y);
t2 = [t1;t];
y2 = [y1;y];
analytic = 1./(1 + exp(-t2));
figure, hold on
plot(t2, y2, 'o')
plot(t2, analytic)
hold off, title('Logistic Equation')
xlabel('t'), ylabel('y')
legend('ode45 Numeric Solution','Analytic Solution', ...
'Location', 'northwest');
11.5.9. Stiff ODEs¶
A problem is stiff if the solution contains multiple terms with different step size requirements. A slower moving component may dominate the solution; however, a less significant component of the solution may change much faster. Adaptive step size algorithms must take small steps to maintain accurate results. Because stiff ODEs problems have solutions with multiple terms, they come from either second or higher order ODEs or from systems of ODEs.
We will now look at an example of a moderately stiff system of ODE equations.
Then we will see how implicit solvers solve stiff systems of ODE and are
unconditionally stable. Then we will loot at MATLAB’s stiff ODE solvers, such
as ode15s
.
11.5.9.1. Stiff ODE Systems¶
Here we show a system of ODEs that have a moderately stiff solution. The reader is referred to Systems of Linear ODEs for a review of systems of first order, linear ODEs.
It is more convenient to express systems of ODEs using vectors and matrices.
The eigenvectors, eigenvalues, and coefficients are found with some help from MATLAB.
The solution to the system of ODEs then comes from the general solution for systems of first order, linear ODEs as given in Systems of Linear ODEs.
This system is stiff because the exact solution has terms with largely
different exponent values coming from the eigenvalues of . The
stability constraints on the terms require . From the beginning of the evaluation, those terms will move
towards zero much faster than the terms. We can see from
Fig. 11.21 and Fig. 11.22 that an adaptive algorithm
such as RKF45 or MATLAB’s ode45
will significantly reduce the step size from
the beginning of the evaluations until the term has
sufficiently gone to zero. Using a longer evaluation time, the errors between
the RKF45 solution and the exact solution go to near zero and the step sizes
get much larger.
>> A = [-25 24; 24 -25];
>> fA = @(t, u) A*u;
>> u0 = [1;2];
>> [t, u] = rkf45ODE(fA, [0 1], u0, 0.04);
>> x = @(t) -0.5*exp(-49*t) + 1.5*exp(-t);
>> y = @(t) 0.5*exp(-49*t) + 1.5*exp(-t);
>> figure, hold on
>> plot(t, u(1,:), 'o')
>> plot(t, u(2,:), '+')
>> plot(t, x(t), ':')
>> plot(t, y(t), '--')
>> hold off
>> axis tight
>> legend('u(1,:)', 'u(2,:)', 'x(t)', 'y(t)')
>> xlabel('t')
>> U = [x(t); y(t)];
>> figure;
>> plot(t, vecnorm(U - u))
>> hold on
>> plot(t(1:end-1), diff(t), 'o:')
>> axis tight
>> xlabel('t')
>> legend('error vector', 'h', 'Location', 'southeast')
>> hold off
11.5.9.2. Implicit Solvers for Systems of ODEs¶
The implicit backward Euler method is used here to solve stiff systems of ODEs. The initial discussion parallels that of Implicit Backward Euler Method but the equations are extended to systems of ODEs. As with the implicit solver for a single ODE equation, the implicit backward Euler (IBE) method for systems of ODEs is also unconditionally stable.
We will again use a decaying exponential ODE such as described in Stiff ODE Systems. As was the case in Stiff ODE Systems, the matrix is required be a symmetric matrix with real, negative eigenvalues.
The solution is .
Notice that we do not have a negative sign in front of the matrix as we previously saw with the scalar ODE in Stability Constraints. But it is a decaying exponential that goes to zero when goes to infinity because the eigenvalues of are negative.
We get the starting equation for the numerical solution by applying (11.6).
(11.8)¶
(11.8) is an implicit equation for solving systems of ODEs
numerically, and is implemented in the IBEsysODE
function listed below.
Notice that the implicit approach requires solving an equation at every step.
In this case, the equation is a linear system with a fixed step size, so the
IBEsysODE
function uses LU decomposition once and calls on MATLAB’s triangular
solver with the left-divide operator to quickly find a solution in each loop
iteration. If this were a non-linear problem, then numerical methods such as
Newton’s method or the secant method described in Numerical Roots of a Function would be
needed, which could add significant computation. For this reason, implicit
methods are not recommended for non-stiff or non-linear problems [SHEN15].
function [t, u] = IBEsysODE(A, tspan, u0, n)
% IBESYSODE - ODE solver using the Implicit Euler Backward
% method for systems of ODEs.
%
% A - matrix defining the system coefficients
% tspan - row vector [t0 tf] for initial and final time
% y0 - initial value of y
% n - number of y values to find
h = (tspan(2) - tspan(1))/n;
t = linspace(tspan(1), tspan(2), n);
m = size(A, 1);
u = zeros(m, n);
u(:,1) = u0;
[L, U, P] = lu(eye(m) - h*A);
for k = 1:n-1
u(:,k+1) = U\(L\(P*u(:,k)));
end
Fig. 11.23 shows the numerical solution that the IBEsysODE
function found to our stiff system of ODEs. Since this is a fixed step size
solution, the step size was decreased to 0.005 to accurately track the quickly
changing terms in the solution. Of course, the small step is
not needed once the term was sufficiently close to zero.
Remember that there is a difference between accuracy and stability. A lack of
stability causes the solution to be wrong as . A lack of
accuracy just means that the exact solution is not well modeled by the
numerical solution, which is often solved by reducing the step size.
>> A = [-25 24; 24 -25];
>> u0 = [1;2];
>> [t, u] = IBEsysODE(A, [0, 1], u0, 50);
>> x = @(t) -0.5*exp(-49*t) + 1.5*exp(-t);
>> y = @(t) 0.5*exp(-49*t) + 1.5*exp(-t);
>> figure, hold on
>> plot(t, u(1,:), 'o')
>> plot(t, u(2,:), '+')
>> plot(t, x(t), ':')
>> plot(t, y(t), '--')
>> hold off
>> axis tight
>> legend('u(1,:)', 'u(2,:)', 'x(t)', 'y(t)')
>> xlabel('t')
To evaluate the stability of the implicit backward Euler method, we start by using induction to express the steady state solution in terms of the initial value.
The stability constraint is that as . So we need that
Since our matrix is symmetric, we can use the property of matrix norms that , where means the eigenvalue of . (See Matrix Norms for more information of matrix norms.)
Now we can make use of the eigenvalue property for symmetric matrices that . (See Properties of Eigenvalues and Eigenvectors)
(11.9)¶
(11.9) holds for any symmetric matrix with negative eigenvalues. So the implicit backward Euler method is unconditionally stable for systems of ODEs.
Unconditionally stable ODE solving algorithms remove the concern about having an unstable numerical solution because the step size is too large, but as we saw in Fig. 11.23, accuracy requirements may still require a reduced step size. The more complex and robust algorithms of MATLAB’s ODE solvers for stiff systems are able to adjust the step size enough to find accurate solutions without being excessively slowed by a stiff systems.
11.5.9.3. MATLAB’s ode15s
¶
MATLAB has several stiff ODE solvers. The ode15s
should be tried first for
stiff ODEs. The primary authors of MATLAB’s suite of ODE solvers, Shampine and
Reichelt, describe ode15s
as an implicit quasi-constant step size
algorithm. They further give the following suggestion regarding picking which
of their ODE solver to use [SHAMPINE97].
Except in special circumstances,ode45
should be the code tried first. If there is reason to believe the problem to be stiff, or if the problem turns out to be unexpectedly difficult forode45
, theode15s
code should be tried.
Fig. 11.24 shows how ode15s
handles the stiff system of ODEs
used in the previous example.
>> A = [-25 24; 24 -25];
>> fA = @(t, u) A*u;
>> u0 = [1;2];
>> [t, y_ode15s] = ode15s(fA, [0 1], u0);
>> t = t'; u = y_ode15s';
>> x = @(t) -0.5*exp(-49*t) + 1.5*exp(-t);
>> y = @(t) 0.5*exp(-49*t) + 1.5*exp(-t);
>> figure, hold on
>> plot(t, u(1,:)', 'o')
>> plot(t, u(2,:)', '+')
>> plot(t, x(t), ':')
>> plot(t, y(t), '--')
>> hold off
>> legend('u(1,:)', 'u(2,:)', 'x(t)', 'y(t)')
>> xlabel('t'), ylabel('y')
11.5.10. MATLAB’s Suite of ODE Solvers¶
MATLAB’s ode45
and ode15s
are the nonstiff and stiff ODE solvers to use
for most problems. If those do not give satisfactory results then ode23
and
ode113
might be tried for nonstiff problems. For stiff problems, ode23s
should be the next function tried after ode15s
. Additional documentation
and research may be needed to select the best solver to use for some problems.
The MathWorks’ web pages have quite a bit of documentation on the suit of ODE
solvers. The MATLAB Guide by Higham and Higham [HIGHAM17] has extended
coverage MATLAB’s suite of ODE solvers. Table 11.1 lists MATLAB’s
suite of ODE solvers.
Solver | Problem type | Description |
---|---|---|
ode45 |
Nonstiff | Explicit Runge-Kutta, orders 4 and 5 |
ode23 |
Nonstiff | Explicit Runge-Kutta, orders 2 and 3 |
ode113 |
Nonstiff | Explicit linear multistep, orders 1–13 |
ode15s |
Stiff | Implicit linear multistep, orders 1–5 |
ode15i |
Fully implicit | Implicit linear multistep, orders 1–5 |
ode23s |
Stiff | Modified Rosenbrock pair, orders 2 and 3 |
ode23t |
Mildly stiff | Implicit trapezoid rule, orders 2 and 3 |
ode23tb |
Stiff | Implicit Runge-Kutta, orders 2 and 3 |
Online Resources
This MathWorks web page has some good tutorial videos about numerical solutions to differential equations. Please watch at least the first three videos (Euler – ODE1, Midpoint Method – ODE2, and Classical Runge-Kutta – ODE4). Although, the ODE solvers in MATLAB are slightly more complex than the examples in the first three videos, they explain the basic concepts.
MATLAB has several ODE solvers, they are reviewed on this web page.