Modules
Modules are subordinate program units that can contain multiple subprograms as well as associated variables.
Modules allow you to organize your code into logically-connected units. It is a form of object oriented programming.
They should contain coherent data+procedures.
Modules permit data hiding. Variables and subprograms may be kept private from other program units. This prevents another source of error, by reducing the number of variables an outside program can affect or procedures it can call.
Fortran Modules
Each module has a name that must be unique. A module begins with
MODULE modname
and ends with
END MODULE [NAME]
Modules are typically placed into separate files. The file name does not need to be the same as the module name, but the module will be referenced by its name and not by the file name. It is acceptable for short, closely-related modules to be in the same file. If more than one module is in a file, each must be USEd individually.
Using Modules
Modules are brought in via the USE statement
USE mymodule
All USE statements must be the first executable statements after the declaration of the program unit (program, function, subroutine), before any IMPLICIT statement and the variable declarations.
There is no distinct “namespace” for a Fortran module. Names imported into the USEing unit do not acquire a distinguishing name.
Variations of USE
Only specified routines can be brought in with ONLY:
USE mymod, ONLY : f1, f2, s4
Routines can be renamed:
USE mymod, name-here => name-in-module
USE stats_lib,sprod=>prod
Module Variables.
IMPLICIT NONE at the top applies throughout the module. All variables declared or types defined before a CONTAINS statement are global throughout the module.
Module symbols (variables and names of procedures) can be private . You may also explicitly declare them public but that is the default. The private and public attributes may be added to the declaration, or they may be specified separately with a list following. Private variables are not directly accessible by program units that use the module. Only procedures in the same module can access them. Using PRIVATE or PUBLIC as a separate statement without a list sets or resets the default and may be done only once per module. Public and private may only be set in the specification (interface) portion of the module, not in the procedure bodies.
We will discuss PUBLIC and PRIVATE in more detail when we cover classes.
Example
MODULE mymod
USE precisions
REAL, PRIVATE :: x, y, z
REAL(sp) :: r_fun
REAL(dp) :: d_fun
PRIVATE ::r_fun,d_fun
where we assume the precisions
module defines the KIND parameters sp
and dp
.
Subprograms in Modules
Subprograms defined in a module must follow a CONTAINS. The FUNCTION or SUBROUTINE keywords after END are not optional, e.g. END SUBROUTINE is required. The name of the procedure is still optional and some authors recommend not using it, in case it is changed later or to avoid cut and paste errors.
All subprograms in a module have an implicit interface. You should not write an explicit interface for them, and in fact it’s illegal to do so.
Example
module mymod
implicit none
integer ::Nmax=100000
contains
subroutine mysub(a,x)
real, dimension(:), intent(in) :: a
real, intent(out):: x
real, dimension(Nmax) :: b
b=x
end subroutine
function myfunc(x,y)
real :: myfunc
real,intent(in) :: x,y
myfunc=x**2+y
end function
end module
Modules and Make
A module must be compiled before any other file that uses it. This can create a complicated build environment, so make
or a similar build manager is usually used.
Exercises
- Type the module
mymod
into a filemymod.f90
. Fortran allows the module and the file to have either the same or a different name, but the name of the module is the name that must appear in the use statement. - Fill out the subroutine
mysub
to set b to 11., then set x to the sum of corresponding elements of a and b. Hint: you can use x=a(:)+b(:size(a)) to avoid a loop. - Write a main program
main.f90
that usesmymod
, initializesA
allocatable, allocates it to 1000, sets its values toi+3
in a loop, then passes it tomysub
. Print the value ofx
that is returned. - Create a Makefile. If you wish you may copy the example Makefile from the earlier chapter. Make the appropriate changes to the program name, the names of the source files, and the names of the object files. Make the dependency line at the end
main.o:main.o mymod.o
Run a make project in Geany or your preferred IDE.