A First Course in Scientific Computing
A First Course in Scientific Computing
Scientific Computing
Symbolic, Graphic, and Numeric
Modeling Using Maple, Java,
Mathematica, and Fortran90
Fortran Version
RUBIN H. LANDAU
Fortran Coauthors:
KYLE AUGUSTSON
SALLY D. HAERER
Preface xiii
Chapter 1. Introduction 1
1.1 Nature of Scientific Computing 1
1.2 Talking to Computers 2
1.3 Instructional Guide 4
1.4 Exercises to Come Back To 6
Chapter 20. 2-D Arrays: File I/O, PDE’s; Realistic Capacitor 344
20.1 Problem: Field of Realistic Capacitor 344
20.2 Theory and Model: Electrostatics and PDEs 344
Laplace’s Partial Differential Equation* 346
20.3 Algorithm: Finite Differences 346
20.4 Implementation: LaplaceFile.f90 348
LaplaceFile.f90 Orientation and Visualization 349
20.5 Exploration 350
CONTENTS vii
Bibliography 400
Index 405
List of Figures
This book contains an introduction to scientific computing appropriate for all lower-
division college students. Its goal is to make students comfortable using comput-
ers to do science and to provide them with tools and knowledge they can utilize
throughout their college careers. Its approach is to introduce the requisite mathe-
matics and computer science in the course of solving realistic problems. On that
account care is given to indicate how each discipline uses its own language to de-
scribe the same concept, how their tools are useful to us, and how computations
are often concrete examples of abstract ideas.
This is easier said than done. On the one hand, lower-division students are
simultaneously learning elementary mathematics and physics, and so this may be
the first place they encounter the science and mathematics used in the problems.
On the other hand, in order for the tools and techniques to be useful for more than
the assigned problem, we give more than an introduction (the original title of this
book) to the computational tools. We address the first issue in our teaching by
reminding the students that our focus is on having them learn the techniques in the
proper context, and that any new science and mathematics they become familiar
with will make it easier for them in their other courses. We address the second issue
by placing an asterisk * in the title of chapters and sections containing optional
materials and by reminding the students of which sections are most appropriate
for the problem at hand.
This book covers some of the basics of computation, numerical analysis, and
programming from a computational science point of view. We want the reader to
acquire some ideas of what is possible with computers, what type of tools there
are for it, and how to go about getting all the pieces to work together. After that,
it is easy to use on-line help or the references to get more details. As a result, our
presentation is more practical and more focused on mathematics and science than
an introductory programming or computer science text, with minimal discussion
of computer science theory. The book follows our own personal preference for
“just enough” computer information in that it avoids going through every option
for every command and instead presents realistic examples.
We follow the dictum that science and engineering students learn computing
best while sitting down at a computer in a trial-and-error mode. Hence, we adopt
xiv PREFACE
to compiling a code, it does make a useful extension of the text. Even though we
do not try to reveal the full power and complexity of LATEX, we do give enough of
its basic elements for the reader to write beautiful-looking scientific documents.
Depending on how many chapters and modules are used, this book contains
enough materials for a one- or two-semester course. Our course has one lecture
and two labs every week, with roughly one instructor for every 10 students in lab.
Attending lectures and reading the materials before lab are important in acquaint-
ing the students with the general concepts behind the exercises and in providing
a broad picture of what we are trying to do. The supervised lab is where the real
learning occurs.
We believe that a modern student should be acquainted with several approaches
to scientific computing. Notwithstanding our avowed claim that there are multiple
paths leading to good scientific computing, we have had to make some choices
as to what to place in the printed version of this book and what to place on the
CD. The basic ideas behind scientific computing are language independent, yet
the details are not. For all these reasons we have decided to cover Maple, Java,
and LATEX in the printed version of this book, but to place other languages on the
CD that comes with the text.
The CD is platform independent and has been tested on Windows, Macs, and
Unix. The Java and Fortran programs are pure text. The Maple and Mathematica
files, however, require the respective programs to execute them. The pdf files will
require Abode Acrobat, which is free. Any difficulties with the CD should be
reported to [email protected]. Additions and corrections to the CD are found on
our Web pages (http://www.physics.orst.edu/˜rubin/IntroBook) or through Princeton University
Press Web pages (http://pup.princeton.edu/titles/7916.html).
Specifically, the CD contains Java programs, LATEX files, data files, and various
supplementary materials. As indicated, it also contains Maple worksheets with
essentially identical materials as in the Maple section of the text but in an interac-
tive format that we recommend over reading the paper version. Furthermore, the
CD contains essentially identical materials to the Maple tutorials as Mathematica
notebooks. These can be read with Mathematica or printed out as an alternative
version of the text. Likewise, the CD also contains the Java materials of the text
converted over to Fortran90, as well as the appropriate Fortran programs. Though
we do not recommend trying to learn two languages simultaneously, having al-
ternative versions of the text does present some interesting teaching possibilities.
Additions and corrections to the CD are found on our Web pages.
Acknowledgements
This book was developed on seven year’s worth of students in the introductory
scientific computing class at Oregon State University. The course was motivated
by the pioneering text by Zachary [Zach 96] and encouraged by [UCES]. The
xvi PREFACE
course has been taught by Albert Stetz, David McIntyre, and the author; I am
proud to acknowledge their friendship and the inclusion of their materials in the
text. I have been blessed with some excellent student assistants without whose
efforts the course could not be taught and the materials developed; these include
Matt Des Voigne, Robyn Wangberg, Kyle Augustson, Connelly Barnes, and Juan
Vanegas. Valuable materials and invaluable friendships have also been contributed
by Manuel Páez and Cristian Bordeianu, coauthors of our Computational Physics
text, and Sally Haerer. They have helped make this book more than the introduc-
tion it would have been otherwise. I look forward to their continued collaborations.
Financial support for developing our degree program in computational physics
and associated curricular materials comes from the National Science Foundation’s
Course, Curriculum, and Laboratory Improvement program directed by Duncan
McBride, and the Education, Outreach and Training Thrust area of the National
Partnership for Computational Infrastructure, under the leadership of Gregory Moses
and Ann Redelfs. The courses and materials have benefited from formative and
summative assessments by Julie Foertsch of the LEAD Center of the University
of Wisconsin. This work has also benefited from formative comments by various
reviewers and colleagues, in particular Jan Tobochnik and David Cook. Thanks
also goes to my editor, Vickie Kearn at Princeton University Press, who has been
particularly insightful, encouraging, and courageous in helping me develop this
multidisciplinary text and having it turn out so well, and to Ellen Foos for her
caring production of the book. And Jan Landau, always.
RHL
Chapter One
Introduction
The goal of scientific computing is problem solving. The computer is needed for
this, because real-world problems are often too difficult or complex for analytic
or human solution, yet workable with the computer. When done right, the use
of a computer does not replace our intellect, but rather leverages it by providing
a super-calculating machine or a virtual laboratory so that we can do things that
were heretofore impossible.
Figure 1.1 Left: Computational science is a multidisciplinary field that combines science with com-
puter science and mathematics. Right: A new paradigm for science in which simulation
plays as essential a role as does experiment and theory.
Before you tell the computer to obey your orders, you need to understand
that life is not simple for computers. The instructions they understand are in a
basic machine language1 that tells the hardware to do things like move a number
stored in one memory location to another location, or to do some simple, binary
1 The “BASIC” (Beginner’s All-purpose Symbolic Instruction Code) programming language should not be
ls cd
dir
javac xmaple
A shell is a name for a command-line interpreter, that is, a place where you
enter a command for the computer to obey. It is a set of medium-level commands
or small programs, run by the computer. As illustrated in Figure 1.2, it is helpful to
think of these shells as the outer layers of the computer’s operating system. While
every general-purpose computer has some type of shell, usually each computer has
its own set of commands that constitute its shell. It is the job of the shell to run
various programs, compilers, and utilities, as well as the programs of the users.
There can be different types of shells on a single computer, or multiple copies of
the same shell running at the same time for different users. The nucleus of the
operating system is called, appropriately, the kernel. The user seldom interacts
directly with the kernel, but the kernel interacts directly with the hardware.
1. Most of education is learning what the words mean; the concepts are usually
quite simple once you understand what you are being told.
2. Confusion is the first step to understanding.
3. Traumatic experiences tend to be the most educational ones.
This book has an attitude, and we hope you will develop one too! We enjoy
computing and relish the increased creativity and productivity resulting from pow-
erful computing tools. We believe that computing has become part of the fabric
of science and that an introductory scientific computing course should be part of
every lower-division university student’s education. Hence we deliberately mix the
languages of mathematics, science, and computer science. This mix of languages
is how modern scientists think about things, and since ideas must be communi-
cated with these same words and ideas, this is how the book is written. However,
we are sensitive to the confusion multiple definitions may reap and do provide a
section at the end of each chapter indicating some key words and concepts, and a
INTRODUCTION 5
glossary at the end of the book defining many technical terms and jargon.
Be warned, there are some exercises in this book that give the wrong answer,
that lead to error messages, or that may “break” the program (but not harm the
computer). Learning to cope with the limits of computation gets easier and less
traumatic after you have done it a few times. We understand, however, that many
instructors may not appreciate a computer’s failure that they cannot explain, and so
we have assembled an Instructor’s Survival Guide, available upon request through
the Web.
It is important that students become familiar with the material in the text
before they come to lab. A lecture helps, but reading and working through the
materials is essential. Even though it may not be that hard to work through the
problems in lab by having instructors and fellow students prompt you with the
appropriate commands to enter, there is little to be gained from that. Our goal is to
make this introductory experience very much a “lab” that develops an attitude of
6 CHAPTER 1
experimentation and discovery and that nurtures rewarding feelings when a project
finally computes correctly.
On the technical side, we have developed the materials with Maple 6–9.5,
Mathematica 4.2, and the Java Development Kit (JDK or Java 2 Standard Edition,
J2SE) [SunJ]. Even though studio and workbench environments are available,
we prefer the pedagogical value in using a shell to issue separate commands for
compilation and execution, and then having to deal with the source and compiled
files directly. In addition, many students are able to load JDK onto their home
computers and work there as well.
We have found that WinEdt [WinEdt] and TextPad work well to edit and run
source code on a Windows platform, and that Xemacs [Gnu] with Java tools is
excellent for Unix/Linux machines. In addition, jEdit, the Open Source program-
mer’s editor [jEdit], is an excellent tool that, because it itself is written in Java, runs
on most any platform. Visualization is very important in computational science. It
is built into Maple and Mathematica and is excellent. Part of the power of Java is
that it has strong graphical capabilities built right into the language, although call-
ing them up is somewhat involved. Consequently, we have adopted the free, open
source package PtPlot [PtPlot] as our standard approach to plotting with Java, and
Dislin for Fortran 90. However, gnuplot [Gnuplot] and Grace [Grace] are also
recommended as stand-alone applications. For 3-D graphics, a more specialized
application, we give instructions on using gnuplot and refer the interested reader
to OpenDx [DX] and VisAd [Visad]. These too are free, powerful, and available
for Unix/linux and Windows computers.
FORTRAN BY DOING
Chapter Nine
Getting Started with Fortran
Overview of a compiler
To solve a numerical problem, we create a distinct, unambiguous set of instruc-
tions using a pre-defined syntax (or grammar) specifically designed for the computer
language we want to use (Fortran in this case). We enter and store these instructions
in a file which is commonly referred to as the source file or source code.
A special system program called the Fortran compiler translates our source code
and creates an equivalent binary set of instructions designed for only the computer to
read and understand. This step is referred to as the compile step. This binary file is
called the object file or the object module.
This object file is then linked with other required system-level library binary files
to produce the final executable file (also called the load module). This resulting file
can now be loaded into the computer’s memory and executed, whereby each instruc-
198 CHAPTER 9
tion that we originally designed to solve our numerical problem is actually performed
by the computer.
Once this compiling process is completed and the executable file has been gen-
erated, the program instructions can be performed many times without re-entering
these instructions or re-compiling the program. It is likely that we have different sets
of input data which require the use of our program’s instructions. Creating a file once
containing the needed instructions to solve a numerical problem, and then using that
file multiple times thereafter, is a clear advantage.
However, if changes are required to improve the program or add new features
and calculations, then we can edit the source file appropriately (just the parts that
need improvement), recompile this newer source file to produce a new executable
file, then execute (or run) our program using various input data as needed.
Just as you probably have found it rather rare to be able to enter many Maple
commands without making at least one error, it will also be rather rare that you can
write a long program perfectly on the first try. However, there are many rewards to
be had by trying, and once you get it right it can be made to really zip along. But
not to worry, we will start you with programs to modify rather than making you
start from scratch.
Area.f90 a.out
Area.o
Area.exe
Whether simple or complex, developing Fortran programs requires the two basic
elements indicated in Fig. 9.1. The first is a source file that you have written using
Fortran commands and has a filename ending with .f90. The second is the binary,
executable file that the computer generates, or “compiles,” using the Fortran90
compiler. It may have the name ending with .o, or .exe (Windows), or be called
a.out (Unix).
For instance, on the CD you will find a simple program Area.f90 which
calculates the area of a circle, and with which we will experiment. As briefly
explained earlier, there are a number of processes involved in order to convert
(translate) Area.f90 to something closer to what a computer can understand and
run. Here are some facts and terms to help further clarify the needed process:
• You enter a command to compile the source program. You must be in an
200 CHAPTER 9
When we illustrate commands like above, the first character (or field of char-
acters) is the shell’s prompt, the second field, in monospaced bold type, is the
command that you enter, and the third field (justified to the right) contains notes
of explanation which should not be entered.
• For these commands to work, you must issue the f90 command from within
the directory in which the file Area.f90 is stored1 . If the compilation was
successful (you get no error messages), the Fortran compiler will have writ-
ten another file in the same directory, named either Area.exe on Windows,
a.out on Unix, or possibly Area.o, where the .o indicates “object file.” As
mentioned before, this compiled program generated by the F90 compiler is
what is called the load module or executable file. This file contains the binary
commands which can be loaded into the computer and then executed.
• A compiled program is actually produced in a number of stages. First, the
source code is compiled into a binary file which lacks some of the things
needed to be complete (such as math library routines). The second stage is
called linking, where one or more object files are combined with needed li-
braries to produce the final executable. This executable will run on your com-
puter, or on one with similar hardware, without having to invoke the compiler
again. In contrast, the compiled code generated by Java can be executed on
almost any computer, but the Java run-time package must be installed in order
to do so, and it runs more slowly.
• The last step of the process in Fig. 9.1 is executing or running your program.
This is done by entering the name of the resulting executable file (depend-
ing upon your operating system) at your operating system’s command line
prompt. Here is an example from Unix:
> a.out Execute the file called a.out
1 If you are using a programming or studio environment package such as Code Warrior, some of this will be
done automatically for you, or maybe you will have to push a button. Nevertheless, it’s a good idea to know what
files you have created.
GETTING STARTED WITH FORTRAN 201
On some Unix machines, the system may not be set up to look for executa-
bles in your current directory, in which case you will need to change to the
directory (cd directory name) containing your executable, or you can sim-
ply provide its full pathname instead.
As a general rule, you do not learn how to compute just by reading about it. To
understand a program you must get it running and giving correct answers. So
before we try to explain what is inside a Fortran program, let us get one running.
In Lst. 9.1 is the Fortran source code for the program Area.f90 that calcu-
lates the area of a circle. The line numbers on the left are there to help us explain
the program to you; they are not part of the program and should not be entered.
The Fortran statements in the middle are the instructions the computer needs to
process. The text after the ! characters is a comment for explanation purposes that
does not have to be entered, but should be for explanation and future reference.
When the compiler encounters a ”!”, it ignores everything on that line following
the !.
Listing 9.1 Area.f90
1 ! Area . f 9 0 : C a l c u l a t e s t h e a r e a o f a c i r c l e , s a m p l e p r o g r a m
2 ! −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
3 Program C i r c l e a r e a ! B e g i n main p r o g r a m
4 I m p l i c i t None ! Declare a l l v a r i a b l e s
5 R e a l ∗8 : : r a d i u s , c i r c u m , a r e a ! Declare Reals
6 R e a l ∗8 : : P I = 3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 ! D e c l a r e , a s s i g n R e a l
7 I n t e g e r : : model n = 1 ! Declare , assign I n t s
8 p r i n t ∗ , ’Enter a radius:’ ! Talk to user
9 read ∗ , radius ! Read i n t o r a d i u s
10 circum = 2 . 0 ∗ PI ∗ r a d i u s ! Calc c i r c u m f e r e n c e
11 a r e a = r a d i u s ∗ r a d i u s ∗ PI ! Calc area
12 p r i n t ∗ , ’Program number =’ , m o d e l n ! P r i n t p r o g r a m number
13 p r i n t ∗ , ’Radius =’ , r a d i u s ! Print radius
14 p r i n t ∗ , ’Circumference =’ , c i r c u m ! Print circumference
15 p r i n t ∗ , ’Area =’ , a r e a ! Print area
16 End Program C i r c l e a r e a ! End main p r o g r a m c o d e
• Use a text editor2 to enter Area.f90 into a file named Area.f90 in the directo-
ry/folder set aside for your work. By “enter” we mean actually type the program
from scratch rather than cut and paste it into a file. You may view this as mindless
clerical work, but reading and looking at what you are entering helps make this
foreign language seem not quite so alien.
2 An editor is a program like Notepad on a Windows PC, or nedit or Xemacs on Unix. Word processing
programs like Word or Word Perfect are possible, but you must remember to save the file as Text to avoid control
characters that will confuse the compiler.
202 CHAPTER 9
• After you have entered the entire program, save it into a file named Area.f90.
Make sure that this file is in the proper directory for your personal work.
• Open a shell from which you may enter commands, change to the directory
where you have saved Area.f90, and compile it:
> f90 Area.f90 Get help if this doesn’t work
• We remind you: the > here is the computer’s operating system prompt to you,
the command you enter is in bold monospaced font, and the last field of text is our note of
guidance or explanation (not to be typed by you).
• In order to stop Fortran from yelling at you when you compile the program, you
may have to correct some silly typographical errors made when you entered the
program. To correct an error, go to your editor (it’s a good idea to keep it open in
a separate window while you compile in the shell’s window), and change what’s
there so that it agrees with what we have in the preceding Area.f90 program. Then
save Area.f90 in the same directory where you are doing the compiling.
• If compilation is successful, you will not be told much (you have to do something
wrong to get noticed). However you can check that the object code, Area.exe or
a.out, was created by listing all the files, including creation times:
• Make sure that you have saved and closed your Area.f90 file. (Saving writes
a copy to the hard disk for storage, and closing removes it from the grasp of the
editor.) The executable file (Area.exe or a.out) is a binary-type file and is not
meant for human comprehension; it is not recommended that you try to view it.
What you would see would not be illuminating and may even mess up your editor.
• If you do not like the name a.out for your executable, you may use the -o option
to specify your preference:
> f90 Area.f90 -o Area.o Name your object file Area.o
• To see how Fortran responds to not doing things correctly, be adventurous and
try below some unconventional variations on the theme:
• Check again that you have created the executable version of your Fortran pro-
gram; that is, ensure there is a file a.out or Area.exe or whatever you may have
named it:
GETTING STARTED WITH FORTRAN 203
• As we see from Fig. 9.1, once we have the compiled code in the file Area.exe
or a.out, we get the computer to execute it by simply typing in its file name:
• Note that Windows does not require the .exe extension to be entered, although
it’s OK if you do. Now that you have a program that is running, check that it
is actually doing what you intended by entering various values for the radius. In
particular, try entering a value of 10 for the radius at the prompt written by your
program:
Enter a radius:
10
As you know, the program should tell you that the circumference of your circle is
equivalent to 20 π , and that the area is equivalent to 100 π .
We now look at Area.f90 to get some idea of how a program goes about its busi-
ness. Though a simple program, it is not trivial in that it contains a number of
important parts. Admittedly it is hard to understand at first all that is going on; be
patient, after seeing them a few times it begins to make more sense.
Program Circle area - This line declares the name of the program to be Circle area,
and begins the program. The name of the program must be different from the
names of any variables used in the program, so be sure to specify a name which is
descriptive and unique. If we had simply used area as the name for the program,
an error would be generated by the Fortran compiler because area is declared on
line 5 as a variable. If the program were named Area or AREA, the compiler would
still complain because Fortran 90 treats all code as if it were one case; it does not
distinguish between uppercase and lowercase letters. In fact, the statements in file
Area.f90 could be typed entirely in uppercase and would execute no differently
204 CHAPTER 9
from the version in lowercase. Actually, the only difference would be that the
quoted text printed by the computer would be displayed on the screen in all capital
letters since this text is taken literally.
The Program line is where the execution of the program begins. The body
of the main program is made up of all the lines of code between the Program state-
ment (line 3) and the End Program statement (line 16). The code lines between
Program and End Program are executed in order, one at a time.
Implicit None- The Implicit None statement on line 4 indicates that there are no
implicit variables, and so all variables must be declared before they can be used.
This is not a required command but it is highly recommended as a good way to
catch errors (like misspellings). Without Implicit None, variables with names
starting with i, j, k, l, m, n are automatically declared as integers (whole
numbers), and all other variables are automatically declared as reals (numbers
with fractional components called floating-point numbers). All variables must be
declared immediately following the Implicit None statement. This means you
can always look up to this area in your code to find a list of all variables used in
the program.
Real*8 :: radius, circum, area- Before you use a variable in Fortran, you should
declare its name and data type. Our use of Implicit None requires you to do this.
The first declaration line in this program lists the variables radius, circum and
area to be of type Real*8, that is, double precision. The next line declares the
variable PI to be of type Real*8, and simultaneously assigns a specific value to it.
The last declaration line states the variable model n to be an Integer. (We will
describe data types in Chapter 10).
Notice that in each of these lines there is first a data type, Real*8 or Integer,
followed by the double colon :: separator, and then a series of one or more vari-
ables which will be stored as the stated data type. This is the basic Fortran syntax
for variable declaration statements. Multiple variables can be placed on a single
line, although it is probably best to add additional declaration lines rather than
have one line so long that its end is hidden beyond the edge of the screen.
read *, radius- This read command captures text entered from the keyboard and
assigns it to the variable radius. When the program runs, a text input cursor is
displayed on the screen and the program waits for the user to enter some text and
press Return. Since radius is a Real*8 (double-precision) variable, the characters
you enter will be converted to a number before being stored in the variable. If
the user of the program is uncooperative and enters some alpha text instead of
a number, the program will generate an error and terminate (commonly called a
crash in computer lingo).
circum = 2.0 * PI * radius - Lines 10 and 11 are assignment statements. They compute
the numerical value of the expression on the right side of the = sign, and then assign
that value to the variable on the left side. Here, we use the word “assign” to mean
store a numerical value in the memory location reserved for that variable. This is
the same as the assignment operator := in Maple.
print *, ’Program number =’, model n - This writes a string and a variable to a single
line on the screen. After the asterisk, the variables to be printed should be separated
by commas.
End Program Circle area - The last line in Area.f90 is the matching End Program
statement for the Program statement on line 3. The Program and End Program
statements always form a pair.
1. Modify Area.f90 into a new program Volume.f90 which calculates the vol-
ume of a liquid in a spherical tank of radius R, when the liquid is a height
H above the bottom of the tank. We have already studied this problem with
Maple in Chapter 8, Searching, Programming; Dipsticks, where we derived
that the volume V = πH 2 (R − H/3). Make sure to test your program for
H = 0, R, and 2R, that is, for an empty, half-full, and full tank.
2. Explain in just a few words:
a. what the Fortran compiler does
b. what the Fortran linker does
c. how Fortran differs from an operating system
d. what a shell is
Chapter Ten
Data Types, Limits, Procedures; Rocket Golf
Michele, our golf fanatic, is still in pursuit of the world’s record for the fastest
golf ball. Recall, she hits her golf balls from a rocket moving to the right with a
velocity v = c/2√ relative to observer Ben on earth. Michele hits her drive with a
speed of U = c/ 3 at an angle θ = 30o with respect to the moving rocket. She
observes her drive to remain in the air for a (hang) time T = 2.6 × 107 seconds.
1. How would Ben, watching Michele’s drive from the earth, describe the golf
ball in terms of its speed, angle φ and hang time T ?
2. How would the answer to 1. change if Michele hit her ball to the left, that is,
in a direction opposite to the rocket’s velocity?
3. If Michele hit the ball with a speed U = c, how would the answers change?
The formulas we need from special relativity relate the description of the
same moving object as it appears to observers in different frames. If Michele in
O’ sees her golf ball having velocity components:
U = (Ux , Uy ), (10.1)
then Ben in O, who sees Michele moving to the right with velocity v , will see her
golf ball move with velocity components:
U = (Ux , Uy ). (10.2)
The two sets of components are related by the following:
Ux + v Uy 1
Ux = , Uy = , γ= . (10.3)
1 + vUx /c2 γ(1 + vUx /c2 ) 1 − v 2 /c2
Before we begin to calculate with Fortran, it is in your best interest to explore the
limitations of its numerical capabilities. The limitations arise from the schemes
208 CHAPTER 10
Table 10.1 Fortran’s basic data types and their sizes in bytes (B)
10.3 INTEGERS
The most elementary unit of memory is, effectively, a little magnet that is either
charged or not (imagine a compass needle pointing up or down). If we associate
“down” with the numeric digit 0 and “up” with the digit 1, then we have a physical
device that symbolically stores 0’s and 1’s. It should then be no great surprise to
hear that all numbers on the computer are ultimately represented in binary form,
that is, in terms of the binary digits (abbreviated bits) 0 and 1.
Just like the digits in the decimal system indicate the number of times that
each 100 , 101 , 102 , . . . , is contained in a numeric value, so it is with the binary
system, except that the base is 2 and not 10. To demonstrate, in Table 10.2 we see
the three bits abc representing the eight numbers from 0 to 7. Likewise, N bits
are used to represent integers (whole numbers) up to 2N . In practice within the
computer’s numeric storage scheme, the first bit is used to represent the sign of
the integer; therefore, we effectively lose one bit. This means that it is possible to
represent integers only up to 2N −1 with N bits.
Long strings of binary zeros and ones are fine for computers, but are awk-
ward for people. For example, decimal 75 is 001011 in binary. Consequently,
binary strings are represented instead as octal or hexadecimal numbers, which are
compact. The problem with our beloved decimal number system is that it is not
one-to-one compatible with the binary number system, since decimal is based on
DATA TYPES, LIMITS, PROCEDURES; ROCKET GOLF 209
Table 10.2 The use of the three binary digits (bits) a, b, and c, to represent the eight decimal integers
from 0 to 23 − 1 = 7.
the power of 10 and not the power of 2. Octal (23 ) or hexadecimal (24 ) are both
easily and effectively translated directly to binary since they share 2 as their base.
Therefore, computer memory schemes for storing numerical values are based on
either octal or hexadecimal representations of binary, depending upon the com-
puter design. In practice, the most common memory scheme is based on hexadec-
imal (24 ), using 4 bits to represent one hexadecimal digit. Then, only during the
output phase, values are converted to decimal for display to humans.
The point of all this discussion about what goes on in the “guts” of memory
is to provide a brief taste of some of the complexities that drive computer design.
Computer texts delve into these details for chapters. The main point for you to
extract is that in one way or another, you must generally understand how many
bits will be required to store the values of each of your variables. The number
of bits is called word length and is often expressed in bytes, where a byte is a
“mouthful of bits”:
def
1 byte ≡ 1 B = 8 bits. (10.4)
Conventionally, storage size is measured in bytes or kilobytes (K). For this reason,
while only one bit is adequate to store a binary digit 0 or 1, two or more bytes
are required to store a decimal system value, or a letter, or a special character.
In practice, 8 bits or 1 byte are more than adequate to store an integer value, in
which case the integers lie in the range 1–27 or 1–128. The more usual practice of
computer design, however, is to utilize 4 bytes (4 B = 32 bits = 1 word) to store
integers. This allows for larger integers which means that the maximum positive
integer is 231 2 × 109 . In spite of what may seem a very large range for values,
it really is not so large when compared with the range of values encountered in the
physical world. To illustrate, the ratio of the size of the universe to the size of a
proton is 1040 . Though integers have limited range, they are stored exactly on the
computer if they fall within this range; otherwise, some precision (in the form of
significant digits) is lost.
210 CHAPTER 10
truncation
Overflow
Overflow
Underflow
0
−10+38 −10−45 10−45 +10+38
Figure 10.1 A schematic representation of the limits of single-precision floating-point numbers, and
the consequences of exceeding those limits.
Scientific work primarily uses floating-point numbers, which are called Reals in
Fortran. In contrast to Integers that are whole numbers, floating-point numbers
have fractional components. The number x is stored as a sign, a mantissa, and an
exponent:
xreal = (−1)s × mantissa × 2exp . (10.5)
Here, the mantissa contains the significant digits of the number, s is the sign bit,
and the exponent permits very large, as well as very small, numbers1 . A single-
precision 32-bit word may allocate 8 bits of computer memory for the exponent
in (10.5), which leaves 23 bits for the mantissa and 1 for the sign. This 8-bit
“exponent” has the range [−127, 128]. In practical terms, this means that single-
precision (4-byte numbers) has 6-7 significant digits of precision (1 part in 223 )
and magnitudes typically in the range
These ranges are represented schematically in Fig. 10.1. If you write a program
declaring double-precision, then 64-bit words (8-bytes) will be used in place of the
32-bit (4-byte) words. With 11 bits used for the exponent and 52 for the mantissa,
double-precision numbers have about 16 decimal places of precision and typically
have magnitudes in the range
1 In practice, a number called the bias is subtracted from the exponent exp so that the stored exponent is
always positive.
DATA TYPES, LIMITS, PROCEDURES; ROCKET GOLF 211
The correct answer is c). Because there is no more room left to store the significant
digits in 2.0 × 10−8 , they are lost or truncated from the answer and the addition
yields 7.
Numerical Constants
Lst. 10.1 contains the small, but significant, program Limits.f90 for you to “test
drive” during your “break in” period with Fortran. By repeatedly comparing 1+m
DATA TYPES, LIMITS, PROCEDURES; ROCKET GOLF 213
1. The code within the lines 14 to 18 form what is called a Fortran do-loop.
This is merely code that is repeated over and over (looped) until a certain
condition finally ends it. There are several syntax versions of do-loops, and
they will be explained in more detail in Chapter 12. Briefly for now, the
variable i in this example is continually incremented by 1 from the initial
value of 1 until i finally exceeds the last value, n. At this point, the loop
terminates and the statements after end do are executed.
2. Enter Limits.f90 by hand into a file of the same name, compile it, and run
it to determine the machine precision m for double-precision on your
computer. Once you understand how this program works, you may want to
modify it so that it starts closer to the final answer, or so that it runs longer in
order to get to the final answer. As is true for many of the programs we give
you, they are meant as models for you to modify, extend, and experiment.
3. Modify Limits.f90 to determine the machine precision m for single-precision
numbers. To modify it correctly, you need to change the phrase Real*8 to
Real or Real*4 in the declaration statements.
4. Underflow: Modify this program to determine the smallest positive single-
precision numbers that Fortran handles. Hint: Continuous division of epsilon m
by 2 will determine the smallest number within a factor of 2. So, modify the
line one = 1.0 + epsilon m to a division and increase the value of n so the
214 CHAPTER 10
All computer languages have syntax rules as to how to name variables. The rules
of the Fortran language are actually very simple:
Although these are the only syntax rules for naming variables in Fortran, we sug-
gest some conventions to help prevent errors and make your programs clearer.
Deviate from these conventions at your own risk!
• Write regular variables in lowercase letters. Even though a variable may start
with a lower case letter, it may contain capital letters within, such as hiMass
and loMass, to aid understanding by programmers. Recall that variable names
are not case sensitive, so iLoveYou and iLOVEYou reference the same thing.
• We have seen PI spelled with all capital letters. If the value of variable does
not change as the program runs, then it is a constant and is often denoted by
all capital letters.
• Although there are no formal reserved words in Fortran, there are many key-
words. Keywords are commands and references like PRINT, WRITE, FORMAT,
REAL, INTEGER, COMPLEX, IF, ELSE, DO, PROGRAM, CALL, USE, FUNCTION,
SUBROUTINE, MODULE, END, and many more. As per the rules, you can use
these as variable names, but experience suggests that this is a bad idea.
• Names should be meaningful and indicate the variables they represent. For
DATA TYPES, LIMITS, PROCEDURES; ROCKET GOLF 215
program readability and future modification, time spent initially naming vari-
ables appropriately is time saved during the life of the code.
Our physics description of projectile motion used the trigonometric functions cos θ
and sin θ. While Fortran itself has no knowledge of trigonometry (in contrast to
Maple or Mathematica), it does have a whole bunch of mathematical functions
built into it. As opposed to user-defined functions, the math functions are intrinsic
and can be used without any preface, loading or defining:
Listing 10.2 Math.f90
1 ! Math . f 9 0 : demo some F o r t r a n math f u n c t i o n s
2 ! −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
3 Program M a t h t e s t ! B e g i n main p r o g r a m
4 R e a l ∗8 : : x = 1 . 0 , y , z ! Declare v a r i a b l e s x , y , z
5 y = sin (x) ! Call the sine function
6 z = exp ( x ) + 1 . 0 ! Call the exponential function
7 print ∗, x , y , z ! Print x , y , z
8 End Program M a t h t e s t ! End main p r o g r a m
In most cases these functions take various argument types, such as Real*4 or
Real*8, and return the same variable type as their value. The functions abs, cos,
exp, log, sin, and sqrt also work with complex numbers (such as Complex*4 or
Complex*8):
While the built-in mathematics functions can be counted on to give accurate an-
swers, they do not know everything about mathematics, and will give error mes-
sages or non-numeric answers if pushed too far:
216 CHAPTER 10
Actions ....
Actions ....
Actions ....
End Program ProgNam e y = f(x)
callg(x,y,z)
Actions ....
Figure 10.2 Left: The structure of a Fortran program with no procedures. Right: The structure
of a Fortran program with a main program, a subroutine, and a function. The main
program and the two procedures are contained in the same source file, for instance,
ProgName.f90.
In some ways it makes sense to do all the computing in the main program (the
code within the Program and End Program block). Since the compiler looks to
this main program as the place to begin executing your code, you may as well put
your work there. For small programs this is fine since you can probably just look at
the code inside the Program code block to figure out everything that is happening;
however, programs get longer and more complicated as they are called on to do
more work. It is much easier to write and understand long programs when they are
divided into smaller parts, each having its own specific task. Also remember that
the presence of documentation, comments embedded in the program code, grows
more important as the length of the code increases.
So far we have only examined Fortran programs that do all of their work
in the main program. We have placed all needed variables and code between the
Program and corresponding End Program statements. This idea is shown on the
DATA TYPES, LIMITS, PROCEDURES; ROCKET GOLF 217
left of Fig. 10.2. Just as Maple and Mathematica permit the user to define their own
functions, so does Fortran. We will demonstrate and study two Fortran constructs
that allow this capability: the Function and the Subroutine. Both functions and
subroutines, jointly called procedures, act as mini-programs. They can perform
calculations, print out results, and even invoke other subroutines or functions. As
indicated on the right side of Fig. 10.2, in the simplest setup, this function f and
subroutine g are placed right in the same source file with the main program; they
can actually occur before or after the main program. In other programming models
that we will discuss later, related procedures are grouped together into modules, or
they can be created as separate programs called external procedures.
The concept that each basic task (or set of related tasks) can be created in a
separate code unit is called modular programming. In good modular design, the
main program is the control unit, or administrator of the entire program. Like a
good boss, it calls upon others to get the work done without doing any of the work
itself. In this approach, you get a good idea of what an entire program does just by
reading through its main program steps, without worrying about the details of the
actual calculations contained in each of the separate units or procedures.
Functions
Lst. 10.3 gives an example of a small program that contains a user-defined function
f (x, y) = 1 + sin(x y):
Listing 10.3 Function.f90
1 ! F u n c t i o n . f 9 0 : Program c a l l s a s i m p l e f u n c t i o n
2 ! −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
3 R e a l ∗8 F u n c t i o n f ( x , y )
4 I m p l i c i t None
5 R e a l ∗8 : : x , y
6 f = 1 . 0 + s i n ( x∗y )
7 End F u n c t i o n f
8 !
9 Program Main
10 I m p l i c i t None
11 R e a l ∗8 : : Xin = 0 . 2 5 , Yin = 2 . , c , f ! d e c l a r a t i o n s ( a l s o f )
12 c = f ( Xin , Yin )
13 w r i t e ( ∗ , ∗ ) ’f(Xin, Yin) = ’ , c
14 End Program Main
218 CHAPTER 10
In this example, the function is defined in the top half of the source file and the
main program is on the bottom. Although the order does not matter within the
rules of Fortran syntax, it is common to have the main program last (after all pro-
cedure units are defined and listed). Notice that our function example has two
arguments in the main program (Xin and Yin) that are passed to the function pro-
cedure and represented locally by the variables x and y that are used to compute
the function value f. Any number of arguments are permitted to be passed to the
function procedure. These values are used in this function to compute the value
of f, and then that value is returned to the calling program as the value of f in the
main program. This is basically how functions work, and we will provide more
examples to examine.
Subroutines
Subroutines can do everything that functions do, and more. For example,
Subroutine.f90 takes the same arguments as Function.f90 as input, but then
returns two answers back to the main program. The results from a subroutine are
not returned as values represented by the subroutine’s name (like with functions),
but rather are assigned as the values of the corresponding arguments (variables).
In our example, the values of the variables in Main program (Xin, Yin, Gout1,
and Gout2) are shared with the variables in Subroutine g (x, y, ans1, and ans2),
respectively, that is, is the same in both. Another important difference from func-
tions is how subroutines are invoked. Unlike functions that are used like variables
that take arguments, subroutines are called, as you see on line 13.
Exercise: Compile and execute Subroutine.f90 and check that the first answer
is the same as that obtained with Function.f90. Check that ans2 is the square of
the ans1. ♠
1. The Fortran compiler gives an error. This is good because evaluating f with
an Integer rather than Real*8 argument is the wrong match with the func-
tion definition.
2. The program gives the correct answer. This indicates that you have a non-
standard compiler, which means your codes will not be portable. In this
case, you may want to be more careful with the matching of argument types,
or start using modules or interfaces (discussed in Chapter 18) as these do the
desirable type checking for you.
3. The program crashes or gives incorrect results. Crashing is OK since it lets
you know there is an error. A wrong answer without an error indication is
220 CHAPTER 10
always a problem (since you may not know it is the wrong answer). Again,
you may want to be more careful with the matching of argument types.
Enter these changes into Function.f90 and compile and execute it. Check that
this runs and gives the correct answers. The use of temporary variables is a general
approach that is useful in many situations.
Finally, here is an important point about constants. Note that we have care-
fully avoided evaluating the function f above using an explicit constant value for
the first argument. For instance, we could have demonstrated f(5,Yin), using the
constant 5 as the value of the first argument, u. Recall that when a constant is rep-
resented without a decimal point, it is assumed to be an integer; therefore, using
5 as the first argument should lead to an error as in the previous demonstration of
using the wrong type. It also may not be acceptable to enter a real constant f(5.,
Yin), since this generally implies Real*4; and Real*8 may actually be required as
the argument type. So, constants may still be used as arguments, but you should be
explicit about their type, for instance, 5.0 8 or 5.0 4. The lesson here is caution
regarding type and precision.
We will now use Fortran90 to solve the same Rocket Golf problem as we did
with Maple in Chap. 3. With the application of modular programming, we will
now write separate procedures, as we did with Maple’s user-defined functions, to
compute γ , Ux , and Uy , and plot a graph of γ versus v using Dislin2 . Our solution
program thus contains a main program, three computational functions, and one
plotting subroutine. (Note: If you have trouble with the plot or your system does
not have Dislin already installed, simply remove the subroutine plotGamma and
2 We describe the use of Dislin in Chap. 11, Visualization with Fortran. We recommend that you read that
chapter soon, however, you may work through the present sections just by copying the plotting commands.
DATA TYPES, LIMITS, PROCEDURES; ROCKET GOLF 221
its call statement to do the exercises in this section). To determine how round-off
error affects the results, we describe and run the program that solves the problem in
double-precision, and then ask you to modify it so that it solves the same problem
in single-precision (we give the results of both, but only the source file for the
double-precision version).
29 ! F u n c t i o n gamma ( v ) − t i m e d i l a t i o n f u n c t i o n
30 R e a l ∗8 F u n c t i o n gamma ( v )
31 I m p l i c i t None
32 R e a l ∗8 : : v
33 gamma = 1 . 0 8 / S q r t ( 1 . 0 8 − v ∗∗ 2 )
34 End F u n c t i o n gamma
35
36 ! F u n c t i o n Ux r e t u r n s x v e l o c i t y
37 R e a l ∗8 F u n c t i o n Ux ( Up , t h e t a , v )
38 I m p l i c i t None
39 R e a l ∗8 : : Up , t h e t a , v , Upx
40 Upx = Up ∗ Cos ( t h e t a )
41 Ux = ( Upx + v ) / ( 1 . 0 8 + v ∗ Upx )
42 End F u n c t i o n Ux
43
44 ! F u n c t i o n Uy r e t u r n s y v e l o c i t y
222 CHAPTER 10
45 R e a l ∗8 F u n c t i o n Uy ( Up , t h e t a , v )
46 I m p l i c i t None
47 R e a l ∗8 : : Up , t h e t a , v , Upx , Upy
48 R e a l ∗8 : : gamma
49 Upx = Up ∗ Cos ( t h e t a )
50 Upy = Up ∗ S i n ( t h e t a )
51 Uy = Upy / ( gamma ( v ) ∗ ( 1 . 0 8 + v ∗ Upx ) )
52 End F u n c t i o n Uy
53
Lst. 10.5 shows the program Golf.f90. It creates initial data for the angle
and velocity of Michele’s golf ball, and computes the velocities and angles as
seen by Ben. If you set the speed of light c equal to a nearly-infinite number, the
relativistic effects vanish. Observe that in this example we have placed the main
program first in the file, followed by the functions gamma, Ux, and Uy, and then the
subroutine plotGamma. Some programmers prefer the main program to be listed
first as it shows from the start how the entire program works. This is top-down
programming. Other programmers prefer defining all the procedures (functions
and subroutines) first before they are called. That is bottom-up programming. The
Fortran compiler does not care if you call a procedure before it is defined as long
as it is defined somewhere within the source file (or in other modules that are
DATA TYPES, LIMITS, PROCEDURES; ROCKET GOLF 223
Figure 10.3 A plot of the function γ(v) output from the program Golf.f90. Compare to similar
plot done with Maple in Chap. 3.
Find where the function Uy calls the function gamma. Having one function
call another is acceptable modular programming practice. Also note that we have
kept the main program neat by placing all the plotting commands in the subroutine
plotGamma. This keeps the technical details from interfering with our ability to
see the logical flow of the program, and permits us to modify the plotting without
messing up the rest of the program. The plot obtained is shown in Fig. 10.3, and
looks much like the Maple plot in Chap. 3.
10 v = 0.5 4
11 theta = 30.0 4 * PI/180.0 4
Running this code on a PC with Compaq Fortran, produces the following output
for the two cases:
This output is the Fortran solution to the first part of the problem, where Michele
hits the golf ball forward. Realize that the exact output of these values (format and
224 CHAPTER 10
significant digits) may differ based on machine type, operating system, compiler,
etc. Generally, we will see that Fortran is smart enough to realize that its single-
precision calculations have 6-7 places of precision, and so prints out just 8 signifi-
cant figures (an extra one or two places so you are able to see the imprecision). In
contrast, Fortran prints out 16 or 17 significant figures for double-precision, where
we expect 15-16 places of precision.
In the second part of the problem, Michele hits the golf ball backwards (at
θ = 150◦ ). To find a solution here, we have to modify the program. In the double-
precision version, we should change the line theta = 30.0 8 * PI / 180.0 8 so
that it reads
theta = 150.0 8 * PI / 180.0 8
After making this modification, the results we obtained when running the program
on a PC are the following:
T = 31843366.6561813 T = 3.1843368E+07 s
ux = -1.480297366166875E-016 ux = -7.9472862E-08
uy = 0.333333333333333 uy = 0.3333333
u = 0.33333333333333333 u = 0.3333333
phi = 1.57079632679490 phi = 1.570797
Notice where the differences in precision occur between single and double in these
examples. Also notice the differences between these results here as run on a PC
and the results you have produced on your computer system.
When we solve the third part of the problem and look at the x component
of velocity that Ben sees for the backward hit, we find that the double and single-
precision calculations give:
ux = -1.4802973661668753E-016 ux = -7.9472862E-08
Assessment
It is honest to say that the single- and double-precision results differ by a factor
of 100 million! Yet this is not good computational science. It is better to say that
within the precision of the calculation, both calculations agree that the x-velocity
is zero, but that it is very hard for floating-point computations to give a result that
is exactly zero.
zero. Since the velocities predicted by the programs are much smaller than the ve-
locities used as input, this is a case in which subtractions within the program have
cancelled off all of the significant figures in our input numbers, and the output
numbers are of (very) questionable significance.
γ = 1.)
12. Modify the double-precision program so that θ = 180◦ , and interpret the
results.
13. Determine what Ben sees as the x velocity of the golf ball when the golf ball
is hit 30◦ below the left horizon, that is, at θ = 210◦ . Compare this to the
result from classical physics.
The DISLIN data-plotting library was written by Helmut Michels at the Max
Planck Institute in Lindau, Germany. Its name is an abbreviation for Device-
Independent Software LINdau since it is system-independent to a high degree,
which allows Fortran programs using Dislin to be ported from one operating sys-
tem to another without changes. Dislin consists of subroutines and functions for
graphically displaying data in the form of curves, bar graphs, pie charts, 3-D color
plots, surfaces, contours, and maps. You should reference the Dislin home page
at www.dislin.de for more information. If your system does not have Dislin in-
stalled, then you cannot run our example programs. (§11.2 describes how to install
Dislin).
VISUALIZATION WITH FORTRAN 229
• On line 9 is the command use dislin. This permits your program to import the
plotting package. It is a requirement in order to use any of the Dislin routines.
• Lines 16 through 20 initialize the variables. Note that the variables xValues and
yValues are arrays (discussed later in Chapter 17) with multiple elements to hold
the x and y values to be plotted. The do - end do pair of statements bracket the
popular Fortran do-loop covered in detail in Chapter 12.
• Lines 22 through 42 are the Dislin subroutine calls. Line 22 establishes the
intended display format before the other Dislin routines are called into action; line
23 and line 42 act as a pair to initialize and then finish the Dislin routines.
• name: labels the axes. The first argument is the string name for the axis, the
second is the internal string name for the axis.
• titlin: defines the title string. Then title builds and inserts the title appropri-
ately.
• graf: plots a 2D-axis system with the stated ranges and tick marks.
• color: sets the color of the plotted points and the curves connecting them.
• curve: connects data points with lines (or can plot them with symbols).
• dash: changes the line plotting style from solid to dashed. The xaxgit command
plots only the y = 0 line.
VISUALIZATION WITH FORTRAN 231
Run the sample program EasyDislinPlot.f90 to see the plot for yourself. On
a PC, once Dislin is installed, simply use the f90link command that is supplied
with the Dislin package. With its -a option, it is customized to handle the compile,
link, and execution of your program (including all needed Dislin libraries). When
using this command, do not enter the .f90 extension. Here is the command with
the option you will need:
If the double-precision Dislin libraries are required for a program, then you would
simply add the -r8 option like this example:
adding the setfil routine, we can establish the filename of our choice. Here is an
example:
Once created, this file could be printed or saved for future reference. When cre-
ating a file to contain a graph image for printing, it is important to note the fore-
ground/background contrast. In Dislin, the default image contains a black back-
ground and white foreground which looks great on a screen, but is difficult to
print. One might prefer these colors to be reversed. This can easily be done with
the following call placed right after the calls to metafl and setfil:
These calls that define the output display structure must all be given before initial-
izing Dislin with call disini.
The table below lists all the possible output options. Although some may
require other routines for full support, this list will provide a good overview of the
Dislin output capabilities:
Look at the EasyDislinPlot.f90 program to verify what kind of output was in-
VISUALIZATION WITH FORTRAN 233
dicated. See if you can make the needed changes to instruct the plot to go to a file
instead.
Dislin has the capability to display the results of a matrix. In the file MatrixPlot.f90,
we demonstrate this fairly straightforward approach.
41 do i =1 , rows
42 do j =1 , c o l u m n s
43 z height = i∗j
44 matrix ( i , j ) = z height
45 end do
46 end do
47 t o p = rows ∗ c o l u m n s
48 c a l l p l o t ( 0 . , 1 . , 0 . , 1 . , 0 . , top , &
49 ’Matrix Plot Example’ , m a t r i x , rows , c o l u m n s )
50 End Program M a t r i x P l o t
This program houses a subroutine plot that handles the Dislin requirements to ini-
tialize and deploy the plotting of the data matrix. The main program MatrixPlot
simply creates the matrix data and then hands it off to the subroutine.
The Dislin plotting package can also make some beautiful 3-D surface plots, which
is just what is needed for the capacitor problem of Chapter 20. Here is an example
of this problem solved in Fortran using Dislin, Laplace.f90, shown in Lst. 11.3.
VISUALIZATION WITH FORTRAN 235
52 ! J a c o b i r e l a x a t i o n u s i n g "nested" Do−Loops
53 do k =1 , tmax , 1 ! Loops tmax t i m e s
54 do i =2 , imax −1 ,1 ! C o n t r o l s row s u b s c r i p t
55 do j =2 , imax −1 ,1 ! C o n t r o l s column s u b s c r i p t
56 V( i , j ) = 0 . 2 5 ∗ (V( i +1 , j ) +V( i −1 , j ) +V( i , j + 1 ) +V( i , j −1) )
57 ! Continue applying i n t e r a l boundary c o n d i t i o n s
58 i f ( j == b o t t o m .AND. i >= r i g h t .AND. i <= l e f t ) t h e n
59 V( i , j ) = −1.0
60 e l s e i f ( j == t o p .AND. i >= r i g h t .AND. i <= l e f t ) t h e n
61 V( i , j ) = 1 . 0
62 end i f
63 end do
64 end do
65 end do
66 End S u b r o u t i n e s o l v e
67 !
68 Program L a p l a c e
69 I m p l i c i t None
70 I n t e g e r , p a r a m e t e r : : imax =101
71 I n t e g e r : : tmax =1001
72 Real , d i m e n s i o n ( imax , imax ) : : A
73 c a l l s o l v e (A, tmax , imax )
74 call plot (0. ,1. ,0. ,1. , −1. ,1. , &
75 ’Realistic Capacitor’ , A, imax , imax )
76 End Program L a p l a c e
Notice that the matrix data, V, is generated in a subroutine called solve. Then
in the subroutine plot which uses Dislin, we have isolated the plotting routine
requirements just like in the previous example. The main program, Laplace, drives
the show. Check out the nice surface plot in Fig. 11.3
1. Download the appropriate file into a work folder that you have created for
Dislin. You will find a readme file that should be quite helpful.
2. Run the program setup.exe by double-clicking on it. As it suggests, allow it
to load the files into a directory called C:\dislin which it will automatically
create.
3. Reconfigure your Windows environment so that the needed files are recog-
nized upon execution. First, you will need to create a new environment vari-
VISUALIZATION WITH FORTRAN 237
able named dislin with C:\dislin as its value. Next, you will need to add
C:\dislin\win to your current PATH environment variable (the subdirectory
\win contains the Dislin library routines). Both of these actions may be done
from the My Computer icon on your desktop:
a. Right-click on My Computer, then click on Properties, then Advanced,
then Environment Variables. Do NOT change System Variables.
b. To create a new Dislin environment variable, click on New, then enter
dislin as the variable name and C:\dislin as the variable value. Then
click OK.
c. To add the correct Dislin search path to your PATH environment variable,
click on PATH inside the box that lists the variables. Now click Edit (not
New). Within the variable value box, click your pointer directly behind
the last search path item, then add a semi-colon and the additional search
path (with no spaces). This addition should look like ;C:\dislin\win,
then click OK.
d. Finally, click OK in the Environment Variables window. Click Apply,
then OK in the System Properties box.
4. Now, change directories to C:\dislin and compile dislin.f90 in that di-
rectory. It is best to do this from within a DOS window. Once you have
initiated a DOS window:
> cd /d C:\dislin Change to the Dislin directory
> f90 -c dislin.f90 Compile to ensure compatibility
238 CHAPTER 11
Note that the file dislin.mod contains interfaces for all Dislin routines. It
must be referenced from all procedures that utilize Dislin routines via the com-
mand Use dislin at the top of each procedure requiring it.
Compilation and execution of Fortran programs that use Dislin should best
be performed from a DOS window when running on a PC. As mentioned earlier,
the Dislin package supplies a convenient linking command called f90link located
in the \win subdirectory. Remember that DOS can always find it now because you
have added its search path to your PATH environment variable. This command will
compile, link, and execute (including all needed libraries) in one fell swoop (by
using its -a option). By default, f90link uses the single-precision Dislin libraries.
For double-precision, add the -r8 option to reference the double-precision Dislin
libraries. Here are examples again for your reference:
For other operating systems you may have to download the compressed
source code1 and compile it for their system.
Gnuplot is a versatile 2-D and 3-D graphing package that makes Cartesian, polar,
surface, and contour plots. It is open software, available for free on the Web, and
produces many output formats.
You begin gnuplot with a file of (x y) data points. In Fortran so far, we have
only demonstrated how to write data and text to the screen. Chapter 13 presents
more details about various input/output (I/O) capabilities. Briefly, here is a short
code segment that may help for now:
1 open ( UNIT =1 , FILE=’graph.dat’ ) ! Open f i l e 1 , c a l l i t g r a p h . d a t
2 do i =1 , imax , 1
3 w r i t e ( UNIT = 1 , ∗ ) x ( i ) , y ( i ) ! W r i t e t o g r a p h . d a t
4 end do
5 c l o s e ( UNIT = 1 ) ! Close f i l e 1
Once you have generated a file of your (x y) data, say, graph.dat, then
you issue the gnuplot command from a shell or from the Start menu. You then
1 If you have never done this before, you may want to do it with a friend. In Windows, you can use WinZip to
unzip files. In Unix, you can try double-clicking the file in the file manager, or decompress it from the terminal
with the gunzip or tar -xvf commands.
VISUALIZATION WITH FORTRAN 239
30
' dat a. gr aph'
20
' 2. dat '
' 3. dat '
10
- 10
- 20
- 30
-6 -4 -2 0 2 4 6
Figure 11.4 A gnuplot graph for three data sets with impulses and lines.
get a new window with the gnuplot prompt gnuplot>.You construct your graph
by entering gnuplot commands at the gnuplot prompt or by using the pull-down
menus in the gnuplot window:
In Figure 11.4 we plot a number of graphs on the same plot using several data files
and the command:
gnuplot> plot ’graph.dat’ with impulses, ’2.dat’, ’3.dat’ with lines
It is necessary to place all file or directory names in single or double quotes and to
separate file names with a comma. Explicit values for the x and y ranges are set
240 CHAPTER 11
Im T(E)
30
15
-15
-30
-100
-80
-60
Im E (Me V) -40 1600
-20 1500
1400
0 Re E (MeV)
1300
Figure 11.5 Gnuplot’s surface plot of a scattering amplitude ImT as a function of complex energy
E.
Printing Plots
Gnuplot supports a number of printers including PostScript ones. The basic method
of printing plots is:
1. Set “terminal type” for your printer.
2. Send the plot output to a file.
3. Replot figure for new output device.
4. Quit Gnuplot (or get out of Gnuplot window).
5. Print file.
You could also import the file into a word processor to have it appear in a document
or into a drawing program to fix it up just right. To see what type of printers and
other output devices are supported by Gnuplot, enter the set terminal command
without any options into a gnu window for a listing of available terminal types.
Here is an example of creating a PostScript figure and printing it:
VISUALIZATION WITH FORTRAN 241
The surface (3-D) plot command is splot, and it is used in the same manner as
plot—with the obvious extension from (x, y) to (x, y, z). As discussed in Chap-
ter 4, a surface, such as that in Figure 11.5, is specified by giving just the z values
for successive rows, with different rows separated by blank lines:
Because there are no explicit x and y values given, Gnuplot labels the x and y axes
with the row and column number. At present Gnuplot does not have the capability
to rotate 3-D plots interactively. Instead, you adjust your plot with the command:
gnuplot> set view rotx, rotz, scale, scalez
where 0 ≤ rotx ≤ 180o and 0 ≤ rotz ≤ 360o are angles in degrees, and the scale
factors control the size. Any changes made to a plot are made when you redraw
the plot using the replot command.
To see how this all works, here we give a sample Gnuplot session that we
will use in Chapter 20 to plot a 3-D surface from numerical data. Listing 11.3
contains the actual code used to output data in the form for a Gnuplot surface plot.
> gnuplot Start gnuplot system from a shell
Then, a special Gnuplot shell starts up with the prompt gnuplot>, and you are
ready to give gnuplot your subcommands.2
2 Under Windows, there is a graphical interface that is friendlier than the gnuplot subcommands. The subcom-
For this sample session, the default output for your graph is your terminal
screen. To print a paper copy of your graph, we recommend first saving it to
a file as a PostScript document (suffix .ps), and then printing out that file to a
PostScript printer. You create the PostScript file by changing the terminal type
to Postscript, setting the name of the file, and then issuing the subcommand
splot again. This plots the result out to a file. If you want to see plots on your
screen again, you need to set the terminal type to x11 again (for Unix’s X Windows
System), and then plot it again.
Chapter Twelve
Flow Control via Logic; Projectiles
In this chapter, we begin discussing some of the control structures that make pro-
gramming so interesting and that make your programs so intelligent. We will have
you write your own program to simulate projectile motion, a standard problem of
elementary physics. In Chap. 15, Differential Equations with Maple and Fortran;
Projectile Motion with Drag, we solve this same problem including air resistance.
We start with a review of the kinematic equations that may be scanned for those
familiar with it, and then go on to describe program design and control structures.
Figure 12.1 shows the trajectory of a projectile fired from a cannon at time t = 0,
with initial velocity V0 , at an angle θ relative to the horizon. The projectile remains
in the air for a total hang time of T , and hits the ground at a horizontal distance or
range x = R away from the origin.
Problem: write a program to simulate the motion of this projectile. Have it per-
form the following steps:
Figure 12.1 Left: The trajectory of a projectile fired with initial velocity V0 in the θ direction.
The nonparabolic curve includes air resistance. Right: The components of the initial
velocity V0 projected onto the x and y axes.
244 CHAPTER 12
If we ignore air resistance, a projectile has only the force of gravity acting on
it. This force causes the projectile to fall towards the center of the earth with a
constant acceleration g = 9.8m/s2 . The resulting solutions to the equations of
motion are
x(t) = V0x t, y(t) = V0y t − 12 gt2 . (12.1)
Here V0x and V0y are the horizontal and vertical components of the initial velocity,
and, as we see from Fig. 12.1,
V0x = V0 cos θ, V0y = V0 sin θ. (12.2)
Likewise, the x and y components of the velocity as functions of time are:
vx (t) = V0x , vy (t) = V0y − gt. (12.3)
Although the equations of motion yield x and y as functions of time, they do not
tell us the shape of the trajectory. For these simple equations it is easy to derive
that the shape is a parabola. We will, instead, determine the shape by plotting up
the solution, a simpler approach as the equations become more realistic.
Now that you are into the program construction business, it is a good idea to under-
stand not only the grammar of each instruction within the selected programming
language, but also the general structure of a well-built code. Books have been
written on program design, but then again, it is a good idea not to believe every-
thing you read! Yet, as seems to be true in much of life, it is helpful to follow the
rules until you know better. Once you have truly mastered a subject, you may then
make new rules. We view programming as a written art that blends elements of sci-
ence, mathematics, and computer science into a set of instructions which permits
a computer to accomplish a scientific goal. Good programs should:
Start
Start
Initialize g,V0,theta
Initialize
constants C alc R,T,step
Loop:tbetween
-T/2 and 3T/2
Basic
C alculations
T F
0< t< T?
T F
Loop over calc t< 0?
tim e x(t),y(t)
Notyet G rounded
Print fired
values
End
Add step
to t
End
Figure 12.2 A flow chart illustrating a possible program to compute projectile motion. On the left,
we show the very high-level basic components of the program, while on the right, we
show some of the details of the logic flow structures.
1. Store g , V0 , and θ
2. Calculate R and T
3. Calculate uniform step
4. Loop 100 times from −T /2 to 3T /2 by step
a. If t < 0, print “not yet fired”
b. If t > T , print “grounded”
c. If projectile is in the air, calculate and print x(t) and y(t)
d. increment t by step
5. End program
FLOW CONTROL VIA LOGIC; PROJECTILES 247
action 1
Logical
T C om parison F
action 2 ?
then else
actions A actions B
action 3
Figure 12.3 Left: Sequential or linear programming. Right: The if-then-else structure, one of several
structures used to write nonlinear program segments based on logical decisions.
For our projectile problem, we need to calculate the position for 100 differ-
ent times. The easiest way to do this is to have the same block of code repeated
100 times, with only the value of the time, t, changing. Such a structure is called a
loop. Like a clock, our example will run for a total time
3 −T
Ttotal = Tf − Ti = T − = 2T, (12.9)
2 2
in steps (ticks) of
2T T
= .
∆t = (12.10)
100 50
Whence, the time increases by ∆t for each repetition of the loop:
t = t + ∆t, (12.11)
with the program using its intelligence to decide what to compute and print de-
pending upon the particular value of t.
“think” logically about what it should do next. Making a program think logically is
done by including some symbolic logic in your program using logical or Boolean
variables. A Boolean variable is a Fortran data type that is either true or false.
Fortran represents these two values as .TRUE. and .FALSE., where the periods are
syntactically part of the name. A Boolean expression is a combination of variables
or expressions containing Boolean operators that when evaluated has a value that
is either true or false. When Boolean expressions are used with control structures
in your program, you are able to affect the order in which statements are executed.
Conditional operators act between two variables or expressions to form a new log-
ical expression that have .TRUE. or .FALSE. values. There are two types of condi-
tional operators, relational operators and logical operators. Relational operators
start with variables like Real::x and Real::y, and create a logical relationship
between them, for example, x > y, that is either .TRUE. or .FALSE., depending
on the numerical values of x and y . This logical relationship is stored in a logical
variable that has .TRUE. or .FALSE. values. Logical operators combine logical
variables to create more complex expressions, for example, (x>3) .AND. (y>4).
In each of the cases in the table, the result is either .TRUE. or .FALSE.. Thus,
even though x > y may be constructed from two Real’s, Fortran knows that it is
a logical variable because it has the relational operator > connecting them. Since
these relational operators are never used in assignment statements, there can be no
confusion. Indeed, this is the reason for introducing the double equal sign == as
a relational operator; x = y is an assignment statement, while x == y is a logical
variable.
The basic logic behind logical operators is that if we have a compound statement
constructed from two simpler statements, then the truth table
True False
true and true true and false
true or true false and false
true or false false or false
not false not true
determines the truth of the compound statement. The logical and is represented by
.AND., while .OR. represents the logical or. As a case in point, if x is true, then
x .OR. y is true regardless of y. Believe it or not, what makes the use of logi-
cal expressions so powerful is that it is possible to combined the different logical
expressions to describe the basis for all logical decision.
Exercise: If a is your age in years, w your weight in pounds, and h your height
in inches, construct Boolean expressions that will be true only when the following
statements are true:
1. you are old enough to obtain a driver’s license but too young to retire, ( (a >
16) & (a < 65)),
2. you are not a teenager,
3. you are either younger than 20 and less than 150 pounds, or you are older
than 40 and more than 6 feet,
4. you are neither old enough to vote, tall enough to hit your head on a five-foot
door frame, nor of the right weight to box in the 132–140 pound division. ♠
Control Structures
The left of Fig. 12.3 shows linear or sequential programming in which the
statements are executed in the order in which they are encountered, that is, from
250 CHAPTER 12
top to bottom. Control structures introduce the possibility that the execution of a
program may “split” into different paths depending on the values of certain vari-
ables, or may repeat certain sections a number of times. If the program does “split,”
then the program is no longer sequential.
In the Fortran if-then-else structure illustrated in Fig. 12.3, there are two sets
of possible actions; one set is executed if the condition is true and the other set
of actions is executed if the condition is false. The syntax requires that actions A
FLOW CONTROL VIA LOGIC; PROJECTILES 251
Loop fora
num berof
iterations
Testa
actions logical T
condition
actions,
am ong w hich
Add to counter F cause a change
to the logical
condition
Figure 12.4 Left: The Fortran Do-loop iteration. Right: The Fortran Do-while loop uses a general
test, in contrast to the Do-loop’s iteration count.
consist of a block of statements contained within the paired if and end if state-
ments. (When there is only one line of actions needed, however, the then and
end if statements are not required; the single action statement simply follows the
if logical condition on the same line). If actions B are included as an alternate
path of actions, they must be preceded with the word Else, which occurs on a
separate line of its own right prior to the list of actions B.
Fig. 12.4 illustrates the Fortran do-loop, probably the most popular looping
control structure. The do-loop is used to iterate, that is, repeat a section of code for
as long as some condition is true. This is useful for things like summing a series
or repeating a calculation until the error gets smaller than some fixed amount.
Because a counter is used to keep track of the number of iterations, it is also called
a counting loop. The statements that are repeatedly executed are bracketed by the
initial do statement and the closing end do statement.
after the keyword do, there is a variable (here, it is named var). It is used to count
the loop iterations; it can be referred to as the counter or the index variable. It is
followed by three fields separated by commas; these may be constants or variables
or arithmetic expressions, and they may be positive or negative. The first field, 1 in
this case, gives the initial value for the index variable. The second field, 100, gives
the final value for the index. The third field is the increment (or decrement, if it is
negative) for the index variable. For each iteration through the statements within
the loop, this value is added to the index variable. If the third field is missing, it
is assumed to be the positive value 1. The program will continue to repetitively
execute all the statements between do and end do until the index variable has
passed the final value. (Note that it is possible to start at 100, decrementing down
to 1 using a change value of -1).
do var = 100, 1, -1
252 CHAPTER 12
The iteration of a do-loop ends when the index (or counter) has passed the
final value. However, if the final condition is already met before any actions are
taken, then the statements inside the do-loop will never be executed. In either
case, if iteration has ended, or never executed, the program moves on to the first
executable statement after the end do statement.
These few ways to incorporate logic into programs are sufficient for the
problem at hand. Nevertheless, there are other commands that use a somewhat dif-
ferent approach in controlling the flow of your program, and we shall now discuss
some. Consider again the right of Fig. 12.3 illustrating the if-then-else structure.
We see in Table 12.1 that the else part of this control structure can have an if-then
structure following it to form an if-then-else-if structure. What’s more, there can
be any number of else if statements included to handle any number of special
cases. For the example in the table, we may add more else if statements to assign
grades of A+, A-, B+, etc..
The Do-While construct, shown on the right of Fig. 12.4, is similar to the do-
loop, and can serve a similar function. It repeats the statements between do while
and end do until the stated logical condition is .False.. The problem is that
without a fixed number of iterations, the loop may never end if the programmer has
made an error (infinite loop). It is literally up to the programmer to decide upon a
good test for a general condition, and to be certain that the general condition will
eventually be false so that the do while loop ends. However, it’s perfectly legal to
start with the logical condition .FALSE., in which case the loop is never executed.
It is common to have the counter index variable (var in our example, but
any variable name is acceptable) in a do loop be an integer, yet this is not required.
A real variable may be used, and it may be given a real initial value, termination
value, and increment value. You may also use either an integer or real variable in a
logical expression within a do while loop to determine if it is time to end the loop.
Be that as it may, be warned that round-off error makes it rather meaningless to
demand true equality between two floating-point numbers, or between a real and
an integer. For example, the following loop may never complete:
Real*8 :: x = 0.
do while (x /= 100.) Comparison may never be satisfied
x = x + 1. Increment
end do
To make sure that the loop will eventually stop, it is better to use the greater-than
and less-than operators <=, <, >=, > when comparing values as part of the logical
expression for a do while loop. The == and /= operators should be avoided, unless
there is a good reason to use them, such as when one wishes to determine if a
sequence has converged exactly to a given value.
Listing 12.1 Select.f90
FLOW CONTROL VIA LOGIC; PROJECTILES 253
1 ! S e l e c t . f 9 0 : D e m o n s t r a t e s t h e u s e o f S e l e c t Case c o n t r o l
structure
2 !−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
3 Program s e l e c t e x a m p l e
4 I m p l i c i t None
5 I n t e g e r : : wake , month
6 do month = 1 2 , 0 , −1 ! Loop f o r 13 months
7 p r i n t ∗ , ’Month is ’ , month ! P r i n t c u r r e n t month
8 s e l e c t c a s e ( month ) ! Choose c a s e v i a month
9 case (0) ! Here f o r month 0
10 p r i n t ∗ , ’ Last year’
11 case (1) ! Here f o r month 1
12 wake = 9
13 p r i n t ∗ , ’ January, wake =’ , wake
14 case (2) ! Here f o r month 2
15 wake = 7
16 p r i n t ∗ , ’ February, wake =’ , wake
17 case (4) ! Here f o r month 4
18 wake = 6
19 p r i n t ∗ , ’ April, wake =’ , wake
20 case default ! Here o t h e r c a s e s
21 wake = 8
22 end s e l e c t ! End S e l e c t
23 end do ! End Do
24 End Program s e l e c t e x a m p l e
Select Case
The Select Case structure is a neat way to execute different blocks of code depend-
ing upon the value of an integer or string variable. While this also can be accom-
plished with a series of if-then statements, as we said, Select Case is neater. As
an instance, consider the program Select.f90 in Lst. 12.1 that we use to program
our clock radio.
Compile and execute Select.f90 to see what the output looks like. Note
that the do-loop on line 6 counts down on the value of month from 12 to 0. Once
within the loop, there is a printout on line 7 that outputs the value of month. Next
within the do-loop is the select case on line 8 controlled by the value of month.
If month = 0, 1, 2, 4, execution will jump to the lines starting with case followed
by the corresponding value of month. If the value of month is not one of these
cases, then execution jumps to the case default on line 20. When execution
jumps to one of the listed cases, the value of the wakeup time variable wake is set
and printed. Once execution is completed within a case set of actions, the program
jumps to the next statement after the end select statement.
254 CHAPTER 12
1. Before you write your program, write down the equations to be solved. Hand
this in with your assignment, and refer to it while working on the program.
2. Create a flow chart, or some pseudocode, that shows the logic of your pro-
gram. Think of the logic flow as the path that converts the initial data to the
printed results. Hand this in, too.
3. Using the program limits.f90 from Chapter 10 as an initial program frame-
work, open it with your editor and then save it as projectile.f90, a new file
in the appropriate directory/folder for this week.
4. Modify projectile.f90 to compute and print T , H and R in a line before
the do-loop. (In other words, strip out the ”limit” tasks and insert the ”pro-
jectile” tasks).
5. Modify the do-loop so that it loops over i = 1 to 100.
6. Declare a variable t2 , the time variable that changes as the projectile flies
through the air. Within the do-loop, calculate t2 by the formula t2 = −T /2+
2 ∗ T ∗ (i/100.).
7. Inside the do-loop, use if statements to decide if the projectile has not yet
been fired, if it’s in the air, or if it has already hit the ground.
8. Have your program print “not yet fired” or “grounded” as appropriate. Oth-
erwise, print explicit values for x(t2 ) and y(t2 ).
9. Have your program make a plot of the particle trajectory. Your instructor may
have to help you determine the available plotting packages for your system.
1. Run your program for a variety of initial conditions, that is, for your choice
of different values for V0 and θ. Try some for which you know the expected
answer (like θ = 0 and θ = π/2).
2. Check that the range R increases as the initial velocity V0 increases in mag-
nitude, and as the elevation θ increases from 0 to π/4.
3. Check that the range R = 0, but that the hang time T = 0, for θ = 90o (this
corresponds to shooting the cannon straight up in the air, not the most clever
thing to do).
4. Check that the y values never exceed the maximum height H .
FLOW CONTROL VIA LOGIC; PROJECTILES 255
1. Take the program Limits.f90 from Chapter 10 that uses a do-loop to deter-
mine machine precision, and make a copy of it.
a. Compile and run Limits.f90 as a check that it is still running, and to get
some output for comparison.
b. Modify the do-loop so that the counter is a double precision variable. You
should get all the same results.
c. Change the do-loop to a do while loop that accomplishes the same task.
(Hint: while (1.0 + epsilon m /= 1.0) will repeat the loop until there
is no difference between the stored values of 1.0 + epsilon m and 1.0.)
d. Include an if-then construct in the loop so that the program prints only one
line of output, and that is for the first time that 1.0 + epsilon m = 1.0.
e. Include an if-then-else construct in the loop so that the program prints the
message “not there yet” if 1.0 + epsilon m /= 1.0, and then the usual
one and epsilon m the first time that 1.0 + epsilon m = 1.0.
2. If a is your age in years, w is your weight in pounds, and h is your height
in inches, construct Boolean expressions that will be true only when the fol-
lowing conditions are met:
a. you are old enough to obtain a driver’s license and you do not weigh 1000
pounds.
b. you are not a teenager.
c. you are either younger than 20 and less than 150 pounds, or older than 40
and greater than 6 feet.
d. you are neither old enough to vote, tall enough to hit your head on a
five-foot door frame, nor the right weight to box in the 132–140 pound
division.
3. Let: A be your age, Y the number of years you have been in college, and D
the number of dollars you have in the bank. Construct Boolean expressions
that will be true when the following conditions are met:
a. you are a millionaire but you are not a senior.
b. you are either too young to vote or you are not a freshman.
c. you are either younger than 20 and broke, or older than 90 and have more
than $100,000.
d. you are 16 years old and your number of years in college is greater than
the number of dollars you have in the bank.
256 CHAPTER 12
4. Iteration refers to the repetition of the same lines of code until a condition
is satisfied. To illustrate, in Lst. 12.2 is a code that computes 1/1 − x for
x2 < 1 via its infinite series expansion
1
= 1 + x + x2 + x3 + x4 + · · · . (12.12)
1−x
The summation of terms is repeated 1000 times or until the new terms have
an insignificant effect on the sum (xn < 10−7 sum).
The Fortran programmer is blessed with a variety of powerful and high-level I/O
statements and formats to use. “High-level” here means that you do not have to
worry about all the details, while “format” means that Fortran will produce a form
for your output so that it looks just the way you want, including alignment. Here
in Lst. 13.1 is a sample code that contains a number of I/O statements:
The simplest input and output in Fortran is writing to the computer screen and
reading from the keyboard. This is the default, and is thus called standard I/O. For
example, on lines 8 and 11 of FortranIO.f90 we have
The write command is used for output. It takes two arguments in parenthesis, the
first indicating where to write (what device), and the second indicating what format
to use when writing. Both these commands above do the simplest thing, which is
to use an asterisk * in place of an explicit argument. The first * indicates that no
UNIT is being specified on which to write, so Fortran will use the default output
device (the computer screen). The second * indicates that no format statement is
being specified (free format), and so Fortran will decide what format to use based
on the types and values of the variables being output.
Here, two variables previously declared as real are read in, with the variable
names separated by a comma. Notice that since we have used the default * again,
we do not specify things like where the decimal point occurs in the input or how
many spaces are used to separate the values on input. In fact, the two values to be
input can be on one line separated by spaces, or commas, or tabs, or even on sepa-
rate lines. The default input device is the computer keyboard, and Fortran figures
out the format on its own from the data it finds.
FORTRAN INPUT AND OUTPUT 259
When you want to specify the exact format of input or output, then the second *
in the read and write statements above should be replaced by a numbered label.
This label is included as part of the format statement in your program, making it
possible for any I/O statements in the program to reference and use it. The internal
part of the Format statement defines your desired I/O layout:
Here the write statements on lines 15 and 16 output identical variables but with
different format statements (as indicated by the labels 100 and 200). The format
statements and their labels are found on lines 22 and 25, but may be placed any-
where in the program since they are just used for reference (not executable action
commands). To keep format statements out of the way of the program’s logical
flow, they are often placed at the end of the code, right before the End Program
statement. We see that format statement 100 produces verbose output, while 200
contains minimal output, but with variables in a slightly different output format.
These format types take modifiers to control the total number of digits (width) used
for the I/O, how many digits appear after the decimal point, and whether some field
is repeated:
260 CHAPTER 13
Example Meaning
A8 8 character alphnumeric
E12.3 exponential of width 12 digits, with 3 after decimal
F12.6 fixed point of width 12 with 6 after decimal
G12.3 general of width 12 digits, with 3 after decimal
I4 Integer of width 4 digits
2X 2 blank spaces
3G12.3 3 general fields of width 12 with 3 digits after the decimal
So now if we go back and look at 100 format on line 22, we see a bunch
of format instructions separated by commas. The slash / tells the computer to
skip a line, ’Example 1:’ and ’Hello,’ are strings that get output exactly as
entered. Accordingly, T10 causes the line to tab to column 10 and A8 prints out
an alphanumeric variable (your name) using 8 places. The / causes the output to
skip to another new line, which is then indented by 5 spaces as indicated by the 5X.
The long string enclosed in quotes is printed on that new line. After that, F12.6
outputs a real value in a field 12 places wide, with 6 digits after the decimal point.
Then there is another string followed by two real values printed as 2E12.3, that
is, as 12-character wide fields with 3 digits after the decimal points, and with an
exponent. Notice how the formatting of these same variables gets changed when
200 Format is used!
Fortran has many options for file I/O that give you the flexibility needed for var-
ious tasks. However, since file I/O deals with the hardware and operating system
of your local computer, it is important to check out various versions of these com-
mands to see which ones work best on your local system.
File I/O can be either free-form or formatted (the second argument to the
read and write commands). In order to write to a file or read from a file, you
must specify a UNIT number associated with the file (this goes in place of the first
* in the I/O commands parentheses). In FortranIO.f90, we associated UNIT 1
with the filename data.dat, in the same directory as the executing program, via
17 open(1, FILE=’data.dat’, STATUS=’REPLACE’)
where REPLACE indicates that it is OK to replace an older version of the file. This
statement may appear anywhere in your program, although we prefer to put OPEN
statements at the top of the program, so they do not get in the way of the logic and
so it is easy to see which UNITs and filenames are being used. The actual writing
to the file is done with the write command:
18 write(1, 100) name, r, area
which uses the same Format statement that we used for screen output. You may
FORTRAN INPUT AND OUTPUT 261
construct any format to meet your needs, but you do not want to spend a lot of
time engineering a beautiful output for a one-time run. Since format statements
are referenced by their numerical labels, several I/O statements can use the same
format.
This releases resources for other tasks, as well as protects the file you have written
in case of crashes.
Chapter Fourteen
Numerical Integration and Nested Loops;
Energy Usage
In Chapter 6 we modeled the electrical power use P (t) over time by some simple
functions. For example,
t πt
Model 3: P3 (t) = 4 + + 12 sin 2 + e− sin 2πt , (14.1)
365 91
where the power is in GW (109 watts) and the time t is in days (the top curve in
Figure 14.1). Your problem is to determine the total energy used over 1000 days
(approximately three years) by evaluating the integral
100
E(100) = P3 (t)dt, (14.2)
0
The highly oscillatory patterns in Figure 14.1 make (14.2) a challenging in-
tegral to evaluate (as demonstrated by the quite different answers obtain by casual
application of Maple and Mathematica). Consequently, we want you to compare
the results from the two different integration rules (trapezoid and Simpson), and to
see if the value for the integral converges as we improve the approximations. There
are fancier integration rules, but we leave those to the references [Press 94, CP 05].
NUMERICAL INTEGRATION AND NESTED LOOPS; ENERGY USAGE 263
22
20
18
16
P 14
o
w
12
e
r
10
0
-0.2 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0 3.2 3.4 3.6 3.8 4.0
2
t x10
Figure 14.1 The three models of power consumption. Time t is in 100 days and power is in Gi-
gaWatts.
f(xi+1)
h h h
Figure 14.2 Left: Straight-line sections used for the trapezoid rule. An individual trapezoid with
area h2 [f (xi ) + f (xi+1 )] is highlighted. Right: Parabolas used in Simpson’s rule (a
single parabola is fit to each pair of consecutive intervals.
Here the xi s are integration points and the wi s are integration weights. This is a
handy way to program up an integration algorithm, since we need only change the
specific values for wi (and maybe xi ) for different rules.
Trapezoid Rule
The trapezoid rule is the simplest integration algorithm. As shown on the left of
Figure 14.2, we divide the area under f (x) into a series of columns each of width
h, and form trapezoids by approximating the integrand f (x) by a straight line con-
necting the endpoints of each interval. In this case the integral is approximately
equal to the sum of the areas of the columns.1 The approximation gets progres-
sively better as the widths of the trapezoids are made progressively smaller, and
the integrand is better approximated by a straight line within the interval.
1 An alternative way of viewing the trapezoid rule is as forming a series of rectangles with horizontal tops, the
height of each rectangle being (fi + fi+1 )/2. If we use fi as the height, then we have a version of the trapezoid
rule known as Euler’s rule.
NUMERICAL INTEGRATION AND NESTED LOOPS; ENERGY USAGE 265
We first deduce an equation that gives the x value for each integration point.
If we evaluate the function at N points, then we have N − 1 columns (it takes two
points to define one column) covering the range b–a. It follows then that the width
of each interval in Figure 14.2 is
b−a
h= , (14.5)
N −1
and the discrete x values. They are thus enumerated with the subscript i:
xi = a + (i − 1)h, i = 1, N. (14.6)
To calculate the area of each trapezoid in Figure 14.2, we look at the isolated
column i. The area of this one trapezoid is its width times its average height:
xi +h
f (x)dx 1
2 h[f (xi ) + f (xi+1 )], (14.7)
xi
which is the same area one gets if each column is considered as a rectangle with
the top passing through the midpoint of the slanted top. The total area in the
integration region from a to b is the sum of the areas of all the columns:
b
h h
f (x)dx f (x1 ) + hf (x2 ) + . . . hf (xN −1 ) + f (xN ). (14.8)
a 2 2
Observe that because each internal point gets counted twice, it gets weighted by h,
whereas the endpoints get counted just once and so are weighted by only h/2. In
terms of the notation of our standard integration rule (14.4), the points and weights
for the trapezoid rule are:
h h
xi = a + (i − 1)h, wi = , h, . . . , h, , i = 1, N. (14.9)
2 2
18 w = h
19 end i f
20 sum = sum + w∗ t ∗∗2
21 end do
22 w r i t e ( ∗ , ∗ ) ’The sum is ’ , sum
23 End Program t r a p
Our approximation to the area under a curve as the sum of columns with straight
or rounded tops should get more accurate as we increase the number of columns
N-1. However, if we make N too large, then round-off error accumulates to the
point where increasing N further leads to a less accurate answer. To get a feel for
the level of accuracy of our numerical integration technique, we want to increase
N and determine in what decimal place the answer changes. If the answer changes
in, say, the fourth decimal place, then we would expect the answer to be good to at
least three places.
Modify a copy of Trap.f90 so that it prints out the value of the integral and
the value for eight values in the range 25 ≤ N ≤ 200. Rather than running the
NUMERICAL INTEGRATION AND NESTED LOOPS; ENERGY USAGE 267
program eight times (increasing the value of N for each run), make the computer
do this for you; modify the program so that it loops over eight values of N:
1 do N = 2 5 , 2 0 0 , 25 ! Outer loop i n c r e a s e s N
2 ···
3 do i = 1 , N, 1 ! I n n e r l o o p sums o v e r c o l u m n s
4 ···
5 end do
6 end do
The procedure outlined in this code fragment uses nested loops, that is, one do-loop
contained within another do-loop. Study how for each value of the total number
of points N, everything within the outer loop gets repeated, and this includes the
inner-loop’s i-summation over the areas of each column. Consequently, it is im-
portant to check that the program re-initializes the value of variables used in the
inner loop, in particular, h and sum. If you look at line 11 of Trap.f90, you will
notice that the column width h varies with the number of integration points used
N. Because of that, we need to begin the new outer do-loop before line 11. Next,
notice that the summation over column areas is ended by the end do on line 21.
As a consequence, we need to end the outer loop incrementing N after line 21.
Simpson’s rule for integration will also give us an algorithm of the form (14.4),
but with different weights than the trapezoid rule. The integration range is again
divided into equal-width columns, with the points given by (14.6). Now, as we
show on the right of Figure 14.2, we approximate f (x) at the top of every two
columns as a parabola:
This is a better than using a straight line. With each parabola containing three
unknown parameters, α, β , and γ , we need three values of f (x) to determine them.
We do that by having one parabola pass through the tops of two adjacent columns.
Whereas the determination of these constants requires some algebra, the idea is
simple. What is important is that because parabolas are being fit to successive
pairs of columns, Simpson’s rule requires an odd number of integration points N
so that there will be an even number of columns.
268 CHAPTER 14
Figure 14.3 Energy consumption as a function of time for model 1 computed with Maple.
1. Explain succinctly the difference between the trapezoid and Simpson rules.
2. Is a parabola or a straight line a better approximation for a function?
1. You are given nonrepeated weights of 1, 2, 4, 8, 16, and 32 kg. Your boss
claims that you should be able to use these six weights to weigh any rice sack
weighing an integer number of kilograms between 1 and 63. For instance,
270 CHAPTER 14
In this chapter we solve for projectile motion with drag by solving simultane-
ous, second-order ordinary differential equations (ODEs) using both Fortran and
Maple. This is a fairly realistic problem that is often missing from undergraduate
education, but whose solution looks familiar to students. The ODE solver used
in our Fortran program is simple, useful for other problems as well, and provides
some insight into numerical differentiation. The Maple solution, however, gets to
be surprisingly involved at times due to the equations being both second-order and
coupled, and having a solution that cannot be plotted simply. A comparison of the
two approaches is quite educational. We have marked this chapter as optional, in
part because there are no new materials that are used elsewhere, and in part be-
cause some students may not yet be familiar with differential equations. However
the subject matter is important for many fields, and it does provide a good balance
to the solution of a partial differential equation studied in Chapter 20.
The basic physics behind this problem is Newton’s second law of motion, which
relates force, mass, and acceleration:
d2 x(t)
F = ma = m , (15.1)
dt2
where the bold symbols indicate vector quantities. This is a second-order ordinary
differential equation. A differential equation because it contains a derivative; an
ordinary derivative because there is only one independent variable and so no partial
derivatives (no ∂ ), the time t; and second-order because it is a second derivative.
Because the equation of motion involves vectors, there are separate differential
equations for the x and y components of each vector:
d2 x 1 d2 y 1
2
= Fxf , 2
= (Fyf − mg), (15.2)
dt m dt m
where we have divided through by the mass, switched the derivative to the LHS
(a standard form), and substituted components for the frictional force Ff and the
gravitational force.
The force of friction Ff is not a basic force of nature with a definite form for
all situations. Indeed, it is just an approximate description of the physics of viscous
flow, with no one expression being accurate for all velocities. We know it always
opposes motion, which means it is in a direction opposite to that of the velocity.
The simplest model, and the one often studied in texts [M&T 88], assumes that the
force of air resistance is proportional to some power n of the projectile’s speed:
v
Ff = −k m |v|n . (15.3)
|vx |
The v/|v| term ensures that the frictional force changes direction, to keep oppos-
ing motion, when the velocity changes sign. If n = 1, or any odd power, then we
may have the frictional force proportional to −v n and get the correct sign. How-
ever, if n is even, then we have to use these absolute values to ensure the correct
sign. Though a frictional force proportional to a power of the velocity is a more
accurate description than a constant force, it is still a simplification. Indeed, phys-
ical measurements indicate the power n appears to change with velocity, and so
the most accurate model would be a numerical one that uses the empirical velocity
dependence n(v).
form:1
d2 x vx d2 y vy
= −k vxn , = −g − k vyn . (15.4)
dt 2 |vx | dt 2 |vy |
We shall consider three values for n, each of which represents a different model for
the air resistance: (1) n = 1 for low velocities; (2) n = 32 , for medium velocities;
and (3) n = 2 for high velocities. For comparison, we will compare these solutions
with air resistance to the analytic results for the frictionless case:
1
x(t) = v0,x t, y(t) = v0,y t − gt2 , (15.5)
2
vx (t) = vx,0 , vy (t) = vy,0 − gt. (15.6)
When air resistance is present, the force on the projectile depends upon the value
of the velocity, which means that the acceleration is not constant. This makes an
analytic solution to the differential equation difficult, but it is not a challenge to
a numerical solution. The trick is to figure out an approximation that takes the
solution at the initial time 0 and advances it a small amount ∆t. Because ∆t is
small, it is not hard to find an approximate solution. One then takes the solution
so found and uses it as the new “initial conditions” to provide the solution at time
2∆t. The process is continued until the solution at the desired time is found. With
[x(t = 0), y(t = 0)] and [vx (t = 0), vy (t = 0)] as the initial conditions, we have
1 For more realistic models used for friction, these equations may become coupled, e.g., because (V 2 ) =
x
(Vx )2 . For simplicity, we ignore the coupling of the equations, although the technique for the numerical solution
remains unchanged.
274 CHAPTER 15
all the information we need to start the solution and will keep it going as long as
we like.
Here ax (t) is the variable acceleration at time t. Likewise, there are similar equa-
tions for y and vy . To make the algorithm simpler, we assume that ∆t is so small
that the terms quadratic in ∆t are negligible with respect to the terms linear in ∆t:
This means that as long as we keep the time step ∆t small, we may ignore the
acceleration term in (15.9). The acceleration still affects the solution via (15.10),
but it does so by changing the velocity, which, in turn, changes the position. For
this simple method to work, we must choose small values of ∆t. As a rule of
thumb, if the physical system under study has a characteristic time or period of
T , then we would start with ∆t T /100 and then see the effect of decreasing
it. A higher-order technique might require fewer steps but use more complicated
formulas.
d2 x d2 y
= −kvx , = −g − kvy . (15.11)
dt2 dt2
The terms on the right-hand sides of these equations are the accelerations we need
for the algorithm. The algorithm starts with the given initial position (the origin)
and the velocities vx,0 , vy,0 , and then steps through many time steps. We label the
time steps with the index i = 1 . . . N . For each time step, the position and velocity
will be updated according to the algorithm:
The acceleration due to gravity enters only for the y component of velocity, since
gravity acts only in the y direction. And as we have said, the forces act by directly
changing the velocity, but change the position only indirectly through the changes
in velocity.
DIFFERENTIAL EQUATIONS WITH MAPLE AND FORTRAN; PROJECTILE MOTION WITH DRAG*275
Implementation: ProjectileAir.f90
1. a main program that sets initial parameters and directs the computation; and
2. a buildPlot subroutine that solves the equations of motion analytically and
numerically and plots each result using the Dislin package.
Examine how the Dislin package is imported with the Use dislin command on
line 4. On lines 54 and 55 we set the values for the constants, and then initialize the
computation by calling buildPlot on line 56. The calculation does the frictionless
and with-friction computations simultaneously, with the analytic calculation on
lines 21 and 22, and the numeric calculations on lines 27-28. The Dislin plotting
routines are called on lines 32-49, and should give a plot looking like the trajectory
in Figure 12.1.
1. Compile and run ProjectileAir.f90 and check that you get a plot similar
to that in Figure 12.1. If your program is not plotting, and your system has
Dislin loaded, then you may need to review some of the materials on using
Dislin in Chapter 11, “Visualization with Fortran.”
2. In general, it is not be possible to compare analytic and numerical results to
realistic problems, because analytic expressions do not exist. However, we
do know the analytic expressions (15.5) for the frictionless case, and we may
turn friction off in our numerical algorithm and then compare the two. This is
not a guarantee that we have handled friction correctly, yet it is a guarantee
that we have something wrong if the comparison fails. Add some lines of
code to ProjectileAir.f90 that calls the buildPlot procedure a second
time, this time with the friction coefficient k = 0.
3. We have deliberately given you a program in which the total number of time
steps N is rather small, and, inversely, the time step dt is rather large. Conse-
quently, the results from the given program will be of low precision. Repeat
the calculation with ever-increasing values for N, until you cannot tell the
difference on the plot between the numeric and the analytic results for fric-
tionless flight.
4. Once the results look good to you, determine the level of precision of the cal-
culation by comparing the actual numbers for the analytic and the numerical
calculations. If necessary, increase N until the relative difference is less than
1%. Use this value of N for future computations.
5. Add lines to the program so that it prints out and plots up the components of
the velocity as a function of time.
6. Study your plots of the velocity components versus time and draw a line on
276 CHAPTER 15
In developing the Euler integration algorithm (15.10), we ignored the direct affect
of the acceleration on the position, as is present in (15.9). We now want to modify
the algorithm so that it includes the acceleration term directly in the solution for
x(t + ∆t). An approach that is nearly as simple as Euler yet appears to work very
well is called the Verlet algorithm. It uses second-order terms for xn , but only
first-order ones for vn :
1 1
xn+1 = xn +vn ∆t+ an (∆t)2 , vn+1 = vn + (an+1 +an )∆t. (15.14)
2 2
We see that while the algorithm for the velocity is only first-order in ∆t, it makes
up for this somewhat by using the average acceleration over the time interval and
not just its value at the beginning of the interval. The only problem with this
method is that it is not fully self-contained; to determine vn+1 you first have to use
the Euler method to obtain an+1 .
Exercise: Implement the Verlet algorithm and compare the number of steps
needed to obtain the three-place precision with both the Euler and Verlet meth-
ods. (The better algorithm should use fewer steps.) ♠
278 CHAPTER 15
Maple is competent at finding solutions to most any differential equation that you
give it. It many cases it can find an analytic solution with no help from you, while
in other cases you may have to give it some hints based on your understanding of
the mathematics of your equation. If all else fails, or if all you want is a plot of the
solution, ask Maple to solve the differential equation numerically.
Warning: Although the commands we have given here appear to work properly
on various versions of Maple, we have noted that the order in which Maple returns
the solution changes with different versions. To cite an instance, [y(t), x(t)] in one
case and [x(t), y(t)] in another. Consequently, you may have to reverse the order
of some of the arguments in the plotting commands given below.
d
Vy := y(t)
dt
> diff eq := diff(Vy, t) = - g; diff eq := diff(diff(y(t),t),t) = - g;
> diff eq := diff(y(t), t, t) = - g; diff eq := diff(y(t), t$2) = - g;
> diff eq := diff(y(t), t$2) + g; # Multiple forms, same result
d2
diff eq := 2 y(t) = −g
dt
Two simpler ways of entering the same differential equation is with the D operator:
> diff eq2 := (D2)(y)(t) = -g; diff eq2 := D(D(y))(t) = -g; # With D
This looks great and is the right answer, yet we have had to be careful. First,
even if the differential equation is entered with diff, the initial conditions must
be entered with the D. Second, because we have a second-order ODE, there are
two initial conditions (displacement and velocity), and we group them as the set
init con, with items separated by a comma, but order irrelevant.
> soltn := dsolve( {diff eq2, init con}, y(t) ); # Solve ODE with initial conditions
> diff( soltn, t ); diff( soltn, t, t ); # 1st, 2nd derivatives
1
soltn := y(t) = − g t2 + Vyo t
2
d d2
y(t) = −g t + Vyo y(t) = −g
dt dt2
In order to plot the solution, all parameters must be assigned numerical values. In
addition, since the expression for the solution is an equation with y(t) on the LHS,
we must use Maple’s rhs() function to extract the RHS. We extract the velocity
and acceleration from the solutions by taking time derivatives:
> g := 9.8; Vyo := 20;
g := 9.8 Vyo := 20
> plot( rhs(soltn), t = 0..4.2, title = ‘y(t) vs t‘ ); # y(t), left plot
> plot( rhs(diff(soltn, t)), t = 0..5, title = ‘v(t) vs t‘ ); # Vy(t), right plot
> plot( rhs(diff(soltn, t, t) ), t = 0..5, title = ‘a(t) vs t‘ ); # a, right plot
–10 –10
5
–20
–10.5
0 1 2 3 4
t
0 1 2 3 4 5
t
Check over how the velocity starts off positive and then gets more and more nega-
tive, and that the acceleration is constant at g = 9.8 in the negative y direction.
Maple has the DEplot command that both solves a differential equation and plots
up the solutions. As before, while our solution was analytic and contained initial
conditions as parameters, to plot a graph we need to have a completely numeric
answer, and so we must assign values to all parameters. The value of the parameter
DIFFERENTIAL EQUATIONS WITH MAPLE AND FORTRAN; PROJECTILE MOTION WITH DRAG*281
g is assigned first, and the values of the initial conditions are placed within the
DEplot command:
20
15
y(t)
10
0 1 3
t
Observe how we include the initial conditions as a list for the third argument.
System of ODEs
When the systems in an environment depend on each other, we usually have si-
multaneous differential equations to solve. As a case in point, in our projectile
problem we have simultaneous equations for the x and y motions (we solved only
for the y motion so far). The same commands and procedures are used for a set of
equations as for a single equation. The additional step is to define the variable that
gave the equation to solve to now be a set of equations (“set” because the order
does not matter):
> dsolve( {diff eqs}, {y(t), x(t)} ); # Maple will generate integration constants
g t2
{y(t) = − + C3 t + C4 x(t) = C1 t + C2 }
2
We see that Maple does find the expected forms of the solution (15.16), with the
constants still to be determined. As before, we include the initial conditions into
the set of equations we give as the first argument to dsolve, this time with four
conditions:
282 CHAPTER 15
1
{y(t) = − g t2 + Vyo t, x(t) = Vxo t}
2
Indeed, we get the familiar solutions as a set within braces. If we want numeric
values for x and y , we must assign numeric values to the parameters.
C1 e(−k t) + g t − C2 k
{x(t) = C3 + C4 e(−k t) , y(t) = − }
k
We see that Maple returns a set of solutions with four constants. Good, we are on
our way. Rather than solving for the constants in terms of the initial conditions, we
define a set of initial conditions, and include them as a second argument to dsolve.
DIFFERENTIAL EQUATIONS WITH MAPLE AND FORTRAN; PROJECTILE MOTION WITH DRAG*283
We specify initial velocities as the initial values for the first derivatives, and use
the D() operator (diff does not work for initial conditions):
This appears to be the analytic solution we want, and it is worth investigating its
properties. Yet before we do that, we need to see if the velocities exhibit reasonable
behaviors, that is, if they attain a terminal speed and then stop increasing. We do
that by taking the derivative of our solution:
√ √
Vox := 11 2 Voy := 11 2 g := 9.8 k := 1.0
We see our solution in its numeric form, as a set with a comma separating the
equation for x(t) from that of y(t). Though they make the equations hard to read,
the zeros after the decimal point indicate the Maple’s level of precision for this
floating-point calculation (it became floating point when we made g and k floating-
point numbers).
284 CHAPTER 15
To plot up the results we need to extract the RHSs of both equations. For a simple
expression this was done with the rhs command. Now that soltn is a set of
equations, we need to indicate which equation it is in the set that we want the RHS
of. For this purpose Maple has the op command to extract operands (pieces) from
an expression. Consequently, rhs(x) is equivalent to op(2, x). First we test that
we know how to extract each equation, and then we take RHSs:
√ √
x(t) = 11.000 2 − 11.0000
2 e(−1.0 t)
√ √
y(t) = −1.00000 (9.8 + 11.0 2) e(−1.0 t) − 9.800000 t + 9.80000+11.0000 2
Now that we have a way to separate out each equation, we take the RHSs of each:
√ √
11.00000000 2 − 11.00000000 2 e(−1.0 t)
√ √
−1.00000 (9.8 + 11.0 2) e(−1.0 t) − 9.80000 t + 9.80000+11.0000 2
At last we have what we need to make our plots. We plot the position and velocity
(time derivative) by entering lists (in square brackets) as the first argument to the
plot command (a list because order matters for the plot):
15 15
10 10
5
5
0 1 2 3
0 1 2 3 t
t –5
–5
x(t) Vx(t)
y(t) Vy(t)
These plots show an initial linear increase of x(t) with time t, as expected for con-
stant velocity. However, as time increases, the action of the frictional force in the
x direction is to keep decreasing Vx until, for large time, Vx vanishes (except that
the ground gets in the way). Then the x motion ceases and x remains constant.
DIFFERENTIAL EQUATIONS WITH MAPLE AND FORTRAN; PROJECTILE MOTION WITH DRAG*285
In turn, y(t) shows a parabolic dependence on time initially, as expected for uni-
form acceleration, but only a linear increase for later times. The linear increase
of y with time indicates that vy has attained its terminal value as the drag force
exactly balances that of gravity. As expected from the analytic expressions, and
our discussion in the previous paragraph, we see that Vx approaches zero and Vy
approaches a constant value for large times (or would if the ground did not get in
the way).
The usual plot of a trajectory is a plot of y(t) as the ordinate versus x(t) as
the abscissa. As you will recall from our discussion of visualization in Chapter 4,
this type of plot is known as a parametric plot. A parametric plot is constructed
by moving the time limits into the list that is used as the first argument (the list
contains {x(t), y(t)} and the range of t):
> plot([rhs(op(1, soltn)), rhs(op(2, soltn)), t = 0..3 ], labels=[‘x(t)‘, ‘y(t)‘]);
4
y(t)
2
0 2 4 6 8 10 12 14
x(t)
–2
–4
We see a trajectory that is much distorted from the symmetric parabola that occurs
for frictionless flight, and looks similar to that computed with Fortran and shown
in Figure 12.1. In fact, this looks very much like the type of trajectory seen for a
golf ball or a baseball in which the ball rises at first and then appears to “drop out
of the sky” at the end of its trajectory.
We now want to determine if we can solve for the range R and hang time T for the
general projectile-with-friction problem. We start by again placing our solution in
symbolic form:
The range R corresponds to the value of x at which the height y = 0 (in addition
to the initial firing). We start our solution for the hang time T at which y(T ) = 0
by extracting x(t) and y(t) :
This just tells us the initial time, which we know, but is not what we want. Instead,
let us be more specific and ask for the time at which the height y just becomes
negative, namely, when it just hits the ground:
> solve(Y < 0, t);
We see that Maple returns nothing. It apparently has given up. If we look at the
expression for y(t), we see that it contains the time t in both an exponential and a
linear term. Apparently, setting Y = 0 leads to a transcendental equation that has
no analytic solution. The only solution, then, is obtained numerically, and we shall
do that with Java (although Maple will also work).
Modify the analysis performed for a drag force proportional to the first power of
the velocity so that it is appropriate for a force proportional to the square of the
velocity. Maple should be able to solve this analytically as well, and you should be
able to follow all of the steps we have for Model 1. Note: since v 2 does not change
sign when v does, you will need to add a v/|v| factor in the frictional force for the
y motion (it is not needed for the x motion because the x component of velocity is
always positive).
DIFFERENTIAL EQUATIONS WITH MAPLE AND FORTRAN; PROJECTILE MOTION WITH DRAG*287
We now want to solve the projectile-with-friction problem for a drag force propor-
tional to the 3/2 power of the velocity. The equations we need to solve are:
d2 x d2 y vy
= −k vx3/2 , = −g − k vy3/2 . (15.18)
dt2 dt 2 |vy |
The acute reader might notice that there is a problem with this last equation;
namely, if vy is negative, then the square root operation, which is part of rais-
ing vy to the 3/2 power, will return an imaginary number. This is clearly not what
we want. We solve that problem by taking the absolute value of vy before raising
it to a power: 3/2
d2 y dy vy
= −g − k . (15.19)
dt 2 dt |vy |
This expression is simpler to read and easier to enter into Maple. (An alterna-
tive approach would be to use the sign function, which extracts the sign of its
argument, to keep track of the sign of the velocity and adjust the frictional force
appropriately.)
We set about solving this model just as we did the problem with drag pro-
portional to the first power. First we define the set of differential equations and
give it the name diff eqs:
This looks fine, and so we go on to look for a general solution by first entering the
initial conditions:
analytic solution with this level of complexity is not illuminating, and probably
not even good for computation (the numerous subtractions and evaluations of the
multivalued tan−1 and ln functions is error-prone).
d
y(t) = 5.458067069137789, y(t) = 6.980924610035919]
dt
d
Soltn := [t = 0.5, x(t) = 6.49693016854386762, x(t) = 10.8534715090049546,
dt
d
y(t) = 5.45806706913778950, y(t) = 6.98092461003591946]
dt
> op(1, Soltn); op(2, Soltn); op(3, Soltn); op(4, Soltn); op(5, Soltn);
d
t = 0.5 x(t) = 6.49693016854386762 x(t) = 10.8534715090049546
dt
d
y(t) = 5.45806706913778950 y(t) = 6.98092461003591946
dt
In order to plot the solutions, we pick off just the RHS of these expressions:
> rhs(op(2, Soltn)); rhs(op(4, Soltn)); # Extract RHS of x(t), y(t) in Soltn
6.49693016854386762 5.45806706913778950
It seems like we should now be able to plot up the solution. However, Maple’s
plot command accepts expressions and functions as input but not procedures.
(We discussed Maple programming and procedures in Chapter 8.) This means we
cannot have plot call our procedure and plot it. It is not much work to define a
function from a procedure and then to plot up the function; essentially, you just
define an arrow function as a call to your procedure. Here we do that for the x and
y positions and velocities:
> plot([X,Y], 0..3, title = "x(t) & y(t), 3/2-power friction"); # Plot 1
> plot([Vx,Vy], 0..3, title = "Vx(t) & Vy(t), 3/2-power friction"); # Plot 2
> plot([X,Y,0..3], title = "y(t) vs x(t) for 3/2-power friction"); # Plot 3
290 CHAPTER 15
(x, y)
y .N
.O
H .
Figure 15.1 Left: The gravitational force on a planet a distance r from the sun. The x and y
components of the force are indicated. Right: Output from the applet PlanetRHL
showing the precession of a planet’s orbit when the gravitational force ∝ 1/r4 .
x(t) & y(t), 3/2-power friction Vx(t) & Vy(t), 3/2-power friction y(t) vs x(t) for 3/2-power friction
20 15
6
15 10
4
10 5
2
We see similar results to Model 1, only now with an even more drastic “drop out
of the sky effect” at the end of the trajectory.
Implementation: Planet.java*
On the Java section of the CD you will find the applet Planet. Although this is
Java based, you can run the applet with just a browser. We suggest that you run the
class file to see how the solution behaves. To keep the calculation simple without
changing the physics, assume that the units we use are such that GM = 1, and
that the initial conditions are [Feyn 63]:
x(0) = 0.5, y(0) = 0, vx (0) = 0.0, vy (0) = 1.63. (15.24)
1. Use Maple, Fortran, or both to find the solution of the differential equation
dn(t)
= −λn(t), (15.25)
dt
with the initial condition n(0) = 100. Plot up the answer for λ = 0.3.
2. In Chapter 16 you will encounter an RLC electrical circuit and the differ-
ential equation describing it. We consider here the same circuit without a
capacitor and described by the differential equation
dI
V (t) = RI + L . (15.26)
dt
Solve this equation for the current in the circuit for the same values of R and
L as in the problem, and for a constant V (t) (same magnitude as in problem).
Plot your solution.
3. Consider exponential growth starting with an initial population N (0) = 2.
a. Solve the equation describing exponential growth
dN (t)
= λN (t). (15.27)
dt
Assign the integration constants to correspond to n(0) = 100, and λ =
0.3, and plot up the solution.
b. Solve for exponential growth with a modulated growth parameter
dy(t) 10000 − N (t)
=λ × N (t). (15.28)
dt 10000
This is the differential-equation version of the logistics map studied in
Chapter 19, “Discrete Math, Arrays as Bins.” The term in square brackets
is insignificant for small N (t).
4. Solve for and plot up the solution to the differential equation
dy(x)
= sin(xy), (15.29)
dx
with initial condition y(0) = 1.
a. Verify that Maple cannot find an analytic solution to this equation.
b. Have Maple find a numerical solution to this equation.
5. Solve for and plot up the solution to the differential equation
d2 y(x)
= −y(x)3 , (15.30)
dx2
subject to the initial conditions y(0) = 1, y (0) = 0. Hint: If Maple cannot
find an analytic solution, you may need to try a numerical one.
Chapter Sixteen
Object-Oriented Programming, Abstract Data;
Complex Currents*
Note to the instructor: As an alternative to the full version of this chapter, you may
skip the study of the RLC circuit and just focus on the mathematics of complex
numbers and their representation in terms of objects. And even with that, you may
defer the use of nonstatic (object-oriented) methods to a later time.
We are given the circuit shown on the left of Figure 16.1 containing a resistor of
resistance R, an inductor of inductance L, and a capacitor of capacitance C . All
three elements are connected in series to an alternating voltage source
V (t) = V0 cos ωt. (16.1)
Problem: Determine the magnitude and time dependence of the current in this
RLC circuit as a function of the frequency of the external voltage. We will solve
the RLC circuit problem for you within this chapter. Your problem is to repeat the
calculation for a circuit in which there are two RLC circuits in parallel, as shown
on the right of Figure 16.1. You may assume a single value for inductance and
capacitance, and three values for resistance:
1 1000 1000 1000
L = 1000 H, C= F, R= , , Ω. (16.2)
1000 1.5 2.1 5.2
√
Consider frequencies of applied voltage in the range 0 < ω < 2/ LC = 2/s.
Try to remember your first exposure to square roots in elementary school. Though
2
√straightforward to understand that 5 = 25, it was a challenge to understand
it was
that 25 = ±5, and more of a challenge to understand what was the true value of
√
√24. For many of us, it was downright impossible to understand the true value of
−1. Mathematicians, being a rather clever and proud bunch, have handled this
294 CHAPTER 16
R R 2R
L L 2L
C C 2C
Figure 16.1 Left: An RLC circuit connected to an alternating voltage source. Right: Two RLC
circuits connected in parallel to an alternating voltage. Observe that one of the parallel
circuits has double the values of R, L, and C as does the other.
Complex numbers are very useful in mathematics and science since they let
us double our work output with only the slightest increase in input. This is accom-
plished by employing the familiar operations of algebra and calculus on complex
numbers, and then separating off the real and imaginary parts of the answer at
the end. By way of example, even if z is a complex number, z 3 /z still equal z 2 ,
without our having to express the individual numbers in terms of their real and
imaginary parts.
z(x,y)
Im z = y
r
Re z = x
z = x + iy. (16.4)
In turn, the complex nature of z is indicated by giving its real and imaginary parts:
Re z = x, Im z = y. (16.5)
In a strict sense, y is the magnitude of the imaginary part of z , and iy is the imagi-
nary part. Yet y is usually called “the imaginary part.”
Because complex numbers have independent real and imaginary parts, a use-
ful way to visualize them is to imagine a coordinate system in which the ordinate
points off into imaginary space and the abscissa points off into real space. As seen
in Figure 16.2, we then visualize z = x + iy as a point with y projection along
the imaginary axis and x projection along the real axis. This is analogous to a
vector in a 2-D space, except that part of this vector lies in an imaginary space.
The analogy between complex numbers and 2-D vectors is taken one step further
by applying the polar coordinate representation of a vector to complex numbers.
On account of this, the point z in Figure 16.2 may be located not only by giving
its Cartesian coordinates x and y , but also by specifying it polar coordinates r,
the length of the vector from the origin to point z , and θ, the angle that the vector
makes with the abscissa. The complex number is the same in either case, and,
indeed, the two representations are related via simple trigonometry:
r = x2 + y 2 , θ = tan−1 (y/x),
(16.6)
x = r cos θ, y = r sin θ.
296 CHAPTER 16
The essence of the computing aspect of our problem is the programming of the
rules of arithmetic for complex numbers. This is an interesting chore because
while Java contains all the rules for real numbers, you must educate Java as to the
rules for complex numbers. Indeed, since complex numbers are not primitive data
types like doubles and floats, we will construct complex numbers as objects.3
3 Because complex numbers are used so often in science and engineering, there is a move afoot to have some
future versions of Java incorporate complex numbers as a primitive data type in order to speed up execution and
make them easier to use.
OBJECT-ORIENTED PROGRAMMING, ABSTRACT DATA; COMPLEX CURRENTS* 297
The basic rules of circuit theory are called Kirchoff’s laws [R & M 93], and we
now apply one of them to the circuit on the left of Figure 16.1. We work our way
around the circuit, setting the external voltage V (t) equal to the sum of the voltage
drops across the resistor, the inductor, and the capacitor. If I(t) is the current in
the circuit, we end up with the basic differential equation of circuit theory
dV (t) dI d2 I I
=R +L 2 + , (16.20)
dt dt dt C
where we have taken an extra derivative to eliminate an integral. The solution to
our problem follows by solving (16.20) when the voltage has the form V (t) =
V0 cos ωt. An elegant way to do that is to recognize that
V0 cos ωt = Re V0 e−iωt = Re (V0 cos ωt − iV0 sin ωt) . (16.21)
Because (16.20) is a linear equation (only first power of I occurs), the law of linear
superposition holds. This means that if we imagine the circuit being driven by a
complex voltage source, whose real part is the physical voltage, then the resulting
current I(t) will also be complex, with its real part the physical current. Thus we
assume that the current has the form
I(t) = I0 e−iωt . (16.22)
If we substitute this and the complex V (t) into (16.20), we obtain
V0 e−iωt = ZI0 e−iωt . (16.23)
298 CHAPTER 16
4 Some elementary texts may refer to |Z| as the impedance and then use the concept of phasors to describe the
effect of the impedance on the phase. We view the use of complex impedance as more direct and elegant.
OBJECT-ORIENTED PROGRAMMING, ABSTRACT DATA; COMPLEX CURRENTS* 299
voltage across them. If two impedances are connected in series, then the voltages
add, and this leads to:
Z = Z1 + Z2 (series connection). (16.30)
If the impedances are connected in parallel, then the currents add, and this leads to
1 1 1
= + (parallel connection). (16.31)
Z Z1 Z2
Hence in the parallel case, the impedances add in inverse, with all the steps of the
calculation being performed with complex arithmetic.
What do you see when you look at the abstract object in Figure 16.3? Some
readers may see a face in profile, others may see some parts of human anatomy,
and others the total absence of artistic ability. This figure is abstract in the sense
that it does not try to present a true or realistic picture of the object, but rather uses
a symbol to suggest more than meets the eye.
For instance, one might create an object with parts that contain a student’s
school record (ID, grades, etc.), as well as other parts that contain methods to cal-
culate the grade point average, etc. Of course, one would need many such objects
because there are many students. To distinguish between the general structure of
this student-record object and specific record objects for individual students, the
general object is called a class, while the object for specific cases is called an
instance of the class, or just an object.
In this chapter, our objects will be complex numbers, while in other chapters
they may be plots, vectors, or matrices. The classes that we form will be combina-
tions of abstract data types and associated methods for modifying those data. The
entire class may also be thought of as objects. In a formal sense, computer science
requires abstract data types to possess the three properties [Zach 96]:
Typename: procedure to construct the new data type from elementary pieces.
Set values: mechanism for assigning values to the defined data type.
Set operations: rules that permit operations on the new data type (you would not
have gone to all the trouble of declaring a new data type unless you were interested
in doing something with it).
Before we examine how these properties are applied in our programs, let us
review the structure we have been using in our Java programs. When we start off
our programs with a declaration statement such as double x. This tells the Java
compiler the kind of variable x is, so that Java will store it properly in memory
and use proper operations on it. The general rule is that every variable we use in
a program must have its data type declared. For primitive (built-in) data types, we
declare them to be double, float, int, char, long, short, or boolean.
If our program employs some user-defined, abstract data types, then they
too must be declared. This declaration must occur even if we do not define the
meaning of the data type until later in the program (the compiler checks on that).
Consequently, when our program refers to a number z as complex, the compiler
must be told at some point that there is both a real part x and an imaginary part y
that makes up a complex number.
OBJECT-ORIENTED PROGRAMMING, ABSTRACT DATA; COMPLEX CURRENTS* 301
One of the powerful and modern aspects of Fortran is its object-oriented approach
to programming. Since the new concepts of object-oriented programming (OOP)
can be a rather hard to grasp as purely theoretical concepts, we will gain some
experience with objects and in the process learn some of the concepts of OOP.
After all, a child learns to speak a language in a similar way!
Data by Reference
When Fortran deals with objects it does so by what computer scientists call
by reference. More simply, when you refer toan object, Fortran understands that to
mean that you are referring to the location in memory where your object is stored
and not to the explicit values of the object’s parts. If you remember that objects
are referenced by their locations in memory rather than their actual values, the
procedures we are about to describe will make more sense.
We suspect that all the words in the preceding section mean little without a real
example to follow. So let’s now examine an example of an object in Fortran, after
which you should be able to go back and make more sense of the preceding words.
The “object” that we will create with Fortran will be a complex number (about
which, after sections § 16.2-16.2, you should be an expert). Despite the fact that
Fortran has its own intrinsic complex data type, we create a custom data type for
302 CHAPTER 16
47 Type ( p u b l i c c o m p l e x ) : : a , b , c
48 C h a r a c t e r ch
49 a%r e = 1 .
50 a%im = 2 .
51 b%r e = 3 .
52 b%im = 4 .
53 i f ( a%im >=0.0) t h e n
54 ch = ’+’
55 e l s e i f ( a%im < 0 . 0 ) t h e n
56 ch = ’-’
57 end i f
58 w r i t e ( ∗ , ∗ ) ’a = ’ , a%r e , ch , a b s ( a%im ) , ’i’
59 i f ( b%im >=0.0) t h e n
60 ch = ’+’
61 e l s e i f ( b%im < 0 . 0 ) t h e n
62 ch = ’-’
63 end i f
64 w r i t e ( ∗ , ∗ ) ’b = ’ , b%r e , ch , a b s ( b%im ) , ’i’
65 c = add ( a , b )
66 i f ( c%im >=0.0) t h e n
67 ch = ’+’
68 e l s e i f ( c%im < 0 . 0 ) t h e n
69 ch = ’-’
70 end i f
71 w r i t e ( ∗ , ∗ ) ’a + b = ’ , c%r e , ch , a b s ( c%im ) , ’i’
72 c = subtract (a ,b)
73 i f ( c%im >=0.0) t h e n
74 ch = ’+’
75 e l s e i f ( c%im < 0 . 0 ) t h e n
76 ch = ’-’
77 end i f
78 w r i t e ( ∗ , ∗ ) ’a - b = ’ , c%r e , ch , a b s ( c%im ) , ’i’
79 c = multiply (a , b)
80 i f ( c%im >=0.0) t h e n
81 ch = ’+’
82 e l s e i f ( c%im < 0 . 0 ) t h e n
83 ch = ’-’
84 end i f
85 w r i t e ( ∗ , ∗ ) ’a * b = ’ , c%r e , ch , a b s ( c%im ) , ’i’
86 i f ( b%r e = = 0 . .AND. b%im = = 0 . ) t h e n
87 w r i t e ( ∗ , ∗ ) ’Error: division by zero ’ , b%r e , ’+’ , b%im , ’i’
88 else
89 c = divide (a , b)
90 i f ( c%im >=0.0) t h e n
91 ch = ’+’
92 e l s e i f ( c%im < 0 . 0 ) t h e n
93 ch = ’-’
94 end i f
95 w r i t e ( ∗ , ∗ ) ’a / b = ’ , c%r e , ch , a b s ( c%im ) , ’i’
96 end i f
97 End Program m a i n p r o g r a m
304 CHAPTER 16
Exercise:
The first thing to notice about ComplexType.f90 is that the data type is
declared with the statements
These are the same techniques we have employed before (it’s good when some
things stay the same in life). However, on line 6 we see that the variables re and
im are declared for the public data type with the statement
6. Real :: re, im
These variables are part of a dynamicdata type, an object. These variables are
dynamic in thesense that they will be different for each object (instance of the
class) created. That is, if we define z1 and z2 to be Complex objects, then the
variables re and im will be different for z1 and z2.
Object Constructors
To construct an object from a module in Fortran, one must simply state the use of
the module before any other declarations, such as in ComplexType.f90.
Some explanation is clearly in order! Modules are covered in more details in Chap-
ter 18. Briefly now, a module acts like a nested class in Fortran. A module can be
used by other programs once it has been compiled. All of the procedures in a mod-
ule are static. A procedure or variable can be declared private, protected, or public.
The declaration of user rights to the module’s constituents is important only if you
are developing programs with security in mind. Once a module is used inside of
a procedure or program, all of the module’s procedures and data types become
available for use therein. For example, look at the program ComplexType.f90 for
a demonstration of multiple functions that may be used by other programs via the
module complex module.
Exercise Add two functions to complex module that allow a user to create a de-
fault complex number and a custom complex number from two real initial values.
Now let’s take stock of what we have up until this point. On line 6, our program
has defined the variables re and im that each object of this program will have. For
this reason these variables that project the component parts are often referred to
as instance variables. We also have a complex number algebra module that can
perform algebraic operations on two complex numbers simultaneously.
In the main program, we can see how to create objects using the data type
public complex. On line 47, in the usual place for declaring variables, we have
the statement
The compiler knows from the type command that public complex is not
one of its primitive (built-in) data types. In the present case this program contains
the module named complex module with the data type public complex. Hence,
the compiler does not have to look very far to know what you mean by a pub-
lic complex data type5 . Accordingly, when the statement Type(public complex)
:: a,b,c declares the variables a, b, and c to be public complex data objects,
we know that they are manifestly objects since instanced data types are not static.
Recall that declaring a variable type, such as real or integer, does not
assign a value to the variable, but, instead, tells the compiler to add the name of
the variable to the list of variables it can be expected to encounter. Likewise, the
declaration statement type(public complex) :: a,b,c lets the compiler know
what custom data type these variables are.
To actually create the objects, and not just register their names, we have to
place numerical values in the memory locations that have been reserved for the
objects. Since an object has multiple parts, we cannot give all its parts initial
values with a simple assignment statement like a = 0;, so some other method is
needed.A new instance of a complex data type is created as above, then values
are assigned by accessing the internal instance variables of the complex data type
variable.
Instances
Since the name of the parent object and the names of objects that are created are
the same, it sometimes is useful to use yet another word to distinguish one from
the other. Accordingly, the phrase instance of a class is used to refer to the cre-
ated objects (in our example, a, b, and c), that is, the created objects are each a
single reference to the parent object. This designation distinguishes them from the
definition of the abstract data type.
5 Other Fortran files could also use our complex methods, but we have enough to worry about right now.
OBJECT-ORIENTED PROGRAMMING, ABSTRACT DATA; COMPLEX CURRENTS* 307
complex numbers.
2. Test your methods by checking that the following identities hold for a variety
of complex numbers:
z + z = 2z, z + z∗ = 2 Rez
z − z = 0, z − z∗ = 2 Imz (16.32)
zz∗ = |z|2 , zz∗ = r2 (which is real)
Hint: Compare your output to some cases of pure real, pure imaginary, and
simple complex numbers that you are able to evaluate by hand.
3. Equations (16.29) and (16.27) are the solution for the current in a single RLC
circuit. It tells us that the magnitude of the current is given by
V0
|I| = , (16.33)
Z
and that the phase of the current (relative to the cos ωt time dependence) is
−1 1/ωC − ωL
θI = tan . (16.34)
R
Modify the given complex arithmetic program so that it performs the com-
plex arithmetic required by (16.33). Hint: You do not have to solve this
from scratch! Instead, use the techniques you have already programmed for
determining the magnitude to determine |I|.
4. Compute and then make a plot of the magnitude and the phase of the current
in the circuit as a function of frequency ω of the external voltage source. For
our problem, a good range is 0 ≤ ω ≤ 2.
5. Assessment: You should notice a resonance peak in the magnitude at the
same frequency for which the phase vanishes. The smaller the resistance R,
the sharper should the circuit pass through resonance. These types of circuits
were used in the early days of radio to tune to a specific frequency. The
sharper the peak, the better the quality of reception.
6. The second part of the problem dealing with the two circuits in parallel is
very similar to the first part. You need to change only the value of the im-
pedance Z used. To do that, explicitly perform the complex arithmetic im-
plied by (16.31), deduce a new value for the impedance, and then repeat the
calculation of the current.
Recall from way back in Chapter 3 that Maple knows all about complex numbers
and complex arithmetic. Indeed, you have probably already seen an occasional I
pop up as the solution
√ to some equations. The point here is that Maple reserves the
symbol I as the −1, and this lets us use its I at our pleasure:
sqrt ( −1 ) = I
√
> expand((a + I*b)ˆ2); # See if Maple uses I as −1
a + 2I ab − b
2 2
In §16.3 we applied circuit theory and complex analysis to the RLC circuit and
found that if the exciting voltage is the real part of
V (t) = V0 e(−I ω t) , (16.35)
then the current in the circuit is
V0 cos(ω t − θ)
I(t) = . (16.36)
|Z|
Here Z is the complex impedance,
1
Z := R + ( − ω L) I.
ωC
We will start our Maple investigation by trying to determine magnitude |Z| and
phase θ of Z using Maple’s capabilities for complex analysis. Whereas needing to
know the magnitude and phase of Z is just another way of saying that we need to
know Z in polar notation, we have Maple calculate these for us:
> Re(Z); Im(Z); # ReZ, ImZ
1 1
Re(R + ( − ω L) I) Im(R + ( − ω L) I)
ωC ωC
This is just a fancy way of giving us back the input. The problem is that Maple does
not know that ω , R, L, and C are real, and so it cannot do the complex arithmetic.
To tell Maple that the constants are real, we tell it what to assume:
> assume (R, real); assume(L, real); assume(C, real); assume (omega, real);
> Re(Z); Im(Z); # Now check again
1
R˜ − ω˜ L˜
ω˜ C ˜
It has taken some work, but now we are ready for some complex arithmetic. Look
at the polar form:
> polar(Z);
1 1
polar( R˜2 + ( − ω˜ L˜)2 , argument(R˜ + ( − ω˜ L˜) I))
ω˜ C ˜ ω˜ C ˜
This is giving us the correct magnitude, but Maple appears unable to compute the
phase. This seems to be a Maple failure. However, we get it to work by combining
the map and evalc commands:
OBJECT-ORIENTED PROGRAMMING, ABSTRACT DATA; COMPLEX CURRENTS* 309
We want to examine the current that occurs in the RLC circuit as a function of
the driving frequency. We have already discussed in Chapter 4 some of Maple’s
commands for plotting complex functions. Irrespective of them being illuminating,
for the problem given here, we first use plot3d to make the familiar z(x, y) surface
plot of the magnitude and phase of the current as functions of both the frequency
of the external voltage ω and of the resistance R:
1 1
Zinv := L := 1000 C :=
R+ ( ω1C− ω L) I 1000
> assume (R, real); assume (omega, real); # Tell Maple the constants are real
> Polar := map( evalc, polar(Zinv) ); # Convert 1/Z to polar form
> polar(1/((Rˆ2+(1000/omega-1000*omega)ˆ2)ˆ(1/2)),
> arctan(-1000/omega + 1000*omega, R));
⎛ ⎞
1 1000
Polar := polar ⎝ , arctan(− + 1000 ω˜, R˜)⎠
R˜2 + ( 1000 − 1000 ω˜)2 ω˜
ω˜
> mag := op(1, Polar); op(2, Polar); # Extract magnitude, phase
1 1000
mag := arctan(− + 1000 ω˜, R˜)
2
R˜ + ( 1000 − 1000 ω˜)2 ω˜
ω˜
310 CHAPTER 16
Check out
√ how the magnitude has a maximum when the external frequency
ω = 1/ LC . This is the resonance frequency. For our choice of constants this
corresponds to ω = 1. We now make some plots to see if this is true.
0.005
0.004
0.003
0.002
0.001
0
200 0
400 0.5
600 1
R~ 800 1.5 omega~
1000 2
1
0.5 200
omega~ 0.5 400
600 R~
–1 0.016
800
2 1000 0.012
0.008
0.004
0
–1 0
–0.5 0.5
0 1
y 0.5 1.5 x
1 2
Sure enough, the plot of 1/|Z| shows that the magnitude of the current has a max-
imum at ω = 1. (It helps to grab and rotate these plots to see them better.) We also
see that as the resistance R in the circuit is made smaller, the maximum current
becomes progressively larger. The second plot of the phase shows that below reso-
nance, ω < 1, the current lags the voltage, while above resonance the current leads
the voltage. Another way to visualize complex functions is with the command
complexplot3d. It makes a 3-D visualization of a complex function of a com-
plex argument. Here we do it by treating the frequency ω = x + iy as a complex
number:
We see in the right plot above that there is a sharp peak at x = Re(ω) = 1,
OBJECT-ORIENTED PROGRAMMING, ABSTRACT DATA; COMPLEX CURRENTS* 311
Vectors and matrices play key roles in scientific computing. Indeed, much of so-
called high-performance computing involves computations with very large arrays.
These arrays may contain experimental data needing processing, or they may con-
tain the results of a simulation in which the discrete nature of breaking space up
into small units leads naturally to the use of arrays. And since real-world prob-
lems are often complicated and require high precision (small units), arrays with
thousands or millions of elements are not unusual. Even though this means that
the matrices used in realistic problems will be big and will require efficient algo-
rithms, often the programs using matrices are simple and direct.
Your problem is similar to the one in Chapter 7. Here we will deal with a plate
and a square whose moments of inertia are given, and we will focus on the matrix
multiplication that converts the angular velocity ω into the angular momentum L.
ARRAYS I: VECTORS, MATRICES; RIGID-BODY ROTATIONS 313
z
y
(-1, 1, 1)
1
y
1
0 x
(1, -1, -1) (1, 1, -1)
x
Figure 17.1 Left: A plate sitting in the x − y plane with a coordinate system at its center. Right: A
cube sitting in the center of a three-dimensional coordinate system.
The plate is rotated so that its angular velocity vector ω always remains in the x−y
plane (which does not mean the plate remains in the x − y plane). Specifically, it
is rotated with the three angular velocities:
Write a Fortran program that computes the angular momentum vector L via the
matrix multiplication L = {I}ω . Plot ω and L for each case, and compare the
results to those found with Maple.
Problem 2: Consider now the rotation of the cube on the right of Figure 17.1.
The cube has side b = 1, mass m = 1, and, for axes on the corner, an inertia tensor
[M&T 88]:
⎛ ⎞ ⎛ ⎞
+2/3 −1/4 −1/4 +2/3 −1/4 −1/4
{I} = mb2 ⎝ −1/4 +2/3 −1/4 ⎠ = ⎝ −1/4 +2/3 −1/4 ⎠ . (17.3)
−1/4 −1/4 +2/3 −1/4 −1/4 +2/3
The cube is rotated along axes passing through two sides and the diagonal, explic-
itly, with the three angular velocities:
Write a Fortran program that computes the angular momentum vector L via the
requisite matrix multiplication. Plot ω and L for each case, and compare the results
to those found with Maple.
314 CHAPTER 17
Recall from Chapter 7 that the angular-momentum vector L is given by the product
L = {I} ω. (17.5)
Here ω is the angular-velocity vector and {I} is the inertia tensor represented by
the matrix [Iij ]:
⎛ ⎞
Ixx Ixy Ixz
{I} = [Iij ] = ⎝ Iyx Iyy Iyz ⎠ . (17.6)
Izx Izy Izz
Despite the use of x, y , and z to label the three axes being standard in elementary
science, the mathematics and the computing gets easier if we label each direction
with a number rather than a letter. Consequently, we now change to a notation in
which A0 indicates the component of the vector A in the x or “0” direction, A1
indicates the component in the y or “1” direction, and A2 indicates the component
in the z or “2” direction:
⎛ ⎞ ⎛ ⎞ ⎛ ⎞ ⎛ ⎞
Ax A1 Ixx Ixy Ixz I11 I12 I13
⎝ Ay ⎠ ⇔ ⎝ A2 ⎠ , ⎝ Iyx Iyy ⎠ ⎝
Iyz ⇔ I21 I22 I23 ⎠ . (17.7)
Az A3 Izx Izy Izz I31 I32 I33
Here we use 1, 2, 3 for the indices, as is standard math, yet Java and C would use
0, 1, 2.
With this new notation, the relation stating that the angular momentum
equals the product of the moment of inertia tensor times the angular velocity vector
is represented by the matrix multiplication
⎛ ⎞ ⎛ ⎞⎛ ⎞
L1 I11 I12 I13 ω1
⎝ L2 ⎠ = ⎝ I21 I22 I23 ⎠ ⎝ ω2 ⎠ . (17.8)
L3 I31 I32 I33 ω3
These three equations may also be written in a convenient form for computations:
3
Lk = Ikj ωj , k = 1, 2, 3. (17.12)
j=1
ARRAYS I: VECTORS, MATRICES; RIGID-BODY ROTATIONS 315
There is no requirement that arrays have only one index. To prove the point,
we could use the 2-D array HW(i,j) to store all homework scores for all students,
with i representing the assignment number and j representing the student num-
ber. It follows then that HW(2,3)=99 would be second homework score for student
number 3, while HW(10,500)=12 would be the tenth homework score for student
500. As you see here, the two indices (subscripts) needed to reference the elements
in a 2-D array are separated by a comma, and enclosed in a single set of paren-
thesis. Likewise, a 3-D array would have three indices separated by commas. The
number of dimension, and the length in each dimension is up to the programmer.
In mathematics and science we deal with objects called vectors and matrices.
Taking into account that only one index is needed to distinguish the components of
a vector, they are stored on a computer in a 1-D array. Because matrices have rows
and columns, their elements are stored in arrays with two indices. As an example,
the matrix Ixy , representing the inertia tensor, could have its components stored
in the array I(x,y). To repeat, the mathematical objects are vectors and matrices,
the computer storage is in single-indexed and double-indexed arrays.
As is often the case when science and computer science are combined, con-
fusion results from using different words to describe the same idea. Even worse,
we often use the same words to describe different ideas. Of necessity we now must
point out that our use of the words “two dimensional” and “three dimensional” is
from physics where the number of dimensions of space equals the number of com-
ponents (indices) that a vector may have, and where the number of values that
316 CHAPTER 17
any one index spans is also equal to the number of dimensions. Yet on a com-
puter, a “three-dimensional array” refers to a data type with three indices, such as
A(i,j,k), and there is no limit on the range spanned by any one of the indices
i, j, and k. In the latter case, the maximum value of some index is referred to as
the “size” or “length” of the array, not its “dimension”. To name an example, the
two-dimensional physics vectors used to describe motion in a plane, are stored in
one-dimensional arrays of length 2.
In most programming languages arrays are stored in memory as a continuous 1-D string of numbers. For example,
an n × m array would be stored as one long string, with some algorithm used to determine how the location in
the string relates to the row and column indices. In Fortran, the mapping of an array to its 1-D form is done in
column major order, that is, first all the elements from column 1 of the array are stored, then all the elements
from column 2 are stored, and so forth, until all columns are stored.
The elements in an array are accessed by stating the array’s name followed by a
comma-separated list of the indices enclosed in parenthesis, for example, A(1) or
B(i,j). As is true for other primitive data types, arrays too must be declared and
assigned values (instantiation) before their use. First, you state an array’s data
type followed by two colons, and then the array’s name. For example, these two
definitions produce the same fixed size array:
1 Real ∗8 , dimension ( 8 ) : : A
2 R e a l ∗8 : : A( 8 )
This same scheme is one of the ways used to assign values to array elements:
1 R e a l ∗8 : : A( 8 )
2 Integer :: i
3 A( 2 ) = 1 .
4 do i =1 , 8 , 1
5 A( i ) = i
6 end do
When using a 2-D array to store a matrix, the first index refers to the column of the
matrix and the second to the row. Take the rotational inertia matrix as an example:
1 R e a l ∗8 : : I ( 3 , 3 ) ! Declare array type
2 Integer :: i , j
3 do i = 1 , 3 , 1
4 do j = 1 , 3 , 1
5 I ( i , j ) = i −j ! I n i t i a l i z e matrix
6 end do
7 end do
ARRAYS I: VECTORS, MATRICES; RIGID-BODY ROTATIONS 317
The output should be C = 1. Here C(1:n,i) accesses the entire ith column (ele-
ments between 1 and n) in one sweep. To access only a range of elements in the
column or row, you only need to describe the range by i:j. For instance, C(i,3:5)
or D(2:10, 4:15, j).
3. Compile and execute the 2D version of the program and see how much longer
it now takes. (The extra time arises from having to move through larger
blocks of memory. We found a 0.3% effect, not big, but real.)
4. Modify OneDArray.f90 to have it print values for a(0) and a(3). Fortran
should not let you access a(0) because it is out of bounds. ♠
Array Sizes
The DIM keyword here designates which index of the array we want the size of.
If you want to know the length of an array with several indices, use the size
command, with specification as to which dimension (DIM) interests you:
Fixed-Sized Arrays
A fixed-size array is one in which the dimensions are defined during its declaration.
We have been using them in our examples so far. To declare a fixed-sized array, you
may use either the dimension modifier (especially useful when defining multiple
arrays of the same dimension), or you may declare each array individually:
1 R e a l ∗ 8 , d i m e n s i o n ( 8 , 8 ) : : D, E , F
2 I n t e g e r : : A( 7 , 8 ) , B ( 9 , 1 0 ) , C ( 1 1 , 1 2 )
ARRAYS I: VECTORS, MATRICES; RIGID-BODY ROTATIONS 319
Assumed-Shape Arrays*
An assumed-shape array is one whose dimensions are not specified when the array
is declared, but rather, is determined by the size of a fixed-size array that is passed
to it. This is called dynamic memory allocation and is useful for creating proce-
dures that have arrays passed as arguments. Assumed-shape arrays are declared by
stating their type, then optional modifiers, then the usual two colons, and finally
the array name. The difference between this declaration and the usual one is that
the dimensions are declared with colons as place holders rather than explicit num-
bers. For example, here we multiply two arbitrary Real*8 arrays, which works as
long as the number of columns on the left array equals the number of rows of the
right:
1 S u b r o u t i n e m u l t i p l y (A, B , C)
2 I m p l i c i t none
3 R e a l ∗ 8 , d i m e n s i o n ( : , : ) , i n t e n t ( i n ) : : A, B
4 R e a l ∗ 8 , d i m e n s i o n ( s i z e (A, DIM= 1 ) , s i z e ( B , DIM= 2 ) ) : : C
5 I n t e g e r : : i , j , k , h , m, n
6 k = s i z e (A, DIM= 1 )
7 h = s i z e (A, DIM= 2 )
8 m = s i z e ( B , DIM= 1 )
9 n = s i z e ( B , DIM= 2 )
10 i f ( h / =m) t h e n
11 w r i t e ( ∗ , ∗ ) ’Error: Dimensions do not match.’
12 stop
13 end i f
14 do i =1 , n , 1
15 do j =1 , h , 1
16 C ( 1 : k , i ) = C ( 1 : k , i ) + B( j , i ) ∗A ( 1 : k , j )
17 end do
18 end do
19 End S u b r o u t i n e m u l t i p l y
Allocatable Arrays*
11 h= s i z e (A, DIM= 2 )
12 m= s i z e ( B , DIM= 1 )
13 n= s i z e ( B , DIM= 2 )
14 i f ( h / =m) t h e n
15 w r i t e ( ∗ , ∗ ) ’Error: Dimensions do not match.’
16 stop ! Aborts program i n t h e case of t h i s e r r o r
17 end i f
18 do i =1 , n , 1
19 do j =1 , h , 1
20 C ( 1 : k , i ) = C ( 1 : k , i ) + B ( j , i ) ∗A ( 1 : k , j )
21 end do
22 end do
23 End S u b r o u t i n e m u l t i p l y
24 End Module l i n a l g
25 !
26 Program t i m e r
27 Use l i n a l g
28 I m p l i c i t None
29 R e a l ∗ 8 , a l l o c a t a b l e , d i m e n s i o n ( : , : ) : : A, B
30 R e a l ∗8 : : t
31 I n t e g e r : : T i ( 8 ) , Tf ( 8 ) , i , i n c =20
32 I n t e g e r , p a r a m e t e r : : n =500
33 R e a l ∗8 : : C( n , n )
34 C h a r a c t e r ( len = 12) : : clock ( 3 )
35 do i =2 , n −1 , i n c
36 a l l o c a t e (A( i −1 , i ) ,B( i , i + 1 ) )
37 A = 1. 8
38 B = 0.2 8
39 c a l l d a t e a n d t i m e ( c l o c k ( 1 ) , c l o c k ( 2 ) , c l o c k ( 3 ) , Ti )
40 c a l l m u l t i p l y (A, B , C)
41 c a l l d a t e a n d t i m e ( c l o c k ( 1 ) , c l o c k ( 2 ) , c l o c k ( 3 ) , Tf )
42 d e a l l o c a t e (A, B)
43 t = 6 0 . 0 ∗ ( Tf ( 6 )−T i ( 6 ) ) + ( Tf ( 7 )−T i ( 7 ) ) + ( Tf ( 8 )−T i ( 8 ) ) / 1 0 0 0 . 0
44 w r i t e ( ∗ ,FMT= 1 0 0 ) i , t
45 end do
46 100 F o r m a t ( I5 , ’ ’ , F12 . 6 )
47 End Program t i m e r
23 Function f ( x )
24 I m p l i c i t None
25 Real , d i m e n s i o n ( : ) , i n t e n t ( i n ) : : x
26 Real : : f ( s i z e ( x ) )
27 f = x/3.0
28 End F u n c t i o n f
While a procedure cannot change the memory address passed when there is
an array argument, it is free to the change the actual values of the array elements
stored in memory. Run ChangeArray.f90 to see how this works. Note that all
three values of x are changed by the function f(x), and that the changed values
of x are seen by the main program. Also note that the write statements here
322 CHAPTER 17
demonstrate the use of implied do-loops contained within the write statements
themselves, thus, permitting several values of an array to be written on a single
line.
Exercise: What we have said about functions dealing with single-indexed arrays
hold equally true for multi-indexed arrays. Modify a copy of ChangeArray.f90 so
that x(3) is now the two-indexed array x(3, 2), and see if you can make changes
to x(i,1) for i=1 ...3. ♠
Usually we write a function to return a value for the function name, but not neces-
sarily to change the value of any of the function’s arguments. As discussed above,
when arrays are used in the argument list to a function, the situation may have
unexpected surprises (since a change in an argument array within a function will
impact that array’s values in the calling routine as well). This is also true for sub-
routines, but the task at hand with array arguments in these types of procedures
tend to be more blatant and less likely to surprise us. Here’s a more extensive
example of using arrays within the argument list for a function:
27 end do
28 c a l l modify ( a , b , c )
29 w r i t e ( ∗ , ∗ ) ’Scalar-after a = ’ , a
30 w r i t e ( ∗ , ∗ ) ’Vector-after b = [’ , ( b ( i ) , i = 1 , 3 , 1 ) , ’]’
31 do i = 1 , 3 , 1
32 i f ( i ==2) t h e n
33 w r i t e ( ∗ , ∗ ) ’After c = [’ , ( c ( i , j ) , j = 1 , 3 , 1 ) , ’]’
34 else
35 write (∗ ,∗) ’ [’ , ( c ( i , j ) , j = 1 , 3 , 1 ) , ’]’
36 end i f
37 end do
38 End Program a r r a y m o d
39 !
40 I n t e g e r F u n c t i o n modify ( x , y , z )
41 I m p l i c i t None
42 Integer :: i , j
43 Real , i n t e n t ( i n o u t ) : : x , y ( : ) , z ( : , : )
44 x = 3.14159265358979
45 do i = 1 , 3 , 1
46 y ( i ) = x ∗( i ∗∗3)
47 do j = 1 , 3 , 1
48 z ( i , j ) = x∗ s i n ( 2 . 0 ∗ i ) ∗ c o s ( 3 . 0 ∗ j )
49 end do
50 end do
51 modify = 1
52 End F u n c t i o n m o d i f y
4 I m p l i c i t None
5 Integer :: i ! Instance
6 Real : : a ( 3 ) , b ( 3 )
7 do i = 1 , 3 , 1 ! Initialize
8 a ( i ) = 1.0∗ i ∗ i
9 b( i ) = sqrt (1.0∗ i )
10 end do
11 w r i t e ( ∗ , ∗ ) ’vector a before = [’ , ( a ( i ) , i = 1 , 3 , 1 ) , ’]’
12 w r i t e ( ∗ , ∗ ) ’vector b before = [’ , ( b ( i ) , i = 1 , 3 , 1 ) , ’]’
13 b(1:2) = a (2:3)
14 a (1:3) = 1.0
15 w r i t e ( ∗ , ∗ ) ’vector a after = [’ , ( a ( i ) , i = 1 , 3 , 1 ) , ’]’
16 w r i t e ( ∗ , ∗ ) ’vector b after = [’ , ( b ( i ) , i = 1 , 3 , 1 ) , ’]’
17 End Program a r r a y s e q u a l
Let’s apply these rules and conventions to our rotation problem. We set up our
moment of inertia tensor Mjk on the computer by declaring that the variable M
is to be an array with two indices, and that the angular momentum and angular
velocity are arrays with one index:
So far we have told the compiler that M, L and w are to be arrays of real numbers,
and have reserved the right number of locations in memory for them. But we have
not actually placed any values for these variables in memory. The most direct
way to assign values to do it for each individual component. For example, if our
angular velocity vector ω were pointing along the x axis with magnitude 10, we
would assign it the three components:
Declaring values for the moment of inertia tensor M with its two indices is more
interesting. We use two loops to assign values to each component:
k=0
do i=1,3,1
do j=1,3,1
k=k+1
M(i,j) = k
end do
end do
ARRAYS I: VECTORS, MATRICES; RIGID-BODY ROTATIONS 325
Indeed, you can even build up an array with each row having a different length, or
with the elements of an array being sub-arrays. In this way, arrays can be used to
build what is called structured data sets.
⎛ ⎞
+2/3 −1/4 −1/4
I = ⎝ −1/4 +2/3 −1/4 ⎠ . (17.14)
−1/4 −1/4 +2/3
For each calculation, take your answer and draw the angular momentum L
and the angular velocity vector ω on a piece of graph paper, taking note if
the two are parallel. Hint: Make a perspective drawing of three perpendic-
ular axes first, and then mark off components on each axis (or use Maple).]
Consider the cases:
a. ω = (1, 0, 0).
b. ω = (0, 1, 0).
c. ω = (1, 1, 1).
4. The determinant of a 3 × 3 matrix is defined to be
⎛ ⎞
M11 M12 M13
det ⎝ M21 M22 M23 ⎠ = M11 M22 M33 + M12 M23 M31 + M13 M21 M32
M31 M32 M33
−M31 M22 M13 − M32 M23 M11 − M33 M21 M12 .
5. Here is the program ArrayTest.f90 that finds the maximum and minimum
of a two-dimensional array of arbitrary length:
• Use as much as you can of ArrayTest just to save yourself some typing.
• The simplest, though not the most efficient, way to sort a list of numbers
is to start with the first two elements, a[1] and a[2], interchange them if
a[1] is larger than a[2], and then go on to the next adjacent pair, a[2]
and a[3], and perform the same operation. Continue until you get to the
end of the array, a[n-1] and a[n]. While one pass through the array will
not be sufficient, n − 1 passes will.
• Design a procedure that implements the sort procedure just described.
While the program will turn out to be quite simple, it may take some
thinking to get the logic thought through. Accordingly, first sketch out a
flowchart or some pseudocode containing the key logical questions and
consequences. Hand in your design with the rest of your assignment.
• Write a procedure xChange(a, i) that sorts a 2D array. To be safe, you
may want to read the discussion on changing an array element in the call
to a procedure in § 17.5.
Chapter Eighteen
Advanced Function Methods, Objects*
The simple function and subroutine examples we have presented so far are all that
a beginning user should need for their work. However, Fortran does permit some
more sophisticated techniques for dealing with procedures, and we shall discuss
some of that now in the context of object-orientated programming (OOP). While
incorporating these newer features in your programs does require some extra lines
of code, OOP techniques lead to less-error prone programs, aid in debugging, and
lead to more efficient compilation and optimization (speed) [F90 UL, ChapF 04].
In addition to saving you time in the long run, we employ some of these techniques
in our examples, and so it is worthwhile for you to understand them somewhat.
Most of the procedures we have used as examples have been external. This
is the older, Fortran77 approach in which each procedure is treated like a sepa-
rate program unit that are developed and compiled independently from the main
program and the other procedures, and eventually linked together for execution.
In Fortran90, you may also group together user-defined data types and the
procedures that manipulate these types into modules. These modules are equiv-
alent to what is called objects or classes in the Java and C++ programming lan-
guages. Since an object is, in some sense, defined by the methods used to manip-
ulate it, it makes sense to couple together new data types and the methods used to
manipulate them.
The real world often maintains some of the traditions of the past, and so
sometimes you may need to include some already-written, tried-and-true, older
330 CHAPTER 18
Module My_module
Figure 18.1 Left: The structure of a Fortran program containing a procedure module. Right: The
structure of a Fortran program containing a procedure interface.
The new aspect of a module is that at its top we have the opportunity to
declare the type definitions for all the arguments used by the procedures in the
module, as well as global data that will be available to all procedures within the
module. In addition, all other programs may utilize procedures from within this
module if they simply issue the Use My module command (indicating the inclu-
sion of this module into their program environment). Once the Fortran module
file is compiled, it is stored as a file with a .mod suffix. It is then available for
other programs to use. A simple example of a module is ModuleExample.f90 in
Lst. 18.1.
Exercise: Compile FuncInterface.f90, run it, and compare the results to the
previous example, ModuleExample.f90. ♠
332 CHAPTER 18
This is a warning of something that is more obvious with subroutines than with
functions. When you call a function, the memory location of the argument is
passed to the function from the calling program. In other words, the main pro-
gram sends only a memory reference or memory location to the function, not the
actual value of the variable itself (the same as with arguments in subroutine calls).
ADVANCED FUNCTION METHODS, OBJECTS* 333
Accordingly, it is quite acceptable to call a function with the variable x as the argu-
ment to the function, and then use a different variable like y for the corresponding
variable within the function itself. As a general rule, a function may change the
value of its arguments, and those changes will be reflected in the corresponding
variables of the invoking routine. In other words, the changed value of the variable
will be returned to the calling program or procedure. Since we only concentrate on
the single value of the function name itself, we often do not think about this side
effect.
The short program Change.f90 in Lst. 18.3 gives surprising results regard-
ing the values of function arguments. To see them:
Look at the code and locate the four write statements. Compare them to
the printed results. Note that we start off with a = 1 and b = 2 in the main
program. Then the function f (a, b) is evaluated, where a and b are assigned
to the variables x and y inside f . Inside f(x, y), the code sets x = 5,
prints out the values (x = 5, y = 2), and returns a value of 7 for f. When
we get back to the main program, we print out f(a, b) = 7, and find that
the assignment statement inside the function has caused the value of a in the
main program to change!
What is happening here is that the variables in each function are local
to that particular function and not “seen” by other parts of the program. The
variables passed to the function f do not have their numerical values sent, but
rather just their location in memory. Accordingly, the values for variables a
and b in the main program are stored in the same memory locations as the
values for variables x and y in the function f. If a is changed in f, then the
corresponding variable x will reflect that change in the main program. Since
memory locations, not values, are transferred between a calling program and
a procedure, it is said that Fortran procedure calls call by reference rather
than call by value.
2. Copy Change.f90 to Change2.f90. Modify the function declaration so that
the arguments are reversed:
Compile and execute Change2.f90. This program should convince you that
the variable names inside a function are arbitrary and may be changed ac-
cording to your preference, as long as the argument types still match. The
334 CHAPTER 18
function’s arguments are, after all, called “dummy” variables to indicate that
they are only place holders.
3. As discussed before, you must always write your programs such that the
arguments in the call to a function and in the function’s declaration match
exactly in type. So, for example, if a function is declared with the second
argument as a Real*8, then the calls to that function must have the second
argument as a Real*8, or else!. To see “or else what”, change the dummy
arguments on line 12 to Real*8. Recompile Change.f90 and see the results.
4. Not only must the arguments of a function being called match the types of
the function arguments declared by the function, but the value that the func-
tion returns must also match the type declared for the function in the calling
program. For example, make a working copy of Change.f90, and replace
the function declaration in on line 12 with one that declares the function
value returned to be a Real*8. Recompile Change.f90 and see the results.
You should get an error message with a reference to “incompatible types”
or “function result types differ.” These responses are signals of inconsistent
data types.
So far, we have used the main program to call other functions. Actually, functions
can call other functions as well. Lst. 18.4 is an example that includes functions
calling other functions. Note that we are using double-precision variables and also
the tangent function from the Fortran Math library.
Exercise: Compile and run Function3.f90. Compare the output you obtain with
the print lines in the code and explain why the results are as they are.
19 Program m a i n p r o g r a m
20 Use f u n c m o d u l e ! I n c o r p o r a t e t h e module
21 I m p l i c i t None
22 R e a l ∗8 : : x = 1 . 0 , y = 3 . 0 , z
23 p r i n t ∗ , ’In main, x =’ , x , ’y =’ , y
24 z = f (x , y) ! c a l l to function f
25 p r i n t ∗ , ’In main, f = ’ , z , ’x =’ , x , ’y =’ , y
26 End Program m a i n p r o g r a m
Now that we have warned you how important it is to have the data types of a
function’s arguments be the same in the calling program as it is in the function
declaration, we show you the exceptions to this rule. With function overloading
you define a number of different functions having the same name but arguments
that somehow differ. Explicitly, each function must have either 1) a different selec-
tion of argument types, 2) a different number of arguments, or 3) a different return
type. You then can use the same function name for differing data types (with the
help of the interface feature), and, incredibly enough, the compiler will choose
the proper one based on the unique combination of arguments and return type.
While this may seem too forgiving, functions that differ only in return type are not
acceptable.
Listing 18.5 Overload.f90
1 ! Overload . f90 : overloading via i n t e r f a c e
2 ! −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
3 Integer Function f i n t ( i )
4 I m p l i c i t None
5 Integer :: i
6 f int = i∗i
7 End F u n c t i o n f i n t
8 R e a l ∗8 F u n c t i o n f r e a l ( x )
9 I m p l i c i t None
10 R e a l ∗8 : : x
11 f r e a l = x∗x
12 End F u n c t i o n f r e a l
13 Complex ∗16 F u n c t i o n f c o m p l e x ( z )
14 I m p l i c i t None
15 Complex ∗16 : : z
16 f complex = z∗ conjg ( z )
17 End F u n c t i o n f c o m p l e x
18 !
19 Program main
20 Interface f
21 Integer Function f i n t ( i )
22 Integer :: i
23 End F u n c t i o n f i n t
24 R e a l ∗8 F u n c t i o n f r e a l ( x )
336 CHAPTER 18
25 R e a l ∗8 : : x
26 End F u n c t i o n f r e a l
27 Complex ∗16 F u n c t i o n f c o m p l e x ( z )
28 complex ∗16 : : z
29 End F u n c t i o n f c o m p l e x
30 End I n t e r f a c e f
31 I n t e g e r : : a =2
32 R e a l ∗8 : : b = 2 .
33 Complex ∗16 : : c = ( 1 . , 1 . )
34 w r i t e ( ∗ , ∗ ) ’Integer: f(a) = ’ , f ( a )
35 w r i t e ( ∗ , ∗ ) ’Real: f(b) = ’ , f (b)
36 w r i t e ( ∗ , ∗ ) ’Complex: f(c) = ’ , f ( c )
37 End Program main
This chapter gives an example of how computations are used to model the pop-
ulation dynamics of biological systems. It employs some fairly simple discrete
mathematics that leads to some unusual nonlinear behaviors to explore. One-
dimensional arrays are used to bin store the results of the simulations, with the
arrays then written to a file and visualized with Gnuplot. This chapter introduces
no new Fortran tools, but instead reviews a number of previously introduced tech-
niques. So even though there is no advanced material in it, we mark this chapter
as optional since it may be skipped without interrupting the logical flow.
As is true with much in nature, insect populations do not appear to follow any
simple patterns. At times they appear stable, at other times they vary periodically,
and at still other times they appear chaotic, only to settle down to something simple
again.1
We look to the simple model of radioactive decay and growth for guidance.
1 We actually use chaos as a technical term meaning complicated behavior in which there does not appear to
be any order, but in which there is some simple mathematical description [CP 05].
338 CHAPTER 19
Notwithstanding the simplicity of (19.5) with its one variable x and one
parameter µ, it leads to surprisingly complicated behaviors. This is a consequence
of its being a nonlinear equation in which the variable x occurs to the second
power. It is called the logistics map [Rash 90], and your problem is now reduced
to exploring the properties of (19.5).
DISCRETE MATH, ARRAYS AS BINS; NONLINEAR BUG DYNAMICS* 339
1.0 1.0
0.8 0.8
0.6 0.6
xn xn
0.4 0.4
0.2 0.2
A B
0.0 0.0
0 10 20 30 0 10 20 30
n n
1.0 1.0
0.8 0.8
0.6 0.6
xn xn
0.4 0.4
0.2 0.2
C D
0.0 0.0
0 10 20 30 0 10 20 30
n n
Figure 19.1 The insect population xn versus generation number n for various survival rates: (A)
µ = 2.8, a period-one cycle; (B) µ = 3.3, a period-two cycle; (C) µ = 3.5, a period-
four cycle; (D) µ = 3.8, a chaotic regime.
Rather than do some fancy mathematical analysis [Rash 90] to determine proper-
ties of the logistics map (19.5), study it directly on the computer. Write a simple
program that uses the logistics map to produce a sequence of population values xn
as a function of the generation number n. Start with a seed population x0 = 0.75
and plot up xn versus n for µ = (0.4, 2.8, 3.3, 3.5, 3.8). The last four simulations
should yield results similar to those in Figure 19.1.
Extinction: If the survival rate is too low, the population dies off.
Two and three cycles: At two-cycle fixed points, the population jumps back and
forth between two semistable x∗ values. At three-cycle fixed points the population
340 CHAPTER 19
jumps between three x∗ values. These attractors occur only for µ > 3.
Intermittency: Try to find solutions for 3.8264 < µ < 3.8304 in which the
system appears stable for a while but then jumps all around, only to become stable
again.
Chaos: The system’s behavior in the chaotic region is critically dependent on the
exact value of µ and x0 . Systems may start out much the same but end up quite
different. Compare the long-term behaviors of starting with the two essentially
identical seeds:
x0 = 0.75, x0 = 0.75(1 + ), (19.7)
where 2 × 10−14 for a double-precision calculation. Repeat the experiment
with x0 = 0.75, but with what should essentially be two identical survival para-
meters:
µ = 4.0, µ = 4.0(1 − ). (19.8)
1.0
0.8
0.6
xn
0.4 0.39
0.37
0.2 0.35
0.33
3.52 3.55 3.58
0.0
1.0 2.0 3.0 4.0
µ
Figure 19.2 The bifurcation plot, attractor populations versus survival rate, for the logistics map.
Listing 19.1 gives our basic program for producing the data for a bifurcation dia-
gram. Computing and watching the population change with each generation gives
a good idea of the basic phenomena. However, it is hard to discern the simple and
beautiful behavior that lies within these complicated behaviors. One way to gain
such understanding is to concentrate on the semistable population values x∗ that
the system jumps among over time. These are called attractors to indicate that the
system is somehow attracted to these populations.
Create your own version of Figure 19.2 using Gnuplot. To get an idea of how many
points may be needed, let us assume that your screen resolution is ∼100 dots per
inch and that your laser printer’s resolution is ∼300 dots per inch. This means that
you are plotting approximately 3000 × 3000 10 million elements. Beware: this
will take a long time to print and require more memory than some printers have
available.
342 CHAPTER 19
Binning
1. Break up the range 1 ≤ µ ≤ 4 into 1,000 steps and loop through them. These
are the “bins” into which we will place the x∗ values.
2. In order not to miss any structures in your bifurcation diagram, loop through a
range of initial x0 values as well.
3. Wait at least 200 generations for the transients to die out, and then print out the
next several hundred values of (µ, x∗ ) to a file.
4. Print out your x∗ values to no more than three to four decimal places. You will
not be able to resolve more places than this on your plot, and this will keep your
output files smaller by permitting you to remove duplicates2 . Another approach is
to remove two successive xn values that differ only beyond the third place. We do
that in the sample code Bugs.f90 by taking advantage of the fact that xn is in the
range
0 ≤ xn ≤ 1. (19.9)
For this reason, before we write out to a file, we multiply our xn ’s by 1,000, cast
them as integers, and compare with the previous xn . If they are not equal, then we
know the xn value differs in the first three decimal places from the previous xn
value.
5. Plot up your file of x∗ versus µ. Use small symbols for the points and do not
connect them.
6. Enlarge sections of your plot and notice that a similar bifurcation diagram tends
to be contained within portions of the original (this is called self-similarity).
8. Inspect the way this and other sequences begin and then end in chaos. The
changes sometimes occur quickly over a very short range of µ, and so you may
have to make plots over a very small range of µ values to see the structures.
9. Close examination of Figure 19.2 shows regions where a very large number of
populations suddenly change to very few populations with a slight increase in µ.
Whereas these may appear to be artifacts of the video display, this is a real effect
and these regions are called windows. Check that at µ = 3.828427, chaos turns
into a three-cycle population.
Name f (x)
Logistics µx(1 − x)
Tent µ(1 − 2 |x − 1/2|)
Ecology xeµ(1−x)
Quartic µ[1 − (2x − 1)4 ]
Only nonlinear systems exhibit unusual behavior like chaos. Yet systems are non-
linear in any number of ways. Table 19.1 has maps that you may use to generate
xn sequences and bifurcation plots.
Chapter Twenty
2-D Arrays: File I/O, PDE’s; Realistic Capacitor
The main purpose of this chapter is to get more experience with arrays, and espe-
cially with the large 2-D ones used to solve realistic problems. As is often the case
with realistic problems, no analytic solution exists and we must employ a variety of
techniques to solve our problem. These include breaking space into a discrete lat-
tice and applying a simple algorithm to solve a partial differential equation (PDE),
file I/O, and 3-D visualization of numerical data using gnuplot. The simplicity
of the solution follows from the use of large arrays that permit us to manipulate
thousands or millions of variables with just a few lines of Fortran code.
Figure 20.1, adapted from a first-year physics text, shows an idealized parallel-
plate capacitor on the left. The equal spacing and single direction of the electric-
field line (arrows) indicate that the field is uniform. On the right is a photograph of
the electric field between the plates of a realistic parallel-plate capacitor, visualized
by small pieces of thread suspended in oil. Observe how the field fringes out near
the ends and extends beyond the ends of the capacitor. Textbooks usually analyze
the ideal capacitor because only it can be treated analytically.
Problem: Determine and visualize the electric field within and surrounding a
realistic capacitor, and compare to Figure 20.1.
Capacitors are devices with the capacity to store electric charge. They usually
consists of two conductors of similar shape separated by a small gap, with equal—
but opposite–charge on each conductor. Because the electric field, which would
otherwise extend over all of space, is condensed to the region between the plates,
capacitors are also called condensers.
V −V V −V
Figure 20.1 Left: Electric-field lines betweens the plates of an ideal parallel-plate capacitor. The
equal spacing and single direction indicate a uniform field. Right: A representation
of the field between the plates of a realistic capacitor. The field tends to “fringe” and
extend beyond the ends of the plates.
that keeps the top plate at 100 volts and the bottom one at -100 volts. To permit
a solution to this capacitor, we need to contain it in a limited space, which we do
by placing it inside a charge-free box made from wires that are “grounded” (kept
at 0 volts). After we solve this problem, we may make it more realistic still by
enlarging the box so that it has no effect on the field near the capacitor. This is
little work for us, but much more work for the computer.
V(x,y )
100
100 V 50
- 50
- 100 V
- 100
0
10 40
0V 20 30
x 30 20 y
40 10
0
Figure 20.2 Left: A parallel-plate capacitor within a grounded box. A realistic capacitor would have
the plates closer together in order to condense the field. Right: A visualization of the
electric potential for this geometry. The contours projected onto the xy plane give the
equipotential surfaces.
346 CHAPTER 20
Rather than solve for the electric field E(x, y), we solve for the electric potential
V (x, y). This is easier because V is a scalar while E is a vector, and because the
equations for V are simpler. Insofar as the field E equals the derivative (gradient)
of V , the two solutions are equivalent. (Electric-field lines are perpendicular to
equipotential surfaces and run from higher to lower potential values.)
∂ 2 V (x, y) ∂ 2 V (x, y)
+ = 0. (20.1)
∂x2 ∂y 2
This is called Laplace’s equation, in honor of the genius who first did those math-
ematical manipulations. The rounded Ds in (20.1) indicate that the derivatives are
partial not ordinary. The reason this is a partial DE is that the potential function
V (x, y) is a function of both x and y . We cannot solve the x behavior without
simultaneously solving for the y behavior. The real world is full of such equations.
The simplest method for solving our PDE is illustrated in Figure 20.3 and is known
as a finite-difference technique. There we see on the left a grid of x and y values,
each uniformly spaced by a step size ∆x = ∆y = ∆. Rather than trying to find a
solution for the continuous range of all possible values of x and y , we try to find
the solution only for the finite number of values that lie on the nodes of the grid.
Yet even for the small 100 × 100 grid, this requires solving for 10,000 unknowns.
Though not a trivial problem, the use of arrays makes it simple.
Figure 20.3 Left: The capacitor’s field is computed only for those (x, y) values on the grid. The
voltage of the plates and containing box are kept constant. Right: The algorithm
for Laplace’s equation in which the potential at the point (x, y) = (i, j)∆ equals the
average of the potential values at the four nearest-neighbor points.
1. Start with an initial guess V (x, y) = 0 every place except on the plates.
2. To obtain an improved guess, apply (20.4) to all points in space, except the
plates and box.
3. Keep applying (20.4) to obtain an even more approved guess until the im-
provement becomes smaller than some preset level of tolerance.
There is no guarantee that this relaxation method converges for arbitrary choices
348 CHAPTER 20
45 imax =101
46 tmax =1001
47 c a l l s o l v e ( tmax , imax )
48 End Program L a p l a c e F i l e
The pseudocode for our solution involves an outermost loop for iterations,
and inner loops over imax x and y values:
1 s e t p o t e n t i a l = 0 on s u r r o u n d i n g a r o u n d box
2 s e t p o t e n t i a l = 1 0 0 , −100 on u p p e r , p l a t e s
3 r e p e a t 1000 t i m e s
4 f o r imax x s p a c e s t e p s
5 f o r imax y s p a c e s t e p s
6 V = average of 4 n e a r e s t neighbors
7 k e e p p o t e n t i a l on box and p l a t e s f i x e d
8 write V matrix to a f i l e
This algorithm is well suited to the use of arrays because the indices vary,
but not the equations. This means, as we see in Listing 20.1, that it does not
take too many lines of code to implement. We store the potential V (x, y) in an
array V(i,j), with the first index spanning all possible x values and the second
index corresponding to all possible y values (measured in steps of ∆). The array is
declared as V(imax,imax), and we set imax = 101 steps for the sample program.
The voltages of the capacitor plates are kept fixed, while the boundary conditions
for the box are imposed on lines 11-16.
The only tricky parts in LaplaceFile.f90 are ensuring that we do not let
the algorithm change the value of the externally-applied voltages, and that we do
specify any indices that lie outside of the array. Once there are no errors, we just
let the program repeat itself tmax=1001 times and relax into what we hope will be
a stable value for the potential.
its output should be. For that purpose, make a copy LaplaceFile.f90 to your
personal directory and read through it to get a general idea of what it does.
• Use gnuplot (or whatever you have available, such as Dislin) to construct a 3-D
surface plots of the potential versus both x and y . Experiment with the options
to create the best visualization. We show you how to do this with Gnuplot in
§11.3, with the explicit command given in § 11.3. Your plot should look like
Figure 20.2. The height of the surface represents the value of the potential V (x, y)
for the x and y values along the horizontal plane. Take stock of how the potential
of the bounding box is always zero, and that of the plates are 100 and -100 volts.
On the horizontal plane we have placed contour lines that correspond to curves
along which the potential is constant. These contours are also called equipotential
surfaces. In general, the field is seen to be compressed between the plate and to
vary more slowly outside the plates than within them.
• This program opens a file called UNIT=1, writes to it, and then closes the file.
The REPLACE option on the open statement indicates that the old version of the file
will be written over, while the KEEP option on the close command ensures that the
file written to disk remains after the program stops executing.
20.5 EXPLORATION
• The program LaplaceFile.f90 assumes that the potential must have relaxed to
its final value after 1000 iterations. Decide if this is a good assumption:
2-D ARRAYS: FILE I/O, PDE’S; REALISTIC CAPACITOR 351
80
60
40
20
0
50 -20
45 -40
-60
40 -80
35
30
25 x Position
20
15
10
5
0
0 5 10 15 20 25 30 35 40 45 50
x Position
Figure 20.4 Contour plot of equipotential surfaces. The electric field lines are perpendicular to these
contours and point toward lower potential.
and print out the value of trace for each iteration. If trace changes in the sixth
decimal place, you probably have five good places of precision.
c. Now modify the program so that it always obtains at least three places of
precision. Define tol = 0.001 as the desired relative precision and modify
LaplaceFile.f90 so that it stops iterating when the relative change from one
iteration to the next is less than tol:
trace - traceOld
< tol. (20.6)
traceOld
• Now that you know the code is accurate, make it simulate a more realistic capac-
itor in which the plate separation is 1/10th of the plate length. You should find the
field more condensed between the plates.
352 CHAPTER 20
• Compare the results of your simulation to the sketch on the right of Figure 20.1.
Whereas we are computing the electric potential while the sketch is of the electric
field, some processing is necessary. We make use of the fact that the electric field
lines point from regions of higher to lower potential, and that the electric field lines
are perpendicular to the equipotential surfaces (the contours in our plots). Though
you may try to draw lines perpendicular to the contours projected onto the base of
the 3-D plot, it would be easier to look down directly onto the base. Make a 2-D
graph, like Figure 20.4, of just the contour lines. The needed gnuplot commands
are gnu> set nosurface
gnu> set view 0,0,1
• Draw in the electric field lines by hand, starting from the plate at -100 volts,
always keeping the field lines perpendicular to the equipotential surfaces and going
downhill.
Our solution for the capacitor is general and realistic. However, our model is only
two dimensional (the “plates” are lines not squares). Extend LaplaceFile.f90 so
that the plates have finite dimensions in both the x and y directions. You will now
have to solve for V (x, y, z), and make three, 3-D surfaces of V (x, y, z) versus
x − y , x − z , and y − z .
In the 1980’s Donald Knuth created a revolutionary computer program called TEX
(“tech”) for producing book-quality technical documents [Knuth 86] that rivaled
the documents produced by a professional human typesetter. In 1985 Leslie Lam-
port combined a number of TEX commands into a set of higher-level macros
known as LATEX [Lap 85] that has fewer details to worry about than TEX. At
present LATEX is widely used for scientific journals, books, and reports, and for
good reason. LATEX automatically generates tables of contents, lists of figures,
cross-references, equations, section and figure numbers, indexes, and bibliogra-
phies. Nevertheless, it is the mathematics that LATEX does better than any other
electronic system. This chapter describes enough of the basic elements of LATEX for
you to produce your own beautiful-looking scientific documents [Wilk 95].
The basic steps for using LATEX are shown in Figure 22.1. It is seen to be
quite similar to compiling and running a code, and so makes a useful last part for
this book. By convention, the LATEX source file has a .tex extender and the com-
piled version of the source has a .dvi extender. We have called our source file
Paper.tex and the compiler has produced the device-independent file Paper.dvi
from it. A .dvi file is independent of any specific computer system or hardware,
and is viewed on a computer screen with a program known as a viewer, or con-
verted to a PostScript (.ps) or Portable Document Format (.pdf) file to be sent to
a printer or posted on the Web.
358 CHAPTER 22
xdvi
compile yap View
Source Compiled dvips
Code Code dvipdf
% latex Paper.tex Print
(Device Independent)
Figure 22.1 The steps followed and utilities used in preparing a document with LATEX. The source
file is Paper.tex, the device-independent file is Paper.dvi, and the file ready for
printing/posting is Paper.ps or Paper.pdf.
The theory behind LATEX is that authors should worry about the contents of a
document and leave the format up to the computer. In practice there are a number
of steps to follow before authors see their documents typeset. This is in contrast
to WYSIWYG (what you see is what you get), in which the formulas appear on the
computer screen as you enter them. We personally prefer a markup-language ap-
proach for complicated documents, especially if that document is to be placed in a
digital library. We find that not having to concentrate on how things look until after
the writing is over lets us get the hard part of creation done first. However, there
are a number of LATEX commands to learn, and debugging complicated equations
can be challenging. Nevertheless, a thing of beauty is a joy forever.
1 \ documentclass [ o p t i o n s ]{ classname }
2 ...
3 P a r t I : preamble
4 ...
5 \ b e g i n { document }
6 ...
7 P a r t I I : a c t u a l document
8 ...
9 %%\end { document }
The first part is the preamble, and it starts with a statement of the type of document
your document is to be. The choices, classname = article, report, book,
slides, or letter, seem to cover most everything. Older versions of LATEX started
with a \documenttype command, but the newer LATEX 2e uses the \documentclass
command. The [options] argument might include the font sizes (in points)—
10 pt (default), 11 pt, or 12 pt—as well as onecolumn (default), or twocolumn,
oneside or twoside, or landscape. With \documentclass{article} you obtain
a document in 10 pt font. The preamble might also include macros (commands)
that you have defined for your own use, and commands for including special pack-
ages, for example, for dealing with graphics.
\documentclass{article}
\begin{document}
We have left off anything fancy, like title page, from the
preamble and used an enumerated list environment
(\tell{enumerate}), with mathematics environment inserted as
needed. An \emph{Environment} usually begins with
\verb+\begin{name}+ and ends with \verb+\end{name}+.
\begin{enumerate}
\begin{enumerate}
\item Use this sequence to simulate a random walk and determine
if the distance from the origin $R = \sqrt{N}$.
360 CHAPTER 22
\begin{equation}
\int_0ˆ1 \int_0ˆ1 {dx\,dy\over xˆ2+yˆ2}
\end{equation}
\end{enumerate}
This document consists of bits and pieces of a final examination given at Oregon State University.
The material is from the text Computational Physics [CP 05], which does not cost much $$.
We have left off anything fancy, like title page, from the preamble and used an enumerated list environ-
ment (enumerate), with mathematics environment inserted as needed. An Environment usually begins with
\begin{name}and ends with \end{name}.
Most of the characters in our input file Sample.tex are the same as in the output.
However, mathematical symbols, Greek, and some special characters are entered
with commands: the math symbols and Greek, because they do not appear on
the keyboard, the special characters because LATEX uses them within its own com-
mands.
Look at the commands in Sample.tex. You will notice that LATEX commands
usually consist of a backslash \ followed by a word. As an instance, we use \item,
\begin{equation}, and \emph{Computation Physics} respectively. √ The Greek
letter ψ was produced with \psi, and the mathematical symbol N with \sqrtN.
As we also see in these examples, the special characters { and } are used to
√
enclose the argument to a LATEX command. To illustrate, the is applied to N
via \sqrtN, and both the words Computational and Physics are emphasized by
\emph{Computational Physics}. Of special importance in this file is the dollar
sign $. When used as part of the text to indicate a dollar sign, it is entered as \$.
When used as part of LATEX command to switch between text and math modes, it
is entered as $, for example:
coupled wave functions $\psi_1$ and $\psi_2$ coupled wave functions ψ1 and ψ2
Special Characters
The characters
# $ % & ˜ ˆ \ { }
are called “special characters” because LATEX uses them for its own purposes. This
means that you cannot use them unless you do something special. If you simply
want the special character to be printed just as any other letter, include a \ in front
of the character:
$ \$
There are two exceptions to this rule. You cannot produce \ via \\, because
LATEX uses \\ to indicate the end of a line. So produce it by typing $\backslash$:
\ $\backslash$
362 CHAPTER 22
The second exception is the tilde. Seeing that \˜ means “place a tilde accent over
the following letter,” a ˜ is produced by \˜{}, that is, having nothing there (empty
braces) for the tilde to go over:
˜name \˜{}name
Look now at the two short paragraphs below the headings in Sample.tex. A new
paragraph is indicated by one (or more) skipped lines. LATEX then automatically
indents the paragraph as appropriate for its place in the document, for example, it
does not indent at the beginning of a new section. To ensure that our first paragraph
after the table is not indented, we placed a \noindent command there.
Though you should not have to do this for most of your work, sometimes
you do need to insert a horizontal or vertical blank space in your document. You
request that LATEX does that (a “request” because LATEX has its own ideas about
spacing, and it gets the last word) with the \hspace{} and \vspace{} commands.
You become more insistent by using the \hspace*{} and \vspace*{} forms. These
commands take the length of the space as an argument in the braces. The length is
specified with a number of dimensional units that include:
ex em pt pc in cm mm
Here, ex and em are the sizes of a typeset x and m, pt and pc are the typesetting
measures of points and picas, and the others are obvious.
If you want to insist on a line ending someplace and a new paragraph begin-
ning, then you insert a double backslash \\ to end the line. In addition, you add
some extra blank space after the line by including an argument to \\. To illustrate,
we place \\*[3ex] here,
and you see that it skips three ex’s of space before printing this line.
Usually LATEX decides where to start a new page according to its own internal
rules. As an example, it tries not to split up tables or place the last line of a
paragraph on a new page. If you disagree with LATEX’s decision and wish to force
a page break, use:
\renewcommand{\baselinestretch}{1.75}
where we have set the spacing to one and three-quarter lines. The command then
holds for the entire document. (You may try to reset the spacing locally, but that
may mess up the length of the page.)
Despite most of us never worrying about such things, LATEX is fairly serious when
it comes to quotation marks and dashes. This is a consequence of its being a
typesetting program, and typesetters are very serious about such things. When
writing in LATEX , we usually place a word in quotation by placing two left quotes
on the left side and two right quotes on the right. As a case in point, the quotes in
“golfballs appear to ‘drop out of the sky’ near the end of their trajectories”
Scrutinize how the left double quote “ is entered as two left single quotes in succes-
364 CHAPTER 22
sion, ‘ and ‘, and the right double quote is entered as two right single quotes, ’ and
’. As a general rule, one should not use the (undirected) ‘double quote’ character
" on the keyboard. (Some text editors, like emacs, automatically substitute either
“ or ” when you enter " if they know you are entering a LATEX document.)
The basic theory behind LATEX is that the user should worry about content and
let the program worry about presentation. So it follows that you should tell
LATEX whether you want some material to be emphasized, or emboldened, or
presented as mathematics, but you should not have to worry about the name or
size of the actual font being used. To give an instance, you emphasize text, and
LATEX usually reacts by placing that text in italic font. However, LATEX uses a dif-
ferent italic font for text than it does for mathematics; for example, this (math)
is different from this (text).
By default, LATEX uses the Computer Modern fonts, which give a character-
istic look to LATEX documents. If you really want some material to have a certain
presentation that differs from LATEX’s standard, then you may have to change some
things “by hand” or develop some macros. However, those occasions should be
rare and should be done only at the last minute before final presentation. The
words you wish to have in a specific format are usually given as the arguments, for
example:
If you are working with someone else’s document, you may run into some old style
commands for font changes. Though not strictly LATEX 2e, these still work:
LATEX FOR TEXT: SCIENTIFIC DOCUMENT PROCESSING, MARKUP LANGUAGE 365
Type Sizes
# \# $ \$ % \% & \&
\ $\backslash$ \ \verb’\’ ˆ \verb’ˆ’ ˆ \char94
ˆ \ˆ{} ˜ \char126 { \{ } \}
\_ œ, Œ \oe, \OE æ, Æ \ae, \AE r a, r A \aa, \AA
ω, Ω \o, \O ł, Ł \l, \L ß \ss ¿ ?‘
¡ !‘ † \dag ‡ \ddag § \S
P \P c \copyright £ \pounds
366 CHAPTER 22
22.6 ENVIRONMENTS
22.7 LISTS
The numbers or bullets are provided automatically by LATEX , so all the user has to
do is separate items by an \item command:
1. This is a numbered list, but you need not enter numbers.
2. This second item contains math sin2 x + cos2 x = 1.
\begin{enumerate}
\item This is a numbered list, but no numbers are entered.
\item This second item contains math $\sinˆ2 x+\cosˆ2 x =1$.
\end{enumerate}
LATEX FOR TEXT: SCIENTIFIC DOCUMENT PROCESSING, MARKUP LANGUAGE 367
Sublists are created just by starting another list within an existing list.
LATEX generates yet different symbols for sublists:
1. First item in list
a. First item in sublist
b. Second item in sublist
2. Second item in list
\begin{enumerate}
\item First item in list
\begin{enumerate}
\item First item in sublist
\item Second item in sublist
\end{enumerate}
\item Second item in list
\end{enumerate}
Text Tables
Tables are produced in the LATEX text mode by entering the tabular environment.
It is entered via \begin{tabular}{...}, and exited via \end{tabular}. The table
is placed in the text at the location in which it is entered. If you want a table that
is numbered, that has a caption, and that can be referenced, then you insert your
\tabular commands between a set of \table commands. We describe that later.
\begin{tabular}{|l||c|c|r|}
\hline\hline \textbf{Description} & \textbf{Data Types} &
\textbf{Size} & \textbf{Examples} \\*[2ex] \hline
single character & \tell{char} & 2B & {a, e, I, \$, 6} \\
integer & \tell{byte, short, int, long} & {1, 2, 4, 8 B} & 12, -30, -128, 127\\
floating point & \tell{float, double} & {4, 8 B} & {9.34F, 7.2867}\\
logical & \tell{boolean} ($\leq,\geq$) & 1 bit&true or false\\
\hline
\end{tabular}
The argument in braces after the \begin{tabular} command specifies the format
for the columns in the table. The l indicates that the first column is left-justified.
368 CHAPTER 22
The two c’s indicates that the next two columns are centered, and the last r in-
dicates that the fourth column is right-justified. The vertical bars | are optional
and instruct LATEX to place vertical bars in the columns indicated. The fact that we
have bars before the first column and after the last means that we want bars on the
outsides of the table.
Peer at how we have two \hline commands before we enter the data, a
single \hline command after we enter the column headings, and a single \hline
command after we have entered all the data. These commands cause the horizontal
lines in the table to be drawn. They too are optional and must be placed after a
row separator \\ or before the rows begin.
Data are entered into the table one row at a time. Each row ends with a
double backslash \\, and the columns are separated by an ampersand character &.
Mathematical symbols or equations are placed in the table by switching to math
mode, which we did with ≤ and ≥.
You do not have to specify the number of rows in your tables; LATEX will
know when you are done from the \end{tabular} command. In the present exam-
ple we end the last row with a \\. Normally that is not necessary, but we include
it because we have a \hline command to follow. If you need some more vertical
space between two rows, include a space option such as \\*[2ex] to end a row.
We did that after the heading.
Floating Tables
In published books and journals, tables and figures often “float” on the page. This
means that they are placed where they fit in best, which is often not at the place
where they are first mentioned. Clearly, this becomes more important as your table
or figure gets larger and harder to fit in someplace. Table 22.1 is an example of a
floating table. It is produced with the commands:
Inspect how the table is made by inserting the standard \begin{tabular} and
\end{tabular} pair within a \begin{table} and \end{table} pair. In addition,
there are \caption{} and \label{} commands within the table environment but
outside of the tabular environment. The argument to \caption contains the caption
that appears under the table. (If the caption command appears before the tabular
command, the caption will be above the table.) The argument to \label is a tag
that is used to reference the table with the \ref command (the numbering is done
automatically):
22.8 SECTIONS
and
Subsections
and
Subsubsections
LATEX permits you to have sections, subsections, and subsubsections in your doc-
uments. You give each a title, and LATEX gives each a sequential number, which
changes automatically as other sections are inserted or removed, and a different
sized heading. By way of example, the section, subsection, and subsubsection
right above this paragraph were produced with the commands:
Placing an asterisk before the title of the section or subsection will suppress
LATEX ’s automatic numbering, as in \section*{A Section without a Number}.
LATEX contains two commands for setting off text from its surroundings. The quote
environment is used for short quotations, while the quotation environment is ap-
propriate for longer ones. They differ in indentation:
Footnotes are created with the \footnote{text} command. You place the
command where you want a reference to the footnote, and LATEX automatically
places a reference there and sets the note at the bottom of the page. For instance,
we place a footnote here2 with \footnote{Sample note with its own period.}.
You should find it below and below a horizontal line.
In addition to dollar signs, you may also use \( and \) to mark the beginning and
the end of a mathematical formula or symbol embedded in text:
√
R varies as R ∝ N \(R\) varies as \(R \propto \sqrt{N}\)
Though probably just a matter of taste, we find it easier to read and edit a
LATEX source file when there are dollar signs in the text; to us, the \( and \) look
too much like part of the equation.
−h̄2 d2 ψ(x)
+ V (x)ψ(x) = Eψ(x). (23.1)
2m dx2
Check that this equation has a number on the extreme right (automatically assigned
by LATEX) and a period for punctuation (put there because we prefer equations with
372 CHAPTER 23
\begin{equation}
{-\hbarˆ2 \over 2m} {dˆ2 \psi (x)\over dxˆ2} + V(x)\psi(x) = E \psi(x).
\end{equation}
\[
{-\hbarˆ2 \over 2m} {dˆ2 \psi (x)\over dxˆ2} + V(x)\psi(x) = E \psi(x).
\]
Most characters have their standard meaning in math mode. However, letters used
as symbols appear in a special mode of italic, and function names and subscripts
appear in Roman. The special characters, already discussed in §22.3, are entered
in math mode as:
The spacings between math symbols will be different than the spacings in text
mode and are designed to make the mathematics clearer. As always, LATEX ignores
extra spaces or carriage returns in the your source file, unless you force the issue.
This means that you may insert extra spaces in your source file for clarity, or
distribute your equations over several lines. LATEX will put it all together and make
it look nice. If you insist on inserting spaces (not worth the trouble unless you are
publishing the document). For example, if you enter $xy$you get xy , otherwise:
Greek Letters
Greek letters are produced in math mode by preceding the full name of the letter
by a backslash \. For example, C = 2πr is input as $C = 2 \pi r$. The lowercase
Greek letters are obtained as:
LATEX FOR MATHEMATICS 373
For those that are different from their Roman counterparts, uppercase Greek letters
are obtained by capitalizing the first character of their names:
Relations
Negative Relations
Most negative relations are formed by including a \not command in front of the
normal relation:
≤ \not\leq ≡ \not\equiv
This is just \not placed in front of \leq and \equiv. In addition, the symbol = may
be formed in a number of ways:
Arrows
Math Parentheses
“Big” Operators
\sum \bigcap
! \bigodot " \prod
\bigcup
\bigotimes \coprod
# $ % \bigsqcup &
\bigoplus \int
\bigvee \biguplus \oint \bigwedge
Ix = m1 x21 + m2 x22
I_x = m_1 x_1ˆ2 + m_2 x_2ˆ2, or I_x = m_1 xˆ2_1 + m_2 xˆ2_2.
Inasmuch as the sub- and superscripts here are above each other, the two ways of
inputting are equivalent. If the sub- or superscript contains more than one charac-
ter, then the characters must be placed together within braces:
I_{11} = m_a x_{a,1}ˆ2 + m_b x_{b,1}ˆ2 or I_{11} = m_a xˆ2_{a,1} + m_b xˆ2_{b,1}
.
We have seen that LATEX sets mathematics in an italic font that is different from the
italics of text mode. You obtain Roman and bold fonts within math mode with the
commands \mathrm and \mathbf:
If you start running out of letters, why not try the uppercase calligraphic letters in
math mode: \,\cal{A}:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z.
In view of the fact that LATEX removes single blank spaces in math mode but not in
text mode, the two single spaces we placed within the box above will remain. Al-
ternatively, we could have inserted spaces with \ as x = 3,\ \mbox{for}\ y > 12}.
The basic mathematical functions are obtained by entering a backlash \ before the
name. To cite an instance, x3 sin y 2 is obtained from xˆ3 \sin yˆ2. Look at how
you need to leave a space after the function name as a separator, unless another
backslash follows. Available functions include:
23.8 FRACTIONS
To make a fraction with num over denom, use the \frac{num}{denom} command:
dx
v= dt v = \frac{dx}{dt}
LATEX FOR MATHEMATICS 377
Even though this LATEX command works fine, we prefer the simpler \over TEX
command:
dx
v= dt v = {dx \over dt}
23.9 ROOTS
√
The square root symbol N is obtained with the \sqrt{N} command.
LATEX automatically adjusts the height and lengths of root symbols to fit into the
equation and to span the argument:
√ √
a± b2 −4ac
x= z \sqrt{x} = {a \pm \sqrt{bˆ2-4ac} \over z}
Except for braces, which are used for commands, most normal-sized brackets or
delimiters are entered into mathematics as typed:
(( )) [[ ]] { \{ } \} || " \|
As an instance: {a} = (b) ∗ [c] + |d| × "e" \{a\} = (b)*[c] + |d| \times \|e\|
Just as it does for roots, LATEX scales the size of these delimiters to match the size
of the rest of the equation. However, since an equation may have a number of
nested brackets, LATEX needs some help in deciding just which brackets you want
to match. Thus, you give it help by tacking on the commands \left and \right to
the delimiters that you wish to match up:
1
√ = {a + ℵ}
z
In order for LATEX to do all the work for you in sizing and placing these
limiters, it demands that all the \rights be balanced by an equal number of \lefts.
LATEX does not demand that the types match up, just the number of rights and lefts.
So, for example, \left( may be paired off with \right]. Although this all makes
378 CHAPTER 23
Having LATEX arrange multiline equations is essentially the same as working with
the tabular environment for text. You place each equation on a separate line (row),
and then align the equal signs in each equation by placing them in the same col-
umn. To cite an instance, Sample.tex on the CD creates
−h̄2 d2 ψ1 (x)
+ V (x)ψ1 (x) + U (x)ψ2 (x) = Eψ1 (x) (23.2)
2m1 dx2
−h̄2 d2 ψ2 (x)
+ V (x)ψ2 (x) + U (x)ψ1 (x) = Eψ2 (x) (23.3)
2m2 dx2
\begin{eqnarray}
{-\hbarˆ2 \over 2m_1} {dˆ2 \psi_1 (x) \over dxˆ2} + V(x)\psi_1(x) +
U(x)\psi_2(x) &=& E \psi_1(x)\\
{-\hbarˆ2 \over 2m_2} {dˆ2 \psi_2 (x) \over dxˆ2} +
V(x)\psi_2(x) +
U(x)\psi_1(x) &=& E \psi_2(x)
\end{eqnarray}
Observe here that we display these equations with the equation-array environ-
ment eqnarray rather than the equation environment that we used for single-line
equations. We begin with \begin{eqnarray} and end with \end{eqnarry}. These
commands produce numbered equations. If unnumbered, multiline equations are
desired, they are produced with the \begin{eqnarray*} and \end{eqnarry*} forms.
The equations are entered into an eqnarray environment in the same way as they
would be with {equation}, except that the equal signs are enclosed by ampersands
&=&, and each line of the equation ends with a double backslash \\. As also occurs
in the tabular environment, this produces a column with all the equal signs aligned,
and permits there to be as many lines with equations as you enter.
\begin{eqnarray*}
- {dˆ2 \psi_1 (x)\over dxˆ2} - {dˆ2 \psi_2 (x)\over dxˆ2}
&+& V(x)\psi_1(x) + V(x)\psi_2(x) \\
&+& U(x)\psi_2(x) + U(x)\psi_1(x) \\
= && E \psi_1(x) +E \psi_2(x)
\end{eqnarray*}
⎛ ⎞ ⎡ ⎤
x x2 y α−µ β Γ
√
⎝ y xy z ⎠ ⇒ ⎣ δ β α+γ ⎦
3
z a z −1 i −x y λ
\left( \begin{array}{ccc}
x & xˆ2 & y \\
\sqrt{y} & xˆy & z \\
zˆa & zˆ{-1} & i \end{array} \right) \Rightarrow
\left[ \begin{array}{ccc}
\alpha - \mu & \beta & \Gamma \\
\delta & \betaˆ3 & \alpha + \gamma \\
-x & y & \lambda
\end{array} \right]
This is essentially identical to how tables are constructed for text. All that is new
is the use of large right and left delimiters to produce a matrix symbol that fits the
array. The alignment characters {ccc} are the same as with tabular.
We see that pmatrix takes care of its own delimiters and uses the carriage return
command \cr to end the rows.
Here too, our preference is the TEX command \cases, which we find simpler:
1, if x ≥ 0,
θ(x) =
0, if x < 0.
Most drawing and graphing programs have a number of options to determine the
file format in which to save graphics. Because LATEX is used to produce publication
quality typesetting, if you include graphics, then they too should be publication
quality. PostScript (.ps) and Encapsulated PostScript (.eps) figures are of publi-
cation quality, so it should not be a surprise that there are nice packages to include
these formats in LATEX documents.
We will discuss how to include .eps figures, with the same commands used
for .ps figures. Given a choice, use encapsulated figures, since it may be easier to
adjust their size to fit the document. If your figure is of a different type, you should
be able to open it in a drawing program and save it as an .eps figure. In addition,
we recommend that you embed the fonts used in your figure with the figure; this
does make for a larger file, but also avoids the possibility of some inappropriate
local font being substituted when the document is printed (especially likely if you
scale the figure).
ew
Vi
t
in
df
Pr
y a vi
r.p
xd
p
pe
Pa
ips
dv d f
s,
ip
r.p
dv
pe
Pa
e d
od le
C pi
om
t)
en
C
nd
pe
le
de
pi
In
vi
m
r.d
co
ex
e
ic
pe
r.t
ev
pe
Pa
(D
Pa
ex
od e
t
la
C urc
%
e
So
x e
r.t
pe
Pa
Figure 23.1 A scaled-down and rotated Figure 9.1.
may be added. Before you use a package, you must include it in your document’s
preamble (the part before the \begin{document}command):
\usepackage[dvips]{graphicx, color}
\begin{figure}
\begin{center}
\includegraphics[angle=45, scale=0.35]{Latex_Compile.eps}
\caption{A scaled-down and rotated
Figure˜\ref{fortran_compile.eps}. \label{sample.fig}}
\end{center}
\end{figure}
The figure environment is standard LATEX. It is also used to draw pictures with
LATEX, or to leave room for and label figures to be pasted in later (use \vspace
to make the room). The \includegraphics command is placed within the figure
environment. To ensure that the figure is centered on the page, we place the figure
in a center environment. The angle=45, scale=0.25 specification in square
brackets is optional and leads to a figure that is slanted and scaled to 25% of its
original size.1 The name of the figure Latex_Compile.eps is given in curly braces,
with a path indication if it is not in current directory. Scrutinize how after the
name of the figure we issue the \caption command containing the caption as its
argument. Within the caption’s argument (still within the curly braces) we have
placed the label command \label{sample.fig}. We then refer to this figure as
\ref{sample.fig}, as we do in the sample \includegraphics command above, and
let LATEX take care of its actual number.
1 We are able to scale and rotate with no loss in quality because PostScript figures are not bit maps, but instead
As an example of \psfig, examine Figure 15.1 (p. 290) with its multiple
parts:
\begin{figure}
\psfig{file=FIGS/planet.eps, height=1.85in} \hspace{6ex}
\psfig{file=FIGS/PlanetApplet.eps, width=1.5in}
\caption{\emph{Left: } The gravitational ....)}
\label{planet.eps}
\end{figure}
1. Enter Sample.tex as given in §22.3. Use a text editor and save the file as
Sample.tex. We recommend WinEdt and MikTex for Windows, and gnu xemacs for
Unix/Linux.
2. Compile the file by pressing the LATEX button or by issuing a command from a
shell:
> latex Sample.tex Compile latex source Sample.tex
If there are no errors in your file, you should get a fairly verbose response with
statements of the sort
3. The warnings that there is No file Sample.aux and that Reference ‘eq.1’
(‘eq.2’) undefined are to be expected on first compilation. The Sample.aux file
contains the information LATEX needs to cross-reference the source Sample.tex.
Yet LATEX does not write it until the end of compilation, and, consequently, it does
not yet know that you have defined references eq.1 and eq.2.
4. Compile the source file again. This time the compiler should find a Sample.aux
file to use for cross-references and not warn you about undefined references.
5. The last part of LATEX’s message tells you that the files sample.aux and
sample.dvi were written, and that the typeset document is one page long. If you
have changed some labels or references, then LATEX may request that you compile
the source file again in order to incorporate the updated .aux file.
6. If there were no errors, your working directory should now contain the files
LATEX FOR MATHEMATICS 383
7. If you are lucky enough to get a sample.dvi file, then look at it to admire your
work. On Unix you do this with:
> xdvi sample.dvi Preview .dvi file
8. If you get complaints that LATEX was not happy with the way a line fits on
the page, just ignore them unless you are really going to publish the paper. If
there are real errors, correct them one at a time and proceed. If you cannot figure
out where the error is, try forcing LATEX to skip it by continually entering Enter.
Alternatively, you isolate the location of an error by moving the %\end{document}
up in your document until LATEX compiles with no errors. Then move it down
gradually, recompiling at each stage until the error is uncovered.
This error message indicates with a carriage return where LATEX notices something
is wrong, in this case, that it has never heard of \iten. Below that, LATEX indicates
that it thinks you meant to write \item. In the second case where a $ is left off,
LATEX responds with
We see that LATEX knows something is wrong in the math environment (we left off
the second $, but it does not know it until the next math environment begins with
a \[ on line 17. Consequently, you need to look at line 17 in the source file, and
work back from there to see where there is a missing math delimiter.
384 CHAPTER 23
10. Once you have produced a complete .dvi file, you convert it into the PostScript
file sample.ps for printing with the dvips command:
> dvips -o sample.ps sample.dvi Convert .dvi file to .ps file
> dvips -o sample.ps sample Also converts .dvi file to .ps file
Here the -o option places the output into the file whose name follows. If you leave
off the -o option, then the .ps file might well be sent directly to some printer.
In WinEdt, the dvips command is issued by pushing the dvi $→ ps button. You
should get an output statement showing you all the page numbers that have been
converted, and indicating that the output is placed in the file sample.ps. There
is also the pslatex version of LATEX that uses PostScript fonts in place of LATEX’s
standard Computer Modern fonts. This does produce a smaller .ps file in the end.
11. If you want a .pdf file, you may issue the pdfLATEX command in the first
place, or use the dvipdf command to convert your .div file. However, if the .eps
figures in your file do not get placed in the .pdf file properly, we recommend the
use of Adobe Distiller to convert the entire .ps file to a .pdf one.
12. If your document does not contain any embedded PostScript figures, then you
may be able to print it successfully from the .dvi previewer. Otherwise, we have
found it best to create a .ps file of your document and to print that.
13. Now print your sample.ps file. You do that from a GhostScript viewer, such
as GSview, or with Unix printer commands:
14. Now let us go back and add some more features to Sample.tex:
\title{My Title}
\author{My Name \and My Friend\\ Our Institution}
\date{Someday}
\thanks{To those who have supported this noble effort with cash.}
LATEX FOR MATHEMATICS 385
After placing these commands in the preamble, you need to create the
title in the body of the document with:
\maketitle
Appendix A
Glossary
array (matrix) A group of numbers stored together in rows and columns that
may be referenced by one or more subscripts. Each number in an array is an
array element.
assignment statement Command that sets a value to a variable or symbol.
B Abbreviation for byte (8 bits).
b Abbreviation for bit or baud (1 bit/sec).
background (1) A technique of having a programming run at low priority (“in
background”) while a higher-priority program runs “in foreground.” (2) The
part of video display not containing windows.
base The radix of a number system. (10 is the radix of the decimal system.)
basic machine language Instructions telling the hardware to do basic operations
such as store or add binary numbers.
batch The running of programs without user interaction; often in background.
baud 1 bit per second.
binary Related to the number system with base 2.
BIOS Basic Input/Output System.
bit Contraction of “binary digit”; the digits 0 or 1 used in binary representation.
Boolean algebra A branch of symbolic logic dealing with logical relations as
opposed to numerical values.
boot To “bootstrap”; to start a computer by loading the operating system.
branch To pick a path within a program based on the value of variables.
bug A mistake in a computer program or operating system; a malfunction.
bus A communication channel (bunch of wires) used for transmitting information
quickly among computer parts.
byte Eight bits of storage. Java uses two bytes to store a single character in
extended unicode.
byte code Compiled code that is read by all computer systems, but still needs to
be interpreted (or recompiled) on each system. Contained in class file.
cache Small, very fast part of memory used as temporary storage between the
very fast CPU registers and main memory.
calling sequence The data and setup needed to call a method or a subprogram.
388 APPENDIX A
central processing unit (CPU) The part of a computer that accepts and acts on
instructions; where calculations are done and communications controlled.
checkpoint A statement within a program that stops normal execution and pro-
vides some output to assist in debugging.
checksum The summation of digits or bits used to check the integrity of data.
child Object created by presently existing parent object.
class A group of objects or methods having a common characteristic. Collection
of data types and associated methods. An instance of an object. Byte code
version of a Java program.
clock Electronics that generate the periodic signal to begin execution.
code A program or the writing of a program.
column The vertical line of numbers in an array.
column-major order The method used by Fortran to store matrices in which the
leftmost subscript varies most rapidly and attains its maximum value before
the subscript to the right is incremented. (Java uses row-major order.)
command A computer instruction. A control signal.
command key A keyboard key, or combination of keys, that performs a prede-
fined function.
compilation Translation of a program written in a high-level language into
(more) basic machine language.
compiler A program that translates source code from a high-level computer lan-
guage to machine language or object code.
concatenate To join together two or more strings, head to tail.
concurrent processing Same as parallel processing; simultaneous execution of
several related instructions.
conditional statement Statement to be executed only under certain conditions.
control character A character that modifies or controls the running of a program
(e.g., control +c).
control statement A statement within a program that transfers control to another
section of the program.
copy To transfer data without removing the original.
CPU See central processing unit.
GLOSSARY 389
modulo (mod) Function that yields only remainder after division of numbers.
multiprocessors Computers with more than one processor.
multitasking The system by which several jobs reside in a computer’s memory
simultaneously; may run in parallel or sequentially.
nesting Embedding a group of statements within another group.
object A software component with properties like physical objects. A combina-
tion of data (variables, properties) and methods (behaviors) to interact with
the data; and abstract data type containing multiple parts.
object-oriented programming A modular programming style focused on
classes of data objects and associated methods to interact with the objects.
object program (code) A program in basic machine language produced by com-
piling a high-level language.
octal Base 8; easy to convert to or from binary.
operating system (OS) The program that controls the computer and runs appli-
cations, processes I/O, and shells.
optimization The modification of a program to make it run more quickly.
overflow A number that is larger than the largest number a computer can store
accurately.
package A collection of related programs or classes.
page A segment of disk memory that gets read into central memory in one block.
parallel (concurrent) processing Simultaneous or independent processing in
different CPUs.
parallelization Rewriting an existing program to run on a parallel computer.
partition The section of memory assigned to a program during its execution.
physical memory The fast, electronic memory of a computer; main memory;
contrast to virtual memory.
physical record The physical unit of data for input or output that may contain a
number of logical records.
pipeline (segmented) arithmetic units Assembly-line approach to central
processing in which CPU simultaneously gathers, stores, and processed
data.
pixel A picture element, a dot on the screen. See also voxel.
GLOSSARY 393
To compile your Fortran file, consult the documentation on your specific compiler.
4 ! D e c l a r e an e x t e r n a l p r o c e d u r e t o add two i n t e g e r s :
5 I n t e g e r Function c add ( x , y ) ! Declare the function type
6 Integer :: x , y ! D e c l a r e dummy v a r i a b l e s
7 c a d d = x+y ! Perform f u n c t i o n o p e r a t i o n s
8 End F u n c t i o n c a d d ! P r o p e r l y end EACH p r o c e d u r e
9
10 ! D e c l a r e t h e main p r o g r a m :
11 Program H e l l o
12 ! C r e a t e an i n t e r f a c e t o u s e t h e ’c_add’ f u n c t i o n
13 Interface
14 Contains
15 I n t e g e r Function c add ( x , y )
16 Integer :: x , y
17 End F u n c t i o n c a d d
18 End I n t e r f a c e
19 I m p l i c i t None ! R e q u i r e s ALL v a r i a b l e s t o be d e c l a r e d
20 I n t e g e r : : i =1 , j =2 ! D e c l a r e w i t h i n i t i a l v a l u e s
21 R e a l ∗8 : : b , c
22 ! A s s i g n any o t h e r n e e d e d i n i t i a l v a l u e s
23 b = 1.57
24 c = sin (b) ! I n t r i n s i c s r e q u i r e no o t h e r r e f e r e n c e s
25 ! W r i t i n g t o t h e s c r e e n w i t h t h e d e f a u l t ’*’
26 w r i t e ( ∗ , ∗ ) ’sin(b)= ’ , c ! D i s p l a y s t r i n g and v a l u e o f c
27 w r i t e ( ∗ , ∗ ) ’i+j= ’ , c a d d ( i , j ) ! invoke function c add
28 End Program H e l l o
396 APPENDIX B
Naming Convention
Array References
Arithmetic Operators
Relational Operators
Logical Operators
Order of Precedence
Flow Control
The Maple and Fortran worksheets and programs given on the CD do not need
any special installation. You just need to pick a directory/folder on your computer
where you want them stored, and copy the appropriate folder from the disk into
that directory. Of course you will need to insert the CD into the CD drive, and
open that drive to see the contents of the CD. (On Windows computers you get to
that drive by clicking on the My Computer icon.)
FORTRAN QUICK REFERENCE 399
The Java programs on the CD are almost all source (.java) files and therefore need
to be compiled before they will execute. There are a number of ways in which you
may work with and execute our Java programs. The least painful is probably to
use a complete programming workbench like Code Warrior or the Forte Suite.
With these you need only punch some buttons to compile, debug, and execute
programs. We view these programming environments as powerful tools that will
increase the productivity of professional programmers. However, we believe that
the more basic approach is preferable for the purpose of this introductory book.
On Windows computers you may use a text editor such as Notepad to modify
Java source file. You should not, in contrast, use a word processor such as MS
Word, since it formats text by inserting control characters that are invisible to you
but stop the Java compiler from getting its job done. We prefer using the WinEdt
[WinEdt] editor on Windows, which also provides immediate access to a shell in
the same directory as the source (it is also excellent for LATEX).
Once you have your .java file open in an editor, you need a shell or com-
mand line from which to issue the javac and java commands. On Unix this is easy
if you first change to the appropriate directory and open your editor from there. It
is equally easy on Windows computers if you open a shell from your editor. How-
ever, if you use the Start > Run > Open > Command route, then you will have to
navigate the Window’s file directory structure with the dir and cd commands.
Bibliography
[Chap 04] C HAPMAN , S. J. (2004), Java for Engineers and Scientists, Second
Ed., Pearson, Prentice Hall, Upper Saddle River, NJ.
[ChapF 04] C HAPMAN , S. J. (2004), Fortran 90/95 for Engineers and Scientists,
Second Ed., McGraw-Hill, New York.
[Dav 99] DAVIES , R. (1999), Introductory Java for Scientists and Engineers,
Addison-Wesley, Harlow, UK.
[Eck 02] E CK , D. (2002), Introduction to Programming Using Java, Version 4.0,
(a free textbook), http://math.hws.edu/javanotes.
[Flan 97] F LANAGA , D. (1997), Java in a Nutshell, Desktop Quick Reference,
Second Ed., O’Reilly, Sebastopol, CA.
[F90 CSEP] T HE C OMPUTATIONAL S CIENCE E DUCATION P ROJECT, Fortran
90 and Computational Science, http://csep1.phy.ornl.gov/pl/pl.html.
[F90 UL] M ARSHALL , A. C. The University of Liverpool Fortran 90 Course
Notes, http://www.liv.ac.uk/HPC/F90page.html.
[Smit 91] S MITH , D. N. (1991), Concepts of Object-Oriented Programming,
McGraw-Hill, New York.
COMPUTATIONAL SCIENCES
[CP 05] L ANDAU , R. H., AND M. J. P ÁEZ (1997), Computational Physics,
Problem Solving with Computers, Wiley, New York;
L ANDAU , R. H., M. J. P ÁEZ , AND C. C. B ORDEIANU (2005), Computa-
tional Physics, Problem Solving with Computers, Second Ed., Wiley, New
York.
[G&T 96] G OULD , H., AND J. T OBOCHNIK (1996), An Introduction to Com-
puter Simulation Methods, Second Ed., Addison-Wesley, Reading, PA.
[Gar 00] G ARCIA , A. L. (2000), Numerical Methods for Physics, Prentice Hall,
Upper Saddle River, NJ.
[Knuth 86] K NUTH , D. E. (1986), The TeXbook, Addison-Wesley, Reading, PA.
[L&F 93] L ANDAU , R. H., AND P. J. F INK (1993), A Scientist’s and Engineer’s
Guide to Workstations and Supercomputers, Wiley, New York.
[Lap 85] L AMPORT, L., (1986), LATEX: A Document Preparation System, Second
Ed. Addison-Wesley, Reading, PA.
[LAP 95] A NDERSON , E., Z. BAI , C. B ISCHOF, J. D EMMEL , J. D ONGARRA ,
J. D U C ROZ , A. G REENBAUM , S. H AMMARLING , A. M C K ENNEY, S. O S -
TROUCHOV, AND D. S ORENSEN (1995), Lapack Users’ Guide, Second Ed.,
SIAM, Philadelphia; http://netlib.org.
402 BIBLIOGRAPHY
[Wilk 95] W ILKINS , D. R., Getting Started with LaTeX, Second Ed.,
http://www.maths.tcd.ie/˜dwilkins/LaTeXPrimer/,
(1995).
[Zach 96] Z ACHARY, J. L. (1993), Introduction to Scientific Programming, Com-
putational Problem Solving using Maple and C, Springer-Telos, Santa Clara,
CA.
MATHEMATICS
[A&S 64] A BRAMOWITZ , M., AND I. A. S TEGUN (1964), Handbook of Math-
ematical Functions, U.S. Govt. Printing Office, Washington.
[B&R 92] B EVINGTON , P. R., AND D. K. ROBINSON (1992), Data Reduction
and Error Analysis for the Physical Sciences, McGraw-Hill, New York.
[Fral 76] F RALEIGH , J. B. (1976), A First Course in Abstract Algebra, Second
Ed., Addison-Wesley, Reading, PA.
[Krey 88] K REYSZIG , E. (1988), Advanced Engineering Mathematics, Sixth
Ed., Wiley, New York.
SCIENCE
[D&A 00] D EGAUDENZI , M. E., AND C. M. A RIZMENDI, Wavelet-Based Frac-
tal Analysis of Electrical Power Demand, Fractals, 8, no. 3 (2000) 239–245.
[Feig 79] F EIGENBAUM , M. J. (1979), J. Stat. Physics 21, 669.
[Fein 76] G. F EINBERG, Phys. Rev. 159 (1976) 1089–1105.
[Feyn 63] F EYNMAN , R. P., R. B. L EIGHTON , AND M. S ANDS , (1963), The
Feynman Lectures on Physics §9.7.
[M&T 88] M ARION , J. B., AND S. T. T HORNTON (1988), Classical Dynamics
of Particles and Systems, Third Ed., Harcourt Brace Jovanovich, Orlando,
FL.
[R & M 93] R EITZ , J. R., F. J. M ILFORD , AND C HRISTY, R. W. (1993), Foun-
dations of Electromagnetic Theory, Fourth Ed., Addison-Wesley, Reading,
PA.
BIBLIOGRAPHY 403
WEB RESOURCES
Web pages change so often that we expect some of these URLs to fail. If so,
we suggest searching on the name.
[Black] The Java-Linux Porting Project, http://www.blackdown.org/.
[CPlets] Interactive Computational Physics Ap-
plets, http://www.physics.orst.edu/˜rubin/nacphy/CPapplets/,
http://www.physics.orst.edu/˜rubin/TALKS/CPtalk/DEMO/samples.html.