Introduction¶
About GOTM¶
GOTM — the General Ocean Turbulence Model — is a one-dimensional water column model for the most important hydrodynamic and thermodynamic processes related to vertical mixing in natural waters. It has been designed so that it can easily be coupled to 3-D circulation models, and used as a module for the computation of vertical turbulent mixing.
The core of the model computes solutions for the one-dimensional versions of the transport equations of momentum, salt, and heat. The key component is the model for the turbulent fluxes of these quantities. GOTM’s strength is the vast number of well-tested turbulence models it implements — spanning simple prescribed diffusivities through complex Reynolds-stress models with several differential transport equations (empirical models, energy models, two-equation models, Algebraic Stress Models, K-profile parameterisations, and more).
GOTM has grown considerably since its first public release. Sediment transport, seagrass dynamics, atmosphere–ocean interaction modules, and biogeochemical models have all been added by the community. In that sense GOTM is an integrated, community-based software environment for an almost unlimited range of applications in geophysical turbulence modelling.
Original GOTM authors: Lars Umlauf, Hans Burchard, and Karsten Bolding. Full documentation and the original Fortran source are available at gotm.net.
About pyGOTM¶
pyGOTM is a faithful Python + Numba reimplementation of GOTM 6.0.7, targeting Fortran-comparable single-column wall-clock performance on standard CPU hardware with no Fortran compiler or compiled binary required.
Key differences from the Fortran GOTM:
Feature |
Fortran GOTM 6.0.7 |
pyGOTM |
|---|---|---|
Language |
Fortran 90/95 |
Python 3.12 + Numba |
Timestep loop |
Compiled Fortran |
Compiled Numba JIT ( |
Configuration |
YAML (gotm.yaml) |
GOTM-compatible YAML (same files) |
Output |
NetCDF |
NetCDF (CF conventions, xarray-compatible) |
Deployment |
Compile from source |
Conda environment plus editable local install |
Scientific parity: pyGOTM must pass every official GOTM test case using a
discrete Fréchet distance comparison against Fortran GOTM 6.0.7 reference
NetCDF output. After time-aligning both datasets, each variable is scored by
the normalized discrete Fréchet distance \(d_\mathrm{norm}\) — the
worst-case leash length between the two value trajectories after dynamic
linear-or-log normalization to \([0, 1]\). For variables whose signal
magnitude is below a per-variable floor, the relative raw Fréchet score
\(d_\mathrm{rel} = d_\mathrm{raw} / \text{signal\_scale}\) is used instead
(metric_mode = "d_rel").
Status |
Score range |
Meaning |
|---|---|---|
PASS |
\(score < 0.01\) |
Variable is within the Fréchet parity threshold. |
MARGINAL |
\(0.01 \leq score < 0.05\) |
Variable is close to parity but outside the pass threshold. |
DISCREPANT |
\(0.05 \leq score < 0.20\) |
Variable has a deterministic implementation difference. |
BROKEN |
\(score \geq 0.20\) or structural failure |
Variable is severely mismatched, missing, extra, or structurally incompatible. |
A case has status PASS only when every compared variable passes. Fréchet
thresholds, normalization settings, and per-variable magnitude floors are
configured in src/pygotm/validation/tolerances.py; see
Validation Overview for the full pipeline and scoring details.
The latest generated full-suite snapshot is PARTIAL PARITY: 15 of 22
official reference cases pass, and the seven remaining failures are documented
in Test Cases.
Execution Model¶
pyGOTM uses a compiled single-column execution model. The Python/Numba boundary is crossed exactly once per full simulation run:
flowchart TD
config["Load YAML config\n(Pydantic validation)"]
alloc["Allocate runtime containers\nRuntimeState · RuntimeWork · RuntimeOutput · RuntimeForcing"]
preproc["Preprocess forcing arrays"]
compiled["time_loop_*_compiled() @numba.njit\nall physics · turbulence closure · output buffering"]
xarray["Convert output buffers to xarray.Dataset"]
netcdf["Write NetCDF\n(CF conventions)"]
config --> alloc
alloc --> preproc
preproc -. "Python / Numba boundary — crossed ONCE per run" .-> compiled
compiled -. "return to Python" .-> xarray
xarray --> netcdf
style compiled fill:#fef3cd,stroke:#c8960c,color:#7a5c00
style config fill:#dce8f7,stroke:#3a78b5,color:#1a4a7a
style alloc fill:#dce8f7,stroke:#3a78b5,color:#1a4a7a
style preproc fill:#dce8f7,stroke:#3a78b5,color:#1a4a7a
style xarray fill:#dce8f7,stroke:#3a78b5,color:#1a4a7a
style netcdf fill:#dce8f7,stroke:#3a78b5,color:#1a4a7a
This eliminates per-timestep Python overhead and targets within 1.5–2× of Fortran wall-clock time on a warm (cached JIT) run.
Design Principles¶
Scientific accuracy is non-negotiable. Every kernel is validated against Fortran GOTM. No accuracy tradeoffs before parity is established.
Reproducibility is a feature. Every simulation result is fully reproducible from its YAML config. No hidden state.
The kernel is the product. The physics and validation runtime live in
src/pygotm/.Double precision everywhere.
np.float64throughout — GOTM usesREAL(8).The compiled runtime is single-column. Each vertical column (\(N_\mathrm{lev} \approx 100\)) is solved serially through the parity-tested Numba timestep loop.
Fail loudly on science errors. NaN or physical-bounds violations raise immediately with a diagnostic message.
Unsupported configurations fail at setup. No silent fallback to a Python timestep loop. If a compiled loop is not yet implemented for a given configuration,
UnsupportedConfigurationErroris raised during setup.
Acknowledgements¶
pyGOTM is built on the scientific foundation of GOTM. We are deeply grateful to Lars Umlauf, Hans Burchard, and Karsten Bolding for creating, maintaining, and freely distributing GOTM. We also acknowledge the broader GOTM community, the CARTUM project (Comparative Analysis and Rationalisation of Second-Moment Turbulence Models, MAS3-CT98-0172), and all contributors whose work is cited in the GOTM manual.
The original GOTM Fortran source is used here as the authoritative scientific reference. All physics equations, constants, and algorithms in pyGOTM are derived from or verified against that source.