Agenda
• Introduction, history
• Source format, gfortran
• Names, Program Structure, Variable Declaration
• Arrays
• Subprograms/Modules
Why Use Fortran?
• “The whole point of compilers, interpreters, layers of abstraction and what-not are to shorten the semantic distance between our intent and the way the computer thinks of things.”
• “… it often helps to have a language that makes expressing your intent very clear, concise, and above all, unambiguous.”– Scott Hansellman (computerzen.com)
Why Use Fortran?
• from the FORTRAN manual for the IBM 704 (1956), the goal of the FORTRAN creators was a language – “…closely resembling the ordinary language of
mathematics …”– “The result should be a considerable reduction
in the training required to program, as well as the time consumed in writing programs and eliminating their errors.”
Why Use Fortran?
• Fortran was designed from the outset (1954-1957) to do numerical computations– FORmula TRANslator
• again, from the IBM 704 (1956) FORTRAN manual:– “The FORTAN language is intended to be
capable of expressing any problem of numerical computation. In particular, it deals easily with problems containing large sets of formulae and many variables, …”
What is Fortran written in?
Compiler Maker Compiler name Source Code Language
GNU Compiler Collection g77, gfortran C
Portland Group pgf77, pgf90, pghpf C
Intel ifort C
SGI f77, f90 C
IBM f77, xlf, xlf90, xlf95 ?
Note: the point here is not that one language is “better” than the other. C is more suitable to doing operations that a compiler does, while Fortran is designed for numerical work – trying to write a compiler in Fortran would be hard. You can certainly do numerical work in C if you want to.
Fortran History
• Fortran is usually credited with being the first high-level programming language– the first language to use natural language
keywords•DO, REAL, INTEGER, …
– the first full language to be compiled• necessary because the computer can’t understand
the programming language
Fortran History
• John W. Backus and a group at IBM started to design the IBM Mathematical Formula Translating System, or Fortran0 in 1954
• the work was completed in 1957• the authors claimed that the
resulting code would be as efficient as handcrafted machine code– it was pretty close
Fortran History
• The IBM 704 Data Processing System was a large-scale computer designed for engineering and scientific calculations
• Fortran included many features that were specific to the IBM 704, the first computer on which it was implemented
http://www.fh-jena.de/~kleine/history/languages/FortranAutomaticCodingSystemForTheIBM704.pdf
Fortran History
• "The 704 is the first large-scale, commercially available computer to employ fully automatic floating point arithmetic commands. …”
• IBM 704 speed:– multiplies or divides in 240 microseconds
• approximately 4,000 operations per second
– floating point addition or subtraction operations require 84 microseconds
• approximately 12,000 operations per second
• 704 memory:– up to 32,768 36-bit words (32 kilo-words)
Fortran Standards
• Fortran was the first high level programming language to be standardized
• compiler vendors could create compilers that behaved in well defined and consistent ways
• programs are much more portable when they don’t depend on vendor specific features
Fortran Standards
Name Date Standard Definition
FORTRAN66 1966ANSI X3.9-1966 - the first standard for a
programming language
FORTRAN77 1977 ANSI X3.9-1978 and ISO 1539-1980
Fortran90 1991 ANSI X3.198-1992
Fortran95 Dec 1997 ISO/IEC 1539-1:1997
Fortran2003 Nov 2004 ISO/IEC 1539-1:2004
Fortran History
• Each new version of Fortran adds extensions to the language while retaining compatibility with previous versions
• For a long time Fortran was the dominant language of programming in scientific and engineering applications
• Now mostly used in High Performance Computing– lots of legacy codes being maintained and developed
Source Code Format
• originally Fortran source code was formatted according to rigid rules– different parts of statements had to fall in specific
column ranges• since Fortran 90/95 source code formatting is
free-form– allows arbitrary use of whitespace to format code
Free Form Source Code
• source file with one of the extensions:*.f90, *.f95, [*.hpf], [*.f03]
– files with extension in [] may be recognized by the compiler, but maybe not - it depends …
• a statement line can be up to 132 characters long
• ! indicates that the rest of the line is a comment – this can be anywhere
• & at the end of a line continues the line
Fixed Form Source Code
• source file with one of the extensions*.f, *.f77, [*.for]
• columns 1: ‘C’ or ‘*’ start a comment line• columns 1-5: reserved for statement labels• column 6: a character here is used to indicate
that a statement has been continued from the previous statement – can use any character except the number zero
• columns 7-72: Fortran statements go here• columns 73-80: characters past column 72 are
ignored
Fixed Form Source Code
• the fixed source format comes from the design of the 704 and the need to use 80 column punch cards
• the Hollerith card format:– cards have 12 rows and 80 columns – decimal digits are encoded in rows 0-9 – other characters are encoded using these rows plus rows 11-12 above
row 0
Fortran Alphabet
• Letters– A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
– upper and lower case letters are equivalent
• Digits– 0 1 2 3 4 5 6 7 8 9
• Special Characters– space ' " ( ) * + - / : = _ ! & $ ; < > % ? , . [ ] { } ~ ` | # ^ @
Fortran Features
• lots of built-in mathematical functions
• array operations– operations on array sections– use vector indices
• array indices can start and end on arbitrary values
• complex numbers as a fundamental data type– complex arithmetic as well, of course
The GNU Fortran Compiler
• part of the GNU compiler collection
• documentation online at– http://gcc.gnu.org/onlinedocs/gfortran/
• under development since 2000
• still a work in progress
• supports most of Fortran 77, 90, 95 and some of 2003
The GNU Fortran Compiler
• invoke the compiler with a command of the form
gfortran [options] input-file• many of the options are common to gcc with
some Fortran specific ones• for example, to compile a program contained in
a file named “MyCalc.f90”
gfortran –o MyCalc MyCalc.f90• the ‘–o’ option tells the compiler the name to
give the executable
The GNU Fortran Compiler
• some useful compiler options-O capital ‘Oh’– optimize the executable
-On n is an integer from 1 to 3– the compiler tries to reduce code size and execution time
-fbounds-check– check array subscripts against the declared minimum
and maximum values
-fopenmp– enable the OpenMP extensions
The GNU Fortran Compiler
• more useful compiler options
-Ldir– add directory dir to the list of directories to be searched
for libraries listed with -l
-llibrary-name– search the library named library when linking
-Idir– Add the directory dir to the head of the list of directories
to be searched for header files
Fortran Program Structure
• a basic Fortran program looks like this
• this is called the “main program unit”
• other program units start with the keywords: FUNCTION or SUBROUTINE
[program] MyProg
declarations
processing and I/O
end [program MyProg]
[ ] denote optional portions.
The program name can be included in the end statement only of the program statement is used.
Activity 1
• using a text editor, type the program into a file named “hello.f90”
• compile the programgfortran hello.f90
• run the program ./a.out
program HelloWorld
implicit none
! Declare variables
! Do work
print *, 'Hello World!'
end program HelloWorld
Input/Output
• to print something to the computer displayWrite(*, "(a)") ‘This is a string‘
• the ‘a’ is the format specifier for a string
• the format string must be inside'(…)' or "(…)"
Input/Output
• Fortran programs transfer data to and from external devices during their runs
• each device is associated with a Unit Number– the number is often in the range 1 to 99– the number cannot be negative
Input/Output
• to associate an external file with a unit use the OPEN() statement– OPEN(20, FILE=‘output.txt’)– OPEN(21, FILE=‘output.txt’, STATUS = 'NEW' )
– OPEN(22, FILE=‘output.txt’, STATUS = 'NEW‘, ERR = 100, IOSTAT = ErrNum)
Input/Output
Open(20, File='outfile.txt', &
Status='New')
Do i = 1, N
If ( i .NE. TestVal(i) ) Then
Write(20, "(I15)") i
End If
End Do
Close(20)
Input/Output
• Fortran has one function for data input and two for data output
• Input: – READ() - transfers input data from external
sequential, direct-access, or internal records
• Output– PRINT() - displays output on the screen
• on some systems TYPE is a synonym for PRINT
– WRITE() - transfers output data to external sequential, direct-access, or internal records
Input/Output
• The general format of READ and WRITE is– READ(clist) list ! clist == control list– WRITE(clist) list
• where the required parts of clist for both READ and WRITE are– [UNIT=] unit-number– [FMT=] format-spec
• and other arguments are optional.! note * refers to default settings READ(*, *) x, yWRITE(*, *) x, y
– the first asterisk refers to the default unit number and– the second is the list directed i/o format specifier
Format Specifier
• There are 3 ways to give a format specifier:
• 1) as an asterisk (*)– the is called list-directed i/o– the format is defined by the computer system
at the moment the statement is executed
Write(*,*) 'Product = ', x*y
Format Specifier
• 2) as a statement label referring to a FORMAT statement containing the specifier between parentheses– this is the Fortran 77 way to do it
Write(*, 100) x*y
100 Format('Product = ', f8.2)
Format Specifier
• 3) as a character expression whose value commences with a format specification in parentheses– this is what we do in the sample programs
Write(*,’(a,f8.2)’) &
'Product = ', x*y
Read(*,’(2f8.2)’) x, y
Edit Descriptors
• the format specification uses a set of descriptors – here are some common ones
• ‘A’ – character string– A20 – the field width is 20 characters
• ‘I’ – integers– I9 – integer field is 9 digits wide
• ‘F’ – floating point numbers– F9.3 – real field is 9 spaces wide with 3 digits to the right of the
decimal point
• ‘E’ – real values with exponents– E12.3E2 – real field is 12 spaces wide with 3 digits to the right
of the decimal point and 2 digits in the exponent field
Fortran Variable Types
• Fortran has five intrinsic variable types– INTEGER: a string of digits with an optional sign
• 0, 314, -4502
– REAL: decimal or exponential representation • 3.1416 or 3.1416E0• DOUBLE PRECISION gives a double length real
– COMPLEX: real and imaginary parts of type real• (1.23, -5.56)
– LOGICAL: 1 to 4 bytes but only 2 values• .FALSE. or .TRUE.
– CHARACTER: characters enclosed in “” or ‘’• ‘One string’ “Another string”
Variables
• variables can be declared using the appropriate data type statement:
INTEGER i, j, k
REAL radius(100), theta, phi
COMPLEX SphericalHarm
LOGICAL MoreData
CHARACTER(Len=80) TestString
Activity 2• using a text editor, type the program shown
in exercise 2 into a file named “io.f90”• compile the program
gfortran io.f90
• run the program./a.out
• modify the program to write the product of x and y (the multiplication operator is ‘*’)
Variables
• Fortran 90 defines a new syntax for declaring variables. The general form is:
TYPE [,attr] :: variable list
• where attr is a list of optional Fortran 90 attributes to further define the properties of variables
• variables can have attributes such as– PARAMETER, SAVE, ALLOCATABLE
Variables
• other attributes:– PARAMETER– PUBLIC– PRIVATE– TARGET– POINTER– INTENT– OPTIONAL
• the double colon (::) is optional unless ATTRIBUTES or an initialization expression are given
• a real 2-d array to allocate laterreal, allocatable :: x(:,:)
• an integer whose value is retained for the next function callint, save :: i
Error Conditions
• it is good practice to handle error conditions gracefully if possible
• if the program fails with a cryptic error message you’ll have to search to figure it out
Error Conditions
• some functions have the following specifiers:– IOSTAT– ERR
• for example, the OPEN statement• OPEN(22, FILE=‘output.txt’, STATUS = 'NEW‘, ERR = 100, IOSTAT = ErrNum)
Error Conditions
• IOSTAT is an integer variable:= 0 if no error occurs
> 0 (the number of the error message) if an error occurs
< 0 if an end-of-file record is encountered
• ERR is a label to transfer control to if an error condition occurs
• OPEN(22, FILE=‘output.txt’, STATUS = 'NEW‘, ERR = 100, IOSTAT = ErrNum)
Activity 3• using a text editor, make changes to your
program from activity 2 as shown in exercise 3 into a file named “io_test.f90”
• compile the programgfortran io_test.f90
• run the program./a.out
Variable Representation
• variables are basically pointers to some part of memory– the number of bytes is part of the declaration of the
variable ( default sizes are frequently 4 bytes)
Variables
• DOUBLE PRECISION values have precision greater than the real values on the machine
• to declare double precision real and complex variables use:
DOUBLE PRECISION theta, phi
DOUBLE COMPLEX SphericalHarm• note that DOUBLE COMPLEX isn’t in the standard• might have to use Kinds to get Double Complex
Integer Representation
• integers in Fortran are signed• INTEGER lengths can be 1, 2, 4, or 8 bytes• the default INTEGER length is 4 bytes
# of Bytes Min Value Max Value
1 -128 127
2 -32,768 32,767
4 -2,147,483,648 2,147,483,647
8 -9,223,372,036,854,775,808 9,223,372,036,854,775,807
Floating Point Representation
• there are ANSI/IEEE standards to define how floating point numbers are represented and behave in a computer
• IEEE Standard 754-1985– defines binary floating point arithmetic
• IEEE Standard 854-1987– defines decimal floating point arithmetic
Floating Point Representation
• given a certain number of bytes allocated to a floating point number, how do we use the bytes to represent the sign, fractional part and the exponent?
• for a 4-byte REAL– 8 bits are for the (signed) exponent– 24 bits are for the (signed) mantissa
Floating Point Representation
• Span and Precision of IEEE 754 Floating-Point Formats
Format # of Bytes
Approximate Absolute Nonzero
Minimum
Approximate Absolute
Maximum
Approximate Precision (decimal digits)
Single 4 1.2E-38 3.4E+38 6 – 9
Double 8 2.2D-308 1.8D+308 15 – 17
Extended Double
≥ 10 ≤ 3.4D-4932 ≥ 1.2D+4932 ≥ 18 – 21
Quadruple 16 3.4Q-4932 1.2Q+4932 33 – 36
Floating Point Representation
• processors generally support single and double precision operations in hardware
• quadruple precision can be implemented in software– quadruple precision is not required by the
Fortran standard but is an extension in many compilers
– this can be slow
Floating Point Representation
• want to run our program on different machines using the same number of significant digits
• if we declare the variables as REAL the length is not certain
• use KINDS
Machine/Data Type Real Double Precision
IBM (SP) 6 15
Cray (T90) 15 33
Cray (T3E) 15 15
Fortran Names
• a name (identifier) must obey the following rules in Fortran 90/95– it can have up to 31 characters– the first character is a letter– remaining characters can be letters, digits or
the underscore– case of letters does not matter
•range, Range, rAnGe all point to the same memory location
Implicit Typing
• Fortran permits real and integer variables to be typed and declared implicitly without their being defined by declaration statements
• by default the types are given by the first letter of the variable name– integer: [i-n]– real: [a-h] and [o-z]
• this has been found to be poor programming practice …
Implicit Typing
• Fortran 90 allows us to disable implicit typing with the statement
IMPLICIT NONE• at the start of the program, function and
subroutine
• this helps reduce errors due to simple spelling mistakes
User-Defined Types
• Fortran 90 introduced user-defined types with the TYPE statement
• these are derived from intrinsic data types• a TYPE definition is required to define
– the name of the type, and – the names and types of its components
• a derived type is resolved into components that are either of intrinsic type or are pointers
User Defined Types
• define a type point • define a point origin
• assign values to the components– to reference the values
inside a point, use the % operator
TYPE point
real :: x, y, z
END TYPE point
TYPE(point) :: origin
origin%x = 0.0
origin%y = 0.0
origin%z = 0.0
Arithmetic Operators
• the basic mathematical operators in Fortran are shown in the table
• precedence order is:()
**
*, /
+, -
Math Fortran + +
- -
x *
÷ /
exponentiation **
parentheses ()
a+x*5/y**2-3*sin(z)**3
= a + ((x*5)/(y**2)) - (3*(sin(z)**3))
Activity 4• using a text editor, create a file “circle.f90”
and write a program which prompts you to input a radius from the terminal and then calculates the circumference and area of the circle
• compile and run the programgfortran circle.f90./a.out
Fortran Program Structure
• every Fortran program must have one and only one main program– The keyword
PROGRAM is optional– it can be followed by
the program name– END is required as the
last statement of the program
PROGRAM [name][specification statements][executable statements]...
END [PROGRAM [name]]
Specification Statements
• specification statements define the environment for the executable statements
IMPLICIT NONEINTEGER :: i, j, k
• type declaration statements integerrealcomplexcharacterlogicaltype(type-name)
Executable Statements
• the executable statements specify the actions that are to be performed– assignment operator– arithmetic operators– relational operators– loops– conditional branching– array operations
Relational Operators
• Fortran 90 includes alternative forms for the relational operators defined in FORTRAN 77
FORTRAN 77 Fortran 90
.LT. <
.LE. <=
.EQ. ==
.NE. /=
.GT. >
.GE. >= if (x < y) then
r = sqrt(y**2 – x**2)
end if
Intrinsic Mathematical Functions
• Fortran provides many intrinsic mathematical functions
• all trigonometric functions take arguments in radians
• the functions are defined only for floating point arguments, not integers– sqrt(4) causes ‘4’ to be converted to
floating point and the return value is a REAL
Intrinsic Mathematical Functions
• the generic names of the mathematical functions are given below– COS, ACOS– SIN, ASIN– TAN, ATAN, ATAN2– EXP, LOG, LOG10– COSH, SINH, TANH– SQRT
Flow Control
• Fortran includes a number of constructs to control the program flow– DO: controls the repeated execution of a
block of statements or constructs – IF: conditionally executes one statement
based on the value of a logical expression – CASE: conditionally executes one block of
constructs or statements depending on the value of a scalar expression
DO Construct
• controls the repeated execution of a block of statements or constructs
• this construct is called a loop
DO i=1, nstep, stepsize
block
END DO• nstep is the maximum value that the loop
variable will take• stepsize is the increment for the loop variable
DO Construct
• print the odd integers starting from 1 and less than 100
DO i=1, 100, 2 WRITE (*, "(a,I4)") 'I = ',i END DO
• I = 1• I = 3• …• I = 99
Implied DO Loop
• the implied DO loop is a shorthand notation useful for the following:– specify iteration of part of an I/O list – initialize an array– transfer part of an array – transfer array items in a sequence different
from the order of subscript progression
• cuts back on the number of lines of code required
Implied DO Loop
• in a data transfer statement, an implied-DO list acts as though it were a part of an I/O statement within a DO loop. It takes the following form:
(list, do-var = expr1, expr2 [,expr3])• list
– a list of variables, expressions, or constants
• do-var– the name of a scalar integer or real variable
– the variable must not be one of the input items in list
• expr– scalar numeric expressions of type integer or real. They do not all have
to be the same type, or the same type as the DO variable.
Implied DO Loop
• print the odd integers starting from 1 and less than 100
WRITE (*, 100) (i, i=1, 100, 2)100 Format(‘I = ’, I4)
> I = 1> I = 3> …> I = 99
• the implied DO can be nested
WRITE (6,150) ((FORM(K,L), L=1,10), K=1,10,2)
DO WHILE Construct
• execute the range of a DO construct while a specified condition remains true
i = 99DO WHILE (i>0) WRITE (*, "(a,I4)") 'I = ',i i = i - 2END DO
• I = 99• I = 97• …• I = 1
IF Construct
• conditionally executes one block of statements depending on the evaluation of a logical expression
IF (expr) THEN block
[ELSE IF (expr) THENblock] ...
[ELSEblock]
END IF• expr is a logical expression
Logical Operators• construct logical expressions with these operators
if ( (x<y) .AND. (y<z)) then
r = sqrt(y**2 – x**2)
end if
Operator Example Meaning.AND. a .AND. b expression is true if both a and b are true
.OR. a . OR. b expression is true if either a, b, or both, are true
.EQV. a . EQV. b expression is true if both a and b are true, or both are false
.NEQV. a . NEQV. b expression is true if either a or b is true, but false if both are true
.NOT. .NOT. b expression is true if b is false and false if b is true
IF Construct
• test values of x and deal with special ranges
IF ( x > 15.0 ) THEN
Call DealWithBigX(x)
ELSE IF ( x <= 0.0 ) THEN
Call DealWithLittleX(x)
ELSE
Call DealWithMediumX(x)
END IF
IF Statement
• when there is a single expression to evaluate
IF ( x + y < 4.0 ) &
z = sqrt( x**2 + y**2 )• a single statement
• no need to use THEN and END IF
SELECT CASE Construct
• conditionally executes one block of constructs or statements depending on the value of a scalar expression in a SELECT CASE statement
SELECT CASE (expr)[CASE (case-value)
block] ...[CASE DEFAULT
block]END SELECT
• expr scalar expression of type integer, logical, or character (enclosed in parentheses).
SELECT CASE Construct
SELECT CASE (i)CASE(1:3) ! Values: 1, 2, 3 …CASE(4) ! Values: 4 …CASE(5, 7, 9) ! Values: 5, 7, 9 …CASE(10:) ! Values: ≥10 …CASE DEFAULT ! Values: all others …
END SELECT
Command Line Arguments
• the Fortran 2003 standard defines some functions for dealing with command line arguments:
• GET_COMMAND()– Retrieve the entire command line that was used to invoke the
program.
• COMMAND_ARGUMENT_COUNT()– Returns the number of arguments passed on the command line
when the containing program was invoked.
• GET_COMMAND_ARGUMENT() – Retrieve the Nth argument that was passed on the command
line when the containing program was invoked.
Command Line Arguments
• one way to process the command line:– get the whole command line into a text buffer
• you might want to test the status of the get_command() function
– get the number of command arguments• check that things are still reasonable
Activity 5• either start from your program from activity
4, “circle.f90” or download files to start with from my web server, and modify your program to use a command line parameter as a radius, if there is one
• compile and run the programgfortran cir_cmdline.f90./a.out
Arrays
• much of numerical work requires manipulation of arrays– so Fortran provides lots of tools for arrays
• arrays can be declared by using: – a type declaration statement– DIMENSION– ALLOCATABLE– TARGET– or, POINTER or COMMON
Arrays
• for exampleREAL MyArr(-1:29, 15:36)
• defines a 2 dimensional array whose– first index takes on values [-1, 29]– second index takes on values [15, 36]
• the above is equivalent to using:REAL MyArr
Dimension MyArr(-1:29, 15:36)
Array Terminology
• an array declared like this
REAL :: X( 2, 5, -1:8 )• has:
– rank of 3 ! # of dimensions– extents of 2, 5, and 10! # in each dim– a shape of (/ 2, 5, 10 /)! vector of extents– a size of 100 ! # of values in array
• the shape of matrix A is a vector with rank(A) elements
Array Terminology• arrays declared like this
REAL :: X( 4:5, -1:8 )
REAL :: Y( 2, 10 )• have the same shape
– same rank and same extent in each dim
• they are said to be conformable • since the shapes are the same we can do
X = Sqrt(Y + 1.0)
→ X(4,-1) = Sqrt(Y(1,1) + 1.0)
Activity• given arrays declared as follows
REAL :: X( 4:5, -1:8 )
REAL :: Y( 2, 10 ), Z(10)
• which of these expressions are valid?
X = Y; Z = Y(:,5) – 3.0
Y = Z + 1.0; Y(3,:) = Z
X(4,:) = Z;X(5,:) = Z+Y(2,:)
Arrays
• Fortran stores higher dimensional arrays as a contiguous sequence of elements
• it is important to know that 2-dimensional arrays are stored by column – referred to as column-
major order– C uses row-major order
Fortran: elements stored in order -
[a11 a21 a31 a21 a22 a32 a13 a23 a33 ]
C: elements stored in order -
[a11 a12 a13 a21 a22 a23 a31 a32 a33 ]
Arrays
• the fact that the array elements are stored contiguously is part of the Fortran standard:
• this is from ISO/IEC 1539 : 1991 (E) section 14.6.3.1, item (6)– A nonpointer array of intrinsic type or sequence
derived type occupies a sequence of contiguous storage sequences, one for each array element, in array element order (6.2.2.2)
• in ISO/IEC 1539-1:2004(E) this is found in section 16.4.3.1, item (7)
Arrays
• why do we care about the array elements being in contiguous memory locations?– this is what allows us to count on
optimizations which access array elements in column orderdo j = 1, ny do i = 1, nx y(i, j) = DoSomething( y(i,j) ) end doend do
Activity 6• do calculations using the planetary data
• note: you DO NOT need to use do loops for this exercise
• compile and run the programgfortran planets.f90./a.out
Allocatable Arrays
• the bounds (and shape) of an allocatable array are determined when it is allocated
• allocatable arrays are given storage on the heap– Fortran also has Automatic Arrays– automatic arrays are allocated upon entry to
the defining subprogram and deallocated on return
– automatic arrays are allocated on the stack
Allocatable Arrays
• it is useful to be able to allocate and deallocate arrays as the program runs
REAL, Allocatable :: MyArr(:,:)• this declares a 2 dimensional array but no
memory is actually allocated• to allocate use
Allocate( MyArr(12,5:15) )– first dimension goes from 1 to 12– second dimension goes from 5 to 15
• release the memory with Deallocate( MyArr )
Allocatable Arrays
• the intrinsic function ALLOCATED() can be used to determine whether an allocatable array is currently allocated:
REAL, ALLOCATABLE :: E(:,:)
...
IF(.NOT.ALLOCATED(E)) ALLOCATE(E(2:4,7))
Allocatable Arrays
• recall that the Fortran standard specifies that arrays be allocated in a contiguous block of memory
• what happens if the memory is fragmented?
• want to allocate a 2 GB array• Fortran can’t do it!• test the allocation for an error
Allocatable Arrays
! Try to allocate 2.0 GB
real, allocatable :: x(:)
integer :: err
…
allocate(x(2.0GB),STAT=err)
if(err /= 0) stop
…
deallocate(x)
Array Expressions
• can write expressions containing arrays without explicitly writing do loops
Real x(10,10), y(10,10), z(10,10)
z = -x + 1.0 ! z(i,j) = - x(i,j) + 1.0
z = x * y ! z(i,j) = x(i,j) * y(i,j)
z = x / y ! z(i,j) = x(i,j) / y(i,j)
z = Sin( x ) ! z(i,j) = Sin( x(i,j) )
• the above requires arrays of the same shape
Array Functions
• many of Fortran’s intrinsic functions take arrays as arguments
• classify the functions as– elemental – operate on array elements
• get an array back of the same dimensions•y = SIN(x) ! sine of each element of x
– transformational• get a number or array of a different shape back•z = SUM(A) ! sums elements of A
Vector Multiplication
• vector multiplication:
DOT_PRODUCT(vector_a, vector_b)
• makes a scalar product of two vectors– must have the same length (same number of
elements)
• note that if VECTOR_A is of type COMPLEX the result is
SUM(CONJG(vector_a)*vector_b)
Matrix Multiplication
• matrix multiplication:
MATMUL(MATRIX_A, MATRIX_B)
• makes the matrix product of two matrices– must be consistent, i.e. have dimensions like
(M, K) and (K, N) – at least one of the matrices must be of rank 2
Array Sections
• an array section is a portion of the array
• we can address subsections of arrays using:– a subscript triplet
• [first-bound] : [last-bound] [:stride]
– a vector subscript• a one-dimensional array of integer values (within
the declared bounds for the dimension) that selects a section of a parent array
Array Sections
• define an array with 4 rows and 5 columns
Real x(1:4,1:5)
• x(1,1) is in the upper left corner
Array Sections
• the subscript triplet is used as followsReal x(10,10), y(10,10), z(3,5)
z = x(2:4,2:10:2) + y(1:5:2,1:9:2)
• the array sections of x and y are both the same size as z
• note that the correspondence is by position in the extent, not by subscript value– the order of scalar operations isn’t specified in the
Fortran standard to the compiler can arrange optimizations
Array Constructor
• an array constructor can be used to create and assign values to rank-one arrays (and array constants)
• the array constructor is denoted by:
(/ ... /) • the ellipsis is a list of values assigned to
the array elements and is created by expressions or implied do loops
Array Constructor
• use a list of numbers to give values to an array
Integer i ! Loop variableReal :: x(4)x = (/ 3, 6, 9, 12 /)write(*,"(4F6.1)") x
• gives the output 3.0 6.0 9.0 12.0
Array Constructor
• use an implied DO loop to give values to an array
Integer i ! Loop variableReal :: x(4)x = (/ (i, i=1, 4) /)write(*,"(4F6.1)") x
• gives the output 1.0 2.0 3.0 4.0
Array Constructor
• use the RESHAPE intrinsic function to change the shape of the array
• the second argument is the shape of the new array
• INTEGER :: :: list(2,3)• INTEGER :: x(6)• x = (/ 11,12,21,22,31,32 /)• list(2,3) = RESHAPE(x, (/2,3/))
Activity 7• use the RESHAPE() function
• compile and run the programgfortran shape.f90./a.out
• use at least one allocatable array to hold the results in this exercise
Masked Array Assignments
• Fortran includes two constructs for masked array assignments– WHERE : applies a logical test to an array on
an element-by-element basis • this is in Fortran 90
– FORALL : a generalization of WHERE• it allows more general array shapes to be assigned• this is in Fortran 95
Masked Array Assignments• a WHERE statement• initialize arrays A, B
and C• note that all elements
of C = -1 to start• for only the elements
of A that are not 0, do the calculation
• get the elements of C: -1, 11, 12, 13, -1
INTEGER A, B, C
DIMENSION A(5), & B(5), C(5)
DATA A /0,1,1,1,0/
DATA B & /10,11,12,13,14/
C = -1
WHERE(A .NE. 0) &
C = B / A
Masked Array Assignments• a WHERE construct• find the indices in the pressure array where the expression is true– do things to arrays with
those indices
• use the indices for which the condition is false to do other things
DIMENSION pressure(1000), temp(1000), precipitation(1000)
WHERE(pressure .GE. 1.0)
pressure = pressure+1.0
temp = temp - 10.0
ELSEWHERE
precipitation = .true.
ENDWHERE
Array Inquiry Functions
• we would like to be able to query an array to find out:– is it allocated?– how many elements are in the array?– the shape of the array– the lower and upper bounds
• Fortran 90 includes intrinsic functions for this
• useful when passing arrays to functions
Array Inquiry Functions
• ALLOCATED(ARR) – a logical function which indicates if the array is
allocated
• SIZE(ARR, dim)– returns the number of elements in ARR, if DIM is
not given, and the number of elements in the relevant dimension if DIM is included
• SHAPE(ARR)– returns the shape of an array ARR as an integer
vector
Array Inquiry Functions
• LBOUND(ARR, dim) – returns the lower dimension limit for ARR– if DIM (the dimension) is not given as an
argument, you get an integer vector, if DIM is included, you get the integer value with exactly that lower dimension limit, for which you asked
• UBOUND(ARR, dim) – similar to LBOUND which returns the upper
dimensional limits
Subprograms
• subprograms make programs more modular
• a subprogram solves a specific problem
• a subprogram is available for use anywhere in the program
• Fortran has two subprogram types–SUBROUTINES–FUNCTIONS
Subroutines
• a subroutine does not return any value and is the same as a void function in C/C++
• in Fortran all arguments are passed as the address of the variable in the calling program– referred to as call by reference in C/C++
• subroutines allow us to return any number of values through the arguments
Subroutines
! Calculate the spherical-polar radius! from 3 Cartesian coordinates and! return the radiusSUBROUTINE radius(x, y, z, r) Real, INTENT(IN) :: x, y, z Real, INTENT(OUT) :: r r = sqrt( x**2 + y**2 + z**2 )END SUBROUTINE radius
• INTENT(IN) and INTENT(OUT) prevent accidental changes of the variables in the calling program by generating an error at compile time
Functions
• a Fortran function takes a set of arguments
• it returns a value of some type
• the function type must be declared in the calling program
• functions end by using the end or return statements
Functions
• a Fortran function always return a value just like corresponding functions in C/C++! Calculate the spherical-polar radius! from 3 Cartesian coordinates and! return the radiusFUNCTION radius(x,y,z) RESULT(r) Real, INTENT(IN) :: x, y, z Real :: r r = Sqrt( x**2 + y**2 + z**2 )END FUNCTION radius
• note that the type of the variable in the RESULT statement is the type of the function
Arrays as Arguments
• the simple thing to do is make sure that the arrays have the same type and dimensions in the calling program and the subprogram
• get fancy with– explicit-shape arrays (Fortran 77)
A(3,4) and B(0:*)
– deferred-shape arrays (Fortran 90)C(:.:)
Modules
• a container, inside of which, different variables and subprogram units can be defined
• the variables and subprograms can then be made available to different program units through the USE statement– USE gives a program unit accessibility to public
entities in a module
• essentially a place to clump global data– an alternative to COMMON blocks– can do object oriented programming with modules
Modules
• use modules to package specifications and definitions
• a module can contain internal subprograms
• modules don’t contain executable code above the CONTAINS statement– modules are not
executable
MODULE name
[specification-part]
CONTAINS
module-subprogram
[module-subprogram] ...]
END [MODULE [name]]
Activity 8• working with a module which contains
data, the Pauli spin matrices
• compile and run the program as in the handout
Timing Code
• you can manually add functions to your program to time sections as it runs
• CPU Time – amount of time it takes for the CPU to execute a set of instructions – the system keeps track of how much time the
CPU is working on your program
• Wall Time – amount of time, according to a clock on the wall, that it takes the cpu to execute the instructions
CPU Time
• Fortran 95 added a functioncpu_time()
• which returns a processor-dependent approximation of the processor time in seconds real :: start_time, finish_timecall cpu_time(start_time) … stuff to time …call cpu_time(finish_time)write(*, "(a,f8.1,a)") & ' Stuff completed in ', & finish_time - start_time, ' cpu seconds'
Wall Time• Fortran 90 added a function
system_clock()• this function returns integer data from a real-time clock
integer :: start_wall_time, finish_wall_timeinteger :: ticks_per_seccall system_clock(start_wall_time, ticks_per_sec) … stuff to time …call system_clock(finish_wall_time)write(*, "(a,f8.1,a)") ‘Stuff completed in ', & real(finish_wall_time - start_wall_time) & & / real(ticks_per_sec), & ' wall seconds‘
• Beware: the returned value can be reset to 0 if the count passes through the maximum integer on the system
Profiling
• given that your program works correctly you may want to make it run faster/more efficiently
• a profiler allows you to find the places where your program spends its time so you reduce that time– focus your efforts where it will do the most
good
• GNU provides ‘gprof’ for profiling
Profiling
• ‘gprof’ produces an execution profile of your program
• the file ‘gmon.out’ contains the call graph profile
• ‘gprof’ outputs:– flat profile: shows how much time your program spent
in each function and how many times that function was called
– call graph: shows, for each function, which functions called it, which other functions it called, and how many times
Profiling
• add the option ‘–pg’ to the compile line• execute the program normally
– get a file named ‘gmon.out’
• run the command ‘gprof’• for example:
gfortran -pg –o MyCalc MyCalc.f90
./MyCalc
gprof -l -b MyCalc gmon.prof
OpenMP
• OpenMP• introduce statements into your code
– in FORTRAN: !$OMP– in C: #pragma
• can compile serial and parallel executables from the same source code
• restricted to shared memory machines– not clusters!
• www.openmp.org
OpenMP
• make the program parallel incrementally– one loop at a time if that works for you
• the pi calculation example contains 4 lines around the main loop to make it parallel
• before the loop:!$ Call OMP_SET_NUM_THREADS(3) !$OMP Parallel!$OMP Do Reduction(+:sum) Private(x, f)
• after the loop!$OMP End Parallel
OpenMP
• the number of threads that OpenMP uses can be controlled by:– using the OpenMP function from the serial
part of the program
!$ Call OMP_SET_NUM_THREADS(3) – setting the environment variable (in BASH)
export OMP_NUM_THREADS=3– using the NUM_THREADS clause
Calculation - OpenMP
• speedup graph for 1 to 4 processors
• quad precision• Opteron 285
procs• runs for 107
steps and 109 steps
Some Online Resources
• The gfortran Wiki– http://gcc.gnu.org/wiki/GFortran
• Michael Metcalf's article on Fortran language features in Wikipedia– http://en.wikipedia.org/wiki/
Fortran_language_features
• King’s College Fortran pages– http://www.kcl.ac.uk/kis/support/cit/fortran/
Fortran
• there’s lots left to learn
• see your favourite compiler manual
• contact [email protected] for numerical help
Appendix 1 - KINDs
• rather than declaring variables of a specific length with constructs like
DOUBLE PRECISIONREAL*n
• Fortran now use KINDS• this is intended to provide true portability
for code• tell the compiler what range and precision
of values you need for the variable
Appendix 1 - KINDs
• the ‘KIND number’ is an integer that specifies the length of the variable
• one common practice is to use the length of the variable in bytes as the KIND number
• the NAG Fortran compiler uses the digits 1, 2, and 3 for the KIND numbers
• G77 3.4.6 uses prime numbers for KINDs
Appendix 1 - KINDs
KIND(X) • returns the kind of the actual argument
– X can be of type INTEGER, REAL, COMPLEX, LOGICAL or CHARACTER
• the argument X does not have to be assigned any value
KIND(3) ! IntegerKIND(12.0) ! RealKIND(1.6D6) ! Double
Appendix 1 - KINDs
SELECTED_INT_KIND(R) – returns an integer kind with the requested number of
digits – R must be scalar integer
• the result of SELECTED_INT_KIND is an integer from zero and upward– if the desired kind is not available you will get -1– if several implemented types satisfy the condition, the
one with the least decimal range is used– if there still are several types or kinds that satisfy the
condition, the one with the smallest kind number will be used
Appendix 1 - KINDs
• SELECTED_REAL_KIND(p, r) • returns the kind for floating-point numbers
with numerical precision at least P digits and one decimal exponent range between -R and +R– the parameters P and R must be scalar
integers– at least one of P and R must be given.
Appendix 1 - KINDs• the result of SELECTED_REAL_KIND is
also an integer from zero and upward– if the desired kind is not available,
• -1 is returned if the precision is not available• -2 if the exponent range is not available• -3 if no one of the requirements are available
– if several implemented types satisfy the condition, the one with the least decimal precision is returned, and if there are several of them, the one with the least kind number is returned
Activity
• The exercises are available from– http://sciviz.aict.ualberta.ca/Fortran/src/
• or– http://www.ualberta.ca/AICT/RESEARCH/
Courses/2007/Workshop/_05_IntroToFortran/src/
• KIND values
• Download the program TestKinds.f90
Fortran Program Structure
• a Fortran program consists of one or more program units.
• a program unit is usually a sequence of statements that define the data environment and the steps necessary to perform calculations– it is terminated by an END statement
• a program unit can be either a main program, an external subprogram, a module, or a block data program unit
• an executable program contains one main program, and, optionally, any number of the other kinds of program units
Fortran Program Structure
• every Fortran program must have one and only one main program– The keyword
PROGRAM is optional– it can be followed by
the program name– END is required as the
last statement of the program
PROGRAM [name][specification statements][executable statements]...
END [PROGRAM [name]]
Fortran Program Structure
• Fortran programs, functions and subroutines have the same basic structure
• functions and subroutines can be– External - self contained (not necessarily
Fortran)– Internal - inside a program unit– Module - member of a module
• Fortran 77 has only external procedures
Fortran Program Structure
• functions and subroutines have the form
FUNCTION [name] (Arg-list) [specification statements]
[executable statements]...
END [FUNCTION [name]]
SUBROUTINE [name] (Arg-list) [specification statements]
[executable statements]...
END [SUBROUTINE [name]]
Fortran Program Structure
• the ordering rules for statements
• these apply to all program units and subprograms
• vertical lines delineate varieties of statements that may be interspersed
• horizontal lines delineate varieties of statements that must not be interspersed.
• USE statements, if any, must appear immediately after the program unit heading
Fortran Program Structure
• internal or module subprograms must follow a CONTAINS statement
• between USE and CONTAINS statements in a subprogram, non-executable statements generally precede executable statements– the FORMAT statement,
DATA statement, and ENTRY statement may appear among the executable statements
• this session considers programs structured as shown in pink
GOTO
• Fortran has a GOTO statement
• when coupled with line labels it’s possible to transfer control to any point in a program in a completely unreadable way
• it is generally considered bad practice to make use of the GOTO statement– there are always alternatives
Top Related