XBeach Output Configuration Tutorial¶
This notebook demonstrates how to configure output for XBeach models using the
Output class. XBeach supports four types of output:
- Time-averaged spatial output (
meanvars) - Statistics over time intervals - Instantaneous spatial output (
globalvars) - Snapshots at specific times - Fixed point output (
pointvars+points) - Time series at specific locations - Run-up gauge output (
pointvars+rugauges) - Time series at moving waterline
Let's start by importing the necessary modules.
from rompy_xbeach.components.output import Output
from rompy_xbeach.types import OutputVarsEnum
from pathlib import Path
import tempfile
import os
def show_params(params):
"""Helper function to display params in XBeach params.txt format."""
for key, value in params.items():
if isinstance(value, list):
# For lists, print each item on its own line
for item in value:
print(item)
else:
# For regular values, print key = value
print(f"{key} = {value}")
1. Basic Output Format Configuration¶
Let's start by configuring the output file format and name. The default output format is NetCDF, which is recommended for most applications.
output_format = Output(
outputformat="netcdf", # Default, can also be "fortran" or "debug"
ncfilename="my_simulation.nc",
outputprecision="double",
)
show_params(output_format.params)
outputformat = netcdf outputprecision = double ncfilename = my_simulation.nc
Available options:
outputformat:"netcdf"(default),"fortran", or"debug"outputprecision:"single"or"double"(for NetCDF only)ncfilename: Name of the NetCDF output file (default:xboutput.nc)
2. Time-Averaged Spatial Output (Mean Variables)¶
Mean variables provide time-averaged statistics (mean, variance, min, max) over specified intervals. This is useful for understanding average conditions.
output_mean = Output(
ncfilename="output.nc",
meanvars=[
"H", # Wave height
"thetamean", # Mean wave direction
"u", # Velocity in x-direction
"v", # Velocity in y-direction
"zs", # Water level
"zb", # Bed level
],
tstart=0.0, # Start output at t=0
tintm=3600.0, # Output interval: 1 hour
)
show_params(output_mean.params)
outputformat = netcdf ncfilename = output.nc tstart = 0.0 tintm = 3600.0 nmeanvar = 6 H thetamean u v zs zb
Key points:
nmeanvaris automatically calculated from the list lengthtintmdefines the averaging interval (seconds)- First output is at
tstart + tintm - The output represents the average over
[tstart, tstart+tintm]
Variable Name Validation¶
Variable names are validated against the OutputVarsEnum. Only variables supported by XBeach and defined in the enum are accepted. This prevents typos and ensures compatibility.
# This works - valid variable names
output_valid = Output(
meanvars=["H", "u", "v", "zs"]
)
print("Valid variables accepted:")
show_params(output_valid.params)
Valid variables accepted: outputformat = netcdf nmeanvar = 4 H u v zs
# This will raise a validation error - invalid variable name
try:
output_invalid = Output(
meanvars=["H", "dummy", "u"] # "dummy" is not valid
)
except Exception as e:
print(f"Validation error: {type(e).__name__}")
print(f"Message: {e}")
Validation error: ValidationError
Message: 1 validation error for Output
meanvars.1
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' [type=enum, input_value='dummy', input_type=str]
For further information visit https://errors.pydantic.dev/2.11/v/enum
Note: Variable names are case-sensitive and must match exactly as documented
by XBeach. For example, use "H" (not "h"), "zs" (not "ZS"), and
"thetamean" (not "ThetaMean").
3. Instantaneous Spatial Output (Global Variables)¶
Global variables provide instantaneous snapshots of the entire model domain at specified time intervals.
output_global = Output(
ncfilename="output.nc",
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)
outputformat = netcdf ncfilename = output.nc tstart = 0.0 tintg = 10.0 nglobalvar = 4 H zs u v
Key points:
nglobalvaris automatically calculatedtintgdefines the output interval (seconds)- First output is at
tstart - Provides instantaneous values (not averaged)
4. Fixed Point Output¶
Point output provides time series at specific fixed locations in the model domain. This is useful for detailed analysis at locations of interest.
output_points = Output(
ncfilename="output.nc",
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)
outputformat = netcdf ncfilename = output.nc tstart = 0.0 tintp = 5.0 npoints = 3 0.0 500.0 1000.0 500.0 2000.0 500.0 npointvar = 4 H u v zs
Key points:
- Points are specified as
(x, y)coordinate pairs - XBeach links each point to the nearest computational grid point
npointsandnpointvarare automatically calculatedtintpdefines the output interval (defaults totintgif not specified)- Coordinates are formatted as space-separated strings in params
5. Run-up Gauge Output¶
Run-up gauges track the moving waterline along cross-shore transects. This is particularly useful for studying run-up and swash processes.
output_rugauges = Output(
ncfilename="output.nc",
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
tstart=0.0,
tintp=1.0, # Output every second
)
show_params(output_rugauges.params)
outputformat = netcdf ncfilename = output.nc nrugdepth = 5 tstart = 0.0 tintp = 1.0 nrugauge = 2 0.0 500.0 0.0 1000.0 npointvar = 2 H zs
Key points:
- Run-up gauges share point output variables (
pointvars) - XBeach automatically adds
xw,yw, andzsto the output - Gauges are linked to the nearest cross-shore transect (not just a point)
nrugdepthspecifies how many water depths to track- Useful for studying swash zone dynamics
6. Output Timing Control¶
XBeach provides two ways to control when output is written: fixed intervals or file-based times.
6.1 Fixed Interval Timing¶
The most common approach is to use fixed time intervals for output. Each output type has its own timing parameter:
output_timing = Output(
ncfilename="output.nc",
globalvars=["H", "zs"],
meanvars=["H", "u"],
pointvars=["H"],
points=[(0.0, 500.0)],
tstart=0.0, # Start time for output (seconds)
tintg=10.0, # Global output interval (seconds)
tintm=3600.0, # Mean output interval (seconds)
tintp=5.0, # Point output interval (seconds)
)
show_params(output_timing.params)
outputformat = netcdf ncfilename = output.nc tstart = 0.0 tintg = 10.0 tintm = 3600.0 tintp = 5.0 npoints = 1 0.0 500.0 nmeanvar = 2 H u nglobalvar = 2 H zs npointvar = 1 H
Timing parameters:
tstart: Start time for output (default: 0.0)tintg: Interval for global (instantaneous) output (default: 1.0 s)- First output at
tstart
- First output at
tintm: Interval for mean output (default:tstop - tstart)- First output at
tstart + tintm - Represents average over
[tstart, tstart + tintm]
- First output at
tintp: Interval for point/runup output (default: same astintg)- First output at
tstart
- First output at
6.2 File-Based Timing¶
For irregular output schedules or specific snapshots, you can specify output times from files using the DataBlob type. This is useful for event-based output or when you need precise control over output times.
The timing files must follow XBeach's format:
- First line: number of output times
- Following lines: one time value per line (in seconds)
First, let's create example timing files in a temporary directory:
def create_timing_file(filepath: Path, times: list[float]) -> Path:
"""Create an XBeach timing file with the specified times."""
content = f"{len(times)}\n" + "\n".join(str(t) for t in times) + "\n"
filepath.write_text(content)
return filepath
# Create a temporary directory for our timing files
tmpdir = Path(tempfile.mkdtemp())
print(f"Creating timing files in: {tmpdir}\n")
# Create global output times file (every 30 seconds for 5 minutes)
global_times = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300]
global_times_file = create_timing_file(tmpdir / "global_times.txt", global_times)
print(f"Created {global_times_file} with {len(global_times)} times: {global_times}")
# Create mean output times file (every hour for 6 hours)
mean_times = [3600, 7200, 10800, 14400, 18000, 21600]
mean_times_file = create_timing_file(tmpdir / "mean_times.txt", mean_times)
print(f"Created {mean_times_file} with {len(mean_times)} times: {mean_times}")
# Create point output times file (specific event times)
point_times = [0, 100, 500, 1000, 2000, 3000]
point_times_file = create_timing_file(tmpdir / "point_times.txt", point_times)
print(f"Created {point_times_file} with {len(point_times)} times: {point_times}")
Creating timing files in: /tmp/tmp6vn6gb0w Created /tmp/tmp6vn6gb0w/global_times.txt with 11 times: [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300] Created /tmp/tmp6vn6gb0w/mean_times.txt with 6 times: [3600, 7200, 10800, 14400, 18000, 21600] Created /tmp/tmp6vn6gb0w/point_times.txt with 6 times: [0, 100, 500, 1000, 2000, 3000]
Now we can create an Output configuration using these timing files with DataBlob:
output_file_times = Output(
ncfilename="output.nc",
globalvars=["H", "zs"],
tsglobal=dict(source=global_times_file), # DataBlob with file source
meanvars=["H", "u"],
tsmean=dict(source=mean_times_file), # DataBlob with file source
pointvars=["H"],
points=[(0.0, 500.0)],
tspoint=dict(source=point_times_file), # DataBlob with file source
)
show_params(output_file_times.params)
outputformat = netcdf
ncfilename = output.nc
tsglobal = {'model_type': 'data_blob', 'id': 'data', 'source': PosixPath('/tmp/tmp6vn6gb0w/global_times.txt'), 'link': False}
tsmean = {'model_type': 'data_blob', 'id': 'data', 'source': PosixPath('/tmp/tmp6vn6gb0w/mean_times.txt'), 'link': False}
tspoint = {'model_type': 'data_blob', 'id': 'data', 'source': PosixPath('/tmp/tmp6vn6gb0w/point_times.txt'), 'link': False}
npoints = 1
0.0 500.0
nmeanvar = 2
H
u
nglobalvar = 2
H
zs
npointvar = 1
H
File-based timing parameters:
tsglobal: DataBlob containing global output timestsmean: DataBlob containing mean output timestspoint: DataBlob containing point output times
Important notes:
- Each file must contain the number of times on the first line, followed by one time value per line (in seconds)
- File-based times supersede fixed interval times if both are specified
- Times are relative to the simulation start
- Useful for irregular sampling or event-based output
6.3 Using the get() Method¶
The Output.get() method fetches external timing files from local and remote sources
and copies them to the destination directory. This method is automatically called by
the Config class when generating the params file, with destdir set to the workspace
folder.
Let's demonstrate how this works:
# Create a destination directory (simulating the workspace folder)
destdir = Path(tempfile.mkdtemp())
print(f"Destination directory: {destdir}\n")
# Call get() to fetch the timing files
params_with_files = output_file_times.get(destdir)
show_params(params_with_files)
Destination directory: /tmp/tmpol1n6ij2 outputformat = netcdf ncfilename = output.nc tsglobal = /tmp/tmpol1n6ij2/global_times.txt tsmean = /tmp/tmpol1n6ij2/mean_times.txt tspoint = /tmp/tmpol1n6ij2/point_times.txt npoints = 1 0.0 500.0 nmeanvar = 2 H u nglobalvar = 2 H zs npointvar = 1 H
Let's verify that the files were copied to the destination directory:
print("\nFiles in destination directory:")
for file in sorted(destdir.iterdir()):
print(f" {file.name}")
lines = file.read_text().splitlines()
for line in lines[:5]:
print(f" {line}")
if len(lines) > 5:
print(f" ... ({len(lines) - 5} more lines)")
Files in destination directory:
global_times.txt
11
0
30
60
90
... (7 more lines)
mean_times.txt
6
3600
7200
10800
14400
... (2 more lines)
point_times.txt
6
0
100
500
1000
... (2 more lines)
Key points about the get() method:
- Automatically called during model generation by the
Configclass - Copies timing files from their source location to the workspace directory
- Returns a params dictionary with updated file paths
- Ensures all external files are available in the model run directory
- The
destdirparameter is typically set to the model's staging directory
Clean up temporary directories:
import shutil
shutil.rmtree(tmpdir, ignore_errors=True)
shutil.rmtree(destdir, ignore_errors=True)
print("Temporary directories cleaned up")
Temporary directories cleaned up
7. Progress Output Control¶
Control whether XBeach displays progress information during the simulation.
output_progress = Output(
ncfilename="output.nc",
timings=True, # Enable progress output to screen
globalvars=["H"],
tintg=10.0,
)
show_params(output_progress.params)
outputformat = netcdf ncfilename = output.nc timings = 1 tintg = 10.0 nglobalvar = 1 H
Note: The timings boolean is automatically converted to an integer (0 or 1)
for XBeach compatibility.
8. Comprehensive Configuration¶
Let's put it all together with a comprehensive output configuration that uses multiple output types simultaneously.
output_comprehensive = Output(
# Output file configuration
outputformat="netcdf",
ncfilename="comprehensive_output.nc",
outputprecision="double",
# Time-averaged spatial output
meanvars=[
"H",
"u",
"v",
],
# Instantaneous spatial output
globalvars=[
"zs",
],
# Fixed point output
points=[
(0.0, 500.0),
(1000.0, 500.0),
(2000.0, 500.0),
],
# Run-up gauges
rugauges=[
(0.0, 750.0),
(0.0, 1250.0),
],
# Point/runup variables (shared)
pointvars=[
"H",
"u",
"v",
"zs",
],
# Timing configuration
tstart=0.0,
tintg=10.0, # Global output every 10 seconds
tintm=3600.0, # Mean output every hour
tintp=5.0, # Point output every 5 seconds
# Run-up configuration
nrugdepth=5,
# Progress output
timings=True,
)
show_params(output_comprehensive.params)
outputformat = netcdf outputprecision = double ncfilename = comprehensive_output.nc nrugdepth = 5 timings = 1 tstart = 0.0 tintg = 10.0 tintm = 3600.0 tintp = 5.0 npoints = 3 0.0 500.0 1000.0 500.0 2000.0 500.0 nrugauge = 2 0.0 750.0 0.0 1250.0 nmeanvar = 3 H u v nglobalvar = 1 zs npointvar = 4 H u v zs
9. Validation and Warnings¶
The Output class includes validators that warn about potential issues. Let's see some examples.
Example 1: Exceeding Variable Limits¶
XBeach has limits on the number of variables for each output type. The Output class will warn you if you exceed these limits.
# Build a list with all supported variables
all_variables = [v.value for v in OutputVarsEnum]
# This will generate a warning (limit is 15 mean variables)
output_too_many = Output(
meanvars=all_variables[:20] # 20 variables exceeds the limit
)
show_params(output_too_many.params)
2025-10-09 18:23:34 [WARNING] rompy_xbeach.components.output: ! More than 15 meanvars requested. XBeach only supports up to 15. Beware of possible unexpected results in the model.
outputformat = netcdf nmeanvar = 20 As BR Cdrag D D15 D50 D50top D90 D90top DR Dc Df Dp Dveg E Fvegu Fvegv Fx Fy H
Limits:
- Mean variables: 15
- Global variables: 20
- Point variables: 50
- Points/run-up gauges: 50 each
Example 2: Inconsistent Point Configuration¶
If you define point variables without locations (or vice versa), you'll get a warning.
# Warning: pointvars without locations
output_no_locations = Output(
pointvars=["H", "u"]
# No points or rugauges defined!
)
show_params(output_no_locations.params)
2025-10-09 18:23:34 [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.
outputformat = netcdf npointvar = 2 H u
# Warning: locations without variables
output_no_vars = Output(
points=[(0.0, 500.0)]
# No pointvars defined!
)
show_params(output_no_vars.params)
2025-10-09 18:23:34 [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.
outputformat = netcdf npoints = 1 0.0 500.0
Example 3: Conflicting Time Specifications¶
If you specify both fixed intervals and file-based times, the file-based times will supersede the fixed intervals, and you'll get a warning.
# Create a simple timing file for demonstration
conflict_tmpdir = Path(tempfile.mkdtemp())
conflict_times_file = create_timing_file(conflict_tmpdir / "times.txt", [0, 100, 200])
# Warning: both fixed and file times specified
output_conflict = Output(
globalvars=["H"],
tintg=10.0, # Fixed interval
tsglobal=dict(source=str(conflict_times_file)), # File-based times (this takes precedence)
)
show_params(output_conflict.params)
# Clean up
shutil.rmtree(conflict_tmpdir, ignore_errors=True)
2025-10-09 18:23:34 [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.
outputformat = netcdf
tintg = 10.0
tsglobal = {'model_type': 'data_blob', 'id': 'data', 'source': PosixPath('/tmp/tmp0qlzyopo/times.txt'), 'link': False}
nglobalvar = 1
H
10. Integration with XBeach Config¶
The Output object is typically used as part of a larger XBeach configuration:
# Example of how Output fits into a Config object
example_usage = """
from rompy_xbeach.config import Config
from rompy_xbeach.components.output import Output
config = Config(
# ... other configuration parameters ...
output=Output(
ncfilename="simulation_output.nc",
meanvars=["H", "zs"],
globalvars=["H"],
points=[(0.0, 500.0)],
pointvars=["H", "u"],
tstart=0.0,
tintg=10.0,
tintm=3600.0,
),
# ... other configuration parameters ...
)
# The output.params will be merged into the params.txt file
params = config.output.params
"""
print("Integration Example:")
print(example_usage)
Integration Example:
from rompy_xbeach.config import Config
from rompy_xbeach.components.output import Output
config = Config(
# ... other configuration parameters ...
output=Output(
ncfilename="simulation_output.nc",
meanvars=["H", "zs"],
globalvars=["H"],
points=[(0.0, 500.0)],
pointvars=["H", "u"],
tstart=0.0,
tintg=10.0,
tintm=3600.0,
),
# ... other configuration parameters ...
)
# The output.params will be merged into the params.txt file
params = config.output.params
Summary¶
Key takeaways:
- Four output types: mean, global, point, and run-up gauge
- Automatic counting:
nmeanvar,nglobalvar, etc. are calculated automatically - Flexible timing: Use fixed intervals or file-based times
- Validation: Built-in warnings for common configuration issues
- Simple to complex: Start simple and add complexity as needed
- Type-safe: Uses enums for variable names to prevent typos
For more information, see the XBeach manual and the Output class documentation.
Next Steps¶
- Explore other XBeach configuration components (grid, boundary conditions, etc.)
- Run a complete simulation with your output configuration
- Analyse the output NetCDF file using xarray or other tools
- Experiment with different output variables and timing configurations