19.5.1: ODE45 Examples and Exercises
- Page ID
- 86605
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)ode45() requires a differential equation function to be defined. This function can be implemented in 3 ways in MATLAB, 2 ways in Octave.
- The ODE function can be a separate file. This is straight-forward. It works in both MATLAB and Octave. It is illustrated in the 2nd example.
- The ODE function can be placed at the bottom of the test script file. This is called a subfunction. It works in MATLAB, but not in the current version of Octave. (However Octave allows a subfunction within a function file, but not in a script file.) It is illustrated in the 1st example.
- An "anonymous function" (an in-line function). It can be used when the function is a single line of code. This is somewhat tricky for beginners and is not illustrated here.
The 1st example can be easily solved analytically.
The 2nd example can be solved analytically with difficulty.
Other ODE's cannot be solved analytically. They can only be solved numerically. One case would be if, in the 2nd example, the constant c were replaced by c*sin(t).
This example uses a sub-function within the test file.
The equation equation for this parabola is y(t) = 2*t^2 - 0.5
% dydt_4t_ODE_example.m
% This example uses a sub-function within the test file.
% The equation equation for this parabola is y(t) = 2*t^2 -4
% The syntax of ode45 is:
% [T_OUT, Y_OUT] = ode45(@ODEFUN, TSPAN, Y0)
% @ODEFUN is the handle to the ode function.
TSPAN = [-1.0, 1.0]; % s
% TSPAN is a 2-element vector = [T0, TFINAL]
% specifying the time interval
Y0 = 1.5; % the initial value of y(t)
[tout, yout] = ode45(@dy4_ODE, TSPAN, Y0);
% Note: Instead of the user specifying a time vector,
% ode45 computes a time vector with appropriate time increments.
% Plot the function computed by ode45
figure;
plot(tout, yout, '-o')
title('ode45() for dy/dt = 4t')
grid on;
function dydt = dy4_ODE(t,y)
dydt = 4*t;
end
The plot is shown in the solution.
Solution
A plot of the solution.
.
Damped spring example
This example uses a separate function file.
The 2nd-order differential equation for an under-damped spring oscillator is:
\(m \frac{d^2 x}{dt^2} + c \frac{dx}{dt} + kx = 0\)
The constants for this example are:
m = 2;
c = 0.4;
k = 4;
The differential equation and the constants are in the function file ODE_Damped_Spring.m
For a 2nd order differential equation, ODE45 requires that the function file has a column vector of 2 inputs and a column vector of 2 outputs.
The input vector, x, has the position and it's 1st derivative:
x(1) = x = the position
x(2) = dx/dt = the 1st derivative of x(1)
The output vector is the derivative of the input vector:
xdot(1) = dx/dt
xdot(2) = d^2x/dt^2 = the derivative of dx/dt
\(\frac{d^2 x}{dt^2} = -\frac{1}{m} (c \frac{dx}{dt} + kx) \)
The code for the function is given here and is also attached as ODE_Damped_Spring.m
function xdot = ODE_Damped_Spring(t, x)
% This models the oscillation of a damped spring
% Inputs:
% t = time is not used, since this is a time-independent model
% x = a column vector with 2 elements:
% x(1) = x = the position
% x(2) = dx/dt = the 1st derivative of x
% Output
% xdot = a column vector with 2 elements:
% xdot(1) = 1st derivative of x = x(2)
% xdot(2) = 2nd derivative of x from this equation:
% m(d^2x/dt^2) + c(dx/dt) + kx = 0
% Constants of the equations
m = 2;
c = 0.4;
k = 4;
xdot = zeros(2,1); % Initialize the output
xdot(1) = x(2); % 1st derivative
xdot(2) = -(1/m)*(c*x(2) + k*x(1)); % 2nd derivative
The test program sets the "initial conditions" (the starting position and derivative), calls ODE45 with a handle to the diferential equation function, and plots the result. This is given here and is also attached as ODE_Damped_Spring_test.m.
%% ODE_Damped_Spring_test
% m(d^2x/dt^2) + c(dx/dt) + kx = 0
% m = 2;
% c = 0.4;
% k = 4;
% To compute the solution to this equation,
% we need a function: ODE_Damped_Spring.m
% The x input needs to be a column vector.
x0 = [10; % Initial values of x
0]; % Initial values the 1st derivative x
Time_Span = [0, 40.0]; % (s)
[t_ex2, x_ex2] = ode45(@ODE_Damped_Spring, Time_Span, x0);
figure;
plot(t_ex2, x_ex2(:,1), 'o-')
title('ode45 Position for Damped Spring')
grid on;
The resulting plot is shown in the solution.
Solution
The resulting plot is shown here.
.
Background:
The Logistic ODE equation is:
dP/dt = r*P*(1 - P/K)
where:
P = population
r = growth rate when the population is small
K = carrying capacity (max. value of P)
This a modification of the version of the exponential population growth ODE which assumes that the population is changing at a constant rate.
When the population population is small, P/K is small, then dP/dt is approximately = r*P. This means that the growth rate is proportional to the population and P grows exponentially.
When the population population becomes close to K, then P/K is near 1, so dP/dt is approximately = 0 and P is approximately constant.
Assignment:
Create an m-file script that computes the solution to the logistic differential equation.
Start with this line:
clear all; close all; clc; format compact
(1 pt) Set these parameters:
tspan = [1,100] % [timeBegin, timeEnd] = the time span for the computation.
P0 = 10 % Initial population
(5 pts) Write the 1 line of code that calls the ode45() solver function with its 3 inputs:
@dPdt (the function handle), tspan, and P0
The outputs are [t, P]
(2 pts) Open a figure and plot P vs. t with this code:
figure;
plot(t, P);
title('Logistic Equation')
xlabel('time')
ylabel('Population')
grid on;
(2 pts) Put the following code that computes the derivative of P as a local function at the bottom of your m-file:
%% Local function
% Ordinary Differential Equation
function dPdt = logistic_ode(t, P)
r = 0.065; % growth rate
K = 38; % max value of P
dPdt = r*P*(1 - P/K);
end
If you want to learn more about the Logistic ODE, visit these links:
https://mathworld.wolfram.com/LogisticEquation.html (Links to an external site.)
https://www.matlab-monkey.com/ODE/logisticV1/logisticV1Pub.html (Links to an external site.)
- Answer
-
The solution is not given here. Your plot should show the population increasing until it gets near to the maximum value, K, then the curve becomes nearly horizontal.
.