Notes
Notes
ENGINEERING COMPUTING
Joseph M. Powers
updated
19 January 2025, 1:49pm
2
Preface 7
1 Overview 9
1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2 A simple program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.2.1 Downloading the program . . . . . . . . . . . . . . . . . . . . . . . . 14
1.2.2 Saving the program onto the AFS server . . . . . . . . . . . . . . . . . 15
1.2.3 Accessing the campus Linux cluster . . . . . . . . . . . . . . . . . . . 15
1.2.4 Compiling a Fortran program . . . . . . . . . . . . . . . . . . . . . . 18
1.2.5 Editing text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.3 Speed test: Fortran versus MATLAB . . . . . . . . . . . . . . . . . . . . . . . 20
1.4 Some definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.5 Introduction to engineering plotting with MATLAB . . . . . . . . . . . . . . . 22
1.5.1 A bad MATLAB plot. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.5.2 A better MATLAB plot . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.5.3 Another bad MATLAB plot . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.5.4 Another better MATLAB plot . . . . . . . . . . . . . . . . . . . . . . . 26
1.6 Introduction to LATEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.7 Introduction to HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.8 UNIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.9 Online compilers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4 Introduction to programming 39
4.1 Statement types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.2 Example program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.3 Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.4 Another example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3
4 CONTENTS
5 Arithmetic 45
5.1 Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.2 Integer division . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.3 Binary representation of integers . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.4 Overflow and underflow limits . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.5 Assignment of undefined variables . . . . . . . . . . . . . . . . . . . . . . . . 51
6 Arrays 1 53
6.1 Dimension of an array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.2 One-dimensional arrays from time series . . . . . . . . . . . . . . . . . . . . 54
6.2.1 Fixed array size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.2.2 Variable array size via parameter declaration . . . . . . . . . . . . . 59
6.3 Simple writing to files and MATLAB plotting . . . . . . . . . . . . . . . . . . . 60
7 Arrays 2 63
7.1 Varying the array size at run time . . . . . . . . . . . . . . . . . . . . . . . . 63
7.2 Higher dimension arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
7.3 Two-dimensional arrays of variable size . . . . . . . . . . . . . . . . . . . . . 69
7.4 Non-standard do loop increment syntax . . . . . . . . . . . . . . . . . . . . . 70
9 Output of results 89
9.1 Unformatted printing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
9.2 Formatted printing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
9.3 Formatted writing to files . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
10 Reading data 99
10.1 Unformatted reading from a file . . . . . . . . . . . . . . . . . . . . . . . . . 99
10.2 Formatted reading from a file . . . . . . . . . . . . . . . . . . . . . . . . . . 102
12 Functions 107
12.1 Pre-defined functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
12.2 User-defined functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
12.2.1 Simple structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
12.2.2 Use of dummy variables . . . . . . . . . . . . . . . . . . . . . . . . . 112
12.2.3 Sharing data using module . . . . . . . . . . . . . . . . . . . . . . . . 113
12.2.4 Splitting functions into separate files . . . . . . . . . . . . . . . . . . 115
12.2.5 Creation of executable script files . . . . . . . . . . . . . . . . . . . . 117
14 Characters 127
15 Complex 129
16 Logical 135
20 Subroutines: 2 161
21 Modules 163
24 Introduction to C 175
24.1 A hello world program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
24.2 A program using the Euler method . . . . . . . . . . . . . . . . . . . . . . . 176
Bibliography 211
Index 213
These are lecture notes for AME 20214, Introduction to Engineering Computing, a one-
hour sophomore-level undergraduate course taught in the Department of Aerospace and
Mechanical Engineering at the University of Notre Dame.
The key objective of the course is to introduce students to the UNIX operating system
and structured high performance computing with a compiled language, here chosen to be
Fortran 90 and its descendants, as well as some others, such as the interpreted languages
MATLAB, Python, Mathematica, VBA, and Microsoft Excel, and a very brief introduction to
the compiled language C. Thanks to Mr. Travis Brown for help with a C example program
and Ms. Laura Paquin for help with VBA example programs and description.
An important secondary objective is to introduce the student to the process of scientific
computing: the art of using a computer to solve problems of scientific and engineering rele-
vance. To achieve that objective, some attention is focused on numerically solving physically
motivated systems of ordinary differential equations. The most important of these will be
the forced mass-spring-damper system, which will be addressed with a variety of methods.
The notes draw often on the text specified for the course, Chivers’ and Sleightholme’s
Introduction to Programming with Fortran, Third Edition, Springer, London, 2015. The
notes will highlight aspects of this text, and augment it in places. The notes and course data
can be found at https://www3.nd.edu/∼powers/ame.20214. At this stage, anyone is free
to make copies for their own use. I would be happy to receive suggestions for improvement.
Joseph M. Powers
[email protected]
https://www3.nd.edu/∼powers
Notre Dame, Indiana; USA
CC BY: $ = 19 January 2025
\
The content of this book is licensed under Creative Commons Attribution-Noncommercial-No Derivative Works 3.0.
7
8 CONTENTS
Overview
1.1 Motivation
We are faced with a problem in constrained optimization. We seek to maximize student
understanding of
• finite time, embodied in the one credit hour allocated to this task,
We might conjecture that the understanding of these topics, Υ, is a function of the mathe-
matical method µ, the language chosen, λ, the operating system, σ, the pedagogy ρ, chosen,
the time τ allotted for study, the student and instructor skill sets, κ1 and κ2 . In a mathe-
matically inspired language, we might say
Υ = f (µ, λ, σ, ρ, τ, κ1 , κ2 ). (1.1)
9
10 CHAPTER 1. OVERVIEW
Our constraints are for time τ , student skills κ1 and instructor skills κ2 . Our constrained
optimization problem might be stated as, select µ, λ, σ, and ρ so as to
• optimization problems.
We are presented with a wide variety of computing languages to formulate these problems,
including
• Ada,
• Pascal,
• C,
• C++,
• C#,
• Java,
• Mathematica, or
• Microsoft Excel.
We are presented with a wide variety of operating system environments in which to execute
our programs including
• Microsoft Windows,
• DOS,
• OS-X,
• UNIX, or
• Linux.
Following considerable consideration, coupled with some experimentation, we believe the
near-optimal solution, reflecting the severe constraint of τ = 1 credit hour is given by the
following: student understanding, Υ, of engineering mathematics, relevant languages, and
advanced operating systems is given by choosing
• λ = Fortran 2003,
• σ = Linux.
Near neighbors within the solution space are also perfectly acceptable, e.g. Fortran 90,
Fortran 95, Fortran 2008, UNIX, OS-X. If the constraints of the curriculum evolve, and
languages and operating systems evolve, the optimal solution may evolve!
All choices have advantages and disadvantages. Certainly one chooses modes of trans-
portation depending on a variety of needs. We depict rough and imperfect analogies be-
tween some modern transportation choices and modern computing languages in Fig. 1.1.1
For transportation purposes, one might imagine that
• The racing cycle has speed, power, and agility but requires a highly trained user to
achieve peak performance. It maps into C.
• The modern muscle car has all features expected by most mass-market drivers, draws
heavily on past experiences, but still may not be the right machine for all market
segments. It maps into Fortran.
1
images from
http://motorsportsnewswire.files.wordpress.com/2011/05/infineon 2011 brammo empulse rr.jpg
http://www.netcarshow.com/ford/2013-mustang boss 302/1600x1200/wallpaper 01.htm
http:///www.motortrend.com/news/2017-dodge-grand-caravan-first-drive-not-dead-yet/
http://www.motorzoeker.nl/public/motorfotos/large/vespa/5611 foto1 k25j3xt2j8.jpg
https://commons.wikimedia.org/wiki/File:Campagna T-Rex 14-R rear left.jpg
• The minivan is appropriate for a wide variety of drivers and passengers, is durable,
and optimized for safety; it will not compete well in a race. It maps into MATLAB.
• The scooter is affordable, maneuverable, and is appropriate for many urban environ-
ments; it is not right for the highway. It maps into Excel.
• The motorized reverse tricycle is stable for some highway use, but unconventional. It
maps into VBA.
Now focusing on our actual computing systems, we list some advantages and disadvan-
tages associated with our present choices. First for Fortran:
• Fortran advantages
– a compiled language which yields very fast binary executable code widely used for
large scale problems in computational science, e.g. the widely used Top 500 su-
percomputing benchmark problem is based on Fortran-implemented algorithms.
– used in many modern supercomputing applications, e.g. the Department of En-
ergy’s major initiative in scientific computing for the 21st century, Predictive
Science Academic Alliance Program (PSAAP),
– explicitly designed for mathematical problems common in engineering; pedagog-
ically straightforward implementation of standard notions such as sine, cosine,
exponential, vectors, and matrices,
– widely used for decades in engineering with a large data base of legacy code and
packaged software,2
2
see http://www.netlib.org/
• Fortran disadvantages
– widely used,
– allows user to more easily understand computer system architecture,
– freely available
– very similar to UNIX and OS-X.
• Linux disadvantages
Whatever language and operating system we use, and this course will consider Fortran
with short excursions into C, MATLAB, Microsoft Excel, VBA, and Mathematica, the essential
job of nearly any programming language is executing so-called three R’s:
• Readin’
• ’Ritin’
• ‘Rithmatic
A typical program will change the order (and we will now use proper spelling) and first
Recognizing the various methods that various languages use to execute the three R’s is the
key to learning a new computer language. There are a small number of typical operations
in scientific computing. Once the student learns how to do an operation in one language, it
is much easier to translate these steps to any of the other languages. Thus, in some sense,
learning a computer language may be more important than learning any particular computer
language. That is because learning a language typically entails learning the more complex
generalities associated with all languages.
program test
print*,’hello world’
end program test
One can download this program from the web by clicking the following web link,
https://www3.nd.edu/∼powers/ame.20214/2e/helloworld.f90
The first line of the program is the program name, where the name is arbitrary. The second
line tells the program to print to the screen, indicated by a ∗, the words within the single
quotation marks. The program is ended by a program end statement. The file name which
ends in “.f90” is essential and tells the compiler that this file follows the syntax of Fortran
90 and beyond, beyond including Fortran 90, 95, 2003, and 2008. It should be noted
that our local system can in fact invoke the Fortran 2003 standard, but for nearly all
problems we will consider, the Fortran 90 standard will suffice.
That said, many users do have sufficient experience to go directly to remote login from a
laptop, and that procedure is described here. One important machine for remote login is
the campus Linux machine darrow.cc.nd.edu. The machine darrow is useful because all
campus personnel can log in to it from any remote site, on or off campus. Here is what one
might do if logging in from the Terminal application of a personal Macintosh machine using
the so-called “secure shell” program ssh:
[powers@darrow5 ~]$
Here, the argument of the −l option is your netid. Mine is powers. The general form is
ssh -X darrow.cc.nd.edu -l netid
If darrow.cc.nd.edu is overloaded with too many users, a user may log in remotely to
any of a set of virtual Linux machines. Their names are
remote101.helios.nd.edu
remote102.helios.nd.edu
remote103.helios.nd.edu
remote104.helios.nd.edu
remote105.helios.nd.edu
remote106.helios.nd.edu
remote107.helios.nd.edu
remote108.helios.nd.edu
remote201.helios.nd.edu
remote202.helios.nd.edu
remote203.helios.nd.edu
remote204.helios.nd.edu
remote205.helios.nd.edu
remote206.helios.nd.edu
remote207.helios.nd.edu
remote208.helios.nd.edu
For example to log in remotely to one of the virtual Linux machines, one might execute the
command sequence
Remote use of this system is not for running big processes. If you need to
run big processes for research, please get an account from Center of Research
Computing (http://crc.nd.edu).
Other campus Linux machines are useful as well, but the user must be sitting at the
machine. A practical advantage of these physical machines is they only allow a single user,
so they will not become overloaded. Several such Linux machines can be found in
Another common way, which requires a little more effort, to bring UNIX functionality
into a Windows environment is to install the free, open-source UNIX-emulator, Cygwin, onto
a Windows machine.
https://www.cygwin.com
• ifort, and
• gfortran.
The compiler ifort is the so-called Intel Fortran compiler. The compiler gfortran is
an open source compiler. The ifort compiler works on most campus Linux machines, but
may not work for all on darrow.cc.nd.edu. The gfortran compiler should work on all
campus Linux machines. Focus here will be on the ifort compiler; though it is a useful
exercise to make sure your program compiles and executes on a variety of compilers, as there
can be subtle differences. All these compilers work in essentially the same way. For instance
to use ifort to compile helloworld.f90, we perform
This generates a so-called “binary” executable file, which is not easily viewable, named
“a.out”. We execute the file a.out via the command and get
The output of the program is printed to the screen. Though it is not at all important for this
problem, we actually compiled the program with a Fortran 90 compiler. We can compile
and execute the program in Fortran 2003 via the command sequence
Here, the so-called compiler option, -stand f03, enforced the compilation using the Fortran
2003 standard.
We can compile and execute the program with the gfortran compiler via the command
sequence
This command spawns a new window in which the file helloworld.f90 can be edited and
saved. The character & is a useful UNIX command which commands the system to allow the
terminal window to be used simultaneously with the program gedit. If one is using gedit
from a remote terminal or personal laptop machine, one must be sure to have logged in from
a so-called X terminal window, using the command ssh -X darrow.cc.nd.edu -l userid
in order for the edit window to display. This is straightforward on a Macintosh computer
through use of its terminal application found in the Utilities folder. On a Windows
laptop, one may wish to use the terminal available via the Cygwin package. This is not an
issue if the user is seated at the actual machine in use.
An incomplete list of common text editors available on the campus Linux cluster, each
with advantages and disadvantages is as follows:
• gedit
• Kate, invoked by kate on the Notre Dame cluster (but not on darrow)
• vi
One can also use ordinary text editors on personal computing machines and save the file as a
plain text file in the appropriate space. Note that one should not save a Fortran source code
file in the common “rich text format” (.rtf) and expect it to be able to compile correctly.
When n is large, it will take a long time to execute the initialization. Let us perform
this process via Fortran and MATLAB on the linux machine, darrow.cc.nd.edu. We shall
take n = 5000, a modestly sized matrix for scientific computing. The Fortran program
matrix.f90 and its execution are as follows:
We shall worry about the details of the program later. Note for now that there are many
complexities to execute this seemingly simple task. This is typical of Fortran codes. We
can check the speed of the program by executing with a UNIX utility time. We find
It must be emphasized that these numbers are typical, but unreliable. The machine may
have been performing different background tasks. Also, one could use optimizing Fortran
compilers to improve Fortran execution time. The main reason for the fast execution of the
Fortran program is that it was compiled prior to execution, whereas the MATLAB program,
using a so-called interpreted language was not. All things equal, compiled languages are typ-
ically much faster than interpreted languages. However, in most cases, interpreted languages
have been designed to be more user-friendly. Note that it is possible to use compiled versions
of MATLAB to improve its execution time significantly.
• Central Processing Unit (CPU) is, in colloquial terms, the main brain of the computer.
• One of the more important memory devices is Random Access Memory (RAM). This
memory is usually transient in that it is only active when the machine is turned on.
It is not used for permanent storage of files. Permanent storage is achieved via hard
drives, memory sticks, etc.
• A terminal is a device which allows direct input and output communications between
a user and the CPU of a machine. Terminals come in many flavors, including virtual.
• Software is an imprecise term which describes programs which allow interaction be-
tween the user and the computer. High level software is often more user-friendly and
has several layers of abstraction between the user and CPU. Low level software has
fewer levels of abstraction, is often more difficult to understand, but often tightly linked
to the CPU architecture. Microsoft Excel is a high level software tool. MATLAB is
somewhat lower level, but still at a high level. Fortran is at a lower level still, but in
many ways a high level language. So called assembly language is much closer to the
machine, and is certainly a low level software tool.
• A compiler, such as ifort, is a tool to convert a high level language such as Fortran
into a fast executable binary low level language usable by the machine. Use of com-
piled languages is highly advantageous for large scale problems in scientific computing
because of the speed of execution. For small scale problems, non-compiled interpreted
languages, such as MATLAB, are advantageous because of their relative simplicity of use.
• A text editor allows the user to alter the source code. Text editors typically refer to
tools which give the user access to the entire ASCII (American Standard Code for
Information Interchange) text of the file and avoid use of hidden and/or binary text.
• If there is more than one curve, be sure the reader knows which curve corresponds to
which case. There are a variety of ways to achieve this. The best is probably to use
combinations of solid lines, dashed lines, dotted lines, etc. Different lines can also be
assigned different colors, but one should recognize that sometimes the user will print
files with black and white printers, obscuring the meaning. Also, some colors are hard
to discern on varieties of computer screens and printers.
• Generally, reserve point markers like small circles or dots for cases where
Often it is best not to “connect the dots” especially if there is no reason to believe that
another data point, if sampled, would lie exactly on the interpolating curve.
• Generally, reserve smooth curves with no small circles or dots for cases where
• Use linear, log-linear, and log-log scaled plots as appropriate for the data at hand.
Sometimes linear scales hide the true nature of the data, and sometimes they reveal it.
The same can be said for log-linear and log-log scales. Be sure to examine your data,
and choose the most revelatory scaling.
x y
0 1
2 4
3 8
4 7
7 10
10 19
MATLAB defaults typically produce faulty plots. The following MATLAB script is an example:
x = [0,1,3,4,7,10];
y = [2,4,8,7,10,19];
plot(x,y)
This script generates the plot of Fig. 1.2. Figure 1.2 has the following problems:
20
18
16
14
12
10
2
0 1 2 3 4 5 6 7 8 9 10
• The numbers on the axes are much smaller than the font size of the surrounding text.
This problem is pervasive when MATLAB default values are used.
• The axes are not labeled.
• The raw data should be indicated with distinct points. Though optional, it is probably
best not to connect them.
25
20
15
y
10
0
0 2 4 6 8 10 12
x
10
10
8
10
6
10
4
10
2
10
0
10
−2
10
−4
10
−6
10
−2 −1 0 1 2 3
10 10 10 10 10 10
clear;
n = 1000;
xmin = 0.01;
xmax = 1000;
dx = (xmax-xmin)/(n-1);
for i=1:n
x(i) = xmin+(i-1)*dx;
y1(i) = x(i)^2;
y2(i) = x(i)^3;
end
loglog(x,y1,x,y2),...
xlabel(’x’,’FontSize’,24),...
ylabel(’y’,’FontSize’,24)
legend(’y=x^2’,’y=x^3’,’Location’,’NorthWest’)
set(gca,’FontSize’,20)
This script generates the plot of Fig. 1.5. Here the data were plotted as continuous curves,
the two curves were clearly distinguished and labeled, and the font sizes were increased to
be nearly the same as that of the surrounding text.
10
10
y=x2
y=x3
5
10
0
10
y
−5
10
−10
10 −2 0 2 4
10 10 10 10
x
• It produces the best output of text, figures, and equations of any program I’ve seen.
• It is the tool of choice for many research scientists and engineers. Many journals accept
LATEX submissions, and many books are written in LATEX.
Some basic instructions are given next. You can be a little sloppy about spacing. It ad-
justs the text to look good. You can make the text smaller. You can make the text tiny. You can
link to web sites
Skip a line for a new paragraph. You can use italics (e.g. Computers are everywhere) or
bold. Greek letters are a snap: Ψ, ψ, Φ, φ. Equations within text are easy— A well known
equation for a line is y = mx + b. You can also set aside equations like so:
d2 x X
m = F, Newton’s second law. (1.9)
dt2
Eq. (1.9) is Newton’s second law. References3 are available. If you have an postscript file,
say f1.eps, in the same local directory, you can insert the file as a figure. Figure 1.6 gives
y
103
101
10-1
10-3
10-5
10-7
x
0.01 0.1 1 10
a log-log plot of some data. Figure 1.6 was first created with MATLAB, was saved as a .eps
file, then imported into Adobe Illustrator to adjust the fonts to match those of the main
text. In this case, it was necessary to download common LATEX fonts onto a local machine.
Running LATEX
You can create a LATEX file with any text editor (vi, Emacs, gedit, etc.). To get a
document, you need to run the LATEX application on the text file. The text file must have
the suffix “.tex” On a Linux cluster machine, this is done via the command
This generates file.pdf. You should execute this command at least twice to ensure correct
figure and equation numbering.
Alternatively, you can use TeXShop on a Macintosh or TeXnicCenter on a Windows-based
machine.
See course TAs for information on how to connect your individual machine to this file
space.
The key file to get a web site going must be named index.html and must reside in the
www folder. An example is given in the file index.html, listed next.
<html>
<head>
<title>My Home Page</title>
</head>
<p>
<a href=https://www3.nd.edu/~powers/ame.20214/helloworld.f90>Link</a> to the file
helloworld.f90. Whatever file to which you link must reside in the proper
directory.
<p>
<a href=https://www.google.com>Link</a> to Google.
</html>
When this file is opened in a browser, one might expect to see something like the screen
shot of Fig. 1.7.
Figure 1.7: Screen shot of a web browser which opened the file index.html.
• Commands within HTML are begun with the structure <....> and ended with the
structure </.....>.
• Examples include
– <html>, </html>, opens and closes the file and identifies is as an html file. The
file itself must be named with the .html extension.
– <head>, </head>, begins and ends the header.
– <title>, </title>, begins and ends the title of the header.
– <a .....>, </a>, begins and ends a link to a page
– <p>, skip a line.
• There are many other commands which can be used, and one can consult one of many
references to find information.
• Many applications have WYSIWYG ways to create and store HTML files.
1.8 UNIX
We will focus on the UNIX operating system and its variants. A full understanding of this
extensive system is beyond the scope of this course, so we shall focus only on the fun-
damentals, which are not difficult. A good source for more help with UNIX is found at
https://www.tjhsst.edu/∼dhyatt/superap/unixcmd.html. Here, we simply summarize
a few simple commonly used commands relevant to the UNIX operating system.
• pwd print working directory. This tells you where you are in the file structure.
• .. A shortcut for one directory up the tree structure from the working directory.
• cd directory This changes directories to the directory named directory, which must be
a sub-directory of the current working directory.
• ls -lrt This lists the elements contained within the working directory in detailed
form, also giving the ordering by files most recently modified.
• rm file This removes the file named file from the directory.
• cp file1 file2 This copies the file named file1 into the file named file2. If file2 already
exists, it is overwritten by file1.
• mv file1 file2 This 1) moves the file named file1 into the file named file2, and 2) removes
the file named file1. If file2 already exists, it is overwritten by file1.
• mkdir directory This creates the directory named directory within the working direc-
tory.
• rmdir directory This removes the directory named directory. The directory must be
empty in order to remove it.
• cat file Concatenate (i.e. print to the screen) the contents of file.
• more file Print to the screen the contents of file one screen at a time and use the space
bar to move down in the file.
• less file Like more except one can use arrows or j, k keys to navigate up and down
in file.
• UNIX command & Execute the process UNIX command in the background so as to
keep the terminal window available for user input.
One should note that other operating systems such as OS-X or Microsoft Windows have
file system devices such as OS-X’s “Finder” which give a WYSIWYG view of the UNIX tree
structure of organizing files. The two approaches are entirely compatible, and in fact can be
applied to arrange the same files. One is simply more visual than the other.
A file can be identified by its local address as long as the user resides in the proper
directory. For example to view the file helloworld.f90, one first insures it lives within the
present directory, and then executes
If the user resides in a different directory and still wishes to view the same file without first
navigating to that directory, one can used the absolute address, for example
A highly useful feature of most modern UNIX implementations is the arrow keys’ ability
to recall previous commands and edit them. It is difficult to display this without an actual
demonstration.
Here we illustrate some of the power of UNIX commands. The user may want to copy all
of the sample Fortran programs from the course home space to the user’s personal home
space. Since at Notre Dame both the course home space and the user’s home space are all
within AFS, and because the course home space is a public directory, copying is easy and can
be done in a few simple commands. The sequence of commands is described as follows:
4. Copy all files with an .f90 extension into your new directory.
Here mkdir made the new directory programs. We then moved into the directory programs,
via the cd command. We then listed the files within programs and found that it was empty.
We then copied all files with the .f90 extension into the existing directory, indicated by
the “dot”, [.], shorthand for the existing directory. We then re-listed the programs in the
directory and found ten new programs listed.
Here, we summarize a few of the key concepts of this chapter. Problems are often formu-
lated in words, which can be ambiguous. Some problems are amenable to mathematical and
computational analysis, and a challenging chore is to translate imprecise words into precise
computer code. The code to solve the posed problem is based upon a logical construct known
as an algorithm. An algorithm is much like a recipe for cooking. An important element of
most good scientific computing task involves what is known as object-oriented programming.
Such an approach relies upon identifying repetitive tasks and writing a single algorithm for
a task that is commonly executed as part of solving a larger problem. These building blocks,
known as objects can be highly refined and optimized since they will be repeated many times
in the course of a calculation. One might imagine developing a sub-algorithm for performing
matrix inversion within a larger problem that requires inversion of many matrices of different
types. Rather than write separate code for each matrix inversion, one writes one subroutine
to invert matrices of arbitrary dimension, provided of course they are invertible. Then that
subroutine may be called upon many times within the more general algorithm.
35
36 CHAPTER 2. INTRODUCTION TO PROBLEM SOLVING
Introduction to programming
languages
One can consult the text for a fine summary of the history of programming languages.
37
38 CHAPTER 3. INTRODUCTION TO PROGRAMMING LANGUAGES
Introduction to programming
1. data description statements: These set the type of data, for example, real, integer,
character, each of which have different features.
2. control structures: These are instructions for how the program is to proceed, for ex-
ample do, if.
3. data processing statements: These instructions actually process the data. If the data are
numbers, a data processing operation might include addition, x=x+1. This is a typical
data processing statement, which is mathematical, but not ordinary mathematics! It
says to take the number x, add one to it, and replace the value of x. We think of it as
an assignment statement rather than a mathematical equation. So, if we start with x
with a value of 5 the processing statement x=x+1 maps 5 into 6.
4. input and output (I/O) statements: These statements allow the program to commu-
nicate with the outside world by reading in data and writing out data. An input
statement will often have a read and an output statement will often have a write or
print.
39
40 CHAPTER 4. INTRODUCTION TO PROGRAMMING
program ch0401
!
! This program reads in and prints out a name
!
implicit none
character*20 :: first_name
!
print *,’ type in your first name.’
print *,’ up to 20 characters’
read *,first_name
print *,first_name
!
end program ch0401
• Lower case characters are used. In old versions of Fortran, upper case was often the
only option. Today, Fortran is simply case-insensitive, so it does not matter. Many
programmers find it æesthetically pleasing to exclusively use lower case. Our text
sporadically reverts to the older convention of upper case. The important thing for
you to recognize is that as far as a Fortran compiler is concerned the variables are case
insensitive; e.g. a variable named VaLuE is seen by the Fortran compiler as identical
to value.
• The order of the statements is important. First things are done first. Last things are
done last.
• The opening statement is the program name and must appear. It is useful to give the
program a meaningful name. Here, we mean the first program of Chapter 4.
• The character “!” denotes a comment statement. They are ignored by the compiler, but
are very useful to the program author and readers who are trying to understand your
program. It is a good practice for students to insert a surplus of comment statements
in their programs.
• The statement implicit none is a highly useful statement that should be included in
all of your programs. It forces you to declare the type of all variables. And if you make
a typographical error in your actual program, you will likely have mis-typed a variable
name, and the compiler will identify this error for you. Otherwise, the compiler may
simply assign a value of 0 to your mis-typed variable, and this can cause your program
to yield results which are difficult to interpret.
• The statement character*20 :: first name declares the variable first name to
be a character variable. Such a variable is one whose value is an ASCII character. It
is not a number. The character here is defined to be up to 20 characters in length.
Note that character*20 works in most older Fortran compilers, but generates a com-
piler WARNING when the Fortran 2003 standard is imposed with the ifort compiler.
Note that compiler warnings are not compiler errors; a program which compiles with
warnings will still execute. To meet the 2003 standard, one can use the command
character (len=20).
• The print statement sends output to the screen. It is an I/O statement; specifically, it
is an O statement. The ∗ indicates the output is unformatted. Later, we shall see how
to format output. The print statement must be followed by a comma. Items within
single right-leaning apostrophes are those which are actually printed to the screen.
• After the data has been read, it is then outputted in an unformatted fashion to the
screen.
• integer: e.g. -461; depending on the computer architecture, e.g. 32 or 64-bit machines,
the upper and lower bounds of the accepted integers can be extended. For a 64-bit
machine, we might say integer (kind=8).
• real, a seven significant digit real number, e.g. 1.234567. This is equivalent to the
statement real (kind=4).
• complex, a seven significant digit complex number, e.g. 1.234567 + 7.654321i. This is
equivalent to the statement complex (kind=4).
Arithmetic
Here, we will reinforce some notions introduced earlier regarding arithmetic on a digital
computer using Fortran. There are several important issues which arise due to precision
limits of the machine as well as specific syntax. Many notions are consistent with standard
mathematics, but some idiosyncrasies arise because of finite precision as well as the need to
have different data types for integers and real numbers.
5.1 Operations
There are five key operations available: To avoid surprises, one should use parentheses liber-
addition +
subtraction -
division /
multiplication *
exponentiation **
ally to avoid confusion when applying operations. If parentheses are not used, Fortran has
a complicated set of priorities for which operation takes precedence. For example, consider
the mathematical expression
5.(1. + 3.)
x= . (5.1)
4.
The following is the preferred way in Fortran to perform this operation:
x = (5.*(1.+3.))/4.
The following is acceptable as well
45
46 CHAPTER 5. ARITHMETIC
x = 5*(1.+3.)/4.
Turning this around, one might ask what is the mathematical meaning of the Fortran
assignment
x = 1.+2./3.-4.*5.
In Fortran, multiplication and division take priority over addition and subtraction, so the
expression can be interpreted mathematically as
2. 55.
x = 1. + − (4.)(5.) = − = −18.33333..... (5.2)
3. 3.
Ordinary mathematics would hold that c should have the same value as i. Both are
found by forming a/b. But their values are different. This is because we have declared c to
be real and i to be integer. The number i must be an integer, and the rule applied was
to round down to the nearest integer, which here was 0.
Another example is seen next in ch0503.f90:
• The integer representation can lead some operations to execute more efficiently, e.g.
x2 when x is real is executed faster and with more accuracy as x ∗ ∗2 than x ∗ ∗2.0.
i = 1
j = 3
print*,i/j
print*,real(i)/real(j)
print*,real(i,8)/real(j,8)
print*,real(i,16)/real(j,16)
end program ch5a ! end of program
[powers@darrow2-p 2e]$ ifort ch5a.f90
[powers@darrow2-p 2e]$ a.out
0
0.3333333
0.333333333333333
0.333333333333333333333333333333333
[powers@darrow2-p 2e]$
Note that i/j maps to 0 for i = 1 and j = 3. The command real(i) gives us a single
precision real version of i, and similarly for j. The commands real(i, 8) and real(i, 16)
give double and quad precision versions of i, and similarly for j.
Here, s is the sign of the integer (±), lk takes on the value of 0 or 1, and q is the maximum
number of terms our computer permits.
Testing the ifort compiler on darrow.cc.nd.edu however shows that the largest integer in
default operating mode is actually 2147483647, when using default compilation. However,
one can invoke 64 bit integers via the compilation command ifort -integer-size 64. For
example, we find for the program ch5d.f90
that we recover the maximum integer limit for a 64 bit architecture. There is an equivalent
syntax for gfortran to invoke 64 bit integers:
For real numbers, there are similar limits. While actual values can vary, C&S report
typical real numbers in a 32-bit architecture machine must be such that
Numbers outside these bounds can generate what is known as overflow and underflow errors.
Note that 0. is not in itself an underflow. Sometimes a compiler will not report an underflow
error, but instead will map the result to zero.
These can actually be checked. On darrow.cc.nd.edu using the ifort compiler, the
ranges are in fact smaller. The program ch5b.f90 yields the following:
[powers@darrow2-p 2e]$ cat ch5b.f90
program ch5b ! beginning of the program
implicit none
real(16) :: x
x=1.e10
print*,’10**4930=’,x**493
print*,’10**-4930=’,x**-493
print*,’10**5000=’,x**500
print*,’10**-5000=’,x**-500
end program ch5b ! end of program
[powers@darrow2-p 2e]$ ifort ch5b.f90
[powers@darrow2-p 2e]$ a.out
10**4930= 1.000000000000000000000000000000001E+4930
10**-4930= 1.000000000000000000000000000000032E-4930
10**5000= Infinity
10**-5000= 0.000000000000000000000000000000000E+0000
[powers@darrow2-p 2e]$
The actual bounds of the intel compiler on darrow.cc.nd.edu in quad precision, found
using the commands tiny(x) and huge(x), are
Numbers outside this bound are reported as Infinity, which will induce difficulties. Under-
flow numbers are mapped to zero, which can also cause surprises and consequent difficulties,
especially if division by that number is required later in the calculation! Note in double
precision using ifort or gfortran on darrow.cc.nd.edu, we find instead
Note we did not initialize the integer m or the real y. In both cases, ifort assigned them
a value of zero. This can cause surprises if it is not intended for the variables to take on a
value of zero.
As an aside, we also wrote the output to a file. To do so we had to open the file, using
the command
open (unit=10,file=’out.txt’)
This opens a file which we have named out.txt. It will be a plain ASCII text file which we
could edit with any text editor, like gedit. To populate this file, we must write to it. We
have chosen to write twice to the file via the write commands
write(10,*) n,m,n*m
write(10,*) x,y,x*y
The number 10 is linked via the open statement to the file out.txt. After execution, we
find that out.txt has been created and populated with output.
Arrays 1
53
54 CHAPTER 6. ARRAYS 1
The vector of Eq. (6.2) is of dimension 7 × 1 and is also a one-dimensional array. Note that a
scalar φ might be thought of as a 1 × 1 array (or for that matter a 1 × 1 × 1 three-dimensional
array:
φ= 9 . (6.3)
A scalar can be thought of as a zero-dimensional array, since it has no non-unity dimensions.
Two-dimensional arrays are known as matrices. An example might be
1 6 8 9
A = 2 −4 2 10 . (6.4)
−9 0 1 5
This array has dimension 3 × 4. In four-dimensional space, it could be represented as
3 × 4 × 1 × 1 array. Because only two of the dimensions are non-unity, we take A to be a
two-dimensional array.
i t (hr) T (K)
1 0 270.00
2 2 265.00
3 4 234.00
4 6 260.00
5 8 261.34
6 10 265.00
7 12 270.00
8 14 275.00
9 16 278.66
10 18 280.00
11 20 278.66
12 22 275.00
13 24 270.00
because it reminds us of our full range of options. Alternatively, we could have used
the simpler
where the first index is by default 1. Or we could have used the simpler still
The second form is common, and tells us both t and temp are one-dimensional arrays
of length 13.
• We set parameter values for a, b, and c. It is good practice to leave as much generality
as possible in your program.
• While we could have defined π, we chose to let the computer do it, since we know from
trigonometry that
π
= tan−1 1. (6.10)
4
Note that in Fortran, the function tan−1 is given by atan. We printed π to the screen
to make sure our formula was correct.
• It is good practice to indent items within the do loop so that it is clear to the reader
what is in and outside of the loop.
• We note that we seem to have only achieved single precision results! Note that at
t = 2, we should have
2π(2)
T = 270 − 10 sin , (6.11)
24
π
= 270 − 10 sin , (6.12)
6
1
= 270 − 10 , (6.13)
2
= 265. (6.14)
The result should be nearly exactly 265, but we see precision errors in the last six
digits, namely temp(2) = 264.999999873816. Why? If we truly want double precision
accuracy, we must take care that every constant is truly double precision.
The following modification, ch6b.f90, allows for single, double, and quad precision, which
we exercise here for double precision:
[powers@darrow1-p ame.20214]$ cat ch6b.f90
program temperature
implicit none
integer, parameter :: p=8
integer (kind=8) :: i
real (kind=p), dimension(1:13):: t,temp
real (kind=p), parameter :: a=270._p, b=10._p, c = 24._p
real (kind=p) :: pi
pi = 4._p*atan(1._p)
print*,’pi = ’, pi
do i=1,13
t(i) = 2._p*(i-1)
temp(i) = a - b*sin(2._p*pi*t(i)/c)
print*,i,t(i),temp(i)
end do
end program temperature
[powers@darrow1-p ame.20214]$ ifort ch6b.f90
[powers@darrow1-p ame.20214]$ a.out
pi = 3.14159265358979
1 0.000000000000000E+000 270.000000000000
2 2.00000000000000 265.000000000000
3 4.00000000000000 261.339745962156
4 6.00000000000000 260.000000000000
5 8.00000000000000 261.339745962156
6 10.0000000000000 265.000000000000
7 12.0000000000000 270.000000000000
8 14.0000000000000 275.000000000000
9 16.0000000000000 278.660254037844
10 18.0000000000000 280.000000000000
11 20.0000000000000 278.660254037844
12 22.0000000000000 275.000000000000
13 24.0000000000000 270.000000000000
[powers@darrow1-p ame.20214]$
Note:
• The parameter p sets the precision; here, we have p = 8, for double precision.
• Every numerical constant is defined in terms of its precision, e.g.
4._p
• The results now have true double precision accuracy.
Note
• The array size is allowed to vary when the parameter statement gives the actual size
of the array.
• We now have a variable time step dt which will have to be calculated. Mathematically,
the formula is
tmax
∆t = . (6.15)
imax − 1
So, if we just have one time step, imax = 2 and ∆t = tmax . If we have two times
steps, imax = 3, and ∆t = tmax /2. For our imax = 7, we have six time steps with
∆t = tmax /6 = (24 hr)/6 = 4 hr.
• We calculated dt, taking care to convert integers to reals when dividing. The com-
mand real(imax) simply converts imax to its single precision real number equivalent.
Recall if we had wanted a double precision real, we would have used the command
real(imax, 8).
pi = 3.141593
1 0.0000000E+00 270.0000
2 2.000000 265.0000
3 4.000000 261.3398
4 6.000000 260.0000
5 8.000000 261.3398
6 10.00000 265.0000
7 12.00000 270.0000
8 14.00000 275.0000
9 16.00000 278.6602
10 18.00000 280.0000
11 20.00000 278.6602
12 22.00000 275.0000
13 24.00000 270.0000
[powers@darrow2-p ame.20214]$
Now we next write and execute a simple MATLAB script, taking care to see it resides in the
same directory as our file temperature.out. The MATLAB script is given in ptemperature.m:
clear;
load(’temperature.out’)
t = temperature(:,1);
temp = temperature(:,2);
plot(t,temp,’-o’),...
xlabel(’t (hr)’,’FontSize’,24),...
ylabel(’T (K)’,’FontSize’,24);...
set(gca,’FontSize’,20)
The contents of temperature.out are loaded into MATLAB via the load command. The first
column is assigned to time t and the second column is assigned to temperature temp. We
then make a plot, taking care to include larger than default font sizes, as well as small circles
for the individual points, and axes labels with units. The command
’FontSize’, 24
within xlabel and ylabel, changed the font size for the axes labels. The command
set(gca,’FontSize’,20)
changed the font size for the numbers on the axes. The figure is shown in Fig. 6.1. While the
MATLAB-generated plot is not bad, it has some minor flaws. The exact solution is not shown,
only a straight line interpolation between points. It is possible to reset MATLAB defaults to
avoid these flaws. Alternatively, we can import the .eps file into another application, such
as Adobe Illustrator, and edit the plot with this highly potent tool. We show in Fig. 6.2
a plot of the continuous function of Eq. (6.6) and the discrete values at the sample points,
after further processing with Adobe Illustrator.
280
275
T (K)
270
265
260
0 5 10 15 20 25
t (hr)
Figure 6.1: Temperature versus time; figure directly from MATLAB, saved in .eps format.
T (K)
280
275
270
265
5 10 15 20 t (hr)
Figure 6.2: Continuous and discrete values of T (t); plot improved with Adobe Illustrator.
Arrays 2
63
64 CHAPTER 7. ARRAYS 2
end do
end program temperature
[powers@darrow1-p ame.20214]$ ifort ch7a.f90
[powers@darrow1-p ame.20214]$ a.out
Enter number of data sampling points
7
pi = 3.141593
1 0.0000000E+00 270.0000
2 4.000000 261.3398
3 8.000000 261.3398
4 12.00000 270.0000
5 16.00000 278.6602
6 20.00000 278.6602
7 24.00000 270.0000
[powers@darrow1-p ame.20214]$ a.out
Enter number of data sampling points
13
pi = 3.141593
1 0.0000000E+00 270.0000
2 2.000000 265.0000
3 4.000000 261.3398
4 6.000000 260.0000
5 8.000000 261.3398
6 10.00000 265.0000
7 12.00000 270.0000
8 14.00000 275.0000
9 16.00000 278.6602
10 18.00000 280.0000
11 20.00000 278.6602
12 22.00000 275.0000
13 24.00000 270.0000
[powers@darrow1-p ame.20214]$
• The variables t and temp have not been dimensioned, but have been declared as arrays
with no dimensions as of yet.
• The dimensions of the arrays, imax is read in from the screen and given as direct input
by the user.
• Once read in, the array dimensions of t and temp are assigned with the allocate
function.
x3
f (3)
T33
T32
T31
T23 f (2)
T13 T22
T21
T12
T11 x2
f (1)
x1
• The program is compiled once and executed twice, each time for a different value of
imax. The first value is 7 and the second value is 13; no recompilation is necessary.
resents a force per area. Each of the surface tractions can be represented in terms of its
three-dimensional Cartesian components, e.g.
Here e1 , e2 and e3 are unit vectors in the 1, 2, and 3 directions, respectively. We see a
structure in these equations, and in fact are inclined to organize the values of Tij into a
two-dimensional array, defined as the stress tensor T:
T11 T12 T13
T = Tij = T21 T22 T23 (7.4)
T31 T32 T33
They are equivalent to the familiar i, j, and k. Now, detailed analysis reveals that the
surface traction force f on an arbitrarily inclined surface, with unit surface normal n is given
by the following:
f = TT · n. (7.5)
Here the superscript T denotes a matrix transpose. In component form, we could say
f1 T11 T21 T31 n1
f2 = T12 T22 T32 n2 (7.6)
f3 T13 T23 T33 n3
Recalling that any vector v can be normalized by dividing by its magnitude, we can say
v v1 e1 + v2 e2 + v3 e3
n= = p 2 . (7.9)
|v| v1 + v22 + v32
Let us build a program which assuming a known value of a stress tensor, takes an arbitrary
vector v as input, converts that vector to a unit vector n, and then finds the associated surface
traction vector f. This will be aided greatly by the use of two-dimensional arrays. However,
before entering into the actual program, let us outline our algorithm:
• initialize the two-dimensional array for the stress tensor T.
Note that our stress tensor is asymmetric. Usually, stress tensors are symmetric, but if
so-called “body couples,” which can be induced by magnetic forces, are present, the stress
tensor may be asymmetric.
Note that if we select a unit vector aligned with one of the coordinate axes, say n =
(1, 0, 0)T , we find
T11 T21 T31 1 T11
(1) T
f =T ·n = T12 T22 T32 0 = T12 ,
(7.11)
T13 T23 T33 0 T13
1 −2 −1 1 1
= 5 4 2 0 = 5 .
(7.12)
3 0 3 0 3
This unit normal vector in the 1 direction selected the components associated with the 1
face of the unit cube.
If we select a direction, say v = (1, 2, 3)T , we then would find
√ √
|v| = 12 + 22 + 32 = 14, (7.13)
and
√1
0.2673
√214
n= 14 = 0.5345 . (7.14)
√3 0.8018
14
The surface traction force associated with the surface whose unit normal is that just given
is
f1 1 −2 −1 0.2673 −1.6036
f = f2
= 5 4 2 0.5345 = 5.0780 . (7.15)
f3 3 0 3 0.8018 3.2071
Here is a Fortran program, ch7b.f90, and its execution for the two values just shown:
1 2 3
n= 0.2672612 0.5345225 0.8017837
f = -1.603567 5.077964 3.207135
[powers@remote101 ame.20214]$
• The two-dimensional array for the stress tensor is T. Its declaration statement is
real, dimension(1:3,1:3) :: T
real, dimension(3,3) :: T
real :: T(3,3)
enddo
do i=1,imax
print*,(x(i,j),j=1,jmax)
enddo
end program twod
[powers@remote105 ame.20214]$ ifort ch7d.f90
[powers@remote105 ame.20214]$ a.out
Enter the two lengths of the array
3 5
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
[powers@remote105 ame.20214]$
Note
• Here, we form the array of integers whose elements are given by xij = ij.
i = 8
i = 10
[powers@darrow2-p 2e]$
The Fortran language has some limited features in manipulating vectors and arrays
with simple global commands, known here as whole array features. These features are fairly
characterized as clumsy but somewhat useful. Some of the whole array features are inspired
by traditional linear algebra. In brief, there are Fortran short cuts for the
Note, there is no shorthand for the matrix inverse, or for eigenvalues or eigenvectors, among
other things. These important operations are often available as part of libraries external to
the Fortran language, but easily woven into a program.
The reader will soon learn that, relative to some competing languages, especially MATLAB,
Fortran has only limited effectiveness employing compact matrix notation for linear algebra
problems. Worse still, the Fortran implementation does not always follow common linear
algebra conventions. Nevertheless, those features that exist can be useful in writing compact
code. Moreover, whatever method is used for matrix operations, Fortran will provide a very
fast execution time, which is in fact what often matters most to the practicing engineer.
73
74 CHAPTER 8. WHOLE ARRAY FEATURES
In Fortran, this is achieved by the function dot product via the command
dot_product(u,v)
uT · v = vT · u, u, v ∈ R. (8.2)
An example is shown next of the dot product of two vectors u = (1, 2, 3)T and v = (4, 5, 6)T .
It is easily seen that
4
uT · v = 1 2 3 5 = (1)(4) + (2)(5) + (3)(6) = 32. (8.3)
6
We note
• We could have achieved the same result with a do loop and extra coding.
uT · v = vT · u, u, v ∈ C, (8.4)
where the overline indicates the complex conjugate, x + iy = x − iy. This unusual definition
is to guarantee that uT · u = |u|2 is a real positive scalar. Among other things, such a
property is necessary for any viable theory of quantum physics.
Consider if
1+i
u = 1 + 0i . (8.5)
0+i
• The complex numbers were entered as integers, but were converted automatically to
floating point numbers. We probably should have used decimal points to be careful,
but it turned out not to matter in this case.
• The dot product of a complex scalar into itself indeed gives a positive real number.
• In this degenerate case, the dot product in fact commutes, only because we are dotting
a vector into itself.
• The reader can easily verify that the dot product does not commute for two different
complex vectors.
Its transpose is
1 4
AT = 2 5 . (8.8)
3 6
A(1,1) = 1 !Initialize A
A(1,2) = 2
A(1,3) = 3
A(2,1) = 4
A(2,2) = 5
A(2,3) = 6
At=transpose(A)
print*,’ ’
print*,’raw form, At = ’,At
print*,’ ’
print*,’ structured form, At = ’
do i=1,3
print*,(At(i,j), j=1,2)
enddo
end program tpose
[powers@darrow1-p ame.20214]$ ifort ch8g.f90
[powers@darrow1-p ame.20214]$ a.out
raw form, A = 1 4 2 5 3
6
structured form, A =
1 2 3
4 5 6
raw form, At = 1 2 3 4 5
6
structured form, At =
1 4
2 5
3 6
[powers@darrow1-p ame.20214]$
Note:
• The default print command prints each element of the matrix as a simple one-
dimensional list of numbers, ordered column by column.
• It probably would have been better for Fortran to have been designed so the default
print command was row by row, which would have allowed more consistency with
standard matrix algebra.
• With a special structuring, we were able to print the matrices in a more standard form.
This involved commands like print*,(A(i,j),j=1,3), as well as the do loop in which
it was embedded.
TT · n 6= nT · T, (8.10)
unless we have the special case in which T is symmetric. Much like the intrinsic function
dot product simplified the coding, the Fortran intrinsic function matmul simplifies matrix-
vector multiplication. This is illustrated with the code ch8c.f90, where we compute
3
X
T
f = T · n, fi = TijT nj , (8.11)
j=1
3
X
f T = nT · T, fi = nj Tji . (8.12)
j=1
[powers@remote101 ame.20214]$
We note
• We used the useful intrinsic operation transpose to form the transpose of several
matrices. Note that both T and TT have dimension 3 × 3.
• The function matmul(n,T) yielded the same result as our more complex program for
f. This really was the equivalent of forming f T = nT · T.
• While doable and efficient to code, whole array matrix operations in Fortran are
complicated relative to some other codes such as MATLAB.
• Fortran does not recognize the difference between row vectors and column vectors;
each is simply a one-dimensional list. For this problem n and nT as well as f and f T
are treated identically. This is not the case in MATLAB.
Note if we write in the dimensions of the arrays as subscripts, we see what the matrix product
will yield,
A2×3 · B3×4 = C2×4 . (8.14)
The adjacent 3’s cancel, leaving us with a 2 × 4 result. Standard matrix multiplication then
reveals that
1 1 1 2
1 2 2 7 13 17 22
2 3 4 5 = (8.15)
1 1 1 4 7 9 12
| {z } 1 3 4 5 | {z }
A | {z } C
B
C =
7 13 17 22
4 7 9 12
[powers@darrow1-p ame.20214]$
Note:
• We used the simplest possible declaration statement.
• We had to initialize each of the elements of A and B.
• The compiler noted the loop was vectorized. At present, this is not important.
• The output C was formed via matmul. The numbers have the correct value, but one
must take care to interpret them as to how they actually fit into the array C. The
unformatted output of C is given as a column-by-column list.
• We also printed C in a traditionally structured way via a do loop.
We illustrate an alternate and more compact way to initialize matrices and do the same
task as the previous program in the code of ch8e.f90:
[powers@darrow1-p ame.20214]$ cat ch8e.f90
program multiply !This program multiplies two rectangular matrices.
implicit none
integer :: A(2,3) = & !Note this ordering convention is backwards from
(/1, 1, & !that of standard matrix algebra...
2, 1, &
2, 1 /)
integer :: B(3,4) = & !Once again a backwards ordering convention
(/1, 2, 1, &
1, 3, 3, &
1, 4, 4, &
2, 5, 5/)
integer :: C(2,4)
C=matmul(A,B)
print*,C
end program multiply
[powers@darrow1-p ame.20214]$ ifort ch8e.f90
ch8e.f90(13): (col. 3) remark: LOOP WAS VECTORIZED.
[powers@darrow1-p ame.20214]$ a.out
7 4 13 7 17 9
22 12
[powers@darrow1-p ame.20214]$
We note that
• We achieved precisely the same result as the previous version of the algorithm.
• Fortran really only keeps track of one-dimensional lists, and we entered the data for
A and B as one-dimensional lists, but we used the continuation line character & to aid
in the visual display of the matrix structure on input.
• This technique for initializing two-dimensional arrays also works for one-dimensional
arrays.
We can also achieve the same result of a traditional matrix-matrix multiplication from a
detailed triply nested do loop, found in ch8f.f90:
C(i,j) = C(i,j)+A(i,k)*B(k,j)
enddo
enddo
enddo
print*,C
end program multiply
[powers@darrow1-p ame.20214]$ ifort ch8f.f90
[powers@darrow1-p ame.20214]$ a.out
7 4 13 7 17 9
22 12
[powers@darrow1-p ame.20214]$
Note that
• We had to insure that i ran from 1 to 2 and j from 1 to 4, consistent with the
dimensions of C. Then k ran from 1 to 3, consistent with the dimensions of A and B.
8.5 Addition
Two arrays of the same dimension can be added. As an example, we take
1 2 5 6
A= , B= . (8.17)
3 4 7 8
Then
1+5 2+6 6 8
C=A+B= = . (8.18)
3+7 4+8 10 12
print*,’ A = ’
do i=1,2
print*,(A(i,j), j=1,2)
enddo
print*,’ B = ’
do i=1,2
print*,(B(i,j), j=1,2)
enddo
C = A + B
print*,’ C = A+B = ’
do i=1,2
print*,(C(i,j), j=1,2)
enddo
Note:
• We printed each matrix using the nested do statements which allow the natural matrix
form and structure to be displayed.
• The matrix C is indeed composed of the sum of each element of A and B. The compact
statement C = A+ B was used instead of a set of instructions involving two do loops
to sum the matrices.
Note that the formal matrix multiplication does not exist because of incompatible dimensions
of A and B for this operation. However, the element-by-element “multiplication” does exist
and is given by
(1)(7) (2)(8) (3)(9) 7 16 27
C= = . (8.21)
(4)(10) (5)(11) (6)(12) 40 55 72
print*,’ A = ’
do i=1,2
print*,(A(i,j), j=1,3)
enddo
print*,’ B = ’
do i=1,2
print*,(B(i,j), j=1,3)
enddo
C = A*B
print*,’ C = A*B = ’
do i=1,2
print*,(C(i,j), j=1,3)
enddo
A =
1 2 3
4 5 6
B =
7 8 9
10 11 12
C = A*B =
7 16 27
40 55 72
[powers@darrow1-p ame.20214]$
Similarly the Fortran statement sqrt(A) takes the square root of every element of the matrix
A. This is not a traditional matrix function.
Output of results
The print* statement we have used thus far sends raw output to the screen, and is a
good way. But it can be æsthetically unwieldy to the extent that the reader has unnecessary
difficulty interpreting the results. To alleviate this difficulty, one can use a variety of tools
to produced output with better format. And the key to this is the use of what is known as
a format statement.
89
90 CHAPTER 9. OUTPUT OF RESULTS
7 1.0000000E+07
8 1.0000000E+08
[powers@darrow1-p ame.20214]$
Note:
• The decimal points are not aligned for the real numbers.
• The output changes suddenly to exponential notation from ordinary decimal notation.
• There are only two digits to the right of the decimal point in all real numbers.
• This is realized due to the format statement 100 format(i3,3x,f12.2). Let us break
this down.
– 100: This is a label, and is called upon by the formatted print 100. We often
place the format statement near the print statement, but this is not required. It
is also possible to have many print statements draw upon one format statement.
– i3: This says to print the number as a three digit integer. If the integer has in
fact four or more entries, the output will be problematic, but the program will
execute.
– 3x: This says to skip three spaces.
– f12.2: The f format says to print a real number in non-exponential notation.
The 12 assigns twelve spaces to the number. These spaces include the +/− signs,
the decimal point, and all digits. The .2 says to include exactly two digits to the
right of the decimal point.
Let us see what happens when we only allow ten instead of twelve slots for the real
number, and simultaneously ask for three digits right of the decimal point. To do that, we
change f12.2 to f10.3. Let’s also change x to −x. Let’s also change the i3 format to i1, so
that we only print one digit of the integer. We will also let 50 values be computed. Results
are shown in ch9c.f90:
9 **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* **********
* -Infinity
* -Infinity
* -Infinity
* -Infinity
* -Infinity
* -Infinity
* -Infinity
* -Infinity
* -Infinity
* -Infinity
* -Infinity
* -Infinity
[powers@darrow1-p ame.20214]$
Note:
• The last value of x that is actually displayed is −10000.000. This number has entries
in 10 slots:
• Numbers that cannot fit into this format are displayed as **********. Note there are
ten stars.
• The last integer that displays is the last single digit integer, 9.
We can change the format to print many large numbers. In ch9h.f90, we change to an
f50.3 format and get
6 -1000000.000
7 -10000000.000
8 -100000000.000
9 -1000000000.000
10 -10000000000.000
11 -99999997952.000
12 -999999995904.000
13 -9999999827968.000
14 -100000000376832.000
15 -999999986991104.000
16 -10000000272564224.000
17 -99999998430674944.000
18 -999999984306749440.000
19 -9999999980506447872.000
20 -100000002004087734272.000
21 -1000000020040877342720.000
22 -9999999778196308361216.000
23 -99999997781963083612160.000
24 -1000000013848427855085568.000
25 -9999999562023526247432192.000
26 -100000002537764290115403776.000
27 -999999988484154753734934528.000
28 -9999999442119689768320106496.000
29 -100000001504746621987668885504.000
30 -1000000015047466219876688855040.000
31 -9999999848243207295109594873856.000
32 -100000003318135351409612647563264.000
33 -999999994495727286427992885035008.000
34 -9999999790214767953607394487959552.000
35 -100000004091847875962975319375216640.000
36 -999999961690316245365415600208216064.000
37 -9999999933815812510711506376257961984.000
38 -99999996802856924650656260769173209090.000
39 -Infinity
40 -Infinity
41 -Infinity
42 -Infinity
43 -Infinity
44 -Infinity
45 -Infinity
46 -Infinity
47 -Infinity
48 -Infinity
49 -Infinity
50 -Infinity
[powers@darrow1-p ame.20214]$
Note that we only achieve seven digits of accuracy and that for large numbers, the output
values have a strong pseudo-random component in many digits. This is because we only
requested single precision accuracy.
Let us do the same chore in exponential notation, using the so-called e format. So, let
us replace f10.3 by e10.3 and examine the result in in ch9d.f90:
Note:
• There is no longer a problem with data that cannot be displayed. This is an advantage
of the e format.
Character variables can be printed to the screen in a formatted form using the a format.
An example is given in ch9e.f90:
Note:
• The formatted print 100 statement calls upon statement 100 to dictate its output
format to the screen.
open(unit=20,file=’numbers’)
do i = 1,8
x = -10.**i
print 100,i,x
write(20,100) i,x
100 format(i3,3x,e10.3)
end do
end program formatoutput5
[powers@darrow1-p ame.20214]$ ifort ch9f.f90
[powers@darrow1-p ame.20214]$ a.out
1 -0.100E+02
2 -0.100E+03
3 -0.100E+04
4 -0.100E+05
5 -0.100E+06
6 -0.100E+07
7 -0.100E+08
8 -0.100E+09
[powers@darrow1-p ame.20214]$ cat numbers
1 -0.100E+02
2 -0.100E+03
3 -0.100E+04
4 -0.100E+05
5 -0.100E+06
6 -0.100E+07
7 -0.100E+08
8 -0.100E+09
[powers@darrow1-p ame.20214]$
Note:
• We associated the arbitrary integer 20 with the output file we chose to name numbers.
• We did not put any identifier like .txt or .dat on the file numbers. This is fine, but
some applications will not recognize it as a text file, while others will.
• We used the same format statement to print and to write the same data; conse-
quently, the output to the screen is identical to that in the file.
If we neglect to open a file, but write to “20” anyway, most compilers will be accommodating.
The ifort compiler will obligingly open a file and give it the name fort.20. It will then
write to this file, if requested. This is shown in ch9g.f90:
program formatoutput6
implicit none
integer :: i
real :: x
do i = 1,8
x = -10.**i
write(20,100) i,x
100 format(i3,3x,e10.3)
end do
end program formatoutput6
[powers@darrow1-p ame.20214]$ ifort ch9g.f90
[powers@darrow1-p ame.20214]$ a.out
[powers@darrow1-p ame.20214]$ cat fort.20
1 -0.100E+02
2 -0.100E+03
3 -0.100E+04
4 -0.100E+05
5 -0.100E+06
6 -0.100E+07
7 -0.100E+08
8 -0.100E+09
[powers@darrow1-p ame.20214]$
Reading data
The read* statement we have used thus far reads raw input from the screen, and is a good
way to read limited amounts of data. But it can be problematic if there is a large amount of
input data that could change from case to case. In such a case, we are well advised to read
the data in from a file. And there are two ways to read the data, unformatted and formatted.
Unformatted is the simplest, but is difficult for the user to comprehend. Formatting input
data requires more effort, but is easier for the user to understand.
There are two columns of data, but the file lacks a clean structure. Let us consider a Fortran
program to read this data and print it to the screen in a formatted fashion. We will associate
the first column with a vector x(i) and the second column with a vector y(i). The program
and its execution are found in ch10a.f90:
99
100 CHAPTER 10. READING DATA
integer :: i
open(10,file=’ch10a.in’)
do i=1,5
read(10,*) x(i),y(i)
print 199, i,x(i),y(i)
end do
199 format(i4,2x,e12.6,2x,e12.6)
end program readdata
[powers@darrow1-p ame.20214]$ ifort ch10a.f90
[powers@darrow1-p ame.20214]$ a.out
1 0.000000E+00 0.000000E+00
2 0.112320E+01 0.223000E+01
3 0.200000E+01 0.410000E+01
4 0.351000E+01 0.790000E+01
5 0.500000E+01 0.100000E+02
[powers@darrow1-p ame.20214]$
Note:
• The number 10 is associated with the input file ch10a.in.
• We print the data to the screen in a formatted fashion and see that it is in fact the
same as our input data.
• We needed to know that there were only five lines in the input file. This can pose a
problem for input data files of arbitrary length.
Let us say we try to consider 10 values of x and y, but we only have 5 values in the input
file. This induces a problem, as is evident in ch10b.f90:
[powers@remote202 ame.20214]$ cat ch10b.f90
program readdata
implicit none
real :: x(10),y(10)
integer :: i
open(10,file=’ch10a.in’)
do i=1,10
read(10,*) x(i),y(i)
print 199, i,x(i),y(i)
end do
199 format(i4,2x,e12.6,2x,e12.6)
end program readdata
[powers@remote202 ame.20214]$ ifort ch10b.f90
program readdata
implicit none
integer, parameter :: imax=1000
real :: x(imax),y(imax)
integer :: i
open(10,file=’ch10b.in’)
do
read(10,*) x(i),y(i)
if(x(i).lt.-9998.)exit
print 199, i,x(i),y(i)
end do
199 format(i4,2x,e12.6,2x,e12.6)
end program readdata
[powers@remote202 ame.20214]$ ifort ch10c.f90
[powers@remote202 ame.20214]$ a.out
0 0.000000E+00 0.000000E+00
0 0.112320E+01 0.223000E+01
0 0.200000E+01 0.410000E+01
0 0.351000E+01 0.790000E+01
0 0.500000E+01 0.100000E+02
[powers@remote202 ame.20214]$
Note:
• We are prepared for as many as imax = 1000 data points, having dimensioned each
vector to this value.
• We exit the do loop if we find a data point with a value of x(i) less than -9998.
• If our input data file does not have the appropriate end of file statement, we will likely
find an execution error.
We see
• The last line is a convenience for counting spaces. It will not be read and not influence
the program.
Use of this input file will allow us to compile the program once, and if we want to change
the input file, we can simply edit it, and re-run the binary executable a.out. The program
itself, its compilation, and execution are given as
1 0.0000000E+00 270.0000
2 2.666667 263.5721
3 5.333333 260.1519
4 8.000000 261.3398
5 10.66667 266.5798
6 13.33333 273.4202
7 16.00000 278.6602
8 18.66667 279.8481
9 21.33333 276.4279
10 24.00000 270.0000
[powers@darrow2-p ame.20214]$
Note:
• We chose to read one value for each read; we could have restructured the reading so
that one read statement read several variables.
• The 100 format statement said to ignore the first 20 spaces in the line, and read as a
real variable that which occupies the next 10 spaces, with up to five decimal points.
This employed the f10.5 format. For exponential notation data, we could have chosen
e10.5, for example.
• The 101 format statement said to ignore the first 20 spaces in the line, and read as an
integer variable that which occupies the next 10 spaces.
I/O Concepts
There is some additional information on Input/Output concepts in the text. The inter-
ested student should review the appropriate material.
105
106 CHAPTER 11. I/O CONCEPTS
Functions
Functions are a useful aspect of the Fortran language. Many intrinsic functions are
built into the language and simplify many mathematical operations. These are pre-defined
functions. It is also possible to build user-defined functions. Let us examine both types.
y = function(x)
Here x is the input, y is the output, and function is the intrinsic Fortran function. One
example is the exponential function. The Fortran version of
y = ex , (12.1)
is
y = exp(x)
107
108 CHAPTER 12. FUNCTIONS
Note:
• We then tried to take the square root of a negative real number. Because the square
root of a negative real number is not a real number, the program refuses to perform
the calculation and returns the value NaN, which stands for Not a Number.
Let us declare x to be complex and take its square root; see ch12b.f90:
program sqroot
complex :: x = (-1.,0.)
print*,sqrt(x)
end program sqroot
[powers@darrow2-p ame.20214]$ ifort ch12b.f90
[powers@darrow2-p ame.20214]$ a.out
(0.0000000E+00,1.000000)
[powers@darrow2-p ame.20214]$
In a similar manner, functions such as sin−1 , cos−1 , or tan−1 are multi-valued, but Fortran
will only return one value. For example, while we know that
π
sin−1 (1) = + 2nπ, n = . . . , −2, −1, 0, 1, 2, . . . (12.2)
2
Fortran returns only
asin(1.) = 1.570796
which we see is a single precision representation of π/2. In fact, Fortran defines asin so
that its range is
The user must take care that the appropriate value of the multi-valued inverse functions
is being used.
computing platforms, it is possible and useful to have Fortran-generated code interact with
C++ or Java code.
Let us say we have a generic function f (x) and wish to have a program to build a list of
values of x and f (x) for x ∈ [0, 1]. We want the main program to be general, and to have
the ability to plug in a function from somewhere else. We will take
We can explore this in the following set of example programs, each of which employs a
different program structure to achieve the same end.
100 format(f12.6,2x,f12.6)
end do
end program fofx
!---------------------------------------------------------------------------------
[powers@remote102 ame.20214]$ ifort ch12c.f90
[powers@remote102 ame.20214]$ a.out
enter number of points, n>1
13
0.000000 0.000000
0.083333 0.500000
0.166667 0.866025
0.250000 1.000000
0.333333 0.866025
0.416667 0.500000
0.500000 0.000000
0.583333 -0.500000
0.666667 -0.866025
0.750000 -1.000000
0.833333 -0.866025
0.916667 -0.500000
1.000000 0.000000
[powers@remote102 ame.20214]$
Note:
• The function subroutine f(x) is embedded within the module named myfunction,
which appears first in the program.
• For function subroutines, we exercise the option of reserving some variables for in-
put. Here our input variable is x, and it is reserved as input by the statement real,
intent(in) :: x.
• The action of the function is to take a value of x and map it into f and return that
value to the main program.
• The main program appears last. It calls upon the function subroutine with the state-
ment f(x).
• We must inform the main program that a function subroutine module here myfunction,
is to be employed. That is achieved by use myfunction, which appears before variable
declaration statements.
• The user must have defined f(x), since it is not a pre-defined Fortran function.
• We can extend this syntax to evaluate functions of N variables of the form f (x1 , x2 , x3 , . . . , xN ).
That is to say, functions can take several inputs and map them to a single output.
y = f (x), (12.7)
x
z = f . (12.8)
2
Thus, with our general form for f , we expect
y = sin(2πx), (12.9)
z = sin(πx). (12.10)
integer :: i,n
print*,’enter number of points, n>1’
read*,n
dx = (xmax-xmin)/real(n-1.)
do i=1,n
x = xmin + dx*(i-1.)
y = f(x) !Here we call on the function subroutine
z = f(x/2.) !Here we again call on the function subroutine
print 100,x,y,z
100 format(f12.6,2x,f12.6,2x,f12.6)
end do
end program fofx
!---------------------------------------------------------------------------------
[powers@remote102 ame.20214]$ ifort ch12f.f90
[powers@remote102 ame.20214]$ a.out
enter number of points, n>1
13
0.000000 0.000000 0.000000
0.083333 0.500000 0.258819
0.166667 0.866025 0.500000
0.250000 1.000000 0.707107
0.333333 0.866025 0.866025
0.416667 0.500000 0.965926
0.500000 0.000000 1.000000
0.583333 -0.500000 0.965926
0.666667 -0.866025 0.866025
0.750000 -1.000000 0.707107
0.833333 -0.866025 0.500000
0.916667 -0.500000 0.258819
1.000000 0.000000 0.000000
[powers@remote102 ame.20214]$
!---------------------------------------------------------------------------------
module commondata !This sets up data which will be shared.
implicit none
real :: pi=4.*atan(1.)
end module commondata
!
!---------------------------------------------------------------------------------
!
module myfunction !This is a module declaration
contains
real function f(t) !This is the function subroutine
use commondata !Import the common data
implicit none
real, intent(in) :: t !Declare t as a real input variable
f = sin(2.*pi*t) !Employ the common data, pi
end function f
end module myfunction
!
!---------------------------------------------------------------------------------
!
program fofx !This is the main program--it comes last
use commondata !Import the common data
use myfunction !The main program draws upon myfunction
implicit none
real :: x,y,z,xmin=0.,xmax=1.,dx
integer :: i,n
print*, pi !print the common data
print*,’enter number of points, n>1’
read*,n
dx = (xmax-xmin)/real(n-1.)
do i=1,n
x = xmin + dx*(i-1.)
y = f(x) !Here we call on the function subroutine
z = f(x/2.) !Here we again call on the function subroutine
print 100,x,y,z
100 format(f12.6,2x,f12.6,2x,f12.6)
end do
end program fofx
!---------------------------------------------------------------------------------
[powers@remote102 ame.20214]$ ifort ch12g.f90
[powers@remote102 ame.20214]$ a.out
3.141593
Note that neither the main program nor the function subroutine constructed pi; moreover, pi
was not declared in either. Instead, pi was declared and initialized in module commondata,
and commondata was imported into the main program and the function via the command
use. The notion of the module is discussed further in Ch. 21.
Now, we can do a different kind of compilation of the function subroutine module first
via the command
This -c option generates the binary file ch12e.o. It is binary, but it is not executable
on its own. To work, it must be linked to a driver program. We can achieve the linkage to
the driver program ch12d.f90 by compiling ch12d.f90 and informing it that it should be
linked to ch12e.o via the compilation command
This command generates the binary executable a.out. Note that if we did not link to
ch12e.o, the main program ch12d.f90 would not compile, because it was missing f(x).
Here is the execution of a.out for 7 points:
Another option is to use the -c option on both .f90 files first and create two .o files,
then use the compiler to merge them to create a.out:
The file has our chores combined into a single list. We next have to one time only declare
this file to be executable. In UNIX this is achieved via
The so-called “change mode” command, chmod, changes permissions on files. We have
changed the permission for the user, u, so as to add, +, the ability to execute, x, the file. So
entering the new UNIX command runch12de compiles and executes, generating
8
0.000000 0.000000
0.142857 0.781832
0.285714 0.974928
0.428571 0.433883
0.571429 -0.433884
0.714286 -0.974928
0.857143 -0.781831
1.000000 0.000000
[powers@darrow2-p ame.20214]$
A more powerful way to build executable programs is through the UNIX utility Make, which
we will not discuss further here, but offers many advantages to the interested user.
Control structures
There are an important set of logical structures to control Fortran programs. We have
seen some of these before. The most critical are based on either
For binary choices, we also have the constructs if, then, else if, endif. For iterations,
we have several constructs:
• do i=1,n,
• do while,
• others.
A typical if statement will require a syntax for the condition to be met. For example,
the English sentence, “If today is Thursday, then attend AME 20214,” has a Fortran-like
structure
We need a syntax for English words like “is.” That syntax and others are listed in Table 13.1,
adapted from C&S: An example of an if-based structure is obtained if we seek the real roots
of the quadratic equation
ax2 + bx + c = 0, a, b, c ∈ R. (13.1)
119
120 CHAPTER 13. CONTROL STRUCTURES
== equal to relational
/= not equal to relational
>= greater than or equal to relational
<= less than or equal to relational
< less than relational
> greater than relational
.and. and logical
.or. or logical
.not. not logical
b2 − 4ac = 0, (13.4)
Given a, b, and c, we should be able to construct a Fortran program to identify the real
roots, if they exist, and to also tell us if no real roots exist. This is achieved in a small
modification of a program given by C&S, found in ch13a.f90:
• there is a logical structure to the if, then, elseif, then, else, endif.
We can also use logical constructs, such as .and. to effect. Let us say we want to plot a
so-called “top hat” function:
0, x ∈ (−∞, 1),
f (x) = 1, x ∈ [1, 2], (13.6)
0, x ∈ [2, ∞).
The nature of the function f (x) is that it has explicit conditional dependency on x which
is appropriate for an if, then implementation in Fortran. We give such an implementation
in ch13b.f90:
[powers@remote102 ame.20214]$ cat ch13b.f90
!---------------------------------------------------------------------------------
module myfunction !This is a module declaration
contains
real function f(t) !This is the function subroutine
implicit none
real, intent(in) :: t !Declare t as a real input variable
if(t<1.0.or.t>2.0) then
f = 0.0
else
f = 1.0
endif
end function f
end module myfunction
!
!---------------------------------------------------------------------------------
!
program fofx !This is the main program--it comes last
use myfunction !The main program draws upon myfunction
implicit none
real :: x,y,xmin=-3.,xmax=3.,dx
integer :: i,n
print*,’enter number of points, n>1’
read*,n
dx = (xmax-xmin)/real(n-1.)
do i=1,n
x = xmin + dx*(i-1.)
y = f(x) !Here we call on the function subroutine
print 100,x,y
100 format(f12.6,2x,f12.6)
end do
end program fofx
!---------------------------------------------------------------------------------
[powers@remote102 ame.20214]$ ifort ch13b.f90
[powers@remote102 ame.20214]$ a.out
enter number of points, n>1
11
-3.000000 0.000000
-2.400000 0.000000
-1.800000 0.000000
-1.200000 0.000000
-0.600000 0.000000
0.000000 0.000000
0.600000 0.000000
1.200000 1.000000
f (x)
1.0
0.8
0.6
0.4
0.2
x
-3 -2 -1 1 2 3
Figure 13.1: Plot of top hat function f (x) for x ∈ [−3, 3], discrete and exact values.
1.800000 1.000000
2.400000 0.000000
3.000000 0.000000
[powers@remote102 ame.20214]$
Note:
• Within the function subroutine, we used the conditional if, then, else, endif
structure.
• The conditional for the if statement involved the Boolean logical operator .or.
We give a plot of the exact representation of f (x) and the eleven discrete points we chose to
evaluate in Fig. 13.1.
We can illustrate a do while structure with the following problem. Use the Euler method
to solve the ordinary differential equation
dy
= λy, y(0) = yo , t ∈ [0, tstop ], (13.7)
dt
for λ = −1, yo = 1, tstop = 1. Euler’s method has us approximate the first derivative as
dy yn+1 − yn
∼ , (13.8)
dt ∆t
and evaluate the right hand side of the differential equation at the n time step. This gives
rise to
yn+1 − yn
= λyn , (13.9)
∆t
yn+1 = yn + λ∆tyn . (13.10)
y
1.0
0.8
0.6
0.4
t
0.2 0.4 0.6 0.8 1.0
Figure 13.2: Plot of the exact solution to dy/dt = −y, y(0) = 1 (y = exp(−t)), along with
its approximation from the Euler method with ∆t = 0.1.
We note that the do while structure has been implemented, and it is an obvious and conve-
nient program control structure for this problem. We give a plot of the exact representation
of y(x) and the eleven discrete points we chose to evaluate with the Euler method in Fig. 13.2.
Characters
One should read the text of C&S to learn further about characters within Fortran.
127
128 CHAPTER 14. CHARACTERS
Complex
Complex mathematics is a rich and varied subject. At its foundation lays the number i
where
√
i ≡ −1. (15.1)
z = x + iy. (15.2)
z ∈ C1 , x ∈ R1 , y ∈ R1 . (15.3)
where C and R denote the complex and real numbers, respectively, and the superscript 1
denotes scalars. The real part of z is defined as
129
130 CHAPTER 15. COMPLEX
2. z = 3 − 4i,
√ p √ √
3. |z| = zz = (3 + 4i)(3 − 4i) = 32 + 42 = 25 = 5 + 0i.
z1 = (-2.,0.)
z2 = (0.,1.)
z3 = (1.,1.)
print*,’sqrt(-2) = ’, sqrt(z1)
print*,’ln(-2) = ’, log(z1)
print*,’sin(-2) = ’, sin(z1)
print*,’sqrt(i) = ’, sqrt(z2)
print*,’ln(i) = ’, log(z2)
print*,’sin(i) = ’, sin(z2)
print*,’sqrt(1+i) = ’, sqrt(z3)
print*,’ln(1+i) = ’, log(z3)
print*,’sin(1+i) = ’, sin(z3)
ln(i) = (0.0000000E+00,1.570796)
sin(i) = (0.0000000E+00,1.175201)
sqrt(1+i) = (1.098684,0.4550899)
ln(1+i) = (0.3465736,0.7853982)
sin(1+i) = (1.298458,0.6349639)
[powers@remote202 ame.20214]$
We see
1. for z = −2 + 0i that
√ √ √
(a) z = −2 = 2i,
(b) ln z = ln(−2) = ln(2) + iπ, and
(c) sin(z) = sin(−2) = − sin(2).
2. for z = 0 + i that
√ √ √ √
(a) z = i = 2 + 2i,
(b) ln z = ln(i) = i π2 , and
1 −e−1
(c) sin(z) = sin(i) = i e 2
.
3. for z = 1 + i that
√ √
(a) z = 1 + i = 21/4 (cos(π/8) + i sin(π/8)) = 1.09868 + 0.45509i,
1
(b) ln z = ln(1 + i) = 2
ln(2) + i π4 = 0.346574 + 0.785398i, and
(c) sin(z) = sin(1 + i) = 1.29846 + 0.634964i.
We lastly note that inverse trigonometric functions have a clean mathematical definition for
complex numbers. For instance, it can be shown that
√
sin−1 z = −i ln iz + 1 − z 2 , z ∈ C1 , (15.12)
Note
• We simply defined our own function subroutine arcsin and gave it the proper defini-
tion, consistent with that of mathematics.
• When exercised on z = 2 + 0i, our program returned the value, sin−1 (2) = 1.570796 −
1.316958i. This value is acceptable, though we must realize that in general others
could be as well.
Logical
135
136 CHAPTER 16. LOGICAL
The interested reader can consult C&S’s Chapter 17 for a discussion of derived types.
137
138 CHAPTER 17. INTRODUCTION TO DERIVED TYPES
An introduction to pointers
139
140 CHAPTER 18. AN INTRODUCTION TO POINTERS
Introduction to subroutines
Many times we have a task that is composed of a sequence of steps that need to be re-
peated many times. For an efficient code, it is to our advantage to write a general subroutine
that can handle tasks which must be repeated.
141
142 CHAPTER 19. INTRODUCTION TO SUBROUTINES
Note:
• The module containing the subroutine is placed first in the program structure.
• The subroutine uses a set of dummy variable names, xx, yy, rr, ttheta, which we
choose to be similar to those of the actual variables. We could have chosen them to be
identical. No matter which choice we made, those variables are local variables to the
subroutine. They are passed back to the main program where they take on the value
of the names assigned in the main program. So rr gets assigned in the subroutine,
and it is passed back to the main program, where it is assigned to the variable r. The
same holds for θ, represented as ttheta and theta.
• It is good, but optional, practice to define variables as either input or output variables
within the subroutine. Here, input variables were defined with intent(in) as input
variables only. This then requires that the subroutine not change their value. Output
variables were defined with intent(out) and were not given initial values.
• Though not used here, variables which are allowed values on input and can be changed
for output can be assigned intent(inout).
• The main program assigns values to x and y, but leaves r and theta unassigned
initially.
• The first real executable line of the main program is to call upon the subroutine, where
r gets its value.
ax2 + bx + c = 0. (19.3)
module solve_module
contains
subroutine solve(e,f,g,root1,root2,ifail)
implicit none
real, intent (in) :: e
real, intent (in) :: f
real, intent (in) :: g
real, intent (out) :: root1
real, intent (out) :: root2
integer, intent (inout) :: ifail
! local variables
real :: term
real :: a2
program roots
use interact_module
use solve_module
implicit none
! simple example of the use of a main program and two
! subroutines. one interacts with the user and the
! second solves a quadratic equation,
! based on the user input.
real :: p, q, r, root1, root2
integer :: ifail = 0
call interact(p,q,r)
call solve(p,q,r,root1,root2,ifail)
if (ifail==1) then
print *, ’ complex roots’
print *, ’ calculation abandoned’
Note:
• For the variables a, b and c, the main program uses p, q, and r, while subroutine
interact uses a, b, and c, and subroutine solve uses e, f, and g.
• The variable ifail is a flag which lets the main program know whether or not the
calculation was such that real roots were found. The variable ifail is initialized to
zero in the main program, and is an input to subroutine solve. If the discriminant
is negative, the roots are complex, and the subroutine sets ifail to 1. Note that
ifail is both an input and an output to the subroutine, and is declared as such with
intent(inout).
dy1
= f1 (y1 , y2 , . . . , yN ), y1 (0) = y1o , (19.5)
dt
dy2
= f2 (y1 , y2 , . . . , yN ), y2 (0) = y2o , (19.6)
dt
..
. (19.7)
dyN
= fN (y1 , y2 , . . . , yN ), yN (0) = yN o . (19.8)
dt
y1n+1 − y1n
= f1 (y1n , y2n , . . . , yN
n
), y11 = y1o , (19.9)
∆t
y2n+1 − y2n
= f2 (y1n , y2n , . . . , yN
n
), y21 = y2o , (19.10)
∆t
..
. (19.11)
n+1 n
yN − yN
= fN (y1n , y2n , . . . , yN
n
), 1
yN = yN o . (19.12)
∆t
Here, the superscripts are not exponents; instead, they are simply indices for counting. We
can solve for the new values at n + 1 in terms of the old at n directly:
If we repeat this process many times for sufficiently small values of ∆t, we get a good
approximation to the continuous behavior of y1 (t), y2 (t), . . . , yN (t).
Now we wish to have a program with two desirable features:
• It can handle arbitrary integration algorithms, say Euler, or say the common Runge-
Kutta method. For example, the two-step Runge-Kutta method is as follows:
n+1/2 ∆t
yi = yin + fi (yjn ), i, j = 1, . . . , N, (19.17)
2
n+1/2
yin+1 = yin + ∆tfi (yj ), i, j = 1, . . . , N. (19.18)
real, intent(inout) :: t
real, intent(in) :: tout
real, dimension(1:neq) :: ydot
real :: dt
dt = tout-t
call fcn(t,y,ydot) !estimate ydot at t
do i=1,neq
y(i) = y(i)+dt*ydot(i) !estimate y at t
enddo
t = tout !update t
end subroutine ode1
end module ode1module
!
!-------------------------------------------------------------------------
!
module ode2module
! The subroutine in this module is a generic algorithm for
! the second order Runge-Kutta method for
! solving the system of neq ordinary differential
! equations evaluated by subroutine fcn.
contains
subroutine ode2(y,t,tout)
use commondata
use rhs
implicit none
integer :: i
real, intent(inout), dimension(1:neq) :: y
real, dimension(1:neq) :: yi,ydot
real, intent(inout) :: t
real, intent(in) :: tout
real :: dt
dt = tout-t
call fcn(t,y,ydot) !estimate ydot at t
do i=1,neq
yi(i) = y(i)+dt*ydot(i)/2. !estimate y at t+dt/2
enddo
call fcn(t+dt/2.,yi,ydot) !estimate ydot at t+dt/2
do i=1,neq
y(i) = y(i) + dt*ydot(i) !estimate y at t
enddo
t = tout !update t
end subroutine ode2
1.000000 0.3486784
error = -1.9200981E-02
[powers@darrow2-p ame.20214]$
Note:
• There is a module for shared data, commondata.
• There are three subroutine modules:
– rhs which evaluates the right hand sides of the differential equations,
– ode1module which embodies the Euler method, and
– ode2module which embodies the second order Runge-Kutta method.
• The three subroutine modules each contain a subroutine.
• Some subroutines use modules. Here ode1 and ode2 both need to call upon fcn to
evaluate the right hand side of the function. Also the main driver program, solveode,
may call on either ode1 or ode2. It does not choose to call upon fcn.
• The main program calls upon either ode1 or ode2 to advance the solution from t to
tout. Both y and t enter the solver with old values and return with new values.
• The particularities of the mathematics problem to be solved is confined to the commondata
and rhs modules. The driver program as well as the Euler and Runge-Kutta solvers
are general.
• When we execute with the Euler solver ode1, we get an error at t = 1 of −1.9200981 ×
10−2 .
• If we do nothing but change to ode2, the error changes to 6.6155195 × 10−4. Thus, a
simple change to our algorithm gave us two orders of magnitude improvement in the
error.
We plot the exact solution along with the approximations of the Euler and two-step Runge-
Kutta methods in Fig. 19.1.
0.8
0.6
0.4
t
0.2 0.4 0.6 0.8 1.0
Figure 19.1: Plot of y1 (t), solid line is the exact solution, blue dots give the finite difference
solution with the first order Euler method, red dots give the finite difference solution with
the second order Runge-Kutta method.
k2 is the non-linear spring constant, Fo is the amplitude of the forcing function, and ν is the
frequency of forcing. Let us do a useful scaling exercise, common in engineering. Our goal
is to achieve more universality in our results. Let us define a dimensionless distance y ∗ by
scaling y by its initial value yo :
y
y∗ = . (19.22)
yo
Thus, we might expect y ∗ to have a value around 1; we say that y ∗ = O(1), or of “order
one.” There are many choices of how to scale time. Let us make an obvious choice of
t∗ = νt. (19.23)
Since the frequency ν has units of Hz = 1/s and time t has units of seconds, t∗ will be
dimensionless. We make these substitutions into our system of equations, Eqs. (19.21), and
get
d2 y ∗ dy ∗ dy
myo ν 2 2 + by o ν + k1 yo y ∗ + k2 yo3 y ∗3 = Fo cos t∗ , yo y ∗(0) = yo , yo ν (0) = 0.
(19.24)
dt ∗ dt∗ dt
Now let us scale the second order differential equation by the constant myo ν 2 , and make
obvious reductions to the initial conditions to get
d2 y ∗ b dy ∗ k1 ∗ k2 yo2 ∗ 3 Fo dy
2 + + 2
y + 2
y = cos t∗ , y ∗ (0) = 1, (0) = 0. (19.25)
dt ∗ mν dt∗ mν mν myo ν 2 dt
Let us take
b k1 k2 yo2 Fo
δ≡ , β≡ , α= , f= . (19.26)
mν mν 2 mν 2 myo ν 2
Each of these system parameters, δ, β, α, and f are dimensionless. Physically, the represent
the ratio of various forces. For example, δ is the ratio of the damping force to the so-called
“inertia” of the system:
byo ν damping force b
δ= = = . (19.27)
myo ν 2 inertia mν
The term β is the ratio of the linear spring force to the inertial force; α is the ratio of the
non-linear spring force to the inertial force, and f is the ratio of the driving force to the
inertia. Thus our governing equation becomes
d2 y ∗ dy ∗ dy ∗
2 + δ + βy ∗ + αy ∗3 = f cos t∗ , y ∗ (0) = 1, (0) = 0. (19.28)
dt ∗ dt∗ dt∗
For convenience, let us drop the ∗ notation, and simply realize that all quantities are dimen-
sionless. So we have
d2 y dy dy
2
+ δ + βy + αy 3 = f cos t, y(0) = 1, (0) = 0. (19.29)
dt dt dt
Now let us take
y1 ≡ y, (19.30)
dy
y2 ≡ . (19.31)
dt
Thus, Eq. (19.29) can be written as
dy1
= y2 , y1 (0) = 1, (19.32)
dt
dy2
= −βy1 − δy2 − αy13 + f cos t, y2 (0) = 0. (19.33)
dt
Lastly, let us define t = s = y3 , so that dt/ds = dy3/ds = 1 with t(s = 0) = y3 (s = 0) = 0.
Then, replacing t by y3 , and multiplying right and left sides of our system by dt/ds = 1, we
get
dt dy1
= (1) (y2 ) , (19.34)
ds dt
dt dy2
= (1) −βy1 − δy2 − αy13 + f cos y3 , (19.35)
ds dt
dt dy3
= (1)1. (19.36)
ds dt
y1 0
−1
Figure 19.2: Plot of prediction of position versus time, y1 (t), for the forced, damped Duffing
equation for t ∈ [0, 200]; α = 1, β = −1, δ = 0.22, f = 0.3.
We also select y1 (0) = 1, y2 (0) = 0, and y3 (0) = 0, and integrate for t ∈ [0, 200] with
∆t = 0.02. Now y3 (t) = t is not very interesting. But y1 (t) = y(t) is interesting. We plot
the position (y1 ) versus time (y3 = t) in Fig. 19.2. We see there is an initial transient and
then a relaxation to a cyclic behavior for t > 100. We then plot the velocity (y2 ) versus
time (y3 = t) in Fig. 19.3. We again see there is an initial transient and then a relaxation
to a cyclic behavior for t > 100. We plot the position (y1 ) versus velocity (y2 ) in Fig. 19.4.
Figure 19.4 was for t ∈ [0, 200]. If we only plot the long time behavior, say t ∈ [100, 200], we
find an interesting result. For this late time domain, we plot the position versus velocity in
Fig. 19.5. We see that the solution has become periodic; that is, it truly repeats itself.
0.4
y2 0
−0.4
−0.8
0 50 100 150 200 250
t
Figure 19.3: Plot of prediction of velocity versus time, y2 (t), for the forced, damped Duffing
equation for t ∈ [0, 200]; α = 1, β = −1, δ = 0.22, f = 0.3.
0.8
0.4
y2 0
−0.4
−0.8
−1 0 1
y1
Figure 19.4: Plot of prediction of velocity versus position, y2 (y1 ), for the forced, damped
Duffing equation, t ∈ [0, 200]; α = 1, β = −1, δ = 0.22, f = 0.3.
0.8
0.4
y2 0
−0.4
−0.8
−1 0 1
y1
Figure 19.5: Plot of prediction of velocity versus position, y2 (y1 ), for the forced, damped
Duffing equation, t ∈ [100, 200]; α = 1, β = −1, δ = 0.22, f = 0.3.
0.8
0.4
0.4
0
0
−0.4 −0.4
Figure 19.6: Plot of prediction of position versus time, y1 (t), t ∈ [0, 200] and velocity versus
position, y2 (y1 ), t ∈ [100, 200], for the forced, damped Duffing equation, α = 1, β = 1,
δ = 0.22, f = 0.3.
Now the negative linear spring constant was highly unusual and might be difficult to
actually build in nature. Let us return to a more physical situation where the linear spring
constant is positive; we now take β = 1 and leave all other parameters the same. We give
relevant plots in Fig. 19.6. It is noted the the phase plane plot has unfolded and now has a
simpler ellipsoidal shape. It also appears there is a single frequency in play in the long time
limit.
Let us make the problem simpler still by removing the effects of the non-linear spring by
setting α = 0. We give relevant plots in Fig. 19.7. It is noted the the phase plane plot has a
circular shape. It also appears there is a single frequency in play in the long time limit. Even
though there is damping, the amplitude of oscillation is O(1) in the long time limit.√This is
because we are forcing the system at a frequency near its resonant frequency of ∼ β = 1.
Let us change the natural√frequency√ of the system by studying β = 10, thus inducing
a resonant frequency of ∼ β = 10 ∼ 3.16. We are still forcing the system with a
dimensionless frequency of unity. We give relevant plots in Fig. 19.8. It also appears there
is a single frequency, that of the driver, in play in the long time limit. It is also noted that
the phase plane plot retains a circular shape, but its amplitude is greatly reduced. This is
because we are forcing the system at a frequency not near its resonant frequency.
Lastly, we can highlight the object-oriented nature of our approach by segregating our
source code into separate files:
• commondata.f90,
y1 y2
1 1
0 0
−1 −1
Figure 19.7: Plot of prediction of position versus time, y1 (t), t ∈ [0, 200] and velocity versus
position, y2 (y1 ), t ∈ [100, 200], for the forced, damped Duffing equation, α = 0, β = 1,
δ = 0.22, f = 0.3.
y1 y2
0.8
0.02
0.4
0.0 0.
−0.4
−0.02
−0.8
Figure 19.8: Plot of prediction of position versus time, y1 (t), t ∈ [0, 200] and velocity versus
position, y2 (y1 ), t ∈ [100, 200], for the forced, damped Duffing equation, α = 0, β = 10,
δ = 0.22, f = 0.3.
• ode1.f90
• ode2.f90, and
• solveode.f90.
Then we can build an executable file runode, to compile and execute our programs:
Subroutines: 2
161
162 CHAPTER 20. SUBROUTINES: 2
Modules
We have already seen some use of the module feature. The interested reader can consult
the text of C&S for more details.
163
164 CHAPTER 21. MODULES
There is a large body of legacy Fortran code written under the Fortran 77 standard.
Code written under this standard often has noticeable differences from that written under
the Fortran 90, 95, 2003, 2008 standards, along with many similarities. With a few
exceptions, the user can expect
• Code which compiles and executes with a Fortran 77 compiler will also compile and
execute, generating the same output, under a Fortran 90, 95, 2003, 2008 standard.
• Code which was written under the enhanced standards of Fortran 90, 95, 2003,
2008 most likely will not be able to be compiled with a Fortran 77 compiler.
As the Fortran 77 standard has fewer features and thus is more streamlined, for certain
applications, it will execute faster than programs written with the later standard, and for this
reason, some users prefer it. However, for many modern scientific computing environments,
especially those requiring dynamic memory allocation and parallelization, Fortran 77 is
simply unusable and thus not an option.
165
166 CHAPTER 22. CONVERTING FROM FORTRAN 77
• All Fortran 77 programs must have most text beginning in column 7 or greater. Ex-
ceptions are the numbers for format statements and for a few other statements. This
is a old feature motivated by the use of punchcards for early computer programs.
• The program compiles with the compiler f77 and executed successfully.
• The program compiled with the modern compiler ifort and executed successfully.
5 16.00000 278.6602
6 20.00000 278.6602
7 24.00000 270.0000
[powers@darrow2-p ame.20214]$
The Fortran 77 equivalent of this program, and its execution, is given in ch22a.f:
5 16.00000 278.6602
6 20.00000 278.6602
7 24.00000 270.0000
[powers@darrow2-p ame.20214]$
• We exercise the common option not to use :: in the variable declaration sections. We
could do this however.
• Variables must first be declared, then later assigned a value in a parameter statement.
• The kind statement is not used in Fortran 77. For (kind=4), we employ a *4. We
also could have simply used real or integer as appropriate.
• Modules are not used in Fortran 77. To pass data between subroutines and the main
program, common blocks are used. It is possible to use common blocks in Fortran 90,
95, 2003, 2008, but we will not focus on that here.
• Whole array functions such as matmul are not a part of Fortran 77.
integer :: i,neq,nt
parameter (neq=1,nt=10)
real :: y(1:neq)
real :: t,tout,dt
real :: tstop,yic(1:neq)
parameter (tstop=1.)
data yic/1./ !data statement for array
open(10,file = ’output.dat’)
t = 0. !initialize t
dt = tstop/real(nt) !determine dt
do i=1,neq
y(i) = yic(i) !assign y to its initial condition
enddo
print*,t,y !output results
write(10,*)t,y
do i=1,nt !main loop in time
tout = t + dt !set incremental end time
call ode1(y,t,tout,neq) !update y and t
print*,t,y !output the results
write(10,*)t,y
enddo
print*,’error = ’,y(1) - exp(-t)
stop
end
!
!-------------------------------------------------------------------------
!
! This subroutine evaluates the right hand side of the
! system of neq ordinary differential equations.
!
subroutine fcn(t,y,ydot,neq)
implicit none
integer neq
real :: t
real :: y(1:neq)
real :: ydot(1:neq)
real :: lambda
parameter (lambda=-1.)
ydot(1) = lambda*y(1)
return
end
!
!-------------------------------------------------------------------------
!
! The subroutine is a generic algorithm for
! the first order explicit Euler method
! for solving the system of neq ordinary
! differential equations evaluated by
! subroutine fcn.
!
subroutine ode1(y,t,tout,neq)
implicit none
integer :: i,neq
real :: y(1:neq)
real :: t
real :: tout
real :: ydot(1:neq)
real :: dt
dt = tout-t
call fcn(t,y,ydot,neq) !estimate ydot at t
do i=1,neq
y(i) = y(i)+dt*ydot(i) !estimate y at t
enddo
t = tout !update t
return
end
!
!-------------------------------------------------------------------------
!
! This subroutine is a generic algorithm for
! the second order Runge-Kutta method for
! solving the system of neq ordinary differential
! equations evaluated by subroutine fcn.
!
subroutine ode2(y,t,tout,neq)
implicit none
integer :: i,neq
real :: y(1:neq)
real :: yi(1:neq),ydot(1:neq)
real :: t
real :: tout
real :: dt
dt = tout-t
Note
• We did not use a commondata structure for shared data. Sometimes this is useful, and
one can employ a so-called common block, not done here, when appropriate.
• The number of equations, neq, was passed as a parameter to most subroutines because
Fortran 77 is more restrictive with variable sized arrays.
• We could have separated our code into distinct codes for the main program and sub-
routines, compiled each under the −c option, and employed an executable script file.
173
174 CHAPTER 23. PYTHON AND FORTRAN
The generation relies on the freeware compiler gfortran. It generates a binary output file
named ch23a.so. It also creates a large output to the screen, omitted here.
At this stage we can open Python, and use it to call upon our Fortran interface to
approximate ex . We will look at three approximations: e0 , e1 , and e2 . The sequence of
commands that achieves this is as follows:
Introduction to C
The C language is a commonly used programming language for which we give brief examples
here.
175
176 CHAPTER 24. INTRODUCTION TO C
Note:
• The #include statement inserts the object file into the program at that line.
• The #define statement will substitute the second argument for the first in all occur-
rences of the first; it is equivalent to a Fortran parameter statement.
• The code needs to appeal to external libraries, a standard input output library, stdio.h,
and a mathematics library, math.h.
• We have also opened, written to, and closed the file output.txt.
The Microsoft Excel software is a common tool for some straightforward tasks in engi-
neering computing. While it is most commonly used for business and finance tasks, with
some effort, it can be used as a a software tool to solve problems in scientific computing. It
is generally not as efficient, both in programming ease as well as computational efficiency,
as other tools that have been studied. But its near universal presence in the worldwide
business environment gives it the advantage of being able to run on nearly every modern
office computer. Occasionally, this advantage can outweigh its considerable disadvantages,
especially for small-scale problems.
179
180 CHAPTER 25. INTRODUCTION TO MICROSOFT EXCEL
Figure 25.2: Microsoft Excel spreadsheet showing formulæ to solve dy/dt = −y, y(0) = 1
using the Euler method with ∆t = 0.1.
format of Microsoft Excel, but can be realized by exercising some of the menu-driven
options. The graph shown within Fig. 25.2 is a plot of y(t) for both the Euler method and
the exact solution. With considerable and non-obvious effort, the plot could be significantly
improved. The rudimentary outline for forming this plot on the Macintosh version of Excel
is as follows:
• With the computer mouse, highlight and select all of the numbers within columns A,
B, and C.
• From the Charts menu item, select Scatter, and from within Scatter, select Smooth
Marked Scatter. This will generate a plot.
• From the Charts menu item, select Chart Layout, and from within this, select Axis
Titles. This will give you options for entering text for axis titles.
• Explore many of the other options available for formatting the graphics, for example,
under Chart Layout, one may define a Chart Title.
The actual display that is given by default upon entry of the formulæ is shown in Fig. 25.3.
Figure 25.3: Microsoft Excel spreadsheet showing results of simulation of dy/dt = −y,
y(0) = 1 using the Euler method with ∆t = 0.1.
Introduction to VBA
The VBA language is a variant of the BASIC language specialized for execution within
the spreadsheet application Microsoft Excel. It is in widespread use in many engineering
environments.
Using a so-called “macro,” a program written or recorded within Microsoft Excel to
automate a process, the user can link a code to a keyboard shortcut or a “button” in order
to perform a task repeatedly. In order to enable macro-writing, one must first activate the
Developer tab in Microsoft Excel. For Macintosh users, this can be achieved by clicking
Preferences... in the Excel drop-down menu, then navigating to Ribbon and checking
Developer in the list of tabs available. For Windows users, this can be achieved by going
to Excel Options in the Office Button, navigating to Popular, and then checking Show
Developer tab in the Ribbon. Additionally, security settings may have to be modified
in order to allow the use of macros. These settings reside again in Excel Options within
the Trust Center tab. From here, you can navigate into Trust Center Settings... and
change the Macro Settings to enable all macros.
Sub Button1_Click()
MsgBox ("hello world")
End Sub
183
184 CHAPTER 26. INTRODUCTION TO VBA
After closing the editor, one can activate the macro by clicking on the button in the spread-
sheet. A depiction of the action of the “hello world” in the Excel environment is shown in
Fig. 26.1.
Figure 26.1: Macintosh screen shot of Excel spreadsheet after executing a simple “hello
world” VBA program.
Figure 26.2: Microsoft Excel spreadsheet showing parameters to solve dy/dt = −y, y(0) =
1 with ∆t = 0.1.
’Initializing
t = tstart
y = ystart
n = Round(((tend - tstart) / dt), 0) ’rounded to 0 decimal places
’Running Euler
For i = 1 To n
t = t + dt
y = y + (-1 * y * dt)
’Printing Values to Cells
Cells((i + 2), 6) = t
Cells((i + 2), 7) = y
Next i
End Sub
• Identifies input variables from the Excel spreadsheet and reads them,
Following execution via clicking the “Run Euler” button, the spreadsheet has the display
shown in Fig. 26.3. The results are identical to those shown in Fig. 25.3.
Figure 26.3: Microsoft Excel spreadsheet showing approximate solution via the Euler
method of dy/dt = −y, y(0) = 1 with ∆t = 0.1.
d2 y dy
m + b + ky = Fo sin(νt), (26.2)
dt2 dt
with the Euler method encoded in VBA. The user may establish parameter values within the
code in the VBA workspace, or the program can call upon cells to initialize these values. For
this example, the program will draw upon a row of populated cells to obtain parameters for
the problem. This allows the user the ability to change parameters, like a damping coefficient
or forcing frequency, on the worksheet, and rerun the macro without opening the code.
One may begin by creating a Form Control Button as shown in Fig. 26.4. The user can
draw the button on the worksheet somewhere that will not interfere with the desired location
of input or output. After naming the macro (in this case MSD solve) as shown in Fig. 26.5,
clicking New will bring the user into the Visual Basic workspace where he/she will code
the program to be activated by the button.
Closing the workspace at any time will automatically save the script and return the user
to the spreadsheet. To access the VBA workspace again, the user may navigate into the
Developer tab and select Visual Basic as shown on the left of the screen in Fig. 26.6. The
code for this macro can be seen below.
Figure 26.5: Creating macro and VBA workspace: a) Drawing button, naming macro, and
beginning program, b) Visual Basic editor.
Sub MSD_solve()
Dim i, N As Integer
Dim m, k, b, Fo, nu, yo, vo, tstart, tend As Double ’Parameters
Dim y, v, t, ynew, vnew, tnew As Double ’Values to be calculated
’Initialize Variables
m = Cells(2, 2)
k = Cells(2, 3)
b = Cells(2, 4)
Fo = Cells(2, 5)
nu = Cells(2, 6)
yo = Cells(2, 7)
vo = Cells(2, 8)
tstart = Cells(2, 9)
tend = Cells(2, 10)
N = Cells(2, 11)
dt = (tend - tstart) / N
’At t=0
t = tstart
y = yo
v = vo
Cells(5, 3) = t ’print initial t
Cells(5, 4) = y ’print initial y
’Calculating solution
For i = 1 To N
tnew = t + dt
ynew = y + dt * v
vnew = v + dt * (-(k / m) * y - (b / m) * v + (Fo / m) * Sin(nu * t))
t = tnew
y = ynew
v = vnew
’print updated t, y, v
Cells(i + 5, 3) = t
Cells(i + 5, 4) = y
Cells(i + 5, 5) = v
Next i
End Sub
• It establishes the value of these variables by calling on the contents of Cells(i, j).
• It prints the values from successive iterations to the cells in a column j using the format
Cells(i + 5, j), and it offsets the row index by 5 in order to begin output beneath
the title cells.
After exiting the editor, one may activate the program by clicking on the button. Results
for t ∈ (0, 20 s), N = 20, and the parameters listed in Table 26.1, are shown in Fig. 26.7.
a cell block spanning more than one column, one can use Ctrl + Shift + ↓ + → after
selecting the top left cell.
Sub Clear()
’
’ Clear Macro
’
’
Figure 26.9: Recording a Clear Data Macro, a) Navigating to Record Macro, b) Naming
macro.
Range("C5").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.ClearContents
End Sub
• It extends the selection to the last cell of the populated cell block within the first
column, denoted Selection.End(xlDown).
• It extends the selection to the rightmost populated column with the populated cell
block with Selection.End(xlToRight).
• Once the entire cell block is included in the Selection, it depopulates it with ClearContents.
To embody this macro in a button, one can again choose a Form Control button in the
Developer tab. After placing the button on the worksheet, the user will assign the Clear
macro to the button as shown in Fig. 26.10. The two buttons now allow the user to perform
as many runs as desired for the Euler approximation of the mass-spring-damper system with
any specified time range and N+1 number of points.
One may automate a visual representation of output by creating a plot linked to the output
cell block. This example will demonstrate how the macro will automate plots of the position
and velocity of the system.
The user can create the plot by selecting the title cell reading time, using Ctrl + Shift
+ ↓ to select all time values in the column, holding Ctrl and selecting the position cell,
and then using Ctrl + Shift + ↓ again to select the entirety of the position data. Once
this data is selected, choosing Scatter from the Insert tab will display a scatter plot of the
position as a function of time.
Performing the same sequence and choosing the velocity title cell instead of the position
one will generate an analogous plot of velocity as a function of time. Figure 26.11 demon-
strates the results of this process.
These plots, synchronized with the cell blocks containing the time, position, and velocity
data, will update each time a macro is activated. Because of the Ctrl + Shift + ↓ com-
mand initially utilized to select the plot data, the scatter plots will update to include as many
entries as are generated with each run. For example, if the user increases or decreases tend or
N and then reruns the calculation macro, the number of points plotted in the scatter plots
will correspond to the new number of populated cells in the time, position, and velocity
blocks.
One may embellish the generated plots in the Chart Tools ribbon.
26.3.4 Miscellaneous
Other important items when programming in VBA:
• One can customize the button by right clicking on it, choosing Edit Text and/or
Format Control.
• One should save the Excel file as a .xlsm (macro-enabled) instead of .xlsx.
Introduction to Mathematica
The Mathematica software can be a useful tool for engineering computing. Among its
advantages are
• It is available on campus cluster machines, and can be downloaded from the OIT
website for use on personal computers, http://oit.nd.edu.
• It has a very particular syntax, forcing the user to employ precision in writing code.
• It has a very particular syntax, forcing the user to employ precision in writing code.
195
196 CHAPTER 27. INTRODUCTION TO MATHEMATICA
In[1]:= 1 + 1
Out[1]= 2
Note:
• The input is 1 + 1.
• One employs “shift-return” from the keyboard and gets the output.
27.3 Precision
Mathematica has many ways to handle precision. Some of them are shown in ch26b.nb:
In[3]:= 1/3
Out[3]= 1/3
In[4]:= 1./3.
Out[4]= 0.333333
In[5]:= 1/3 // N
Out[5]= 0.333333
In[6]:= N[1/3]
Out[6]= 0.333333
Out[7]= 0.33333333333333333333
Out[9]= 0.33333333333333333333333333333333333333333333333333
Note:
• When rational numbers, i.e. ratios of integers, are entered, rational numbers are out-
put.
• The default number of digits output to the screen for a finite precision number is six.
• We can request as much precision as we desire. Twenty digits are requested for x by
N[x, 20]; fifty digits are requested by N[x, 50].
Out[1]= 3
Out[2]= 27
Out[3]= {2, 4, 5}
Out[4]//MatrixForm=
2
4
5
Out[6]//MatrixForm=
1 3 2
4 5 2
0 9 1
Out[8]= {2, 4, 5}
Out[9]= {1, 2, 3}
Out[11]= 5/47
Out[12]= 16/47
Out[13]= -(3/47)
Out[14]= 1
Out[15]= {0, 0, 0, 0, 0}
Out[16]= {1, 2, 3, 4, 5}
Out[19]//MatrixForm=
1 2 3
2 4 6
3 6 9
Out[20]//TeXForm=
\left(
\begin{array}{ccc}
1 & 2 & 3 \\
2 & 4 & 6 \\
3 & 6 & 9
\end{array}
\right)
27.5 Algebra
The code ch26d.nb gives some algebra operations:
(* Factor a polynomial *)
Factor[x^2 + 4 x + 3]
Out[2]= (1 + x) (3 + x)
Out[4]= 6 + 5 x + x^2 == 0
Out[7]= -3
Out[8]= -2
In[9]:= (* Solve a general quadratic equation and give the result in Fortran form *)
{s1, s2} = Solve[a*x^2 + b*x + c == 0, x]
x1 = x /. s1
x2 = x /. s2
Out[9]= {{x -> (-b - Sqrt[b^2 - 4 a c])/(2 a)}, {x -> (-b + Sqrt[b^2 - 4 a c])/(2 a)}}
In[12]:= x1 // FortranForm
In[13]:= x2 // FortranForm
The plot is in Fig. 27.2a. Had we not specified any FontFamily, we would have obtained
the default font.
We can make the fonts more readable and the axes labels italicized with the
y y
8 8
6 6
4 4
2 2
x x
-2 -1 1 2 -2 -1 1 2
a) b)
Plot[{2 x^2 + 1, x^3}, {x, -2, 2}, AxesLabel -> {x, y},
LabelStyle->{FontFamily->"Times"}, AxesStyle -> Directive[16]]
x
-2 -1 1 2
-5
y
10
x
2 4 6 8 10
Figure 27.5: List plot of the data (0, 0), (1, 1), (2, 2), (10, 10).
Plot3D[x^2 + y^2, {x, -4, 4}, {y, -4, 4}, AxesLabel -> {x, y, z},
LabelStyle -> {FontFamily -> "Times"}, AxesStyle -> Directive[14]]
The plot is in Fig. 27.7.
We can save figures in a variety of formats, including .eps. This is achieved by using the
mouse to select the figure, then going to the menu under File, and choose Save Selection
As. These plots were generated directly from Mathematica. We could have also imported
them into Adobe Illustrator for further processing.
y
10
x
2 4 6 8 10
Figure 27.6: Plot of the data (0, 0), (1, 1), (2, 2), (10, 10) combined with a plot of y = x.
27.7 Calculus
A variety of operations from calculus are described in ch26e.nb:
In[65]:= y = 2 x^2 + 3
(* Indefinite integral *)
Integrate[y, x]
(* Definite integral *)
Integrate[y, {x, 0, 1}]
Out[65]= 3 + 2 x^2
Out[66]= 3 x + (2 x^3)/3
Out[67]= 11/3
Out[68]= 4 x
Out[69]= 4
Out[4]= E^-t
nt = 11;
p = 20
yyy = Table[0, {i, 1, nt}];
ttt = Table[0, {i, 1, nt}];
tstop = 1;
dt = N[tstop/(nt - 1), p];
yyy[[1]] = 1;
ttt[[1]] = 0;
Do[
{
yyy[[i + 1]] = yyy[[i]] + dt*lambda*yyy[[i]],
ttt[[i + 1]] = ttt[[i]] + dt
},
{i, 1, nt - 1}]
yt = Table[{ttt[[i]], yyy[[i]]}, {i, 1, nt}]
p2 = ListPlot[yt];
Show[p1, p2];
Out[7]= 20
Figure 27.9: Plot of exact and Euler solution to dy/dt = −y, y(0) = 1.
Out[22]= InterpolatingFunction[{{0,1.0000000000000000000}},<>][t]
The plot of the exact and Euler solution is in Fig. 27.9. Some miscellaneous features include
• Greek letters can be formatted by use of the esc key. For example for the symbol φ,
one enters esc f esc.
• Online help for commands is available in many ways. For example for more information
on NDSolve, enter ?NDSolve.
• Occasionally, you will need to “reboot” Mathematica. This can happen when its cache
gets cluttered with old variables and you would like to refresh them. One can achieve
this by quitting the kernel. To do so, go to the Evaluation menu and select Quit
Kernel.
S. J. Chapman, 2018, Fortran for Scientists and Engineers, Fourth Edition, McGraw-Hill,
New York.
This useful text is written for first year students in engineering.
I. Chivers and J. Sleightholme, 2015, Introduction to Programming with Fortran with Cov-
erage of Fortran 90, 95, 2003, 2008 and 77, Third Edition, Springer, London.
This text gives an excellent introduction to the neophyte as well as useful information to the expert.
Practical details as well as underlying programming philosophy are included. Moreover, the authors
recognize that scientific computing is often the purpose of programming in Fortran, and include
useful examples directed at mathematical science problems which extend beyond programming.
N. S. Clerman and W. Spector, 2012, Modern Fortran: Style and Usage, Cambridge, New
York.
This is a modern text which does a good job explaining the usage of the Fortran language.
H. P. Langtangen, 2016, Python Scripting for Computational Science, Fifth Edition, Springer,
Berlin.
This text focuses on how to implement the Python scripting language for problems in scientific com-
puting. It includes a discussion of how to interface with lower level languages such as Fortran or
C.
W. E. Mayo and M. Cwiakala, 1995, Programming with Fortran 77, Schaum’s Outlines,
McGraw-Hill, New York.
211
This is a readable guide which is very useful for learning programming in Fortran 77. While it does
not have all of the modern upgrades to the language, it is nevertheless a useful source, especially with
regard to legacy code.
W. E. Mayo and M. Cwiakala, 1995, Programming with Fortran 90, Schaum’s Outlines,
McGraw-Hill, New York.
This is a readable guide which is very useful for learning programming in Fortran 90.
M. Metcalf, J. Reid, and M. Cohen, 2011, Modern Fortran Explained, Oxford, Oxford.
This is a fine textbook which introduces the Fortran language.
212
Index
213
75, 78, 80, 81, 83, 84, 86, 87, 99, 107, MATLAB, 11, 20–22, 60, 61, 73, 80, 173
109, 110, 112, 119–121, 124, 127, 129– matmul, 73, 78, 80, 168
132, 165 matrix addition, 84
Fortran 2003, 11, 14, 18, 165 matrix-matrix multiplication, 80
Fortran 2008, 11, 132, 165 matrix-vector multiplication, 78
Fortran 77, 165–168 Microsoft Excel, 11, 22, 179, 183
Fortran 90, 11, 14, 18, 165 Microsoft Windows, 11
Fortran 95, 11, 165 mkdir, 31
function subroutine, 107, 111–113, 115, 116 module, 109–111, 113, 150, 163
more, 31
gedit, 19, 28, 52 mv, 31
gfortran, 18, 174
NaN, Not a Number, 108
hello world, 14, 165, 175, 179, 183, 195
netfile, 15
HTML, 28, 30
non-linear ordinary differential equations, 145,
if, 39 150
ifort, 18, 22, 41, 49, 51, 97, 132, 166
object-oriented programming, 35, 109
imag, 129
open, 96
implicit none, 40, 43
operations, 45
input output, I/O, 39, 41, 43
ordinary differential equations, 10, 123, 145
int, 108
OS-X, 11, 13
integer, 39, 41
output, 89
integer division, 46
intent, 111, 142 overflow, 49, 93
interpreted language, 21 Pascal, 10
Java, 10, 109, 110 pointers, 139
pre-defined functions, 107
Kate, 19 print, 39
kind, 41 pwd, 30
Python, 173
LATEX, 27, 200
less, 31 quadratic equation, 119, 143, 201
Linux, 11, 13, 15–19, 27, 28
load, 61 Random Access Memory (RAM), 22
local variable, 142 read, 39, 99
log, 108 real, 39, 41, 108, 129
log10, 108 rm, 31
logical, 42 rmdir, 31
ls, 30 Runge-Kutta method, 146, 150
214
software, 22
sqrt, 108
ssh, 15
subroutine, 35, 141–143, 150, 161, 172, 173
function, 107, 111–113, 115, 116
tan, 108
tanh, 108
Taylor series, 173
Terminal, 15
terminal, 17, 19, 22, 31
TeXnicCenter, 27, 28
TeXShop, 27, 28
text editor, 19, 22
transpose, 76
transpose, 73
undefined variables, 51
underflow, 49
unformatted, 41, 99
Linux, 13
UNIX, 11, 19, 20, 30–32, 117
user-defined functions, 109
X Windows, 17
X11, 17
xming, 17
XQuartz, 17
215