Fortran modules

The general structure of a Fortran module:

module <MODULE-NAME>
    ! Declare variables
contains
    ! Define subroutines or functions
end module <MODULE-NAME>

A program or subroutine can use this module:

program <NAME>
    use <MODULE-NAME>
    ! Declare variables
    ! Executable statements
end program <NAME>

The line:

use <MODULE-NAME>

can be replaced by:

use <MODULE-NAME>, only: <LIST OF SYMBOLS>

to specify that only certain variables/subroutines/functions from the module should be used. Doing it this way also makes it clear exactly what symbols are coming from which module in the case where you use several modules.

A very simple module is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
! /codes/sub1m.f90

module sub1m

contains

  subroutine sub1()
    print *, "In sub1"
  end subroutine sub1

end module sub1m

and a program that uses this:

1
2
3
4
5
6
7
! /codes/main.f90

program demo
  use sub1m, only: sub1
  print *, "In main program"
  call sub1()
end program demo

Some reasons to use modules

  • Can define global variables in modules to be used in several different routines (we will see more examples later). In Fortran 77 this had to be done with common blocks – much less elegant.
  • Subroutine/function interface information is generated to aid in checking that proper arguments are passed. It’s often best to put all subroutines and functions in modules for this reason.
  • Can define new data types to be used in several routines.

Compiling modules

Modules must be compiled before any program units that use the module. When a module is compiled, a .o file is created, but also a .mod file is created that must be present in order to compile a unit that uses the module.

Circles module example

Here is an example of a module that defines one parameter pi and two functions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
! /codes/circle1/circle_mod.f90

module circle_mod

  implicit none
  real(kind=8), parameter :: pi = 3.141592653589793d0

contains

  real(kind=8) function area(r)
    real(kind=8), intent(in) :: r
    area = pi * r**2
  end function area

  real(kind=8) function circumference(r)
    real(kind=8), intent(in) :: r
    circumference = 2.d0 * pi * r
  end function circumference

end module circle_mod

This might be used as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
! /codes/circle1/circle_main.f90

program circle_main

  use circle_mod, only: pi, area
  implicit none
  real(kind=8) :: a

  ! print parameter pi defined in module:
  print *, 'pi = ', pi

  ! test the area function from module:
  a = area(2.d0)
  print *, 'area for a circle of radius 2: ', a

end program circle_main

To compile, you first need to generate circle_mod.o and circle_mod.mod, followed by circle_main.o. Only then, you can link the two object files together to produce a binary (or an executable) file, e.g., circle_main.exe

$ gfortran -c circle_mod.f90     # produces circle_mod.o and circle_mod.mod
$ gfortran -c circle_main.f90    # produces circle_main.o
$ gfortran circle_mod.o circle_main.o -o circle_main.exe   # linking to generate circle_main.exe

If you reverse the order of the compilations between circle_mod.f90 and circle_main.f90 in the above it won’t compile and fail with an error message such as:

circle_main.f90:5.6:

use circle_mod, only: pi, area
       1
Fatal Error: Can't open module file 'circle_mod.mod' for reading at (1): No such file or directory

Executing the program by running ./circle_main.ext after a successful compilation gives the following output:

pi =    3.14159265358979
area for a circle of radius 2:    12.5663706143592

Note that a parameter defined with a specific value in a module (e.g., pi as defined in circle_mod.f90) is available to all program units using the module (e.g., pi is accessible from circle_main.f90 via use circle_mod, only: pi). See Module variables.

Note

You now may guess that compiling N codes via using N command lines will be very daunting, especially when N is large. In this case the compilation via using a Makefile becomes very handy (see Makefiles).

Module variables

It is also possible to declare variables that can be shared between all program units using the module. This is a way to define “global variables” that might be set in one program unit and used in another, without the need to pass the variable as a subroutine or function argument. Module variables can be defined in a module and the Fortran statement

save

is used to indicate that variables defined in the module should have values saved between one use of the module to another. You should generally specify this if you use any module variables.

Here is another version of the circles code that stores pi as a module variable rather than a parameter:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
! /codes/circle2/circle_mod2.f90
! Version where pi is a module variable.

module circle_mod2

  implicit none
  real(kind=8), save :: pi 

contains

  real(kind=8) function area(r)
    real(kind=8), intent(in) :: r
    area = pi * r**2
  end function area

  real(kind=8) function circumference(r)
    real(kind=8), intent(in) :: r
    circumference = 2.d0 * pi * r
  end function circumference

end module circle_mod2

In this case we also need to initialize the variable pi by means of a subroutine such as:

1
2
3
4
5
6
7
8
9
! /codes/circle2/circle_initialize2.f90

subroutine circle_initialize2()

  ! Set the value of pi used elsewhere.
  use circle_mod2, only: pi
  pi = acos(-1.d0)

end subroutine circle_initialize2

These might be used as follows in a main program:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
! /codes/circle2/circle_main2.f90

program circle_main2

  use circle_mod2, only: pi, area
  implicit none
  real(kind=8) :: a

  call circle_initialize2()   ! sets pi

  ! print module variable pi:
  print *, 'pi = ', pi

  ! test the area function from module:
  a = area(2.d0)
  print *, 'area for a circle of radius 2: ', a

end program circle_main2

This example can be compiled and executed by going into the directory $lecture_note/chapters/chapt02/codes/circles2/ and typing:

$ gfortran circle_mod2.f90 circle_initialize2.f90 circle_main2.f90 -o main.exe
$ ./main.exe

Or by using the Makefile in this directory:

$ make main.exe
$ ./main.exe

Here is the Makefile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# /codes/circle2/Makefile

OBJECTS = circle_mod2.o\
	circle_main2.o\
	circle_initialize2.o

MODULES = circle_mod2.mod

.PHONY: clean

output.txt: main.exe
	./main.exe > output.txt

main.exe: $(MODULES) $(OBJECTS)
	gfortran $(OBJECTS) -o main.exe

%.o: %.f90
	gfortran -c $<

%.mod: %.f90
	gfortran -c $<

clean:
	rm -f $(OBJECTS) $(MODULES) main.exe

In the next section we are going to learn more about Makefiles, see Makefiles.