Output Component Tutorial¶
This tutorial introduces the Output component in rompy-xbeach, which controls what data XBeach writes during simulation and when.
What You'll Learn¶
- Output file format configuration
- Four types of output: mean, global, point, and runup gauges
- Timing control (fixed intervals vs file-based)
- Variable selection and validation
- Integration with Config
Prerequisites¶
- Basic familiarity with XBeach concepts
- rompy-xbeach installed (
pip install rompy-xbeach)
1. Introduction¶
XBeach supports four types of output:
| Type | Field | Description |
|---|---|---|
| Time-averaged spatial | meanvars |
Statistics (mean, var, min, max) over intervals |
| Instantaneous spatial | globalvars |
Snapshots of entire domain |
| Fixed point | pointvars + points |
Time series at specific locations |
| Run-up gauge | pointvars + rugauges |
Time series at moving waterline |
The Output component simplifies configuration by:
- Automatically calculating count parameters (
nmeanvar,nglobalvar, etc.) - Validating variable names against XBeach's supported list
- Warning about common configuration issues
from rompy_xbeach.components.output import Output
from rompy_xbeach.types import OutputVarsEnum
def print_params(lines, filename="params.txt"):
"""Special printing to simulate a params.txt file content"""
max_content_width = max(len(line) for line in lines) if lines else 0
max_width = max(len(filename), max_content_width)
box_width = max_width + 2
print("┌" + "─" * box_width + "┐")
print("│ " + filename.ljust(max_width) + " │")
print("├" + "─" * box_width + "┤")
for line in lines:
print("│ " + line.ljust(max_width) + " │")
print("└" + "─" * box_width + "┘")
def show_params(obj, destdir=None):
"""Helper to display parameters that would be written to params.txt."""
params = obj.get(destdir=destdir)
content = []
if not params:
content.append("")
else:
for key, value in params.items():
if isinstance(value, list):
# For lists (variable names, coordinates), show each on its own line
content.append(f"{key} = {len(value)}")
for item in value:
content.append(f" {item}")
else:
content.append(f"{key} = {value}")
print_params(content)
def print_warning(text):
"""Print text with warning-style highlighting."""
print(f"\033[48;5;224m\033[30m {text} \033[0m")
# Default output - just NetCDF format
output = Output()
show_params(output)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ outputformat = netcdf │ └───────────────────────┘
The default Output() sets outputformat=netcdf. All other parameters use XBeach defaults.
2.1 Output File Configuration¶
output_format = Output(
outputformat="netcdf", # "netcdf", "fortran", or "debug"
ncfilename="my_simulation.nc", # Output filename
outputprecision="double", # "single" or "double"
)
show_params(output_format)
┌───────────────────────────────┐ │ params.txt │ ├───────────────────────────────┤ │ outputformat = netcdf │ │ outputprecision = double │ │ ncfilename = my_simulation.nc │ └───────────────────────────────┘
3. Time-Averaged Spatial Output (meanvars)¶
Mean variables provide time-averaged statistics over specified intervals. Useful for understanding average conditions.
output_mean = Output(
meanvars=[
"H", # Wave height
"thetamean", # Mean wave direction
"u", # Velocity x
"v", # Velocity y
"zs", # Water level
"zb", # Bed level
],
tstart=0.0, # Start output at t=0
tintm=3600.0, # Averaging interval: 1 hour
)
show_params(output_mean)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ outputformat = netcdf │ │ tstart = 0.0 │ │ tintm = 3600.0 │ │ nmeanvar = 6 │ │ meanvars = 6 │ │ H │ │ thetamean │ │ u │ │ v │ │ zs │ │ zb │ └───────────────────────┘
Key points:
nmeanvaris automatically calculated from list lengthtintmdefines the averaging interval (seconds)- First output at
tstart + tintm - Output represents average over
[tstart, tstart+tintm]
4. Instantaneous Spatial Output (globalvars)¶
Global variables provide snapshots of the entire domain at specific times.
output_global = Output(
globalvars=[
"H", # Wave height
"zs", # Water level
"u", # Velocity x
"v", # Velocity y
],
tstart=0.0,
tintg=10.0, # Output every 10 seconds
)
show_params(output_global)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ outputformat = netcdf │ │ tstart = 0.0 │ │ tintg = 10.0 │ │ nglobalvar = 4 │ │ globalvars = 4 │ │ H │ │ zs │ │ u │ │ v │ └───────────────────────┘
Key points:
nglobalvaris automatically calculatedtintgdefines output interval (seconds)- First output at
tstart - Provides instantaneous values (not averaged)
output_points = Output(
points=[
(0.0, 500.0), # Point 1: x=0m, y=500m
(1000.0, 500.0), # Point 2: x=1000m, y=500m
(2000.0, 500.0), # Point 3: x=2000m, y=500m
],
pointvars=[
"H", # Wave height
"u", # Velocity x
"v", # Velocity y
"zs", # Water level
],
tstart=0.0,
tintp=5.0, # Output every 5 seconds
)
show_params(output_points)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ outputformat = netcdf │ │ tstart = 0.0 │ │ tintp = 5.0 │ │ npoints = 3 │ │ points = 3 │ │ 0.0 500.0 │ │ 1000.0 500.0 │ │ 2000.0 500.0 │ │ npointvar = 4 │ │ pointvars = 4 │ │ H │ │ u │ │ v │ │ zs │ └───────────────────────┘
Key points:
- Points specified as
(x, y)coordinate pairs - XBeach links each point to nearest grid cell
npointsandnpointvarcalculated automaticallytintpdefines output interval (defaults totintgif not set)
6. Run-up Gauge Output¶
Run-up gauges track the moving waterline along cross-shore transects. Particularly useful for studying run-up and swash processes.
output_rugauges = Output(
rugauges=[
(0.0, 500.0), # Gauge 1: transect at y=500m
(0.0, 1000.0), # Gauge 2: transect at y=1000m
],
pointvars=[
"H", # Wave height
"zs", # Water level
],
nrugdepth=5, # Number of depths to compute runup
tintp=1.0, # Output every second
)
show_params(output_rugauges)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ outputformat = netcdf │ │ nrugdepth = 5 │ │ tintp = 1.0 │ │ nrugauge = 2 │ │ rugauges = 2 │ │ 0.0 500.0 │ │ 0.0 1000.0 │ │ npointvar = 2 │ │ pointvars = 2 │ │ H │ │ zs │ └───────────────────────┘
Key points:
- Run-up gauges share
pointvarswith fixed points - XBeach automatically adds
xw,yw,zsto output - Gauges linked to nearest cross-shore transect
nrugdepthspecifies how many water depths to track
7.1 Fixed Interval Timing¶
Each output type has its own timing parameter:
output_timing = Output(
globalvars=["H", "zs"],
meanvars=["H", "u"],
pointvars=["H"],
points=[(0.0, 500.0)],
tstart=0.0, # Start time for all output
tintg=10.0, # Global output every 10s
tintm=3600.0, # Mean output every hour
tintp=5.0, # Point output every 5s
)
show_params(output_timing)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ outputformat = netcdf │ │ tstart = 0.0 │ │ tintg = 10.0 │ │ tintm = 3600.0 │ │ tintp = 5.0 │ │ npoints = 1 │ │ points = 1 │ │ 0.0 500.0 │ │ nmeanvar = 2 │ │ meanvars = 2 │ │ H │ │ u │ │ nglobalvar = 2 │ │ globalvars = 2 │ │ H │ │ zs │ │ npointvar = 1 │ │ pointvars = 1 │ │ H │ └───────────────────────┘
Timing parameters:
| Parameter | Description | First output |
|---|---|---|
tstart |
Start time for output | - |
tintg |
Global (instantaneous) interval | tstart |
tintm |
Mean output interval | tstart + tintm |
tintp |
Point/runup interval | tstart |
7.2 File-Based Timing¶
For irregular schedules, specify output times from files using DataBlob.
from pathlib import Path
import tempfile
def create_timing_file(filepath: Path, times: list[float]) -> Path:
"""Create an XBeach timing file."""
content = f"{len(times)}\n" + "\n".join(str(t) for t in times) + "\n"
filepath.write_text(content)
return filepath
# Create timing files
tmpdir = Path(tempfile.mkdtemp())
global_times = [0, 30, 60, 90, 120, 150, 180]
global_times_file = create_timing_file(tmpdir / "global_times.txt", global_times)
mean_times = [3600, 7200, 10800]
mean_times_file = create_timing_file(tmpdir / "mean_times.txt", mean_times)
print(f"Created timing files in {tmpdir}")
Created timing files in /tmp/tmpxdqpil94
output_file_times = Output(
globalvars=["H", "zs"],
tsglobal=dict(source=str(global_times_file)),
meanvars=["H", "u"],
tsmean=dict(source=str(mean_times_file)),
)
# Note: When using file-based timing (tsglobal, tsmean, tspoint),
# we need to provide a destdir for get() to copy files to
destdir = Path(tempfile.mkdtemp())
show_params(output_file_times, destdir=destdir)
┌─────────────────────────────┐ │ params.txt │ ├─────────────────────────────┤ │ outputformat = netcdf │ │ tsglobal = global_times.txt │ │ tsmean = mean_times.txt │ │ nmeanvar = 2 │ │ meanvars = 2 │ │ H │ │ u │ │ nglobalvar = 2 │ │ globalvars = 2 │ │ H │ │ zs │ └─────────────────────────────┘
File format:
<number of times>
<time 1>
<time 2>
...
Note: File-based times supersede fixed intervals if both are specified.
7.3 Using get() with destdir¶
The get() method fetches external files and copies them to the destination.
Let's see what files were copied:
print("Files copied to destdir:")
for f in sorted(destdir.iterdir()):
print(f" {f.name}")
# Clean up
import shutil
shutil.rmtree(tmpdir, ignore_errors=True)
shutil.rmtree(destdir, ignore_errors=True)
Files copied to destdir: global_times.txt mean_times.txt
8. Hotstart Output¶
Hotstart files allow you to restart a simulation from a saved state. This is useful for long simulations or chaining multiple runs.
output_hotstart = Output(
globalvars=["H", "zs"],
tintg=10.0,
writehotstart=True, # Enable hotstart file writing
tinth=3600.0, # Write hotstart every hour
)
show_params(output_hotstart)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ outputformat = netcdf │ │ tintg = 10.0 │ │ tinth = 3600.0 │ │ writehotstart = True │ │ nglobalvar = 2 │ │ globalvars = 2 │ │ H │ │ zs │ └───────────────────────┘
Hotstart parameters:
| Parameter | Description |
|---|---|
writehotstart |
Enable writing hotstart files (default: False) |
tinth |
Interval for hotstart output (seconds). If 0 or not set, writes only at end. |
Hotstart files can be used with the Hotstart component to initialize subsequent simulations.
9. Variable Name Validation¶
Variable names are validated against OutputVarsEnum. Only XBeach-supported
variables are accepted.
# Valid variables
output_valid = Output(meanvars=["H", "u", "v", "zs"])
show_params(output_valid)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ outputformat = netcdf │ │ nmeanvar = 4 │ │ meanvars = 4 │ │ H │ │ u │ │ v │ │ zs │ └───────────────────────┘
# Invalid variable - raises ValidationError
from pydantic import ValidationError
try:
output_invalid = Output(meanvars=["H", "invalid_var", "u"])
except ValidationError as e:
print_warning(f"{e.errors()[0]['msg']}")
Input should be 'As', 'BR', 'Cdrag', 'D', 'D15', 'D50', 'D50top', 'D90', 'D90top', 'DR', 'Dc', 'Df', 'Dp', 'Dveg', 'E', 'Fvegu', 'Fvegv', 'Fx', 'Fy', 'H', 'Hrunup', 'L1', 'Qb', 'R', 'Sk', 'Subg', 'Susg', 'Sutot', 'Svbg', 'Svsg', 'Svtot', 'Sxx', 'Sxy', 'Syy', 'Tbore', 'Tsg', 'alfau', 'alfav', 'alfaz', 'bedfriccoef', 'bi', 'breaking', 'bwalpha', 'c', 'ca', 'ccg', 'cctot', 'ccz', 'ceqbg', 'ceqsg', 'cf', 'cfu', 'cfv', 'cg', 'cgx', 'cgx_s', 'cgy', 'cgy_s', 'cobs', 'costh', 'costh_s', 'ctheta', 'ctheta_s', 'cx', 'cy', 'dU', 'dUi', 'dV', 'dassim', 'dcbdx', 'dcbdy', 'dcmdo', 'dcsdx', 'dcsdy', 'depo_ex', 'depo_im', 'dinfil', 'dnc', 'dnu', 'dnv', 'dnz', 'dobs', 'dsc', 'dsdnui', 'dsdnvi', 'dsdnzi', 'dsu', 'dsv', 'dsz', 'dzav', 'dzbdt', 'dzbdx', 'dzbdy', 'dzbed', 'dzbnow', 'dzs0dn', 'dzsdt', 'dzsdx', 'dzsdy', 'ee', 'ee_s', 'ero', 'fw', 'gw0back', 'gwbottom', 'gwcurv', 'gwhead', 'gwheadb', 'gwheight', 'gwlevel', 'gwqx', 'gwqy', 'gwu', 'gwv', 'gww', 'hh', 'hhw', 'hhwcins', 'hhws', 'hold', 'hu', 'hum', 'hv', 'hvm', 'idrift', 'infil', 'istruct', 'iwl', 'jdrift', 'k', 'kb', 'kturb', 'maxzs', 'minzs', 'n', 'nd', 'ndist', 'nuh', 'nutz', 'pbbed', 'pdisch', 'ph', 'pntdisch', 'pres', 'qdisch', 'qx', 'qy', 'refA', 'rolthick', 'rr', 'runup', 'sdist', 'sedcal', 'sedero', 'setbathy', 'shipFx', 'shipFy', 'shipFz', 'shipMx', 'shipMy', 'shipMz', 'shipchi', 'shipphi', 'shippsi', 'shipxCG', 'shipyCG', 'shipzCG', 'shobs', 'sig2prior', 'sigm', 'sigt', 'sigz', 'sinth', 'sinth_s', 'strucslope', 'structdepth', 'taubx', 'taubx_add', 'tauby', 'tauby_add', 'tdisch', 'tdriftb', 'tdrifte', 'thet', 'thet_s', 'theta', 'theta_s', 'thetamean', 'tideinpt', 'tideinpz', 'tsetbathy', 'u', 'ua', 'ucrcal', 'ududx', 'udvdx', 'ue', 'ue_sed', 'ueu', 'ui', 'umean', 'umwci', 'ur', 'urepb', 'ureps', 'urms', 'usd', 'ust', 'ustr', 'ustz', 'uu', 'uv', 'uwcins', 'uwf', 'uws', 'uz', 'v', 'vdudy', 'vdvdy', 've', 've_sed', 'vegtype', 'vev', 'vi', 'viscu', 'viscv', 'vmag', 'vmageu', 'vmagev', 'vmagu', 'vmagv', 'vmean', 'vmwci', 'vrepb', 'vreps', 'vu', 'vv', 'vwcins', 'vwf', 'vws', 'vz', 'wb', 'wete', 'wetu', 'wetv', 'wetz', 'wi', 'winddirts', 'windinpt', 'windnv', 'windsu', 'windvelts', 'windxts', 'windyts', 'wm', 'ws', 'wscrit', 'x', 'xhrunup', 'xu', 'xv', 'xyzs01', 'xyzs02', 'xyzs03', 'xyzs04', 'xz', 'y', 'yu', 'yv', 'yz', 'z0bed', 'zb', 'zb0', 'zbobs', 'zi', 'zs', 'zs0', 'zs0fac', 'zs1' or 'zswci'
Available Variables¶
Common output variables include:
| Variable | Description |
|---|---|
H |
Wave height |
zs |
Water level |
zb |
Bed level |
u, v |
Velocity components |
thetamean |
Mean wave direction |
Qb |
Fraction breaking waves |
sedero |
Cumulative sedimentation/erosion |
ccg, cctot |
Sediment concentration |
See OutputVarsEnum for the complete list.
10.1 Variable Limits¶
XBeach has limits on the number of variables:
import logging
logging.basicConfig(level=logging.WARNING, format='%(message)s')
# Too many mean variables (limit: 15)
all_vars = [v.value for v in OutputVarsEnum][:20]
output_many = Output(meanvars=all_vars)
2026-01-10 17:11:12 [WARNING] rompy_xbeach.components.output: ! More than 15 meanvars requested. XBeach only supports up to 15. Beware of possible unexpected results in the model.
Limits:
- Mean variables: 15
- Global variables: 20
- Point variables: 50
- Points/rugauges: 50 each
10.2 Inconsistent Point Configuration¶
# Warning: pointvars without locations
output_no_loc = Output(pointvars=["H", "u"])
2026-01-10 17:11:12 [WARNING] rompy_xbeach.components.output: ! Point output variables (pointvars) are defined, but no point locations (points) or runup gauge locations (rugauges) have been prescribed. Output will not be generated.
# Warning: locations without variables
output_no_vars = Output(points=[(0.0, 500.0)])
2026-01-10 17:11:12 [WARNING] rompy_xbeach.components.output: ! Point locations (points) or runup gauge locations (rugauges) are defined, but no point output variables (pointvars) have been prescribed. No point/runup output will be generated.
10.3 Conflicting Time Specifications¶
# Create a timing file for demo
conflict_tmpdir = Path(tempfile.mkdtemp())
conflict_file = create_timing_file(conflict_tmpdir / "times.txt", [0, 100, 200])
# Warning: both fixed and file times
output_conflict = Output(
globalvars=["H"],
tintg=10.0, # Fixed interval
tsglobal=dict(source=str(conflict_file)) # File times (takes precedence)
)
shutil.rmtree(conflict_tmpdir, ignore_errors=True)
2026-01-10 17:11:12 [WARNING] rompy_xbeach.components.output: ! Global times defined by both fixed (tintg) and file (tsglobal) times. The file-based times (tsglobal) will supersede the fixed interval.
output_storm = Output(
# File configuration
outputformat="netcdf",
ncfilename="storm_output.nc",
outputprecision="double",
# Time-averaged output (hourly statistics)
meanvars=["H", "u", "v", "zs", "zb"],
tintm=3600.0,
# Instantaneous output (every 10 seconds)
globalvars=["H", "zs"],
tintg=10.0,
# Point output (every 5 seconds)
points=[
(0.0, 500.0),
(500.0, 500.0),
(1000.0, 500.0),
],
pointvars=["H", "u", "v", "zs"],
tintp=5.0,
# Run-up gauges (every second)
rugauges=[
(0.0, 500.0),
],
nrugdepth=5,
# Start time
tstart=0.0,
# Progress output
timings=True,
# Hotstart (write every hour)
writehotstart=True,
tinth=3600.0,
)
show_params(output_storm)
┌──────────────────────────────┐ │ params.txt │ ├──────────────────────────────┤ │ outputformat = netcdf │ │ outputprecision = double │ │ ncfilename = storm_output.nc │ │ nrugdepth = 5 │ │ timings = 1 │ │ tstart = 0.0 │ │ tintg = 10.0 │ │ tintm = 3600.0 │ │ tintp = 5.0 │ │ tinth = 3600.0 │ │ writehotstart = True │ │ npoints = 3 │ │ points = 3 │ │ 0.0 500.0 │ │ 500.0 500.0 │ │ 1000.0 500.0 │ │ nrugauge = 1 │ │ rugauges = 1 │ │ 0.0 500.0 │ │ nmeanvar = 5 │ │ meanvars = 5 │ │ H │ │ u │ │ v │ │ zs │ │ zb │ │ nglobalvar = 2 │ │ globalvars = 2 │ │ H │ │ zs │ │ npointvar = 4 │ │ pointvars = 4 │ │ H │ │ u │ │ v │ │ zs │ └──────────────────────────────┘
config_example = """
from rompy_xbeach import Config
from rompy_xbeach.components.output import Output
config = Config(
project="storm_simulation",
grid=grid,
bathy=bathy,
output=Output(
ncfilename="output.nc",
meanvars=["H", "zs"],
globalvars=["H"],
points=[(0.0, 500.0)],
pointvars=["H", "u"],
tintg=10.0,
tintm=3600.0,
),
# ... other components ...
)
config.generate(destdir="./model_run")
"""
print(config_example)
from rompy_xbeach import Config
from rompy_xbeach.components.output import Output
config = Config(
project="storm_simulation",
grid=grid,
bathy=bathy,
output=Output(
ncfilename="output.nc",
meanvars=["H", "zs"],
globalvars=["H"],
points=[(0.0, 500.0)],
pointvars=["H", "u"],
tintg=10.0,
tintm=3600.0,
),
# ... other components ...
)
config.generate(destdir="./model_run")
Summary¶
Key Takeaways¶
Four output types: mean, global, point, runup gauge
Automatic counting:
nmeanvar,nglobalvar, etc. calculated from list lengthsTiming options:
- Fixed intervals:
tintg,tintm,tintp - File-based:
tsglobal,tsmean,tspoint
- Fixed intervals:
Hotstart: Use
writehotstartandtinthto save simulation stateValidation: Variable names checked against
OutputVarsEnumWarnings: Catches common issues (missing locations, conflicting times)
Output Timing Summary¶
| Type | Interval | File | First Output |
|---|---|---|---|
| Global | tintg |
tsglobal |
tstart |
| Mean | tintm |
tsmean |
tstart + tintm |
| Point | tintp |
tspoint |
tstart |
| Hotstart | tinth |
- | tinth (or end) |
Next Steps¶
- See the Physics Tutorial for hydrodynamics
- See the Sediment Tutorial for morphology
- Analyse output with xarray:
xr.open_dataset("xboutput.nc")