Modules and submodules
Although in examples I write the main program, modules and submodules, modules and submodules should be stored in a separate file.
A module contains declarations and procedures which can be used in another program unit. In a module, all variables declared implicitly have SAVE attribute, and all procedure declared have an explicit interface, which means if we use a module procedure, we never need to add an explicit block.
program main
use :: mod1
implicit none
print *, i, a, b
call print_a_and_array(b)
end program main
module mod1
implicit none
integer :: i
integer, save :: a = 0, b(9) = [(i, i = 1, 9)]
contains
impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end module mod1
A submodule CANNOT be used, and it only makes a module “bigger”. The procedure defined in a submodule must have module
in front of subroutine
or function
in the start statement of the procedure, and its interface must be declared in its ancestor. Add (`ancestor-module`)
behind submodule
in the start statement to specify which ancestor module does the submodule extend.
program main
use :: mod1
implicit none
print *, i, a, b
call print_a_and_array(b)
end program main
module mod1
implicit none
integer :: i
integer, save :: a = 0, b(9) = [(i, i = 1, 9)]
interface
module impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
end subroutine print_a_and_array
end interface
contains
end module mod1
submodule (mod1) mod1_submod1
implicit none
contains
module impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end submodule mod1_submod1
Add (`ancestor-module`:`parent`-submodule)
behind submodule
in the start statement to specify which ancestor module and parent submodule does the submodule extend.
program main
use :: mod1
implicit none
print *, i, a, b
call print_a_and_array(b)
end program main
module mod1
implicit none
integer :: i
integer, save :: a = 0, b(9) = [(i, i = 1, 9)]
interface
module impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
end subroutine print_a_and_array
end interface
contains
end module mod1
submodule (mod1) mod1_submod1
implicit none
contains
end submodule mod1_submod1
submodule (mod1:mod1_submod1) mod1_submod1_subsubmod1
implicit none
contains
end submodule mod1_submod1_subsubmod1
submodule (mod1:mod1_submod1_subsubmod1) mod1_submod1_subsubmod1_subsubsubmod1
implicit none
contains
module impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end submodule mod1_submod1_subsubmod1_subsubsubmod1
Statements related to modules and submodules
USE statement
USE statement makes a module used in another program unit.
program main
use :: mod1
implicit none
print *, i, a, b
call print_a_and_array(b)
a = -1
print *, i, a, b
call print_a_and_array(b)
end program main
module mod1
implicit none
integer :: i
integer, save :: a = 0, b(9) = [(i, i = 1, 9)]
contains
impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end module mod1
To use an intrinsic module like iso_fortran_env
, you should add , intrinsic
behind use
.
A “bare” USE statement use :: `module`
is like from `module` import *
statement in Python, and everything public defined in `module`
is used. A USE statement use :: `module`, only: ......
is like from `module` import ......
statement in Python, and ......
defined in `module`
is used.
program main
use :: mod1, only: a, b, print_a_and_array
implicit none
print *, a, b
call print_a_and_array(b)
a = -1
print *, a, b
call print_a_and_array(b)
end program main
module mod1
implicit none
integer :: i
integer, save :: a = 0, b(9) = [(i, i = 1, 9)]
contains
impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end module mod1
The variable defined in a submodule CAN’T be used, and the following program is invalid.
program main
use :: mod1
implicit none
print *, a, b
call print_a_and_array(b)
a = -1
print *, a, b
call print_a_and_array(b)
end program main
module mod1
implicit none
integer :: i
integer, save :: a = 0
contains
impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end module mod1
submodule (mod1) mod1_submod1
implicit none
integer :: b(9) = [(i, i = 1, 9)]
contains
end submodule mod1_submod1
IMPORT statement
In a submodule, what defined in its parent can all be referenced in default. You can use IMPORT statement import, only: ......
to make the submodule be only able to reference ......
in its parent. This feature is new, and your compiler may not allow it.
program main
use :: mod1
implicit none
print *, a, b
call print_a_and_array(b)
a = -1
print *, a, b
call print_a_and_array(b)
end program main
module mod1
implicit none
integer :: i
integer, save :: a = 0, b(9) = [(i, i = 1, 9)]
interface
module impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
end subroutine print_a_and_array
end interface
contains
end module mod1
submodule (mod1) mod1_submod1
import, only: a, print_a_and_array
implicit none
contains
module impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end submodule mod1_submod1
PRIVATE statement
PRIVATE statement should be added at the top of the specification part of a module, and it makes everything defined in the module inaccessible to the program unit which is not a descendant submodule of the module and uses the module.
program main
use :: mod1
implicit none
end program main
module mod1
implicit none
private
integer :: i
integer, save :: a = 0, b(9) = [(i, i = 1, 9)]
contains
impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end module mod1
PUBLIC statement
PUBLIC statement overwrite the inaccessibility of something defined in a module, and again make it accessible to the program unit which uses the module.
program main
use :: mod1
implicit none
call print_a_and_array([0])
end program main
module mod1
implicit none
private
integer :: i
integer, save :: a = 0, b(9) = [(i, i = 1, 9)]
public :: print_a_and_array
contains
impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end module mod1
Attributes related to modules and submodules
PUBLIC attribute
The specifications of PUBLIC attribute overwrite the inaccessibility of something defined in a module, and again make it accessible to the program unit which uses the module.
program main
use :: mod1
implicit none
print *, a, b
call print_a_and_array(b)
a = -1
print *, a, b
call print_a_and_array(b)
end program main
module mod1
implicit none
private
integer :: i
integer, save, public :: a = 0, b(9) = [(i, i = 1, 9)]
public :: print_a_and_array
contains
impure elemental subroutine print_a_and_array(array)
integer, intent(in) :: array
print *, a, array
end subroutine print_a_and_array
end module mod1
PROTECTED attribute
The specifications of PROTECTED attribute makes the value of a variable can only be changed by a procedure defined in the module or its descendant submodules, and also it cannot be an effective argument to be associated with a dummy argument.
program main
use :: mod1
implicit none
print *, a
call change_a(1)
print *, a
end program main
module mod1
implicit none
private
integer, save, public, protected :: a = 0
public :: change_a
contains
subroutine change_a(val)
integer, intent(in) :: val
a = val
end subroutine change_a
end module mod1
The following two programs are INVALID.
program main
use :: mod1
implicit none
print *, a
a = 1 ! Invalid!
print *, a
end program main
module mod1
implicit none
private
integer, save, public, protected :: a = 0
public :: change_a
contains
subroutine change_a(val)
integer, intent(in) :: val
a = val
end subroutine change_a
end module mod1
program main
use :: mod1
implicit none
print *, a
call change(a, 1) ! Invalid!
print *, a
end program main
module mod1
implicit none
private
integer, save, public, protected :: a = 0
public :: change
contains
subroutine change(var, val)
integer, intent(out) :: var
integer, intent(in) :: val
var = val
end subroutine change
end module mod1