You are on page 1of 4

Further Programming Hints

David Heintz
October 14, 2009

Abstract
This is a note on the second computer exercise in the course TME080: Computations in me-
chanics (given during the first term of fall in 2009). The intent is to provide, hopefully useful,
hints on how to implement a finite volume solver, adding to the ones already provided in the
assignment instruction1 .

1 Pseudocode
As a support for you to structure your code, which otherwise easily gets complicated, please
review the suggestive pseudocode in Algorithm 1, where it is assumed that you will write your
program as a MATLAB-function, to be called as U = fvsolve(n, w, k).

2 Yet some comments


Finite volume problems—and finite element ones—tend to get large and sparse. To keep the com-
putational cost reasonable, one relies on sparse storage formats, which effectively avoids storing
zero-elements in the system matrix S (you may keep the load vector f in full storage format).
Thus the memory requirement decreases (if the computer run out of memory your program will
not execute). One straightforward—but depending on the implementation possibly not the most
efficient—way to do this in MATLAB is to use SPALLOC (type help spalloc in MATLAB for
detailed information on usage).

MATLAB is user-friendly by allowing dynamic memory handling and not demanding explicit
type declarations (variables become doubles if not declared explicitly). This is usually an advan-
tage, if not only convenient, as compared to “lower-level” programming languages like Fortran
or C. However, make it a habit to preallocate memory for your variables; especially, do not let
them grow inside loop constructs! A nice tool in MATLAB is the PROFILER. It can help you catch
the most common bottlenecks concerning performance. I suggest you read the help text and try
it out, e.g., by running: profile on, U = fesolve(n, w, k); profile viewer on your code.
You may be in for a surprise!

As for another habit: see to it that your code is commented properly; e.g., explain what different
parts of your program are supposed to do, choose suitable variable names (not too short, not too
long), and describe what your variables represent. It is no meaning in exaggerating comments,
however, which only obfuscates the code. A measure of “reasonable” amount of comments could
be to detail as much of your code as to make it readable to you, say, in a month’s time after finish-
ing the program (without to much trouble). Last but not least—always use consistent indentation.
1 Provided via the course homepage http://www.math.chalmers.se/Math/Grundutb/CTH/tme080/
0910/labb2.pdf.

1
2.1 How do I know if my code works?
Download the debug files from the course homepage2 , decompress the folder, run a suitable
routine, say, LAB2 (either read the accompanying help text help debug-lab2, or open the file
Contents.m in a text editor), and then compare its output to your own results. If we assume you
have stored your cell averages in a vector v, which is present in MATLAB’s workspace, it may
suffice to check
>> u = lab2([set input variables to match your own]);
>> norm(v - u) / norm(u)

which ought to produce a small relative difference if things are in order. The solution could look
something like the one shown in Figure 2.1:

F IGURE 1: Upwind method for n = 6 (mesh refinements) and ω = 3/4 (smaller elements at upper boundary)

2.2 Oops! It seems it doesn’t. . . ?


If something goes wrong, and you cannot discover any bugs in your code at first glance, please
consult the debug programs as your primary resource. Store their output variables and compare
them to your own—do they differ, and if so, what part of your code is responsible for that,
supposedly erroneous, calculation? Check it out for mistakes!
In this exercise debugging is made easier by checking the rows of S, since each cell contributes
exactly one equation, or one row, to the system matrix. There will be at most five non-zero entries
in each row, and only boundary cells will contribute to f . Do your non-zero entries appear in the
same columns as in the debug code? If so, are they equal, and if not, is this due to diffusive or
convective contributions (the debug program outputs three matrices, S = Sdiff + Sconv , so check
2 http://www.math.chalmers.se/Math/Grundutb/CTH/tme080/0910/debug-lab2.zip.

2
them out)? Is the error located to a particular cell side (perhaps one which is part of the domain
boundary)?
Also, when you debug, use a coarse mesh in order to easily view output on screen.

Please do not hesitate to ask for help, but do remember that should you implement your code
differently from how it was suggested, you may find yourself to be, more or less, on your own.
The reason is not that we do not encourage you to try out other approaches, but rather that it
could require a disproportionate amount of time for the teacher to squash any bugs.

3
Algorithm 1: FVSOLVE (using an upwind approximation)

Data: number of times to refine initial mesh n, mesh parameter ω, diffusion coefficient k
Result: FV-solution u (also visualize the approximation)

To do before FV-assembly
• define the topology, i.e., set nodes, xnod, and ynod (a four element partition of Ω)

• refine initial mesh (use the supplied REFINE-routine)

• locate all neighbours (use the supplied NEIGHBOURS-routine)


• initialize system matrix S (use sparse storage) and RHS-vector f (need not be sparse)

• it may be convenient to pre-calculate all cell midpoints before the assembly process

FV-assembly
Typically use nested for-loops as follows (you’ll only need two of them):
for all cells (I = 1, . . . , number of cells) do
fetch cell node numbers (I refer to them as cnod later)
fetch cell vertex coordinates (e.g., xcoord = xnod(cnod)), and so on)
for all sides (side = 1 : 4) do
fetch side vertex coordinates (e.g., xside = xcoord(v(side, :)), and so on, using
the pre-defined help vector v = [1 2; 2 3; 3 4; 4 1])
Approximating curve integrals using numerical quadrature requires:

• calculating midpoint on side (we use a 1-point quadrature)

• calculating length of side dS

• calculating exterior unit normal n to side

• setting velocity field c

• calculating convective flux (in the normal direction) cn

Calculate and add diffusive and convective contributions:


fetch neighbour J
if side is internal interface then
calculate cell-to-cell distance ∆ to approximate normal derivative
determine upwind flux (use cn )
update S and (possibly) f accordingly
else
if side is part of Dirichlet boundary then
calculate cell-to-side distance ∆ to approximate normal derivative
determine upwind flux (use cn )
update S and f accordingly
else
determine upwind flux (use cn )
update, if appropriate, S accordingly
end
end
end
end
Concluding steps
solve FV-LES Su = f (use MLDIVIDE, or “backslash”, as described in the instructions)
visualize FV-solution u (see the instructions for hints on using PATCH)

You might also like