Database namelists (varslice)
Most forcing in YelmoX is now loaded through the shared varslice reader. A database namelist is a small, static description of a dataset on disk: where the file lives, which variable to read, how to convert its units, and how its records map onto a time axis. The consuming modules — varslice itself, esm_forcing, snapesm, ismip6 — all read the same group layout, so once you understand one group you understand them all.
The point of these files is to keep the provenance of every forcing field visible and in one place. Nothing in the namelist runs code; each group is a declarative record that says “this NetCDF file, this variable, these units, this period” — everything the reader needs to ingest the dataset and hand back a time-indexed field.
See input/esm/esm_ant_ismip7.nml for a full, real-world example.
Anatomy of a group
A single dataset is described by one namelist group. All five keys are mandatory (the reader pre-sets defaults, but the convention is to always write them out so the provenance stays in the file):
&gcm_ts_ref
filename = "ice_data/{domain}/{grid_name}/RACMO2.3/{grid_name}_ERA5-3H_RACMO2.3p2_1979-2022_monthly.nc"
name = "t2m"
units = "K" "K"
scaling = 1.0 0.0
time = 1, 1979.0, 2022.0, 1.0, 12.0
/| Key | Type | Meaning |
|---|---|---|
filename |
string | Path to the NetCDF file (relative to the run dir). May contain placeholders and wildcards — see Paths. |
name |
string | Name of the variable to read inside the NetCDF file. |
units |
2 strings | "<units_in>" "<units_out>" — documentation labels only. |
scaling |
2 reals | <unit_scale> <unit_offset> — the actual linear unit conversion. |
time |
5 reals | <active> <x0> <x1> <dx> <sub> — describes the time axis. See The time array. |
The group name (&gcm_ts_ref, &gcm_to_proj, …) is chosen by the consuming module — it decides which physical role a group plays (reference vs. projection, atmosphere vs. ocean, etc.). The five keys inside are always the same.
units vs. scaling
The two units strings are labels for humans — they do not trigger any conversion. The real conversion is the linear transform in scaling, applied to every value as it is read:
value_out = value_in * unit_scale + unit_offset
units documents the intent so a reader can check that scaling actually performs it. For example, precipitation stored in kg m-2 s-1 and wanted in mm yr-1:
units = "kg m-2 s-1" "mm yr-1"
scaling = 31556926.25 0.0 ! CMIP standard seconds-per-yearor ocean temperature stored in °C and wanted in K:
units = "degrees C" "K"
scaling = 1.0 273.15Use scaling = 1.0 0.0 when no conversion is needed.
The time array
The time key is the only subtle one. It packs five numbers:
time = active, x0, x1, dx, sub
| Element | Name | Meaning |
|---|---|---|
active |
with_time | 1 = the field is time-varying (read record-by-record). 0 = the field is static (one slice); x0..x1 then merely document the period the data represents. |
x0 |
start | First time value on the axis (calendar year, in ESM convention). |
x1 |
end | Last time value on the axis. |
dx |
step | Spacing between successive major time units (usually 1.0 year). |
sub |
sub-count | Number of sub-annual records per major unit: 1 = annual, 12 = monthly. Any value > 1 switches on sub-annual handling. |
How the reader interprets these:
Static field (
active = 0).x0..x1are preserved as-is and describe the period the (single) slice represents. Typical for a fixed surface elevation or an ocean climatology:time = 0, 2000, 2000, 0, 1 ! one slice, "representing year 2000" time = 0, 1990, 2014, 0, 1 ! one slice, "a 1990–2014 climatology"Time-varying, annual (
active = 1,sub = 1). The axis is built asx0, x0+dx, …, x1:time = 1, 1850, 2014, 1, 1 ! 165 annual records, 1850…2014Time-varying, sub-annual (
active = 1,sub > 1). A sub-annual axis is built with spacing1/sub, centred within each major unit (e.g. mid-month forsub = 12), spanningx0throughx1:time = 1, 1979.0, 2022.0, 1.0, 12.0 ! monthly records, Jan 1979 … Dec 2022Static field, sub-annual (
active = 0,sub > 1).activeandsubare independent switches:activedecides whether the field advances along a multi-year calendar axis,subdecides whether there is a within-year (monthly) cycle. Combining them gives a monthly climatology — a fixed seasonal cycle, selected by month-of-year, that does not advance year to year.x0..x1document the period the climatology averages over;dx = 0:time = 0, 1961, 1990, 0, 12 ! 12-month climatology, averaged over 1961–1990Collapse to a single slice. For a time-varying field, setting
dx = 0collapsesx1tox0, i.e. read exactly one record atx0. (For a static field,dx = 0is normal andx0..x1are left untouched.)
The generated axis length must match the length of the NetCDF file’s time dimension, or the reader stops with an error — a useful check that x0, x1, dx, sub describe the file you actually pointed at.
Paths: placeholders and wildcards
filename is expanded before the file is opened.
Placeholders in {braces} are substituted by the caller:
{domain}and{grid_name}are built in — every module supplies them (e.g.Antarctica,ANT-16KM).Additional keys are passed by the consuming module.
esm_forcing, for instance, supplies{gcm}and{experiment}, so an ISMIP7 projection path can read:filename = "ice_data/ISMIP7/{domain}/{grid_name}/{gcm}/{experiment}/ocean/thetao/v3/{grid_name}_{gcm}_{experiment}_v3_2015-2299_thetao.nc"and the same namelist serves every GCM/experiment combination — you select the concrete values in the driver’s
[esm]configuration, not here.
Wildcards (shell globs, * and ?) are also allowed. The reader expands the pattern with ls -1 … | sort, so a dataset split across many files is matched and concatenated in alphabetical order:
filename = "ice_data/{domain}/{grid_name}/{gcm}/historical/tas/*.nc"Sort the split so alphabetical order equals chronological order (zero-pad years).
Worked examples
Monthly, time-varying reference climate (RACMO2.3 on the ice grid):
&gcm_ts_ref
filename = "ice_data/{domain}/{grid_name}/RACMO2.3/{grid_name}_ERA5-3H_RACMO2.3p2_1979-2022_monthly.nc"
name = "t2m"
units = "K" "K"
scaling = 1.0 0.0
time = 1, 1979.0, 2022.0, 1.0, 12.0
/Annual ESM projection ocean temperature, °C → K, GCM/experiment templated:
&gcm_to_proj
filename = "ice_data/ISMIP7/{domain}/{grid_name}/{gcm}/{experiment}/ocean/thetao/v3/{grid_name}_{gcm}_{experiment}_v3_2015-2299_thetao.nc"
name = "thetao"
units = "degrees C" "K"
scaling = 1.0 273.15
time = 1, 2015, 2299, 1, 1
/Static surface elevation (single slice, no unit change):
&gcm_zs_ref
filename = "ice_data/{domain}/{grid_name}/RACMO2.3/{grid_name}_ERA5-3H_RACMO2.3p2_1979-2022_monthly.nc"
name = "z_srf"
units = "m" "m"
scaling = 1.0 0.0
time = 0, 2000, 2000, 0, 1
/Static ocean climatology (single slice representing a 1990–2014 average):
&gcm_to_ref
filename = "ice_data/ISMIP7/{domain}/{grid_name}/meltMIP/{grid_name}_OI_Climatology_thetao_extrap.nc"
name = "thetao"
units = "degrees C" "K"
scaling = 1.0 273.15
time = 0, 1990, 2014, 0, 1
/How the groups are consumed
A module loads a group into a varslice object once at initialization (varslice_init_nml(vs, filename, group, domain, grid_name, subs=…)) and then asks for a field at a given time during the run (varslice_update(vs, time, method=…)). The database namelist supplies everything the object needs; the method (e.g. exact, interp, extrap) is chosen by the caller at read time, not in the namelist.
esm_forcinggroups the atmosphere/ocean database groups into reference, variability, ESM-reference, historical, and projection periods (&gcm_ts_ref,&gcm_to_proj, …) and supplies{gcm}/{experiment}. See ESM forcing.snapesmuses the same reader for its snapshot climate database.ismip6uses it for the ISMIP6 atmosphere/ocean forcing files.
Because they share the reader, the layout documented here is identical across all of them — a group is a group regardless of which module owns it.
Quick reference
- All five keys are mandatory; always write them for provenance.
units= two documentation labels;scaling=[scale, offset]does the realout = in*scale + offsetconversion.time = [active, x0, x1, dx, sub]:active1/0 = time-varying/static ·sub1/12 = annual/monthly ·dx = 0collapses a time-varying field to a single slice atx0.- Paths expand
{domain}/{grid_name}plus module-supplied keys like{gcm}/{experiment}, and accept*/?globs (sorted alphabetically). - The generated time axis length must match the file’s time dimension.