View
21
Download
0
Category
Preview:
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)
Recommended