The Queen's University of Belfast
QUBPCCParallel Computer Centre

[Next] [Previous] [Top]

Procedures
and
Modules


Procedures
and modules

Topics

Program units



Main program

PROGRAM [name]
[specification statements]
[executable statements]
...
END [PROGRAM [name]]
PROGRAM test
...
...
! END
! END PROGRAM
END PROGRAM test

Procedures

Functions and subroutines

External procedures

Form

SUBROUITNE name ( dummy-argument-list )
[specification-statements]
[executable-statements]
...
END [SUBROUTINE [name]]
or

FUNCTION name ( dummy-argument-list )
[specification-statements]
[executable-statements]
...
END [FUNCTION [name]]

Internal procedures

Example

PROGRAM main

IMPLICIT NONE
REAL :: a, b, c
REAL :: mainsum
... mainsum = add( )
...
CONTAINS FUNCTION add ( )
REAL :: add ! a,b,c defined in `main'
add = a + b + c
END FUNCTION add
...

END PROGRAM main

INTERFACE blocks

Explicit vs implicit

Form

INTERFACE
interface_body
...
END INTERFACE

where interface_body is an exact copy of the subprogram specification, its dummy argument specifications and its END statement

INTERFACE
REAL FUNCTION func(x)
REAL, INTENT(IN) :: x
END FUNCTION func
END INTERFACE

Procedure arguments

INTENT

INTEGER, INTENT(IN) :: in_only REAL, INTENT(OUT) :: out_only INTEGER, INTENT(INOUT) :: both_in_out

Keyword arguments

REAL FUNCTION area (start, finish, tol)
IMPLICIT NONE
REAL, INTENT(IN) :: start, finish, tol
...
END FUNCTION area
a = area(0.0, 100.0, 0.01) b = area(start = 0.0, tol = 0.01, finish = 100.0) c = area(0.0, finish = 100.0, tol = 0.01)

Optional arguments

REAL FUNCTION area (start, finish, tol)
IMPLICIT NONE
REAL, INTENT(IN), OPTIONAL :: &
start, finish, tol
...
END FUNCTION area
a = area(0.0, 100.0, 0.01) b = area(start=0.0, finish=100.0, tol=0.01) c = area(0.0) d = area(0.0, tol=0.01)

PRESENT

REAL FUNCTION area (start, finish, tol)
IMPLICIT NONE
REAL, INTENT(IN), OPTIONAL :: &
start, finish, tol
REAL :: ttol
...
IF ( PRESENT(tol) ) THEN
ttol = tol
ELSE
ttol = 0.01
END IF
...
END FUNCTION area

Derived type

Procedure arguments can be of derived type if:

Procedures as arguments

The calling program unit:

...
INTERFACE
REAL FUNCTION func(x, y)
REAL, INTENT(IN) :: x, y
END FUNCTION func
END INTERFACE
...
CALL area(func, start, finish, tol)

The external function:

REAL FUNCTION func(x, y)
IMPLICIT NONE
REAL, INTENT(IN) :: x, y
...
END FUNCTION func

RESULT clause
for functions

FUNCTION add (a, b, c) RESULT (sum)
IMPLICIT NONE
REAL, INTENT(IN) :: a, b, c
REAL :: sum
sum = a + b + c
END FUNCTION add

Array-valued functions

FUNCTION add_vec (a, b, n)

IMPLICIT NONE
INTEGER, INTENT(IN) :: n
REAL, DIMENSION (n), INTENT(IN) :: a, b
REAL, DIMENSION (n) :: add_vec
INTEGER :: i

DO i = 1, n
add_vec(i) = a(i) + b(i)
END DO

END FUNCTION add_vec

Recursive procedures

RECURSIVE FUNCTION fact(n) RESULT(res)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n
INTEGER :: res
IF (n == 1) THEN
res = 1
ELSE
res = n * fact(n - 1)
END IF
END FUNCTION fact

Generic procedures

INTERFACE generic_name
specific_interface_body
specific_interface_body
...
END INTERFACE

Example

SUBROUTINE swapreal (a, b)
IMPLICIT NONE
REAL, INTENT(INOUT) :: a, b
REAL :: temp
temp = a; a = b; b = temp
END SUBROUTINE swapreal
SUBROUTINE swapint (a, b)
IMPLICIT NONE
INTEGER, INTENT(INOUT) :: a, b
INTEGER :: temp
temp = a; a = b; b = temp
END SUBROUTINE swapint

Example

INTERFACE swap ! generic name
SUBROUTINE swapreal (a, b)
REAL, INTENT(INOUT) :: a, b
END SUBROUTINE swapreal
SUBROUTINE swapint (a, b)
INTEGER, INTENT(INOUT) :: a, b
END SUBROUTINE swapint
END INTERFACE
CALL swap(x, y)

Modules

MODULE module-name
[specification-stmts]
[executable-stmts]
[CONTAINS
module procedures]
END [MODULE [module-name]]

Global data

MODULE globals
REAL, SAVE :: a, b, c
INTEGER, SAVE :: i, j, k
END MODULE globals
USE globals
! allows all variables in the module to be accessed
USE globals, ONLY : a, c
! allows only variables a and c to be accessed
USE globals, r => a , s => b
! allows a, b and c to be accessed with local
! variables r, s and c

Module procedures

Example to `add' variables with derived type:

MODULE point_module
TYPE point
REAL :: x, y
END TYPE point
CONTAINS
FUNCTION addpoints (p, q)
TYPE (point), INTENT(IN) :: p, q
TYPE (point) :: addpoints
addpoints%x = p%x + q%x
addpoints%y = p%y + q%y
END FUNCTION addpoints
END MODULE point_module

A program unit would contain:

USE point_module
TYPE (point) :: px, py, pz
...
pz = addpoints(px, py)

Generic procedures

MODULE genswap
IMPLICIT NONE
TYPE point
REAL :: x, y
END TYPE point
INTERFACE swap ! generic interface
MODULE PROCEDURE swapreal, &
swapint, swaplog, swappoint
END INTERFACE
CONTAINS
SUBROUTINE swappoint (a, b)
TYPE (point), INTENT(INOUT) :: a, b
TYPE (point) :: temp
temp = a; a = b; b = temp
END SUBROUTINE swappoint
... ! swapint, swapreal, swaplog
! procedures are defined here
END MODULE genswap

Public and private objects

INTEGER, PRIVATE :: keep, out

Overloading operators

INTERFACE OPERATOR (intrinsic_operator)
interface_body
END INTERFACE

Example

MODULE operator_overloading
IMPLICIT NONE
...
INTERFACE OPERATOR (+)
MODULE PROCEDURE concat
END INTERFACE
...
CONTAINS
FUNCTION concat(cha, chb)
CHARACTER (LEN=*), INTENT(IN) :: &
cha, chb
CHARACTER (LEN=LEN_TRIM(cha) + &
LEN_TRIM(chb)) :: concat
concat = TRIM(cha) // TRIM(chb)
END FUNCTION concat
...
END MODULE operator_overloading
Now the expression `cha + chb' is meaningful

Defining operators

PROGRAM main
USE distance_module
TYPE (point) :: p1, p2
...
distance = p1 .DIST. p2
...
END PROGRAM main

Example

MODULE distance_module
...
TYPE point
REAL :: x, y
END TYPE point
...
INTERFACE OPERATOR (.DIST.)
MODULE PROCEDURE calcdist
END INTERFACE
...
CONTAINS
...
REAL FUNCTION calcdist (px, py)
TYPE (point), INTENT(IN) :: px, py
calcdist = SQRT ((px%x-py%x)**2 &
+ (px%y-py%y)**2 )
END FUNCTION calcdist
...
END MODULE distance_module

Assignment overloading

REAL :: ax
TYPE (point) :: px
...
ax = px ! type point assigned to type real
... ! not valid until defined
INTERFACE ASSIGNMENT (=)
subroutine interface body
END INTERFACE

Example

MODULE assignoverload_module
...
TYPE point
REAL :: x, y
END TYPE point
...
INTERFACE ASSIGNMENT (=)
MODULE PROCEDURE assignnew
END INTERFACE
...
CONTAINS
SUBROUTINE assignnew (ax, px)
REAL, INTENT(OUT) :: ax
TYPE (point), INTENT(IN) :: px
ax = MAX(px%x, px%y)
END SUBROUTINE assignnew
...
END MODULE assignoverload_module

The program unit might include:

...
USE assignover_mod
...
REAL :: ax
TYPE (point) :: px
...
ax = px ! Type point to type real now defined
...

Scope

Scoping unit

The scope of a named entity or label is the set of non-overlapping scoping units where that name or label may be used unambiguously.

A scoping unit is one of the following:

Labels and names

Example

MODULE scope1 ! scope 1
... ! scope 1
CONTAINS ! scope 1
SUBROUTINE scope2 ! scope 2
TYPE scope3 ! scope 3
... ! scope 3
END TYPE ! scope 3
INTERFACE ! scope 3
... ! scope 4
END INTERFACE ! scope 3
REAL x, y ! scope 3
100 ... ! scope 3
CONTAINS ! scope 3
FUNCTION scope5(...) ! scope 5
REAL y ! scope 5
y = x + 1.0 ! scope 5
100 ... ! scope 5
END FUNCTION scope5 ! scope 5
END SUBROUTINE scope2 ! scope 2
END MODULE scope1 ! scope 1

Program structure

Order of statements

When to use INTERFACE blocks

When a module/external procedure is called:

Additionally, when an external procedure:

Summary

Fortran 77 style:

Simple Fortran 90:

Fortran 90 with modules:


[Next] [Previous] [Top]
All documents are the responsibility of, and copyright, © their authors and do not represent the views of The Parallel Computer Centre, nor of The Queen's University of Belfast.
Maintained by Alan Rea, email A.Rea@qub.ac.uk
Generated with CERN WebMaker