L09 - Fortran Programming - Part 1 1. Compiled Languages
L09 - Fortran Programming - Part 1 1. Compiled Languages
1. Compiled Languages
Thus far in this class weve mostly discussed shell scripting. Here we bring a bunch of different
utilities together into a recipe or a script. Once we do that we can execute the script and the job
runs. This is a very low level style of programming if you can even call it programming. Note,
that this Shell scripting relied almost entirely on programs that were developed by other people.
So, how do people develop these programs? The answer lies mostly in compiled languages
(although many programmers today are getting away from compiled languages). That is, most of
the programs we used were written in a language like C or Fortran.
Fortran is an example of a compiled language. What does this mean? It means that we write
code in human readable format. E.g.,
IF (variable == 10 ) THEN
write(*,*) The variable is 10
ENDIF
But, our computer does not have the capability to read such code. The shell might, but that takes
time. Instead we want to convert the above statement into something that the processor on our
computer can understand. Usually, the processor can understand instructions given to it in a
binary form, that we call machine language or assembly code. In the old days, one used to have
to write code in these rather obtuse looking machine languages, some people still do if they are
seriously interested in making their code run fast. But, eventually some people started writing
different codes, called compilers, that can convert a language that is easily readable by humans
into something that is easily readable by your cpu.
In short, a compiler is like a language translator. It converts the statements you make in a
language (a language like Fortran or C) to a language the cpu can speak.
In this class we will focus on the human readable language called Fortran 90. The reasons are
partly historical. In many of the physical sciences (geophysics, meteorology, etc.) most of the
original work was written in Fortran. Hence, we have a long history of Fortran codes in our
disciplines. But, Fortran still persists as a primary language in these fields. I have heard many
computer scientists express their dismay that Fortran is still used with exclamations of, I thought
that was a dead language. I think it ultimately comes down to the majority of computer
scientists these days spending their time on web apps instead of serious problems like simulating
the weather, or seismic wave propagation on the global scale, or gravity wave propagation across
the universe. Hence, my standby response, Fortran still produces the fastest executable code.
This makes a serious difference when you are talking about days or weeks of simulation time
versus months or years when trying to solve the same problem in something like Java. Fortran is
also quite simple for trying to solve mathematical problems that is what it was designed for.
Its not fancy. But it is powerful.
When we talk about Fortran programming it is important to distinguish which version of Fortran
we are referring to. You will see several versions (e.g., f66, f77, f90, f95 etc.) so a brief
background is in order. John Backus developed the first Fortran compiler in 1954 it was the
Geophysical Computing L09-2
first high-level programming language! Different versions of Fortran compiler were being
developed almost from the start and the need for some kind of standard became immediately
apparent. The first official ANSI standard was introduced in 1966 and Fortran 66 (f66) was born.
The next major standard was a huge improvement to the 1966 version and was released in 1978.
Because the standard was agreed upon in 1977 it was termed Fortran 77 (f77). This was a major
improvement to the standard and included much needed program elements such as IF THEN
ELSE blocks! The majority of older code you will encounter was written with the f77 standard
(although if you ever get any old seismology related code from Don Helmberger its likely still
written in f66).
Fortran Compilers
There are several different Fortran compilers on the market today. Some are free and others are
commercially developed. Their primary differences are related to (1) which features of the most
recent standard are included, and (2) how good are the optimizations (we will discuss what this
means in a later lecture). Some common compilers available on our systems are:
So, lets dive in with a really quick example. Open up a new file called myprog.f90 and type in
the following:
PROGRAM first
IMPLICIT NONE
This is about as simple of a Fortran code as can be written. The important points are:
IMPLICIT NONE is not required before the main part of the code is written, but it is
terrible, terrible practice to leave it out. More on this later!
write(*,*) says to write something to standard output (a fancy way to say write it out to
the screen).
So, how do we run this code? Well as noted above, it cannot be run until we compile it. In this
class we will use the g95 Fortran compiler. So, at the command line type:
What happens is that a new file called a.out is created (on some systems this may be named
a.exe). This new file which is created is in binary format (you cannot open it up with your text
editor and view its contents) and is an executable file. To run the program just type:
>> ./a.out
Before we move on, lets introduce our first compile flag: the o flag.
The o flag lets us name the executable file that is created. In this case we have a new file called
myprog.x. Note, Fortran 90 programs require a .f90 extension or else some compilers assume
the code is written with the f77 standard. The .x extension above is just my preferred extension to
let me know that I have an executable file. So, there you have it. You are now a Fortran
programmer.
Geophysical Computing L09-4
3. Numeric Variables
Creating variables in f90 programs is slightly more complicated than in Shell scripts. This is
because we have a few different types of variables we can use. The three main types you need to
worry about now are:
INTEGER These are just the set of integers (e.g., 0, 1, 2, 3, -1, etc.). Use integers for
counting, but dont for example use integers to do math like 1/3 because the result is not
an integer.
REAL The set of real numbers (for your normal mathematical operations).
There are other types of variables you may decleare as well (e.g., Complex) but most of what you
will do revolves around those three types.
In a f90 program we define our variables at the beginning of the program. For example:
IMPLICIT NONE
REAL(KIND=8) :: arg ! argument for trig functions
INTEGER(KIND=4) :: J ! looping variable
Note that in f90 programs we start writing comments with the exclamation point! We will
discuss what the KIND statement means in Section 5 of this lecture. But first, lets create a new
example and see how to assign variables.
PROGRAM variables
IMPLICIT NONE
! Define my variables
REAL(KIND=8) :: A, B ! some real numbers
INTEGER(KIND=4) :: J, K ! just a lowly integer
! Declaring integers
J = 10
J = J + 10
write(*,*) J =, J
Geophysical Computing L09-5
Never declare a real number without a decimal point in it! For example, we declared A = 10.0,
Never do this as A = 10 (without the decimal point). Why? Some Fortran compilers are buggy
and will give you A=10.2348712410246287 or some kind of similar garbage if you dont put the
decimal point there.
Another key point is that in Fortran variable names are not case sensitive:
PROGRAM casesense
IMPLICIT NONE
REAL(KIND=8) :: gH
gH = 10.0
Another fine point to make here is that in the older styles of Fortran programming (f77) one
didnt have to declare their variables at the start of the program. There were specific rules one
could follow. For example, if you created a variable name that started with an i then it was taken
to be an integer. Do Not do this. Writing code like this is an example of the worst of
programming practices. Always declare your variables at the beginning of the code. This will
trap many errors (some with very subtle effects) that may go unnoticed otherwise. In fact, writing
in the IMPLICIT NONE statement at the beginning assures that you will have to, as the
IMPLICIT NONE statement means that the compiler should expect all variables to be declared.
4. Arithmetic
In the examples above we already showed a slight arithmetic example. Just to clarify our options
in Fortran the following are out arithmetic operators:
Important Note: In Fortran (as in most programming languages) the arguments to the
trigonometric functions are expected to be in radians. If your arguments are in degrees you need
to first convert them to radians! For example: To take the sine of 45:
PROGRAM example
IMPLICIT NONE
REAL(KIND=8) :: argument, answer
REAL(KIND=8) :: pi
pi = 3.141592654 !Define pi
argument = 45.0 !My argument is 45 deg
One should at this point be excited. Remember how challenging it was to do math inside a shell
script. By comparison this is downright easy in Fortran.
5. Numeric Types
In our examples we have specified the naming of our variables in terms of KIND=4 or KIND=8.
What this means is that we use numbers that are stored with either 4- or 8-bytes. Lets take a
look at the following example to see what this means:
Geophysical Computing L09-7
PROGRAM simpletest
IMPLICIT NONE
INTEGER(KIND=1) :: J
J = 0
DO
write(*,*) J
J = J + 1
IF (J < 0) EXIT
ENDDO
This isnt a very complicated program, although we havent looked at DO or IF statements yet.
The program starts out with the variable J = 0, and starts a loop. It adds 1 to J at each step. So
that J = 0, then J = 1, then J = 2, etc.
Then it makes a test that says if J is less than 0 lets exit the program.
Run this program and write down that last value of J before it becomes < 0:_________________
Thats some odd behavior for sure. We keep adding a positive number to J and eventually J
becomes negative.
INTEGER(KIND=2) :: J
Now what was the number we got to before J became < 0:_______________________________
Definitely a bigger number. The important point is that we actually have to specify how much
memory to use to store the numbers. In the above two examples we used 1 or 2 bytes per integer
number. Recall that there are 8 bits per byte and that a bit is either a 1 or 0. So, a 1-byte or 8 bit
number might look like:
10010110,
11111111 = 127 + 126 + 125 + 124 + 123 + 122 + 121 + 120 = 255
However, we havent considered sign (i.e., + or -). So we need to use one bit to store the
numbers sign. Hence, the largest number we can store in an 8-bit integer is:
The largest 2-byte (16 bit) number possible is 32767, and so on.
Hence, if we are expecting to do some math with large numbers it is important to realize what the
biggest number our memory can hold. Real numbers are another story and we need to be
concerned with our precision. Remember that a true real number like 1/3 is 0.33333 where we
extend off into infinity. Well, a computer does not have infinite memory so we dont have true
real numbers in the computers representation, but just an approximation to them.
In general when doing mathematical operations we want to store our real numbers with 8-bytes
(KIND=8) or else we will start to notice some real precision problems especially when working
with trigonometric functions. However, programs will run faster with smaller storage space per
number (e.g., KIND=4) as we arent spending as much time writing numbers into memory. So,
we dont always want to go all out and use the largest KIND type available to us.
Fortran does provide an easy way to see what the largest available number is for the KIND type
you are using by supplying the HUGE intrinsic function. For example, in the example program
add the statement:
write(*,*) HUGE(J)
What is the largest number available for 8-byte integers? How about 8-byte reals?
6. More Information
It is not possible in these tutorials to describe all aspects of Fortran, or even to show you all of the
intrinsic functions that are available. Fortunately there are several good web sites available. A
couple are listed below:
7. Homework
1) Write a program that allows you to define the latitude and longitude at a point on the Earths
surface and will return the x-, y-, and z- Cartesian coordinates for that point. Assume the positive
z-axis goes through the geographic spin axis (N pole). Make sure your coordinate system is right
handed.
Geophysical Computing L09-9
2) By definition of the dot product we can find the angle between two vectors from the formula:
a b = a b cos
Write a program that will let you define the x-, y-, and z- coordinates of two vectors in a
Cartesian space and find the angle between the two vectors.
3) Combining the programs you wrote above write a program that will allow you to input two
latitude and longitude coordinates on the Earths surface and will return the angular distance
between the two points in degrees. Assume the Earth shape to be a sphere with radius = 6371.0
km. Also have the program return the distance (in both km and miles) between the two points on
the surface. This distance is the great circle arc distance.