An Introduction to Fortran

Document Sample
An Introduction to Fortran Powered By Docstoc
					An Introduction to Fortran
         Lecture 1
        Mar 19 2009

         Kevin Keay

• Lecture 1: 10-12 PM (Thu)
• Lecture 2: 10-12 AM (Fri)
• Lab session 1: 2-3:30 PM (Thu)
• Lab session 2: At your leisure
• Fortran (Formula translator) is a scientific
    programming language which began life in the late
    1950s. The language was designed to help
    scientists and engineers perform complex
    computational tasks. Basically it was a way of
    getting a computer to operate on mathematical
    formulae and equations in various fields, like
    meteorology, and produce ‘answers’ to practical
•   It has evolved over the ensuing decades to
    become the leading scientific language. Much of
    the world’s library of scientific programs is in
    Fortran although this will change with the
    increasing popularity of C, which is suitable for any
    programming task, not just for science.
• Many scientific organisations, like the
 Australian Bureau of Meteorology,
 continue to use their older Fortran code
 since it is too expensive and inefficient to
 rewrite the existing code in C, especially if
 it is working correctly. Of course, many
 new routines are being written in C and
 the two languages may be interfaced too.
 Hence Fortran programs will still be
 compiled and used in the future.
• Today there are two common versions of
    Fortran which are widely used: Fortran 77 and
    Fortran 90 (the numbers are supposed to reflect
    the years in which they appeared). The former is
    available for all platforms (PC, Sun, iMac) while
    the latter is traditionally associated with
    supercomputers (Cray, NEC), which have more
    than one CPU, since it features parallel and
    vector processing (ways to make a program run
•   Only Fortran 77 is covered in this course.
    However there will be a simple illustration of
    Fortran 90.
                 Fortran 90
• There is not a lot of experience with Fortran 90
  in our group. However there are Fortran 90
  compilers on atlas (Sun) f90 and Linux machines
  pgf90. Kevin Keay has limited experience with
  Fortran 90 but should be approached initially
  with any queries. He has compiled a few Fortran
  90 programs written elsewhere. Fortran 90
  allows the user to operate on arrays and vectors
  in a simpler way than Fortran 77 – the code
  looks quite different! Most of you probably won’t
  need to use it but there is a possibility that you
  might obtain code from outside the group
  written in this way
Other programming languages
• For your research you are most welcome
 to use other languages such as C. We
 recommend Fortran due to the wealth of
 experience within our group and it is not
 too difficult to learn. For your information
 the free C compiler gcc is available on all
 operating systems. The Suns also have
 the compiler cc. Kevin Keay has written
 some programs in C but is not an expert!
• There are electronic documents at:

• It is recommended that you read the following documents in this order:
  A Simple Fortran Primer – Rosemary Mardling, Monash University (1997)
  (used with permission of the author). See: primer.pdf
  Supplementary Notes for An Introduction to Fortran Programming – Kevin
  Keay (2006). See: suppnotes_2007.pdf

                         Further information

• You may obtain further information from the following sources.
  Professional Programmer’s Guide to Fortran 77 - Clive Page, University of
  Leicester (1995) (public domain). See: reference.pdf
  Interactive Fortran 77: A Hands on Approach (2nd Ed) - Ian D Chivers and
  Jane Sleightholme (1990). See: f77book.pdf
• See: man g77, info g77 and g77 –-help on the Linux PCs and Suns. Some
  of these help pages may not be on other operating systems. On the Suns
  see: man f77 for help on the Sun f77 compiler (not the same as g77).
         A simple example

• We will consider a simple Fortran program
 to illustrate the basic concepts involved.
Basic structure of the program
• Here is a very simple Fortran program. It
 consists of a set of statements that start
 with the program statement and finish
 with the end statement. This set of
 statements, or the Fortran source code, is
 saved in a text file e.g. first.f . To avoid
 compilation ‘hassles’ it is a good idea to
 use the extension .f for your source code
 files. Also, save as ‘text-only’, not as a
 Word document.
• Each statement begins in column 7 and ends no greater than
    column 72 (the ruler just before the example is to make this
    clear – this ruler does not appear in the source code file).
    There are a couple of exceptions to this.
•    Firstly, if you have a long statement you place a character in
    column 6 of the next line (often a + or *) and continue the
    rest of the statement.
•    Secondly, you may need to use statement numbers
    associated with the goto and format statements. These
    numbers may go anywhere in columns 1-5. They are actually
    labels of your choice and have not connection with the line
    number in the source code file. Thirdly, you may put
    comments anywhere in your program. These have the
    character c in column 1 followed by any text. You may also
    use an exclamation mark (!) after a statement – an in-line
      program first
c * Declaration section
      implicit none ! Need to declare all variables
      real x,y
c * Executable section
      write(*,*)'My first program'
      write(*,*)'Enter a number: '
      y= x**2 +4*x -12
c * Free format output
c   In Mardling, print is used instead of write
c   i.e. write(*,*) == print *,
      write(*,*)'x=',x,' y= ',y
c * User-specified formatted output
10    format('x=',F8.4,2X,'y=',F9.5)
• The program comprises two sections:
    declaration and executable.
•   The declaration section consists of statements
    that define variables and parameters used in
    your program. These immediately follow the
    program statement (this just has the name of
    your program) and come before all executable
•   The executable section consists of statements
    that actually do something
    e.g. the read statement reads in data from the
    keyboard or a data file. The executable
    statement: y= x**2 +4*x -12 computes the
    variable y from the value of x.
•    Finally, we have the end statement.
• We may also regard the executable section
 as comprising three generic blocks: input,
 processing and output.
• The input block is the read statement –
 this allows us to input data into the
• The statement: y= x**2 +4*x -12 is the
 processing block. Here we perform
 operations on (process) x to get y.
• Finally, the write statements constitute the
 output block – we need to view our results,
 in this case the value of y.
What does this example program do?

• Well, it prints a couple of informative messages on the computer
  screen (write) and waits for you to enter a real (floating point)
  number (read) e.g. 2.5 (note that if you enter 2 it is interpreted as
  2.0). The statement: read(*,*) x means read from the keyboard and
  the number will be interpreted from its declaration i.e. real. This
  number is assigned to the variable x
• Then the statement: y= x**2 +4*x -12 computes the variable y – in
  this case, y would be 4.25. Finally, the values of x and y are written
  on the screen (write).
• For illustration, this is done in free format and then by a user-
  defined format. The first approach involving write(*,*) is convenient
  - this means write to the screen in a default way - while the second
  approach using the two statements write(*,10)x,y and 10 format
  allows greater control over the written output. Note that the
  connecting statement number or label (10) for the second approach.
              Compiling the program
• To compile this program we need a Fortran
  compiler. This is a piece of software which reads
  the Fortran source code file (first.f) and turns it
  into an executable program (software) which
  runs on your computer. The executable program
  is often called an executable or a binary. On
  most of the computers systems in the School of
  Earth Sciences there is a public domain Fortran
  77 compiler called g77. Traditionally, the
  compiler is called f77 but on some machines
  (especially the Suns) there is a proprietary
  Fortran compiler (f77) as well as the ‘free’ one
  (g77). In general, f77 may have some different
  options to g77.Note: On the Linux PCs and
  Windows XP, g77 is usually aliased to f77 so the
  names actually refer to the same compiler.
• Hence to compile our example on any
  computer system:
      g77 –o first first.f
• The option –o allows us to specify the
  output name of the executable. By default
  i.e. without the –o option, it is called
  a.out (or a.exe on Windows PCs).
• The compiler produces one or more binary objects with
    the extension .o corresponding to your source code In
    our case, there is one called first.o but it is not retained
    unless the –c option of the g77 compiler is used. When
    the program is compiled some pre-packaged routines
    which are stored as libraries are linked with the compiler
    binary output (objects) from your source code to create
    an executable.
•    To show the creation of the object, the above
    compilation could be performed in two steps:
    g77 –c first.f            (this creates the binary object
    g77 –o first first.o      (this links the object to the
    system libraries to create the executable)
• An extension of this approach is used in
  makefiles involving the make command. (This
  will be touched on in the Lab Session). Some
  simple examples of these are intrinsic (inbuilt)
  functions e.g. sin(x). Depending on the
  complexity of your program, a host of libraries
  may be required. For instance, to incorporate
  NCAR Graphics into your Fortran program (like
  conmap7) the NCAR Graphics libraries need to
  be available to the compiler so that the graphics
  routines are linked with your code.
• The executable will only run on your
 current operating system e.g. an
 executable compiled on a Linux PC will
 not run on a Windows XP PC or an iMac.
 However, in principle you can transfer the
 source code (first.f) to other machines and
 compile it there – and it should work! This
 is the real power of programming.
               Running the program
• To run the executable, just type in the name: first . On
    the screen you will see the messages:
      My first program
      Enter a number:
    followed by a prompt. Enter a number from the
    keyboard e.g. 2.5. Then some more output text is
    written to the screen:
     x= 2.5 y= 4.25
     x= 2.5000 y= 4.25000
•   The above is the screen output on a PC running
    Windows 2000. The program was compiled with g77
    under the Cygwin Linux emulation software. (This
    software is available on the PCs running Windows XP in
    the PC Lab.)
• The first line uses free format and is chosen by
  the compiler. The second line is specified by the
  user in the format statement. Firstly, we write
  the text: x= on the screen. The value of the
  variable x is written in a field of 8 columns with
  4 decimal places (F8.4), followed by a white
  space of 2 columns (2X). Finally, we write the
  text: y= and the value of the variable y in a field
  of 9 columns with 5 decimal places (F9.5). In
  both fields F denotes floating point (real)
  numbers corresponding to the declaration of x
  and y as real variables.
Some remarks on the example
• Although the above program is quite simple it
    nevertheless illustrates the basics of Fortran
    programming (in fact, any programming
    language). Extensions of the example might
    include reading from a data file, doing some
    processing e.g. computing the mean or a Fourier
    transform, and outputting to another data file.
•   The input and output files may have a special
    format, perhaps even binary i.e. not viewable as
    text. Much of our weather data is in binary
    formats – usually they result in smaller files and
    are read more quickly than text files if there is a
    lot of data.
                   Fortran 90
• Most of the programs written by our group are
    in Fortran 77.
•   In the past couple of years there has been some
    exposure to Fortran 90, which is used at the
    BoM and CSIRO
•   Our Fortran 90 compilers (Linux: pgf90 Solaris:
    f90) will process Fortran 77 code too (Fortran 77
    is a subset of Fortran 90)
•   A good reference book is:
    Introduction to programming with Fortran : with
    coverage of Fortran 90, 95, 2003, and 77 / Ian
    D. Chivers and Jane Sleightholme (2006) (Earth
    Sciences Library: 005.262 CHIV)
                 Fortran 90 (2)
• For Fortran 90 on the Linux machines see:
 man pgf90 for use on pgf90. There is also
 an introductory document on Fortran 90

• This is also saved on the Honours website
   site as: 138fortran90.pdf
• On the Solaris machines see: man f90 for
  use on f90
                Fortran 90 (3)
• Fortran 90 is designed for high performance
    scientific computing
•   It can treat arrays (vectors and matrices) by
    their symbolic form
    e.g. Y = A * B
    rather than by a set of do loops to operate on
    the individual elements
    e.g. y(i) = a(i,j) * b(j)
•   A lot of concepts from C are implemented
•   It is free format – you don’t need to start in
    column 7!
                   Fortran 90 (4)
• Example
integer i
b=a +1.     ! Vector addition
c=a*sin(b)  ! Vector operation
print *, c  ! Same as write(*,*)c

do i=1,10
           Fortran 90 (5)

• On the Linux machines you may compile
  this program with pgf90
  e.g. pgf90 –o example example.f90
• On the Solaris machines use f90
  e.g. f90 –o example example.f90
Some basic Fortran concepts
 1. Program source file (.f file)

For historical reasons dating back to the days of punched cards the
standard Fortran statement record or line is 72 columns (characters)

1   567                                      72
↑      ← Statement (code) in columns. 7-72 →

   Long statements (exceeding column 72) can be continued on the next line by
   putting a character in column 6 (often a *). Statement labels e.g. on format
   statements are from 1-99999 in columns 1-5 (any justification). Comments
   have a c in column 1. You can also use ! at the end of a statement

e.g. 100□□□format(‘x= ‘,F8.2)□□!A comment (□ is a blank space)
Code from other source files can be incorporated
with the include statement e.g.

include ‘extracode.f’

When the f77 or g77 command is used then the
code in the file extracode.f will be ‘pasted’ into
the current file at the include statement. We use
this approach in Lab Session notes example 11
(c) (corr3.f).
2. Assignment of variables
 As a general rule you will have the statement:

    implicit none

 as the second line of your program. This means
 that you must explicitly declare all variables in
 the same way as the C programming language.
 Without this statement it is assumed that
 variables beginning with I-N are integer e.g.
 icount and A-H and O-Z are real e.g. radius.
The = sign is interpreted as ‘assigned to’. Each
variable or array element e.g. x, p(3) has a
memory location allocated to it. Assuming that x
is declared as real then the statement x = 2
stores the real number 2.0 in the memory
location allocated (or reserved for) the variable x.
If we have the two statements:

   x = 2
   x = x + 5.7

then the second statement takes the current
value of x (2.0), adds 5.7 to x to get 7.7 and then
overwrites the memory location for x with the
new value i.e. after the second statement x is
now 7.7.
3. Format descriptors
In the ‘old days’ numbers had to be right-justified for read. This doesn’t seem to
apply anymore. In the following the field width w includes the decimal point and
+/– . d is the number of decimal places. Note that for write numbers are output
as right-justified and text as left-justified.

Real or floating point numbers
              → d ←
Fw.d     ----•--                    e.g. F7.2
         ← w →

e.g. a = 104.5627 will be output as □104.56 (note rounding to fit format;
 □ represents a space)

Exponential representation of floating point numbers
             ← d →
Ew.d     ±0•------E±xy              e.g. E13.6
         ←       w       →
This always begins with a decimal part less than one.
e.g. a = 104.5627 will be output as □0.104563E+03 (note rounding to fit format)
Iw     ------           e.g. I6
       ← w →

e.g. j = 4 will be output as □□□□□4

Character or text variables
Aw ------             e.g. A6
   ← w →

Character variables are written left-justified
e.g. label= ‘date‘
With the above format (A6) this will appear as:
date□□ (□ is a blank space)
  4. Input
Read a real number from the keyboard and assign to real
variable x.

  real x
keyboard ↑ ↑ free format

Note: read(*,*) == read(5,*) i.e. unit 5 is reserved for the keyboard.

Read an integer from the keyboard into variable i.

integer i

Read in 5 real numbers from the keyboard into array a.

integer i
real a(5)
read(*,*)(a(i),i=1,5)                ← implied DO loop
The last line is equivalent to: read(*,*)a(1),a(2),a(3),a(4),a(5)
  Input/output from a file
To access a disk file for reading (input) or writing (output) we use the open
   statement e.g.
  open (1,file=‘test.dat’,format=‘formatted’)
  open (1,file=‘test.dat’)
For a text (readable) file omit the format keyword.
To read from the file use something like: read(1,*)x
To write to the file use something like: write(1,*)x

Note: The number 1 refers to a unit number in the
range 1-99. However there are two special (reserved)
unit numbers: 5,6.

  read(*,*) == read(5,*) i.e. unit 5 is reserved for the keyboard.
  write(*,*) == write(6,*) i.e. unit 6 is reserved for the screen.

To avoid portability issues do not use these special units to open files.
In many cases we read data from a file and we’re not sure how many numbers
there will be in the file. We make use of the read end keyword. For simplicity we will
assume that the file press.dat contains a column of numbers e.g.


      integer i,n
      real p(100)
      open (1,file=’press.dat’) ← Unit 1 is assigned to the file press.dat
                                          (a kind of short name or handle)
      do i=1,100
  9   continue ← Go to here if we encounter the end of the file (end=9)
      n= i –1    ← Last value of i corresponds to the end of the file (one greater)

We can now process the array of numbers p(i) i=1 … n .
In the last example it was assumed that we were reading in a single column of
Imagine that the file press.dat contains the following:
Data□□□□□Pressure                    ← □ denotes a blank space
Column 1
To read in the second column of numbers into array p:
   character line*80 ← A variable to hold 80 characters
   integer i,n
   real p(100)
   open (1,file=’press.dat’)
   read(1,*)line or read(1,’(A)’)line
   do i=1,100
      read(1,’(9x,F6.1)’,end=9)p(i) ← Formatted read statement
9 continue
   n= i –1
We can also use a format statement:

    read(1,200,end=9)p(i) ← Use the format statement with label 200
200 format(9x,F6.1)

which is equivalent to:


To read in the line of text as two column labels and both columns of data:
     character label1*4, label2*8 ← Variables to hold column labels of 4 and 8 characters
     integer i,n
     real p(100)
     integer date(100)                  ← Array to hold integer date
     open (1,file=’press.dat’)
210 format(A4,5x,A8)                    ← Format for labels
     do i=1,100
        read(1,’(I6,3x,F6.1)’,end=9)date(i),p(i) ← Formatted read statement to read date(i)
                                                                  and p(i)
  9 continue
     n= i –1

If we are only reading numerical values e.g. three columns of numbers, then usually the simplest approach
would be something like:
 5. Output
Generally write is just the opposite of read.
Write a real number x to the screen.
     real x
      screen ↑ ↑ free format

Note: write(*,*) == write(6,*) i.e. unit 6 is reserved for the screen.

In the primer: write(*,*)x is equivalent to print *,x
You can use a format statement and include some
output text:
100 format(’The answer is ’,F8.2)
      is equivalent to
write(*,’(’’The answer is ’’,F8.2)’)x ← Note repeated
6. Internal read and write
This involves reading from or writing to a character variable that is
treated as a ‘pretend’ file. For instance:

integer n
character*80 optarg              ← or character optarg*80

The integer variable n is read from the character variable optarg as if it
were a line of text in a file. Similarly for a real variable we can have:


We can also use a format e.g. read(optarg,’(2x,F6.1)’)x
Similarly we can write to a character variable:

7. Logical variables
See the primer and reference. These are declared as logical type e.g.

logical lexist

A logical variable is either true (1) or false (0).
Usually we use an if statement with a logical expression involving our
variables e.g.

if (x.eq.5) then           ← Is x=5? If so then go to the then section otherwise
                             go to the else section
  y = 2                    ← If x=5 then go here and set y=2
  y = -4                   ← If x is not 5 then go here and set y=-4
write(*,*)’x= ’,x,’ y= ’,y

If the expression in (…) is true the then section is executed otherwise
we jump to the else section.
Sometimes we code the above as:

logical istrue
istrue= (x.eq.5) ← This will be either true (1) or false (0)
if(istrue)then      ← If x is 5 then istrue will be 1 and we
               go to the then section

write(*,*)’istrue=’,istrue,’ x= ’,x,’ y= ’,y

Note: If you write out a logical variable you will see T for
true (1) and F for false (0) on most systems.
You can also set a logical variable to true or false e.g.
exists= .true.
8. Mixed mode arithmetic
An expression that involves a combination of real and integer variables
will give a real value, as long as the output variable is real.
    real x,y
    integer i,j
    y= x/i                  ← y is real
    j= x/i                  ← j is an integer i.e. integer truncation of x/i
Hence if i= 4 and x= 11. then y= 2.75 and j= 2 i.e. 2.75 is truncated
    to 2.
An expression involving integers only will be the integer truncation.
    integer i,j,k
    real y
    k= i/j                 ← k is an integer i.e. integer truncation of i/j
    y= i/j                 ← y is the real conversion of the integer truncation
Hence if i= 7 and j= 2 then k= 3 (integer truncation 7/2= 3).
Note that y= 3. i.e. the integer 3 is converted to real (3.0).
9. do loops
These are covered in the primer and reference but a few
comments will be made.
do loops are convenient for summations used to compute
the mean and other statistics. Consider the mean of the
sample x1, x2, …, xn :

The summation is x1+ x2+ …+ xn . If we identify an array
x of size n with the sample then the summation is
 x(1) + x(2) + …+x(n).
Alternatively the summation can be expressed as a set of
successive accumulations:
  s1 = x(1)
  s2 = x(1) + x(2) = s1 + x(2)
  s3 = x(1) + x(2) + x(3) = s2 + x(3)
We can use a do loop to represent these accumulations:

  xbar = 0.                        ←   Initialise xbar i.e. start with a sum of zero

  do i=1,n
    xbar = xbar + x(i)             ←   Add x(i) to previous sum to get current sum

  xbar = xbar / n                  ←   Get the mean by dividing the sum by n

In older code the form:

        do 200 i=1,n
200     continue

is often seen.
Note: do loops are often indented for clarity.
A useful variation is the do while loop. In this case the
logical condition that must be true for the loop to be
processed is given as part of the do while statement e.g.
  n= 10
  i= 1
  y= 2.
 do while (                   ←     Logical condition

    y= y +sin(x(i))       ←   sin is a Fortran intrinsic (built-in) function

    i= i +1 ← i is modified
Note that both aspects of this particular condition must be
true for the operations within the loop to be processed.
A pair of ‘nested’ DO loops is useful for processing 2D array

 do j=1,nlat
   do i=1,nlon
     y(i,j)= z(i,j)* a + b

Here i might correspond to longitude and j to latitude.

Note: the array element y(i,j) may be treated as a simple
variable in computations.
There is a special form of the do loop which
is used only with the read and write
statements – it is called an implied do loop e.g.
   n= 3
The list in () is expanded i.e. it is equivalent to
listing the array elements x(i) explicitly i.e.
For large n e.g. n=10000, the implied do loop form
is obviously very useful.
  10. Binary (unformatted) files
The files encountered in the primer and reference are
formatted files that are appropriate for text data. We open
such files with a statement like:
   open (1,file=’press.dat’)
   read (1,*)x
Much of the output from GCMs and related reanalysis
projects e.g. NCEP is in a binary form i.e. not readable to
the naked eye. Such files are opened and read in a different way.
Assume we have a binary version of press.dat called pressb.dat:
   open (1,file=’pressb.dat’,format=’unformatted’)
   read (1)x
In the open statement we need the extra keyword format set to
’unformatted’ that means binary in Fortran. Also in the read
statement we just have the unit number without any format
11. Functions

These are a special kind of variable. There is no
need to declare intrinsic (built-in) functions
   e.g. sin
but you need to declare your own e.g. probst in
the correlation examples. A function returns a
value that is normally assigned to a variable e.g.
   real x,y
   y = sin(x)
Here the value of x is input to the intrinsic function
sin which returns the value sin(x), assigned to the
variable y.
 12. Subroutines

These don’t require declaration. There is an
association between the variables in the
calling routine and the subroutine. Variables
must match in terms of type e.g. real, and
array size but they can have different
names. For instance:
program test2
integer n
real x(100)
real meanx
call calcmean       (n,x,meanx)
…                    ↓ ↓ ↓
subroutine calcmean (n,y,ybar)
integer n
real y(n)
real ybar

The subroutine takes the array x of size n i.e. x(1), x(2), … x(n),
computes the mean ybar and passes this back with the name meanx in
the calling routine. Note that n and y are also passed back so if they
are modified in the subroutine then they will be modified in the calling program
after the call statement. Usually we label subroutine arguments that are not
modified as inputs and those that are as outputs.
13. Command-line arguments: getarg, iargc
These are useful intrinsic (built-in) routines to simply input and output. Note that
getarg is a subroutine and iargc is a function.
Imagine we have a program called jason1. By using the above routines
we can read filenames and other arguments from the command line. In our
case we want to give an input file (argument 1) and an output file (argument 2)

e.g. jason1 press.dat mean.dat
            ↑Argument 1 ↑Argument 2

A program fragment to do this is:

character optarg*80, infile*80, outfile*80
integer narg
narg= iargc() ← This will be 2 in the above example i.e. 2 arguments
write(*,*)’No. of arguments: ’,narg
call getarg (1,optarg) ← Get first argument from command line and put into optarg
             ↑Argument 1
infile= optarg ← This variable holds the name of the input file
call getarg (2,optarg) ← Get second argument from command line and put into optarg
              ↑Argument 2
outfile= optarg ← This variable holds the name of the output file
open(1,file=infile) ← Open the input file
open(2,file=outfile)← Open the output file
We can also read numerical arguments from the command line
e.g. jason1 press.dat mean.dat 24.5
             ↑Argument 1  ↑Argument 2      ↑Argument 3
Argument 3 can be read by adding:
real x
call getarg (3,optarg) ← Get third argument from command line and put
                                      into optarg

             ↑Argument 3
read(optarg,*)x← Do an internal read from optarg    i.e. read x from optarg

write(*,*)’x= ’,x
This approach is very useful for handling a large set of
input files
e.g. jason1 press.9601?? mean.dat
Under UNIX or Linux the argument press.9601?? is
expanded into a set of filenames which differ in the last
two characters. Note that at least one of these files must
exist. Assume that the files are called press.960101,
press.960102, press.960103, …, press.960107 i.e. daily
pressure files for Jan 1 1996 to Jan 7 1996. Then the
command line will be expanded as if the individual files
were given i.e. as if we had specified:
jason1 press.960101 press.960102 … press.960107 mean.dat
       ↑Argument 1   ↑Argument 2    ↑Argument 7   ↑Argument 8

Such an approach is used in statcon.f (see Lab Session
notes example 9).
   14. Common blocks
Basically a common block is a shared area of memory accessible by a program and its subprograms
(subroutines and functions). In order to share the variables contained in this memory area, a common
block is declared in the subprograms. For instance:

     program prog1
     real x(5),n,q
     common /myblock1/ n,x,q
C * Read in array x(i),i=1,n – code omitted
     call sub1
     subroutine sub1
     real x(5),n,q
     common /myblock1/ n,x,q
     q= 0.
     do i=1,n
       q= q + cos(x(i))

Subroutine sub1 uses array x of length n to compute q. All of this information is transferred via the
common block myblock1. On return to the main program prog1 we have access to the computed value of
q. Common blocks are mainly used when memory requirements are large (more of an issue in the past).

See also Lab Session notes examples 10 (cblk1.f, cblk2.f) and 11 (c) (corr3.f).
15. Makefiles
A makefile is a useful approach for handling the compilation of large projects e.g. a GCM.
Or you might have a fairly simple program that needs some special library e.g. NetCDF.
All of the required information for compilation can be stored in the makefile – the default
name is called Makefile. The file includes variables for the Fortran compiler and its flags
(options) – FC and FFLAGS respectively. The actual compilation is carried out by the
UNIX command make. In the example below the program tnc2mpl is compiled by:

make tnc2mpl

This calls the file Makefile and looks for the section beginning with:

(note the colon at the end).


make clean

goes to the section beginning with:


and removes the Fortran .o files as well as the executable (tnc2mpl)
Note: make all will go to the section all: which sends control to the section for tn2cmpl.
Also lines beginning with # are comments.

Special note: The source file has a .F extension, not .f. This means that it probably contains special compiler directives
that begin with a #. In this case: #include "“ appears in tnc2mpl.F. Therefore the .F file will be
subject to ‘pre-processing’ .

There are a lot of ‘rules’ used by the make command and things can get rather complicated. In addition make often
works in conjunction with an associated command called makedepend. This is often used to compile software for use
on multiple platforms e.g. Linux, Microsoft Windows. Often the LIBDIR variable (location of libraries) will appear in
conjunction with the LIBS (library names) variable e.g.
    LIBDIR = -L/home/dcn/lib -L/usr/local/lib
    LIBS = -lnetcdf -lanalysis -lfft
The notation –lfft refers to a library called libfft.a.

See also example 11 (d) (corr4.f) in the Lab Session notes.

# Makefile for tnc2mpl
# Linux version: No MUGCM functionality; NetCDF for output
# make [all|tnc2mpl|clean|new]
# NOTE: File dummy.h is a dummy header file to prevent a make error
# if header files are not used

# Note: f77 == g77 on Linux
        FC      = f77

# Location of Linux NetCDF library
        LIBS    = /work18/kevin/netcdf-3.5.1/netcdf-3.5.1/lib/libnetcdf.a

#        BINDIR   = bin/
# g77 flags
#       FFLAGS = -O3 -Wimplicit -ffortran-bounds-check -finit-local-zero
# NOTE: Omit -ffortran-bounds-check as this causes a character subset error
        FFLAGS = -O3 -Wimplicit -finit-local-zero

         CPPDEFS =

         OBJS     = tnc2mpl.o getopt.o

         OUTPUT   = tnc2mpl

         make tnc2mpl

tnc2mpl: $(OBJS)
        $(FC) -o $(OUTPUT) $(FFLAGS) $(OBJS) $(LIBDIR) $(LIBS)
#       cp ${OUTPUT} ${BINDIR}

         rm -f $(OUTPUT) $(OBJS)
        make clean
        make tnc2mpl
# default suffix rules
        $(FC) $(FFLAGS) -c $*.f
        $(FC) $(CPPDEF) $(FFLAGS) -c $*.F $(INCDIR)

# dependncies

$(OBJS): *.h
$(OBJS): Makefile

The source files present in the project are:

dummy.h getopt.f Makefile tnc2mpl.F

After: make tnc2cmpl

The files present are:

dummy.h getopt.f getopt.o Makefile tnc2mpl tnc2mpl.F tnc2mpl.o

There are now Fortran .o files and the executable tnc2mpl.
16. Error messages
In general, Sun f77 compilation and runtime messages are often cryptic. The
messages from g77 tend to be clearer. The following are some common errors
encountered using Sun f77. They have a similar expression using g77.

list io: [-1] end of file
logical unit 1, named ‘press.dat’
part of last data 11.0 ^J |
This occurs if you try to read past the end of a file i.e. the program expects more data
than is given in the file.

There is not enough system memory to run the program. This could be due to the
presence of other processes on the system consuming most of the available memory or
the program’s memory requirements exceed the limits for the system.

Segmentation fault
This usually means that the memory allocated to the program as it is running has been
corrupted in some way. It often arises with illegal array processing e.g. try to write out
a(1) … a(1000) when the maximum size of a is (say) 5.
I/O error
This occurs when you have the wrong format
e.g. read (1,’(I5)’)x
where x is real. Note that this is a runtime error –
depending on the compiler it may not show up in the
compilation stage.

Subscript out of bounds
This occurs when you try to process an array element
outside the valid range when the program was compiled
with f77 –C (Sun) or g77 –ffortran-bounds-check (Linux PC)
e.g. real a(5)
The element a(6) is not valid so using the above options
will cause the program to abort.