After a few days of Fortran programming, I found a record of commonly used Fortran commands need to be kept, as there are subtle differences between Fortran and other languages I have used in the past.

Terminal Commands

Simple compilation

gfortran my_program.f90 -o my_program

Compiling only

gfortran -c my_program.f90

Multi-thread compilation

caf my_program.f90 -o my_program

Multi-thread execution

cafrun -n x ./my_program

where x is the number of images

note

  • $! can be used to speed up command typing

Fortran commands

Variable initialization

Declaration statement

single variable declaration

data_type :: variable_name

Array declaration

data_type :: array_name(n)
data_type, dimension(n) :: array_name

Finally don’t need to indexing with (y, x) lol

Dynamic array declaration

data_type, allocatable :: array_name(:)

Coarray declaration

data_type :: array_name(n)[*]

Constant declaration

data_type, parameter :: const_name = xxx

Allocation and Initialization of array

Array initialization

a = [(0, i = 1, 1000)]

Dynamic array allocation

integer :: is = -5, ie = 10
allocate(a(is:ie))

mold—A variable or an expression that has the same type as the object being allocated

real, allocatable :: a(:), b(:)
allocate(b(10:20))
allocate(a, mold=b)
a = 0

source—Equivalent to mold, except that the values of source are used to initial- ize the object being allocated

real, allocatable :: a(:), b(:)
b = [1.0, 2.0, 3.0]
allocate(a, source=b)

note If you assign an array to an allocatable array variable, the target array variable is auto-matically allocated with the correct size to match the array on the right side. The array variable can be already allocated or not.

clean use array after use

deallocate(a)

check a array is allocated or not

allocated(a)

Catching allocation

allocate(u(im), stat=stat, errmsg=err)

stat—An integer that indicates the status of the allocate statement. stat will be zero if allocation was successful; otherwise, it will be a nonzero positive number. errmsg—A character string that contains the error message if an error occurred (such as stat being nonzero) and is undefined otherwise.

Variable type

integer :: i, n
real :: x
complex :: c = (a, b)

note

  • a constant can be used to initialize other variables
  • constant’s value must be provided on initialization

specific kind of variable

use iso_fortran_env
integer(kind = int32) :: n

Control flow statements

if statement

if (condition) !...

if (condition) then
    !...
end if

if (condition) then
    !...
else if (other_condition) then
    !...
end if

do loop

do n = start, end
    !...
end do

do n = start, end, increment
    !...
end do

!named loop
outer_loop: do j = 1, jm
    inner_loop: do i = 1, im
        !...
    end do inner_loop
end do outer_loop

Fortran program units

program: the only unit can be invoked as an executable from the operating system

program xxx
    implicit none 
    integer :: a, b !declaration of variables

    if a == 1 call add(a, b) !invoke a subroutine
end program

function: Invoked in expressions, return only one value.

function sum(a,b)
    integer, intent(in) :: a, b
    integer :: sum

    sum = a + b
end function sum

OR

integer function sum(a,b)
    integer, intent(in) :: a, b
    ! no need to define sum

    sum = a + b
end function sum

OR

integer function sum(a,b) results(res)
    integer, intent(in) :: a,b

    res = a+b
end function sum

subroutine: Invoked with a call statement.

subroutine add(a,b)
    integer, intent(inout) :: a
    integer, intent(in) :: b
    a = a+b
    print *, 'a=', a
end subroutine add

Attributes

pure : indicate the function has no side effects. This includes modifying the value of a variable declared outside the procedure.

elemental : allows receiving array arguments in place of scalars

pure elemental integer function sum(a,b)
    integer, intent(in) :: a, b
    sum = a+b
end function sum

sum([1,2], 3) ! is valid
sum([1,2], [3,4]) ! is valid
sum([1,2,3], [4,5]) ! is not valid as arrays are not of the same shape.

optional argument

subroutine add(a, b, res, debug)
    integer, intent(in) :: a, b
    integer, intent(out) :: res
    logical, intent(in), optional :: debug

    if (present(debug)) then
        if (debug) then
            !...
        end if
    end if

    res = a + b
end subroutine add

modules

import module

use iso_fortran_env, only: int32, real32

rename entity when import

use mod_atmosphere, only: temperature
use mod_ocean, only: temperature_ocean => temperature, velocity_ocean => velocity

=> means point to

Module variable

module mod_circle
    implicit none
    private :: pi
    real, parameter :: pi = 3.14159265
contains
    !...
end module mod_circle

Parallel programming commands

Parallel programming image indexing

get current image number

this_image()

get total image number

num_images()

wait and sync

sync all

Coarray initialization

scalar coarray

real :: a[*]

array coarray

real :: a(10)[*]

dynamic coarray

real, allocable :: a(:)[:]

Coarray operation

assign value to coarray

a = 3.14 !assign value to local image

a[2] = 3.14 !assign value to indexed image

Parallel programming flow statements

embarrassingly parallel iteration

do concurrent (i = 1:grid_size)
    !...
end do