0% found this document useful (0 votes)
99 views57 pages

Computer Labs Post

This document describes using Python to model groundwater flow using finite difference methods. It discusses using Gauss-Seidel iteration in Python and spreadsheets to calculate groundwater heads at nodes in a grid. It introduces using successive over relaxation to potentially speed up convergence by applying a relaxation factor to the calculated head difference between iterations. The reader is directed to modify an existing Python script for Gauss-Seidel iteration to incorporate successive over relaxation by adding needed variables and taking the absolute value of the maximum error for comparison to the convergence criterion.

Uploaded by

soniakutti
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
99 views57 pages

Computer Labs Post

This document describes using Python to model groundwater flow using finite difference methods. It discusses using Gauss-Seidel iteration in Python and spreadsheets to calculate groundwater heads at nodes in a grid. It introduces using successive over relaxation to potentially speed up convergence by applying a relaxation factor to the calculated head difference between iterations. The reader is directed to modify an existing Python script for Gauss-Seidel iteration to incorporate successive over relaxation by adding needed variables and taking the absolute value of the maximum error for comparison to the convergence criterion.

Uploaded by

soniakutti
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

Groundwater ow modelling (450008)

Computer laboratories

dr. V.E.A. Post

Contents
Part I: Python 1 Calculating heads 1.1 Solution methods . . . . . . . . . . . . . . . . . 1.1.1 Gauss-Seidel iteration using a spreadsheet 1.1.2 Gauss-Seidel iteration using Python . . . 1.1.3 Successive over relaxation . . . . . . . . 1.1.4 Direct solution . . . . . . . . . . . . . . 1.2 Regional ow example . . . . . . . . . . . . . . 1.2.1 No-ow boundaries . . . . . . . . . . . . 1 5 5 5 6 8 8 9 10 13 13 14 17 17 19 21 27 29 33 37 39 39 40

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

2 Calculating ows 2.1 Water budgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Abstraction well . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Transient simulations 3.1 Abstraction well (transient) . . . . . . . . . . . . . . . . . . . . . Part II: MODFLOW 4 Well eld in a river valley Part III: MicroFEM 5 Well in a semi-conned aquifer 6 Inltration canal Part IV: Linear algebra 7 Systems of linear equations 7.1 Linear equations . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 Systems of linear equations . . . . . . . . . . . . . . . . . . . . . 3

8 Matrices 8.1 Denition . . . . . 8.2 Special matrices . . 8.3 Operations . . . . . 8.4 Determinant . . . . 8.5 Cramers rule . . . 8.6 Inverse of a matrix References

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

45 45 45 46 48 50 51 53

Part I: Creating nite difference models in Python

Introduction
Nowadays, a wide selection of very powerful groundwater ow models is available. For almost every problem there is a code that suits your needs. But sometimes, the code at hand is not just what you want. It may be that it doesnt handle a specic boundary condition or you want the output to be in a slightly different format to make the post-processing easier. Wouldnt it be convenient then if you have the skills to modify the original code a bit, or even to create your own model? Moreover, if you have made (simple) models yourself, you also better understand how existing codes work. This may be helpful in a situation where the model crashes or behaves unexpectedly in a different way. Fewer and fewer hydrologists possess the skills to modify or write computer codes. So, learning to write your own models will give you an advantage. In order to do so, you also need to learn a programming language. A programming language is a set of functions and statements that allow you to pass commands on to the computer. There are dozens of different programming languages available. Examples include Visual Basic, Pascal, C, FORTRAN, Python and many, many more. In this course we will use Python. Python is a so-called command-line interpreter: you type in the commands that are subsequently executed. These commands can be combined into a program which we call a script. The advantage of using Python is that lots of the things you would normally have to worry about as a programmer have already been done for you. For example, creating plots and charts is extremely easy because the statements to send graphics to the screen have already been programmed. You can simply use the commands included in Python and its libraries like matplotlib instead of guring out all this complicated stuff yourself. Another advantage of Python is that it is becoming widely used in various parts of the scientic community. Popular geographic information systems like ArcGIS and GRASS also have Python functionality. In the groundwater industry, MATLAB, another interpreted programming language, is still the standard, although that also slowly starts to change. The reason that we do not use MATLAB in this course is that (i) Python is just as good and sometimes even better than MATLAB and (ii) Python is open-source software. The latter means that there are no licensing issues and that you can install and work with Python on any computer, for example at your home or on a laptop during your eldwork. So, in short, being able to write your own modeling code helps you to better understand what you are doing if you are using an existing model. Also, it gives 3

Chapter 0
you the ability to modify and improve models or create custom-made models. In the learning process, you will become familiar with the basics of programming languages, which you can apply to other areas outside groundwater ow modeling. It is assumed that you are familiar with the basics of Python. If not, or if you want to refresh your memory, then rst familiarize yourself by going through the Python tutorial, which is available from your instructor.

Chapter 1

Calculating heads
1.1 Solution methods
During the lectures we have looked at the solution of unknown heads at the interior nodes of a grid for which the heads at the boundary nodes are known (Dirichlet boundary condition). We have seen that by moving the so-called ve-star operator through the grid, the head at each node could be calculated as a function of the heads in the neighboring nodes. Calculating the heads once, however, was not enough to obtain the nal solution. Instead, we started with an initial guess and then repeated the calculations until the heads no longer changed signicantly (iteration).

1.1.1

Gauss-Seidel iteration using a spreadsheet

Such calculations are easily done by computers. Before creating a program in Python, lets look at how we can use a spreadsheet to do these calculations. Suppose we have a grid as in gure 1.1 with the heads given for each cell on the model boundary.

Figure 1.1: Simple mesh with heads xed on the boundaries. We can easily imagine the cells of a spreadsheet to coincide with the nodes of the model mesh. To do the calculations, proceed as follows: Open your spreadsheet program. 5

Chapter 1
Type in the xed head values at the cells representing the model boundary. Type a formula in the upper left interior cells that calculates the average of the heads in the 4 neighboring cells (see gure 1.2). Copy this formula to the remaining interior cells.

Figure 1.2: Entering the formula for Gauss-Seidel iteration in Excel. It is that easy! The only thing is that, depending on the spreadsheet you use, you may need to iterate manually. In Microsoft Excel, this is done automatically if you select Tools Options and then on the Calculations tab enable the Iteration option.

1.1.2

Gauss-Seidel iteration using Python

The advantage of using a spreadsheet is that it is easier to envisage the model structure because, like a nite-difference model, a spreadsheet consists of cells. In the remainder of the exercises, however, we will use Python because of its much greater exibility. As an example, take a look at the following Python-script, which does exactly the same as what we did before in our spreadsheet.
from numpy import array h = array([[4., [4., [4., [4., 5., 0., 0., 5., 6., 0., 0., 6., 7.], 7.], 7.], 7.]])

Python
dummy = h.shape nrow = dummy[0] ncol = dummy[1] print Head matrix is a , nrow, by , ncol, matrix. ni = 1 conv_crit = 1e-3 converged = False while (not converged): max_err = 0 for r in range(1, nrow - 1): for c in range(1, ncol - 1): h_old = h[r, c] h[r, c] = (h[r - 1, c] + h[r + 1, c] + h[r, c - 1] + h[r, c + 1]) / 4. diff = h[r, c] - h_old if (diff > max_err): max_err = diff if (max_err < conv_crit): converged = True ni = ni + 1 print Number of iterations = , ni - 1 print h

At rst sight, this may look incomprehensibly complicated. It is certainly more complicated than entering the formulas in a spreadsheet. But if you get used to programming it will become much easier to read such scripts. Note how indentation is used to structure the script. In fact, you have to indent in Python, otherwise it will complain! Try if you can understand what is going on here and then answer the following questions: What is the purpose of the variable converged? What values does the shape variable return? Can you think of a reason why it is better to use shape to dene the number of rows and columns rather than just assigning xed values to these variables yourself? What is the name of the variable that is used to store the number of iterations? How does the program know that it only needs to calculate the interior nodes? Exercise: The script is available on Blackboard. Download it to a local disk and open it in Python (simply by clicking File Open and selecting it). The script is opened in the script editor and can be run by pressing F5. Investigate the effects of the convergence criterion and initial head guess on the number of iterations. Set the convergence criterion to different values and note the number of iterations. Do the same for the initial heads of the interior nodes. 7

Chapter 1

1.1.3

Successive over relaxation

A way to speed up the convergence is to use Gauss-Seidel iteration in combination with successive over relaxation (SOR). In this method, the difference between the calculated value at the new iteration interval and that of the previous iteration interval c = hm+1 hm is multiplied by a relaxation factor . The new value of i,j i,j hm+1 becomes: i,j hm+1 = hm + c (1.1) i,j i,j This equation can be written as: hm+1 i,j = (1 )hm i,j + hm+1 + hm+1 + hm hm i+1,j i,j+1 i1,j i,j1 4 (1.2)

Exercise: Open the example script of Gauss-Seidel iteration and modify it in such a way that it can incorporate SOR. What extra variable(s) are needed? Note that max err can become negative with SOR and that you need to take care that you compare the absolute value of max err to the convergence criterion. Use a value of = 1.1. The number of iterations is now . . . . . . . Increase the value of and run the script again. Note that when > 1.25 the number of iterations increases compared to the script without SOR! This is because for high values of the calculated heads during the rst iterations overshoot the nal true values and it takes some time to converge back towards these values.

1.1.4

Direct solution

The previous exercise shows that the heads at the interior nodes are readily calculated using Gauss-Seidel iteration, either with or without SOR. Iterative solutions, however, are not the most efcient way to solve the system of nite difference equations. Direct solution methods are an alternative, more efcient way and are easily applied in Python. Remember that a system of linear equations (such as the nite-difference expressions for this problem) can be written in matrix form: [A]h = f (1.3)

where [A] is a coefcient matrix, h a column vector of unknown heads and f a column vector containing all known values. h follows from: h = [A]1 f (1.4)

where [A]1 is the so-called inverse of [A]. For the problem presented above, write down a nite-difference expression for each unknown head at the interior nodes. The result is a system of 4 linear equations with 4 unknowns. Transfer all known values (the heads at the boundaries) to the right-hand side and express the system of equations in matrix format. Then 8

Python
use Numpys linear algebra package to solve for h (see page 19 20 of the Python tutorial on how to do this). Did you get the same result as before? Although direct solution methods are more efcient than iterative methods they require large amounts of computer memory for real-world numerical models. Therefore, most codes use solution schemes that combine the best of both worlds of iterative and direct solution techniques.

1.2 Regional ow example


The previous example was very basic and not of much use in real-world modeling. In the next example, we will use our numerical model to analyze ow systems in a topographically-driven groundwater system. In the course Groundwater hydraulics you derived an analytical solution for this problem and did a numerical calculation with FlexPDE. We will now modify our script so we are able to solve the problem ourselves. We will combine the model with the powerful graphical capabilities of Pythons Matplotlib package to visualize the output. In that way, we have already created a tool that starts to look like the industry-standard modeling packages! Take the script for Gauss-Seidel iteration with SOR as your starting point. First save the script under a different name. Set the value of omega to = 1.8 and set the convergence criterion to 1 105 . As a rst step, we will increase the number of rows and columns of the model from 4 by 4 to 26 by 26. An easy way to so is to use the function zeros() to create the matrix h. In that way, all the starting heads will be set to 0 automatically. Look up how the function works and insert the appropriate statement in the script. Note that you have to import the function zeros() from numpy, just like the function sin() and pi (see below). We use the same conguration as for the exercise in Groundwater hydraulics, so our model will measure 500 by 500 m. What will be the width of the grid cells (note: we have a mesh-centered grid!). Declare a variable called dx and set its value to the appropriate grid cell width. We will use square cells, so there is no need to dene the height of the cells explicitly. The heads at the top of the model can be dened by superposition of 2 sine functions with different wavelengths. This is expressed in the formula: h = A1 sin(k1 x) + A2 sin(k2 x) (1.5)

where A1 and A2 are the amplitudes of the respective waves, k = 2 n/L, n is the wave number and L is the width of the model. Modify the script to include the parameters L, A1 , A2 , n1 , n2 , k1 and k2 . Set the values of A1 = A2 = 5.0 m and n1 = 1 and n2 = 2. Equation 1.5 contains the variable x, so we need to know x for each column in the grid. Try to nd the right statements to accomplish this and then implement equation 1.5 in the script. Once you have done this, youre almost ready to start the calculations. As a nal step, include this statement at the beginning of the script: 9

Chapter 1
from numpy import *

Include the following statements at the end of the script to produce graphical output:
close() f = figure() [X, Z] = meshgrid(linspace(0, L, ncol), linspace(0, -L, nrow)) contourf(X, Z, h) colorbar() [dhz, dhx] = gradient(h) quiver(X, Z, -dhx, dhz, color = w)

Look up what these functions do. Can you understand what they mean? If you do youre now ready to start calculating your rst real-world, self-made groundwater ow model!

1.2.1

No-ow boundaries

Note that we didnt worry about the no-ow boundary at the bottom of the model in the previous exercise. How can you see from the contour lines of the hydraulic heads that the bottom boundary is not a no-ow model? In the next exercise we will implement the no-ow boundary. We only need to make a few adjustments. Remember from the lectures that a way to incorporate no-ow boundaries is to add imaginary nodes outside the model domain. The type of grid determines how the no-ow boundary is implemented. For a mesh-centered grid, the gradient across the boundary becomes zero (the condition for no-ow) if hi,j+1 = hi,j1 , where hi,j+1 the head at the the imaginary node outside the model domain and hi,j1 is the head at rst node inside the model boundary. We will expand our matrix at the bottom with one additional row, representing the imaginary nodes. To do so, change the declaration of matrix h. Then implement the no-ow boundary by adding the following line:
h[-1, :] = h[-3, :]

Specifying -1 at the row index is short in Python for the last row; -3 indicates the third-last row. The colon at the column index means all columns. So this statement assigns the heads of the third-last row to the heads of the last row, for all columns. Where would you insert this line into our script? If you add it your script is almost ready to handle the no-ow boundary. Before you start the calculation though, you need to make some minor changes to the statements that produce the graphics. These prevent the imaginary cells from being displayed. The correct syntax is:

10

Python
close() f = figure() [X, Z] = meshgrid(linspace(0, L, ncol), linspace(0, -L, nrow - 1)) contourf(X, Z, h[:-1, :]) colorbar() [dhz, dhx] = gradient(h[:-1, :]) quiver(X, Z, -dhx, dhz, color = w)

Only 3 lines are different. Study the differences and make sure you know what they mean. Then start the calculations and pay particular attention to the head contours near the bottom boundary. What has changed?

11

Chapter 2

Calculating ows
2.1 Water budgets
In the previous examples the convergence criterion controls the accuracy of the solution. As a second check on the accuracy, a water balance can be set up. Remember from the lectures that for a 2D model with square grid cells: Q = k h x = kh x (2.1)

Assume that the hydraulic conductivity (k) is 10 m/d. Extend the script of the regional ow example to calculate the water balance of the whole model domain. Calculate inow and outow of each model boundary except for the bottom boundary. Make sure to adopt a sign-convention for inow (+) and outow (-). Fill in the table below. Table 2.1: Water budget for regional ow example ow component qlef t qright qtop qbottom qtotal magnitude ... ... ... ... ...

Compare the net inow (inow - outow) to the magnitude of the inow/outow. Is the error in the water balance acceptable? Note that the net ow over the top model boundary is basically zero but that the inow and outow components themselves over this boundary are not. What are the magnitudes of the inow and outow over the top boundary? 13

Chapter 2

2.2 Abstraction well


In this exercise we calculate the drawdown due to a well that fully penetrates a conned aquifer. Flow is horizontal and the aquifer is isotropic. Under these conditions and when x = y, the formula for Gauss-Seidel iteration takes the following form (check your lecture notes): hi,j = hi1,j + hi,j1 + hi+1,j + hi,j+1 + x2 R/T 4 (2.2)

where T is the transmissivity (m2 /day) and R is the volume of recharge/discharge per unit time per unit surface area. R and Q are related by (for square grid cells, so x = y): Q R= (2.3) x2 Transmissivity is T = 300 m2 /day. The well is located at x = 0, y = 0 and has a discharge of Q = 2000 m3 /day. The value of R is for the innitesimal volume around the well (gure 2.1). Outside this volume R = 0.

Figure 2.1: Finite difference grid for abstraction well exercise. Modied from Wang and Anderson (1982). Because the equipotential lines will be cylindrical around the well, the problem is symmetric and we only need to consider one quarter of the problem domain. Lets model the lower-right quardrant so the left and upper boundary are the noow boundaries (gure 2.1). The analytical solution for this problem is given by the Thiem equation: Q r ln (2.4) 2T rmax where h0 is the head before pumping and rmax is the radius of inuence of the pumping well. Assume for this exercise that rmax = 2000 m. Note that although time is not in this formula, this is actually not a steady-state problem: The h = h0 + 14

Python
Thiem equation calculates the heads for a given rmax . Check your lecture notes of Groundwater hydraulics to see how rmax varies with time. As before, take the script for Gauss-Seidel iteration with SOR as your starting point. Set the value of omega to = 1.8 and set the convergence criterion to 1 103 . Use a (mesh-centered) grid of 12 rows by 12 columns (of which the rst row and column are imaginary nodes!). Use x = y = 200 m. Make the following modications to the script (not all of them are straightforward, so ask for help if you dont succeed yourself): Calculate the distance of each node to the well and nd the nodes whose distance most closely match the radius of inuence (rmax = 2000 m). Set the heads of these nodes and of those outside the radius to h = 10 m. Set the starting heads of all remaining nodes to h = 5 m. Include lines to make the left and upper boundaries no-ow boundaries. Modify the statements that perform the Gauss-Seidel iteration in such a way that they can take into account the abstraction well (equation 2.2). Make sure that the heads are only calculated for the nodes that are part of the area of inuence of the well. In other words, dont calculate the heads of the nodes that you have set to h = 10 m. You will have to think of a smart trick to accomplish this. Include the options for graphical output at the end. Finally, add a program line to calculate the analytical solution with the Thiem equation so you can compare it to the numerical result. You will nd that the analytical and numerical results agree very well. You could include a water balance calculation but that involves quite a bit of administration since the inow here is not simply through the right and bottom grid boundaries but across the circumference formed by the sides of the cells that are mark the radius of inuence.

15

Chapter 3

Transient simulations
3.1 Abstraction well (transient)
The previous exercises all assumed steady-state conditions. In this exercise the well-drawdown problem will be expanded to a transient simulation. As before, only the lower-left quadrant, measuring 2000 by 2000 m, is considered but now all the boundaries are no-ow boundaries and the cell size is x = y = 100 m. The numerical results will be compared to the analytical solution by Theis that calculates the drawdown at a radius (r) from the well: h0 h = where

Q W (u) 4T e d

(3.1)

W (u) =
u

(3.2)

r2 S (3.3) 4T t W (u) is called the well functions and is usually tabulated in textbooks. It is also implemented in Python so there is no need to look it up: you simply calculate it with Python! The input le for this exercise has been prepared for you (it is available via Blackboard). Study it and answer the following questions: u= 1. What is the function of the parameters alpha and n steps? 2. What is the size of the time steps? 3. See if you can nd the lines that calculate the analytical solution. What is the Python equivalent of the well function W (u)? 4. At what distance are the analytical solution and the numerical solution compared? 17

and

Chapter 3
After you have studied the script, run it and observe the graph that is produced. It compares the t between the analytical and numerical results. 1. At what time do they start to deviate and why is this? 2. What causes the smaller deviations before this time? 3. Modify the script to have it perform fully-implicit calculations. What is the effect on the number of iterations? 4. Then change to a fully-explicit formulation. What happens? To prevent this, only one line of the code needs to be changed. Which one? And how would you change it? Make the change and discuss the implications. To nish, uncomment the lines that produce the 3D graph of the heads during the calculations. A movie will be displayed on the screen that shows the change in heads over time. In a relatively short time you have mastered Python, learned to program your own modelling codes and became a movie producer. Not bad, dont you think?!

18

Part II: Creating nite difference models in MODFLOW

Chapter 4

Well eld in a river valley


This exercise is a modied version of tuturial 3 from Chiang (2005). It serves to (1) become familiar with the input le structure of MODFLOW, (2) compare 3D and quasi-3D vertical discretization methods, (3) illustrate the use of the MODFLOW Well and River packages and (4) practice the interpretation of the water balance. The les that are needed for this exercise are available on Blackboard.

Problem description
A river ows through a valley, which is bounded to the north and south by impermeable granite intrusions (gure 4.1). The hydraulic heads in the valley at the upstream and downstream model boundaries are known. The river forms part of a phreatic aquifer, which overlies a conned aquifer of a variable thickness. A silty layer with a thickness of 0.5m separates the two aquifers. A well eld consisting of 3 pumping wells is to be installed, which will be abstracting groundwater at a proposed rate of Q = 500 m3 /day from the conned aquifer. The question is how that well eld will affect the discharge of the river, which provides water to a valuable ecosystem downstream. The relevant hydraulic parameters of the aquifer system are listed in table 4.1.

Model setup
Several les are available on Blackboard with information on the geometry and the heads of the aquifer system. Start by downloading these les and put them in your working directory. We will initially simulate the system with a quasi-3D model (steady-state). That means that the silt layer is not explicitly included in the model. Instead, we enter an appropriate value of the vertical leakance. Hence, the head in the silt layer is not calculated but the exchange of water between the upper and the lower aquifer through the silt layer is. To set up the model, proceed as follows:

Chapter 4

Figure 4.1: Conguration of the model Create a new model in PMWIN and lay out the grid. Use 2 model layers (each representing a single aquifer), 20 rows and 27 columns. You can nd the model extent from gure 4.1. Load the basemap for this exercise by going to Options Map in the grid editor. Right click on the DXF File eld and open the le basemap.dxf (which you just copied from Blackboard). Make sure you check the box in front of the lename. The map will be loaded but it is shifted relative to the grid. You can move the grid by selecting Options Environment and entering Xo = 200 and Yo = 6000 in the Coordinate System tab. You can already rene the grid at the location of the well eld. To do so, leave the Grid Editor and enter it again. Then halve the widths of the columns 8 through 14 and rows 7 through 12 by repeatedly right-clicking each of them and specifying the appropriate renement factor (= 2). Your grid will look like the one in gure 4.2. Set the appropriate layer properties (conned or unconned) under Grid Layer property. Select User dened for the Transmissivity and Leakance. Set the boundary conditions. The granite hills will be represented by inactive grid cells. Use the Polygon feature of the PMWIN editor to accurately delineate the hills. You can copy the inactive cells to the second model layer by activating the Layer copy button on the toolbar. The boundary condtition 22

MODFLOW
Table 4.1: Aquifer system parameters for river valley exercise Parameter magnitude units m/day m/day

Aquifer 1 (phreatic) Horizontal hydraulic conductivity (kh ) 5 Vertical hydraulic conductivity (kv ) 0.5 Porosity (n) 0.2 Silt layer (conning unit) Horizontal hydraulic conductivity (kh ) 0.5 Vertical hydraulic conductivity (kv ) 0.05 Porosity (n) 0.25 Aquifer 2 (conned) Horizontal hydraulic conductivity (kh ) 2 Vertical hydraulic conductivity (kv ) 1 Porosity (n) 0.25 River Stage (upstream/downstream) 19.4/17 Bottom elevation (upstream/downstream) 17.4/15 Width 100 River bed hydr. conductivity 2 River bed thickness 1

m/day m/day

m/day m/day

m m m m/day m

at the upstream and downstream valley boundaries will be xed heads. The values of the xed heads (which you need to enter later under Grid Initial and prescribed heads) are in the le xed heads.dat. Specify the layer top elevations by going to Grid Top of Layers and loading the les top1.dat and top3.dat. Specify the layer bottom elevations by going to Grid Bottom of layers. Do not accept the option for determining the bottom elevations from the top elevations of the underlying layers. Set the bottom elevation of layer 1 to the elevation of the top of the silt layer, which is stored in the le top2.dat. Set the bottom of layer 2 to a constant value of 0 m. Select Parameters Time and set the time units to days and specify that this will be a steady-state simulation. Specify the transmissivity, vertical leakance, horizontal hydraulic conductivity and effective porosity. You can calculate these number with the data from table 4.1 and the thicknesses of the layers (look these up in the model). Take care of the following: 1. Note that the thickness of the conned aquifer is not constant. Therefore, the transmissivity of this layer varies. You can calculate it au23

Chapter 4
tomatically by using a trick. First, set the hydraulic conductivity to 2 m/day in each cell (use the Reset matrix function). Then load the le top3.dat which contains the aquifer top elevation. Since the bottom elevation is 0 everywhere, the numbers in this le equal the thickness of the aquifer. Before pressing the Ok button to load the le, select the option multiply. The numbers currently in the grid will be multiplied with the numbers in the le. 2. The vertical leakance is only dened for the rst model layer. It is not dened for the bottom model layer (you can check this in the MODFLOW input le later). It is dependent on the thicknesses of all 3 hydrostratigraphic units. It is a bit harder to calculate than the transmissivity so the le has been prepared for you. It is called vcont1.dat. Check if you understand how these values have been calculated. Do this by calculating the value for a particular cell by hand. Add the river. MODFLOW requires that the river data (i.e. stage, bottom elevation, and riverbed conductance) are specied for each grid cell that the river intersects. Go to Models MODFLOW Flow packages River. Use the Polyline input method to accurately trace the river. Vertices are added by left-clicking; dening the polyline is cancelled by right-cliking. To complete the polyline, left-click the last vertex you specied again. Then right-click the leftmost (upstream) vertex and enter the data for this river node (the values are in table 4.1). Do the same for the rightmost (downstream) vertex. You do not need to enter the values for the other vertices: PMWIN interpolates between the two outer vertices, which makes life a bit easier. After entering all the data make sure that you did not forget anything. Checking the input is an important step in groundwater modelling, especially if you are running models that take a couple of hours to nish. Then run MODFLOW. Graphical user interfaces like PMWIN are great in that they tremendously facilitate data entry. The drawback is that a lot of the action takes place behind the scenes and remains hidden from the user. For example, PMWIN generates all the input les that MODFLOW needs. Usually, there is no need to edit these input les yourself but as an academic you are naturally curious of how they look. Moreover, sometimes a graphical user interface does not support all the options of a code and you may need to modify the input les directly. Therefore, before proceeding, go to your working directory that contains all the les of this model. Look up the le that has the extension .nam. It contains a list of the lenames that are used by MODFLOW. Look up these les and try to nd out what their purpose is and what data they contain. Then plot the hydraulic head distribution using Tools 2D Visualization. Also check the water balance. You can use either the water budget option of PMWIN or open the le output.dat in a text editor. How much water enters the model domain 24

MODFLOW

Figure 4.2: Model grid through the upstream valley boundary? And how much water leaves through the downstream boundary? The river is both a source and a sink of water to the aquifer. But on the whole, is this a losing or a gaining river? Note that the water balance error is basically zero. Write down the numbers as we will compare them to the model with groundwater abstraction later. Then run the model again but with the 3 wells in place in the conned aquifer. Each withdraws water at a rate of 500 m3 /day from layer 3, which is entered under Models MODFLOW Flow packages Well. Again, observe the head distribution. This time, also use PMPATH to draw ow lines. Then check the water budget again. What percentage of the pumped water derives from groundwater and how much is inltrated river water? By how much has the river discharge decreased at the downstream model boundary compared to the natural situation? Then change the model from a quasi-3D to a full 3D model. The easiest way to do this is to: go to Grid Mesh size and subdivide the second model layer into 2 layers. Do this by pressing PgDn to go to the second model layer. Then you can right-click on any cell and type 2 in the Layer renement eld. set the appropriate layer properties under Grid Layer property. Select Calculated for the Transmissivity and Leakance. This means that the values of these parameters will be calculated by MODFLOW using the hydraulic conductivities and layer top and bottom elevations. 25

Chapter 4
set the boundary conditions. The values for the two aquifers remain the same as before. The inactive cells of the second model layer (the silt layer) are the same as for the aquifers, but the boundaries on the upstream and downstream valley boundaries are no-ow boundaries (we assume that ow is purely vertical in the silt layer so there is no ow over the boundary). set the layer top and bottom elevations using the values from the les you used earlier. set the horizontal and vertical hydraulic conductivity and effective porosity to the values from table 4.1. If you run the model you will get basically the same results as with the quasi3D model. Check this by comparing the head distribution and the water balance. As a nal exercise, do a sensitivity analysis for the hydraulic conductivity of the river bed. As you can imagine, this parameter is extremely difcult to quantify and it will also probably be quite variable along the streambed. We have used a value of 1 m/day but why could they not range between 0.5 to 2 m/day? Re-run the model using these extremes and investigate the effect on the hydraulic head distribution and the water budget. Dont let these result make you lose faith in models but consider them a lesson in critical thinking.

26

Part III: Creating nite element models in MicroFEM

Chapter 5

Well in a semi-conned aquifer


This exercise serves to illustrate the basic capabilities of MicroFEM. A well abstracts groundwater at a constant rate of 50 m3 /hour from a conned aquifer. Under natural conditions uniform ow occurs in a WSW direction, parallel to the long sides of a rectangular model. We will model the head distribution in the aquifer and calculate a water balance. 1. Create a network using the FemGrid generator: Choose Files New grid and in the window that appears select Create new grid and press OK. In the subsequent window, enter a descriptive model name. This is required before you can continue. By pressing OK you enter the grid editor. In the upper righthand corner you see 3 tabsheets in which you enter the required information to create the grid. You will have 5 xed nodes: four at the corners of the grid and 1 for the well. Only 3 xed nodes are default, however. To change this, type 5 in the edit eld and click the button Change number to. Now there will be 5 rows for which you can enter the x- and y-coordinates. The coordinates are (1000, 0), (13000, 3000), (12000, 7000) and (0, 4000) for the model boundary corner nodes and (4500, 3000) for the well. Dene the segments and regions as explained during the lecture. Set the distance between nodes to 400 m on the model edges and to 250 m in the model interior. Then press the button Fixed nodes in the toolbar at the bottom of your screen. The xed nodes are created and displayed on your screen. The caption of the button has changed to Nodes on segments. Press it again and observe what happens. Press it again and again and each time make sure you understand what is going on. Your network will have 866 nodes (gure 5.1). Then you can either save the network (recommended) or choose the number of aquifers (which is 1) and start entering the hydraulic parameters. 2. Find the dimensions of the rectangular model domain, i.e. the exact model width and length. Do this by placing the cursor in one of the 4 corner nodes and assigning the variable r to all nodes for a parameter (e.g. h0) in the input

Chapter 5

Figure 5.1: Rectangular model area with short east- and western and long northern and southern boundaries. mode. Look up the meaning of this parameter in the help le! What are the model dimensions? 3. We start with a conned aquifer so the vertical resistance of the rst model layer should be set to 0 (which is interpreted as innite by MicroFEM). The transmissivity is T = kD = 800 m2 /day. These parameters are entered in the input mode. 4. Groundwater ow is in a WSW direction parallel to the long sides of the model. The head at the eastern boundary is 20 m and the hydraulic gradient is 0.001. Assign head values to all model nodes by marking the east model boundary in the walking mode and using a formula that calculates the head as a function of the head on the eastern boundary, the gradient and the variable d (which represents the distance to the nearest marked node). 5. Make a contour map in the drawing mode to check that the heads were entered correctly. Double-check by going to the western boundary: the head should be 7.631 m here. 6. Go to the xed node that contains the well (coordinates 4500, 3000). Note that it has the label xed node 5 so it is easily found by using the Jump to node function in the walking mode. Press F12 or the Jump to node button, select Next label and choose xed node 5 from the pull-down list. Make sure that you ended up in the right node (check the coordinates as well as the label in the lower-right corner of the screen) and then assign the well discharge to this node in the input mode. Well discharge has a positive value in MicroFEM, contrary to MODFLOW! Also change the name (= the value of the parameter label1) of this node from xed node 5 to Well. 30

MicroFEM
7. Run the model by going to Calculate Go calculate. Why is there no convergence? 8. Restore the natural hydraulic head situation by repeating step 4. Then x the heads on the eastern and western model boundaries. Mark the nodes on these boundaries and make sure that the head of the rst aquifer is selected in the parameter list. Then use the Toggle heads for marked nodes function to x the heads: The word xed will appear in the parameter list for the marked nodes. 9. Run the model again by going to Calculate Go calculate. This time, a solution is found. Why? 10. Draw the hydraulic head contours in the drawing mode. You can overlay a set of ow vectors to visualize the ow. Explore the options of the drawing mode by clicking around a bit. 11. Go to the node that contains the well to draw the owlines to delineate the capture zone of the well. Specify a number of 12 owlines, a timestep of 100 years, layer thickness of 40 m and a porosity of 30 %. What is the width of the capture zone? Why are the isochrons curved? 12. Set up a water balance for the entire model. You can nd the water balance options in the walking mode. What is the inow through the eastern model boundary? And what is the outow over the western boundary? 13. We will now change the model from a conned aquifer with a well to a semi-conned aquifer without a well. Moreover, we set the transmissivity downstream of the well to 300 m2 /day. The groundwater table (h0) is set to the original hydraulic heads under natural conditions. Make sure to make the following changes: Assign a hydraulic resistance (= parameter c1) of 2500 days to the conning unit. Set the groundwater table by marking the eastern boundary and entering the formula (as in step 4 but now for h0 instead of h1): 20-0.001*d. Change the transmissivity downstream of the well from 800 m2 /day to 300 m2 /day. Do this by marking the appropriate nodes and assigning the value of 300 m2 /day to the marked nodes only in the input mode. Remove the well from the model (i.e. set the discharge to 0). 14. Calculate the heads. Also make a contour plot of h1-h0 through the following steps: Go to Project Project Manager to add an extra variable for each node that can be used to hold intermediate results. A window will appear with a list of all MicroFEM les for this model. 31

Chapter 5
Click the button with the bright-green + sign, select Xtra worksheet, check New in the Create data from eld (otherwise you will be asked for a le to read the data from) and click OK. You can choose to have as many registers (= new input elds) as you like, but 1 will be enough for our purposes. Note that the project manager is also the place to add special types of boundaries. Close the project manager and note that an new tab has been created that is called Xtra. It contains an edit eld for a variable x1. This variable can contain any value we assign to it without affecting the calculations. Since we are interested in the head difference across the semi-conning unit we assign the result of the formula h1-h0 to all nodes. The positive values of the head difference indicate that there is upward seepage in the whole model domain. Check the water balance. How much is the upward seepage through the semi-conning unit? 15. Then activate the well again. Calculate the model and check the water balance. Indicate the zones of upward seepage and inltration by drawing the difference between h0 and h1. Calculate the volumetric rate of upward seepage/inltration (in m3 /day) for each node (in the Xtra worksheet). Check your calculation by comparing it to the water balance. 16. What proportion of the well discharge inltrates through the semi-conning unit and what proportion derives from regional groundwater ow?

32

Chapter 6

Inltration canal
This problem serves to demonstrate the supremacy of nite element models over nite difference models when it comes to grid design. A shallow inltration canal loses water to two fully penetrating drains. The drains are 120 m apart, with water levels at 40 and 35 m (left and right side, respectively) above an impervious base. The water level of the 5 m deep and 25 m wide inltration canal is 55 m (see gure 6.1). The aquifer is homogeneous and isotropic, with hydraulic conductivity k = 25 m/day. We will simulate this problem as a prole model. A hollow groundwater table will develop between the inltration canal and the drains. The grid must be deformed in order to represent the saturated part of the model domain. Remember that at the groundwater table the pressure of the water P = Pabs Patm = 0 so P that the hydraulic head h = z + g = z, where z is the so-called elevation head. In other words, the elevation of a water table node above a reference level (in this case the impermeable base) needs to be equal to the calculated head. The mesh needs to be adjusted after each calculation so that the top model boundary coincides with the groundwater table. 1. In order to save you some time, the conguration of the network has already been prepared and can be found on Blackboard. The xed nodes, triangles and quadrangles that make up the mesh are stored in the le prole model.fen. Open this le in MicroFEM by going to Files New Grid and pressing OK. A le selector window appears. Open the fen le and check how the FemMesh network has been dened. 2. Create the network and go to MicroFEM. Select 1 as the number of layers. A prole model is implemented in MicroFEM by assigning an innite resistance to the upper conning unit (i.e., c1 = 0) and entering the hydraulic conductivity (k-value) instead of the transmissivity. 3. Then set up the model: assign xed heads to the nodes that represent the canal and the drains and set the appropriate values for h1. Enter the transmissivity (= hydraulic conductivty). As a preparation for subsequent steps

Chapter 6

Figure 6.1: Conguration of the ow problem of the inltration canal give the nodes that sit between the canal and the drains the label water table. 4. You are now ready to calculate the model for the rst time. New heads will be calculated, which provide a rst estimate of the shape of the groundwater table. We can use these to relocate the nodes at the top of the model domain. Take the following steps and follow these carefully (otherwise MicroFEM could crash): Go to Export Special ASCII les and select CSV-le. For each node all the model parameters, together with the x- and y-coordinates, will be exported. The trick is now to change the y-coordinates of the water table nodes and set these equal to the head we just calculated (parameter h1). You could in theory do this in Excel but its a pain. Python is much better suited for this purpose. Remember also that this is only a small le but the output from a real-world model may not even t in Excels datasheet. A le called read csv le.py is available on Blackboard. Download it to the same directory where you saved the csv le. The comments in the le explain in detail what it does. Inspect the le and make sure that you understand what is going on. Then run it. Return to MicroFEM and select Import Special ASCII les. Select CSV-le and open the le you just saved in Excel. The new coordinates will be read and the nodes on the upper model boundary have shifted downwards. The grid has been deformed and now is a better approximation of the shape of the saturated part of the model domain. With the nodes shifted, the shape of the elements is not necessarily ideal. Therefore we will let MicroFEM optimize the shape of the net34

MicroFEM
work. In the Walking mode, mark all nodes. Then go to the Alter grid mode and press F10 (Relocate marked nodes). You can see the network being optimized. It doensnt hurt to do this 2 more times to get the most optimal grid. Now calculate the heads again and repeat the steps above until the shape of the grid (or the position of the groundwater table) no longer changes. The ow problem is then solved. In this example, the shape of the grid depends on the calculated heads. The exibility of nite element methods and the powerful capabilities of MicroFEM allow you to solve this problem. Solving the same type of problem in MODFLOW is not so easy! 5. Draw owlines starting at all nodes of the inltration canal bed. Hint: give these nodes the same label (e.g. canal). 6. Set up a water balance. How much water is lost to each drain? 7. If you have time left, you can play around with the hydraulic conductivity and see what effect it has. For example, change use a value of k = 1 m/day and note the effect on the head contours and the water balances. Or you could introduce anisotropy (e.g. kh = 25 and kv = 1 m/day).

35

Part IV: Linear algebra

Chapter 7

Systems of linear equations


Numerical approximations of the governing equations for groundwater ow lead to a set of algebraic equations that can be solved for the unknown heads by (i) iteration or (ii) direct solution techniques. With direct solutions, the system of equations is transformed into matrices and the unknown heads are solved using the techniques of linear algebra. Therefore, some knowledge these subjects is indispensable if you are working with numerical groundwater models. This document is intended for self-study and will give you a basic comprehension of the relevant topics for the practicing hydrologist. Some of the exercises require the use of Python. Python provides support for matrix operations through the Numpy library. These are not described here but you are expected to try and look these up yourself in the on-line documentation for Numpy. A good starting point is the following website: http://docs.scipy.org/doc/numpy/reference/index.html But of course, when in doubt or when you get stuck, do not hesitate to ask your instructor!

7.1 Linear equations


A linear equation is an algebraic expression with one or more variable in which each term is a constant or the product of a constant and a variable. For example: h(x) = Ax + B

(7.1)

where h is the dependent variable, x is the independent variable, A is the slope or gradient and B is the intercept, i.e. the value of h when x = 0. 39

Chapter 7

h0

qx

h1

x0 x

x1

Figure 7.1: Schematic cross-section depicting a conned aquifer with onedimensional horizontal ow.

7.2 Systems of linear equations


Two variables
Recall that Equation 7.1 is the general solution of a one-dimensional partial differential equation 2h =0 (7.2) x2 that describes the hydraulic head h in a conned aquifer between two canals as depicted in Figure 7.1. As a demonstration example of a system of linear equations, lets try to determine the integration constants A and B from boundary conditions. So instead of treating h and x as the dependent and independent variables, respectively, their values become xed by the following boundary conditions: h h
x=x0

= h0 = h1

(7.3) (7.4)

x=x1

Combining conditions 7.3 and 7.4 with Equation 7.1 and yields a system of two linear equations: h0 = Ax0 + B h1 = Ax1 + B (7.5) (7.6)

in which A and B are the unknowns and x0 , x1 , h0 and h1 are known constants. If we wish to nd the numerical values of A and B we must nd the solution to this 40

Linear equations
system of linear equations. This means nding the values of A and B so that both Equation 7.5 and 7.6 are satised. Assume that h0 = 10, h1 = 9, x0 = 50 and x1 = 1501 . Let B now be the dependent and A be the independent variable so that we have: B = 10 50A B = 9 150A (7.7) (7.8)

One way to nd the solution is to plot Equations 7.7 and 7.8 in a graph and to look up the point where they intersect. This is shown in Figure 7.2. Obviously, this method can be inaccurate when the graph is drawn by hand and is not suitable for systems of equations with more than 2 variables. Exercise: Find the graphical solution to Equations 7.5 and 7.6 for A and B assuming x0 = 0 and the other parameters as listed above. A better way would be to use the method of substitution. This involves reducing the number of unknowns by expressing A as a function of B using either one of the Equations 7.7 or 7.8 and substituting the result into the other. The equation obtained this way can be solved for B. The value of A is subsequently found by substituting the calculated value of B in either Equations 7.7 or 7.8 and solving for A. Exercise: Find the solution of Equations 7.7 and 7.8 by the method of substitution. Verify that your answer is the same as in Figure 7.2. Note that the solution is written as {(A, B)}, i.e. a set containing an ordered pair. For the system described by Equations 7.7 or 7.8 there is one solution and therefore it is called a consistent system. An inconsistent system on the other hand has no solution. For example, the linear system: 50A + B = 10 50A + B = 9 (7.9) (7.10)

represents two parallel lines and therefore has no solution. This is denoted by a null or an empty set: or {}. Note that substitution would yield 10 = 9, which is a contradiction from which it is clear that there can be no solution. A system of two linear equations with two variables will have an innite number of solutions when the two lines coincide. This occurs if the equations are a multiple of each other. For example: 50A + B = 10 100A + 2B = 20
1

(7.11) (7.12)

All having length units, for example m

41

Chapter 7

20 15 10 5
( 0. 01,10. 5) B = 10 50A

B = 9 150A

-0.050

-0.025

0.000 A

0.025

0.050

Figure 7.2: Graphical representation of Equations 7.7 and 7.8. represent the same line in a plot of A versus B. This is called a dependent system and the solution is either of these two equations: {(A, B) | 50A + B = 10}.

Three (or more) variables


To develop a system of linear equations of three variables, suppose we would like to solve Equation 7.2 numerically. For this purpose, the domain between x0 and x1 is rst discretized into n cells. The numerical approximation yields (central in space, cf. lecture notes): 2h hc1 2hc + hc+1 =0 2 x (x)2 or: 2hc = hc1 + hc+1 (7.14) where the subscript c indicates the cell number (1 c n). Suppose that n = 5 and that the heads in the rst and fth cells are xed heads with h1 = 10 and h5 = 6. The heads in the nodes h2 , h3 and h4 are then given by: 2h2 = 10 + h3 2h3 = h2 + h4 2h4 = h3 + 6 42 (7.13)

Linear equations
that can be written as a system of linear equations with three variables: 2h2 h3 = 10 h2 + 2h3 h4 = 0 h3 + 2h4 = 6

(7.15)

This system system of equations can be solved for h2 , h3 and h4 by an algorithm called Gaussian elimination. It uses elementary row operations to transform the linear equations into a form that is easily solved. Application of these operations does not change the solution of the system of linear equations. The operations are: 1. Equations can be interchanged 2. An equation can be multiplied with a non-zero constant 3. An equation can be multiplied by a constant and added to another equation As an example, rst reverse the rst and second equation in the system dened by Equation 7.15 (Operation 1): h2 + 2h3 h4 = 0 2h2 h3 = 10 h3 + 2h4 = 6

(7.16)

Then add 2 times the rst equation to the second equation (Operation 3): h2 + 2h3 h4 = 0 3h3 2h4 = 10 h3 + 2h4 = 6

(7.17)

Finally, multiply the third equation by 3 (Operation 2) and add the second equation (Operation 3): h2 + 2h3 h4 = 0 3h3 2h4 = 10 4h4 = 28

(7.18)

This form of the system of equations is called echelon form (or row echelon form), meaning that that the rst non-zero leading coefcient in an equation is to the right of the rst leading coefcient in the equation above it. A system is in reduced-echelon form when the rst coefcient in an equation is always one. To transform the system of equations into reduced-echelon form, equation 1 is multiplied by -1, equation 2 by 1/3 and equation 3 by 1/4: h2 2h3 + h4 = 0 h3 2/3h4 = 10/3 h4 = 7

(7.19)

43

Chapter 7
which immediately yields h4 = 7. The values of h2 and h3 are subsequently found by substitution. Exercise: Find the values of h2 and h3 by back-substitution.

Exercise: Find the values of A and B in Equations 7.7 and 7.8 by Gaussian elimination.

44

Chapter 8

Matrices
8.1 Denition
A matrix is a rectangular array of numbers. It consists of m rows and n columns, which are written between square or round brackets. For example, the matrix A: A= 1 3 5 2 4 6 (8.1)

This matrix has 2 rows and 3 columns. Its order is therefore 2 3. Each number in the matrix is called an element. Elements can be real or complex numbers. Elements are denoted by ar,c whereby subscripts r and c refer to the row and column number, respectively. For example, a2,3 refers to the number in the second row and third column, i.e. a2,3 = 6. Sometimes the comma between the row and column indexes is omitted but this may lead to ambiguity when m 10 or n 10. Two matrices are equal if their order is the same and when all the corresponding elements in both matrices are the same. The transpose of a matrix is obtained when its rows and columns are interchanged. The transpose of A is denoted by AT and is dened as AT = (ac,r ), for 1 r m and 1 c n. The order of AT is n m. For example: 1 2 AT = 3 4 (8.2) 5 6 Exercise: Dene A in Python and nd AT .

8.2 Special matrices


A row vector is a matrix that has only one row, i.e. m = 1. Similarly, a column vector has n = 1. A square matrix has m = n. A square matrix is a symmetric 45

Chapter 8
matrix when AT = A. For a skew-symmetric matrix AT = A. The elements ar,c of a square matrix A for which r = c together form the principal or main diagonal. The sum of these elements is called the trace. If a square matrix A has ar,c = 0 when r = c then this matrix is called a diagonal matrix. A triangular matrix is a square matrix that has only non-zero values on or on one side of the principal diagonal. An upper triangular matrix has all non-zero elements on the principal diagonal or above it. All elements below its principal diagonal are zero. A lower triangular matrix has all non-zero elements on or below the principal diagonal and only zero elements above it. A diagonal matrix of which all elements ar,c = 1 when r = c is called an unit or identity matrix, which is denoted by I. For example, an identity matrix of size 3: 1 0 0 (8.3) I= 0 1 0 0 0 1 A matrix whose elements all equal zero is called a zero matrix, which, unlike an identity matrix, is not necessarily square. It is usually denoted by O or 0. Zero and identity matrices play the same role as the numbers 0 and 1 in ordinary algebra. Exercise: Use the standard Numpy commands to create a diagonal matrix, a zero matrix and an identity matrix, all of order 3 3.

8.3 Operations
Addition
If two matrices A and B are of the same order, their individual elements can be added. Their sum is dened as A + B = (ar,c + br,c ), for 1 r m and 1 c n. For example: B= 7 9 11 8 10 12 7 9 11 8 10 12 8 12 16 10 14 18 (8.4)

A+B =

1 3 5 2 4 6

(8.5)

Matrix addition is both commutative: A + B = B + A and associative: A + (B + C) = (A + B) + C. For a zero matrix of the same order as A it holds that A + O = O + A = A. 46

Matrices

Subtraction
Similarly, matrices A and B can be subtracted. The difference is dened as A B = (ar,c br,c ), for 1 r m and 1 c n. So: 1 3 5 2 4 6 7 9 11 8 10 12 6 6 6 6 6 6

AB =

(8.6)

Scalar multiplication
Multiplying each element of a matrix A with a scalar number gives the scalar product A = A = (ar,c ), for 1 r m and 1 c n. For example: 2A=2 1 3 5 2 4 6 = 2 6 10 4 8 12 (8.7)

Matrix multiplication
A matrix can also be multiplied with another matrix provided that the left matrix has the same number of rows as the number of columns of the right matrix. The result is called the matrix product. If A has order m n and C has order n p then the product
n

AC =D =
i=1

ar,i ci,c

(8.8)

for 1 r m and 1 c p. The order of D is m p. For example: 7 8 C = 9 10 11 12 1 3 5 2 4 6 7 8 9 10 = 11 12

(8.9)

AC =

1 7 + 3 9 + 5 11 1 8 + 3 10 + 5 12 2 7 + 4 9 + 6 11 2 8 + 4 10 + 6 12

89 98 116 128

(8.10)

Exercise: Dene A and C in Python and calculate AC.

Matrix multiplication is not commutative, i.e. AB = BA, because the dimensions may not agree if the order is reversed. Just like for real numbers, matrix 47

Chapter 8
multiplication is both associative, i.e. (AB)C = A(BC) and distributive, i.e. (A + B)C = AC + BC and C(A + B) = CA + CB. The result of a multiplication of a matrix A by a zero matrix O is A O = O = 0. Multiplying a matrix A with an identity matrix I gives A I = A. For square matrices it holds that A I = I A = A and A O = O A = O. Note that matrix division is undened. So if A C = D then there is no such thing as C = D/A. If A and D are give, C can be found, however, by multiplying D with the so-called inverse of A (A has to be square). Before discussing this concept, it is necessary to introduce another matrix property, the determinant.

8.4 Determinant
Every square matrix has a real number associated with it which is called the determinant. The determinant of matrix A is denoted by det A or sometimes |A|. It is not so easy to explain what a determinant is in words so lets just consider its mathematical denition and start with the determinant of a 2 2 matrix. It is dened as the product of the elements on the principal diagonal minus the product of the elements off the principal diagonal: det a1,1 a1,2 a2,1 a2,2 = a1,1 a2,2 a1,2 a2,1 (8.11)

For square matrices of size 3 and more, a technique called Laplace expansion can be used to determine the determinant. It is based on the expansion of a matrix in minors and cofactors.

Minor
Suppose we have square matrix A. For every element ar,c in A there exists a quantity called minor which is the determinant of the matrix that results when the row r and column c are deleted from the original matrix. For example: 1 1 1 (8.12) A = 2 4 3 3 6 5 then for a1,1 the minor M1,1 is: M1,1 = det 4 3 6 5 = 4 5 3 6 = 2 (8.13)

Cofactor
The cofactor is the minor Mr,c multiplied by (1)r+c : Cr,c = (1)r+c Mr,c 48 (8.14)

Matrices
where Cr,c is the cofactor. The factor (1)r+c effectively determines the sign of the minor depending on its position within the matrix. So if r + c is positive, the sign of the minor does not change. If r+c is negative the sign of the minor reverses. Exercise: Calculate the cofactors C1,1 , C1,2 and C1,3 .

With the minor and cofactor dened, the determinant of a matrix can be found from:
n

det A =
c=1

ar,c Cr,c

(8.15)

for any row r. In words this formula reads: The determinant of a matrix is the sum of the product of the elements in a particular row multiplied by their cofactors. For example: 1 1 1 (8.16) det A = det 2 4 3 = a1,1 C1,1 + a1,2 C1,2 + a1,3 C1,3 3 6 5 Inserting the numbers gives: det A = 1 2 + 1 1 + 1 0 = 1 (8.17)

Exercise: Calculate det A by selecting r = 3.

The same approach can be applied by selecting a particular column rather than a row. The determinant is the calculated from:
m

det A =
r=1

ar,c Cr,c

(8.18)

for any column c. Exercise: Calculate det A by selecting c = 2.

For square matrices of size 4 and higher, the approach is the same. The work involved can be substantial: For a 4 4 matrix, four cofactors must be calculated, each requiring three 2 2 determinants to be calculated, i.e. a total of twelve 2 2 determinants. For any size n the number of 2 2 determinants to be calculated is n!/2. In practice this number can be less if the matrix contains zero elements: Because the cofactor is multiplied with the value of the element, there is no need 49

Chapter 8
to calculate the cofactor if it is multiplied by a zero anyway. Consider a matrix Z which contains 2 zero elements in column c = 2: 6 4 0 2 8 0 2 4 (8.19) Z= 6 0 4 2 18 4 6 2 Expanding along column c = 2 will halve the number of calculations involved since there is no point in calculating the cofactors C2,2 and C3,2 because these are multiplied with z2,2 = 0 and z2,3 = 0. Exercise: Use Python to calculate the determinant of Z.

Transposing a square matrix does not change it determinant, i.e. det A = det AT . If any two rows or columns are interchanged the numerical value of the determinant remains the same but its sign changes. If a matrix is multiplied by a scalar, then the determinant is also multiplied by this scalar, i.e. det A = det A. For matrix multiplication it holds that when A and B are square and of the same order, det AB = det A det B

8.5 Cramers rule


One application of determinants is the solution of a system of linear equations using Cramers rule. Suppose we have a system of 3 linear equations with 3 unknowns: x1 + x2 + x3 = 9 2x1 + 4x2 3x3 = 1 3x1 + 6x2 5x3 = 0 which can be written in matrix form as (cf. Equation 8.8): 1 1 1 x1 9 2 4 3 x2 = 1 x3 3 6 5 0 or, with A, X and R representing the respective matrices: AX = R Cramers rule states that the elements of X can be found from: xr = 50 det Ac det A (8.23) (8.22)

(8.20)

(8.21)

Matrices
for 1 r m and c = r. Ac is the matrix that is obtained when column c in A is replaced by column vector R. For example, to nd x1 , the rst step is to calculate det A1 , which is: 9 1 1 (8.24) det A1 = det 1 4 3 = 7 0 6 5

The determinant of A was calculated earlier (Equation 8.17). Inserting these values into Equation 8.23 gives: 7 x1 = =7 (8.25) 1

Exercise: Apply Cramers rule to nd x2 and x3 .

The determinant of a matrix can be zero if an entire row is zero or if a row (or column) is a multiple of another row (or column). This also includes rows (or columns) which are the same (i.e. the multiplier is 1). If the determinant of a matrix is zero, it is called a singular matrix. Since det A appears in the denominator of Equation 8.23, Cramers rule can not be applied when a matrix is singular. Several conditions may apply depending on the values of the determinants of A and R. These are summarized in table 8.1. A hydrological application of Cramers rule is in the derivation of the nite element approximation of the groundwater equation.

8.6 Inverse of a matrix


The inverse of a square matrix A is denoted by A1 and is dened by AA1 = I. The inverse can be used to solve a system of linear equations. The solution of X in Equation 8.22 is: X = A1 R (8.26) For a square matrix A the inverse can be found from: A1 = CT det A (8.27)

Table 8.1: Possible solutions for systems of linear equations depending on the values of det A and det R. det A = 0 det A = 0 det R = 0 unique solution innite number of solutions det R = 0 X = 0 (trivial solution) innite number of solutions if det Ac = 0, 1 c m 51

Chapter 8
in which C is a matrix of cofactors of A and its transpose C T is the so-called adjugate of A. From Equation 8.27 it follows that the inverse can only exist if det A = 0. If this is the case then A is called a non-singular matrix (as opposed to a singular matrix). For matrix A in Equation 8.12, C is: 2 1 0 (8.28) C = 11 8 3 7 5 2 so: 2 11 7 2 11 7 1 1 1 8 5 = 1 8 5 = CT = det A 1 0 3 2 0 3 2

A1

(8.29)

Exercise: Insert A1 and R (Equation 8.21) into Equation 8.26 to nd X.

Exercise: Express the system of linear equations dened by Equation 7.15 in matrix form, i.e., Ah = R. Find h by calculating A1 and applying Equation 8.26. Obviously, calculating the inverse of a matrix by hand can be a lot of work and mistakes are easily made. Computers are much better at these sorts of calculations than humans. Exercise: Use Python to calculate A1 and A1 R = X.

52

References
Chiang, W. H., 2005. 3D-Groundwater modeling with PMWIN. Springer, Berlin Heidelberg, Germany. Wang, H. F., Anderson, M. P. 1982. Introduction to Groundwater Modeling: Finite Difference and Finite Element Methods. W. H. Freeman and Co, Gordonsville, Virginia, USA.

53

You might also like