<<

Outline

Fortran as a language – look and feel – from code to program Variables and operators – declare, assign – arrays Getting started with Fortran Control structures – branches – loops

1 2

Why learn Fortran?

Well suited for numerical computations – Likely over 50% of scientific applications are written in Fortran FORTRAN AS A LANGUAGE Fast code ( can optimize well) Handy array data types Clarity of code Portability of code Optimized numerical libraries available

3 4 Short history of Fortran Short history of Fortran

John W. Backus et al (1954): The IBM Mathematical Fortran 2003 (2004): a major revision, adding e.g. object- Formula Translating System oriented features, -bindings Early years development: Fortran II (1958), Fortran IV – ”Fortran 95/2003” is the current de facto standard (1961), Fortran 66 & Basic Fortran (1966) The latest standard is Fortran 2008 (2010): a minor Fortran 77 (1978) revision Fortran 90 (1991) a major revision and Fortran 95 (1997) – Most notable addition: Fortran coarray syntax a minor revision to it – support nearly complete – The next revision: Fortran 2015

5 6

Compiling and linking Transition from code to a program

source code Compile and link in one go, execute the binary (., .F, .f90, .F90) gfortran main.f90 -o foo ./foo INCLUDE compiler output In more complex cases (multiple sources) files compiler (optional) – Compile each source code file (.f90) into an object file (.o) modules object code gfortran -c main.f90 gfortran -c sub.f90 (.o, .so) – Link object files into a binary and execute the binary libraries linker output linker gfortran -o foo main.o sub.o (.a, .so) (optional) ./foo

# after some modifications in “sub.f90” executable gfortran –c sub.f90 gfortran -o foo main.o sub.o ./foo 7 8 Look and feel Source code remarks program square_root_example Free format source code, but ! comments start with an exclamation point. ! you will find declarations, couple arithmetic operations – A variable name can be no longer than 31 characters containing ! and an interface that will ask a value for these computations. implicit none only letters, digits or underscore, and must start with a letter real :: x, y intrinsic sqrt ! fortran standard provides many commonly used functions – Maximum row length is 132 characters

! command line interface. ask a number and read it in No distinction between lower and uppercase characters write (*,*) 'give a value (number) for x:' – Character strings are case sensitive read (*,*) x Line break is the statement separator y = x**2+1 ! power function and addition arithmetic – If a line is ended with an (&), the line continues onto write (*,*) 'given value for x:', x the next line (max. 39 continuation lines allowed) write (*,*) 'computed value of x**2 + 1:', y ! print the square root of the argument y to screen – Semicolon (;) is the separator between statements on a single write (*,*) 'computed value of sqrt(x**2 + 1):', sqrt(y) end program square_root_example line

9 10

Variables

Variables must be declared at the integer :: n0 beginning of the program or procedure where they are used real :: a, real :: r1=0.0 the intrinsic data types in Fortran are VARIABLES integer, real, complex, character and complex :: c logical complex :: imag_number=(0.1, 1.0) They can also be given a value at character(len=80) :: place declaration (not recommended) character(len=80) :: name='james bond'

logical :: test0 = .true. Constants are defined with the logical :: test1 = .false. PARAMETER clause – they cannot be altered after their declaration real, parameter :: pi=3.14159

11 12 Operators Arrays Arithmetic operators real :: x,y integer, parameter :: m = 100, n = 500 integer :: i = 10 x = 2.0**(-i) !power function and negation precedence: first integer :: idx(m) x = x*real(i) !multiplication and type change precedence: second real :: vector(0:n-1) By default, Fortran indexing starts x = x/2.0 !division precedence: second real :: matrix(m, n) from 1 i = i+1 !addition precedence: third character (len=80) :: screen (24) i = i-1 !subtraction precedence: third Relational operators ! or < or .lt. !less than <= or .le. !less than or equal to integer, dimension(m) :: idx == or .eq. !equal to real, dimension(0:n-1) :: vector /= or .ne. !not equal to > or .gt. !greater than real, dimension(m, n) :: matrix >= or .ge. !greater than or equal to character(len=80), dimension(24) :: screen Logical operators .not. !logical negation precedence: first .and. !logical conjunction precedence: second .or. !logical inclusive disjunction precedence: third

13 14

Conditionals (if-else)

Conditionals allow the program to execute different code based on some condition()

if (condition) then CONTROL STRUCTURES ! do something else if (condition2) then ! .. or maybe alternative something else else ! .. or at least this end fi Condition can be anything from a simple comparison to a complex combination using logical operators

15 16 Conditionals example Loops 2 program placetest Three loop formats available in Fortran implicit none 1 logical :: in_square1, in_square2 real :: x, y – integer counter (fixed number of iterations) write(*,*) ’give point coordinates x and y’ – condition controlled (do until condition is false) read (*,*) x, y in_square1 = (x >= 0. .and. x <= 2. .and. y >= 0. .and. y <= 2.) – explicit exit statement in_square2 = (x >= 1. .and. x <= 3. .and. y >= 1. .and. y <= 3.) if (in_square1 .and. in_square2) then ! inside both write(*,*) ’point within both squares’ do {control clause} else if (in_square1) then ! inside square 1 only ! execute something again and again until stopped write(*,*) ’point inside square 1’ end do else if (in_square2) then ! inside square 2 only write(*,*) ’point inside square 2’ ! where the control clause (optional) is either of the form else ! both are .false. ! i=init_value, max_value, increment write(*,*) ’point outside both squares’ ! or a condition to execute while true end if ! while (condition) end program placetest

17 18

Loops example Loops example integer :: i, stepsize, numberofpoints real :: x, totalsum, eps integer, parameter :: max_points=100000 totalsum = 0.0 real :: x_coodinate(max_points), x, totalsum ! do loop without loop control ! a do-loop with an integer counter (count controlled) do stepsize = 2 read(*,*) x do i = 1, max_points, stepsize if (x < 0) then x_coordinate(i) = i*stepsize*0.05 end do ! = exit the loop ! condition controlled loop (do while) else if (x > upperlimit) then totalsum = 0.0 cycle ! = do not execute any further statements, but read(*,*) x ! instead cycle back to the beginning of the loop do while (x > 0) end if totalsum = totalsum + x totalsum = totalsum + x read(*,*) x end do end do

19 20 Labels example Select case program gcd integer :: i ! computes the greatest common divisor, Euclidean algorithm select case statements logical :: is_prime, implicit none test_prime_number matches the entries of a integer :: m, n, t write(*,*)’ give positive integers m and n :’ list against the case index ... read(*,*) m, n write(*,*)’m:’, m,’ n:’, n – Only one found match is Labels can be given to select case (i) positive_check: if (m > 0 .and. n > 0) then allowed case (2,3,5,7) main_algorithm: do while (n /= 0) control structures and used is_prime = .true. t = mod(m,n) in conjunction with e.g. exit – Usually arguments are case (1,4,6,8:10) m = n and cycle statements character strings or is_prime = .false. n = t case default integers end do main_algorithm is_prime=test_prime_number(i) write(*,*) ’greatest common divisor: ’,m – default branch if no end select else match found write(*,*) ’negative value entered’ ... end if positive_check end program gcd

21 22

Summary

Fortran is – despite its long history – a modern designed especially for scientific computing – Versatile, quite easy to learn, powerful In our first encounter, we discussed – Variables, data types, operators – Control structures: loops and conditionals

23 Outline

Structured programming Modules Procedures: functions and Interfaces

Procedures and modules

24 25

Structured programming

Structured programming based on program sub-units Modularity means dividing a program into minimally (functions, subroutines and modules) enables dependent modules – Testing and debugging separately – Enables division of the program into smaller self-contained – Re-use of code units – Improved readability Fortran modules enable – Re-occurring tasks – Global definitions of procedures, variables and constants – The key to success is in well defined data structures and Compilation-time error checking scoping, which lead to clean procedure interfaces – Hiding implementation details – Grouping routines and data structures – Defining generic procedures and custom operators

26 27 What are procedures? Procedure declarations

Procedure is of code that can be called from other Function code. Declaration: Declaration: Calling code passes data to procedure via arguments subroutine sub(arg1, arg2,...) [type] function func(arg1, Fortran has two types of procedures: arg2,...) [result(val)] [declarations] subroutines and functions [statements] [declarations] [statements] Subroutines pass data back via arguments end subroutine sub call mySubroutine(arg1_in, arg2_in, arg_out) end function func Functions return a value Use as Use as value = myFunction(arg1, arg2) call sub(arg1, arg2,...) res = func(arg1, arg2,...)

28 29

Procedure declarations: example Procedure arguments subroutine dist(x, y, d) real function dist(x, y) Fortran passes call arguments by reference implicit none implicit none real :: x, y, d real :: x, y – Only the memory addresses of the arguments are passed d = sqrt(x**2 + y**2) dist = sqrt(x**2 + y**2) end subroutine dist end function dist to the called procedure – Any change to the value of an argument changes the value program do_something program do_something ...... at the calling program call dist(x, y, ) r = dist(x, y) ...... – The INTENT keyword can be used to specify how argument is used

30 31 INTENT keyword Local variables in procedures subroutine foo(x, y, z) Declares how formal argument Local variables can be declared in the procedure implicit none is intended to be used for real, intent(in) :: x subroutine foo(x, y) real, intent(inout) :: y transferring a value implicit none real, intent(out) :: z – IN: the value of the real, intent(in) :: x real, intent(out) :: y argument is read-only i.e. x = 10 ! compilation error y = 10 ! correct cannot be changed integer :: i ! Local variable z = y * x ! correct – OUT: the value of the ... end subroutine foo argument must be provided Local variables are not visible outside the procedure – INOUT (the default) Compiler uses INTENT for error By default, local variables do not retain their values checking and optimization through successive calls of the procedure Improves readability of code

32 33

Local variables in procedures Should I use subroutine or function?

If local variable is given SAVE attribute, its value is Main difference is that functions can be used in retained through successive calls expressions: Initialization in declaration is done only in the first call to r = dist(x1, y1) + dist(x2, y2) procedure, and implicit SAVE is applied Recommendation as good programming practice: subroutine foo1(x) subroutine foo2(x) – Use functions for computing value based on input … … integer :: i integer :: i = 0 – Use subroutines for performing operation that changes i = 0 i = i + 1 i = i + 1 some of the inputs In foo1 variable i starts always from 0 and gets value 1 In foo2 variable i gets values 1, 2, 3, … in each successive call 34 35 Procedure types

There are four procedure types in Fortran 90: intrinsic, external, internal and module procedures Procedure types differ in PROCEDURE TYPES, MODULES – Scoping, i.e. what data and other procedures a procedure can access – Interface type, explicit or implicit Compiler can check the argument types of the at compile time only if the interface is explicit!

36 37

Implicit and explicit procedure types Module procedures and variables Procedures defined in modules can be referred The interfaces of the intrinsic, internal and module Declaration Usage to in any other program unit with the USE clause procedures are explicit MODULE check PROGRAM testprog The interfaces of the external procedures, such as many IMPLICIT NONE USE check INTEGER, PARAMETER :: & IMPLICIT NONE library subroutines, are implicit. You can write an explicit longint = SELECTED_INT_KIND(8) INTEGER(KIND=longint) :: x,test CONTAINS test = check_this(x) interface to those, though. FUNCTION check_this(x) RESULT(z) END PROGRAM testprog INTEGER(longint):: x, z Intrinsic procedures are the procedures defined by the ... A good habit programming language itself, such as INTRINSIC SIN END FUNCTION USE check, ONLY: longint END MODULE check

Module procedures are declared after the CONTAINS statement

38 39 Visibility of module objects Internal procedures

Variables and procedures in modules can be PRIVATE or Each program unit (program/subroutine/function) may PUBLIC contain internal procedures – PUBLIC = visible for all program units using the module (the default) SUBROUTINE mySubroutine ... – PRIVATE will hide the objects from other program units CALL myInternalSubroutine ... REAL :: x, y CONTAINS PRIVATE :: x SUBROUTINE myInternalSubroutine PUBLIC :: y ... ! Or END SUBROUTINE myInternalSubroutine REAL, PRIVATE :: x END SUBROUTINE mySubroutine REAL, PUBLIC :: y

40 41

Internal procedures Internal procedures: example

SUBROUTINE parent() Declared at the end of a program unit after the IMPLICIT NONE CONTAINS statement INTEGER :: i,j i = 1; j = 1 – Nested CONTAINS statements are not allowed CALL child() ! After subroutine call i = 2 and j = 1 Variable scoping: – Parent unit’s variables and objects are accessible CONTAINS – SUBROUTINE child() Parent unit’s variables are overlapped by local variables IMPLICIT NONE with the same name INTEGER :: j i = i + 1 ! Variable i is from the of parent Can be called only from declaring program unit j = 0 ! Variable j has local scope END SUBROUTINE child Often used for ” and local, convenience” procedures END SUBROUTINE parent

42 43 External procedures Interfaces

Declared in a separate program unit For external procedures, interfaces determine the type – Referred to with the EXTERNAL keyword and properties of arguments and return values – Compiled separately and linked to the final executable Defined by an INTERFACE block: Avoid using them within a program, module procedures interface provide much better compile time error checking interface-body External procedures are often needed when using end interface – procedures written with different programming language The interface-body matches the subprogram header – library routines (e.g. BLAS and LAPACK libraries) – position, rank and type of arguments – old F77 subroutines – return value type and rank (for functions)

44 45

Interfaces Interfaces: example

INTERFACE Wrong calling arguments ! LU decomposition from LAPACK SUBROUTINE not_dangerous(a, b, c) INTERFACE INTEGER :: a, b, c to EXTERNAL procedures SUBROUTINE DGETRF(M, N, A, LDA, IPIV, INFO) END SUBROUTINE not_dangerous may lead to errors during INTEGER :: INFO, LDA, M, N END INTERFACE INTEGER:: IPIV(*) the executable linking DOUBLE PRECISION :: A(LDA,*) INTEGER :: x, y, z phase or even when the END SUBROUTINE DGETRF x=1; y=1; z=1 END INTERFACE ! Call external subroutine without executable is being run ! Euclidean norm from BLAS ! an interface INTERFACE call dangerous(x,y,z) It is highly recommended FUNCTION DNRM2(N, X, INCX) ! Call external subroutine with to construct INTERFACE INTEGER :: N, INCX ! an interface DOUBLE PRECISION :: X(*) call not_dangerous(x,y,z) blocks for any external DOUBLE PRECISION :: DNRM2 END FUNCTION DNRM2 procedures used END INTERFACE

46 47 Global data and global variables Summary

Global variables can be accessed from any program unit makes the code more readable Module variables with SAVE attribute provide and easier to develop controllable way to define and use global variables – Procedures encapsulate some piece of work that makes MODULE commons sense and may be worth re-using elsewhere INTEGER, PARAMETER :: r = 0.42 INTEGER, SAVE :: n, ntot Fortran uses functions and subroutines REAL, SAVE :: abstol, reltol END MODULE commons – Values of procedure arguments may be changed upon – Explicit interface: type checking, limited scope calling the procedure Generally, use of global variables is not recommended Fortran modules are used for modular programming and data encapsulation

48 49 Outline

Introduction to Fortran arrays Array declaration and syntax Array initialization Array sections

Fortran arrays

50 51

Introduction to Fortran arrays Array declaration

INTEGER, PARAMETER :: M = 100, N = 500 Fortran is a very versatile programming language for INTEGER :: idx(M) handling arrays REAL :: vector(0:N-1) REAL :: matrix(M,N) – especially multi-dimensional arrays CHARACTER(len=80) :: screen(24) TYPE(my_own_type) :: object(10) Arrays refer to a data type (built-in or derived), but also have one or more dimensions specified in the variable ! or equivalently declaration INTEGER, DIMENSION(M) :: idx – Fortran supports up to 15 dimensions REAL, DIMENSION(0:N-1) :: vector REAL, DIMENSION(1:M,N) :: matrix CHARACTER(len=80), DIMENSION(24) :: screen TYPE(my_own_type), DIMENSION(1:10) :: object

52 53 Arrays in modern Fortran Array initialization

INTEGER :: m = 3, n = 4, i, j Array syntax in modern Arrays can be initialized REAL :: A(m,n), x(n), y(m) Fortran enables a neat – element by element ! Array syntax (and fast) way to express y=0.0 – copied from another array do j = 1, n linear algebra operations y(:) = y(:) + A(:,j)*x(j) 푁 – using single line data initialization statements end do – using the FORALL and WHERE statements 푦 = 퐴푥 = ෍ 푎푗푥푗 ⟺ ! or, equivalently, with explicit 푗=1 ! loops 푥 푦 푎 푎 푎 푎 1 y=0.0 1 11 12 13 14 푥 푦 푎 푎 푎 푎 2 do j = 1, n 2 = 21 22 23 24 푥 푦 푎 푎 푎 푎 3 do i = 1, m 3 31 32 33 34 푥 y(i) = y(i) + A(i,j)*x(j) 4 end do end do

54 55

Array initialization Array initialization with array constructors

! Element-by-element initialization do j = 1, n integer :: idx(0:10) idx(j) = j vector(j)=0 ! array constructor [ ] end do idx(0:10) = [0, (i, i = 1, 3), (0, j = 4, 10)] ! these can be used in setting variable values upon declaration ! Initialization by copying from another array integer :: values(3) = [11, 22, 33] REAL :: to1(100,100), from1(100,100) REAL :: to2(100,100), from2(0:199,0:199) ! equivalently, the older notation (/ /) ... idx(0:10) = (/ 0, (i, i = 1, 3), (0, j = 4, 10) /) to1 = from1 ! or the archaic F77 way data idx / 0, 1, 2, 3, 7 * 0 / to2(1:100, 1:100) = from2(0:199:2,0:199:2)

Every 2nd element

56 57 Array sections Array sections

! set elements from 3 to n+8 to 0 Fortran array syntax ! Conforming size of 3-by-10 When copying array sub_vector(3:n+8) = 0 LHS(1:3, 0:9)=RHS(-2:0, 20:29) enables accessing a subset sections, both left and ! access a subblock of a matrix of an array in an intuitive ! Error: LHS 2-by-10, RHS 3-by-10 right hand sides of the a(2:500,3:300:3) = 4.0 LHS(1:2, 0:9) = RHS(-2:0, 20:29) way: array sections assignment statement ! set every third element from 1 to must have conforming ! 3*n+1 to 1 every_third(1:3*n+1:3) = 1 dimensions

! set block [i-1:i+1,j-2:j+2] to k diag_block(i–1:i+1,j–2:j+2) = k

! access a subcube of a 3D array pixel_3d(128:150,56:80,1:256:8) = 320

58 59

Array sections Data layout in multi-dimensional arrays integer :: array(10, 20) Array sections can be Always increment the left-most index of multi- ! pass a full array passed into a procedure dimensional arrays in the innermost loop (i.e. fastest) call sub(array) An array section is usually – “Column major” ordering in Fortran vs. “Row major” ! pass a subblock copied into a hidden ordering in C call sub(array(5:10,10:20)) temporary array upon A compiler (with sufficient optimization flags) may re- ! pass a non-contiguous subblock calling a procedure and order loops automatically call sub(array(1:10:2,1:1)) copied back to the array ! pass an array slice section upon return do i=1,N do j=1,M call sub(array(1:4,1:)) do j=1,M do i=1,N call sub(array(:10,:)) y(i) = y(i)+ a(i,j)*x(j) y(i) = y(i)+ a(i,j)*x(j) end do end do end do end do

60 61 Summary

Arrays make Fortran a very versatile programming language for computationally intensive program development Using array syntax, vectors and matrices can be initialized and used in a very intuitive way – perfect for scientific computing! Use of array sections increase code readability and often reduce the chance for mistakes

62 Outline

Dynamic memory allocation Array intrinsic functions Fortran pointer attribute

More about Fortran arrays

63 64

Dynamic memory allocation Dynamic memory allocation: example

integer :: m, n, alloc_stat Fortran provides two different mechanisms for allocating integer, allocatable :: idx(:) dynamically memory for arrays: real, allocatable :: mat(:,:)

1. Array variable declaration has an allocatable (or a m = 100 ; n = 200 pointer) attribute, and memory is allocated through allocate( idx(0:m–1) , stat = alloc_stat ) the allocate statement if (alloc_stat /= 0) stop ! an error 2. Array variable, which is declared in the procedure with (runtime) size information coming from the procedure’s allocate( mat(m, n) , stat = alloc_stat ) if (alloc_stat /= 0) stop ! an error argument list or from a Fortran module, is called an automatic array: no allocate is needed deallocate(idx , mat)

65 66 Dynamic memory allocation: example Array intrinsic functions subroutine sub (m) When automatic arrays Array intrinsic functions are built-in functions which can use some_module, only : n integer, intent(in) :: m are being used, no explicit apply various operations on the whole array at once allocate or integer :: idx(0:m–1) As a result another array or just a scalar value is returned real :: mat(m , n) deallocate is needed ! implementation omitted A subset selection through masking is also possible end subroutine sub – Operations are performed for those elements where corresponding elements of the mask are .true. – Masking and use of array (intrinsic) functions is often accompanied with use of forall and where array statements

67 68

Array intrinsic functions: Array intrinsic functions size, shape, count, sum The most commonly used array intrinsic functions are: size(array [, dim]) returns # of elements in the – size, shape, count, sum array [, along the specified dimension] – any, all shape(array) returns an integer vector containing the – minval, maxval , minloc, maxloc size of array in each dimension – reshape count(l_array [,dim]) returns count of elements – dot_product, matmul, transpose which are .true. in l_array – pack, unpack, spread sum(array[, dim][, mask]) sum of the elements of array [, along dimension] [, under mask]

69 70 Array intrinsic functions: Array intrinsic functions: any, all minval, maxval, minloc, maxloc any(l_array [, dim]) returns a scalar value of minval(array [,dim] [, mask]) returns the .true. if any value in l_array is .true. minimum value of a given array [, along the specified dimension] and [, under mask] all(l_array [, dim]) returns a scalar value of maxval is the same as minval, but returns the maximum .true. if all values in l_array are .true. value of a given array minloc(array [, mask]) returns a vector of location(s) [, under mask], where the minimum value(s) is/are found maxloc similar to minloc, but for maximums

71 72

Array intrinsic functions: example Array intrinsic functions: reshape integer :: j integer, parameter :: m = 10, n = 20 reshape(array, shape) returns a reconstructed (=a real :: x(m,n), v(n) copy of an) array with different shape than in the call random_number(x) input array print *, size(x), size(v) ! prints m * n, n can be used as a single line statement to initialize an array print *, shape(x) ! prints m, n print *, size(shape(x)) ! prints 2 (sometimes at the expense of readability) print *, count(x >= 0) print *, sum(x, dim=2, mask=x < 0.5) ! the result is a vector integer :: a(6), b(3,2), i v(1:n) = [ (j, j=1,n) ] a = [(i, i=1,6)] print *, any(v > -1 .and. v < 1) print *, all(x >= 0, dim=1) b = reshape(a, [3,2]) print *, minval(v), maxval(v) print *, minloc(v), maxloc(v)

73 74 Array intrinsic functions: Array intrinsic functions: example dot_product, matmul, transpose dot_product(a_vec, b_vec) returns a scalar dot integer :: l, m, n real :: a(l,m), b(m,n), c(l,n) product of two vectors real :: a_tr(m,l) matmul(a_mat, b_mat) returns a matrix containing real :: v1(n), v2(n), dotp matrix multiply of two matrices ! transpose a matrix a_tr = transpose(a) transpose(a_mat) returns a transposed matrix of the ! compute matrix-matrix product c=a*b input matrix c = matmul(a, b) ! compute dot product (v1,v2)=v2^t*v1 dotp = dot_product(v1, v2)

75 76

Array intrinsic functions Array intrinsic functions: example

Array control statements forall and where are integer :: j, ix(10000) integer :: j commonly used in the context of manipulating arrays ... real :: a(100,100), b(100), c(100) where (ix < 0) forall and where can provide masked assignment of ... ! fill in diagonal elements values using efficient vector operations elsewhere forall (j=1:100) a(j,j) = b(j) ... end where ! fill in lower bi-diagonal matrix forall (j=2:100) a(j,j-1) = c(j)

77 78 Pointers to arrays Pointers to arrays

The pointer attribute enables to create array (or scalar) A pointer can refer to an already allocated memory aliasing variables region – Pointer variables are usually employed to refer to another Initialized to point to nothing integer, pointer :: p_x(:) => null() array or an array section integer, target :: x(1000) A pointer variable can also be a sole dynamic variable ... p_x => x Pointers provide a neat way for array itself p_x => x(2 : 300) sections p_x => x(1 : 1000 : 5) – Not recommended; use the allocatable attribute ... instead and employ pointer variables for aliasing only p_x(1) = 0 nullify(p_x) This would also change x(1) to 0 Note for C : a "pointer" has a different meaning in C and Fortran Disconnects p_x from x

79 80

Pointers to arrays Array arguments to procedures real, pointer :: p_mat(: ,:) => null() associated function can Two (three) ways to pass arrays to procedures real, target :: mat(100,200) be used to check whether – Explicit shape array (dimensions passed explicitly, F77-style) p_mat => mat a pointer is associated subroutine foo(size1, size2, ..., matrix, ...) if ( associated (p_mat) ) & with a target implicit none print *, 'points to something' integer :: size1, size2 nullify(p_mat) – Returns .true. if real, dimension(size1, size2) :: matrix if (.not. associated (p_mat) ) & associated with a target, ... print *, 'points to nothing' .false. if not – Assumed shape array (requires explicit interface) – For an uninitialized subroutine foo(matrix) pointer variables, the real, dimension(:,:) :: matrix return value is undefined . One can use the SIZE for checking the actual dimensions

81 82 Summary

Array intrinsic functions further simplify coding efforts and improve program code readability when using Fortran arrays Dynamic memory allocation enables sizing of arrays according to particular needs Pointers offer a versatile alias mechanism to refer into the existing arrays or array sections

83 Outline

Input/output (I/O) formatting Internal I/O File I/O – File opening and closing – Writing and reading to/from a file – Formatted and unformatted (binary) files Input/Output – Stream I/O

84 85

Input/Output formatting Output formatting Data type Format descriptors Examples To prettify output and to make it human readable, use Integer iw, iw.m write(*,'(i5)') j format descriptors in connection with the write write(*,'(i5.3)') j statement write(*,'(i0)') j Real (decimal and fw.d write(*,'(f7.4)') r Although less often used nowadays, it can also be used exponential forms, ew.d write(*,'(e12.3)') r with read to input data at fixed line positions and using auto-scaling) gw.d write(*,'(g20.13)') r predefined field lengths Character a, aw write(*,'(a)') c Used through format statements, character variable Logical lw write(*,'(l2)') l or embedded in read/write fmt keyword w=width of the output field, d=number of digits to the right of decimal point, m=minimum number of characters to be used. Variables: Integer :: J, Real :: R, Character :: C, Logical :: L

86 87 Output formatting: miscellaneous The I0 and G0 format descriptors

With complex numbers provide format for both real and Dynamic sizing of REAL and INTEGER valued output imaginary parts: – I0 appeared in F03 and G0 was introduced in F08 complex :: z write (*,'(f6.3,2x,f6.3)') z ! real & imaginary parts Output fields are left justified with all the unnecessary leading blanks (and precision for REAL valued variables) Line break and whitespace: removed write (*,'(f6.3,/,f6.3)') x, y ! linebreak between x,y write (*,'(i3,2x,f6.3)') i, x ! 2 spaces between i & x integer :: i = 12345 real (kind=4) :: sp = 1.23e0 It is possible that an edit descriptor will be repeated a real (kind=8) :: dp = 1.234567890d0 specified number of times write(*,fmt='("")') i,sp,dp write (*,'(5i8)') ivec(1:5) Output is write (*,'(4(i5,2x,f8.3))') (ivec(j),zvec(j),j=1,4)

88 89

Handling character strings Internal I/O

Fortran provides several intrinsic functions for handling Often it is necessary to filter out data from a given character strings, such as character string – trim(string) - removes blank spaces from the end of – Or to pack values into a character string string Fortran internal I/O with READ & WRITE becomes – adjustl(string)/adjustr(string) - moves blank now handy spaces from the beginning/end of the string to the Actual files are not involved at all end/beginning of it – len(string) - length of a string – index(string, substring) - returns the starting position of a substring within a string

90 91 Internal I/O: examples Opening and closing files: concepts character(len=13) :: cl1 character(len=60) :: cl2 Writing to or reading from a file is similar to writing onto integer :: njobs, istep a terminal screen or reading from a keyboard ! extract a number from character string Differences cl1 = 'time step# 10' read(cl1,fmt='(10x,i3)') istep – File must be opened with an OPEN statement, in which the unit number and (optionally) the file name are given ! write data to a character string njobs = 2014 – Subsequent writes (or reads) must to refer to the given write(cl2,'(a,i0)') 'the number of jobs completed = ', njobs unit number – File should be closed at the end

92 93

Opening and closing a file Opening and closing a file

The syntax is (the brackets [ ] indicate optional keywords The first parameter is the unit number or arguments) The keyword unit= can be omitted open([unit=]iu, file='name' [, options]) The unit numbers 0, 5 and 6 are predefined close([unit=]iu [, options]) – 0 is output for standard (system) error messages For example – 5 is for standard (user) input open(10, file= 'output.dat', status='new') close(unit=10, status='keep') – 6 is for standard (user) output – These units are opened by default and should not be re- opened nor closed by the user

94 95 Opening and closing a file File opening options

The default input/output unit can be referred with a star: status: existence of a file write(*, ...) – 'old', 'new', 'replace', 'scratch', 'unknown' read(*, ...) position: offset, where to start writing – Note that these are not necessarily the same as the stdout and stdin unit numbers 6 and 5 – 'append' If the file name is omitted in the OPEN, the file name will action: file operation mode based on unit number being opened, e.g. for unit=12 – 'write', 'read', 'readwrite' this usually means the filename ’fort.12’ (on UNIX- form: text or binary file systems) – 'formatted', 'unformatted'

96 97

File opening options File opening: file properties access: direct or sequential file access Use inquire statement to find out information about – 'direct', 'sequential', 'stream', – file existence iostat: error indicator, (output) integer – file unit open status – non-zero only upon an error – various file attributes err: the fortran number to jump upon an error The syntax has two forms, one based on file name, the recl: record length, (input) integer other for unit number inquire(file='name', options ...) – for direct access files only inquire(unit=iu, options ...) – warning (check): may be in bytes or words

98 99 File opening: file properties File opening: file properties example exist does file exist? (logical) ! check the existence of a file opened is file / unit opened? (logical) logical :: file_exist form 'formatted' or 'unformatted' (char) inquire(file='foo.dat', exist=file_exist) access 'sequential' or 'direct' or 'stream' (char) if (.not. file_exist) then write(*,*) 'the file does not exist' action 'read', 'write', 'readwrite' (char) else recl record length (integer) ! do something with the file foo.dat size file size in bytes (integer) endif

100 101

File writing and reading Formatted vs. unformatted files

Writing to and reading from a file is done by giving the Text or formatted files are corresponding unit number (iu) as a parameter : – Human readable write(iu,*) str The star format (*) indicates list- – Portable i.e. machine independent write(unit=iu, fmt=*) str directed output (i.e. does read(iu,*) str not choose the input/output styles) Binary or unformatted files are read(unit=iu, fmt=*) str – Machine readable only, generally not portable Formats and other options can be used as needed – Much faster to access than formatted files If keyword 'unit' is used, also the keyword 'fmt' must be – Suitable for large amount of data due to reduced file sizes used – Internal data representation used for numbers, thus no – Note: 'fmt' is applicable to formatted, text files only number conversion, no rounding of errors compared to formatted data

102 103 Unformatted I/O Stream I/O A binary file write adds extra record delimiters (hidden Write to a sequential binary file from programmer) to the beginning and end of records real :: rval character(len=60) :: string In Fortran 2003 using access method 'stream' avoids this open(10, file='foo.dat', form='unformatted') and implements a C-like approach write(10) rval write(10) string It is recommended to use stream I/O close(10) Create a stream (binary) file No format descriptors allowed real :: dbheader(20), dbdata(300) Reading similarly open(10,file='my_database.dat', access='stream') write(10) dbheader read(10) rval write(10) dbdata read(10) string close(10) Reading similarly

104 105

Summary

Input/Output formatting Internal I/O Files: communication between a program and the outside world – Opening and closing a file – Data reading & writing Use unformatted (stream) I/O for all except text files

106 Built-in data types in Fortran

Fortran has built-in data types for integers, floating point numbers (real), truth values (logical) and variable length character strings – Each of these built-in types may be declared as multi- dimensional arrays The numerical precision of reals and integers can be controlled through the kind parameter, e.g. Derived data types use iso_fortran_env, only : REAL64, INT16 ... real(kind=REAL64) :: double_precision_number integer(kind=INT16) :: short_integer_number

107 108

What is a derived data type? What is a derived data type?

Derived data type is a composed of built- For real-world applications, using only intrinsic types is in data types and possibly other derived data types often insufficient – Equivalent to structs in C programming language It is beneficial to group the data together as larger Derived type is defined in the variable declaration section objects of programming unit – Code becomes easier to read and maintain – Not visible to other programming units – Cleaner interfaces – Unless defined in a module and used via the use clause, – Encapsulation of data which is most often the preferred way Variables used in the same context should be grouped together using modules and derived data types

109 110 Derived type declaration Derived type declaration

Type declaration Data type initialization type particletype real :: x water(1) = particletype(0.75, 0.19, 0.0, 1) real :: y water(2) = particletype(0.0, -0.38, 0.0, 8) real :: z water(3) = particletype(-0.75, 0.19, 0.0, 1) integer :: charge end type particletype ! or elementwise water(1) % x = 0.75 water(1) % y = 0.19 Declaring a variable with the type declaration water(1) % z = 0.0 type(particletype) :: proton, water(300)

111 112

Nested derived types Data structures: memory layout

Derived types can contain other derived types as Array of Structures Structure of Arrays components type point type point type moleculetype real :: x, y, z real, allocatable :: x(:) type(particletype), allocatable :: atoms(:) end type point real, allocatable :: y(:) real :: mu real, allocatable :: z(:) type(point), allocatable :: points end type moleculetype end type point ... type(point) :: points type solvent allocate(points(N)) type(moleculetype), allocatable :: fluid(:) complex :: epsilon allocate(points%x(N), & end type solvent points%y(N), & points%z(N)) Access as beverage % fluid(1) % atoms(1) % x = 0.75

113 114 Data structures: memory layout Summary

Array of Structures Structure of Arrays Derived data types enables grouping of data to form integer :: i, j integer :: i, j logical objects real :: dist(4,4) real :: dist(4,4) do i = 1, 4 do i = 1, 4 A Fortran program becomes more readable and modular do j = i, 4 do j = i, 4 dist(i,j) = sqrt( & dist(i,j) = sqrt( & with sensible use of derived data types (points(i)%x-points(j)%x)**2 + (points%x(i)-points%x(j))**2 + (points(i)%y-points(j)%y)**2 + (points%y(i)-points%y(j))**2 + Handling of complex data structures such as linked lists (points(i)%z-points(j)%z)**2) (points%z(i)-points%z(j))**2) end do end do or binary trees becomes more manageable with use of end do Memory layout end do Memory layout derived types 0 0 Enables the use of object oriented programming concepts points(i)%x points(i)%y points(i)%z points%x(:) points%y(:) points%z(:)

115 116 Outline

Generic procedures Command line arguments Environment variables Executing commands

Useful features

117 118

Generic procedures Generic procedures example

Procedures which perform similar actions but for MODULE swapmod PROGRAM switch IMPLICIT NONE USE swapmod different data types can be defined as generic INTERFACE swap IMPLICIT NONE procedures MODULE PROCEDURE swap_real, swap_char CHARACTER :: n,s END INTERFACE REAL :: x,y Procedures are called using the generic name and CONTAINS n = 'J' SUBROUTINE swap_real(a, b) s = 'S' compiler uses the correct procedure based on the REAL, INTENT(INOUT) :: a, b x=10 REAL :: temp y=20 argument number, type and dimensions temp = a; a = b; b = temp PRINT *,x,y END SUBROUTINE PRINT *,n,s – Compare with ”overloading” in C++ SUBROUTINE swap_char(a, b) CALL swap(n,s) CHARACTER, INTENT(INOUT) :: a, b CALL swap(x,y) Generic name is defined in INTERFACE section CHARACTER :: temp PRINT *,x,y temp = a; a = b; b = temp PRINT *,n,s END SUBROUTINE END PROGRAM END MODULE swapmod

119 120 Overloading operators example

Procedures can also be assigned to operators MODULE operator_demo PROGRAM switch IMPLICIT NONE USE operator_demo – For example *, +, -, ==, <, > TYPE pair IMPLICIT NONE REAL :: a, b TYPE(pair) :: p1, p2 – Own operator names can be used too, for example .dot. END TYPE INTERFACE operator (<) p1%a = 1.0; p1%b = 2.0 Can improve code readability MODULE PROCEDURE is_smaller p2%a = 3.0; p2%b = 4.0 END INTERFACE – Overuse can have opposite effect! CONTAINS IF (p1 < p2) THEN LOGICAL FUNCTION is_smaller(x, y) PRINT *, ‘p1 is smaller’ Useful with user-defined datatypes TYPE(pair), INTENT(INOUT) :: x, y ELSE IF (x%a < y%a .and. x%b < y%b) THEN PRINT *, ‘p1 not smaller’ is_smaller = .true. END ELSE is_smaller = .false. END PROGRAM END IF END SUBROUTINE END MODULE swapmod

121 122

Command line arguments Command line arguments …

Parameters to a program are very often given to Access separate command line arguments programs as command line arguments get_command_argument(number[,value][,length][,status]) – Input file(s), modify program behavior, etc. – number is of type integer and denotes which argument to get Fortran 2003 has a standardized method for reading command line arguments – value is of type character string and contains the value of the requested argument on return (optional) – get_command_argument and – length is of type integer and contains the length of the command_argument_count requested argument on return (optional) To access the whole command line, use – status is of type integer. On successful return status is – get_command 0, -1 if value was too short to contain actual argument and 1 if argument could not be returned (optional)

123 124 Command line arguments … Command line input

Get the number of command line arguments Example: reading in subroutine read_command_line(height, width) integer :: command_argument_count() integer, intent(out) :: height, width two integer values character(len=10) :: args(2) integer :: n_args, i from the command n_args = command_argument_count() if ( n_args /= 2 ) then line, e.g. write(*,*) ' Usage : ./exe height width' % ./a.out 100 100 call abort() end if do i = 1, 2 call get_command_argument(i,args(i)) args(i) = trim(adjustl(args(i))) end do read(args(1),*) height read(args(2),*) width end subroutine read_command_line

125 126

Command line arguments … Environment variables

Access the whole command line Besides command line arguments, environment variables call get_command(command[,length][,status]) are a common way to modify program behaviour – command is of type character string and contains the value Fortran 2003 has a standardized method for accessing of the command line on return. values of environment variables – length is of type integer and contains the length of the command line on return (optional) – status is of type integer. On successful return status is 0, -1 if value was too short to contain actual argument and 1 if argument could not be returned (optional)

127 128 Environment variables Environment variables: example

program environment Access a value of an implicit none call get_environment_variable(name,value[,length] character(len=256) :: enval [,status][,trim_name]) integer:: len,stat

– name is of type character string and contains the name of the ! extract hostname requested variable call get_environment_variable('hostname',enval,len,stat) if (stat == 0) write (*,'(a,a)') 'host=', enval(1:len) – value is of type character string and contains the value of the requested variable ! extract user call get_environment_variable('user',enval,len,stat) – length is of type integer and contains the length of the if (stat == 0) write (*,'(a,a)') 'user=', enval(1:len) requested variable on return (optional) end program environment – status (optional) – trim_name is of type logical and sets if trailing blanks are allowed in variable names or not (optional) 129 130

Executing commands Executing commands

Invoking external programs from within a program is Execute a command line occasionally needed call execute_command_line(command[,wait][,exitstat] [,cmdstat][,cmdmsg]) – No source nor library API available for a useful program – command is a character string containing the command to be invoked – /python/etc parsing scripts – wait is logical value indicating if command termination is to be waited Fortran 2008 has a standardized method for invoking an (.true., the default) or if the command is to be executed external command asynchronously (.false.) (optional) – exitstat is an integer value containing the return value of the command if wait=.true. (optional) – cmdstat is an integer value. It is assigned a value of zero if command executed successfully. For other return codes, see docs (optional) – cmdmsg is a character string containing explanatory message for positive values of cmdstat (optional) 131 132 Executing commands: example Summary program execcommand Generic procedures implicit none integer :: estat, cstat – Same procedure name for multiple argument types Operator overloading ! execute a unix command – Can use operators for user-defined types call execute_command_line('ls -al', .true., estat, cstat) if (estat==0) write (*,'(a)') 'command completed successfully’ Reading command line arguments and environment end program execcommand variables Executing system commands

133 134