Post on 25-Mar-2018
Introduction to Fortran 90/95/2003NGSSC Cource : Programming in Science and Technology 2008Jonas Lindemann
History
Fortran Development
First version 1954
FORTRAN 66FORTRAN 77
Fortran 90 – Backwards compatible
(The F programming language)Fortran 95
Fortran 2003, (2004)
Pascalprogram tpk(input,output);var i : integer;y : real;a : array [0..10] of real;
function f ( t : real) : real;beginf := sqrt(abs(t)) + 5*t*t*t
end;
beginfor i := 0 to 10 do read(a[i]);for i := 10 downto 0 dobeginy := f(a[i]);if y > 400 then writeln(i,' TOO LARGE')
else writeln(i,y);
end;end;
end.
C#include <stdio.h>#include <stdlib.h>#include <math.h>
double f (double t){
double temp;temp = sqrt(fabs(t)) + 5*pow(t,3);return temp;
}
int main(){
int i;double y;double a[11];for ( i = 0; i <= 10; ++i)
scanf("%lf", &a[i]);for ( i = 10; i >= 0; i = i - 1 ) {
y = f(a[i]);if ( y > 400 ) {
printf(" %d",i); printf(" TOO LARGE\n");
}else {
printf(" %d",i); printf(" %lf",y); printf(" \n");
}}return 0;
}
FORTRAN 0
DIMENSION A(11)READ A
2 DO 3,8,11 J=1,113 I=11-J
Y=SQRT(ABS(A(I+1)))+5*A(I+1)**3IF (400>=Y) 8,4
4 PRINT I,999.GOTO 2
8 PRINT I,Y11 STOP
FORTRAN I
C FORTRAN I STYLEFUNF(T)=SQRTF(ABSF(T))+5.0*T**3DIMENSION A(11)
1 FORMAT(6F12.4)READ 1,ADO 10 J=1,11I=11-JY=FUNF(A(I+1))IF(400.0-Y)4,8,8
4 PRINT 5,I5 FORMAT(I10,10H TOO LARGE)
GOTO 108 PRINT 9,I,Y9 FORMAT(I10,F12.7)
10 CONTINUESTOP 52525
FORTRAN IV eller Fortran 66
C FORTRAN IV STYLEDIMENSION A(11)FUN(T) = SQRT(ABS(T)) + 5.0*T**3READ (5,1) A
1 FORMAT(5F10.2)DO 10 J = 1, 11
I = 11 - JY = FUN(A(I+1))IF (400.0-Y) 4, 8, 8
4 WRITE (6,5) I5 FORMAT(I10, 10H TOO LARGE)
GO TO 108 WRITE(6,9) I, Y
FORMAT(I10, F12.6)10 CONTINUE
STOPEND
Fortran 77PROGRAM TPK
C FORTRAN 77 STYLEREAL A(0:10)READ (5,*) ADO 10 I = 10, 0, -1
Y = FUN(A(I))IF ( Y .LT. 400) THEN
WRITE(6,9) I, Y9 FORMAT(I10, F12.6)
ELSEWRITE (6,5) I
5 FORMAT(I10,' TOO LARGE')ENDIF
10 CONTINUEEND
REAL FUNCTION FUN(T)REAL TFUN = SQRT(ABS(T)) + 5.0*T**3END
Fortran 90/95program tpk! Fortran 90 styleimplicit noneinteger :: ireal :: yreal, dimension(0:10) :: Aread (*,*) Ado i = 10, 0, -1 ! Backwards
y = fun(A(I))if ( y < 400.0 ) then
write (*,*) i, yelse
write (*,*) i, ' Too large'end if
end docontains ! Local functionfunction fun(t)
real :: funreal, intent(in) :: tfun = sqrt(abs(t)) + 5.0*t**3
end function funend program tpk
Fprogram tpk! Fortran F styleimplicit noneinteger :: ireal :: yreal, dimension(0:10) :: Aread *, Ado i = 10, 0, -1 ! Backwards
y = fun(A(I))if ( y < 400.0 ) then
print *, i, yelse
print *, i, "Too large"end if
end docontains ! Local functionfunction fun(t) result(fun_result)
real :: fun_resultreal, intent(in) :: tfun_result = sqrt(abs(t)) + 5.0*t**3
end function funend program tpk
Language elements
Source form
Free form Fixed form
Source format Max 132 characters Code in positions 7‐72, linenumbers in position 2‐5
Comments ! anywhere on a line !, C or * at position 1
Continuation & at end of line character at position 6 on continuation line
Multiple statements per line
; between statements On statement per row
Example of Fortran 90/95 codeprogram example
implicit none
integer, parameter :: ap=selected_real_kind(15,300)real(ap) :: x,yREAL(ap) :: K(20,20)
x = 6.0_ap ! This is line comment
y = &0.25_ap + &0.25_ap
write(*,*) x; write(*,*) ywrite(*,*) ap
call myproc(K)
stop
end program example
Variable names
Max 31 characters
Letters a‐z, A‐Z (not Å, Ä, Ö) Numbers 0‐9
Underscore _
First character must be a letterLower case letters equivalent with upper caseletters
Variabletypes
integer Integer
real Floating point
complex Complex numbers
logical Boolean variables
character Characters and strings
Variable declaration
integer :: i Scalar integer
real :: p Floating point scalar
integer, parameter :: a = 5 Integer constant
integer, dimension(10) :: b Integer array with 10 elements
real :: C(10) Floating point array with 10 elements
real :: K(20,20) Floating point array with 20 x 20 elements
Variable type parameters
integer(kind=4) :: a integer(4) :: b ! Short form
real(kind=8) :: c real(8) :: a ! Short form
character(len=20) :: textstringcharacter(20) :: textstring2character(len=20, kind=1) :: textstring3 ! english stringcharacter(len=20, kind=kanji) :: textstring4 ! kanji string
integer and real typeparameters system
dependent.
Determining appropriate type
selected_int_kind(r) returns the appropriatetype parameter to represent all integer values, n, in the range ‐10r < n < 10r
selected_real_kind(p,r) returns the appropriatetype parameter for representing a number with at least p decimal precsicion and decimal exponent range of at least r
Appropriate type ‐ example
integer, parameter :: rk = selected_real_kind(15,300)
integer, parameter :: ik = selected_real_kind(6)
real(kind=rk) :: xreal(rk) :: y
integer(kind=ik) :: zinteger(ik) :: c
General type rule
Undeclared variables are defined as integer if the variable name starts with i,j,k,l,m,n, otherwisereal.
The implicit none directive forces declarationof all variables. Recommended.
Array storage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 9
2 10
3 11
4 12
5 13
6 14
7 15
8 16
1 3
2 4
5 7
6 8
9 11
10 12
13 15
14 16
real :: A(16)
real :: A(8,2)
real :: A(2,8)
Character and strings
Declaration Description
Character :: ch Character
character, dimension(60) :: chv array of characters
character :: chv(60) array of characters
character(len=80) :: line character string
character :: line*80 character string
character(len=80), dimension(60) :: page array of strings
character(len=80) :: page(60) array of strings
Derived data types
type pointreal :: xreal :: yreal :: size
end type point
Type definition:
type(point) :: point ! Structure
Declaration statement:
Accessing structure member variables:
point%x = 1.0point%y = 2.0point%size = 4.0
Assignments
integer :: mm
integer, parameter :: ap = 8
real(kind=ap) :: pi
mm = 113
pi = 3.141592653589793_ap
m = 113
pi = 3.141592653589793
Python:
datatype parameter
Assignments
integer, parameter :: ap = & selected_real_kind(15,300)
real(kind=ap) :: K(20,20)
Element (5,6) is assigned a value of 5.0
All elements of K are assigned a value of 5.0
K(5,6) = 5.0_ap
K = 5.0_ap
Assignments
integer, parameter :: ap = & selected_real_kind(15,300)
real(kind=ap) :: A(3,3)
Row 2 is assigned 1, 2, 3
Column 2 is assigned 4, 5, 6
A(2,:) = (/ 1.0_ap, 2.0_ap, 3.0_ap /)
A(:,2) = (/ 4.0_ap, 5.0_ap, 3.0_ap /)
Assignments
program pi_testinteger, parameter :: &
ap = selected_real_kind(15,300)real(ap) pi1, pi2
pi1 = 3.141592653589793pi2 = 3.141592653589793_apwrite(*,*) ’pi1=', pi1write(*,*) ’pi2=', pi2stopend program pi_test
pi1= 3.14159274101257 pi2= 3.14159265358979
Assignments
logical :: flag
character(40) :: first_name
flag = .false.
first_name = ’Jan’
Defined and undefined variables
A variable is said to be undefined until it has been assigned a valuereal :: speed ! variable speed exists, but is undefined
An undefined variable must not be referencedWhen a variable is assigned a value it is considered definedspeed = 42.0 ! variable speed is definedIt can now be referenced by other expressions
An array is said to be defined when all elements have been assigned values
Arithmetic operators
** exponentiation
* Multiplication
/ Division
+ Áddition
‐ Subbtraction
Order of precedence
Unary operators
‐x or +x
Not allowed to follow directly after ordinaryoperator, hence:x**‐y is illegal
x**(‐y) is ok
Expressions‐a+b+c
((‐a)+b)+c
Evaluated from left to right as:
a**b**c
a**(b**c)
Evaluated as:
Integer expressions
Results of divisions will be truncated towards 0
6/3 = 28/3 = 2‐8/3 = ‐2
A warning!
2**3 = 82**(‐3) = 1/(2**3) = 0
Mixed‐mode expressions
Numeric expressions with operands of differingdatatypes
Weaker of to datatypes will be coerced to the stronger oneResult will be of the stronger type
real :: ainteger :: ireal :: b
b = a*i
i coerced to real
Array expressions
Intrinsic operations can also apply to arrays
Same shape arrays are assumedOne or more operands can be scalarscalar values ”broadcast” to array operands
Order of array operations is not specified in the standardEnabling efficient execution on a vector or parallelcomputer
Array expressions examples
real, dimension(10,20) :: a, b
real, dimension(5) :: v
a/b ! Array of shape (10,20), with elements a(i,j)/b(i,j)
v+1. ! Array of shape (5), with elements v(i) + 1.0
5/v+a(1:5,5) ! Array of shape (5), with elements 5/v(i) + a(i,5)
a.eq.b ! .true. if a(i,j)==b(i,j) and .false. otherwise
Relational operators
Operator Meaning Python
< .lt. less than <
<= .le. less than or equal <=
== .eq. equal ==
/= .ne. not equal !=
> .gt. greater than >
>= .ge. greater than or equal >=
Logiska operatorer
Operator Meaning Python
.and. and and
.or. or or
.not. not not
Control constructs
If‐statements
if (x>1000) thenx = 1000
end if
if (x>1000) x = 1000
if x>1000:x = 1000
Fortran Python
If‐statements
if (x>1000) theny = 100
else y = 200
end if
if x>1000:y = 100
else:y = 200
Fortran Python
If‐statements
if (x>1000) theny = 10
else if (x<0) theny = 20
elsey = 30
end if
if x>1000:y = 10
elif x<0:y = 20
else:y = 30
Fortran Python
case‐statements
select case (display_mode)case (0)...case (1)...case default...end select
case‐statements
select case (number)case (:‐1)...case (0)...case (1:)...case default...end select
case(low:high) low <= number <= high
case(:high) number <= high
case(low:high) <=> low <= number
‐1 1
(:‐1) (1:)
0
(0)
default
do‐statements (loops)
do i = 1, 10j = j + i
end do
do i = 2, 30, 4j = j + i
end do
start‐value end‐value
start‐value end‐value
step
1 2 3 4 5 6 7 8 9 10
2 6 10 14 18 22 26 30
loop‐variable is not allowed to be modified in do‐statement
do‐statements (loops)
do i=1,1000:if (x>50) thenexit
else if (x<20) thencycle
end if:
end do:
Exit do‐statement and execute next executablestatement after loop.
Continue to next iteration
Program units and procedures
Main program
[program program‐name][specification statements][executable statements]
[containsinternal‐subprograms]
end [program [program‐name]]
A Fortran program contains only onemain program.
The end‐statement signals the end of the program‐unit and also terminatesthe program execution.
The stop‐statement
Stops program execution
Can be used in all program units”Well‐behaved” programs returns control to the main program, so stop‐statements should appearin the main program
A stop‐statement can contain stop codesNumber or strings
Subprograms
External subprogramsPlaced in separate source files. Implicit interface.
Can be implemented in other languages
Internal subprogramssubprograms contained inside program units, externalsubprograms and in module subprograms
Module subprogramsubprogram contained in a module
External subprogram
subroutine statement[specification statements][executable statements]
[contains[internal subprograms]
end [subroutine [subroutines‐name]]
function statement[specification statements][executable statements]
[contains[internal subprograms]
end [subroutine [subroutines‐name]]
External subprogram ‐ Example
subroutine myproc(a, B, C)integer, intent(in) :: areal, dimension(:,:) intent(in) :: Breal, dimension(:), intent(out) :: C
:
returnend subroutine myproc
Calling external subprogram
program maininteger, parameter :: areal :: B(a,a)real :: C(a)
:
call myproc(a,B,C)
:
end program main
Modules
Packagesglobal data
derived types and associated operations
subprograms
interface blocks
namelist definitions
Package everything associated with some kind of taskinterval arithmetic
FEM elements of a certain type …
Modulesmodule module‐name
[specification statements][contains
module‐subprograms]end [module [program‐name]]
module constantsinteger, parameter :: &
ik6 = selected_int_kind(6)end module constants
:use constants
integer(ik6) :: myint
Modulermodule truss
integer ...real, private ...:public :: bar2e:
contains
subroutine bar2e(...)...return
end subroutine bar2e:end module truss
variables and subprogramscan be made private and public using the public and private attributes.
Moduler
program mainuse truss:call bar2e:
end program main
All public variables, subprograms and datatypesfrom truss now available in program unit
Arguments of procedures
Paramters passed as referenceChanging a parameter in a subroutine affects variable in calling routine
Quicker subroutine calls
Undesired “sideeffects”
Declaration of parametersDon’t have to be the same as the calling routine
Last dimension can be left out for arrays.
Subroutines exampleprogram sub_declaration1
real(8), dimension(4,4) :: Ainteger, dimension(3) :: v
A = 0.0_8v = 0
call dowork(A,4,4,v,3)
print *, A(4,4)print *, v(3)
end program sub_declaration1
subroutine dowork(A,rows,cols,v,elements)
integer :: rows, cols, elementsreal(8), dimension(rows*cols) :: Ainteger, dimension(elements) :: v
A = 42.0_8v = 42
return
end subroutine dowork
Subroutine interfaces
2 flavorsexternal/implicit interfaceInternal/explicit interface
Implicit (Fortran 77)Separately compiled .f90‐filesCompiler does not have all information
Explicit (Fortran 9x / 200x)Declared in modules, program contain‐section or with interface declarationCompiler has all information on the subroutine interface
Subroutines and Fortran 90/95/2003
Arrays and vectors can be declared with (:,:) or (:) dimensions
The explicit interface gives the compiler all information to determine the sizes of the parametersShorter subroutine parameter lists
Actual dimensions of the arrays can be queried using the size(array, dimension) function.
Example – Implicit interfaceprogram test
real(8), dimension(20,30) :: A
A = 0.0_8
call mysub(A, 20, 30)
end program testsubroutine mysub(A,rows,cols)
integer :: rows, colsreal(8), dimension(rows,cols) :: A
A = 42.0_8
print *, 'rows = ', size(A,1)print *, 'cols = ', size(A,2)
return
end subroutine mysub
Example (Module)
module utils
contains
subroutine mysub2(A)
real(8), dimension(:,:) :: A
A = 42.0_8
print *, 'rows = ', size(A,1)print *, 'cols = ', size(A,2)
return
end subroutine mysub2
end module utils
program test
use utils
real(8), dimension(20,30) :: A
A = 0.0_8
call mysub2(A)
end program test
Assumed shape array
Example – Internal subprogramprogram test
real(8), dimension(20,30) :: A
A = 0.0_8
call mysub3(A)
contains
subroutine mysub3(A)
real(8), dimension(:,:) :: A
A = 42.0_8
print *, 'rows = ', size(A,1)print *, 'cols = ', size(A,2)
end subroutine mysub3
end program test
Assumed shape array
Example – Explicit interfaceprogram test
interface subroutine mysub4(A)
real(8), dimension(:,:) :: Aend subroutine mysub4
end interface
real(8), dimension(20,30) :: A
A = 0.0_8
call mysub4(A)
end program test
subroutine mysub4(A)
real(8), dimension(:,:) :: A
A = 42.0_8
print *, 'rows = ', size(A,1)print *, 'cols = ', size(A,2)
return
end subroutine mysub4
Assumed shape array
Automatic fields
Temporary fields in subroutines
Created on the stackMust fit in the stack
Automatic fields
program automatic_arrays
real(8), dimension(20,30) :: A
call mysub(A)
contains
subroutine mysub(A)
real(8), dimension(:,:) :: Ainteger, dimension(size(A,1),size(A,2)) :: B
B = 0
print *, "rows = ", size(B,1)print *, "cols = ", size(B,2)
end subroutine mysub
end program automatic_arrays
Array features
Allocatable arrays
Size of arrays not always known at compile timeDeclared using the allocatable attributeThe array rank is defined at declarations, but bounds undefined until array has been allocatedAllocate‐statements used to allocate the array”Work arrays” where used in Fortran 77 as a replacement for allocatable arraysDeallocated with deallocate‐statementAllocatable arrays automatically deallocated when returning from a function or subroutine
Allocatable arrays
real, dimension(:), allocatable :: f
real, dimension(:,:), allocatable :: K
allocate(f(20))
allocate(K(20,20))
deallocate(f)
deallocate(K)
deallocate(f, K)
or
allocate(f(20), K(20,20))
Where‐statement
Often desired to perform operations on only certain elements of an array
where (logical‐array‐expr) array‐variable = expr
where (logical‐array‐expr)array‐assignments
end where
where (logical‐array‐expr)array‐assignments
elsewherearray‐assignments
end where
Where‐statement example
where (a>0.0) a = 1.0/a
where (pressure <= 1.0)pressure = pressure + inc_pressuretemp = temp + 5.0
elsewhereraining = .true.
end where
where (a>0.0) a = log(a)
function is only called when condition is fulfilled.
a, pressure, temp are arrays
forall‐statement
In do‐loops the processor must each succesive iteration in order and after each otherPerformance penalties (especially on parallel machines)
forall‐statement a replacement when operations can be executed in any orderArray assignments expressed with indices
forall‐statement
do i=1,na(i,i) = 2.0 * x(i)
end do
forall(i=1:n) a(i,i) = 2.0 * x(i)
forall(i=1:n, j=1:m) a(i,j) = i + j
forall(i=1:n, j=1:n, y(i,j)/=0.) x(i,j) = 1.0/y(i,j)
Masking condition
Risk of dividing by zero
Pure procedures
Using functions with side‐effects in forall can affect performance and resultspure functions must be used in forall‐statementsA procedure in Fortran in considered pure
if it does not alter any dummy argumentdoes not alter any part of a variable accessed by host or use associationcontains no local variable with save attributeperforms no operations on external filescontains no stop statement
pure attribute used to indicate pure function
Elemental procedures
Subroutines operating on elements of arrays
Elemental subroutines must be pure (defined automatically)
elemental subroutine swap(a, b)real, intent(inout) :: a, breal :: work
work = aa = bb = work
end subroutine swap
:
real, dimension(20,20) :: areal, dimension(20,20) :: b
call swap(a,b)
Array subobjects
Used to extract fields/arrays from other arrays
Can be used as parameters in subroutine callsCompare Matlab’s index notation
Array subobject exampleprogram array_subobjects
integer, dimension(5,10) :: Ainteger :: i, j
do i=1,5do j=1,10
A(i,j) = (i‐1)*10 + jend do
end do
print *, "Entire array:"call writeArray(A)
print *, "A(1, 5:10)"call writeVector(A(1, 5:10))
print *, "A(1:5, 5:10)"call writeArray(A(1:5, 5:10))
print *, "A(1:5, 5:10)"call writeArray(A(1:5, 5:10))
print *, "A((/1,3/), (/2,4/))"call writeArray(A( (/1,3/), (/2,4/) ))
Array subobjects exampleEntire array:1 2 3 4 5 6 7 8 9 1011 12 13 14 15 16 17 18 19 2021 22 23 24 25 26 27 28 29 3031 32 33 34 35 36 37 38 39 4041 42 43 44 45 46 47 48 49 50A(1, 5:10)5 6 7 8 9 10A(1:5, 5:10)5 6 7 8 9 1015 16 17 18 19 2025 26 27 28 29 3035 36 37 38 39 4045 46 47 48 49 50A(1:5, 5:10)5 6 7 8 9 1015 16 17 18 19 2025 26 27 28 29 3035 36 37 38 39 4045 46 47 48 49 50A((/1,3/), (/2,4/))2 422 24
Intrinsic procedures
Intrinsic procedures (builtin...)
Elemental procedures
Inquiry functionsReturns properties of the arguments that does not depend on their values, kind, range etc...
Transformational functionsHas array arguments and returns arrays depending on all elements of the input arrays
Non‐elemental subroutines
Elemental functions
abs(x) absolute value of x
int(x) converts x to integere, truncates towards 0
nint(x) returns integer, nearest to x
real(x) converts to floating point value
...
sin(x) returns the sine of x
sqrt(x) returns the square root of x
atan2(y,x) returns the arc tangent for pairs of reals
... converts to floating point value
Routines that may convert
Mathematical functions
Vector and matrix multiplication
Matrix multiplicationmatmul(A,B), where A and B are matrices
Scalarproductdot_product(a,b), where a and b are vectors
Vector and matrix multiplication
program matrix_multiply
real(8), dimension(4,4) :: Areal(8), dimension(4,8) :: Breal(8), dimension(4,8) :: C
call randomMatrix(A)call randomMatrix(B)call randomMatrix(C)
C = matmul(A,B)
print *, "A = "call writeArray(A)print *, "B = "call writeArray(B)print *, "C = "call writeArray(C)
end program matrix_multiply
Vector and matrix multiplication
A =.984 .700 .275 .661.810 .910 .304 .484.985 .347 .548 .614.971 .882 .129 .929B =
.763 .534 .711E‐01.404 .731 .636 .879 .689
.786 .231 .238 .951 .621 .528 .733 .588E‐01
.466 .302 .209 .294 .598 .461 .911 .343
.690E‐01.619 .305 .326E‐01.438 .202 .617 .851C =
1.48 1.18 .496 1.17 1.61 1.26 2.04 1.381.51 1.03 .486 1.30 1.55 1.23 1.96 1.131.32 1.15 .455 .909 1.53 1.19 2.00 1.411.56 1.34 .589 1.30 1.74 1.33 2.19 1.56
Reduction routines
allTrue if all element = .true.
anyTrue if any element = .true.
maxval/minvalMax/min value in the field
productProduct of all elements in the field
sumSum of all elements in the field
Reduction functions
print *, 'Product of A = ', product(A)print *, 'Sum of A = ', sum(A)print *, 'Max of A = ', maxval(A)print *, 'Min of A = ', minval(A)
A =.984 .700 .275 .661.810 .910 .304 .484.985 .347 .548 .614.971 .882 .129 .929...Product of A = 0.00016095765496870103Sum of A = 10.534961942117661Max of A = 0.9853920286986977Min of A = 0.12899155798368156
Information functions
lboundReturns lower field index
uboundReturn upper field index
shapeReturns the matrix shape in an array [rows, columns]
sizeReturns the size of matrix in a specific dimension
Input and output
Reading and writing files
One row for each READ/WRITE‐statement
Fortran automatically converts text in a file to typed variable valuesSeveral variables can be read in the same statement using a comman separated list of variables
To handle a large number of values on a row an implicit loop can be used
Example
! Read 8 floating point values from unit ir
read(ir,*) a(1), a(2), a(3), a(4), a(5), a(6), a(7), a(8)
! or perhaps even better...
read(ir,*) (a(i), i=1,8)
! Same procedure for writing
write(iw,*) (a(i), i=1,8)
Formatted IO
Second parameter in the WRITE statement defines the output format
* represents the default format which often displays at full precisionA format parameter is a string describing the output format
The format is defined using format codes
Formatted IO
Common codesA[n] – character string with the width n
I[n] – integer with the width n
G[m.n] – floating point value with width m and n decimals
Format codes can be repeated by giving a integer in front of the code“(6I5)” = 6 integers with the width 5
Exampleprogram format_print
real(8), dimension(3) :: ainteger, dimension(4) :: binteger :: i, j
! Write table header
a = (/ 1.0, 2.0, 3.0 /)b = (/ 4, 5, 6, 7 /)
write(*, '(3A8,4A5)') 'aaaaaaaa', &'bbbbbbbb', 'cccccccc', 'ddddd', 'eeeee', 'fffff', &'ggggg‘
! Write table
do j=1,10write(*, '(3G8.3,4I5)') (a(i),i=1,3), (b(i), i=1,4)
end do
end program format_print
Example
aaaaaaaabbbbbbbbccccccccdddddeeeeefffffggggg1.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 71.00 2.00 3.00 4 5 6 7
“Dynamic” format codes
Format strings are static strings
How to create a format code that can handle dynamic number of valuesWRITE can use a character string as a “file”
Examplesubroutine writeArray(A)
real(8), dimension(:,:) :: Ainteger :: rows, cols, i, jcharacter(255) :: fmt
rows = size(A,1)cols = size(A,2)
write(fmt, '(A,I1,A)') '(',cols, 'G8.3)'
do i=1,rowsprint fmt, (A(i,j), j=1,cols)
end do
return
end subroutine writeArray
String that will contain final format codes.
Write to fmt string using a write statement ”colsG8.3”.
Use the fmt string as a format string when printing the array.
Reading
read(*,*) Aread(5,*) A
integer, parameter :: ir=15
open(unit=ir, file=’example.dat’)read(ir,*) Aclose(unit=ir)
Keyboard
File
Please see, Metcalf for more parameters for the open‐statement
Writing
write(*,*) Awrite(6,*) Awrite(*,’ (TR1,A,G15.6)’) ’A = ’, A
integer, parameter :: iw=16
open(unit=iw, file=’example.dat’)write(iw, ’(A,G15.6)’) Aclose(unit=iw)
Screen
File
Please see, Metcalf for more parameters for the open‐statement
Code structuring
Structuring of projects
For smaller project modularisation not necessary
For larger project it is a must to be able to maintain the codeIn Fortran 95 the key to modularisation is the module
Modules should be used to group related subroutines and data
Code structuring
inputdata outputdatafem solve
utils
program
Example code
program stress
use inputdatause outputdatause femuse solve
.
.
end program stress
module fem
use utils
.
.
end module fem
module utils
.
.
end module utils
Using the Photran IDE
Selecting workspace
A workspace is a directorycontaining settings for the enviroment and a set of development projects.
Welcome screen
Click here
Workbench screen
File/New/other…
Create a Fortran project
Click Next
Select project type and name
1
2
3
Click Finish
Switch to Fortran Perspective
Workbench with empty project
Adding a Fortran source fileFile/New/Other…
Click Next
Name source file
Click Finish
Enter name of sourcefile
Makefile generation with pymkmf
Select the source directoryusing the browse button.
Click ”Generate” to create a Makefile for source files.
Refreshing project tree
Right click and select ”Refresh” to display the generatedMakefile
Building the projectRight click and select ”BuildProject” to start the buildprocess.
Running the project
Click to run project
Click Ok
Program output
Debugging with Photran
Special FX
Procedures as arguments
procedures in Fortran 95 can take procedures as arguments
Properties of “dummy” procedure arguments must agreeThe procedure type is declared in the specification part
Internal procedures can’t be used
Procedures as argumentsmodule utils
implicit none
contains
real(8) function myfunc(x)
real(8), intent(in) :: x
myfunc = sin(x)
end function myfunc
subroutine tabulate(startInterval, endInterval, step, func)
real(8), intent(in) :: startInterval, endInterval, stepreal(8) :: x
interface real(8) function func(x)
real(8), intent(in) :: xend function func
end interface
x = startIntervaldo while (x<endInterval)
print *, x, func(x)x = x + step
end do
returnend subroutine tabulate
end module utils
Declaration of function interface. Function used as argument must havethe same interface
Procedures as arguments
program procedures_as_arguments
use utils
implicit none
call tabulate(0.0_8, 3.14_8, 0.1_8, myfunc)
end program procedures_as_arguments
Procedures as arguments0.0000000000000000 0.0000000000000000 0.10000000000000001 9.98334166468281548E‐0020.20000000000000001 0.19866933079506122 0.30000000000000004 0.29552020666133960 0.40000000000000002 0.38941834230865052 0.50000000000000000 0.47942553860420301 0.59999999999999998 0.56464247339503537 0.69999999999999996 0.64421768723769102 0.79999999999999993 0.71735609089952268 0.89999999999999991 0.78332690962748330 0.99999999999999989 0.84147098480789639 1.0999999999999999 0.89120736006143531 1.2000000000000000 0.93203908596722629 1.3000000000000000 0.96355818541719296 1.4000000000000001 0.98544972998846025 1.5000000000000002 0.99749498660405445 1.6000000000000003 0.99957360304150511 1.7000000000000004 0.99166481045246857 1.8000000000000005 0.97384763087819504 1.9000000000000006 0.94630008768741425 2.0000000000000004 0.90929742682568149 2.1000000000000005 0.86320936664887349 2.2000000000000006 0.80849640381958987 2.3000000000000007 0.74570521217671970 2.4000000000000008 0.67546318055115029 2.5000000000000009 0.59847214410395577 2.6000000000000010 0.51550137182146338 2.7000000000000011 0.42737988023382895 2.8000000000000012 0.33498815015590383 2.9000000000000012 0.23924932921398112 3.0000000000000013 0.14112000805986591 3.1000000000000014 4.15806624332891589E‐002
Keyword and optional arguments
Many procedures have long argument listsAll arguments not needed
Procedural arguments in Fortran can be given the attribute optionalreal, optional :: a
Optional arguments can be omitted in the procedure callPresence of an argument can be tested with the present function.
Arguments can be specified with keywords
Keyword and optional arguments
subroutine order_icecream(number, flavor, topping)
integer :: numberinteger, optional :: flavorinteger, optional :: topping
print *, number, 'icecreams ordered.'
if (present(flavor)) thenprint *, 'Flavor is ', flavor
elseprint *, 'No flavor was given.'
end if
if (present(topping)) thenprint *, 'Topping is ', topping
elseprint *, 'No topping was given.'
end if
end subroutine order_icecream
call order_icecream(2)call order_icecream(2, 1)call order_icecream(4, 4, 2)call order_icecream(4, topping=3)
Overloading
Procedure call to different procedures depending on datatype
Declare an interface with procedural interfaces for all used datatypesExplicit interfaces (modules) can use a simpler form module procedure procedure‐name‐list
Overloadingmodule special
interface funcmodule procedure ifunc, rfunc
end interface
contains
integer function ifunc(x)
integer, intent(in) :: xifunc = x * 42
end function ifunc
real(8) function rfunc(x)
real(8), intent(in) :: xrfunc = x / 42.0_8
end function rfunc
end module special
program overloading
use special
implicit none
integer :: a = 42real(8) :: b = 42.0_8
a = func(a)b = func(b)
print *, aprint *, b
end program overloading
17641.00000000000000000
Operator overloading
Define operations on derived types
Vector / Matrix operationsinterface operator(operator) used to define a function implementing the operations for this operator
Function has the formtype(derived‐type‐name) function‐name(operand1, operand2)
Operator overloading
module vector_operations
type vectorreal(8) :: components(3)
end type vector
interface operator(+)module procedure vector_plus_vector
end interface
contains
type(vector) function vector_plus_vector(v1, v2)
type(vector), intent(in) :: v1, v2vector_plus_vector%components = v1%components + v2%components
end function vector_plus_vector
end module vector_operations
Operator overloading
program operator_overloading
use vector_operations
implicit none
type(vector) :: v1type(vector) :: v2type(vector) :: v
v1%components = (/1.0, 0.0, 0.0/)v2%components = (/0.0, 1.0, 0.0/)
v = v1 + v2
print *, v
end program operator_overloading
1.00000000000000000 1.00000000000000000 0.0000000000000000
Public and private attributes
Control visibility of variables and functions
Hide module implementation detailsPrevent side effects in modules
Visibility of variables controlled by private and public attributes
procedure visibility controlled by private access‐list
public is the default for all module variables and procedures
Public and private
module mymodule
implicit none
integer, public :: visibleinteger, private :: invisible
private privatefuncpublic publicfunc
contains
subroutine privatefunc
print *, 'This function can only be called from within a module.'
end subroutine privatefunc
subroutine publicfunc
call privatefunc
end subroutine publicfunc
end module mymodule
Public and privateprogram private_entities
use mymodule
implicit none
call publicfunc
end program private_entities
This function can only be called from within a module.
program private_entities
use mymodule
implicit none
call privatefunc
end program private_entities
make all gfortran ‐g ‐fbounds‐check ‐Wall ‐Wtabs ‐c main.f90gfortran ‐o private_entities mymodule.o main.omain.o: In function `private_entities':D:\edu\lunarc\sciprog\workspace\private_entities/main.f90:7: undefined reference to `privatefunc_'collect2: ld returned 1 exit statusmake: *** [private_entities] Error 1
Pointers
Pointer = reference to a variable
Strictly typedPointer targets must have target attributeFor compiler optimisation
Enables the return of allocatable arrays from procedures
nullify(pointer) disassociates pointer from target=> operator is used to associated a pointer with a target
Pointersprogram pointers
implicit none
integer, allocatable, dimension(:,:), target :: Ainteger, dimension(:,:), pointer :: B, C
allocate(A(20,20))
B => A
print *, size(B,1), size(B,2)
call createArray(C)
print *, size(C,1), size(C,2)
deallocate(C)
B => null()
B(1,1) = 0 ! Dangerous!
contains
subroutine createArray(D)
integer, dimension(:,:), pointer :: D
allocate(D(10,10))
end subroutine createArray
end program pointers
B points to A
B can be queried just like a normal array
An unassociatedpointer can be passedto a subroutine and be returned as an allocated array
Advanced I/O
List directed I/O
Fortran uses a specific format for reading and writing variables to files
Variables output from write(*,*) are separated with space/blanksComplex numbers surrounded by ( )
Strings must be enclosed in ‘ ‘ or “ “ when output
Reading variables require the same format
List directed I/Oprogram list_io
implicit none
integer, parameter :: ir = 15integer, parameter :: iw = 16
integer :: a = 42real :: b = 42.0 * 42.0character(len=20) :: string = 'Hello, string!'logical :: topping = .true.complex :: c = (1.0,2.0)
open(unit=iw, file='list.txt', status='replace')write(iw,*) a, b, '"',string,'"', topping, cclose(unit=iw)
open(unit=ir, file='list.txt', status='old')read(ir,*) a, b, string, topping, cclose(unit=ir)
print *, aprint *, bprint *, toppingprint *, c
end program list_io
42 1764.0000 "Hello, string! " F ( 1.00000000 , 2.0000000 )
.true. and .false. canalso be used as input for logical variables
Namelist I/O
Reading list of named values
Value names defined in a namelistInput must consist of lists of named value pairs separated with comma& name = value, name = value /
Can contain arraysname = 1,2,3,4,5
Fortran can also write named values
Namelist I/O
program namelist_io
implicit none
integer, parameter :: ir = 15integer, parameter :: iw = 16integer :: no_of_eggs, litres_of_milk, kilos_of_butter, list(5)namelist /food/ no_of_eggs, litres_of_milk, kilos_of_butter, list
list = 0
open(unit=ir, file='food.txt', status='old')read(ir, nml=food)close(unit=ir)
print *, no_of_eggs, litres_of_milk, kilos_of_butter
open(unit=iw, file='food2.txt', status='new')write(iw, nml=food)close(unit=iw)
end program namelist_io
namelist definedvariables to be read from file
namelist definedvariables to be writtento file.
Namelist I/O
&food litres_of_milk=5, no_of_eggs=12, kilos_of_butter=42, list=1,2,3,4,5 /
&FOODNO_OF_EGGS= 12,LITRES_OF_MILK= 5,KILOS_OF_BUTTER= 42,LIST= 1, 2, 3, 4, 5,/
food.txt:
food2.txt:
writing namelistalways producesuppercase variable names
Unformatted I/O
Writing data using a textual representation not efficient in all cases
No format needed, binary outputread(unit=xx) a
write(unit=xx) b
Output from unformatted I/O often system dependent
Scratchfiles and temporary files
Direct access files
Used when a random access pattern is needed
File consists of a set of equal sized recordsAny record in the file can be accessed randomly
If the record is changed data cannot be read back from file
Size of a record can be found using inquire(iolength=variable‐name) recordLength
Direct access files / unformatted IOprogram unformatted_io
implicit none
type accountcharacter(len=40) :: account_holderreal :: balance
end type account
integer, parameter :: iw = 15type(account) :: accountAtype(account) :: accountBinteger :: recordSize
inquire(iolength=recordSize) accountA
print *, 'Record size =',recordSize
accountA%account_holder = 'Olle'accountA%balance = 400
accountB%account_holder = 'Janne'accountB%balance = 800
open(unit=iw, file='bank.dat', access='direct', recl=recordSize, status='replace')write(iw, rec=1) accountAwrite(iw, rec=2) accountBclose(unit=iw)
end program unformatted_io
Derived datatypesgood candidates for storing as records in a random access file
Inquire for the required record length
access=’direct’ createsa direct access file.
The rec attributedetermines the location to store/read the record
File positioning
File pointer – Invisible cursor in the file
backspace unitMove file pointer back 1 record
rewind unitMove file pointer to beginning of file
endfile unit Move file pointer to the end of the file.
Error handling in file operations
open, close, read and write have an err attribute that can be set to a specific label to jump to when an error occurs
Well behaved programs should implement error handling when reading and writing files
Error handling in file operationsprogram error_handling
implicit none
integer, parameter :: ir = 15integer :: a
open(unit=ir, file='test.txt', status='old', err=99)read(ir,*,err=99) aclose(unit=ir,err=99)
stop
99 print *, 'An error occured reading the file.'
end program error_handling
Fortran 2003 extensions
Allocatable array extensions
Remove the need for pointers to use allocatablearrays as dummy arguments
Inefficient
Allocatable dummy argumentsprogram allocatable_dummy
implicit none
real, allocatable :: A(:,:)
call createArray(A)
print *, size(A,1), size(A,2)
deallocate(A)
contains
subroutine createArray(A)
real, allocatable, intent(out) :: A(:,:)
allocate(A(20,20))
end subroutine createArray
end program allocatable_dummy
A pointer dummy argument was neededto implement this i Fortran 95
Allocatable functions
program allocatable_function
implicit none
real :: A(20)
A = createVector(20)print *, size(A,1)
contains
function createVector(n)
real, allocatable, dimension(:) :: createVectorinteger, intent(in) :: n
allocate(createVector(n))
end function createVector
end program allocatable_function
Vector allocated in function will be automaticallydeallocated when it has been used.
Allocatable components
type stackinteger :: indexinteger, allocatable :: content(:)
end type stack
Pointers used in Fortran 95, but no automaticdeallocation available
Submodules
The Fortran 95 module concept adequate for moderate size projects
Difficult to modularize modules themselvesDividing modules into several modulesexposes internal structure
nameclashes
Changes to module features require recompilation of all files using this module
Submodules
Separation of module intoInterface – defined in the module
Body – defined in submodule
Submodulesmodule points
type pointreal :: x, y
end type point
interface real module function point_dist(a, b)
type(point), intent(in) :: a, bend function point_dist
end interfaceend module points
submodule (points) points_a
contains
real module function point_dist(a,b)type(point), intent(in) :: a, bpoint_dist = sqrt((a%x‐b%x)**2+(a%y‐b%y)**2)
end function point_dist
end submodule points_a
Not available in gfortran yet.
C interoperability
No clear definitions existed between Fortran 95 and the C language
C/Fortran programming is importantInterfacing with C libraries
C user interface application interfacing with Fortran code
New intrinsic module, iso_c_binding, includedContains definitions of all the C datatypes mapped to Fortran types
C interoperability
program c_interop
use iso_c_binding
implicit none
integer(c_int) :: areal(c_float) :: breal(c_double) :: c
a = 42b = 42.0_c_floatc = 84.0_c_double
print *, a, b, c
end program c_interop
C interoperability
Fortran always passes all variables by reference
In C scalar arguments are often passed by valueArgument value is copied to procedure
The variable attribute value is added for compatibility with C code
Enables direct linking with C
Object‐oriented programming
module mytype_module
type mytypereal :: myvalue(4) = 0.0
containsprocedure :: write => write_mytypeprocedure :: reset
end type mytype
private :: write_mytype, reset
contains
subroutine write_mytype(this, unit)class(mytype) :: thisinteger, optional :: unitif (present(unit)) then
write(unit,*) this%myvalueelse
print *, this%myvalueend if
end subroutine write_mytype
subroutine reset(variable)class(mytype) :: variablevariable%myvalue = 0.0
end subroutine reset
end module mytype_module
class(mtype) :: x
call x%write(6)call x%reset
Not available in gfortran yet.
Access to computing environment
get_environment_variable(…)Query environment variables
command_argument_count()Retrieve the number of command line arguments
get_command_argument(…)Retrieve specific command line argument