Programming Fortran 2

About the author


Imperial College London

This is a continuation of Fortran 1. This tutorial might not make much sense unless you have read that first.

Writing and Reading from Files, Screens and Keyboards

Fortran is capable of reading data from files and from the keyboard. It can also write data to files and to the screen. The I/O (Input-Output) in Fortran is a little cumbersome and is not very flexible, but is easy to get the hang of.

  • Writing to the screen is done with:
    WRITE(*,*) "what you would like to write", aVariable
  • Any thing between the "" is written. The value stored in the variable, aVariable is printed. Note the comma. A space is put in front of the variable on most systems.
  • To write to a file you need to do two things:
    • Open a unit
    • Write to that unit
  • To open a unit that points to a file:
    OPEN(UNIT=10, FILE="filename", IOSTAT=ios)
    The unit number can be anything, but start from 10 to be safe (some computers reserve lower number for things like punch cards!). The filename is the file you wish to read/write from/to. IOSTAT is an optional argument, which indicates errors. The error code is placed in the integer variable ios. If ios is greater than zero, an error occurred.
  • To then write to the file:
    WRITE(10,*) data
    which writes the value of data to the file which is associated with unit 10
  • The second asterisk determines how to write the data. This is done with the Format argument. The format can be on it's own line (see above, the line labeled 10), or inside the WRITE statement. If the format statement is on it's own line, simply replace the second asterisk with the appropriate line number (technically called a label)
  • To place the format statement in the write statement:
    WRITE(10,FMT="(///////(F6.1,2X,F6.3))") data
  • The format descriptor can contain:
Descriptor Meaning
Iw An integer variable, which is w characters long
Fw.d A real number variable, which has w characters with d decimal places
Ew.d Real number variable, which has w characters in exponent form, with d decimal places. Note that w includes the four characters needed for the exponent
Aw Character variable, which has w characters.
nX Ignore the next n characters
Tc Output the next item at position c
Lw Output w-1 spaces, followed by a T of F for a logical value
'a string' Output 'a string' in the file
/ Skip a line
() Repeat these item in brackets

Examples:

  • Format=(//////(F6.1,2X,F6.3))

Skip 6 lines, then do a six character float with 1dp, miss two spaces, then a 6 character float with 3dp, until no more output is available.

  • Format=(I2,5X,F5.3) i, sum

Will output: 10----- 25.431 in the file (- = spaces) if i=10 and sum =25.4312456826928652.

  • Exactly the same process is used for reading data:
    READ(*,*) input will read a value from the keyboard into the variable, input
  • READ(10,FMT="(I2,2X,I2)") i, j
    will read 2 integer values from the file connected to unit 10, into i and j, if they are 2 characters long, with 2 spaces in between

Subroutines

Subroutines are small programs that can be called from within the main program. They have to follow the same rules as a normal program, including IMPLICIT NONE and variable declaration. They allow the program to by written in a modular fashion. If a certain segment of code is being used repeatedly, then it may be a good idea to put it in a subroutine. However, calling a subroutine does require more resources than not and this may slow your program down, but this is not really a problem unless your code goes very slowly.

  • Subroutines are written using:

    SUBROUTINE Name (argument list)

    CODE

    END SUBROUTINE Name
  • To use a subroutine in the main code:
    CALL SubroutineName(arguments)
  • The arguments are a list of variable, whose values you want to pass to, or get from the subroutine. They do not have to be the same name in the main program and the subroutine, but they do have to be the same type
  • A subroutine can also have it's own variables, which can have the same name as those in the main program. These are called local variables and are only accessible in the subroutine
  • To make life easier, for you, declare which variables are intended for input and output with the INTENT statement:
    REAL, INTENT(IN) :: inputData
    REAL, INTENT(OUT) :: outputData
    REAL, INTENT(INOUT) :: bothWaysData
  • Variable declared as INTENT(IN), can NOT be altered inside the subroutine. Variable declared as INTENT(OUT) must be assigned a value somewhere in the subroutine. Variable declared INTENT(INOUT) can be altered in any way, and is the same as having no INTENT statement, but it does make it obvious you are altering the value of an input variable
  • All variables with an INTENT statement must be in the argument list.
  • Subroutines are very useful if you need to repeat the code inside several times, or it is complicated, so is better in its own block. Using subroutines allows better testing of code, as you can write small program, specifically design to test the subroutine in question. Subroutines separate portions of code, making debugging easier.

Functions

  • Fortran comes with many built in functions (called intrinsics).
  • They are used in a similar way to subroutines but return only one value.
  • You can write your own but as subroutines do a similar job, I'll leave functions for somebody else to describe in detail. Briefly, do exactly the same as a subroutine, but use a FUNCTION instead
  • The name of the function must be the same as the name of the variable that is to be returned
  • For example:
    FUNCTION sum (x, y)

    REAL, INTENT(IN) :: x, y

    sum = x + y

    END FUNCTION sum
  • To use an intrinsic:
    x = SIN(y)
    uses the sine function on the variable y, and puts the result in x

Compiling

  • Write your code in a text editor - something like notepad or Nedit will do. Some editors have syntax highlighting, which makes the code much easier to read. The file should be saved with a .f90 extension.
  • When you have your code (known as source code), you need to compile it. In windows this is probably done in your Integrated Development Environment, which will include a text editor too. On Unix systems type:
    f90 -o progname file.f90
  • The -o option lets you define the name of the program produced. The file.f90 is your source code. You can include many files here, perhaps one for your main program and one for your subroutines. Another option to consider is -fast, which optimises your code.

Arrays and DO loops

  • Arrays are used a lot in software. Traditionally, they are accessed with loops, the loop counters acting as indices for the array:

    DO i=1,100
    DO j=1,100
    array1(i,j) = 5 * array2(i,j)
    END DO
    END DO
  • In Fortran 90 has array syntax. This allows array operations to be simplified:
    array1 = 5 * array2
    will do exactly the same as the above code
  • Arrays also have triplet notation. This allows to specify segments of the array
    array1(20:100:10)
    identifies array2 from 20 to 100 in steps of 10. This notation allows arrays of different size be used in array syntax-type operations, e.g.:
    array(20:100) = array2(100:160) * 5
    Note the arrays have to be the same size for this to work - the program may crash if they aren't.

References

T.M.R Ellis et al., 1994. Fortran 90/95 Programming.