The FTCS scheme is possibly the easiest scheme to understand, hence we
discuss it first. We will discuss this scheme twice in basically the
same way, firstly in a very explicit form, where it is obvious in the
computational loop how the differential equation is being processed,
and secondly in a matrix form which we will find is more powerful and
enables us to easily understand the changes and extensions to the FTCS
scheme introduced later.
FTCS stands for Forward Time Centred Space.
What does this mean? Well, it means that we calculate the time
derivative in a ``forward'' manner (using effectively
Equation (3.2)) and calculate the spatial derivative in
a ``centred'' manner (using effectively
Equation (3.4) and/or
Equation (3.5)). It is best to understand this
scheme in the context of an example. Let us take for this example,
the diffusion equation:
 |
(3.6) |
In this equation, the scalar field3.4
is a function
of both space and time. The variable
is just a constant
describing the rate of diffusion of the field
. Note that we have
a first derivative in time and a second derivative in
space, one may think that it would be simpler to discuss as a first
example an equation with just a first derivative in both time
and space, but it turns out that such an equation (the form of which
is known as the advection equation) is actually harder to calculate
numerically than the diffusion equation. By the end of these notes
you may either know the diffusion equation really well, or be
completely sick of it, as we will use it in most of the sections and
examples that follow.
Okay, to use the FTCS scheme on the diffusion equation, we need to
calculate the first derivative in time using the forward first
derivative equation (Equation (3.2)) and the second
derivative in space using the centred second derivative equation
(Equation (3.5)). Substituting these into
Equation (3.6) we get:
 |
(3.7) |
which is the discretised form of the diffusion equation.
Let's simplify things slightly by introducing the notation that
spatial indices are represented by a subscript, and time indices are
represented by a superscript, such that the value of the function
at the point
and at time
is represented as
, or in
another form
 |
(3.8) |
The discretised first derivative in time in this notation becomes
 |
(3.9) |
the discretised second derivative in space becomes
 |
(3.10) |
and the diffusion equation is now rewritten as:
 |
(3.11) |
Since we know the value of the function at the current point in time
(
which is
), what we are really interested
in is the value of the function at the next point in time (
,
which is
). We therefore solve
Equation (3.11) for
to obtain
 |
(3.12) |
which is the equation that we are now going to convert into Matlab
code.
I have already written Matlab code to solve this differential
equation (it is adapted from Professor Drummond's code, which was
originally adapted from the code in Garcia), and I now give the
code listing and will give a discussion of the various parts of the
program line-by-line.
The code listing for diffuse1.m is3.5:
1 % diffuse1.m - Program to solve the diffusion equation
2 % using the FTCS method.
3
4 clear; % clear memory
5 help diffuse1.m % print help information
6
7 %%%%%%%% INITIALISATION %%%%%%%%%%
8
9 % set up input variables
10 tmax = 1; % window size in t
11 nt = 100; % number of grid points in t
12 delta_t = tmax/nt; % step-size in t
13 nplots = 21; % number of plot points in t
14 nplotstep = nt/nplots; % plot step-size in t
15
16 xmax = 2; % window size in x
17 nx = 11; % number of grid points in x
18 delta_x = xmax/(nx + 1); % step-size in x
19
20 kappa = 1; % coupling constant
21 c = kappa*delta_t/delta_x^2; % constant of propagation
22
23 % initial conditions and boundary conditions
24 A = zeros(nx,1); % allocates and zeros a column vector
25 A(floor((nx+1)/2)) = 1/delta_x; % sets up an initial delta 'spike' in A
26 iplot = 1; % initialise the plotting index
27
28 % set up plotting matrices
29 xplot = (1:nx)*delta_x - xmax/2; % row vector of x-coordinates
30 tplot(iplot) = 0; % assign first time-coordinate
31 Aplot(:,iplot) = A(:); % assign first value of A
32
33 %%%%%%%% MAIN LOOP %%%%%%%%%%
34
35 % main loop
36 for i = 1:nt
37
38 % evolve our solution using the FTCS method
39 A(2:(end-1)) = A(2:(end-1)) + c*( A(1:(end-2)) + A(3:end) - 2*A(2:(end-1)) );
40
41 % save current data for plotting
42 if (rem(i,nplotstep) < 1)
43
44 iplot = iplot + 1; % increment plotting index
45 Aplot(:,iplot) = A(:); % record current value of A for plotting
46 tplot(iplot) = i*delta_t; % record current time value
47
48 % print some progress information
49 fprintf('%g out of %g steps completed\n',i,nt);
50
51 end
52
53 end
54
55 %%%%%%%% PLOTTING/OUTPUT %%%%%%%%%%
56
57 % plot stuff
58 figure(1) % opens a new figure window
59 subplot(121) % divides window into a 1x2 matrix
60 % and assigns next plot to the
61 % left-hand frame (frame 1)
62 mesh(tplot,xplot,Aplot) % wire mesh plot of the solution
63 view([-70 30]) % change the viewing direction
64 xlabel('t') % label the x-axis
65 ylabel('x') % label the y-axis
66 title('Diffusion of a delta spike')% give the thing a title
67
68 subplot(122) % assigns next plot to right-hand
69 % frame (frame 2)
70
71 % find contours of 3D plot and assign to the vector cs
72 cs = contour(xplot,tplot,flipud(rot90(Aplot)),0:0.1:2.5);
73 xlabel('x') % label the x-axis
74 ylabel('t') % label the y-axis
75 clabel(cs,0:5) % label the contours
76 title('Contour of a delta spike') % give the thing a title
77
78 subplot(111) % return plotting mode to one
79 % figure per window
Notice that the code is separated into basically three parts: an
initialisation section, a main computational loop, and a plotting
section. This is a very simple structure that is quite useful in the
programs you will be writing in this section of the course.
Going through the code line-by-line we have
- lines 1-2:
- give the name of the program and what it does.
- line 4:
- clear the memory (a good idea to do at the start of each
program).
- line 5:
- prints help information. What this does is print any
lines of code that appear at the top of the file in comments before
any commands are entered. So what it does in this case is merely echo
the top two lines of the file out to the terminal window.
- lines 9-21:
- intialise input variables. This code is
hopefully fairly self explanatory. A couple of points to note though:
we are not using a variable called
for the step size in
, but
; and we have wrapped up all of the constant terms
into a variable called c. This variable
can give us an indication of whether the solution will be stable or
not (more on this point later).
- line 24:
- this line merely allocates some memory for the
vector A. We allocate its memory by calling the zeros
function with the size of each dimension of the array as its
arguments.
- line 25:
- we now set up an initial delta spike in A
(basically a discrete version of a Dirac delta function). The
delta spike is dependent upon the step size in
only. We put the
delta spike at the mid-point of the array by using the value offloor((nx+1)/2). What does the floor function do? Well,
it looks at the number in its argument (in this case, the value of(nx+1)/2) and if the number isn't an integer, it rounds it
down to the nearest integer. Why do we want to do this? Well,
Matlab wants integer indices to its arrays, and it's possible that(nx+1)/2 could be a non-integer fraction. Just for your
information, there is also a function called ceil that takes the
ceiling of the number, i.e. it always rounds a number up
to the nearest integer.
- line 29:
- this sets up the vector of
-coordinate positions.
Note that we are using the Matlab colon operator (:) to
generate the vector. The notation 1:nx means to create a vector
from 1 to nx in integer steps. In the case shown here, we
are setting up our
-coordinates to be from -xmax/2 toxmax/2.
- line 31:
- here we store the initial value of A into our
plotting storage vector Aplot.
- line 39:
- now we are in the main loop. This is the line that
does all of the hard work and implements the evolution of the vectorA according to the diffusion equation. Compare the code we are
using here with Equation (3.12). You may have
noticed that we are not assigning to the outside points of A.
Why is this? We don't assign to these points to maintain the boundary
conditions. In this example we are implicitly using the
Dirichlet boundary conditions that the function value is zero
at the boundary. To put this into a physical context, say we are
investigating the heating of a metal bar. The diffusion equation
describes the way in which the temperature changes with time and
position along the bar. The ends of the bar we keep at zero
temperature, hence the boundary conditions of our PDE. What is
cool3.6 about this line
of code is that all of the points in space are being acted upon
simultaneously, because we are using Matlab's array slicing
notation (i.e. in the bit where we say A(2:end-1), we are
slicing out only the values of A from the second element
to the second to last element, and then using only these elements in
the calculation). The first term in the equation on line 39
corresponds directly to the first term in
Equation (3.12). As mentioned before, the
variable c rolls all of the various constants together. The
next term corresponds to the
part of
Equation (3.12). So, the code A(1:(end-2))
means to say ``all of the left-hand
points''
i.e.
. The code A(3:end) means ``all of
the right-hand
points'' i.e.
. And
the code 2*A(2:end-1) means ``all of the centre
points'' i.e.
. A pictorial explanation may be
helpful at this point.
Figure:
The use of element by element addition in calculation of the
centred second derivative in space in the FTCS scheme. The vector
is split into three parts:
representing
the left-hand elements of
;
representing the centre elements of
, each multiplied by 2;
and
representing the right-hand elements of
. Each element is added to its corresponding partner shown
by the arrows in the figure, to then give the elements of the new
value of
which is denoted here
.
![\begin{figure}\centerline{%%
\includegraphics[width=100mm]{matrixAddDiag}%%
}\end{figure}](Timg117.png) |
Figure 3.2 shows the process of element by element
addition of parts the vector
in order to calculate the
centred second derivative in space in the FTCS scheme. The vector
is split into three parts:
representing
the left-hand elements of
;
representing the centre elements of
, each multiplied by 2;
and
representing the right-hand elements of
. All elements of these vectors are added to corresponding
elements in the other vectors as shown by the arrows in the figure.
These element by element processes then produce the elements of
which is the new value of the vector
at
the next time step. Notice that the end elements of
and
are set to zero. This is the implementation of
the Dirichlet boundary conditions, and is why the intermediate vectors
have a length with is two elements shorter than
.
- line 42:
- we now do a check to see if we should take a point
for plotting3.7. We defined the variablenplotstep in the initialisation section so that we can get 21
samples of the function evolution through time. The function we use
here is the rem() function, and it calculates the remainder ofi/nplotstep. What we are doing here is using the if
statement to check to see if this remainder is less than one, if so,
to then take a plot point.
- lines 44-46:
- here we just take the value of A and
assign it to part of the array Aplot and add to the time
recording vector (tplot) with the current time.
- line 49:
- this just prints out the number of steps out of the
total number of steps we have completed. It's sometimes helpful to
have progress information like this to make sure your program is doing
something when it is running.
- line 58:
- this opens a new figure window, and will call itFigure 1 (hence the ``1'').
- line 59:
- this splits the window into two parts, so that we can
plot something first on the left half of the figure, and then on the
right half. The notation defines a matrix, namely: subplot(121)
means make a subplot of the current figure window in a
matrix (the first 1 and 2), and put the next plot into the first
element of that matrix (hence the last 1, and the first element of a
matrix is the left-hand one, and so the plot goes into
the left hand half of the figure window).
- line 62:
- make a mesh plot of the array Aplot
using the vectors tplot and xplot along the
and
axes respectively.
- line 63:
- change the angle that we look at the graph from.
- lines 64-66:
- put
and
labels on the graph, and give it
a title.
- line 68:
- same idea as line 59, just this time we are plotting
into the second element (hence the 2 at the end of the subplot
command).
- line 72:
- generate a variable used for plotting contours of the
array Aplot. Don't worry about this too much, if you're
interested type help contour for Matlab's information on thecontour function.
- line 78:
- subplot(111) resets any subsequent plotting
output to take up the whole window: a
matrix, first
element.
The stability of this scheme for the diffusion equation can be shown
to be dependent upon the value of the variable c. It is
possible to show (and for the analysis on this point see Garcia) that
for
the solution will be unstable. In fact, it
is possible to show for the advection equation that the FTCS scheme is
unstable for all values of the time step!3.8 One can think
of the evolution of the function according to the discretised
diffusion equation as being due to perturbations on the currently
known step in time. If you look at
Equation (3.12), you can see that the
new point in time is basically the old point in time plus some
perturbation. It isn't desirable in perturbation theory to have large
perturbations, so if c is too big, then the perturbation is
large and the solution is likely to diverge as we iterate it further.
So, when you are running the sample code and you find for certain
parameters that the solution ``blows up'', check the value of c
and see what it is; it is quite possible that it is greater than 0.5.
To fix this one needs to either increase the
step width,
and/or decrease the time step or coupling constant. Why is
this do you reckon? Have a think on it, and look at the diffusion
equation again.
Hopefully now you have a reasonable grasp of the FTCS scheme. I'll
now introduce a matrix notation that will help us understand
subsequent schemes.
Footnotes
- ... field3.4
- In general, one would work
with vector fields, such that
would actually be a vector of
various (say, spatial) dimensions, it is easier to learn this stuff if
we are content just to consider scalar fields.
- ... is3.5
- It is also given as
the sample code at the back, but here I want to discuss it
line-by-line, hence I include it here with line numbers.
- ...
cool3.6
- Believe it or not, pun not intended.
- ... plotting3.7
- Have a think about why we may not want to
take all of the data points.
- ... step!3.8
- Hence, we use
different techniques to treat the advection equation.
Paul Cochrane
2002-04-18