Running goSPL#

Once the input file is ready, a goSPL simulation can be launched either from the command line or from a Python script — both run the same forward model.

Command line#

Installing goSPL provides a gospl console command:

# serial
gospl -i input.yml

# parallel (recommended) — choose any number of processes
mpirun -np 8 gospl -i input.yml -v

Options:

  • -i / --input (required) — the YAML input file.

  • -v / --verbose — print per-step model progress (phase-grouped). The first line reports the goSPL version.

  • --log — write the PETSc solver log summary.

  • --profile — record a per-phase wall-clock profile (profile.json).

  • --version — print the goSPL version and exit.

--i / --v are accepted as aliases of --input / --verbose. The equivalent python -m gospl -i input.yml -v is available without a console-script install. Note that fast mode is not a flag — set domain: fast: true in the input file.

Python script#

The command above is a thin wrapper around the Model class, so a run can equally be driven from Python (handy for parameter sweeps, notebooks or coupling):

from gospl.model import Model as sim

# Read the input file  (filename, verbose, showlog)
model = sim(args.input, args.verbose, args.log)

# Run the forward model
model.runProcesses()

# Clean up the PETSc objects
model.destroy()

Launch it under MPI the same way as any mpi4py program:

mpirun -np 8 python run_model.py -i input.yml

The number of processes used to run the model is independent of the number used later for post-processing.

Post-processing & utility commands#

Installing goSPL also provides several command-line tools (each is equally python -m gospl.<module> if you haven’t reinstalled to register the console scripts). They read the model output in the h5 directory; the output fields page describes what each variable means.

Stratigraphic volume for ParaView — gospl-strata-volume#

Stacks the recorded layers into a 3-D wedge (triangular-prism) volume and writes an XDMF (per-partition HDF5 + one .xdmf) for ParaView:

gospl-strata-volume --h5dir myrun/h5                       # --field basic (default)
gospl-strata-volume --h5dir myrun/h5 --field lithology     # or provenance
mpirun -np 4 gospl-strata-volume --h5dir myrun/h5 --field provenance \
    --tout 100000                                          # ParaView time in yr

Key options: --outdir/--out (default strata), --field basic|lithology|provenance, --tout/--tstart (label time in years), --steps, --first-layer. Runs serially or under mpirun (partitions split across ranks, independent of the run’s processor count).

Per-cell fields attached to every wedge: thickness, elevation (wedge mid-height) and layer (the recorded stratigraphic-layer index) always. --field basic (the default) adds just the per-layer porosity and needs nothing beyond a plain stratigraphy run (no dual lithology, no provenance) — use it for a single-lithology run. --field lithology adds coarse/fine thickness, fine fraction and per-fraction porosity; --field provenance adds the per-class volume fraction (src_classN), the dominant source class and the per-layer porosity (plus phiFine for a dual-lithology run). An eroded / pinched-out layer (zero thickness, hence no source) inherits the dominant source and composition of the cell directly below it in the column, so it never renders as a no-source cell.

Publication sections, wells & Wheeler — gospl-section#

Vector (PDF/SVG) stratigraphic figures via matplotlib:

# vertical cross-section coloured by lithology, with surface + basement lines
gospl-section --h5dir myrun/h5 --mesh input/mesh.npz:v:c --kind cross \
    --along x --color-by lithology --out section.pdf

gospl-section ... --kind slice   --z -50          # map at elevation z
gospl-section ... --kind well    --xy 4.2e5,3.1e5  # synthetic borehole
gospl-section ... --kind wheeler --color-by thickness \
    --strat-dt 1e4                                 # chronostratigraphic chart

# depositional facies from the deposition water depth, exaggerated x10,
# custom figure size, an interface line every 2 layers
gospl-section ... --kind cross --color-by facies --vexag 10 \
    --figsize 12,3 --layer-lines 2

--color-by ∈ {deposition, thickness, lithology, coarse, porosity, age, provenance, facies}; --along x|y or --path x0,y0;x1,y1;.... The cross-section y-axis shows true elevation; --vexag applies a real vertical exaggeration (data aspect, labels stay true); --figsize W,H sets the figure size; --layer-lines N overlays a thin interface line every N layers. ``facies`` classifies each layer by the water depth at deposition (sea_level stratZ): fluvial/deltaic plain (subaerial), shoreface (0–20 m), distal offshore (20–50 m), upper slope (50–75 m), lower slope (>75 m) — all tunable via --facies-depths (bin edges) and --facies-colors; --color-by facies works for both cross and wheeler (the Wheeler shoreline overlay is the subaerial↔marine boundary, consistent with the facies). --figsize applies to every --kind. The time axis of the Wheeler / age colouring is the real simulation time: the per-layer interval is derived from the step’s stratal display time (the .xmf Time) so the surface layer maps to that time — --strat-dt YR overrides it. The sea-level datum (section line / Wheeler shoreline trajectory / facies depth reference) is read from the simulation for the step by default (the step’s .xmf sea constant); --sea-level FLOAT overrides it. --legend-loc positions the legend (e.g. 'upper left'), --title-fontsize sets the title size, and --xlim MIN,MAX / --ylim MIN,MAX clip the cross-section / Wheeler to a distance / elevation (or time) window (pinning a limit leaves the aspect auto, so --vexag then has no effect). --figsize is honoured in the saved file by default (pass --tight to crop to content instead); for the cross-section, --vexag exaggerates via the data aspect without overriding --figsize. Horizontal distance is labelled in km and time in ky (the data stay in m / yr). The synthetic well draws its colour bar horizontally at the base (few ticks, small font, so it stays readable for a tall narrow figsize like 1,8); well_panel() draws several wells on one figure with a shared colour scale and a single colour bar (titled well 1, well 2, … by default, or pass labels). The same functions are importable for notebooks (with extra keyword args — figsize, layer_lines, facies_depths, facies_colors, facies_labels, legend_loc, title_fontsize, xlim, ylim, well cbar_orientation / vmin / vmax / colorbar / ylim, panel labels / vmin / vmax / ylim) (cross_section(), horizontal_slice(), synthetic_well(), wheeler(), well_panel()).

Regular-grid NetCDF for PyGMT / ArcGIS — gospl-grid#

Rasterises the surface to a CF-NetCDF grid with drainage basins, chi and drainage area; auto lon/lat for global meshes:

gospl-grid --h5dir myrun/h5 --mesh input/mesh.npz:v:c --out surface.nc \
    --spacing 1000 --mn 0.5

Base level for catchments/chi defaults to the run’s sea level (--base-level overrides); --latlim crops the polar caps (default 89.9). The sea level used is written into the NetCDF as the global attribute sea_level and a scalar sea_level variable (and returned in the result dict as base_level), so the grid is self-describing. The priority-flood-filled elevation is also written (filled). Every NetCDF variable carries its units and a long_name definition (CF-style), so the file is self-describing. The companion notebook API extracts / plots per-basin river longitudinal profiles (basin_rivers(), plot_long_profile(), plot_basin_map()). plot_long_profile plots the raw elevation by default (which='elev' — keeps real lakes / depressions + interpolation roughness as small peaks); which='filled' plots the hydrologically-conditioned elevation, which is strictly monotonic upstream. plot_basin_map overlays the sea-level coastline (the elev == sea_level contour; defaults to the run’s sea level) and takes a figsize.

Per-basin outflow fluxes — gospl-catchment#

For every drainage basin of a gridded surface, extract the cell of maximum water discharge and the cell of maximum sediment load — i.e. each basin’s river-mouth (outflow) point and its flux. It reads the gospl-grid NetCDF directly (it uses the same variable names — FA, sedLoad, basin, lon/lat — falling back to the legacy flowDischarge / sedimentLoad / basinID names, so old files still work). The water flux defaults to FA; pass --flow-var fillFA to use the depression-filled accumulation instead (routes the trunk discharge through lakes):

gospl-catchment -i index.csv -o flowsed

The index CSV has two columns time,netcdf (one row per step):

time,netcdf
1,results/surface1.nc
5,results/surface5.nc
10,results/surface10.nc

For each step it writes flowsed/flow{time}.csv and flowsed/sed{time}.csv (columns basin,lon,lat,val; val in m³/yr). Basins with <= --min-cells cells (default 10) are skipped. The per-basin maximum is a single vectorised lexsort (grouped arg-max), so a global 0.1° grid is processed in ~1 s per step serially — the old MPI fan-out is no longer needed. From a notebook: catchment_flux() (batch → CSVs) and basin_outflow() (one file → two DataFrames).

Sediment provenance — gospl-provenance#

Source-to-sink attribution (per-basin / per-pixel source mix, transport distance, optional Cu-fertility layer) → HDF5 + XDMF + CSV. See provenance for the inputs and --cu-weights.

ELA maps from paleo-temperature — gospl-ela#

A pre-processing helper that derives the glacier-geometry maps (hela/hice) for the ice block from a per-vertex temperature map by inverting the lapse rate:

gospl-ela --temperature t2m.npz --t-key t2m --lapse 0.0065 --t-ela -5 \
    --elevation mesh.npz --z-key z --band 800 --out glaciers_0Ma

Then list the output in the ice.glaciers time series (hela: ['glaciers_0Ma', 'hela'] etc.; see Surface processes parameters). --reference surface|sealevel selects whether the temperature map is at the surface or reduced to sea level.

Note

The console commands (gospl, gospl-strata-volume, gospl-section, gospl-grid, gospl-catchment, gospl-provenance, gospl-ela) appear after installing goSPL. Until then, use the equivalent python -m gospl.<module> form. The analysis tools need the optional extras: pip install gospl[analysis] (numba, geopandas, netCDF4, matplotlib).

From a Jupyter notebook (import the API)#

Every tool is also importable, so it can be driven and the figures shown inline in a notebook (no CLI needed):

# --- stratigraphic sections / wells / Wheeler (matplotlib, inline) ---
from gospl.analyse.stratasection import (
    load_strata, cross_section, horizontal_slice, synthetic_well, wheeler)

data = load_strata("myrun/h5", "input/mesh.npz", step=20)
cross_section(data, kind="x", color_by="lithology", vexag=20, sea_level=0)
synthetic_well(data, 4.2e5, 3.1e5, color_by="porosity")
wheeler(data, kind="x", color_by="thickness", sea_level=0, dt=1e4)
horizontal_slice(data, z=-50.0, color_by="age")

# --- gridded NetCDF + per-basin river profiles (PyGMT/ArcGIS + matplotlib) ---
from gospl.analyse.gridexport import (
    grid_export, to_netcdf, basin_rivers, plot_long_profile, plot_basin_map)

g = grid_export("myrun/h5", "input/mesh.npz", step=20, spacing=1000.)
to_netcdf(g, "surface.nc")                       # for PyGMT / ArcGIS
riv = basin_rivers(g, basin_id=g["main_basin"], area_threshold=5e6)
plot_long_profile(riv); plot_basin_map(g, riv)

# --- ELA maps from temperature (pre-processing) ---
import numpy as np
from gospl.tools.ela_from_temperature import derive_ela
hela, hice = derive_ela(np.load("t2m.npz")["t2m"], 0.0065, -5.0, 800,
                        reference="surface", elevation=np.load("mesh.npz")["z"])

Each plotting call returns the matplotlib Axes/Figure (or PyGMT-ready NetCDF) so you can tune it for a paper. The wedge volume (gospl-strata-volume) is written for ParaView rather than inline rendering.