Chapter 8 — Key Takeaways (Modules)
A one-page reference. Modules are the container that makes large Fortran possible; keep this beside you until the syntax is automatic.
The anatomy of a module
module name
use kinds, only: dp ! import what this module itself needs
implicit none ! once, governs the whole module
private ! hide everything by default
public :: api1, api2 ! expose only the interface
real(dp) :: state ! module variable (implicitly SAVE) — keep private
contains
subroutine api1(...) ! module procedure: explicit interface for free
...
end subroutine api1
end module name
Core syntax
| Construct | What it does |
|---|---|
module m … end module m |
Define a container of shared entities |
use m |
Import all public entities of m |
use m, only: a, b |
Import only a and b (preferred — documents the dependency) |
use m, only: x => a |
Import a, renamed to x (resolve a clash) |
private (bare) |
Default-hide every entity |
public :: a, b |
Expose the named entities |
submodule (m) child |
Hold the bodies of m's separate module procedures |
module function f(...) … |
A separate module procedure (interface in module, body in submodule) |
module procedure f … end procedure f |
Shorthand submodule body (inherits the interface) |
Which construct, when
| You want to… | Use |
|---|---|
| Share a constant/type/procedure across files | a module |
| A helper used in just one program | an internal procedure (contains in the program, Ch. 6) |
| Hide implementation, expose an API | private default + public :: … |
| Shared mutable state, safely | a private module variable + public accessor procedures |
| Cut rebuild time on a big, volatile module | split interface (module) / body (submodule) |
| Break a genuine circular dependency | move the shared need down a layer, or use a submodule |
Compile order (the rule newcomers trip on)
- A module must be compiled before any file that
uses it — its.modmust already exist. - One
gfortrancommand compiles files left to right, so order the sources: dependencies first. - Compile order = a topological sort of the dependency graph: leaves first,
programlast.
$ gfortran -std=f2018 -Wall kinds.f90 heat_solver.f90 heat_io.f90 heat.f90 -o heat
.mod and .smod files
| File | Holds | Note |
|---|---|---|
foo.o |
the machine code | must be linked |
foo.mod |
the module's public interface | read by users at compile time |
foo.smod |
the submodule interface | emitted when a module has separate module procedures |
Pitfalls
Cannot open module file 'x.mod'→xwas not compiled first (or needs-I<dir>). Compile order, not broken code.- Circular dependency (
ausesb,busesa) → will not compile. Refactor the shared need down. - Module variables are implicitly
save→ they persist for the whole run and initialize once. privateby exception (private :: helper) → a helper you forget to list leaks into the API. Prefer bareprivate+public ::.- Calling a private module entity from outside → "not found in module." It is invisible on purpose.
Explicit interface — the payoff you get for free
Putting a procedure in a module gives every caller its explicit interface, which:
- lets the compiler check argument count, type, rank, and intent at the call site;
- is required for keyword args, optional args, and assumed-shape arrays (all from Ch. 6);
- lets the optimizer inline and vectorize across the call (Ch. 27).
Why modules replaced COMMON/INCLUDE
COMMON / INCLUDE (legacy, Ch. 17) |
Module (modern) |
|---|---|
| Untyped memory overlay; no cross-routine checking | One typed, checked, authoritative definition |
| Can share data only | Shares data, types, and procedures |
INCLUDE = textual paste kept in sync by hand |
use imports named, typed entities |
| Mismatch → silently wrong numbers | Mismatch → compile error |
Flags introduced
-c compile to a .o without linking · -I<dir> add a directory to the .mod search path.
Project piece added this chapter
The heat solver is split into a module hierarchy: kinds (dp) at the bottom, heat_solver (step)
and heat_io (read_config, write_field) as peers above it, and program heat on top. Compile order:
kinds → heat_solver, heat_io → heat. The physics now lives behind a stable public step, ready
for the real stencil in Ch. 24 and the parallel back-ends of Part VIII.