Modules in Fortran
A MODULE is Fortran's mechanism for packaging related data, type definitions, and procedures into a single reusable, compile-time-checked unit, replacing the older and riskier practice of COMMON blocks and external subroutines from FORTRAN 77. Any program or procedure that needs a module's contents brings them into scope with the USE statement, and because the compiler generates a .mod file describing the module's interface, calls to module procedures are automatically checked for matching argument types, ranks, and count.
Cricket analogy: A national cricket board's central rulebook, referenced by every domestic league instead of each league inventing its own LBW interpretation, is like a Fortran MODULE — one authoritative, checked definition that every USEr consumes consistently instead of duplicating error-prone copies.
Defining a Module and Its Public Interface
A module is written as MODULE name ... [type/data/interface declarations] ... CONTAINS ... [procedure definitions] ... END MODULE name, and by default everything declared in it is PUBLIC (accessible to any program that USEs the module), though PRIVATE can be set as the module's default with individual items marked PUBLIC to expose only a deliberate, minimal interface — a common and recommended pattern for encapsulating implementation details.
Cricket analogy: A franchise's dressing room is PRIVATE by default — outsiders can't walk in — but the team sheet and starting eleven are explicitly made PUBLIC each match day, just as a module marks most internals PRIVATE while exposing only a deliberate PUBLIC interface.
MODULE physics_constants
IMPLICIT NONE
PRIVATE
PUBLIC :: gravity, kinetic_energy
REAL, PARAMETER :: gravity = 9.81
CONTAINS
REAL FUNCTION kinetic_energy(mass, velocity) RESULT(ke)
REAL, INTENT(IN) :: mass, velocity
ke = 0.5 * mass * velocity**2
END FUNCTION kinetic_energy
END MODULE physics_constants
PROGRAM drop_test
USE physics_constants, ONLY: gravity, kinetic_energy
IMPLICIT NONE
REAL :: fall_time, velocity, energy
REAL, PARAMETER :: mass = 2.0
fall_time = 3.0
velocity = gravity * fall_time
energy = kinetic_energy(mass, velocity)
PRINT *, 'Velocity at impact: ', velocity
PRINT *, 'Kinetic energy: ', energy
END PROGRAM drop_testUSE, ONLY, and Renaming
USE module_name brings every PUBLIC entity from a module into scope, but USE module_name, ONLY: name1, name2 restricts the import to just the named items, which reduces namespace pollution and makes dependencies explicit and easier to audit in large codebases. The => operator allows renaming an imported entity to avoid a naming clash, e.g., USE constants, ONLY: pi_local => pi, which is useful when two modules happen to export identically named items.
Cricket analogy: USE the tournament rulebook, ONLY: overs_limit brings in just the one rule a scorer needs instead of the entire regulations document, the same selective import a Fortran USE...ONLY statement performs to avoid pulling in irrelevant clauses.
USE module_name, ONLY: local_name => original_name both restricts the import and renames it in one statement — handy when two modules you need both export a variable called, say, tolerance, and you need to distinguish them in the same scope.
Module Data, State, and Compilation Order
Variables declared in a module's specification section (outside CONTAINS) become module data with a lifetime that persists for the entire program run, effectively acting as safer, type-checked global state shared by every procedure that USEs the module — a deliberate improvement over FORTRAN 77's COMMON blocks, which required matching memory layouts by position and were a notorious source of bugs. Because a module must be compiled before any unit that USEs it (the compiler needs its .mod file to check the interface), build systems for large Fortran projects must respect dependency order, and circular USE dependencies between two modules are not allowed.
Cricket analogy: A shared team database of player fitness scores, updated by the physio and read by the selectors, acts like module data — one authoritative, type-safe shared record, replacing the old days of separate paper injury lists that had to be manually cross-checked and often disagreed.
Fortran does not allow circular module dependencies — if module A USEs module B, module B cannot also USE module A. Large projects must structure modules in a strict dependency hierarchy (often called a 'module tree'), or the build will fail with an unresolved .mod file error.
- MODULE ... END MODULE packages types, data, and procedures into a reusable, compile-time-checked unit, replacing legacy COMMON blocks.
- Module contents are PUBLIC by default; use PRIVATE as the module default and mark selected items PUBLIC to expose a minimal interface.
- USE module_name imports everything PUBLIC; USE module_name, ONLY: name restricts the import to named items.
- The => operator renames an imported entity, useful for resolving naming clashes between modules.
- Data declared in a module's specification section acts as type-safe shared state accessible to every USEr.
- A module must be compiled before any unit that USEs it, since the compiler needs its generated .mod interface file.
- Circular USE dependencies between two modules are not permitted; large projects must maintain a strict module dependency hierarchy.
Practice what you learned
1. What is the default accessibility of items declared inside a Fortran MODULE?
2. What does USE module_name, ONLY: name1, name2 accomplish that a plain USE module_name does not?
3. Why can't module A USE module B while module B also USEs module A?
4. What replaced legacy COMMON blocks as the recommended way to share global-like state across program units in modern Fortran?
5. What does the => operator do in a USE statement like USE constants, ONLY: pi_local => pi?
Was this page helpful?
You May Also Like
Subroutines and Functions
Structuring reusable Fortran code with SUBROUTINEs, FUNCTIONs, INTENT, and pass-by-reference arguments.
Arrays in Fortran
Declaring, indexing, sectioning, and efficiently looping over Fortran's column-major arrays.
Conditionals in Fortran
How Fortran branches execution with block IF-THEN-ELSE, SELECT CASE, and logical operators.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics