CPT3701 - Study Guide
CPT3701 - Study Guide
SCHOOL OF ENGINEERING
CIVIL AND CHEMICAL ENGINEERING
CHEMICAL ENGINEERING
Prof B Patel
University of South Africa
Pretoria
Open Rubric
© 2019 University of South Africa
CPT3701/1/2020
MSWord
Learning unit 1: Introduction to computational techniques
1.1 Introduction
The use of computers in engineering has become increasingly important since computers are
accurate, fast and can accomplish many tasks easily. Can you recall the number of times you left an
answer in Reactor Technology or Thermodynamics incomplete simply because the mathematics
became too complicated or tedious? A considerable amount of time and thinking is required to
complete calculations manually. Using a computational technique can greatly reduce the amount of
time spent on tedious calculations. This does not mean that you can simply feed questions into a
computer program and expect it to provide you with the necessary answers. The aim of this learning
unit is to equip you with the language that will enable you to use the Octave software and to point
you in the right direction as far as documentation and resources are concerned.
Numerical simulation involves defining a problem for a digital computer. This can be achieved in two
ways, namely,
• using a programming language and encoding every step used for numerical computation
• using a specialised software framework that presents a general framework to define a
mathematical problem that the computer understands
The first approach is referred to as scientific computation. Using the programming language, a
generalised scheme of numerical computing is defined for a scientific problem on the basis of
fundamentals. In this way, a library of functions is developed, which can be used as required.
Engineers, on the other hand, base mathematical models on experimental data for specific systems.
The focus is shifted from efficient code writing to problem definition, and, as a result, programs such
as Octave and Matlab are known as the languages of engineering.
Analytical schemes that are used to solve mathematical problems involve deriving equations
describing a system using relationships between different parameters and then solving these
equations by either using invented functions or inventing new functions that fit the purpose. A
numerical scheme also involves describing the system using a relationship between various
parameters and functions, but deriving a solution is markedly different since it involves an iterative
technique. This is demonstrated by means of the following example:
𝑓𝑓(𝑥𝑥) = 𝑥𝑥 + 3
1
We find the analytical solution to the equation by setting 𝑥𝑥 + 3 = 0. To satisfy this, we need to add
−3 to both sides and obtain 𝑥𝑥 = −3.
If we are obtaining a numerical solution, then we use the bisection method, which involves guessing
the initial value and using an iterative technique to determine the solution:
At this point you may ask: if we have an analytical solution, why do we need to go through the
tedious steps of determining a numerical solution? The reason for this is that, sometimes, it may not
be so simple to obtain an analytical solution. Take, for example, complex systems involving
differentiation and integration – these may become difficult to solve using analytical solutions and,
therefore, numerical schemes need to be defined. Octave was developed primarily to solve chemical
engineering and, in particular, chemical reactor design problems. This module is aimed at
introducing you to the use of Octave to solve engineering problems. Should you be interested, you
can read more about the history of Octave by accessing the article titled “Octave: past, present and
future” at https://pdfs.semanticscholar.org/c3c5/1ceefc387f4ba5db330e3394360f1eea595f.pdf.
GNU Octave can be downloaded on different operating systems, such as macOS (previously Mac OS
X) and Windows. To download Octave on a Windows operating system, visit the URL
https://www.gnu.org/software/octave/. Should you have difficulty following the installation
prompts, watch the introductory clip, “Octave tutorial #1: Introduction and setup” (3.35), at
https://youtu.be/X0xLTKRWPgo or visit the wiki “Octave for Microsoft Windows” at
https://wiki.octave.org/Octave_for_Microsoft_Windows.
If you use a different operating system, installation instructions are available at the wiki “GNU
Octave Wiki” at https://wiki.octave.org/GNU_Octave_Wiki. Another option is to use Octave without
installing it on your system and to use it live on the web. This is particularly useful if you do not have
access to your own computer and are using a public computer in a library. To use Octave Online, go
to the URL https://octave-online.net/. You will be required to create a login account first, and the
programs you create online may be limited by the server storage available.
Figure 1.1 shows a screenshot of the Octave graphic user interface (GUI).
2
Current Directory allows you to view and interact with files
in the current folder.
3
The left-hand panel has three panels: File Browser, Workspace and Command History. A brief
explanation of each is given below:
• File Browser allows you to browse through files in a working directory. A file can be opened by
clicking on the .m file; it will run in the Editor window.
• Workspace is where variable names, values and associated properties are stored. These will be
discussed in later chapters.
• Commands used in an Octave session are stored in the Command History directory. These
commands can be executed using the Octave command prompt.
The right-hand panel has the Command Window, which reads input prompts one line at a time. The
Editor window is activated by clicking the Editor tab at the bottom of the window and is used to
write the .m script file, which can then be executed. The Documentation window can be used to
read documentation and provides help for learning more about commands.
In an interactive session in Octave, you have to input a command, which is then executed as soon as
you press the Enter key. The interactive shell is known as REPL because it
An interactive session is useful since it allows for easy debugging. REPL allows for writing code,
analysing results and continuing until a final result is computed.
Getting help in Octave is also easy. For example, typing help in the Octave GUI yields the following
(refer to figure 1.2):
4
Figure 1.2: Using the Help function
You are given usage instructions and directed to the Documentation window, where you can search
for topics in respect of which help is needed using the manual index. For example, typing doc will
direct you to the Documentation window, as shown in figure 1.3:
5
Help function in the top tab
Alternatively, you can use Help at the main menu bar on the left-hand side of the window (the fifth
option is Help). A sub-menu under Help has the Documentation bar.
How can you obtain a clear screen in order to explore the Octave session further? Type clc to clear
the screen. You can learn more about using this command by typing in help clc or using the
documentation that is presented when you type in doc clc. Activity 1.1 will introduce you to basic
operations in Octave in order to familiarise you with the interface.
Activity 1.1
• >>Ans+4 <Enter>
6
• >>15/5 <Enter>
• >>Ans*4 <Enter>
• >>20-10 <Enter>
• >>2^2 <Enter>
Note: >> is the command prompt in Octave and <Enter> indicates that you must press the
Enter key on the keyboard.
3. Use the Help function to look up how the command disp works: >>help disp.
4. Use the Help function to look up how the command input works: >>help input.
5. Use clc to clear the screen.
Feedback: Figure 1.4 shows a screenshot of the output for activity 1.1.
7
Figure 1.4: Output for activity 1.1
Apart from working on Octave REPL, you can write multiline programs using the built-in text editor in
Octave and run the program. Let’s see how this works by writing a program, which we will call
helloworld.m. The program is created in Editor by clicking on the lowermost part of the
Command Window, which has an option named Editor. This opens a blank Editor window in which
the helloworld.m code can be written manually. Recall from activity 1.1 the use of the disp
command. In the Editor window, type in disp ("Hello World!"). You can then save the file by
clicking on Save File and Run, where you will be prompted to name the file. Note that all Octave
script files are saved with an .m extension. You can open the existing file by navigating to the
appropriate folder and choosing the file in the explorer. Figure 1.5 shows the Editor with the file
helloworld.m.
8
Save File and Run
Activity 1.2
9
f. To clear the screen, type in clc.
10
Figure 1.7: Command Window running pickAnumber
This now brings us to the concept of a variable and the workspace. The workspace is the abstract
space reserved for objects in an Octave session (refer to figure 1.7 – the red border indicates the
workspace). When running pickAnumber.m, you will notice that the first number is saved as a=3
and b=3. The ans displayed in the workspace is also a variable (because it can store a variety of
values) and it stores the last executed values as a result of evaluating the expression at the Octave
command prompt. This means that should you re-run pickAnumber.m with different first and
second inputs, the values of a, b and ans will change in the workspace to the last executed values.
In order to clear the workspace of the variables, you need to type in clear after the command
prompt. This will clear all stored variables. Remember, typing in clc will only clear the screen and
not the stored variables.
11
Activity 1.3
1. How do you think Octave will handle 1/0 and 0/1? Try it.
2. Enter in the Octave session >>a = 3. Notice what happens in the workspace.
3. Now type in >>a = a + 1. What is the answer? What value is now assigned to variable a?
4. Type in >>b = a + 1. Notice how a new variable is defined in the workspace.
5. Now type in >>c = 3;. Did you notice the function of the semicolon? The output is not
displayed at the execution of the command but the variable c is defined in the workspace.
6. Give some values to variables x and y. Write other statements to sum, difference, product and
quotient of x and y.
1.8 Conclusion
Learning unit 1 introduced you to the basics of Octave and was aimed at familiarising you with the
interface of Octave. Before you start with learning unit 2, you should be able to recognise the
interface, anatomy and basic language of Octave and to execute basic commands in Octave. You
were directed to documentation and help available to allow you to explore Octave sessions further.
Moreover, you were shown how to create and run scripts. It is important that you work alongside
the study guide when you use the Octave program in order to gain a thorough understanding of the
programming language.
12
Learning unit 2: Octave and mathematics
2.1 Introduction
The first learning unit provided you with a brief introduction to programming with Octave. At this
point you should be able to recognise the interface, anatomy and basic language of Octave and be
able to execute basic commands in Octave. You should also be familiar with the documentation and
help available for further exploration of Octave sessions.
Learning unit 2 expands on the concepts introduced in learning unit 1, focusing on the execution of
mathematical expressions in Octave and the use of matrices to simplify complex calculations.
Octave is a good tool for solving mathematical expressions numerically. This means the Octave
program has the ability to understand mathematical structures and symbols like addition,
subtraction, multiplication and division and to evaluate them. In its simplest form, Octave functions
like a calculator to execute mathematical expressions. Activity 2.1 illustrates the use of Octave as a
calculator, which you may already be familiar with from learning unit 1, activity 1.1.
Activity 2.1
• >>2 + 7 <Enter>
• >>2.0 + 7.0 <Enter>
• >>2.2 + 7.3 <Enter>
• >>3 – 5 <Enter>
• >>3.0 * 5 <Enter>
• >>1/3 <Enter>
• >>format long
• >>1/3
• >>format short
• >>1/3
13
Feedback: Figure 2.1 provides a screenshot of the executed commands under Command
Window.
As you can see from figure 2.1, when a command is entered at the Octave REPL command prompt
>>, it is executed and an answer is displayed in the next line as ans =. As you will recall from
learning unit 1, ans is a global variable that stores the value of the last executed expression. The
commands written in Octave REPL are called expressions and are evaluated by REPL. The behaviour
of this expression execution must be well defined to get a meaningful answer. Notice that 2.0 +
7.0 is displayed as an integer, 9, but when 2.2 + 7.3 is evaluated, the answer is displayed as
9.5000. To display more numbers in the result, you can use the format long command. Octave
works with the format short command by default. Format short shortens the number of
significant figures while format long lengthens it (refer to figure 2.1). The format short e and
format long e commands print the result in scientific notation, as shown in figure 2.2.
14
Figure 2.2: Use of scientific notation
From figure 2.2 you can see that the power of 10 is separated by either a lowercase e or an
uppercase E as we have defined it. The short command sets the significant figures to five while the
long command sets it to 15.
A number of constants are predefined in Octave. These include pi, e (Euler’s number), i and j
(imaginary numbers), inf (infinity) and NaN (“not a number”, which results from undefined
operations such as Inf/Inf). Refer to figure 2.3, which demonstrates the input and output of the
predefined constants.
15
Figure 2.3: Predefined constants and engineering format
Note that if format short eng or format long eng is chosen, the output is displayed as an
engineering format, as can be seen from the last four lines of code in figure 2.3.
So, how would we compute complex numbers in Octave? It is important to understand the method
of defining complex numbers in Octave since these numbers provide an enriching picture by
extending a one-dimensional number line into a two-dimensional complex plane. Computations
involving complex numbers can be found in many branches of science and engineering. In Octave,
complex numbers are defined with ease since most of their functions are present and flexible. A
complex number can be defined in two ways, namely, by means of the built-in complex() function
and straight away as a+bi or a+bj. (Refer to figure 2.4.)
16
Figure 2.4: Complex numbers in Octave
Figure 2.5 gives an overview of the mathematical functions mentioned above. To learn more,
browse the Arithmetic section under Documentation in Octave. Should you have forgotten how to
access Documentation in Octave, refer back to figure 1.1 and section 1.5 in learning unit 1.
17
Figure 2.5: Common mathematical functions in Octave
Activity 2.2
1. Use the Help function to look up how the command sqrt works: >>help sqrt.
2. Locate the Arithmetic file under Documentation and find a mathematical function not listed
above. Use the Help function to determine how to use it in Octave.
3. Evaluate the following in Octave:
• >>sqrt (4)
• >>log (2)
• >>sin(180)
• �𝑠𝑠𝑠𝑠𝑠𝑠(10)2 + 𝑐𝑐𝑐𝑐𝑐𝑐(10)2 >>sqrt(((sin(10))^2)+(cos(10)^2)
sin (10)
• �cos (10)
>>sin(10)/sqrt(cos(10))
• >>abs(sin(10))
• >>(2+3i)*(2-3i)
• >>(2+3i)+(3+2i)
18
Up to this point, you have been feeding numbers into Octave REPL with on-the-spot evaluation.
Alternatively, you can designate a memory location where values are stored. This memory location
can be known by a name for ease of usage. Such a programming construct is known as a variable. To
store values temporarily, you use variables that store the values in a particular memory location and
tag them with a symbol or a set of symbols, for example:
Let a = 5, b = 10 and c = 15. If we compute a + b +c in Octave, what will the output be?
From figure 2.6 you can see that the variables are stored in Workspace and the = sign works as an
assignment operator that assigns a value to a variable. You could also use the ; operator to suppress
the results on-screen, for example, >> a = 5; b=10; c = 15;.
Up to this point, we have only considered storing one value as a variable. In order to store more than
one variable, we can store them as an ordered set of variables. Ordered sets of elements are known
as arrays in Octave. An array can have any data type: integers, floating point numbers and complex
numbers. A matrix is an array of numbers that are enclosed in square brackets, that is, [ ]. The
different rows are separated by semicolons (;) and in each row the entries are separated by commas
(,) or spaces.
Recall from mathematics: a column vector is a 𝑛𝑛 × 1 matrix and a row vector is a 1 × 𝑛𝑛 matrix. These
are the dimensions of a matrix that tell us about the size of a matrix. To revise matrices, watch the
Khan Academy’s video titled “Introduction to matrices” (11.50) at this URL:
https://youtu.be/xyAuNHPsq-g . Should bandwidth be an issue, try to access the notes to the video
at the website, https://www.khanacademy.org/math/precalculus/precalc-matrices/intro-to-
matrices/a/intro-to-matrices. Bill Shillito’s video titled “How to organize, add and multiply matrices”
19
(4.40) also gives a very useful recap of the addition, subtraction and multiplication of matrices. You
can find the video at https://youtu.be/kqWCwwyeE6k.
Activity 2.3
It is also important to remember that a vector is a list that has one dimension; it is a row of data. An
array is a list that is arranged in multiple dimensions. There are different ways to create vectors in
Octave, as described below.
• To create a row vector with known numbers, just type in the numbers separated by commas
or spaces, as in this example:
• To create a column vector, use the transpose sign or separate the entries by a semicolon, as
in this example:
• To create a matrix using rows and columns, for example, a 3 × 3 matrix, define it as follows:
20
Two coordinates can be added and subtracted in Octave, as shown below.
Suppose we have a matrix (1, 3, 9) and (2, -4, 10), addition and subtraction will be as follows:
We could also divide or multiply a matrix by a real number. For example, define matrix a = (2, 4, 6)
and multiply/divide by 2:
Activity 2.4
21
6. What would the following give?
>>y=[1 3 7];
>>y=[a 0 -1]
7. Work out what matrix Y would look like if we have
>>X=[3 4 5];
>>Y=[X; 6 7 8];
8. The colon notation can also be used in the definition of multirow matrices. What would the
following give?
>>Z=[1:3; 8:-2:4]
The colon (:) tells Octave to create a (row) vector of numbers, starting from the first number and
counting up to (and including) the second number, incrementing by 1 each time. Should the
increment not be 1, we would need to define the increment, that is to say, the number in the
centre of 8:-2: 4 is the increment step. In this case, we have -2, which is counting down until
the end number.
9. Enter the following:
>>clear y
>> clear all
Notice what happens to the variables in the workspace.
Table 2.1 provides a summary of vector and creation functions. To recap: a vector is a matrix where
there is only one row and one column – a row /column vector. Numbers are considered to be a
special case of matrix in Octave in that they are considered to be 1 × 1 matrices. Understanding how
to build and manipulate matrices is therefore important in Octave. To find out more about the
functions listed in table 2.1, refer to the Octave Help function. Activity 2.5 will demonstrate the use
of these functions.
linspace(x1,x2,N) Create a row vector of N elements evenly spaced between x1 and x2.
22
Activity 2.5
23
2.7 Operations on arrays and vectors
Operations on arrays and vectors are described in this section. You will learn more about matrix
multiplication and division in Octave. Matrices are a useful tool in linear algebra and can easily
represent data as grids of numbers. As we move further into the learning units, you will find matrix
operations increasingly challenging. This section therefore lays an important foundation.
Operations on arrays can be done by operating on two or more arrays as well as element-wise
operations. The addition (+) and subtraction (-) operators are defined to work on matrices as well as
scalars, as in section 2.5. Multiplication and division are, however, different. The multiplication (*)
symbol is used for matrix multiplication. Recall from mathematics: a 𝑎𝑎 × 𝑏𝑏 matrix can only be
multiplied by a 𝑏𝑏 × 𝑐𝑐 matrix, which would result in a 𝑎𝑎 × 𝑐𝑐 matrix. If we define a = [1 2 3] and b = [5
6 2], we are not able to multiply matrices a*b since these do not have the correct dimensions for
matrix multiplication. However, if b is transposed (b’), then we have a (1 × 3) matrix and b’ (3 × 1)
and we are able to multiply the two matrices. To perform element-wise multiplication, (.*) is used.
Similarly, to perform element-wise addition, we would use (.+), subtraction( .-) and division (./).
Remember that element-by-element operations can only be carried out on matrices of the same
dimensions. This aspect is demonstrated more clearly in the following Octave snippet:
24
Should you have difficulty understanding matrix multiplication, watch the video clip titled “Matrix
multiplication in Octave” (8.24) at this URL: https://youtu.be/kkzpHMvipUM.
Matrix division is slightly more complicated than matrix multiplication. To perform matrix division
element wise, you would need to use ./ since the symbols / and \ are used for matrix division.
Division for matrices involves matrix inversion. Recall from mathematics: division of one matrix by
another is undefined. However, you are able to solve the problem A*B-1. In Octave, this could be
achieved by using the inv() function. This will be valid if the input matrix is a square matrix, that is,
if it has an equal number of rows in each dimension. The function issquare() is used to check if
the matrix is a square matrix. Consider this example:
13 26 7 4 2 4 5
𝐴𝐴 = � � 𝑎𝑎𝑎𝑎𝑎𝑎 𝐵𝐵 = � � 𝑎𝑎𝑎𝑎𝑎𝑎 𝑥𝑥 = � �
39 13 2 3 3 6 9
From figure 2.9 we can see that A and B are both square matrices but x is not; we see that a matrix is
square if 1 is returned and not square if 0 is returned. Therefore, if we compute A/x or A*inv(x),
an error is returned:
25
Figure 2.10: Division of a square matrix
An identity matrix is obtained when the inverse of a matrix is multiplied by itself. This would mean
that it has 1 as its elements in the diagonal and 0 everywhere else, as in figure 2.11:
26
Figure 2.11: Identity matrix
From figure 2.11 we can see that matrix a returns an identity matrix with 1s and 0s but matrix A
results in very small numbers instead of 0. These numbers can be approximated to be very close to
0; as a result, it is an approximation of an identity matrix. The determinant of an identity matrix is,
therefore, 1. Determinants are useful because they tell us whether or not a matrix can be inverted,
in other words, if the determinant of a matrix is zero, the matrix cannot be inverted. This is
illustrated in figure 2.12, where we have matrices A and B:
3 2 2 4
𝐴𝐴 = � � 𝑎𝑎𝑎𝑎𝑎𝑎 𝐵𝐵 = � �
6 4 −3 1
27
Figure 2.12: Determinant of a matrix
Should you struggle to understand the mathematical concepts, refresh your memory by watching
the video clips titled “Matrix multiplication (part 1)” (13.40) (https://youtu.be/aKhhYguY0DQ) and
“Dividing matrices by using inverses” (5.30) (https://youtu.be/0-gFvk22xSQ).
Activity 2.6
1. Read the Wikibooks notes on vectors and matrices in Octave programming at the following link:
https://en.wikibooks.org/wiki/Octave_Programming_Tutorial/Vectors_and_matrices.
2. We have the following matrices:
𝑋𝑋 = [2 4 6] 𝑎𝑎𝑎𝑎𝑎𝑎 𝑌𝑌 = [3 4 5]
Compute in Octave:
a. >>X+Y
28
b. >>X*Y Why is an error obtained?
c. >>X.*Y Does this give an error, too? What does the .* mean?
d. >>X*Y’ What can we say about Y’?
e. What happens when we take the log(X) >>log(X)?
f. >>X/Y Is Y/X the same as X/Y?
g. >>X./Y What does ./ mean?
3. We have the following matrices:
3 1 6
𝐴𝐴 = [1 4] 𝑎𝑎𝑎𝑎𝑎𝑎 𝐵𝐵 = � �
5 2 7
a. Compute 2AB in Octave.
b. Given A, explain the output of A.^2. How does this differ form A^2?
c. Use the command issquare() to determine if A and B are square matrices.
4. We have matrix Z:
2 1 8
𝑍𝑍 = �7 3 9�
5 6 9
a. Is matrix Z a square matrix?
b. Can matrix Z be inverted?
c. What is the determinant t of matrix Z?
d. Compute in Octave >>Z*inv(Z)Do you obtain an identity matrix?
e. Compute in Octave >>det(Z*inv(Z)) Do you obtain a 1 or 0?
A set of linear equations can easily be solved in Octave using arrays. Let us take a set of linear
equations as an example:
𝑥𝑥 − 2𝑦𝑦 − 𝑧𝑧 = 6
−𝑥𝑥 − 𝑦𝑦 + 𝑧𝑧 = −1
2𝑥𝑥 + 3𝑦𝑦 − 𝑧𝑧 = 8
We need to solve for 𝑥𝑥, 𝑦𝑦 and 𝑧𝑧 for the equations to hold true. As a first step, we should rewrite
these equations in matrix format:
1 −2 1 𝑥𝑥 6
�−1 −1 1 � × �𝑦𝑦� = �−1�
2 3 −1 𝑧𝑧 8
Define:
1 −2 1 𝑥𝑥 6
𝐴𝐴 = �−1 −1 1 � , 𝑋𝑋 = �𝑦𝑦� 𝑎𝑎𝑎𝑎𝑎𝑎 𝐵𝐵 = �−1�
2 3 −1 𝑧𝑧 8
𝐴𝐴𝐴𝐴 = 𝐵𝐵
29
This is equivalent to:
𝑥𝑥 = 𝑖𝑖𝑖𝑖𝑖𝑖(𝐴𝐴) ∗ 𝐵𝐵
To avoid computing the inverse of 𝐴𝐴 directly, use the left divisor (\). Therefore:
𝑥𝑥 = 𝐴𝐴\𝐵𝐵
Activity 2.7
30
2𝑥𝑥 + 3𝑦𝑦 + 𝑧𝑧 = 7
3. Solve the following set of linear equations:
𝑥𝑥 + 𝑦𝑦 + 𝑧𝑧 = 6
𝑥𝑥 − 𝑦𝑦 + 𝑧𝑧 = 2
𝑥𝑥 + 2𝑦𝑦 − 𝑧𝑧 = 2
2.9 Conclusion
Octave provides an easy means of performing mathematical calculations owing to its many built-in
functions. These functions allow the user to save time when defining a problem. Furthermore,
Octave provides a suitable platform for performing matrix calculations with ease. Learning unit 2
was aimed at providing you with an introduction to mathematics and Octave. The functions
introduced in this learning unit are summarised in table 2.2.
31
Learning unit 3: Plots and curve fitting
3.1 Introduction
The first two learning units provided you with an introduction to programming with Octave and
executing mathematical expressions in Octave. At this point you should understand the interface
and anatomy of Octave, how to execute mathematical expressions in Octave and how to use
matrices to simplify complex calculations.
Learning unit 3 introduces the creation of plots in order to provide quality visuals from output data.
This is an important aspect because without visualisation, numerical data are difficult to interpret.
Producing quality images of complex plots that provide a meaningful analysis of numerical results
represents a key challenge for both scientists and engineers.
Octave provides various plotting functions in both 2D format and 3D format. Additional
functionalities allow a plot to be labelled with titles, as well as the creation of labelled axes, grids,
labels for data, equations and other information that relates to the plot. In this section we will
explore the plotting of graphs in Octave by means of a few examples. In addition to studying this
section, you could watch the video clip titled “Octave tutorial #4 – plotting data” (25.47) at this URL:
https://youtu.be/B29EftnPbWo.
Graphs are drawn in 2D using the plot statement. In its simplest form, it takes a single vector
argument, as in plot(y). If y is a matrix, then its columns are plotted against element indexes.
More commonly for 2D plots, you would need to create data to plot on the x- and y-axes. Let us
consider a function, y=sin(x). The command plot() in Octave can only display points and
straight-line connections between them. Therefore, you have to compute the coordinates of the
points first and then generate the graphics. It is important to remember that x and y have to be
vectors of the same length, as discussed in learning unit 2 (refer to section 2.5). Create the x data as
follows: x = 0:0.1:7. This defines the x data points from 0 to 7 at intervals of 0.1. Refer to figure 3.1
for the execution of the code.
32
Figure 3.1: Plot (x,y) for the function y=sin(x)
3.3.2 Labels
In Octave, a graph can be edited by inserting text to create headings, to label the axes and to
autoscale the plot window. These functionalities are found at the top of the Figure window (circled
in figure 3.1) or can be programmed, as explained below:
title (‘text’)
Writes the text as a title on top of the graph.
xlabel(‘horizontal’)
Labels the x-axis.
ylabel(‘vertical’)
Labels the y-axis.
33
Activity 3.1
1. Draw a line between the point with Cartesian coordinates (0,1) and (4,3):
>>plot([0 4], [1 3])
In other words, [0,4] are the x coordinates of two points and [1 3] are the y coordinates.
2. x and y are vectors of the same length.
>>x=0:pi/40:4.*pi;
>>y=sin(x);
>>plot(x,y)
3. Add a grid to the plot:
>>grid on
4. Create a title for the graph:
>>title (‘y=sin(x)’)
There are different ways of plotting multiple plots on the same axes. The simplest way is to use hold
or hold on to keep the current plot on the axes. The multiple plots will be drawn on the same
figure until hold off or hold is used.
A second way to plot multiple plots on the same axes is to use the form
Plot (x,y…)
where x and y may be either matrices, or where one is a matrix and the other a vector. In this case,
we would require a different colour to be used for each.
One can choose the line styles, the colour or the point style, as summarised in table 3.1.
m magenta
c cyan
w white
For example, ‘-*b’ means that we will plot a solid line using star pointers in blue, which is
demonstrated below.
34
The code below shows an example leading to figure 3.2, where we plot more than one graph on the
same figure: x = 0:0.1:7, y=sin(x) and y2=cos(x).*exp(-x/3).
Recall from learning unit 2 that in element-wise operations, a .dot is placed before the operator.
Therefore, the operators become .+, .-, .* and ./, as shown in line 3 of the code indicated
above.
Line 4 of the code executes multiple plots on the same axes: x and y are plotted using a solid line
joining the red stars* while the second plot x and y2 is plotted using a plus+, with no line joining the
points, in the colour black.
Should you have difficulty grasping multiple plots on the same axes, access the URL
https://sysplay.in/blog/mathematics/2014/01/figures-graphs-and-plots-in-octave/ for additional
35
examples. You could also access a video tutorial titled “Octave tutorial #4 – plotting data” (25.47) at
this link: https://youtu.be/B29EftnPbWo.
The subplot (m,n,p) function is used to plot multiple plots on the same figure separately.
subplot (m,n,p) divides the Figure window into 𝑚𝑚 × 𝑛𝑛 small sets of axes and selects the 𝑝𝑝th set
for the current plot. Therefore, subplot (2,2,4) will plot a graph on the second row in the
second column and in the fourth index. So, for example, the following statements lead to figure 3.3:
>>x=linspace(1,100,100);
>>y1=x.^2.0;
>>y2=log(x);
>>y3=sin(x);
>>y4=log10(x);
>>subplot(2,2,1), plot(x,y1)
>>subplot(2,2,2), plot(x,y2)
>>subplot(2,2,3), plot(x,y3)
>>subplot(2,2,4), plot(x,y4)
36
The command subplot(1,1,1) goes back to a single set of axes in a figure. Use help subplot to
see more information on the function and its dimensions.
Octave also has a built-in area() function, which results in a plot that shades the area under the
curve. To do this, first define a variable x that has 100 linearly-spaced data points (use the function
linspace())and y=x2. If you need to read up on how linspace works, use the Help function,
>>help linspace. The code that generates figure 3.4 is as follows:
Bar charts may be old fashioned and not used often in engineering but are effective in visualising
statistical information. Bar charts will be introduced briefly here; should you wish to explore the
function further, consult the documentation available in Octave and use the Help function. Figures
3.5–3.7 demonstrate the code that is used to generate the relevant plots in the corresponding
figures.
37
Figure 3.5: Generating a bar chart in Octave
38
Figure 3.6: Generating a horizontal bar chart in Octave
A histogram can be plotted using the hist() function. Let’s look at the behaviour of a normalised
distribution of random numbers generated by the randn() function, as in figure 3.7. The following
Octave code produces uniformly distributed random numbers:
39
Figure 3.7: Histogram plot showing a normalised distribution of random numbers
Activity 3.2
40
>>x=0:pi/40:4.*pi;
>>y1=sin(x);
>>y2=cos(x);
>>subplot(1,2,1), plot(x,y1)
>>subplot(1,2,2), plot(x,y2)
8. What happens if we change lines 4 and 5 of the code to the following?
>>subplot(2,1,1), plot(x,y1)
>>subplot(2,1,2), plot(x,y2)
Recall from mathematics: the point (𝑥𝑥, 𝑦𝑦) in Cartesian coordinates may be represented by the point
(𝜃𝜃, 𝑟𝑟) in polar coordinates, where
𝑥𝑥 = 𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟(𝜃𝜃)
𝑦𝑦 = 𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟(𝜃𝜃)
The function polar (θ,r) generates a polar plot with angles in θ and magnitude in r. Take, for
example,
>>x=0:pi/40:2.*pi;
>>polar (x,sin(2.*x))
41
Figure 3.8: Polar plot of θ vs sin (θ)
There are three different options for plotting graphs on a logarithmic scale in Octave:
>>y=0:2:10;
>>x=exp(-y/2);
>>semilogx(x,y)
>>grid on
42
Figure 3.9: A logarithmic plot
Activity 3.3
43
3.4 Plotting 3D graphs in Octave
Octave has various functions for plotting 3D graphs. This section will briefly describe some of the
functions used for 3D plotting. Should you wish to learn more about these functions, access them
using the Octave documentation. In addition, a detailed video clip titled “Complex plots in Octave”
(16.26) is available at this URL: https://youtu.be/mSqGYzofG3U.
The function plot3 is a 3D version of the plot function. The command plot3 (x, y, z) draws a
2D projection of a line in a 3D space. For example,
generates eight random points in a 3D space and joins them with lines, as shown in figure 3.10.
When plotting graphs in 3D, we need evenly spaced 𝑥𝑥 and 𝑦𝑦 values, spaced on a grid where each
value function 𝑧𝑧 is taken of a point (𝑥𝑥, 𝑦𝑦) on the grid. There are different variations of the mesh
function, as outlined in table 3.2 below. Use the Help function to read up about each function in
more detail. A brief summary of each function is given in the table below.
44
Table 3.2: mesh surfaces
Function Description
Octave plots a wireframe mesh using rectangles
mesh( ) mesh (x,y,z).
meshgrid ( ) is used to produce input for a 2D or 3D function
meshgrid( ) that will be plotted.
See help meshgrid for further details.
See the example below for a detailed explanation.
meshc( ) generates a 3D rectangular mesh, including a contour
meshc( ) plot. Matrix equation needs to be defined.
surf( ) generates a surface plot whereby a wire mesh surface is
surf( ) filled up with small tiles.
contour( ) plots contours of a matrix.
contour( ) See help contour for an example.
The following example demonstrates the use of mesh () and meshgrid ()(refer to figure 3.11):
>>x=y=linspace(-2,2,30);
>>[xx,yy]=meshgrid(x,y; %given x and y matrices, returns matrices xx
and yy corresponding to a full 2D grid
>>z=xx.^2+yy.^2;
>>mesh(xx,yy,4-z)
>>xlabel (‘x-axis’), ylable (‘y-axis’), zlable(‘z-axis’)
45
Should you have difficulty visualising the example in Octave, watch the video tutorial titled “Octave
tutorial 34 – miscellaneous topic (meshgrid function)” (4.49), which demonstrates the use of
meshgrid( ), at this URL: https://youtu.be/P9tPBVLIRGo.
Activity 3.4
1. Given 𝑧𝑧 = 𝑥𝑥 2 − 𝑦𝑦 2 , plot the 3D surface for x=y with 10 linearly spaced data points from -2 to
2:
>>x=y=linspace(-2,2,10);
>>[xx,yy]=meshgrid(x,y)
>>z=xx.^2-yy.^2
>>mesh(xx,yy,z)
2. Draw the surface in Q1 above using a finer mesh, that is, use 30–50 linearly spaced data
points:
>>x=y=linspace(-2,2,30);
>>[xx,yy]=meshgrid(x,y)
>>z=xx.^2-yy.^2
>>mesh(xx,yy,z)
3. Try using the functions surf() and meshc() to see how the above surfaces change.
4. Plot the function 𝑐𝑐 = �𝑥𝑥 2 + 𝑦𝑦 2 for the x=y with 45 linearly spaced data points from -8 to 8.
In this section you will learn how to create and save files in different formats. By creating files for
storing data, you will not have to retype data every time you open or close Octave. Whenever you
close Octave, all the data are lost. If you create files, you will also be able to access and change the
contents of a file with a few commands, as well as move data to a new computer easily.
As you will recall from learning unit 1, Current Directory allows you to view and interact with files in
the current directory. File Browser allows you to browse through files in a working directory. A file
can be opened by clicking on the .m file; it will run in the Editor window. To access the files saved in
learning unit 1, first check if the correct directory is available to load the files – by typing >>pwd, the
path of the present working directory will be displayed, as shown in figure 3.12.
The command mkdir octave creates a new directory named octave, which is circled in figure 3.13.
The importance of defining a clear directory to store files will become clearer as we progress
through the unit.
46
Figure 3.12: File path
In Octave there are different options available for reading and writing information to a file:
Table 3.3 summarises the main commands used to read and write data to a file. Not all of these
commands will be discussed in this section. You can use the Help function to read more about
commands in cases where examples have not been provided.
47
Table 3.3: Reading and writing data to files
load() Load Octave variables.
save() Save Octave variables.
dlmread() Read all data from a file.
dlmwrite() Write data to a file.
textread()
strread() Read data from a file.
Read data from a string.
fopen() Open a stream file.
fclose() Close a stream file.
fgetl()
sscanf() Read one line from a file.
Scan a string for formatted data.
The save and load commands allow you to write and read data to memory. Consider the following
example that demonstrates the use of the save and load functions:
The command save myfile.mat A saves matrix a to the file myfile.mat (refer to figure 3.14). The
command load myfile.mat loads the variables in the workspace. You could also right-click the
file myfile.mat in File Browser and view the file in Editor to edit it.
48
The above commands only work with files that adhere to Octave (and Matlab) standards. When data
are generated by other programs or if the format is not in the above format, then you need more
flexible commands. Delimited reading and writing, that is, dlmread() and dlmwrite() is a useful
command for files that contain data with known delimiters between the numbers. Take, for
example, the following data on kilometres travelled against litres of fuel used that were recorded in
Notepad:
Kilometres
The text file needs to be saved in the current directory accessible to Octave. If you are not sure
which directory you are currently working in, use the command pwd, as described in section 3.5.1.
You must then work with this text file in Octave and calculate the distance per fuel amount. The
following code (with explanations after the %) generates a new file, “mileage2”, that presents the
distance travelled, fuel used and kilometres per litre:
Figure 3.15 displays the output from Octave. From this figure we can see that a new file,
“mileage2.txt”, has been created in Current Directory and the appropriate variables have been
stored in Workspace.
49
Figure 3.15: Using the dlmread() and dlmwrite() commands
The delimiters used most often are spaces or commas, that is, comma-separated values (.csv files).
In such cases, the commands csvread() and csvwrite() can be used instead of the dlmread()
and dlmwrite()commands. Use help csvread() and help csvwrite() to find out how these
commands are used.
Activity 3.5
1. Generate a 3 × 3 matrix with random values. Save the file as myFile.mat and load the
variables into the workspace:
>>matrixA = rand(3,3);
>>save myFile.mat matrixA
>>load myFile.mat
>>matrixA
2. Save a multivariable file: create two matrices with random values and save the file as
multivariable.mat:
>>matrix1 = rand(2,3);
50
>>matrix2 = rand(2,2);
>>save (‘multivariable.mat’,’matrix1’,’matrix2’)
>>load multivariable.mat
>>matrix1
>>matrix2
4. The dependence of density on temperature has been measured for liquid-phase water and is
tabled below:
Load the data into Octave and plot the change in density along with the change in
temperature.
Data are often present in the form of Excel files. Octave as a programming language does not have a
built-in function to work with these files and you therefore have to download a separate module to
find out how to work with these files. An IO (input output) module is available from SourceForge at
this URL: https://sourceforge.net/projects/octave/. You must download the module and save the file
in Current Directory. Alternatively, you can install the module using the code >>pkg install -
forge package_name. In this case the, package_name is io:
Note that you need an active internet connection for the above command to ensure the successful
installation of the module. If you are interested in how Octave handles the installation of various
packages, consult the help page for the pkg command (i.e., help pkg).
51
Once the installation process is complete, load the IO package first:
>>pkg load io
The xlsopen, xlsclose and xlswrite commands open, close and write .xls files. The process of
using these commands is summarised in table 3.5.
52
Activity 3.6
The dependence of density on temperature has been measured for liquid-phase water and is tabled
below:
1. Save the data in an Excel file and in a directory accessible to Octave: densityH2O.xlsx.
2. Read the data from the file densityH2O.xlsx for the temperature range 100 ˚C to 20 ˚C and
create an array named density:
The following section is based on excerpts from the book Fundamental concepts and computations
in chemical engineering by Vivek Utgikar (2017):
Chemical engineers deal with many equations that range in complexity from simple linear equations
to more complex equations such as partial differential equations. The simplest forms of equations
that engineers often encounter are linear algebraic equations. The terms in an algebraic equation
are either constant or first-order variables. Take, for example, the equations encountered in a
distillation operation, where phase separation occurs (refer to the module in Separation Principles
(CES2601), study unit 1: distillation). These are often linear equations in the form of 𝑦𝑦 = 𝑚𝑚𝑚𝑚 + 𝑐𝑐 and
they can be solved quite easily. If the data available take the form of a matrix, these equations are
relatively easy to solve.
Algebraic equations are not always linear. Take, for example, the cubic equation of state: 𝑎𝑎𝑉𝑉 3 +
𝑏𝑏𝑉𝑉 2 + 𝑐𝑐𝑐𝑐 + 𝑑𝑑 = 0. In this equation, V is the volume of a substance at the given temperature and
pressure of a system. Constants 𝑎𝑎, 𝑏𝑏, 𝑐𝑐 and 𝑑𝑑 are functions of the system temperature, pressure,
number of moles and fluid properties. Similarly, the ideal gas equation 𝑃𝑃𝑃𝑃 = 𝑛𝑛𝑛𝑛𝑛𝑛 is the simplest of
the equations of state. Chemical engineers encounter different types of equations that are
polynomial or even transcendental in nature. These equations are more challenging and require the
use of special techniques. Some of these methods will be covered in learning unit 4.
53
Chemical engineers routinely collect data through various experiments, which they then use for
control, design and optimisation. Very often, values of functions are obtained in relation to
independent variables within the domain of experimental data where direct measurement is not
possible or available. Regression analysis allows chemical engineers to approximate data outside the
range measured. Regression analysis can be classified into
• linear regression, which involves approximating data using a straight line (supported by
Octave)
• non-linear regression, which involves using polynomial or transcendental functions to
approximate data
• multiple regression, which involves using two or more independent variables to determine
the value of the function
The most common basis for linear and multiple regression is to minimise squared errors between
the experimentally observed values and the values predicted by the model. The sum of squared
errors (SSE) is defined:
𝑛𝑛
2
𝑆𝑆𝑆𝑆𝑆𝑆 = ��𝑦𝑦𝑖𝑖 − 𝑓𝑓(𝑥𝑥𝑖𝑖 )�
𝑖𝑖=1
where 𝑦𝑦𝑖𝑖 is the observed value and 𝑓𝑓(𝑥𝑥𝑖𝑖 ) is the predicted value based on the model, that is, the
fitted line. This function can be linear in a single variable or multiple variables or even polynomial.
The remainder of the learning unit focuses on curve fitting using the least squares method.
As indicated in section 3.6, regression of data involves getting a mathematical expression that best
fits all data. Simply put, given a set of data in which the dependent variable y is a function of x:
𝑦𝑦 = 𝑓𝑓(𝑥𝑥)
𝑦𝑦 = 𝑎𝑎𝑎𝑎 + 𝑏𝑏
Using the least squares method, the sum of squared distances between the points and the fitted line
is minimised.
Should you have difficulty understanding the linear least squares method, you can read a detailed
explanation of least squares fitting on the WolframMathWorld website at this URL:
http://mathworld.wolfram.com/LeastSquaresFitting.html.
54
𝑥𝑥 = [0; 1.1; 2; 3.4; 5] 𝑎𝑎𝑎𝑎𝑎𝑎 𝑦𝑦 = [−0.4; 1.1; 2.5; 2; 3.2]
We want to determine the straight line 𝑦𝑦(𝑥𝑥) = 𝑝𝑝1 ∙ 1 + 𝑝𝑝2 ∙ 𝑥𝑥 to match the x and y data as
accurately as possible and to minimise the residual: 𝑟𝑟𝑖𝑖 = 𝑝𝑝1 ∙ 1 + 𝑝𝑝2 ∙ 𝑥𝑥𝑖𝑖 − 𝑦𝑦𝑖𝑖 . In matrix notation,
this would be expressed as follows:
1 𝑥𝑥1 𝑦𝑦1
𝑝𝑝1
𝑟𝑟⃗= 𝑋𝑋 ∙ 𝑝𝑝⃗ − 𝑦𝑦⃗ = � ⋮ ⋮ � ∙ �𝑝𝑝 � − � ⋮ �
2
1 𝑥𝑥𝑛𝑛 𝑦𝑦𝑛𝑛
We want to allow a non-zero intercept for our linear equation. In other words, we don’t want our
fitted equation to go through the origin. We do this by adding a column of ones to our x column:
We will use the normal equation to calculate the residual, that is, 𝑛𝑛𝑛𝑛𝑛𝑛𝑛𝑛𝑛𝑛𝑛𝑛 𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒𝑒 =
(𝑋𝑋 𝑇𝑇 𝑋𝑋)−1 𝑋𝑋 𝑇𝑇 𝑦𝑦. This minimises the residual values between the predicted equation and the actual
values:
Should you be interested in learning more about the derivation of the normal equation, go to this
URL: http://mathworld.wolfram.com/NormalEquation.html Putting this into Octave.
55
Figure 3.16: Linear regression for a straight line
Let us now try to fit a parabola through our data in order to see if the residual could be minimised
further:
1 𝑥𝑥1 𝑥𝑥1 2 1 0 0
⎡ ⎤
⎢1 𝑥𝑥2 𝑥𝑥2 2 ⎥ ⎡1 1.1 1.12 ⎤
⎢ ⎥
𝑋𝑋 = ⎢1 𝑥𝑥3 𝑥𝑥3 2 ⎥ = ⎢1 2 22 ⎥
⎢ ⎥ ⎢1 3.4 3.42 ⎥
⎢1 𝑥𝑥4 𝑥𝑥4 2 ⎥
⎣1 5 52 ⎦
⎣1 𝑥𝑥5 𝑥𝑥5 2 ⎦
56
>>p = (X’ *X)\(X’ *y); % the normal equation
>>residual = norm(X*p-y)
>>xn =[-1:0.1:6];
>>yn = p(1) +p(2) *xn +p(3)*xn.^2;
>>plot (x, y, ‘o g’, xn, yn);
>>xlabel (‘x data’)
>>ylabel (‘y data’)
57
Activity 3.7
1. The change in density along with the change in temperature has been measured and is tabled
below.
Develop an equation that will predict the density as a function of the change in temperature.
2. The rate at which crickets chirp as the temperature changes has been measured and the data
are available as a .csv file (T in ˚F, rate):
88.6,20
71.6,16
93.3,19.8
84.3,18.4
80.6,17.1
75.2,15.5
69.7,14.7
82,17.1
69.4,15.4
83.3,16.3
79.6,15
82.6,17.2
80.6,16
83.5,17
76.3,14.4
3. The progress of a homogeneous chemical reaction is followed and the rate constant and the
order of the reaction have to be evaluated. The rate law expression for the reaction is known to
follow the power function form:
−𝑟𝑟 = 𝑘𝑘𝐶𝐶 𝑛𝑛
58
Hint: ln(−𝑟𝑟) = ln(𝑘𝑘) + 𝑛𝑛𝑛𝑛𝑛𝑛(𝐶𝐶)
3.8 Conclusion
Learning unit 3 showed that Octave is a good choice for visualising data since it has a library of built-
in functions. Octave has commands that enable you to access files in different file paths and formats,
and functions that enable you to plot graphs. This learning unit also introduced you to linear
regression, which allows you to approximate data outside the range measured. The key commands
dealt with in this learning unit are summarised in table 3.9.
59
3.9 Sources consulted
60
Learning unit 4: Numerical techniques for solving
non-linear equations
4.1 Introduction
Having covered some equation-solving principles in your previous mathematics courses, you are
probably good at solving linear equations, 𝑎𝑎𝑎𝑎 + 𝑏𝑏 = 0, and quadratic equations, 𝑎𝑎𝑥𝑥 2 + 𝑏𝑏𝑏𝑏 + 𝑐𝑐 = 0.
You may also be familiar with the formulas for the roots of cubic equations and you are probably
capable of performing some trigonometric equations like 𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠 + 12𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠 = 0. But what happens
when you encounter an equation that cannot be solved using a pen and paper, that is, analytically?
In such a case, rather than finding an exact solution, you should use a numerical method to
determine an approximate solution. Numerical methods will allow you to solve any algebraic
equation.
In this learning unit, we will look at methods for solving non-linear equations, focusing on the
creation of loops for iterative processes; the use of built-in functions of Octave to determine the
roots of an equation; computational time and accuracy; and the secant, bisection and Newton’s
methods.
Up to this point, we have considered arithmetic in Octave and how to compute answers for simple
equations. But is it possible to perform a repetitive task for a process? Loops can be used to define
start and end conditions for repetitive tasks easily. They form an essential part of an algorithm
because they undertake repetitive actions in a fast manner. This is particularly useful when solving
equations numerically, as in section 4.5, where we need to define convergence criteria.
In this section we will look at for loops, while loops and if…elseif…else statements.
Additional notes and examples relating to this section are available at Wikibooks at this URL:
https://en.wikibooks.org/wiki/Octave_Programming_Tutorial/Loops_and_conditions.
61
4.3.1 A for loop
A for loop is a construct that allows the iterative execution of code to be implemented repeatedly.
The keyword for declares the start of the loop while end declares the end of the loop. We will
demonstrate the use of a for loop by means of a simple example:
Figure 4.1 shows the execution of the code. The disp statement is repeated six times. Change the
code to
and
Do you notice what happens? The disp statement is repeated three times and then not at all.
For a detailed explanation of for loops, watch the video clip “Octave tutorial 15 – repetitive
execution, part 1 (for loops)” (12:10) by Paul Nissenson at this URL: https://youtu.be/rTxm8ffbz-A.
62
4.3.2 A while loop
A while loop defines a logical condition that allows code to be executed repeatedly until the
condition defined is satisfied. Take the following example: we would like to determine √𝑥𝑥 for 𝑥𝑥 <
12:
>>x=2;
>>while x<12
disp (sqrt(x));
x = x+2;
end
Octave runs the code by first initialising a variable to x and since we have defined the initial value of
x=2, the code executes from this value. The condition will be satisfied from the initial value of 2 until
10 (2, 4, 6, 8 and 10), as long as x<12. Line 4 of the code defines x to be increased in increments of 2.
Figure 4.2 displays the output from Octave.
You could watch the video clip titled “Octave tutorial 16 – repetitive execution, part 2 (while
loops)” (10:39) by Paul Nissenson for additional examples – go to https://youtu.be/Y256ZMtdwNg.
When writing code, we have different conditional statements for different actions that we want the
code to perform. Examples of conditional statements are as follows:
63
• An if…else statement: this statement executes certain code if one condition is true and other
code if that condition is false.
• An if…elseif…else statement: this statement executes different codes for two different sets
of conditions.
The code below will generate a list of random integers between 0 and 50. Then from all the numbers
larger than 20, we will subtract 20. The script (i.e., the code below) is typed up in Editor and then
saved and executed as a loop. In this manner we can easily edit the script (which we have saved as
ifexample.m) without having to retype the code. Revise section 1.7 of learning unit 1 if you need
to refresh your memory on creating scripts. Revise section 2.6 if you have forgotten how to use the
rand function. Figure 4.3 shows the executed script for ifexample.m.
64
Figure 4.3: Using an if statement
Note that the semicolon in line 4 suppresses the output of all the iterations and, as a result, only the
final result is displayed after subtraction.
Suppose we would like to subtract 20 for all numbers ≥20 and add 20 to all numbers ≤20. We could
use an if…else statement as follows:
>>vec = round(rand(1,10)*50);
>>for k=1:10
if (vec(k)>=20)
vec(k)=vec(k)-20;
else
vec(k)=vec(k)+20;
endif
endfor
vec
65
Note: In Editor you can just add the else statement lines, that is, lines 5 and 6 and do not have to
retype the code. Save the edited file under a new name, ifelseexample.m. Figure 4.4 shows the
executed script.
An if…elseif…else loop can be used. The general syntax of the loop is given by
if (condition)
then body1
elseif (condition)
elseif body2
else
else body3
endif
x=55
if (rem(x,2)==0);
66
disp(“x is even\n”);
elseif (rem(x,5)==0)
disp(“x is odd and divisable by 5\n”);
else
disp(“x is odd\n”);
endif
67
Activity 4.1
1. Create a script that will calculate the square root for the first ten numbers:
For x=1:10
ans=sqrt(x)
end
3. Create a script that returns good morning, good day or good night, depending on the
present time:
time = hour(now);
if (time <= 12)
disp ("have a good morning");
elseif (time <= 17)
disp ("have a good day");
else
disp ("have a good night");
endif
4. Without using Octave, try to explain what sequence of numbers the following for loop will print
on the screen. Check your answer in Octave:
n=12;
for j =1:n
n = n-1;
j
end
Hint: As you may recall from mathematics, factorials are the products of 𝑛𝑛 numbers and are
followed by an exclamation mark (!). That is to say:
3! = 1 × 2 × 3 = 6.
Similarly:
𝑛𝑛! = 1 × 2 × 3 × 4 × … … … . (𝑛𝑛 − 1) × 𝑛𝑛
For example, the following code will generate a list of 𝑛𝑛 and 𝑛𝑛!:
n=5;
factorial=1;
for k=1:n
factorial=k*factorial;
disp([k factorial])
end
68
Try increasing the value of 𝑛𝑛 to 100 and 1 000. What is the largest value of 𝑛𝑛 for which
Octave can find 𝑛𝑛!?
In order to optimise computational performance, the execution time of a particular set of code has
to be determined. Convergence criteria need to be defined and programmed so as to ensure
convergence, within a reasonable time and with reasonable accuracy. Iterative techniques require
that convergence criteria be defined so that the program would know when to terminate the
iterations. Poorly chosen convergence criteria lead to the program giving results that have a large
error. Similarly, if we are too strict with the convergence criteria, the program might run for too
long. At a glance, there are no rules for choosing convergence criteria; instead, the criteria depend
on the specifics of the problem being solved. For example, if you are measuring distance in
kilometres, then you may want the accuracy to be within one metre, whereas if you are measuring
the positioning of a screw in a piece of wood, the tolerance may need to be within a few millimetres.
In mathematical terms, we can define the tolerance limit as
𝑒𝑒 = |𝑥𝑥 −𝑥𝑥 ∗ |
|𝑥𝑥 −𝑥𝑥 ∗ |
𝑒𝑒𝑟𝑟 =
𝑥𝑥
If the absolute error is less than the tolerance limit defined, then the solution is acceptable.
The relative error is the magnitude of the absolute error, divided by the magnitude of the exact
value. Multiplying the relative error by 100 gives the per cent error. This will be covered in greater
detail in section 4.5.
In this section, we will look at how to calculate the time taken to run a program, which serves as an
indicator of whether the program is efficient.
The use of tic and toc calculates the runtime of a loop, which would include the time taken while
the CPU was executing some other threads or waiting for an input structure. cputime displays only
the computational time to run a loop, that is to say, the time taken to run the code. Let us look at
some examples that demonstrate the use of the timing codes.
69
100 000
� 𝑛𝑛
𝑛𝑛=1
tic
s=0;
for n = 1:100 000
s=s+n;
end;
toc
Figure 4.6 shows the computational output time as 0.213012 seconds. What is the total time on your
machine?
Now let us compare tic and toc with cputime to generate a surf plot. Figure 4.7 shows the
comparison.
70
Figure 4.7: Comparison of tic and toc with cputime
From figure 4.7 we can see that the computational time taken to process the code is 0.156 seconds
using cputime and 0.198011 seconds using tic and toc. What do you think the difference in
runtime is due to?
The computational time can be reduced by avoiding for loops and vectorising instead. Take, for
example:
100 000
1
�
𝑛𝑛2
𝑛𝑛=1
tic
s=0;
for n = 1:100 000
s=s+1/n^2;
end;
toc
71
On our PC, this took about 0.272015 seconds. Let us try vectorising:
tic
n = 1:100 000;
s=sum(s+1./n.^2);
toc
This took about 0.001 seconds. Compare the runtimes on your PC. Different processors (faster or
slower, depending how old/new your PC is) will give different processing times. In terms of
programming efficiency, by vectorising or improving the way we write our program and the
convergence criteria, the computational time can also be increased.
Activity 4.2
Numerical methods are used to find solutions to mathematical problems that have no analytical
solution. Numerical solutions are an approximation in comparison with analytical solutions, and
accuracy requires evaluation, especially when working with large sets of data and long runtimes. This
section briefly explores an area of numerical integration that has been developed to solve non-linear
equations.
In the following sections, we will look at the graphical technique, the bisection method, the secant
method and Newton’s method for solving equations.
One of the simplest ways of finding the root of an 𝑓𝑓(𝑥𝑥) = 0 equation is to plot the equation
graphically and then to determine where the x-axis passes. The intersection/s then provide/s a rough
72
estimate of the root. Often, the graphical method is used as a rough estimate in numerical methods
(Chapra & Canale 2015).
As you will recall from learning unit 3, section 3.3.1, 2D plots are drawn using the plot function.
Using the graphical technique, we need to estimate the roots of the equation:
𝑓𝑓(𝑥𝑥) = 𝑥𝑥 3 + 𝑥𝑥 − 3
>>x=-2:0.1:2;
>>y=x.^3+x-3;
>>plot(x,y)
Intercept at x=1.2184
Using visual inspection, we see that an estimate of the equation is 1.2184. For the interval drawn,
we can see that there is only one root. Try changing the interval to >>x=[10;0.1:10]. Is it possible
to determine another root? What can you say about the shape of the curve? To increase the
accuracy of the root, reduce the interval further: >>x=[1;0.1:1.5].
73
Activity 4.3
Estimate the roots of the following equations using the graphical technique:
The bisection method is guaranteed to find a root if you can find two starting values for 𝑥𝑥𝐿𝐿 and 𝑥𝑥𝑅𝑅
between which the function changes sign. Consider the problem:
𝑓𝑓(𝑥𝑥) = 𝑥𝑥 3 + 𝑥𝑥 − 3
We need to find, by trial and error, two values of 𝑥𝑥, 𝑥𝑥𝐿𝐿 and 𝑥𝑥𝑅𝑅 , such that 𝑓𝑓(𝑥𝑥𝐿𝐿 ) and 𝑓𝑓(𝑥𝑥𝑅𝑅 ) have
different signs. Should we find two such values, then the root must lie somewhere in the interval
between them since 𝑓𝑓(𝑥𝑥) changes sign on the interval, as shown in figure 4.9.
𝑓𝑓(𝑥𝑥)
𝑥𝑥𝐿𝐿
𝑥𝑥𝑀𝑀 𝑥𝑥𝑅𝑅
If, in this example, we choose 𝑥𝑥𝐿𝐿 = 1 and 𝑥𝑥𝑅𝑅 = 2, then 𝑓𝑓(1) = −1 and 𝑓𝑓(2) = 7 will be reasonable
because we have 1 +ve value and another –ve value. The midpoint of the interval, 𝑥𝑥𝑀𝑀 , is estimated:
𝑥𝑥𝐿𝐿 + 𝑥𝑥𝑅𝑅
𝑥𝑥𝑀𝑀 =
2
• If 𝑓𝑓(𝑥𝑥𝑀𝑀 ) has the same sign as 𝑓𝑓(𝑥𝑥𝐿𝐿 ), the root lies between 𝑥𝑥𝐿𝐿 and 𝑥𝑥𝑀𝑀 . The new
value of 𝑥𝑥𝐿𝐿 = 𝑥𝑥𝑀𝑀 .
• If 𝑓𝑓(𝑥𝑥𝑀𝑀 ) and 𝑓𝑓(𝑥𝑥𝐿𝐿 ) have different signs, the root lies between 𝑥𝑥𝑀𝑀 and 𝑥𝑥𝑅𝑅 . The new
value of 𝑥𝑥𝑅𝑅 = 𝑥𝑥𝑀𝑀 .
74
• Having redefined 𝑥𝑥𝐿𝐿 or 𝑥𝑥𝑅𝑅 , we bisect the interval again and repeat the process
until the distance between 𝑥𝑥𝐿𝐿 and 𝑥𝑥𝑅𝑅 is as small as we need.
The advantage of this method is that the number of bisections needed to obtain a certain accuracy
can be estimated beforehand:
|𝑎𝑎 − 𝑏𝑏|
log ( 𝐸𝐸 )
𝑛𝑛 >
log(2)
Should you have difficulty understanding the mathematical principles of the bisection method,
watch the video clip titled “How to locate a root: bisection method” (12:51) by ExamSolutions at this
URL: https://youtu.be/OzFuihxtbtA.
We need to calculate the root of the following polynomial introduced in section 4.5.1:
𝑥𝑥 3 + 𝑥𝑥 − 3 = 0
function bisection()
f=@(x)x^3+x-3;
e=1e-6; %absolute error defined
a=0; b=1000;
[solution, no_iterations] = bisection(f, a, b, e);
if solution <=b
fprintf('number of function calls:%d\n',1+2*no_iterations);
fprintf('a solution is: %f\n', solution);
else
fprintf('abort execution .\n');
end
end
75
break
end
x_M=(x_L+x_R)/2.0;
f_M=f(x_M);
iteration_counter=1;
while abs(f_M)>e
left_f=f(x_L);
right_f=f(x_R);
if left_f*f_M>0 %same sign
x_L=x_M;
else
x_R=x_M;
end
x_M=(x_L+x_R)/2;
f_M=f(x_M);
iteration_counter = iteration_counter +2;
end
result1=x_M;
result2=iteration_counter;
end
76
Figure 4.10: The bisection method
Activity 4.4
1. Try changing the relative error to 1𝑒𝑒 − 8 in the bisection_method example. How does this
change the number of function calls?
2. Set 𝑎𝑎 = 1 and 𝑏𝑏 = 2. Is the number of function calls increased or decreased? And if you set 𝑎𝑎 =
2 and 𝑏𝑏 = 3?
3. Calculate the processing time using the bisection method.
4. Solve the following equation using the bisection method:
𝑝𝑝(𝑥𝑥) = 3 + 5𝑥𝑥 + 2𝑥𝑥 2
Compare your answer with the estimate found in activity 4.3, Q1.
5. Compare the code for the bisection method that is provided in this section with the code that
can be found at this URL: https://sites.google.com/site/numericalprocessespro2012/closed-
methods/bisection/octave-code.
What are the notable differences between the codes?
6. Solve the equation:
𝑥𝑥 3 + 𝑥𝑥 − 3 = 0
Using the downloaded code from Q5, calculate the roots of the equation. Compare the solution with
the solution obtained in the example above. Comment on the changes, if any.
77
4.5.3 Newton’s method
Newton’s method is one of the easiest and most efficient methods of solving equations and uses
iterations in that it repeatedly attempts to improve an estimate of a root. Refresh your memory by
reading the background notes on the method that can be found at this URL:
https://en.wikibooks.org/wiki/Calculus/Newton%27s_Method
Newton’s method, also known as the Newton–Raphson method, is used to find approximations to
the roots of a real-valued function. The method begins with a function 𝑓𝑓 defined over real numbers,
the derivative of the function 𝑓𝑓 ′ and an initial guess 𝑥𝑥0 in order to determine the root of the
function 𝑓𝑓. If the initial guess is close and the function satisfies the Newton conditions, then a better
approximation is defined:
𝑓𝑓(𝑥𝑥0 )
𝑥𝑥1 = 𝑥𝑥0 −
𝑓𝑓 ′ (𝑥𝑥0 )
𝑓𝑓(𝑥𝑥𝑛𝑛 )
𝑥𝑥𝑛𝑛+1 = 𝑥𝑥𝑛𝑛 −
𝑓𝑓 ′ (𝑥𝑥𝑛𝑛 )
If 𝑥𝑥𝑛𝑛 is an approximation to the root, then we can relate it to the next approximation 𝑥𝑥𝑛𝑛 + 1 using
the right-angled triangle in figure 4.11 (the tangent to the function).
𝑓𝑓(𝑥𝑥)
𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠 = 𝑓𝑓′(𝑥𝑥𝑛𝑛 )
𝑓𝑓(𝑥𝑥𝑛𝑛 )
78
Therefore, we express the approximation mathematically as
𝑓𝑓(𝑥𝑥𝑛𝑛 ) − 0 ∆𝑦𝑦
𝑓𝑓 ′ (𝑥𝑥𝑛𝑛 ) = 𝑜𝑜𝑜𝑜 𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠𝑠 =
𝑥𝑥𝑛𝑛 − 𝑥𝑥𝑛𝑛+1 ∆𝑥𝑥
𝑑𝑑𝑑𝑑
where 𝑓𝑓 ′ (𝑥𝑥) = .
𝑑𝑑𝑑𝑑
𝑓𝑓(𝑥𝑥𝑛𝑛 )
𝑥𝑥𝑛𝑛+1 = 𝑥𝑥𝑛𝑛 −
𝑓𝑓′(𝑥𝑥𝑛𝑛)
Let us see how to solve the equation 𝑥𝑥 3 + 𝑥𝑥 − 3 = 0, introduced in the bisection method, using the
above algorithm:
Now we will write a separate script file that will stop when the relative error is less than 10−8 or
after 20 steps (whichever occurs first):
steps = 0;
x = input (‘Initial guess: ‘); %estimate root
re = 1e-8;
myrel = 1;
79
end
if myrel <= re
disp (‘zero found at’)
disp(x)
else
disp(‘zero not found’)
end;
If our initial guess is 1, we achieve convergence in 5 steps, with a zero found at 1.213 (refer to figure
4.12). This is very efficient in comparison with the bisection method.
The code indicated above can be modified for solving other equations.
80
Should you need to learn more about the Newton–Raphson method, study the notes of the
Mathematics Department of the University of the British Columbia that are available at this URL:
http://www.math.ubc.ca/~anstee/math104/newtonmethod.pdf. Alternatively, watch the video clip
titled “Newton–Raphson method – maths made easy” (12.23) at this URL:
https://youtu.be/PIPiv6gn_Ls.
By way of example, the square root of any positive number may be found using Newton’s method.
Background notes on Newton’s method of finding square roots can be accessed at this URL:
http://www-math.mit.edu/~stevenj/18.335/newton-sqrt.pdf.
The structure of the algorithm for finding the square root of a positive number 𝑎𝑎 is as follows:
1. Initialise a
2. Initialise x to a/2
3. Repeat 6 times (6 times as an example)
Replace x by (x+a/x)/2
Display x
4. End
Let us look at the following example of finding the square root of 5 (√5) – refer to figure 4.13 for the
Octave output:
a=5;
x=a/2;
for i=1:6
x=(x+a/x)/2;
disp(x);
end
disp(sqrt (5))
Line 7 checks the answer using the Octave square root function. In this way we can compare the
accuracy of the solution. Try changing the format to format long to see if/how the decimal places
affect the change in convergence. What can you say about the convergence and the number of
iterations needed? Change the code to determine the square root of 2( √2).
81
Figure 4.13: Execution of Newton’s method to find a square root
Activity 4.5
1. Calculate the square root of 6 (√6). Determine the computational time needed to run the code.
2. Using cputime, calculate the computational time taken to run the loop.
Feedback: See the code saved as newt.m below.
82
3. Compare the execution time related to Q1 by using tic and toc. Why is there a difference in
the time?
4. Solve the following equation using Newton’s method:
𝑥𝑥 2 + 4𝑥𝑥 − 1 = 0
Hint: You need to change the function files as follows:
5. Try changing the initial guess in Q4 to -1 and 0. Does this change the answer?
6. Solve the non-linear equation using Newton’s method. Calculate the cputime, too:
𝑝𝑝(𝑥𝑥) = 3 + 5𝑥𝑥 + 2𝑥𝑥 2
6. You have a spherical storage tank containing oil. The tank has a diameter of 2 m. You are asked
to calculate the height ℎ to which a dipstick that is 2.5 m long would become wet with oil when
immersed in the tank when it contains 2 m3 of oil. The equation giving the height of the liquid in
the spherical tank for the given volume and radius is as follows:
𝑓𝑓(ℎ) = 0.30ℎ3 − ℎ2 + 0.16 = 0
83
Dipstick
Spherical tank
The secant method is used when the function evaluations take too long using Newton’s method or
when it is difficult to determine the derivative of a function. In this method, we use secants instead
of taking tangents to the function (refer to figure 4.11 on Newton’s method). This is illustrated in
figure 4.14.
84
Figure 4.14: The secant method (source: Wikimedia Commons
https://commons.wikimedia.org/wiki/File:Secant_method_2.svg#/media/File:Secant_method_2.svg)
The secant method does not use the derivative of 𝑓𝑓(𝑥𝑥), but rather uses the approximation of the
straight line going through the most recent approximations 𝑥𝑥𝑛𝑛 and 𝑥𝑥𝑛𝑛−1. The slope of the secant
would then be
𝑓𝑓(𝑥𝑥𝑛𝑛 ) − 𝑓𝑓(𝑥𝑥𝑛𝑛−1 )
𝑥𝑥𝑛𝑛 − 𝑥𝑥𝑛𝑛−1
𝑓𝑓(𝑥𝑥𝑛𝑛 )
𝑥𝑥𝑛𝑛+1 = 𝑥𝑥𝑛𝑛 −
𝑓𝑓(𝑥𝑥𝑛𝑛 ) − 𝑓𝑓(𝑥𝑥𝑛𝑛−1 )
𝑥𝑥𝑛𝑛 − 𝑥𝑥𝑛𝑛−1
or
𝑥𝑥𝑛𝑛 − 𝑥𝑥𝑛𝑛−1
𝑥𝑥𝑛𝑛+1 = 𝑥𝑥𝑛𝑛 − 𝑓𝑓(𝑥𝑥𝑛𝑛 )
𝑓𝑓(𝑥𝑥𝑛𝑛 ) − 𝑓𝑓(𝑥𝑥𝑛𝑛−1 )
In figure 4.13 we see that the first two iterations 𝑥𝑥0 and 𝑥𝑥1 are used to compute the next iteration
𝑥𝑥2 . Similarly, once we have 𝑥𝑥2 , 𝑥𝑥1 and 𝑥𝑥2 are used to compute the next iteration 𝑥𝑥3 . The procedure
is repeated until some limit on the number of iterations has been reached or 𝑓𝑓(𝑥𝑥𝑛𝑛 ) is below some
chosen limit value. Unlike Newton’s method, in order for the algorithm to start, we need two
guesses, 𝑥𝑥0 and 𝑥𝑥1 .
Should you have difficulty understanding the secant method, access the notes, which include
examples, that are available at this URL:
85
https://mat.iitm.ac.in/home/sryedida/public_html/caimna/transcendental/iteration%20methods/se
cant/secant.html.
You can also watch the video clip titled “Roots: secant method” (3:02) by Jacob Bishop at this URL:
https://youtu.be/ZfMibcIr5YA.
Let us calculate the roots of the polynomial introduced in the previous sections and compare the
secant method with the other methods:
𝑥𝑥 3 + 𝑥𝑥 − 3 = 0
function secant()
f=@(x)x^3+x-3;
e=1e-6;
x0=1000; x1=x0-1;
[solution, no_iterations] = secant(f, x0, x1, e);
if no_iterations > 0 %solution is found
fprintf('number of function calls:%d\n',2 + no_iterations);
fprintf('a solution is: %f\n', solution);
else
fprintf('abort execution .\n');
end
end
function [solution, no_iterations]=secant(f, x0, x1, e)
f_x0=f(x0);
f_x1=f(x1);
iteration_counter = 0;
while abs(f_x1)> e && iteration_counter<100
try
denominator = (f_x1 - f_x0)/(x1 - x0);
x = x1-f(x1)/denominator;
catch
fprintf('error-denominator zero for x= \n', x1)
break
end
x0=x1;
x1=x;
f_x0=f_x1;
f_x1=f(x1);
iteration_counter = iteration_counter +1;
end
%solution found or too many iterations
if abs(f_x1)>e
iteration_counter = -1;
end
solution = x1;
no_iterations = iteration_counter;
end
86
From figure 4.15 we can see that the solution is found in 30 iterations, which is better than what is
obtained using the bisection method. Try changing 𝑥𝑥0 to 10. How many iterations are needed? And if
you change 𝑥𝑥0 to 1?
Activity 4.6
follows an elementary rate law and is carried out isothermally in a flow system. The
concentrations of A and B in the feed streams are 2 M before mixing. The volumetric flow
87
rate of each stream is 5 dm3/min and the entering temperature is 300 K. The streams are
mixed immediately before entering. A 200 dm3 CSTR that can be heated to 77 °C or cooled to
0 °C is available. Calculate the conversion that can be achieved in the CSTR.
Hint:
20000 1 1
𝑘𝑘 = 0.07𝑒𝑒𝑒𝑒𝑒𝑒 � − �
1.987 300 350
𝑑𝑑𝑑𝑑3
𝑘𝑘 = 8.45 . 𝑚𝑚𝑚𝑚𝑚𝑚
𝑚𝑚𝑚𝑚𝑚𝑚
(𝑉𝑉)(−𝑟𝑟𝐴𝐴 )
CSTR: 𝑋𝑋 = 𝐹𝐹𝐴𝐴0
𝑉𝑉�𝑘𝑘𝐶𝐶𝐴𝐴0 2 (1 − 𝑋𝑋)2 �
𝑋𝑋 =
10
𝑑𝑑𝑑𝑑3 𝑚𝑚𝑚𝑚𝑚𝑚 2
(200𝑑𝑑𝑑𝑑3 ) �8.45 � �1 � (1 − 𝑋𝑋)2
𝑚𝑚𝑚𝑚𝑚𝑚. 𝑚𝑚𝑚𝑚𝑚𝑚 𝑑𝑑𝑑𝑑3
𝑋𝑋 =
𝑚𝑚𝑚𝑚𝑚𝑚
10 𝑚𝑚𝑚𝑚𝑚𝑚
simplify the expression and solve for 𝑋𝑋 using the bisection method, Newton’s method or the secant
method.
𝑓𝑓(𝑥𝑥) = 0
Some built-in functions of Octave exist to solve for zeros of single linear or non-linear functions, as
well as systems of non-linear functions. These functions are summarised in table 4.1.
The following activity will demonstrate the abovementioned Octave functions by means of
examples.
88
Activity 4.7
>>roots([3 0 2 1])
The Octave output should give you one real root 𝑥𝑥 = −0.4 and two complex roots 𝑥𝑥 =
0.2 ± 0.9𝑖𝑖.
Compare this with the estimate obtained in activity 4.3, Q2.
>>x0=fsolve(@(x)sin(x),3)
Note: @(x) is a convenient function handle that can point to an existing function (like a .m
file) or an anonymous function. This is essential for problems that include solving a non-
linear equation or a differential equation. In the above code, the @(x) handle is used to
point to an anonymous function. Recall from Q3: the Help function >>help fsolve gives
fsolve (FCN, X0, OPTIONS).
𝑥𝑥 2 + 4𝑦𝑦 2 − 1 = 0
4𝑥𝑥 4 + 𝑦𝑦 2 − 1 = 0
x0=[1;1];
function y = f(x)
y=[x(1)^2 + 4*x(2)^2 - 1; 4*x(1)^4 + x(2)^2 - 1]
endfunction
[x, fval, info]=fsolve(@f,x0)
89
6. Try solving the following set of equations:
𝑥𝑥 2 + 2𝑦𝑦 2 − 2 = 0
2𝑥𝑥 3 + 𝑦𝑦 2 − 3 = 0
4.6 Conclusion
In learning unit 4 we looked at methods for approximating solutions for equations that cannot be
determined analytically. Loops for iterative processes; built-in functions in Octave for determining
the roots of an equation; computational time and accuracy; and the secant, bisection and Newton’s
methods were discussed. The key Octave functions discussed in this learning unit are summarised
below.
90
Table 4.2: Summary of Octave functions for solving equations
Function Description
for Allows the iterative execution of code to be implemented
repeatedly
while Code to be executed repeatedly until the condition defined is
satisfied
if Executes code if one statement is true
if…else Executes certain code if one condition is true and other code if
that condition is false
if…else…else…if Executes different codes for two different sets of conditions
tic…toc Calculates the runtime of a loop
cputime Calculates the time taken to run a code
roots() Finds zeros of polynomials
fzero() Solves one non-linear equation
fsolve() Solves non-linear equations and systems
1. Chapra, SC & Canale, RP. 2015. Numerical methods for engineers. 7th edition. New York:
McGraw-Hill Education.
91
Learning unit 5: Numerical integration techniques
5.1 Introduction
Integration is a well-known mathematical method that you have been exposed to since high school
as part of calculus. Its inverse operation, differentiation, was covered in learning unit 4. Integration
assigns numbers to functions whereby the area under the curve 𝑓𝑓(𝑥𝑥) is calculated between the
definite limits of 𝑎𝑎 and 𝑏𝑏. Most integrals are complex to do using pen and paper, and a computerised
1 2
solution is much simpler. For example, the integral of 𝑒𝑒 −2𝑥𝑥 cannot be found analytically. We
therefore need a numerical method of evaluating the integral.
𝑏𝑏
� 𝑓𝑓(𝑥𝑥)𝑑𝑑𝑑𝑑
𝑎𝑎
Numerical methods for computing this integral basically split the original integral into a sum of
several integrals, each covering a smaller part of the original integration interval between 𝑎𝑎 and 𝑏𝑏.
The integration points may be distributed evenly or, in some cases, they may be odd. Using an even
number of integration points simplifies expressions greatly; the methods discussed below will be
restricted to an even number of intervals. The integration points then become
𝑥𝑥𝑖𝑖 = 𝑎𝑎 + 𝑖𝑖ℎ, 𝑖𝑖 = 0, 1, … … … … . 𝑛𝑛
and
𝑏𝑏 − 𝑎𝑎
ℎ=
𝑛𝑛
92
ℎ is the width of each panel and is known as the step length, and 𝑛𝑛 is the number of integration
points.
The methods that will be discussed in the sections below will differ in the way each integral on the
right-hand side is approximated. The fundamental idea is that each section of the integral will be
approximated by a polynomial such as a straight line or a parabola, making it easy to integrate by
hand.
We will also look at how to choose the sample points, that is, 𝑥𝑥1 , 𝑥𝑥2 , 𝑥𝑥3 … … . 𝑥𝑥𝑛𝑛 so that we obtain a
desired level of accuracy at a reasonable computational cost. For numerical quadrature,
computational work is usually measured by the number of evaluations of the function that is
required to ensure reasonable accuracy.
𝑏𝑏
The integral ∫𝑎𝑎 𝑓𝑓(𝑥𝑥)𝑑𝑑𝑑𝑑 may be defined as the area between 𝑥𝑥 and 𝑦𝑦 = 𝑓𝑓(𝑥𝑥). Graphically, this is
represented as follows:
𝑦𝑦 = 𝑓𝑓(𝑥𝑥) 𝑓𝑓(𝑥𝑥)
a b 𝑥𝑥
Figure 5.1: The integral of 𝒇𝒇(𝒙𝒙) interpreted as the area under the curve
93
If we replace the function in figure 5.1 with a set of straight-line segments, thereby applying the
trapezoidal rule, as shown in figure 5.2, the area may be viewed as a set of trapezoids rather than an
irregular area. The approximate area under the curve then becomes easier to compute.
𝑦𝑦 = 𝑓𝑓(𝑥𝑥)
𝑓𝑓(𝑥𝑥)
1 2 3
a b
𝑥𝑥
Figure 5.2: Approximating the integral of the function as the sum of the areas of trapezoids
If we increase the number of intervals, n, then the accuracy of the result is increased (refer to figure
5.3). From this we can see that the more trapezoids there are, the better the approximation since
the trapezoids in the upper side then follow the original graph more closely. Increasing the number
of intervals may be tedious by hand but would be easy to do using a computer.
94
𝑦𝑦 = 𝑓𝑓(𝑥𝑥)
𝑓𝑓(𝑥𝑥)
1 2
3
4
5 6
a b
𝑥𝑥
𝑏𝑏
The general formula for the trapezoidal rule approximating the integral ∫𝑎𝑎 𝑓𝑓(𝑥𝑥)𝑑𝑑𝑑𝑑 for 𝑛𝑛 equal
widths is given by
𝑏𝑏
ℎ
� 𝑓𝑓(𝑥𝑥)𝑑𝑑𝑑𝑑 = [𝑓𝑓(𝑥𝑥0 ) + 2𝑓𝑓(𝑥𝑥1 ) + 2𝑓𝑓(𝑥𝑥2 ) + ⋯ + 2𝑓𝑓(𝑥𝑥𝑛𝑛−1 ) + 𝑓𝑓(𝑥𝑥𝑛𝑛 )]
𝑎𝑎 2
Substitute limits:
0.8 1
∫0 𝑑𝑑𝑑𝑑 = − ln(3 − 0.8) + 𝑙𝑙𝑙𝑙(3 − 0) = 0.310355
3−𝑥𝑥
95
𝑥𝑥1 = 0.2 1 𝑓𝑓(𝑥𝑥1 ) = 0.357143
𝑓𝑓(𝑥𝑥0 ) =
3 − 0.2
𝑥𝑥2 = 0.4 1 𝑓𝑓(𝑥𝑥0 ) = 0.384615
𝑓𝑓(𝑥𝑥0 ) =
3 − 0.3
𝑥𝑥3 = 0.6 1 𝑓𝑓(𝑥𝑥0 ) = 0.416667
𝑓𝑓(𝑥𝑥0 ) =
3 − 0.6
𝑥𝑥4 = 0.8 1 𝑓𝑓(𝑥𝑥0 ) = 0.454545
𝑓𝑓(𝑥𝑥0 ) =
3 − 0.8
0.8 1 ℎ
∫0 𝑑𝑑𝑑𝑑 = [𝑓𝑓(𝑥𝑥0 ) + 2𝑓𝑓(𝑥𝑥1 ) + 2𝑓𝑓(𝑥𝑥2 ) + 2𝑓𝑓(𝑥𝑥3 ) + 𝑓𝑓(𝑥𝑥4 )]
3−𝑥𝑥 2
Substitute:
0.8 1 0.2
∫0 𝑑𝑑𝑑𝑑 = [0.333333 + (2 × 0.357143) + (2 × 0.384615) + (2 × 0.416667) +
3−𝑥𝑥 2
0.454545]
0.8 1
∫0 𝑑𝑑𝑑𝑑 = 0.310473
3−𝑥𝑥
In comparison with the analytical solution, the trapezoidal rule gives an estimate that is
identical to the analytical solution to three decimal places. This is quite accurate.
For an additional example, watch a video clip titled “Trapezoidal rule: example 1” (7:47) by the North
Carolina School of Science and Mathematics at this URL: https://youtu.be/Kcka3EicAys.
You can also access notes on the trapezoidal rule by the Khan Academy at this link:
https://www.khanacademy.org/math/ap-calculus-ab/ab-integration-new/ab-6-2/a/understanding-
the-trapezoid-rule.
Furthermore, you can watch the video clip titled “Trapezoidal rule” (12:09) by The Organic Chemistry
Tutor at this URL: https://youtu.be/Rn9Gr52zhrY.
Coding the trapezoidal rule in Octave is fairly simple since Octave has a built-in function that makes
it easy to integrate. In learning unit 4, section 4.4, you saw that by avoiding for loops and
vectorising instead, computational time is decreased. This is exactly what the Octave function trapz
does. We will demonstrate computational time for the different codes below.
we will first compute the integral of the function using a for loop (an explanation for each line of
code is given after the % sign):
96
>>for k = 1:(n-1)
integral = integral + 0.5 *(y(k)+y(k+1))*(x(k+1)-x(k));
%trapezoidal rule formula evaluating each point
end
>>toc;
integral
Let us compare the computational time by using the built-in trapz function (refer to figure 5.5):
>tic;
>>x = 0:0.8/10:0.8;% defining the number of points in the interval
>>y = 1./(3-x);
>>toc;
>>trapz(x,y)
From figure 5.5 we can see that, in only a few lines of code, we obtained an answer very similar to
that of the code shown in figure 5.4. We also find that the elapsed time decreased from 0.06 s to
0.023 s. This is very efficient for the same number of points.
97
Figure 5.5: Evaluating the integral using the trapz function
Activity 5.1
2
� (𝑥𝑥 2 − 3) 𝑑𝑑𝑑𝑑
1
1.1 Evaluate the integral analytically. Use four significant figures. (answer: -0.6667)
1.2 Evaluate the integral using the trapezoidal rule by hand. Take n = 4.
1.3 Estimate the integral using the for loop in figure 5.4.
Hint: Change line 4 to y=(x.^2)-3.
1.4 Vectorise the trapezoidal rule (i.e., avoid using a for loop).
98
In learning unit 2 you saw that vectorising reduces computational time. In order to replace
the for loop, we can rewrite the trapezoidal formula as a scalar product of two vectors:
𝑛𝑛
〈𝑥𝑥̅ 𝑦𝑦�〉 = � 𝑥𝑥𝑘𝑘 𝑦𝑦𝑘𝑘
𝑘𝑘=1
𝑛𝑛
1.5 Evaluate the function using the built-in trapz function. What can you say about the
accuracy of the solution?
2. Given the integral
3
1
� 𝑑𝑑𝑑𝑑
0 1 + 𝑥𝑥 5
2.1 Evaluate the integral analytically. Use four significant figures. (answer: 1.074)
2.2 Evaluate the integral using the trapezoidal rule by hand. Take n = 4.
2.3 Estimate the value of the integral using the vectorised code introduced in Q1.4.
2.4 Evaluate the integral using the built-in trapz function.
3. Given the integral
10
� cos (𝑥𝑥) 𝑑𝑑𝑑𝑑
−10
3.1 Estimate the value of the integral using the vectorised code introduced in Q1.4.
3.2 Evaluate the integral using the built-in trapz function.
99
5.3.2 Simpson’s rule
Simpson’s rule is a numerical integration method that is more accurate than the trapezoidal rule and
should be used/tested before any of the other numerical integration methods are tried. Like the
trapezoidal rule, it divides the area under the function to be integrated, into panels. Instead of
joining the panels with straight lines, as in figures 5.2 and 5.3, every set of three consecutive points
are fitted with a parabola. This proves to be more efficient than the trapezoidal rule, as can be seen
in figure 5.6. Since every set of three points is fitted with a parabola, we need an even number of
panels; therefore, 𝑛𝑛 has to be an even number:
𝑏𝑏 − 𝑎𝑎
ℎ=
𝑛𝑛
Parabola
Figure 5.6: Approximating the area under a curve using Simpson’s rule (Source: Wikimedia
Commons https://commons.wikimedia.org/wiki/File:Composite_Simpsons_rule.png)
𝑏𝑏
The general formula for Simpson’s rule approximating the integral ∫𝑎𝑎 𝑓𝑓(𝑥𝑥)𝑑𝑑𝑑𝑑 for 𝑛𝑛 equal widths is
given by
𝑏𝑏
ℎ
� 𝑓𝑓(𝑥𝑥)𝑑𝑑𝑑𝑑 = [𝑓𝑓(𝑥𝑥0 ) + 4𝑓𝑓(𝑥𝑥1 ) + 2𝑓𝑓(𝑥𝑥2 ) + 4𝑓𝑓(𝑥𝑥3 ) + 2𝑓𝑓(𝑥𝑥4 ) + ⋯ + 2𝑓𝑓(𝑥𝑥𝑛𝑛−2 ) + 4𝑓𝑓(𝑥𝑥𝑛𝑛−1 )
𝑎𝑎 3
+ 𝑓𝑓(𝑥𝑥𝑛𝑛 )]
The following link has a proof of Simpson’s rule, should you be interested:
https://www.intmath.com/integration/6-simpsons-rule.php.
We will demonstrate the use of Simpson’s rule by means of the following example:
100
0.8
1
� 𝑑𝑑𝑑𝑑
0 3 − 𝑥𝑥
𝑏𝑏 − 𝑎𝑎 0.8 − 0
ℎ= = = 0.2
𝑛𝑛 4
𝑥𝑥0 = 0 1
𝑓𝑓(𝑥𝑥0 ) = 𝑓𝑓(𝑥𝑥0 ) = 0.333333
3−0
𝑥𝑥1 = 0.2 1 𝑓𝑓(𝑥𝑥1 ) = 0.357143
𝑓𝑓(𝑥𝑥0 ) =
3 − 0.2
𝑥𝑥2 = 0.4 1 𝑓𝑓(𝑥𝑥0 ) = 0.384615
𝑓𝑓(𝑥𝑥0 ) =
3 − 0.3
𝑥𝑥3 = 0.6 1 𝑓𝑓(𝑥𝑥0 ) = 0.416667
𝑓𝑓(𝑥𝑥0 ) =
3 − 0.6
𝑥𝑥4 = 0.8 1 𝑓𝑓(𝑥𝑥0 ) = 0.454545
𝑓𝑓(𝑥𝑥0 ) =
3 − 0.8
0.8
1 ℎ
� 𝑑𝑑𝑑𝑑 = [𝑓𝑓(𝑥𝑥0 ) + 4𝑓𝑓(𝑥𝑥1 ) + 2𝑓𝑓(𝑥𝑥2 ) + 4𝑓𝑓(𝑥𝑥3 ) + 𝑓𝑓(𝑥𝑥4 )]
0 3 − 𝑥𝑥 3
Substitute:
0.8 1
∫0 𝑑𝑑𝑑𝑑 = 0.310157
3−𝑥𝑥
The answer obtained analytically is 0.310355. Therefore, the answer obtained using Simpson’s rule is
accurate to five decimal figures.
Should you have difficulty understanding Simpson’s rule, revise the notes that are available at this
URL: https://study.com/academy/lesson/what-is-simpsons-rule-example-formula.html.
The video titled “Simpson’s rule and numerical integration” (12:10) by The Organic Chemistry Tutor
may also be helpful: https://youtu.be/7EqRRuh-5Lk.
Octave only has an adaptive vectorised Simpson’s rule. We will demonstrate how to code Simpson’s
rule in Octave and how to use the adaptive built-in function for Simpson’s rule, quad().
function I = simpson(f,a,b,n)
if isa(f, 'function_handle')%see help isa – returns true if the
object is from the classname
n=round(n/2+0.1)*2; % even number of subintervals
h=(b-a)/n;
x=linspace(a,b,n+1);
f_x=x;
for k=0:n
f_x(k+1)=feval(f,x(k+1));
end
else
101
n=length(f)
if(floor(n/2)-n/2==0)
error ('error odd number of points')
else
n=n-1;%corrects for odd number of points
h=(b-a)/n;
f_x=f(:)';
end
end
w = 2*[ones(1,n/2); 2*ones(1, n/2)]; w = w(:); %constructs the
simpson weights
w=[w;1];w(1)=1;
I = (b-a)/(3*n)*f_x*w
Figure 5.7 shows the function in Editor and the executed function.
Lines 1–6 define the parameters of the function. Lines 7–13 then check if the n chosen is even. The
if…else loop from lines 12–19 correct the number of panels chosen if an odd number of panels
was chosen. Lines 20–22 execute Simpson’s formula to approximate the value of the integral. The
function in Command Window is as follows:
102
>>f=@x1/(3-x)
>>I = simpson(f, 0, 0.8, 100)
Try running the code with a smaller number of panels – choose n = 4. What if we choose an odd
number of panels, say, n = 7 or n = 101? How close are the answers to the answer obtained through
the analytical method?
Let us now see how to use the built-in adaptive Simpson’s rule in Octave. The adaptive Simpson’s
technique uses a recursive method to stop subdivision of the interval of panels between 𝑎𝑎 and 𝑏𝑏. In
other words, instead of 𝑛𝑛 being chosen upfront, a tolerance/error is defined and the number of
panels is chosen by the program in order to satisfy the tolerance. The function is used in Octave as
follows:
Q=quadv(f,a,b,tol)
where 𝑓𝑓 is the function handle and 𝑎𝑎 and 𝑏𝑏 are the upper and lower integration limits, respectively.
The argument tol is optional and, if not specified, the default value that Octave will use is 1e-6.
Should you wish to read more about the adaptive Simpson’s method, access this link:
https://en.wikipedia.org/wiki/Adaptive_Simpson%27s_method.
From figure 5.8 we can see that the built-in quadv function saves a lot of time and effort since it
produces the same answer as our coded Simpson’s rule.
103
Activity 5.2
2
� (𝑥𝑥 2 − 3) 𝑑𝑑𝑑𝑑
1
1.3 Evaluate the function using the built-in quadv function. What can you say about the
accuracy of the solution?
3
1
� 𝑑𝑑𝑑𝑑
0 1 + 𝑥𝑥 5
10
� cos (𝑥𝑥) 𝑑𝑑𝑑𝑑
−10
Gaussian quadrature is computationally more demanding but yields more accurate answers than the
trapezoidal rule and Simpson’s rule. Take, for example, the polynomial (blue line) represented by the
function 𝑦𝑦(𝑥𝑥) = 7𝑥𝑥 3 − 8𝑥𝑥 2 − 3𝑥𝑥 + 3 in figure 5.9. The orange line represents the approximation to
the integral using the trapezoidal rule. The trapezoidal and Simpson’s rules employ x values that are
equally spaced in order to calculate the function values. Evaluating the integral using the trapezoidal
rule yields 𝑦𝑦(−1) + (𝑦𝑦(1) = −10. Test this using the built-in trapz function introduced in section
5.3.1.
104
Gaussian quadrature calculates the function values at specific x values determined by Gauss using a
Legendre transformation, allowing for a more accurate estimation of the integral, as depicted by the
2
black dashed line in figure 5.9. Using Gaussian quadrature, the integral is estimated as , which is
3
exactly the same as the analytical solution. You will verify this solution in activity 5.3 at the end of
the section.
Figure 5.9: Comparison between two-point Gaussian quadrature and the trapezoidal rule (Source:
Wikimedia Commons
https://en.wikipedia.org/wiki/Gaussian_quadrature#/media/File:Comparison_Gaussquad_trapezoid
al.svg )
For a detailed derivation of the Gauss quadrature formula, you could refer to any textbook on
numerical methods. Chapra and Canale (2015) give a derivation for the two-point Gauss-Legendre
formulae. You can also watch the video clip titled “An introduction to numerical integration through
Gaussian quadrature” (26:03) by Ben Lambert for an in-depth explanation of how Gaussian
quadrature works: https://youtu.be/Hu6yqs0R7GA.
Basically, Gaussian quadrature evaluates the function at several specific points (x-values) and
multiplies these function values by corresponding weights to approximate the integral by a weighted
sum. The Gauss formula is given as follows:
105
1 𝑛𝑛
Weighting factors (𝐻𝐻𝑡𝑡 ) and function arguments (𝑥𝑥𝑡𝑡 ) are presented in table 5.1.
The Gauss quadrature method will be demonstrated by means of the example introduced in the
previous sections.
Evaluate the integral numerically, using four-point Gaussian quadrature. Remember to transform the
limits of integration since the Gauss formula is only valid between limits of 1 and -1.
106
The 𝐻𝐻𝑡𝑡 values for n = 4 are as follows:
𝒙𝒙𝒕𝒕 N 𝑯𝑯𝒕𝒕
4
-0.861136 𝑓𝑓(𝑥𝑥1 ) = 0.33962 𝐻𝐻1 = 0.347855
-0.339981 𝑓𝑓(𝑥𝑥2 ) = 0.365498 𝐻𝐻2 = 0.652145
0.339981 𝑓𝑓(𝑥𝑥3 ) = 405843 𝐻𝐻3 = 0.652145
0.861136 𝑓𝑓(𝑥𝑥4 ) = 0.443352 𝐻𝐻4 = 0.347855
0.8
1 0.8 − 0
� 𝑑𝑑𝑑𝑑 = [𝑓𝑓(𝑥𝑥1 )𝐻𝐻1 + 𝑓𝑓(𝑥𝑥2 )𝐻𝐻2 + 𝑓𝑓(𝑥𝑥3 )𝐻𝐻3 + 𝑓𝑓(𝑥𝑥4 )𝐻𝐻4 ]
0 3 − 𝑥𝑥 1 − (−1)
= 0.310155
Octave has different built-in functions for supporting integration of the function 𝑓𝑓 over an interval 𝑎𝑎
to 𝑏𝑏. These functions are summarised in the table below.
All the rules in table 5.2 follow the basic integration as defined at the beginning of section 5.3. The
Lobatto rule is based on the trapezoidal rule while the Gauss–Konrad rule is an adaptive method of
Gaussian quadrature. It is often referred to as the nested quadrature rule because it follows two
quadrature rules, namely, a higher order one and a lower order one. The calculation error is then
approximated from the difference between the two approximations.
The Clenshaw–Curtis formula is like Gaussian quadrature where the points are not equally spaced,
and is selected on optimal points. However, it differs from Gaussian quadrature in that formulas are
based on sampling of the integrand at Chebyshev points that can be implemented in 𝑛𝑛𝑛𝑛𝑛𝑛𝑛𝑛𝑛𝑛
operations using the fast Fourier transform. The Chebyshev points are specific real algebraic
numbers and are defined as integrating the change of variable 𝑥𝑥 = 𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐.
107
We will not discuss the mathematical derivation of the Lobatto, Gauss–Konrad and Clenshaw–Curtis
rules in detail in this section. Table 5.3 provides a guideline on when to apply the different rules.
Function Characteristic
quadgk Medium accuracy with smooth integrands; can handle oscillatory functions and
infinite bounds
quadcc Low to high accuracy with non-smooth/smooth integrands; can handle oscillatory
functions, singularities and infinite bounds
quad
We will use the built-in Gaussian quadrature function to estimate an answer to the integral. Like
Simpson’s method, the built-in quad function uses a recursive method to stop subdivision of the
interval of panels between 𝑎𝑎 and 𝑏𝑏. In other words, instead of 𝑛𝑛 being chosen upfront, a
tolerance/error is defined and the number of panels is chosen by the program in order to satisfy the
tolerance. The function is used in Octave as follows:
Q=quad(f,a,b,tol)
where 𝑓𝑓 is the function handle and 𝑎𝑎 and 𝑏𝑏 are the upper and lower integration limits, respectively.
The argument tol is optional and, if not specified, the default value that Octave will use is 1e-6.
108
Figure 5.10: The use of quad to evaluate the integral
If we access the Help function, >>help quad, in Octave, the following is noted (refer to figure
5.11):
109
Figure 5.11: Using help quad
We can then evaluate the error of the integral efficiently in a single line of code.
From figure 5.12 we can see that since the IER (integer error code) was 0, the integral was evaluated
successfully in 21 evaluations with a relatively small error.
110
Figure 5.12: Determining the error and number of function calls
quadl
The quadl function is coded in Octave just like the quad function. The function 𝑦𝑦 = 𝑓𝑓(𝑥𝑥) should
accept a vector argument 𝑥𝑥 and return a vector result 𝑦𝑦. Up to this point, we have not given thought
to whether the function is smooth or not. From table 5.3 we can see that quadl is used for smooth
integrands. Smooth functions have a unique defined first derivative (slope or gradient) at every
point. Graphically, a smooth function of a single variable can be plotted as a single continuous line
with no abrupt bends or breaks. So, let us first plot the function to see what it looks like. Revise
learning unit 3 if you have forgotten how to plot in Octave.
In figure 5.13 we can see that the function is smooth between the limits 0 and 0.8. Try plotting the
function between the limits -100 and 100. What can you say about the shape of the curve? Will it
still be smooth/continuous?
111
Figure 5.13: Visualising the function 𝒇𝒇(𝒙𝒙)
Now that we have ascertained that the function we are working with between the limits of 0 and 0.8
is smooth, let us evaluate the function using the built-in quadl function.
112
Figure 5.14: Evaluating an integral using quadl
Unlike quad, the quadl function does not have the ability to evaluate the integer error code or the
estimate of error. The optional output NFUN is used to evaluate the total number of function
evaluations performed. In figure 5.14 we can see that the integral converges to the correct answer in
8 evaluations using quadl compared to 21 evaluations for the same estimate using quad.
quadgk
quadgk uses an adaptive Gauss–Konrad quadrature method of evaluating integrals. Again, the
function handle is required in a vectorised form. The advantage of the quadgk function is that it is
able to handle oscillatory functions and infinite bounds. Using the same function, we will evaluate
the integral from 0 to infinity:
∞
1
� 𝑑𝑑𝑑𝑑
0 3 − 𝑥𝑥
113
Figure 5.15: Using the quadgk function to evaluate an integral
Figure 5.15 shows that the integral cannot be estimated after the maximum interval count of 650 has
been reached. Try evaluating the integral from 0 to 100. What do you notice? At which value do we
obtain an answer without a warning?
Use the help quadgk command to read more about using this function. What is the absolute
tolerance value used to stop the integration procedure?
quadcc
The function quadcc is a robust function in that it can handle discontinuities, singularities and
infinite bounds. Like the other quad functions, this function must be vectorised, that is, it must be in
the element-by-element (or dot) form for all operators. Use help quadcc to read more about how
to use the built-in adaptive Clenshaw–Curtis quadrature rule.
Let us evaluate the same function we have been working with throughout the chapter but from 0 to
∞:
∞
1
� 𝑑𝑑𝑑𝑑
0 3 − 𝑥𝑥
114
Figure 5.16: Using the quadcc function
From figure 5.16 we can see that the function cannot be evaluated in this interval range. The error is
large and the number of points is high. Try plotting the function in the range 0 to 1 000 to see what
happens to the function as it goes toward infinity. This function, evaluated from 0 to infinity, does
not work well, and we are unable to estimate the integral. From figure 5.17 we can see that for an
interval of 0 to 2, the quad function has better accuracy.
115
Let us look at another function:
3
sin (𝑥𝑥)
� 𝑑𝑑𝑑𝑑
−3 𝑥𝑥
>>x=-10:0.2:10;
>>y=sin(x)./x;
>>plot (x,y)
𝐬𝐬𝐬𝐬𝐬𝐬 (𝒙𝒙)
Figure 5.18: Visualising the function
𝒙𝒙
Figure 5.18 shows the plot between the interval -10 to 10 in order to get an idea of the complexity of
the function. Now let us estimate the function for the interval -3 to 3 where the large oscillation is
apparent and compare the reliability of the functions quadcc and quad in figure 5.19.
which is obtained using the quadcc function. The quad function is unable to evaluate the function
and Q yields NaN. From table 5.3 we can see that the function quadgk might also yield a good
estimate with high accuracy for oscillatory functions. The use of guadgk is shown in figure 5.19. The
116
answer obtained using quadgk is the same as that of quadcc with a smaller error. Do you think the
functions quadv and quadl can be used to evaluate the integral?
𝐬𝐬𝐬𝐬𝐬𝐬 (𝒙𝒙)
Figure 5.19: Estimating the function using the quadcc function
𝒙𝒙
Activity 5.3
2
� (𝑥𝑥 2 − 3) 𝑑𝑑𝑑𝑑
1
1.1 Evaluate the integral using three-point Gaussian quadrature by hand. Remember to
transform the limits of integration.
1.2 Plot the function. Which quad function from table 5.3 would be appropriate to use?
1.3 Evaluate the function using the built-in quad function. What can you say about the accuracy
of the solution?
117
3
1
� 𝑑𝑑𝑑𝑑
0 1 + 𝑥𝑥 5
2.1 Evaluate the integral using four-point Gaussian quadrature. Remember to transform the
limits of integration.
2.2 Plot the function over the range -1 to 4. What can you say about the curve? Which quad
function would be appropriate to use in order to evaluate the integral?
2.3 Evaluate the integral using the built-in quad function. Compare the solution with the
solution obtained using the quadcc function. What can you say about the accuracy of the
functions?
2.4 Evaluate the integral between the limits -1 and 4 using the quad and quadcc functions.
Notice how quad is unable to estimate the solution. Why do you think this is so?
4
1
� 𝑑𝑑𝑑𝑑
−1 1 + 𝑥𝑥 5
10
� cos (𝑥𝑥) 𝑑𝑑𝑑𝑑
−10
3.1 Plot the function over the range -10 to 10. Which quad function would you use to evaluate
the integral?
3.2 Evaluate the integral using the appropriate quad function.
1
� 7𝑥𝑥 3 − 8𝑥𝑥 2 − 3𝑥𝑥 + 3 𝑑𝑑𝑑𝑑
−1
4.1 Evaluate the integral by hand using the trapezoidal rule with 𝑛𝑛 = 4 and two-point Gaussian
quadrature.
4.2 Plot the function over the range -1 and 1.
4.3 Evaluate the function using the trapz and quad functions.
5. Estimate
1 1 2
� 𝑒𝑒 −2𝑥𝑥 𝑑𝑑𝑑𝑑
0
using
5.1 Simpson’s rule by hand with spacings of 0.1 – compare your answer with that found using
the adaptive quadv function in Octave
5.2 the six-point Gaussian quadrature formula by hand – compare your answer with that found
using the appropriate quad function in Octave
118
6. Consider the reaction 𝐴𝐴 + 𝐵𝐵 ⇔ 2𝑃𝑃. The forward and reverse reactions are both second order.
We have k1 = 0.08 litre/mol s and k2 = 0.004 litre/mol s. The feed to the reactor system is 400
litres/min of a stream containing CA0 = 1.2 mol/litre, CB0 = 1.5 mol/litre and CP0 = o.3 mol/litre.
Stating your assumptions clearly, determine the volume of the PFR required to convert 60% of
the A in the feed stream. (answer: V = 87 litres)
Assumptions: steady state, isothermal, constant density
60% of A in the feed stream, therefore, x = 0.72
CA = 0.48 mol/litre
CB = 0.78 mol/litre
CP = 1.74 mol/litre
Hint:
𝑑𝑑𝐶𝐶𝐴𝐴
𝑄𝑄 = 𝑟𝑟𝐴𝐴
𝑑𝑑𝑑𝑑
𝑑𝑑𝐶𝐶𝐴𝐴 = −𝑑𝑑𝑑𝑑
𝑑𝑑𝑑𝑑 2
−𝑄𝑄 = −𝑘𝑘1 �𝐶𝐶𝐴𝐴 0 − 𝑥𝑥��𝐶𝐶𝐵𝐵 0 − 𝑥𝑥� + 𝑘𝑘2 �𝐶𝐶𝑃𝑃 0 + 2𝑥𝑥�
𝑑𝑑𝑑𝑑
𝑑𝑑𝑑𝑑
𝑄𝑄 = (0.08)(1.2 − 𝑥𝑥)(1.5 − 𝑥𝑥) − 0.004(0.3 + 2𝑥𝑥)2
𝑑𝑑𝑑𝑑
𝑑𝑑𝑑𝑑
6.67 = (0.08)(1.8 − 2.7𝑥𝑥 + 𝑥𝑥 2 ) − (0.004)(4𝑥𝑥 2 + 1.2𝑥𝑥 + 0.09)
𝑑𝑑𝑑𝑑
𝑑𝑑𝑑𝑑
6.67 = 0.064𝑥𝑥 2 − 0.2208𝑥𝑥 + 0.1436
𝑑𝑑𝑑𝑑
0.72
𝑉𝑉 1
=� 2
𝑑𝑑𝑑𝑑
6.67 0 0.064𝑥𝑥 − 0.2208𝑥𝑥 + 0.1436
7. The reaction 3𝐴𝐴 + 2𝐵𝐵 → 2𝐶𝐶 has a rate given by 𝑟𝑟𝐴𝐴 = −𝑘𝑘𝐶𝐶𝐴𝐴 𝐶𝐶𝐵𝐵 where k = 0.03 m3/kmol.min. The
feed stream to a reactor is 130 m3/min of an aqueous solution containing 6 kmol/m3 of A and 7
kmol/m3 of B. We would like to obtain 60% conversion of A using a PFR. Determine the required
volume. (answer: V = 717 m3)
5.4 Conclusion
Learning unit 5 introduced you to important numerical techniques for estimating integrals using the
trapezoidal rule, Simpson’s rule and quadrature. The basic principle of integration was introduced to
help you understand the mathematics behind the built-in functions, as well as the applicability of the
appropriate functions to the different types of integrals encountered. Table 5.4 contains a summary
of the important functions introduced in this learning unit.
119
Table 5.4: Summary of Octave functions for numerical integration
1. Chapra, SC & Canale, RP. 2015. Numerical methods for engineers. 7th edition. New York:
McGraw-Hill Education.
120