You are on page 1of 9

# Differential Equations in Matlab

Cheng Ly1
1

## University of Pittsburgh, Department of Mathematics, Pittsburgh, Pennsylvania

15260, USA.
E-mail: chengly@math.pitt.edu

This workshop assumes you have some familiarity with ordinary (ODEs) and partial
differential equations (PDEs), and also that you are relatively comfortable with basic
programming in Matlab.
Matlab is a very powerful high-level computing tool with a lot of nice built in packages. It is relatively easy to learn, but lags in computation time compared to complied
languages such as Fortran, C, or C++. In particular, when solving PDEs with 3 or more
spatial dimensions (i.e., 4 or more when including time) Matlab is not something you
should use. However, for 2 or less spatial dimensions, Matlab is fast enough these days
to be successfully utilized.
Numerical simulations are undoubtedly an important tool in investigating the complex behavior of many systems (presumably that is why you are here unless you only
came for the free pizza in which case you should...). Mathematical analysis and ingenuity
are obviously important as well, but the value of numerical tools cannot be underscored.

## 1. Getting Started: A Quick Review

Matlab is optimized to work with vectors and matrices. You can specify variables to be
row or column vectors. For example, the command
>> x=[1 2 3];
creates a 3x1 row vector with the entries 1, 2, and 3. The semicolon ; at the end
hides the output (try it without a semicolon).
You can also create a column vector with the command
>> x=[3; 2; 1];
The semicolons between [ and ] terminates that the row. You can access parts of
the vector x. To see how this works, type
>> x(1:2)
and
1

>> x(2:end)
and
>> x(1:end-1)
You can also reverse the order of the entries with a command like
>> x(end:-1:2)
Important functions. The function zeros(n,m) and ones(n,m) creates matrices
of size n x m with all 0s and 1 entries (respectively). Also, eye(N) creates the identity
matrix of size N x N.
You can concatenate vectors and columns easily in between brackets. Type in the
following commands:
>> A=[1 0 -1; 2*ones(3,1); 8 zeros(2,1)]
>> B=[eye(3); A]
You can also multiply and divide component-wise when you have a matrix/vector
with the . operator. Type:
>> x./3
to divide every entry in x by 3.
The function diag(x) creates a square matrix with x on the main diagonal and 0s
on the off diagonal. The matrix of size N x N where N is length of the vector x. The
command length(x) will return this length:
>> length(x)
Type:
>> C=diag(x)
The function diag can also be used to create matrices with entries above or below
the main diagonal. If you want to create an N x N matrix with a vector z that is of size
N-1 x 1, that is one above the main diagonal, you can type:
>> z=[8; 4];
>> diag(z,1)
to create a 3 x 3 matrix. Or if you want z to be 1 below the main diagonal type:
>> diag(z,-1)
For example, can you guess what you would get when you type in
>> D=diag(x) + diag(x(1:2),1) - diag(x(2:3),-1)
Now what we have a better understanding of how vectors/matrices work, we can
proceed. Type
>> clear
2

## to delete all of the variables in our workspace.

In Matlab, you work mostly with function files or script files (name.m). The difference
is that in a function file, the first lines looks like:
function [y,z]=name(x1,x2)
where the outputs are y and z, the inputs are x1,x2. You can run this function in
the command window by typing:
>> y=name(x1,x2);
or
>> [y,z]=name(x1,x2);
A script file is just a series of commands that you would type into the command line.
There is a difference in scope. The function file has a local scope (you can create new
variables in there that will be deleted when you exit) versus in a script file, you have
do in the script file will be changed in your workspace as well.

2. ODEs
Matlab can solve large dimensional ODE systems with built-in solvers. You may want
to consider using XPP if you are going to alter many parameters and do other dynamical
system things (i.e., bifurcation diagrams, phaseplane analysis, etc.). Note that higher
level programming is easier to implement in Matlab. Examples are complicated logical
(if-else) statements in your system, weird boundary conditions, as well as look up
tables [Sorry Bard]. You can use look-up tables in XPP as well, but Im not sure how
well it is documented.
There are various methods (see Matlabs documenation), but I will consider my
favorite stiff solver: ode15s.
For this workshop, we will assume the ODEs are first-order. For higher orders, we
simply have to introduce auxiliary variables and enlarge the size of the system.
Consider y R2 , and an ODE system of the form
y1 = y1 (a1 + a2 y2 )

(1)

y2 = y1 y2

(2)

## with some initial conditions.

Open up the file rhs.m ; notice the syntax for this file. It basically specifies the
right-hand side of the ODE system above. The parameters come after t (independent
variable) and y (the functions y1 =y(1) and y2 =y(2).
Fill in the appropriate commands for y1 =dy(1) and y2 =dy(2)..... ask for help if
there is something unclear.
Now open the file slv ode.m. Notice the initial conditions are random. Also the
parameters for the time-length (t end) and a1 and a2 are already filled in (you can play
with these later). Ignore the command options=..; you can explore this later by typing
help ode15s in the command lind. You will write the syntax to solve the ODE
[T,Y] = ode15s(@rhs,[0 t end],y0,options,a 1,a 2);
Type the following in the command line:
>> slv ode
do this several times and see what happens.
Before moving on to the next section, type:
>> clear

3. PDEs
We will discuss how to numerically solve partial differential equations of the form (x R1
and t [0, )):

o
o
u(x, t)
2 n
n
A(x, t)u(x, t) 2 D(x)u(x, t) = 0.
+
t
x
x

(3)

These are called advection-diffusion equations and arise all of the time in the physical
and life sciences. This encompasses equations called Fokker-Planck, Black-Scholes,
and a biological phenomena known as chemotaxis with some augmentations.
For this workshop, we will consider the following advection-diffusion equation:
o
o
2 n
u(x, t) 1 n
((t) x)u(x, t) D 2 u(x, t) = 0
+
t
x
x

(4)

## With zero boundary conditions: limx

u(x, t) = 0. o
This can be understood intuitively
n

## as follows. The advection term 1 x

((t) x)u(x, t) causes the mass at x 6= (t) to

move (or advect) toward (t) with a velocity of 1 . Thus, if is smaller, the mass moves

faster towards (t). Of course, the value (t) is changingnin timeo which adds to the
2
complications of these dynamics. The diffusion term D x
2
4

out the mass equally in all directions (2 directions here since x R1 ) with a coefficient of

D that is constant here. Think of heat or gas diffusing on a line. Many different systems
have a D that depends on x: D(x) (equation 3), which also complicates things.

3.1. Implementation
Let us first rewrite the PDE
o
u(x, t)
2 u(x, t) (t) u(x, t)
1 n
xu(x, t) + D
=

t
x
x2

(5)

## On a computer, we cant go out to t = , so we pick a large enough Tend = 50 say.

Discretize time with a mesh size t << 1 (say t = 0.01), and label tk = 0 + t(k 1)
(for k = 1, 2, .., 5001). In general, k = 1, 2, ..., Tend/t + 1. We approximate the time-

## derivative with the finite difference method:

u
u(x, tk ) u(x, tk1 )
=
t
t
Let us focus on the x derivatives in u and forget the time derivative

u
t

for the

## moment. Again on a computer, we cant go out to x = , so we will choose some

M large enough and consider x [M, M]. Let x = 2M/(N 1) << 1, by choosing

## M = 25 and N = 200. Label xj = M + x(j 1) for j = 1, 2, ..., N. In both x and

t variables, we are assuming equally spaced points (i.e., uniform mesh) 1 , but t 6= x

necessarily (in fact, this is usually the case). Write equation (4) as follows:

o
2 u(x, t) (t) u(x, t)
n
u(x, tk ) u(x, tk1)
xu(x, t) + D
=

t
x
x2

(6)

Let ~u = [u1 ; u2 ; ..; uN ], where uj = u(xj , t). We will now create the matrices to
discretize the right-hand-side of equation (5).
Advection to 0 operator (M0) We want a matrix M0 that represents the
operator:

o
n
xu(x, t) = M0~u
x
We will use a simple forward finite difference method:
o x u x u
n
j+1 j+1
j j
xj u(xj , t) =
x
x
1

Many complicated numerical solvers do not assume a uniform mesh, although you can get quite far
with this assumption. Some people have debated this issue and the answer is that it all depends on
your problem (i.e., domain, stiffness, etc.).

xj+1
; 0; ..0]
x

o
2 n
u(x
,
t)
= Md~u
j
x2

## We will use a standard 2nd derivative finite difference approximation:

o u 2u + u
2 n
j+1
j
j1
u(x
,
t)
=
j
x2
x2
2
1
So the j th row of Md looks like [0...; x1 2 ; x
2 ; x2 ; ..0]

## Advection to (t) operator (Am) Similarly, we want to form the matrix Am

so that

o
n
u(x, t) = Am~u
x
We will use a simple forward finite difference method:
o u
n
j+1 + uj

u(xj , t) =
x
x

1
1
So the j th row of Am looks like [0...; x
; x
; 0; ..0]

I have avoided talking about boundary conditions so far because they can be quite

complicated. Neglecting boundary conditions, you can now think about how you would
create the matrices. Some people would use a for-loop but they are NOT a good idea
in Matlab because they take enormous computation times (for example if you make N
large). You should look at the diagonal structure of these operators (recall the function
diag).
Now, open the file make matrix.m. Look at the syntax and the commands. If you
have any questions, now is the time to discuss this.
In this file (make matrix.m), insert the following commands in
M0=diag([0;-x(2:end-1);0]./dx)+diag([x(2:end-1);0]./dx,1);
and
Md=diag([-1;-2*ones(N-2,1);-1]./(dx^ 2))+...
diag(ones(N-1,1)./(dx^ 2),1)+diag(ones(N-1,1)./(dx^ 2),-1);
and
Am=diag([0;ones(N-2,1);0]./dx)-diag([ones(N-2,1);0]./dx,1);
After this, type in
M0=sparse(M0);
Md=sparse(Md);
6

Am=sparse(Am);
to make the matrices sparse. This will speed up the matrix-vector solver that we will
write below.
3.1.1. Solve the PDE with Trapezoidal Rule
Now that we have all our operators created in the file make matrix.m, we are ready
to (crudely) solve this system. The trapezoidal rule is a decent implicit solver (recall
equation (5)):


u(x, tk ) = u(x, tk1) + t 0.5 RHS(u(x, tk1)) + 0.5 RHS(u(x, tk ))
u(x, tk ) 0.5 t RHS(u(x, tk )) = u(x, tk1 ) + 0.5 t RHS(u(x, tk1))

## Here, RHS is the right-hand-side operators



RHS(u(x, tk )) = 1/ M0 + D Md (tk )/ Am u(:, k)
Scroll down to the for loop that begins with for j=2:length(t). Think about how
you would solve the matrix-vector equation given the inputs in this file....
HINT: It amounts to solving A*u(:,j)=b for each j=2,3,..,length(t). And we
can write
A=eye(N)-.5*dt*(1/tau*M0+D*Md+mu t(j)/tau*Am);
and similarly for b.
.....
.....
Now that we have all our files written, we can solve the PDE. In the command line,
type
>> help make matrix You should be able to see the form of the function and description. Now type
>> [M0,Md,Am,x]=make matrix(25,200);
Now we have our matrices in the workspace. Specify tau, D, and the end of time
T end with the commands
>> tau=2;
>> D=5;
>> T end=30;
SOLVE THE PDE with the command:
7

We will look at movies of our solutions in a bit.....

## 3.2. Monte Carlo Simulations

Dont be alarmed if you do not know any stochastic differential equations or statistical
physics. But..
The advection-diffusion equation (4) describes how the probability density u(x, t) of
a random variable X(t) evolves. The equation is:
X = (t) X +

2D(t)

where (t) is a white noise process (i.e. a Gaussian random variables for all t with 0
mean and variance of 1; where each Gaussian random variable is uncorrelated in time).
Since we took u(x, 0) = [0,1] , we can think of the initial condition X(0) as a random
variable itself with uniform distribution.
In the command line, type:
>> avgX = monteCarlo sims(t,x,tau,D,mu t);
After it is finished running, type:
>> movie scpt
to see a movie of how well the solution u(x, t) approximates the noisy system.
The match is pretty good despite the crudeness of the methods (first order).
Other issues to be aware of: i) mesh size isnt large enough (in x or t, ii) conserving
probability with weird boundary conditions, etc.
You can go back and play with the function mu t in the file solve advDif if you are
comfortable with the syntax, but you MUST enlarge your domain and mesh size x
appropriately!

4. Nonlinear PDEs
Nonlinear PDEs are a mess to solve. Here is all I have to say about it. The instabilities
that arise generally call for an implicit method (at the very least) to have any hope of
a reasonable numerical solution. The following sections assume you want an implicit
time-stepping solver.

## 4.1. Method of Lines

If your PDE is nonlinear in u(x, t), then you have to use a fancier method than what
has been outlined. One method is to write the PDE as a large system of ODEs and
use the Method of Lines (Google it). This basically involves discretizing your domain
x [M, M] into N pieces of width x = 2M/N, and letting u(xj , t) = u(M +
R M +xj
1
x(j 1), t) represent x
u(x, t) dx. Note here that xj = M + x(j 1)
M +x(j1)
for j = 1, 2, .., N. We still have

u
t

u(x,tk )u(x,tk1 )
.
t

The system of ODEs can be written down if you discretize the advection and diffusion
parts with a finite difference method. For example, you could use a centered-difference
method:
o A(x , t)u(x , t) A(x , t)u(x , t)
n
j+1
j+1
j1
j1
A(xj , t)u(xj , t) =
x
2x
o D(x )u(x , t) 2D(x , t)u(x ) + D(x )u(x , t)
2 n
j+1
j+1
j
j
j1
j1
D(x
)u(x
,
t)
=
j
j
x2
x2
Care must be taken with the boundary conditions. Again, you might want to use XPP if
your boundary conditions are not nasty.
There are many good nonlinear ODE solvers once you have properly discretized the
system (e.g., CVODE, ode15s, etc.).

## 4.2. Newtons Method

Alternatively, you could use Newtons Method to resolve the nonlinearity at each time
step. This involves finding u(x, tk ) given that you know u(x, tk ). There are many deep
and troubling issues such as uniqueness of roots, stability, etc. This is not unexpected
with nonlinear PDEs.