Fortran90 Tutorial

Embed Size (px)

DESCRIPTION

Fortran 90 Tutorial

Citation preview

  • 1Einfuhrung in die Numerische Programmierung mit

    dem Schwerpunkt Fortran 90

    Georg Kresse, A. Eichler and Robert Lorenz

    Universitat Wien

    March 2011

    LiteratureFortran 90 explainedMichael Metcalf, John Reid, Oxford University Press

    Fortran 90Regionales Rechenzentrum fur Niedersachsen RRZN

    Fortran 90 programmingT.M.R. Ellis, Ivor R. Philips, Thomas M. Lahey, Addison-Wesley

    An Introduction to Computer Simulation MethodsH. Gould, and J. Tobochnik, Addison-Wesley

  • CONTENTS 2

    Contents

    1 Lets get started: a simple example program 61.1 Language elements of F90 . . . . . . . . . . . . . . . . . . . . . . . . . 6

    1.1.1 Basic elements . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.2 Source format and statements . . . . . . . . . . . . . . . . . . . . . . . 7

    1.2.1 Specification statements . . . . . . . . . . . . . . . . . . . . . . 71.2.2 Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.2.3 Specification of a named constant . . . . . . . . . . . . . . . . . 81.2.4 Input and Output statements . . . . . . . . . . . . . . . . . . . 91.2.5 A few style recommendations . . . . . . . . . . . . . . . . . . . 9

    1.3 Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.4 A first look at the IF statement . . . . . . . . . . . . . . . . . . . . . . 101.5 A first look at the DO statement . . . . . . . . . . . . . . . . . . . . . . 11

    2 A little bit more complicated: Types, LOOPs and IFs 112.1 Concept of types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

    2.1.1 Specification of variables and named constants . . . . . . . . . . 132.1.2 Single precision and double precision . . . . . . . . . . . . . . . 132.1.3 KIND attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.1.4 Implicit typing: IMPLICIT NONE . . . . . . . . . . . . . . . . 15

    2.2 Vectors, Matrices and Tensors . . . . . . . . . . . . . . . . . . . . . . . 152.2.1 Input and output statements . . . . . . . . . . . . . . . . . . . . 162.2.2 DO loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

    2.3 Infinite loops: the conversion program again . . . . . . . . . . . . . . . 182.4 The IF construct in more detail . . . . . . . . . . . . . . . . . . . . . . 192.5 A small example program: a calculator . . . . . . . . . . . . . . . . . . 20

    3 Expressions and assignments in more detail 213.1 Scalar numerical expressions and assignment . . . . . . . . . . . . . . . 223.2 Scalar character expressions and assignment . . . . . . . . . . . . . . . 223.3 Scalar relational operators . . . . . . . . . . . . . . . . . . . . . . . . . 233.4 Scalar logical operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.5 Precedence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.6 Array-Expressions and array-assignment . . . . . . . . . . . . . . . . . 25

    4 Some example programs 264.1 Sum of input values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264.2 Mean square deviation . . . . . . . . . . . . . . . . . . . . . . . . . . . 264.3 Minimum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264.4 Sorting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.5 Inproduct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.6 Matrix times Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

  • CONTENTS 3

    5 FUNCTIONS and MODULES: the mean value again 285.1 Mean value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285.2 Functions and Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . 295.3 Sorting again . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305.4 Subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315.5 Built-in Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325.6 Lets add some extra flexibility . . . . . . . . . . . . . . . . . . . . . . 35

    6 PROGRAM units and MODULES in more detail 366.1 The Main PROGRAM . . . . . . . . . . . . . . . . . . . . . . . . . . . 366.2 External procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376.3 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376.4 Order of statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386.5 Dummy arguments - actual arguments - local variables . . . . . . . . . 38

    6.5.1 Local variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 396.6 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406.7 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

    6.7.1 Modules for storing constants . . . . . . . . . . . . . . . . . . . 406.7.2 Reverse polish calculator . . . . . . . . . . . . . . . . . . . . . . 40

    6.8 Recursive Functions and Subroutines: the factorial . . . . . . . . . . . . 416.9 A faster factorial subroutine . . . . . . . . . . . . . . . . . . . . . . . . 426.10 Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436.11 Passing functions as arguments . . . . . . . . . . . . . . . . . . . . . . 45

    7 Boring but required: Input and Output 477.1 OPEN and CLOSE statements . . . . . . . . . . . . . . . . . . . . . . 477.2 READ, WRITE statements . . . . . . . . . . . . . . . . . . . . . . . . 477.3 List directed input/output, FMT= * . . . . . . . . . . . . . . . . . . . 487.4 Formated input/output . . . . . . . . . . . . . . . . . . . . . . . . . . 497.5 Edit descriptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

    7.5.1 Grouping edit descriptors . . . . . . . . . . . . . . . . . . . . . 507.5.2 Integer Format (I-Format): rIw . . . . . . . . . . . . . . . . . . 517.5.3 Float Format (F-Format): rFw.d . . . . . . . . . . . . . . . . . 517.5.4 Exponential Format (E-Format): rEw.d or rEw.dEe . . . . . . . 527.5.5 Logical Format (L-Format): rLw . . . . . . . . . . . . . . . . . . 527.5.6 Character Format (A-Format): rAw . . . . . . . . . . . . . . . 527.5.7 General Format (G-Format): rGw.dEe . . . . . . . . . . . . . . 527.5.8 Blank Format (X-Format): rX . . . . . . . . . . . . . . . . . . 527.5.9 New Record (/-Format): r/ . . . . . . . . . . . . . . . . . . . . 53

    8 More about arrays 548.1 Literal constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548.2 Array constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558.3 Rank, shape and size . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

  • CONTENTS 4

    8.4 Array-Section . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558.5 Zero sized arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568.6 Assumed shape array . . . . . . . . . . . . . . . . . . . . . . . . . . . 568.7 Automatic arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568.8 Elemental intrinsic functions . . . . . . . . . . . . . . . . . . . . . . . 578.9 Array valued function . . . . . . . . . . . . . . . . . . . . . . . . . . . 578.10 Allocatable arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578.11 WHERE stmt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

    9 Derived Types and operator overloading 599.1 Derived Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599.2 Operator overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

    10 Numerical representation of numbers 6210.1 Rounding Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6210.2 Floating-point Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . 6210.3 The IEEE Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

    11 Integration of Functions 6411.1 NewtonCotes formulas . . . . . . . . . . . . . . . . . . . . . . . . . . . 6511.2 Derivation of Simpson rule using Lagrange polynomials . . . . . . . . . 6711.3 The open NewtonCotes Formulas . . . . . . . . . . . . . . . . . . . . . 6811.4 Combined Formulas (Zusammengesetzte Formeln) . . . . . . . . . . . . 6811.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

    12 Numerical Differentiation 7112.1 Interpolation Formulas . . . . . . . . . . . . . . . . . . . . . . . . . . . 7112.2 Example: derivative of exp(x) . . . . . . . . . . . . . . . . . . . . . . . 72

    13 Stochastic Methods: Monte-Carlo methods the rejection method 73

    14 Ordinary Differential Equations 7614.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7614.2 Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7614.3 Systems of Differential Equations . . . . . . . . . . . . . . . . . . . . . 7714.4 Numerical Solution Methods . . . . . . . . . . . . . . . . . . . . . . . . 7714.5 One-Step Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

    14.5.1 Taylor Series Methods . . . . . . . . . . . . . . . . . . . . . . . 7914.6 Runge-Kutta Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

    14.6.1 Classical RungeKutta Formulas . . . . . . . . . . . . . . . . . 8214.7 Example code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8314.8 Some Implementation Issues . . . . . . . . . . . . . . . . . . . . . . . . 8514.9 The Codes RKSUITE . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

    14.9.1 Where to find it . . . . . . . . . . . . . . . . . . . . . . . . . . . 8614.10Multi-Step Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

  • 1 LETS GET STARTED: A SIMPLE EXAMPLE PROGRAM 6

    1 Lets get started: a simple example program

    We will set out from a very simple example program; the conversion of a number fromone unit to another unit. The F90 source code is shown below (conversion1.f90):

    PROGRAM conversion1

    REAL :: a, result

    WRITE(*,*) "convert cal to Joules"

    READ(*,*) a ! read in a number

    result = a * 4.186

    WRITE(*,"(F10.5)") result

    END PROGRAM conversion1

    C source code:

    main() {

    double a, result ;

    printf("convert cal to Joules\n") ;

    scanf("%10.5lf", &a) ;

    result = a * 4.186

    printf("%10.5lf", result) ;

    }

    1.1 Language elements of F90

    1.1.1 Basic elements

    A F90 program must contain only characters from the F90 character set, which consistsof the following characters:

    the letters A ... Z and a ... z,

    the numerals 0 ... 9,

    the underscore

    and the following special characters:

    = : + blank - * / ( ) , . $ (old Fortran 77)

    ! " % & ; < > ? (new Fortran 90)

    From these components tokens are build. A token is similar to a word in human lan-guages.

    In F90, upper case and lower case characters are equivalent outside a string; thisimplies that a variable result is considered to be equivalent to the variable Result orRESULT.F90 distinguishes six classes of tokens:

  • 1 LETS GET STARTED: A SIMPLE EXAMPLE PROGRAM 7

    Labels: 123 (1-5 numerals, not recommened)

    Constants: 123.456789

    Keywords: PROGRAM

    Operators: + - * / **

    Names: solve_equation (up to 31 characters, including underscore _)

    Separators: / ( ) (/ /) , = => : :: ; %

    In F90 and C, only one name space exists: functions, derived types must have differentnames (exceptions to this rule will be discussed later).

    1.2 Source format and statements

    Tokens are grouped to form statements (loosely speaking sentences):

    In F90, 132 characters per line are allowed.

    The exclamation mark ! starts a comment and all comments extend to the endof the line.

    Semi-colons ; and a newlines are used to separate statements.

    The ampersand & initiates the continuation of a statement on the next line.In this case the next line may optionally also start with an ampersand &

    x= y & ! continue on next line

    * 12 ; z = y * 24 ! line continues here

    x= y & ! continue on next line

    & * 12 ; z = y * 24 ! line continues here

    In the first example, we can find three classes of statements which are explained in thefollowing sections.

    1.2.1 Specification statements

    PROGRAM conversion

    REAL :: a, result

    ...

    END PROGRAM conversion

    The PROGRAM statement tells the computer that a legal F90 program follows.The REAL statement declares the two variables a and result. Each variable points

    to a storage location, which can hold a numerical number. With the declaration of avariable sufficient space is allocated (generated) to store a floating point number.

    storage unit for a

    storage unit for resultvariable result

    variable a

  • 1 LETS GET STARTED: A SIMPLE EXAMPLE PROGRAM 8

    In F90 (and most programming languages), all specifications must be placed beforeany executable statement, i.e. it is not possible to declare a variable somewhere in themiddle of the program.

    1.2.2 Assignment

    An assignment is a statement that assigns a value to a variable. In the previousexample, the variable result is set to the current value of variable a multiplied by theconstant 4.186.

    result = a * 4.186

    variable result

    variable a value read: e.g. 10

    41.86 (10 * 4.186)

    1.2.3 Specification of a named constant

    A handy and commonly used feature of F90, is the declaration of a named constants.Let us assume that we want to convert calories to joules at many times in the program,and from the top of the head we know only the first three digits of the conversionfactor. In this case, we simply create a named constant termed cal to joule and usethis named constant instead of the value 4.186 throughout the program:

    PROGRAM conversion2

    REAL :: a, b, result

    REAL, PARAMETER :: cal_to_joule= 4.186

    WRITE(*,*) "convert cal to Joules"

    READ(*,*) a

    result= a * cal_to_joule

    WRITE(*,"(F10.5)") result

    END PROGRAM conversion2

    If we want to change the conversion factor at a later time, we need to change only asingle value in the program. In addition, our program has become more transparent.Alternatively, we could have stored the value 4.186 in a variable. This, however, is notparticularly save, since variables can be changed anywhere in the program, whereas anamed constant can be set only when the constant is declared. In summary, namedconstants make programs less susceptible to errors and more transparent (defensiveprogramming). In Fortran, named constants behave as conventional constants, andcan be used wherever conventional constants can be used.

  • 1 LETS GET STARTED: A SIMPLE EXAMPLE PROGRAM 9

    1.2.4 Input and Output statements

    To allow the program to interfere with the user, input and output statements arerequired. In the previous example, the program stops when it encounters the READstatement and waits until the user types in a value and finishes his input using the or key. The WRITE statement, writes the current value of the variableresult onto the screen.

    READ(*,*) a

    WRITE(*,"(F10.5)") product

    ! "(F10.5)" write a floating point number with a total of 10 digits

    ! with 5 digits after the comma

    If we do not care for formating, we could have alternatively used the statement:

    WRITE(*,*) "input ",a," result ",result

    The WRITE(*,*) statement can be applied to print any number of variables and anytype of variables.

    1.2.5 A few style recommendations

    All F90 keywords should be written in upper case !

    Indent by 2 columns, after the PROGRAM statement, or in IF and DO blocks!

    1.3 Compilation

    The file that contains the user readable text is usually called source code. In F90, thesource code is stored in a file with the extension .f90.

    conversion1.f90

    Such files are generated using a standard editor or, preferably, a programming editorthat is specially designed to assist the programmer in writing programs. They are oftenable to perform basic syntax checks. In the exercises, we recommend to use a powerfuleditor available in the UNIX word (Xemacs).

    After the source file has been typed in, a compiler is used to generate a machinereadable executable from the human readable source file. On most systems, the For-tran90 compiler is called by typing f90

    f90 conversion.f90 -o conversion

    g90 conversion.f90 -o conversion # Gnu Fortran compiler

    gfortran conversion.f90 -o conversion # alternative Gnu Fortran compiler

    ifc conversion.f90 -o conversion # intel fortran compiler

    The compiler generates an executable file with no extension (conversion1) (or theextension .exe on MS-Windows systems). The program can be executed by typing

  • 1 LETS GET STARTED: A SIMPLE EXAMPLE PROGRAM 10

    conversion1

    on the keyboard.The usual program writing cycle consists of several steps summarised below:

    analyse problem.

    design program, often setting out from the data and data structures.

    Coding, ideally starting with comments or written documentation what the pro-gram is supposed to do.

    Compile

    Test

    Amend program

    Compile

    Test

    Testing often involves inserting WRITE statements at critical points in the source codeto determine whether the program does what the programmer expects it to do.

    1.4 A first look at the IF statement

    PROGRAM conversion_if

    INTEGER, PARAMETER :: n = 5

    REAL :: a, r

    REAL, PARAMETER :: c= 4.186

    WRITE(*,*) "convert cal to Joules"

    READ(*,*) a ! read in five values and store in a

    IF (a==0) THEN

    WRITE(*,*) "Null bleibt immer null"

    ENDIF

    IF (a==1) THEN

    WRITE(*,*) "Die Konversionkonstante ist",c

    ENDIF

    r= a * c ! multiply each value of a with c

    WRITE(*,"(F10.5)") r ! write result vector to screen

    END PROGRAM conversion_if

    The IF statement allows to deviate from the usual line by line execution. If the expres-sion in the IF statement is true, all statements between THEN and ENDIF are executed.The expression in the parenthesis of the IF statement must yield a logical value. Suchlogical expressions are frequently build from comparison between (numerical values),where the following relational operators for comparison between numerical expressionsare allowed

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 11

    < >=

    corresponding to less, less or equal, equal, not equal, larger, and larger or equal.

    1.5 A first look at the DO statement

    PROGRAM conversion_DO

    INTEGER, PARAMETER :: n = 5

    INTEGER :: i

    REAL :: a, r

    REAL, PARAMETER :: c= 4.186

    WRITE(*,*) "convert cal to Joules"

    DO i=1,n

    READ(*,*) a ! read in five values and store in a

    r=a*c

    WRITE(*,*) i,a,r ! write result to screen

    ENDDO

    WRITE(*,*) "das wars"

    END PROGRAM conversion_DO

    The DO statement also allows to deviate from the usual line by line execution of aPROGRAM. The statement between the lines DO and ENDDO are executed n times. In thebody of the loop (between the statements DO and ENDDO) the variable i will take onthe values

    1 first execution

    2 second execution

    3

    ...

    n n.th execution

    It is even possible to do calculations using the value of the variable i. For instanceexpressions such as

    r=a*c*i

    are allowed.

    2 A little bit more complicated: Types, LOOPs

    and IFs

    Let us assume we want to convert a set of numbers from calories to joules. The followingprogram will do exactly this:

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 12

    PROGRAM conversion3

    INTEGER, PARAMETER :: n = 5

    REAL :: a(n), r(n)

    REAL, PARAMETER :: c= 4.186

    WRITE(*,*) "convert cal to Joules"

    READ(*,*) a ! read in five values and store in a

    r= a * c ! multiply each value of a with c

    WRITE(*,"(F10.5)") r ! write result vector to screen

    END PROGRAM conversion3

    Thats a couple of new things to digest.

    2.1 Concept of types

    F90 is a strongly typed language; any constant or variable must have a specific type.F90 supports 5 intrinsic types with constants and variables for each of these types. Forcompleteness, all types are listed below together with an example for literal constantsof this type:

    INTEGER 123 -15 +3

    REAL 1.5 100.76 1.5E+10 1.5

    COMPLEX (1.5,1) (1.5,0.3)

    CHARACTER(LEN=40) "1234" Hallo "Georgs"

    LOGICAL .TRUE. .FALSE.

    Note:

    REAL constants have a dot, or exponentiation symbol E (single precision) orD (double precision), whereas INTEGER constants neither have a dot nor anexponentiation symbol.

    CHARACTER constants are enclosed in double quotes () or single quotes (). Thereis no difference between single and double quotes.

    If CHARACTER constants go over more than one line, a continuation letter shouldbe used at the end of the current and at the beginning of next line:

    "Hallo this is &

    &a test"

    A LOGICAL constant, can take only the values .TRUE. or .FALSE.. Abbrevia-tions are not allowed in the source code.

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 13

    2.1.1 Specification of variables and named constants

    A specification statement creates space for a variable with a specific name, and possiblyinitialises the variable. Since F90 is a strongly typed language, each variable must haveone specific type when it is declared, and it can store only values of this type.

    Examples for the declaration of the five available types are given below:

    INTEGER :: loop=0, i, j

    REAL :: x, y=0

    COMPLEX :: c

    CHARACTER :: s1*(20), s2*(20) ! a string variable

    ! that can hold 20 characters

    CHARACTER(LEN=20) :: s1, s2 ! same as above

    Named constants are created by adding the PARAMETER attribute:

    REAL, PARAMETER :: cal_to_joule= 4.186, stop_value=-1

    A named constant can not be overwritten in other places of the program. As already ex-plained, this makes the program saver, more readable and less prone to programmingerrors.

    2.1.2 Single precision and double precision

    All CPUs currently on the market allow for the native manipulation of single precisionand double precision floating point and integer numbers. Single precision numbers arestored in a binary format in four bytes (32 bits), whereas double precision numbersare stored in 8 bytes (64 bits), and the precise data layout is defined in the IEEE 754standard for floating point numbers shown below:

    float or REAL 1 word 4 bytes 32 bits

    31 30 0

    sign Mantisse

    double 2 word 8 bytes 64 bits

    63 62 051

    22

    Exponent

    sign Exponent Mantisse

    For single precision floating point numbers, 24 bits are reserved for the sign and themantissa, and 8 bits for the exponent. This allows for 7-8 significant digits in thedecimal system and a range of values between 1045 1038.

    For double precision floating point numbers, 53 bits are reserved for the sign andthe mantissa, and 11 bits for the exponent. This allows for 15-16 significant digits inthe decimal system and a range of values between 10324 10308.

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 14

    The most important issue to recall is that numbers are stored in the binary system,and that only a finite number of digits is stored. Some numbers that can be exactlyrepresented in the decimal system become periodic bit-streams in the binary system.This even applies to simple numbers such as 0.1 in the decimal system. The finiteprecision has significant impact on the exactness of the final solution, an issue that willbe discussed in much more detail in the lectures Scientific Computing.

    2.1.3 KIND attribute

    Fortran allows to declare single precision and double precision numbers. This appliesto both floating point as well as integer numbers.

    Appending an underscore ( ) and an integer constant (named or literal) specifiesthe number of bytes used in the internal representation:

    INTEGER, PARAMETER :: prec=8

    123_4 12.3E-12_8 123.4E-15_4 12.4_4 12.4_5 (1.5_8,0.3)

    123_prec 12.3E-10_prec

    Here 4 implies a single precision floating point number or integer, whereas 8 impliesa double precision floating point number or integer.

    For variables, the KIND attribute can be used to specify the number of bytes usedin the internal representation:

    INTEGER(KIND=4) INTEGER(4) INTEGER(8)

    REAL(KIND=4) REAL(4) REAL(8)

    COMPLEX(KIND=4) COMPLEX(4) COMPLEX(8)

    The keyword KIND= is optional, and can be omitted (although we recommend to useit to improve the clarity of the code). Furthermore some compilers allow for quadrupleprecision by using KIND=16. Use of quadruple precision, however, always leads to se-vere performance penalty, since current processors do not directly support quadrupleprecision, and the corresponding calculations must be emulated using double precisionoperations.

    For CHARACTERs, the KIND attribute is not allowed. In this case, the value in paren-theses specifies the number of characters in the string (length)

    CHARACTER (LEN=4):: string ! preferred definition

    CHARACTER (4):: string ! correct but somewhat confusing

    CHARACTER :: string(4) ! defines a vector with 4 single characters

    Note that the last specification statement is not equivalent to the first two. In this casea vector is defined. In this vector each element can hold a strong with one character(one character is the default length).

    To make the programs portable, it is advisable to specify the precision at the verybeginning of the program using a named constant, and to declare all variables andconstants with the appropriate KIND attribute:

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 15

    INTEGER, PARAMETER :: p=8

    REAL ( KIND=p ) :: a,b

    INTEGER ( KIND=p ) :: i,j

    INTEGER ( p ) :: k

    REAL ( p ) :: pi=3.14159388_p

    If this rule is observed everywhere in the program, the precision of the program can beeasily changed at a later point.

    To make programs even more portable it is also possible to specify the desirednumber of digits in the mantissa using the internal function SELECTED REAL KIND

    INTEGER, PARAMETER :: psingle=SELECTED_REAL_KIND(6)

    INTEGER, PARAMETER :: pdouble=SELECTED_REAL_KIND(12)

    REAL ( KIND=psingle ) :: pi=3.14159388_psingle

    SELECTED REAL KIND(n) returns an integer that is sufficiently large that a vari-able of this kind can store numbers with at least n significant digits in the dec-imal system. For current CPUs SELECTED REAL KIND(6) always returns 4, andSELECTED REAL KIND(12) always returns 8.

    2.1.4 Implicit typing: IMPLICIT NONE

    Most Fortran compiler allow to introduce and use variables without explicitly specify-ing them in the declaration part of the PROGRAM. The convention is that all variablesstarting with I-N are automatically declared as INTEGER variables, whereas all vari-ables starting with A-H and O-Z are automatically declared as REAL. This behaviourwas commonly in Fortran 77, but it is not particularly safe. For instance typing errorsare difficult to spot. As shown in the example program below.

    PROGRAM notalot

    DO I0=1,10 ! the variable I0 is implicitly typed

    WRITE(*,*) IO ! typo IO instead of I0 (zero)

    ENDDO

    END PROGRAM

    We recommend to switch the implicit typing off by including the statement IMPLICITNONE before declaring any variable.

    2.2 Vectors, Matrices and Tensors

    Fortran is a language designed to convert mathematical expressions directly into a F90expression, and since vectors and matrices are very often used by scientists, these twodata types are natively supported by Fortran 90.

    A vector-variable is defined by placing parentheses after the name of the variable:

    REAL :: a(5), r(5) ! the variables x and y can store 5 values

    INTEGER, PARAMETER :: n = 5

    REAL :: a(n),r(n) ! sames as above

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 16

    In an expression, each element of the vector can be addressed with the name of thevariable followed by an integer index in parentheses. The lowest and largest allowedindices are 1 and n, respectively. If we want to multiply the five numbers stored in thevector a by a constant, we could use:

    r(1) = c*a(1)

    r(2) = c*a(2)

    r(3) = c*a(3)

    r(4) = c*a(4)

    r(5) = c*a(5)

    This is obviously not particularly elegant, since whenever the constant n is changed,we would need to change the program. In F90, however, vectors can be manipulatedin the same way as simple scalars: we can, for instance, multiply each element of thevector a by a number c and store the result in a second vector:

    r= c * a ! multiply each value of a with c

    This is very similar to the usual mathematical expression

    ~r = c~a.

    Fortran of course also supports matrices. The declaration is very similar to vectors, onejust needs to add additional dimensions in the declaration:

    REAL :: m(5,5) ! a real valued matrix with 5x5 entries

    INTEGER, PARAMETER :: n = 5

    REAL :: m2(n,n)

    Elements of the matrix can be accessed in a similar way as that of vectors

    m=0 ! initialise all elements of the matrix to 0

    m(1,1) = 1 ! set one element

    m2 = 2 * m ! multiply each element of the matrix by 2

    m2 = m + m ! same as above

    WRITE(*,*) m ! print out the entire matrix

    2.2.1 Input and output statements

    Input and output statements operate on vectors in the same way as on scalars. Inthe example program conversion3, the READ statement reads n numbers from thekeyboard (the numbers must be separated by , or commas ,).Conversely, the WRITE statement writes the entire vector to the screen.

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 17

    2.2.2 DO loops

    We can write the conversion3 program using DO loops instead of the vector constructs.Although this is not particularly elegant, we will use it to illustrate the concept ofloops. As indicated before, we could have used the following construct to multiply eachelement of the vector with a constant:

    r(1) = c*a(1)

    r(2) = c*a(2)

    r(3) = c*a(3)

    r(4) = c*a(4)

    r(5) = c*a(5)

    With a loop we can write a much more portable program, which again requires nomodifications when n is changed.

    PROGRAM conversion4

    INTEGER, PARAMETER :: n = 5

    INTEGER :: i

    REAL :: a(5), r(5)

    REAL, PARAMETER :: c= 4.186

    WRITE(*,*) "convert cal to Joules"

    READ(*,*) a ! read in five values and store in a

    DO i=1,n

    r(i)=a(i)*c

    ENDDO

    WRITE(*,"(F10.5)") r ! write result vector to screen

    END PROGRAM conversion4

    In the construct

    DO i=1,n

    r(i)=a(i)*c

    ENDDO scale

    the assignment r(i)=a(i)*c is executed five times, with i taking the values 1, 2, 3, 4and 5.

    In general, the DO statement has the following form:

    [name:] DO var=expr1,expr2[,expr3]

    f90-statement

    ...

    f90-statement

    ENDDO [name]

    Here and in the following, terms in brackets [] are optional. var is an integer variable(which must be declared somewhere at the beginning of the program) and expr1,

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 18

    expr2 and expr3 are three integer expressions. The expression expr1 is used as theinitial value for var, expr2 specifies the final value, and expr3 the step-size. If expr3is missing, a step-size of 1 is used (this is the case in the previous examples).

    Optionally, a DO loop can be given a name. In this case, the name must be placedbefore the DO statement (followed by a colon), and after the ENDDO statement (withouta colon !). In few cases, this can make the program easier to read and maintain, butexcessive use of named-DO loops is not recommended.

    Between the DO and ENDDO statement any number of legal F90 statements can beplaced. These statements are executed for the variable var taking on the values

    expr1, expr1+expr3, expr1+2*expr3, ... , expr1+ k*expr3

    In the do loop, var will be always less or equal expr2. Therefore, if expr2 is smallerthan expr1, the loop is not executed (zero trip loop). It is easy to show that the loopis executed exactly ic times:

    ic = max((expr2 expr1+ expr3)/expr3, 0).

    The final value of the variable var outside the loop is well defined and given by

    expr1+ icexpr3

    In our previous example, the variable i is 6 after the loop. One way to memorise thisis that this is the first value for which the loop is not executed!

    It is also possible to program infinite loops using the following construct:

    [name:] DO

    f90-statement

    ...

    f90-statement

    ENDDO [name]

    where the loop can be terminated anywhere inside the body using the exit statement:

    EXIT [name]

    2.3 Infinite loops: the conversion program again

    To illustrate infinite loops in combination with an EXIT statement, we use anotherversion of the conversion program:

    PROGRAM conversion5

    REAL :: a, result

    LOGICAL :: is_zero

    DO

    WRITE(*,*) "please type in a number to convert, 0 to end"

    READ(*,*) a

    is_zero = a==0

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 19

    IF (is_zero) EXIT

    result = a * 4.186

    WRITE(*,"(F10.5)") result

    ENDDO

    ! exit jumps right here and the program stops

    WRITE(*,*) "stopping now"

    END PROGRAM conversion5

    This version of the program asks the user to input numbers and terminates, if the usertypes in 0 followed by a . This example also introduces the IF statement, andthe concept of logical or boolean variables. We have already mentioned, that logicalvariables can only take on the values .TRUE. and .FALSE.. An assignment to a logicalvariable works in essentially the same way as an assignment to a real or integer variable:

    logical_variable=logical_expression

    A logical expression is usually constructed by a comparison between two numericalexpressions using one of the scalar relational operators:

    < >=

    logical_expression: numerical_exp relational_operator numerical_exp

    For the operation < the result is .TRUE., if the first numerical expression is smaller thanthe second numerical expression, and .FALSE. in other cases. Other scalar relationaloperators, work essentially along the same line. Therefore, in our example program,the variable is zero will be set to .TRUE. only if the variable a is zero, otherwise thevalue .FALSE. will be assigned to the variable is zero.

    The variable is zero is tested in the IF statement. The statement after the IFstatement is only executed if the logical expression is .TRUE. Therefore, the programwill exit the loop, if the user types a 0 followed by on the keyboard.

    The variable is zero was mainly introduced to illustrate the concept of logicalvariables. In most cases, one would simply replace the two statements

    is_zero = a==0

    IF (is_zero) EXIT

    by the single statement:

    IF (a==0) EXIT

    2.4 The IF construct in more detail

    In fact, there are two versions of the IF construct in F90. The short one is:

    IF (scalar-logical-expr) stmt

  • 2 A LITTLE BIT MORE COMPLICATED: TYPES, LOOPS AND IFS 20

    The parentheses ( and ) around the logical expression are mandatory. The state-ment stmt must be placed on the same line as the IF statement and is only executed ifthe scalar-logical-expr is .TRUE.. The simple IF construct, allows to execute onlya single expression conditionally.

    To handle more complex cases, the IF THEN construct can be used.

    [name:] IF (scalar-logical-expr) THEN

    f90-statement

    ...

    f90-statement

    ENDIF [name]

    Similar to the DO statement, the name is optional (both the IF and ENDIF statementsmust be named or unnamed). The parentheses surrounding the scalar-logical-exprare again mandatory. The statements enclosed in the IF and ENDIF block are onlyexecuted if the scalar-logical-expr is .TRUE..

    A slightly more elaborated version of the IF statement is the IF ELSEIF ENDIFconstruct:

    [name:] IF (scalar-logical-expr1) THEN

    block1

    [ ELSE IF (scalar-logical-expr2) THEN [name]

    block2

    [ ELSEIF (scalar-logical-expr3) THEN [name]

    block3

    [ ELSE [name]

    block_else of f90-statements

    ]

    ]

    ]

    ENDIF [name]

    Here terms in brackets [] are again optional. In principle this construct worksexactly as one would expect. If scalar-logical-expr1 is .TRUE., block1 is exe-cuted. If this expression is .FALSE. and scalar-logical-expr2 is .TRUE., block2is executed. If scalar-logical-expr1 and scalar-logical-expr2 are .FALSE. andscalar-logical-expr3 is .TRUE., block3 is executed. If none of the scalar logical ex-pressions are .TRUE., the final block block else is executed. Mind, that one block isexecuted at most (if the ELSE clause is missing, possibly no block is executed).

    2.5 A small example program: a calculator

    PROGRAM calculator

    REAL :: res, a

    CHARACTER (LEN=1) :: operation

    res=0

  • 3 EXPRESSIONS AND ASSIGNMENTS IN MORE DETAIL 21

    DO

    WRITE(*,*) result ,res

    READ(*,*) operation

    READ(*,*) a

    IF (operation == *) THEN

    res=res*a

    ELSE IF (operation == +) THEN

    res=res+a

    ELSE IF (operation == -) THEN

    res=res-a

    ELSE IF (operation == /) THEN

    res=res/a

    ELSE

    EXIT

    ENDIF

    ENDDO

    END PROGRAM calculator

    3 Expressions and assignments in more detail

    We have now discussed sufficient examples to have a closer look at the way expressionsand assignments are constructed and handled in F90. The essential idea to keep inmind is that F90 maps quite naturally from mathematical expressions to statements.The formula

    f(x) = a+ bx+ cx2

    can be programmed in F90 as:

    f = a+ b*x + c*x**2

    Mind that the multiplication symbol * must be used; a simple blank between twovariables or constants is not interpreted as a multiplication:

    f = a+ b x + c x**2 ! compiler will report an error

    In general, we can distinguish two classes of operators:

    dyadic (binary) operators: + - * / ** .AND. .OR. for instance

    expr1 + expr2

    monadic (unary) operators: - .NOT. for instance

    .NOT. expr1 - expr2

    A dyadic operator operates on two operands (one to the left and the other one to theright of the operator), whereas a monadic operator requires only one operand after theoperator. Legal operands are any legal f90 expression: constants, variables, functioncalls and expressions (possibly in parentheses).

  • 3 EXPRESSIONS AND ASSIGNMENTS IN MORE DETAIL 22

    3.1 Scalar numerical expressions and assignment

    For scalar numerical expressions, the allowed operands are INTEGER, REAL or COMPLEXscalars (constants, variables, function calls or F90 expressions in parentheses). Thefollowing operations are supported:

    ** exponentiation

    * / multiplication and division

    + - sum and difference

    + - unary operators (change of sign)

    The order of precedence is the same as in mathematical expressions

    f = a+ b*x + c*x**2*2 ! a + (b*x) + ((c*(x**2))*2)

    but parentheses can be used to regroup the expressions:

    f = a+ b*x + (c*x)**2*2

    F90 supports mixed type expressions, where conversions from one type to the othertype are automatically handled according to the following rules:

    operand 2 Int Real Complex

    operand 1

    Int Int Real Complex

    Real Real Real Complex

    Complex Complex Complex Complex

    A scalar-assignment has the form:

    numerical_variable=numerical_expression

    Again, conversions are done automatically. It is, for instance, possible (but dangerous)to assign a floating point number to an integer variable. In this case, the digits afterthe comma are simply removed. Conversely, it is also possible to assign an integer valueto a floating point number (with less adverse side effects than in the opposite case)

    3.2 Scalar character expressions and assignment

    Only the concatenation of strings is supported. Legal operands are CHARACTERS (con-stants, variables or function calls). The dyadic operand is

    // concatenation

    The assignment of a character expression to a character variable is again very simple:

    character_variable=character_expression

    Some illustrations:

  • 3 EXPRESSIONS AND ASSIGNMENTS IN MORE DETAIL 23

    CHARACTER (LEN=4):: c

    c = "HE" // "LLO WORLD" ! -> HELL

    c = "H" ! -> "H "

    c(1:2)= "HELLO WORLD"

    c(3:4)= "HELLO WORD"(7:8) ! -> "HEWO"

    Here subindexing is use. The syntax

    character_string(integer_exp_1 : integer_exp_2)

    creates a substring of the original string, that spans from the integer exp 1 characterto the integer exp 2 character. This construct can be used for character constantsas well as for character variables in an expression as well as in the assignment. In theexample above c(3:4)=, overwrites the 3rd and 4th character in the string c with thestring WO.

    3.3 Scalar relational operators

    A scalar relational operation takes two INTEGER, REAL, COMPLEX or CHARACTER ex-pressions as arguments and yields as a result one logical value. The following operationsare allowed (where the second is preferred):

    .LT. < less than

    .LE. greater than

    .GE. >= greater or equal

    Again a few examples:

    LOGICAL :: f

    f= "Hello"(1:2) == "He" ! -> .TRUE.

    f= 1.5 < 1 ! -> .FALSE.

    3.4 Scalar logical operators

    A Scalar logical operator can operate only on logical expressions (constants, variablesor function calls). The following operations are supported:

    .NOT. unary negation

    .AND.

    .OR.

    .EQV. and .NEQV.

    LOGICAL :: f

    REAL :: a = 1.5

    f= 1 < a .AND. a < 2 ! a between 1 and 2

    f = 1 < a < 2 ! ** not allowed **

    f= .NOT. (a < 1) ! same as a >= 1

  • 3 EXPRESSIONS AND ASSIGNMENTS IN MORE DETAIL 24

    3.5 Precedence

    The order of precedence is given in the following table:

    ---- monadic user defined

    ** numerical expression

    * /

    + -

    // character concatenation

    < > == relational

    .NOT. logical expression

    .AND.

    .OR.

    .EQV. .NEQV.

    ---- dyadic user defined

    Monadic user defined functions are executed first, than exponentiation ** is performed,followed by multiplications and divisions, and so on. Parentheses can be used to changethe order of precedence.

  • 3 EXPRESSIONS AND ASSIGNMENTS IN MORE DETAIL 25

    3.6 Array-Expressions and array-assignment

    One exceptional feature of Fortran90 is that any operation can be applied to arrays.There are however some (quite natural) restrictions:

    Arrays used in array expressions must be conformable, i.e., they must have thesame number of dimensions and the same number of elements!

    operations are always done element by element!

    REAL :: a(5),b(5),c(5)

    c= a*b

    is the same as

    c(1)= a(1)*b(1)

    c(2)= a(2)*b(2)

    ...

    One operand may be scalar:

    REAL :: a(5),c(5),b

    c= a*b

    is equivalent to

    c(1)= a(1)*b

    c(2)= a(2)*b

    ...

    For assignments similar rules apply:

    An array expression may be assigned to an array, if both are conform-able. (i.e.have the same dimensions and the same number of elements).

    Scalars can be assigned to arrays:

    REAL :: a(5), b=1.5

    a=b ! each element of the vector a is set to 1.5

    Here are some additional examples:

    REAL, DIMENSION(10):: x,y,z

    z = x /y ! z_i = x_i/ y_i i=1,2,...,10

    z = x + 1 ! z_i = x_i +1

    z = x * 2 ! z_i = x_i *2

    z = 0 ! z_i =0

  • 4 SOME EXAMPLE PROGRAMS 26

    4 Some example programs

    4.1 Sum of input values

    PROGRAM sum

    INTEGER, PARAMETER :: n=5

    INTEGER :: i

    REAL :: a(n), suma

    READ(*,*) a

    suma=0

    DO i=1,n

    suma=suma+a(i)

    ENDDO

    WRITE(*,*) sum is ,suma

    END PROGRAM sum

    The statement suma=suma+a(i) is discussed in more detail in the section 5.1.

    4.2 Mean square deviation

    PROGRAM var

    INTEGER, PARAMETER :: n=5

    REAL :: a(n), suma, suma2

    READ(*,*) a

    suma=0

    suma2=0

    DO i=1,n

    suma=suma+a(i)

    suma2=suma2+a(i)**2

    ENDDO

    WRITE(*,*) sqrt(suma2/n-(suma/n)**2)

    END PROGRAM var

    4.3 Minimum

    PROGRAM minimum

    INTEGER, PARAMETER :: n=5

    REAL :: a(n), amin

    INTEGER :: i, ifound

    READ(*,*) a

    ifound=1

    amin=a(1)

    DO i=2,n

    IF ( a(i) < amin) THEN

    ifound=i

  • 4 SOME EXAMPLE PROGRAMS 27

    amin=a(i)

    ENDIF

    ENDDO

    WRITE(*,*) amin, found at ,ifound

    END PROGRAM minimum

    4.4 Sorting

    PROGRAM sort

    INTEGER, PARAMETER :: n=5

    INTEGER :: a(n), amin, j, i, ifound

    READ(*,*) a

    DO j=1,n

    ifound=j ; amin=a(j)

    DO i=j+1,n

    IF ( a(i) < amin) THEN

    ifound=i

    amin=a(i)

    ENDIF

    ENDDO

    a(ifound)=a(j) ; a(j)=amin ! swap data

    ENDDO

    WRITE(*,*) a

    END PROGRAM sort

    4.5 Inproduct

    PROGRAM dotprod

    INTEGER, PARAMETER :: n=5

    INTEGER :: j

    REAL :: a(n), b(n), cdot

    READ(*,*) a ; READ(*,*) b

    cdot=0

    DO j=1,n

    cdot=cdot+a(j)*b(j)

    ENDDO

    WRITE(*,*) cdot

    END PROGRAM dotprod

    4.6 Matrix times Vector

    PROGRAM mat_vec

    INTEGER, PARAMETER :: n=2

    INTEGER :: i, j

  • 5 FUNCTIONS AND MODULES: THE MEAN VALUE AGAIN 28

    REAL :: a(n,n), b(n), c(n)

    READ(*,*) a ; READ(*,*) b

    c=0

    DO j=1,n

    DO i=1,n

    c(j)=c(j)+a(j,i)*b(i)

    ENDDO

    ENDDO

    WRITE(*,*) c

    END PROGRAM mat_vec

    5 FUNCTIONS and MODULES: the mean value

    again

    5.1 Mean value

    To calculate the mean value of a set of numbers we use the following simple program:

    PROGRAM calculate_mean1

    REAL :: m

    INTEGER, PARAMETER :: n=5

    REAL :: a(n)

    WRITE(*,*) "now please type in ",n," numbers"

    READ(*,*) a

    ! calculate mean value

    WRITE(*,"(F10.5)") m

    END PROGRAM calculate_mean1

    The program is supposed to calculate the mean value of a set of five values, but therequired lines for the calculation are still missing. The simplest f90 statement thatperforms the required calculation is (calculate mean1.f):

    m=(a(1)+a(2)+a(3)+a(4)+a(5))/n

    Obviously, this is again not a particular elegant way of calculating the sum, sincewhenever the named constant n is changed, we need to change the program as well. Oneway of calculating the sum is to use DO loops as discussed before (calculate mean2.f):

    INTEGER :: i ! must be placed in the declaration part

    m =0

    DO i=1,n

  • 5 FUNCTIONS AND MODULES: THE MEAN VALUE AGAIN 29

    m=m+a(i)

    ENDDO

    m=m/n

    Only one peculiar new feature needs to be discussed:

    m=m+a(i)

    In F90 (and most other programming languages), the expression to the right of theequation sign is evaluated first, and then the calculated value is stored back in thevariable to the left of the assignment! If we work step by step through the program,we realise that m is initialised to 0 outside the loop. When the loop is executed for thefirst time, m is set to 0 + a(1). Then i is increased to 2, and the statements in the DOENDDO block are executed again. This time m is set to a(1) + a(2). Therefore, afterthe fifth loop, m has the desired value.

    5.2 Functions and Modules

    To make the program more readable we will now place the routine that calculates themean value into a separate module (calculate mean3.f):

    MODULE statistics

    CONTAINS

    FUNCTION mean(b)

    REAL :: b(:)

    REAL :: mean

    INTEGER :: n, i

    n=size(b)

    mean =0

    DO i=1,n

    mean=mean+b(i)

    ENDDO

    mean=mean/n

    END FUNCTION

    END MODULE statistics

    Whenever we want to calculate the mean value we can now simply use the followingstatements:

    USE statistics ! must be placed at the beginning

    ! of the declaration part before IMPLICIT NONE

    m=mean(a)

    A module provides a wrapper for a set of variables and a set of functions and subrou-tines. All variables, functions and subroutines defined in the module can be importedto other programs or modules by using the USE statement.

  • 5 FUNCTIONS AND MODULES: THE MEAN VALUE AGAIN 30

    In a module, functions and subroutines must be defined after the CONTAINS state-ment. When the function mean is called, the dummy argument b in the function isreplaced by the actual argument a. The actual argument must have the same defini-tion as the dummy argument: a real argument can be passed only to a real dummyvariable, and an integer argument only to an integer dummy argument. Vectors canobviously be passed only to vector arguments.

    In the previous example, the vector b in the function mean assumes automaticallythe size of the vector a in the calling routine, and by means of the SIZE() function,the actual (current) size of the vector in the function can be determined. Once thefunction has finished, the control is transfered back to the calling program, and thelink between the dummy argument and the actual argument is removed. The functionmight now be called by another routine with a different vector.

    The function mean also introduces two new variables n and i. These two variablesare only accessible inside the subroutine, and, actually, storage for these two variablesis only made available, when the function is called. After the function is left, n and iloose their values.

    We can now easily extend the program to calculate the variance (actually this is notquite the usual definition of the variance, but here we do not care for such subtleties):

    =a2 a2,

    where a stands for the mean value of a. We simply rewrite this as

    = sqrt{mean(a2)mean(a)2

    },

    which can be coded in Fortran as:

    sigma = SQRT( mean(a**2) - mean(a)**2)

    Clearly this is simple and more elegant than coding a seperate DO loop!

    5.3 Sorting again

    A nice demonstration how to use functions is the following version of the simple sortalgorithm already implemented above. This version declares a subroutine minpos thatlocates the minimum value in a vector and passes back the position of the minimumvalue. The main program then swaps the minimum value (located at minpos) with thecurrent top of the vector. Not only does this avoid the complicted nested loops we haveencountered before, it also separates the entire task into two much simpler tasks thatare easier to code.

    MODULE some

    CONTAINS

    FUNCTION minpos( a)

    INTEGER :: a(:)

    INTEGER :: minpos

  • 5 FUNCTIONS AND MODULES: THE MEAN VALUE AGAIN 31

    ! local

    INTEGER :: i

    minpos=1

    DO i=2, SIZE(a)

    IF ( a(i)

  • 5 FUNCTIONS AND MODULES: THE MEAN VALUE AGAIN 32

    CALL mean_and_variance(a, m, sigma)

    When the subroutine is called, the dummy variables b, m, and variance are linked to thereal arguments a, m, and sigma. Whenever one of the dummy arguments is modified, thecorresponding actual argument (a, m, and sigma) is also modified. This allows to passthe new values back to the main program. Mind, that the same rules (modificationof actual arguments) are true for function calls, but it is generally considered badprogramming practice to rely on such side effects in functions. In other words, onlysubroutines are supposed to modify the content of dummy arguments.

    5.5 Built-in Functions

    One final note about functions: F90 offers a built-in function that can be used tocalculate the sum of all elements of a vector. This function is called SUM, and can beused to calculate the mean value and the variance in two simple statements:

    m=SUM(a)/n

    sigma = SQRT( (SUM(a**2)/n) - m**2),

    Generally F90 supports a larger variety of so called built-in or intrinsic func-tions. We have already encountered three of them: the SUM, SQRT and theSIZE functions. For a complete and concise list of functions we refer tohttp://www.nsc.liu.se/ boein/f77to90/a5.html.

    The following list gives an overview of the commonly used mathematical functions.The arguments of these functions can be either REAL(KIND=4) (R), REAL(KIND=8) (D) orCOMPLEX (D). It is generally recommended to use the Generic name whereever possibleinstead of the Specific name.

    Function Generic Specific Data type

    name name Arg Res

    Square root SQRT SQRT R R

    DSQRT D D

    CSQRT C C

    Exponential EXP EXP R R

    DEXP D D

    CEXP C C

    Natural LOG ALOG R R

    logarithm DLOG D D

    CLOG C C

    Common LOG10 ALOG10 R R

    logarithm DLOG10 D D

  • 5 FUNCTIONS AND MODULES: THE MEAN VALUE AGAIN 33

    Sine SIN SIN R R

    DSIN D D

    CSIN C C

    Cosine COS COS R R

    DCOS D D

    CCOS C C

    Tangent TAN TAN R R

    DTAN D D

    Arcsine ASIN ASIN R R

    DASIN D D

    Arccosine ACOS ACOS R R

    DACOS D D

    Arctangent ATAN ATAN R R

    DATAN D D

    ATAN2 ATAN2 2R R

    DATAN2 2D D

    Hyperbolic SINH SINH R R

    sine DSINH D D

    Hyperbolic COSH COSH R R

    cosine DCOSH D D

    Hyperbolic TANH TANH R R

    tangent DTANH D D

    A list of the most important numerical functions is given below (again the use of thegeneric name is recommended):

    Function Generic Specific Data type

    name name Arg Res

    Conversion INT - I I

    to integer * INT R I

    (of the real part) - C I

    Rounding NINT NINT R I

    IDNINT D I

    Conversion REAL * REAL I R

  • 5 FUNCTIONS AND MODULES: THE MEAN VALUE AGAIN 34

    to real

    Conversion CMPLX - I (2I) C

    to complex - R (2R) C

    - D (2D) C

    Absolute ABS IABS I I

    value ABS R R

    DABS D D

    Remainder MOD MOD 2I I

    AMOD 2R R

    DMOD 2D D

    MODULO - 2I I

    - 2R R

    - 2D D

    Maximum MAX * MAX0 I I

    * AMAX1 R R

    * DMAX1 D D

    Minimum MIN * MIN0 I I

    * AMIN1 R R

    * DMIN1 D D

    Imaginary part - AIMAG C R

    Conjugate - CONJG C C

    The function INT truncates towards zero, i.e. INT(-3.7) becomes -3. Whereas NINTrounds towards the next nearest integer number as one would expected (i.e. NINT(-3.7)becomes -4 and NINT(-3.2) becomes -3).The function REAL(integer [, KIND=4]) converts to a single precision real, andREAL(integer, KIND=8) converts to a double precision real.

    The function MOD(X,Y) calculates X - INT(X/Y)*Y, whereas MODULO is the correctmathematical modulo function:

    MOD (8,5) gives 3 MODULO (8,5) gives 3

    MOD (-8,5) gives -3 MODULO (-8,5) gives 2

    MOD (8,-5) gives 3 MODULO (8,-5) gives -2

    MOD (-8,-5) gives -3 MODULO (-8,-5) gives -3

    MAX and MIN require a least two arguments of the same type and return the maximumand minimum value of all supplied values.

  • 5 FUNCTIONS AND MODULES: THE MEAN VALUE AGAIN 35

    5.6 Lets add some extra flexibility

    Our mean value program is still limited to five input values. Although we could inprinciple recompile the program, whenever we want to change n, it would be better ifwe could ask the user to type in n.We can achieve this with a few minor modifications in the program(calculate mean5.f):

    PROGRAM calculate_mean5

    USE statistics

    REAL :: m, sigma

    INTEGER :: n

    REAL, ALLOCATABLE :: a(:)

    WRITE(*,*) "how many numbers do you want to type in ?"

    READ(*,*) n

    ALLOCATE(a(n))

    WRITE(*,*) "now please type in the numbers"

    READ(*,*) a

    ! calculate mean value

    m = mean(a)

    sigma=SQRT( mean(a**2) - m**2)

    WRITE(*,"(F10.5)") m,sigma

    DEALLOCATE(a)

    END PROGRAM calculate_mean5

    The declaration

    REAL, ALLOCATABLE :: a(:)

    Declares a vector a but leaves the actual size undetermined yet. The size of the vectoris determined later in the program with the ALLOCATE statement:

    ALLOCATE(a(n))

    The allocated space is freed by calling the DEALLOCATE statement.

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 36

    6 PROGRAM units and MODULES in more detail

    A F90 program consists of

    one main program (enclosed in the PROGRAM and END PROGRAM statements)

    internal procedures (not recommended)

    external procedures (not recommended)

    a collection of modules (usually placed in separate source files)

    and intrinsic procedures (i.e. built in procedures).

    A MODULE is a collection of variables, functions and subroutines. Generally, all dataand variables are local to a module, program or procedure, with the following importantexceptions:

    The names of modules and external procedures are global. Usually, names arenot case sensitivity.

    All subroutines and functions in a module can be made available using the USEstatement. Variables defined in a module before the CONTAINS statement are alsomade accessible by the USE statement.

    6.1 The Main PROGRAM

    The main program must be defined in the following way:

    PROGRAM program-name

    specification-stmts

    executable-stmts

    [ CONTAINS

    internal-subprograms ]

    END [ PROGRAM [program-name]]

    where terms in brackets are optional as before. The CONTAINS statement indicatesthat internal procedures follow. These procedures are not executed automatically, butcan be called from the main program (they can be accessed only from the main pro-gram). Internal procedures are only used very rarely and will not be discussed in detail,since they decrease code re-usability. Instead procedures should be defined in separateMODULES.

    Specification statements specification-stmts are for instance USE statements orthe declaration of variables:

    INTEGER, PARAMETER :: i=10

    REAL :: a , b(i,i)

    All USE statements must be placed before other declaration statements.executable-stmts are assignments, control statements (DO, IF) and IO-statementsetc.

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 37

    6.2 External procedure

    The general syntax for an external procedure is:

    [ RECURSIVE ]

    SUBROUTINE subroutine-name [ ( [ dummy-arg-list] ) ]

    FUNCTION function-name ( [ dummy-arg-list] )

    specification-stmts

    executable-stmts

    [ CONTAINS

    internal-subprograms ]

    END [ SUBROUTINE [subroutine-name]]

    END [ FUNCTION [function-name]]

    The RETURN, END or CONTAINS statement transfer the control back to the calling routine.The CONTAINS statement introduces procedures that are local to this procedure. Gen-erally external procedures should be used with care, since when an external procedureis called from a program, the number of arguments and the types of the arguments arenot checked against the dummy argument list. This leads to many unnecessary errorsduring programming.

    Internal procedures are similar to external procedures but must not have a CONTAINSclause (remember, internal procedures are defined within the CONTAINS clause of ansurrounding subroutine, program or module). For internal procedures, the dummy ar-gument list is checked by the compiler against the argument list of the calling routine.

    6.3 Modules

    Whenever possible new functions and procedures should be defined within a MODULE.The general syntax of a module is specified below:

    [ MODULE modul-name]

    specification-stmts

    [ CONTAINS

    module-subprograms ]

    END [ MODULE [modul-name]]

    The simplest MODULE might contain only the definition of global variables, for in-stance, the definition of useful constants:

    MODULE constants

    REAL, PARAMTER :: cal_to_joule= 4.186

    REAL,PARAMETER :: pi =3.14159265358979323,tpi=2*pi

    END MODULE

    But usually a module contains derived data type definitions and a collection of sub-routines. To use a module the statement

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 38

    USE modul-name

    must be placed in the program or procedure that wants to call subroutines from thismodule.

    The syntax for a module subprogram is similar as that for an external subprogrambut the END SUBROUTINE/END FUNCTION statements are mandatory (in an externalsubprogram it is sufficient to write END instead of END SUBROUTINE).

    6.4 Order of statements

    The order of statements is rather strict in F90, as mentioned before. Below a summaryhow statements must be placed is show:

    PROGRAM, FUNCTION, SUBROUTINE, MODULE statements

    USE statements

    IMPLICIT statements

    derived type definition

    variable declarations

    executable statements

    CONTAINS

    internal or module procedures

    END PROGRAM, FUNCTION, SUBROUTINE, MODULE statements

    Mind that the USE statements must be placed at the very beginning of the program.

    6.5 Dummy arguments - actual arguments - local variables

    In Fortran 90, arguments are passed by reference. We have already briefly elaboratedon this feature, and we will now discuss it in more detail. Consider for instance thefollowing small subroutine

    SUBROUTINE add(dum1,dum2,dum3)

    REAL :: dum1, dum2, dum3

    dum1=dum2+dum3

    END SUBROUTINE add

    If this subroutine is called, by the statement

    CALL add(a,b,c)

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 39

    it is exactly the same as writing:

    a=b+c

    The variables dum1, dum2 and dum3 are called dummy arguments, and a, b and c arecalled actual arguments. Fortran behaves as if we would have cut and pasted the codefrom the subroutine body to the calling routine, replacing every occurrence of thedummy argument by the corresponding actual argument.

    We can describe this behaviour in another way: upon calling a subroutine, thedummy arguments are linked to the same storage position as the actual arguments:

    dummy argument dum1

    variable a storage unit for a

    vector a

    vector dummy argument dum1

    storage unit for a(1)storage unit for a(2)storage unit for a(3)

    Whenever the dummy argument dum1 is modified, the contents of the variable ais also changed. Actually this description is very close to what the compiler does inreality. This behaviour is called call by reference, as opposed to the call by valuemodel used by such programming languages as C. In the call by reference model, anymodification of the dummy argument will automatically change the actual argument(remember both variables point to the same storage unit). Generally the call by ref-erence model is more flexible, but has the disadvantage of being much more prone toprogramming errors than the call by value model. Side effects (modifications of thevariables passed down by the calling routine) are difficult to control in F90 and requirethe programmers to carefully document their programs.

    6.5.1 Local variables

    All procedures can have their own set of local variables. These variables are not acces-sible to any other procedure or program. Storage for these variables is usually created,when the procedure is called, and such variables loose their values, when the subroutineis left. If this behaviour is not desirable, the SAVE attribute can be used to protect thevariable.

    INTEGER, SAVE :: init

    This feature can be used to initialise certain values in a subroutine, and we will see anexample in a minute.

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 40

    6.6 Functions

    In Fortran, functions behave in exactly the same manner as subroutines. The only dif-ference is that they return a value, and that they are called differently than subroutines.Functions are defined by the following clause:

    [ RECURSIVE ]

    FUNCTION function-name ( [ dummy-arg-list] ) RESULT (func_res)

    specification-stmts

    executable-stmts

    END [ FUNCTION [function-name]]

    A function is called by an expression of the form:

    function-name ( [ actual-arg-list] )

    The RESULT(func res) clause is optional and creates a variable with the namefunc res, which must be declared and set to a value before exiting. If the RESULTclause is missing, the name of variable is the function-name. The result of a functionmay be any type (scalar, arrays or pointers). In all other respects, functions behave likeprocedures, in particular, they can change any of the values of their actual arguments.This however is not recommended, since such side effects are difficult to control. If afunction has to return two values, either a vector should be returned or a subroutineshould be used.

    6.7 Examples

    6.7.1 Modules for storing constants

    MODULE constants

    REAL, PARAMTER :: cal_to_joule= 4.186

    REAL,PARAMETER :: pi =3.14159265358979323,tpi=2*pi

    END MODULE

    6.7.2 Reverse polish calculator

    MODULE simple_stack

    INTEGER, PARAMETER :: nmax=4

    REAL :: a(nmax)

    INTEGER :: nstored=0

    CONTAINS

    SUBROUTINE push(value)

    REAL :: value

    nstored=nstored+1

    IF (nstored>nmax) THEN

    WRITE(*,*) stack exhausted

    STOP

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 41

    ENDIF

    a(nstored)=value

    END SUBROUTINE push

    FUNCTION pop()

    REAL :: pop

    IF (nstored

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 42

    INTEGER(8):: f,n

    IF (n

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 43

    ELSE

    fac2=table(n)

    ENDIF

    END FUNCTION fac2

    The only new feature is the STOP command, which immediately stops the execution ofthe program.

    6.10 Scope

    Scope tells us, where a particular variable, function, subroutine or defined type isknown. F90 uses a fairly simple lexical scoping scheme:

    Labels are always local to a procedure (labels have not been discussed, since theiruse is strongly discouraged).

    Names: F90 has only one name space, which is local to one programming unit.Only the name of the programming unit is known to the outside world (it isglobal). This implies that

    derived types,

    variables,

    and subroutines and functions

    must have different names to distinguish them from each other inside one unit.One can not, for instance, define a function and a variable with the same namein the same programming unit, although context would often allow to distinguishboth (in C this is possible and allowed):

    MODULE test

    REAL :: f=1.2

    CONTAINS

    FUNCTION f(x) ! illegal, since f was already defined above

    Different programming units may use the same names. These names are local tothe unit in which they are defined.

    MODULE test

    REAL :: f=1.2, pi = 3.1415926

    END MODULE test

    MODULE test2

    REAL :: pi = 3.1415 ! thats a different pi

    CONTAINS

    FUNCTION f(x) ! this is legal

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 44

    Names defined inside other units become available be means of the use associa-tion. All named entities of a module are made available with the statement

    USE modul

    Names which are imported with the use command, can be redeclared but thesyntax will not be discussed in this lecture, since it this feature is rarely used.

    USE test2

    REAL :: pi = 3.1415926 ! illegal since pi is defined in test2

    USE test

    USE test2 ! illegal since pi is defined in both modules

    Host association: Internal procedures, derived type definitions, and moduleprocedures know all names of the surrounding block. But in contrast to theUSE association, names can be redeclared locally!

    MODULE test

    REAL :: x

    CONTAINS

    SUBROUTINE set_x_local(y)

    REAL :: x, y ! x differs from first x

    x=y

    END SUBROUTINE set_x_local

    SUBROUTINE set_x(y)

    REAL :: y

    x=y ! this will set the x define in the MODULE header

    END SUBROUTINE set_x

    END MODULE

    This is actually a feature leading to errors which are very difficult to find. Thereforenever use internal subroutines.

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 45

    6.11 Passing functions as arguments

    The last important feature of F90, that we will discuss in this section, is how to pass thename of a function to a procedure. Why is this necessary in the first place? Considerthat we want to write a general MODULE for integrating a function. Obviously we wouldlike to pass the name of the function for which the integral must be calculated to thismodule. Exactly this is done in the following example program:

    MODULE functions

    CONTAINS

    FUNCTION f1(x) ! f1(x) = x^2

    REAL :: f1,x

    f1=x**2

    END FUNCTION f1

    FUNCTION f2(x) ! f2(x) = e^x

    REAL :: f2,x

    f2=exp(x)

    END FUNCTION f2

    END MODULE functions

    MODULE integrate

    CONTAINS

    FUNCTION simple_int(f,xstart,xend,intersections)

    INTERFACE

    FUNCTION f(y); REAL :: f,y; END FUNCTION

    END INTERFACE

    REAL :: simple_int,xstart,xend,d

    INTEGER:: intersections,i

    simple_int=0

    d=(xend-xstart)/(intersections-1)

    DO i=0,intersections-1

    simple_int=simple_int + f(xstart+d*i)*d

    ENDDO

    END FUNCTION simple_int

    END MODULE integrate

    PROGRAM test

    USE functions

    USE integrate

    IMPLICIT NONE

    REAL a,b

    WRITE(*,*) simple_int(f1,0.,1.,100),simple_int(f2,0.,1.,100)

    END PROGRAM test

  • 6 PROGRAM UNITS AND MODULES IN MORE DETAIL 46

    The only new feature we encounter here is the INTERFACE statement (which is shownbelow in a slightly more expanded form):

    INTERFACE

    FUNCTION f(y)

    REAL :: f,y

    END FUNCTION

    END INTERFACE

    This statement tells the compiler two things. First, it specifies that f is not a con-ventional dummy variable but a dummy function. It also tells the compiler whicharguments this function takes, and which type of value the function returns. Betweenthe INTERFACE and the END INTERFACE statements, any number of declaration state-ments can be placed. Usually we will place here all declaration statements found in theactual function definition, but no executable statements (the body of the function).Please compare the INTERFACE statement with the actual definition of the functionsf1 and f2. The names of the variables have of course changed, but their types agreewith that of f1 and f2.

    When the function simple int is called the first time, the dummy function f islinked to the machine executable code of the function f1, and simple int is executedonce.

    machine code for f1

    machine code for f1

    function f1

    dummy argument dum1

    Whenever the function f is now called in simple int, the code of the function f1 isexecuted. Upon the second call of simple int, the dummy argument is linked to thefunction f2.

  • 7 BORING BUT REQUIRED: INPUT AND OUTPUT 47

    7 Boring but required: Input and Output

    Output: transfers data from the program to the screen or filesInput: transfers data to the program from the keyboard or files

    As all other executable statments, input and output is performed at run-time. Duringthe execution, the program performs the required operations and continues after theuser has supplied the input.

    In Fortran, the location to which data is written or from which it is read is specifiedby an integer expression called a unit. Such units are similar to C file handles. InFortran, the following three units are preconnected:

    UNIT=5 ! stdin usually the keyboard

    UNIT=6 ! stdout usually the screen

    UNIT=0 ! stderr (usually also the screen)

    7.1 OPEN and CLOSE statements

    The OPEN and CLOSE statements are used to open or close a file:

    INTEGER :: u=10

    CHARCATER :: file=my_file

    OPEN([UNIT=] u, FILE=file)

    CLOSE([UNIT=] u)

    Here file is a string (any legal string expression), and u an integer expression. Thesecommands establish a connection between the file with the name file, and the unitwith the number u. If the file does not exist, it is created on the hard disc when theOPEN command is encountered. From now on, the unit number can be used to write orread data from the file with the READ or WRITE commands:

    REAL :: A=12

    OPEN(10,FILE=data) ! create the file data

    WRITE(10,*) A*2+1 ! write the value of A*2+1 to file data

    CLOSE(10)

    After the execution of the commands, the content of the file data can be inspectedwith an editor (for instance Xemacs).

    7.2 READ, WRITE statements

    The syntax of the READ and WRITE statements is indicated below:

    READ ( [UNIT=] u, [FMT=] fmt) [iolist]

    WRITE( [UNIT=] u, [FMT=] fmt) [iolist]

  • 7 BORING BUT REQUIRED: INPUT AND OUTPUT 48

    The integer expression u specifies the unit to which the operation is performed, andthe format specification fmt specifies the format that is used for the IO. As always,terms in square brackets [] are optional. The units 5 and 6 are preconnected, andsince most people lack a good memory, F90 allows to use the * instead of thesetwo numbers: READ(*,*) is the same as READ(5,*); and WRITE(*,*) is the same asWRITE(6,*).

    The ftm specification might be either

    a star * (List directed input/output)

    or a string.

    a line number refering to a FORMAT statement (not covered in this lecture).

    The iolist consists of a list of comma separated expressions or implied do-loops.For the READ statement, the expressions must be expressions which can also be locatedon the left hand side of an assignment (usually variables or vectors).

    7.3 List directed input/output, FMT= *

    The simplest version for the FMT specifier is the star. It allows to read or write anarbitrary number of items:

    WRITE(*,FMT=*)"Number of datas and comment"

    READ(*,FMT=*) n,comment

    WRITE(UNIT=*,*)Please input ,n,data

    READ(*,*) (a(i),i=1,n)

    This requires e.g. the following input:

    3 "test"

    1.5 2.3

    2.4

    It is quite usual to use list directed input, but the list directed output looks prettyugly and the way the output is performed depends on the compiler. Therefore, we willconcentrate on list directed input.List directed inputWhen the compiled Fortran program is executed and a READ statement is encountered,the program stops, and the user is required to perform the input. The input mustconform to the following guidelines:

    In the input, each item must be separated by a blank, a comma, a slash or anend of record mark (newline).

    If the slash / is found in the file or typed on the keyboard, the input statementterminates immediately (end of file condition).

  • 7 BORING BUT REQUIRED: INPUT AND OUTPUT 49

    It is possible to specify a repeat count on the input line: 3*3.5 is the same istyping 3.5 three times.

    The allowed input for logical variables is T and F.

    Strings must be enclosed in delimiters (they might go over several records). Ifstrings are not enclosed by delimiters, the string must not contain a blank, acomma or a slash.

    For complex numbers two numbers must be specified in brackets:

    ( 1E4 separator 1.456 )

    where separator is a blank, a comma or a newline.

    7.4 Formated input/output

    Formated output makes the output of a program more readable. Each item in theformat must correspond to one item in the input/output list.

    INTEGER :: i

    REAL :: flt

    WRITE(*,(I10,F10.3,A10)) i,flt*2,hello

    WRITE(*,FMT=(I10,F10.3,A10)) i*2+1,flt,hello

    READ (*,(I10,F10.3,A10)) i,flt,hello

    Here the edit descriptor I10 is used for the integer expression i, the edit descriptorF10.3 for the real expression flt*2, and the edit descriptor A10 for the characterexpression hello.

    7.5 Edit descriptors

    A format specification is a list of edit descriptors separated by commas, and possiblygrouped with parentheses. The list of edit descriptors must be enclosed in at leastone parentheses (see previous examples). The following list shows the most importantformat specifications.

    I integer rIw

    F fixed real rFw.d

    E exponential real rEw.d rEw.dEe

    L logical rLw

    A character rAw

    G general rGw.d rGw.dEe

    X blank rX

    / new-line r/

  • 7 BORING BUT REQUIRED: INPUT AND OUTPUT 50

    r repeat countw width of the output fieldd number of decimal digits after the decimal pointe number of digits in the exponential

    In F90, the output is generally centred to the right. The repeat count specifies, howmany numbers, strings or logical values can be written using the corresponding editdescriptor.

    The repeat count is particularly useful to output vectors or matrices, but it can beapplied to any list of expressions:

    INTEGER :: i

    REAL :: f(10),a,b

    WRITE(*,(5F10.5)) f ! prints out the 10 numbers in the vector f

    WRITE(*,FMT=(5F10.5)) a,b ! prints out two numbers a and b

    If the list of edit descriptors is exhausted, a new line is generated and the list of editdescriptors is repeated from the beginning. It is allowed, to use an editor descriptorwith more items than in the io-list.

    7.5.1 Grouping edit descriptors

    It is possible to group edit descriptors, with parentheses and to put a repeat countbefore the parenthesis. The following format specification

    (3(2F10.4,5X))

    allows to read or write 6 double precision numbers, where two numbers are grouped to-gether without additional blanks in-between. The groups are separated by 5 additionalblanks:

    dd.dddd dd.dddd~~~~~ dd.dddd dd.dddd~~~~~ dd.dddd dd.dddd

    1234567890123456789012345678901234567890123456789012345678901234567890

    0 1 2 3 4 5 6 7

    If a format list is exhausted, the last group in parentheses is repeated. If no groupingwith parentheses exists, a newline is generated and the format is repeated from thevery beginning (see above). This is illustrated below:

    WRITE(*,(I10,F10.3)) i,a,j,b

    is

    iiii aa.aaa

    jjj bbbb.bbb

    1234567890123456789012345678901234567890123456789012345678901234567890

    0 1 2 3 4 5 6 7

  • 7 BORING BUT REQUIRED: INPUT AND OUTPUT 51

    7.5.2 Integer Format (I-Format): rIw

    Upon output: the numbers are printed adjusted to the right in a field of width w:

    WRITE(8,(2I10)) 12,156

    12 156

    1234567890123456789012345678901234567890123456789012345678901234567890

    0 1 2 3 4 5 6 7

    Upon input: read w characters from the record and convert to integer (blanks areremove):

    READ(8,(2I5)) i,j

    For the following input, the variables i and j will be set to the values shown below:

    12 156 -> i=12 j=156

    1 2156 -> i=12 j=156

    1234512345

    7.5.3 Float Format (F-Format): rFw.d

    Output: the number is printed adjusted to the right with d decimal digits, rounding isdone automatically:

    WRITE(*,(F8.3)) 13.568924

    13.569

    1234567890123456789012345678901234567890123456789012345678901234567890

    0 1 2 3 4 5 6 7

    Input: read w characters from the record, remove all blanks. If no decimal point exists,one is inserted at the position d from the right (after the removal of all blanks!) andfinally the string is convert to a floating point number:

    READ(*,(F10.3)) a

    13.569 -> 13.569

    1233 -> 1.233 (decimal point inserted at 3. pos)

    1 3 4 -> .134 (blanks removed, dec. point ins. at 3. pos)

    1.E10 -> 1E10

    1E10 -> unpredictable since a dec. point is inserted

    not to be used !!!!

    1234567890123456789012345678901234567890123456789012345678901234567890

    0 1 2 3 4 5 6 7

    Use of formated input for keyboard input can lead to undesired results and is hencenot recommended.

  • 7 BORING BUT REQUIRED: INPUT AND OUTPUT 52

    7.5.4 Exponential Format (E-Format): rEw.d or rEw.dEe

    Upon input, this format behaves in exactly the same manner as the F format.For output it produces the following string: s.ddddEveeee

    blanks to fill the available spaces signd mantissa with d digitsv sign of exponente exponential with e digits (default 2 or 3)

    It is recommended to set the field width to at least w = z+e+5 . If the Ee specificationis missing, the field width should be at least w = z+8 .

    7.5.5 Logical Format (L-Format): rLw

    Output: T or F in the right-most position.Input: first character differing from and dot . is used to decide, whether theinput is true or false:

    LOGICAL :: L

    READ(*,(L3)) L

    T -> L= .TRUE.

    .Txx -> L= .TRUE.

    F -> L= .FALSE.

    7.5.6 Character Format (A-Format): rAw

    Output: string is printed out centred to right. If w is too short, the rightmost charactersof the string are not printed.

    WRITE(*,(A10,A10)) "Hello world",right

    Hello worl right

    1234567890123456789012345678901234567890123456789012345678901234567890

    0 1 2 3 4 5 6 7

    Upon input, the next w characters are read from the keayboard or file and stored inthe specified variable.

    7.5.7 General Format (G-Format): rGw.dEe

    The general format is used rather rarely. It allows, in principle, to read or write anyexpression. For more details we refer to a F90 manual.

    7.5.8 Blank Format (X-Format): rX

    Output: transfers n blanks to the file or screen.Input: skips over n characters.

  • 7 BORING BUT REQUIRED: INPUT AND OUTPUT 53

    7.5.9 New Record (/-Format): r/

    Output: start a new record (newline).Input: go to next record (even if the current one has not been finished).

  • 8 MORE ABOUT ARRAYS 54

    8 More about arrays

    Arrays are natively support in F90 and far more flexible than discussed in the mainlectures. Arrays can have any dimension, and the array bounds need not to start at1. Dimensions can be specified either with the DIMENSION attribute or in parenthesesafter the name of the variable. The general syntax for the specification of an array isgiven below:

    DIMENSION(extent-list) or variable_name(extent-list)

    extent: [lower :] upper

    Here an extent-list is a list of extents, which are comma separated. An extentconsists of an optional lower bound and an upper bound for the array index. Thedefault for the lower bound is 1. Below are few examples for the specification of arrays:

    REAL, DIMENSION(3) :: x,y ! simple vector

    INTEGER, PARAMETER :: n=50, m=100

    REAL :: rho(0:n,0:m), vel(3,0:n,0:m) ! rho is a matrix

    ! vel is a tensor of rank 3

    REAL, DIMENSION(3,3) :: a,b ! two matrices

    REAL :: c(-10:3) ! a vector

    The storage layout of arrays has not been changed since F77 and is a row firstordering. This meant that a matrix with 3 3 elements

    a(1,1) a(1,2) a(1,3)

    a(2,1) a(2,2) a(2,3)

    a(3,1) a(3,2) a(3,3)

    is stored in the memory in the following manner (first row first, then second row andso on):

    a(1,1) a(2,1) a(3,1) a(1,2) a(2,2) a(3,2) a(1,3) a(2,3) a(3,3)

    This is important for the optimisation of program. If arrays are used in nested DO loops,one should try to make the first index of all arrays the innermost variable of the DOloop.

    8.1 Literal constants

    Literal constants for arrays are constructed by enclosing a list of literal real or integerconstants in (/ and /):

    (/ 2, 4, 3 /)

  • 8 MORE ABOUT ARRAYS 55

    8.2 Array constructors

    A more flexible way to specify arrays is the array constructor. The general syntax forthis is

    array = (expression, var=expr1, expr2, expr3)

    The variable var takes on all values it would take in a DO loop of the form:

    DO var=expr1, expr2, expr3

    This is called implicit DO loop. For any of the possible values of var one element is addedto the final vector. Such implicit DO loops can be nested as shown in the examples below:

    (/ (i,i=1,7,2) /) % same as (/1,3,5,7/)

    (/ (j*i,i=1,3),j=1,3) /) % matrix

    8.3 Rank, shape and size

    The rank of an array, i.e. the number of dimensions, can be changed only during compiletime and is fixed in the source code. The shape and size of an array can be determinedduring run-time using the following commands (with examples assuming the previousdeclarations):

    shape: sequence of extents, SHAPE(rho) (/ 51, 101/)size: total number of elements, SIZE(rho) 5151

    The extent of an array is the upper bound minus the lower bound plus 1.For multidimensional arrays, the number of elements in each dimension can be

    determined using the following construct

    REAL :: a(5,-1:10)

    WRITE(*,*) SIZE(a,1) ! number of elements along first dim (i.e. 5)

    WRITE(*,*) SIZE(a,2) ! number of elements along 2nd dim (i.e. 12)

    8.4 Array-Section

    It is possible to address only parts of an array using array-sections. This is an extremelyflexible and powerful feature that often allows to avoid complicated DO loops. Somesimple examples are indicated below:

    x(1:2) ! same as vector (/ x(1), x(2) /)

    rho(:,1) ! vector that equals the first column of rho

    rho(3,:) ! vector that equals the third row of rho

    One can even select sub-parts of a matrix:

    rho(2:4,3:6)

    This selects only the area between the 2nd and 4th row and the 3rd and 6th column.

  • 8 MORE ABOUT ARRAYS 56

    8.5 Zero sized arrays

    If the lower bound of an array exceeds its upper bound, the array is called zero sizearray. All intrinsic subroutines and all F90 expressions can handle such arrays (nooperation for zero sized arrays).

    8.6 Assumed shape array

    This feature was already encountered before. In subroutines, dummy arguments assumethe shape of actual arguments. Unfortunately the number of dimensions must agreewith the calling routine, which limits the usefulness of the feature somewhat.

    REAL :: a(3:12),m(10,10)

    CALL t(a,m)

    SUBROUTINE t(b,n)

    REAL :: b(:)

    REAL :: n (-1:,-1:)

    One important point is that only the extents (upper minus lower bounds plus 1) arepassed down to the subroutine, and the lower bound in the subroutine always defaultsto 1 (regardless of the lower bound in the calling routine). In the example above thelower bounds for the array n are -1 and the upper bounds are 8. Furthermore, in thesubroutine the element n(-1,-1) corresponds to m(1,1) in the calling routine, andn(8,8) to m(10,10).

    The general syntax for the declaration of an assumed shape array in a subroutineis:

    dummy-argument(extent-list)

    extent: [lower-bound:]

    (mind since, the extent is passed by the calling routine, only the lower bound can beset in the subroutine). The actual bounds of the array can be found by calling theSHAPE and SIZE functions:

    SIZE (b) ! total number of elements of b=a: 10

    SIZE (n) ! total number of elements of n=m: 100

    SIZE (b,1)! first extent, result is 10

    SIZE (n,1)! first extent of n=m is 10

    SIZE (n,2)! second extent of n=m is 10

    SHAPE(b) ! vector of extents, in this case (/10/)

    8.7 Automatic arrays

    In subroutines, it is often required to temporarily create an array that has the sameshape as an array passed to the subroutine. This can be done by means of automaticarrays:

  • 8 MORE ABOUT ARRAYS 57

    SUBROUTINE swap(a,b)

    REAL:: a(:), b(:), work(SIZE(a))

    work=a ; a=b; b=work

    END SUBROUTINE

    In this case, the array work is allocated from the stack or an internal heap and auto-matically freed after the RETURN statement or the end of the procedure.

    8.8 Elemental intrinsic functions

    All elemental intrinsic functions can be applied to arrays. The resulting array has thesame shape as the initial array:

    REAL, DIMENSION (10): a,b,c,d

    a=b+c

    d=SQRT(a)

    8.9 Array valued function

    The result of a function can be an array (for instance automatic objects):

    FUNCTION gurk(a)

    REAL:: a(:),gurk(size(a))

    gurk=a**2

    END FUNCTION

    In this case, the array gurk is freed when it is no longer needed by the calling routine.

    8.10 Allocatable arrays

    Arrays can be allocated at runtime using the ALLOCATE command. This feature wasalready discussed before, however, for completeness you can find another example be-low:

    REAL, ALLOCATABLE :: a(:,:), b(:)

    READ(*,*) n

    ALLOCATE(a(n,n),b(n))

    ...

    DEALLOCATE(a,b)