GCM adapters#
In Fortran TRACMASS each GCM has a project folder (projects/NEMO,
projects/ROMS, …) with code that sets up the grid (setup_grid.F90),
reads the fields (read_field.F90) and defines kill zones
(kill_zones.F90). You choose one in Makefile.prj and compile.
In TRACMASS-JAX a GCM is supported by an adapter, a Python module in
tracmass.gcm with a fluxes function. You choose an adapter at run time,
by name ([env.gcm] name = "glorys", new_flux("glorys", ...)) or by
passing the function itself.
Available adapters#
Adapter |
Model / data |
Grid |
Timestep |
Vertical motion |
Data |
|---|---|---|---|---|---|
|
Synthetic double gyre with noise |
100 × 80 × 30, 250 m cells, zonally periodic |
1 h |
yes (random |
none, generated |
|
Fabboni (2009) analytical decaying inertial oscillation, as in the Fortran Theoretical project |
300 × 300 × 1, 250 m cells |
1 h |
no |
none, generated |
|
Copernicus Marine GLORYS12 reanalysis (NEMO) |
4318 × 3059 × 50 (1/12°, ORCA tripolar), halo removed |
1 day |
yes |
local daily Zarr stores |
|
ECCO2 cube92 state estimate (MITgcm) |
0.25° regular lat/lon, global, re-centred on 0° |
1 day |
yes |
OPeNDAP (APDRC), cached as Zarr |
|
Scripps Gulf of Guinea regional MITgcm, top 200 m |
1/64°, 11° W–10.5° E, 2–7° N, 25 levels |
1 day |
no (no |
HTTPS, cached as NetCDF |
theoretical#
A double-gyre flux field with small random perturbations, slowly evolving
from 2007-06-01 by day-by-day random increments, plus random vertical
fluxes. The first and last rows are land, and the domain is periodic in x.
It needs no data, so it is the standard case for tests and for the
Quick start.
gcm.theoretical.initial_state(n_particles) draws random interior starting
positions.
fabboni#
The spatially uniform test case of the Fortran distribution (Fabbroni,
2009): \(u\) starts at 0.5 m s⁻¹ and decays with an inertial oscillation at
45° N. It has an analytical solution, and gcm.fabboni.initial_state()
reproduces the Fortran seeding, so it is used to validate the schemes
against the Fortran code (tests/test_fortran_comparison.py).
glorys#
GLORYS12 daily means, read from per-day, per-variable Zarr stores under
/data/{disk}/mercator/{product} (tracmass.seagrid.glorys). Notes:
The NEMO halo columns are removed. Velocity stores and mesh files carry different halos and are trimmed differently, so that
uflux[i]is the east face of T-celli.tests/test_glorys_alignment.pychecks this.Volume fluxes are
uvel · dzt · dyu,vvel · dzt · dxvandwvel · dxdy.Land fill values are masked (velocities become 0) after the subset is cut out, which is about 7 times faster than masking whole chunks.
[env.gcm] subsetlimits the region and the levels. An x-subset turns off zonal periodicity.lonlat_grid,lonlat_to_xyandxy_to_lonlatconvert between model positions and geographic coordinates.seagrid.glorys.rechunk_wvel(dtm1, dtm2)rewriteswvelstores downloaded before 2026-10-08 with 10-level chunks, which makes reading a few levels much faster. Don’t rechunk days that a running job is about to read.
ecco2#
ECCO2 cube92 daily fields from the APDRC OPeNDAP server, one remote
dataset per variable for the whole 1992–2025 record. Each requested day is
cached locally as a Zarr store. The grid is regular lat/lon, so cell areas
are computed analytically. kmt and dzt are derived from the cells where
the velocity is exactly zero, because the source mislabels its fill value.
Junk values in wvel (|w| > 10¹⁰) are set to zero, and longitudes are
rolled to −180…180. fluxes(dtm, include_wflux=None) reads w only when
move_vertically is true.
scrippsgog#
The daily Scripps Gulf of Guinea MITgcm run, downloaded from
https://sose.ucsd.edu/GoG/DATA/PRELIM/daily/ on first use and cached
unchanged under /data/raid/scrippsgog/PRELIM/daily/YYYY/:
from tracmass.seagrid import scrippsgog
scrippsgog.available_dates() # dates on the server
scrippsgog.retrieve("2024-01-02") # download one day (no-op if cached)
grid, lazy = tracmass.new_flux("scrippsgog", dtm_start="2024-01-02",
dtm_end="2024-01-31")
MITgcm puts UVEL on the west face and VVEL on the south face
of each T-cell. The adapter shifts both by one face onto TRACMASS’s east
and north faces, and uses the files’ own face metrics and open fractions
(dyG, dxG, drF, hFacW, hFacS). kmt and dzt come from
MITgcm’s partial-cell rule (hFacMin = 0.2) applied to the bathymetry. The
western and southern open boundaries are closed in the tracking, and there
is no vertical velocity, so tracking is horizontal only.
What an adapter returns#
An adapter function has the signature
def fluxes(dtm: pd.Timestamp | str | None = None) -> xr.Dataset: ...
It returns one snapshot, the fields at time dtm (with dtm=None
meaning the adapter’s own default date), as an xarray.Dataset with:
Variable |
Dims |
Description |
|---|---|---|
|
|
Zonal volume flux through east faces, m³ s⁻¹ |
|
|
Meridional volume flux through north faces, m³ s⁻¹ |
|
|
Vertical volume flux through the top face of each level, positive upward, m³ s⁻¹ (optional; leave out for 2-D runs) |
|
|
Layer thickness, m |
|
|
Free-surface stretching factor (1 for fixed levels) |
|
|
Number of ocean levels; 0 on land |
|
|
Horizontal cell area, m² |
|
scalar |
Grid size |
|
scalar |
1 if periodic in x / north fold, else 0 |
|
scalar |
Output interval of the model |
|
scalar |
Time of this snapshot |
|
scalar |
Always |
A trailing size-1 t dimension is removed automatically. The fields can,
and for real models should, be lazy Dask arrays: new_flux and
update_flux never read them, and LazyFluxFields.compute() reads them
one window at a time. Adapters that support subsets set the dataset
attributes _i_offset and _j_offset (the subset start), and may set
_zarr_chunk_x and _zarr_chunk_y so the patched integrator can line its
patches up with the storage chunks.
Optional functions add features:
Function |
Used by |
|---|---|
|
|
|
geographic seeding; |
|
|
The tutorial Adding a GCM writes an adapter from scratch.
The seagrid layer#
Data access is kept apart from flux computation. tracmass.seagrid.<model>
modules download, cache and open the raw model output (open_dataset,
grid_definition, retrieve), and know nothing about TRACMASS.
tracmass.gcm.<model> turns that into fluxes. The seagrid modules also
give every model a land mask and a distance-to-land field (see
Land and coast).