XBeach Declarative Workflow¶
This notebook demonstrates the declarative approach to setting up an XBeach model using rompy-xbeach. The entire configuration is defined in a YAML file, which is then loaded and executed.
Why Declarative?¶
The declarative approach offers several advantages:
- Reproducibility - Configuration is version-controlled and shareable
- Separation of concerns - Configuration is separate from execution logic
- Automation - Easy to integrate with workflows and batch processing
- Validation - YAML is validated against the Pydantic schema
For the procedural approach with step-by-step Python code, see the companion notebook.
In [1]:
Copied!
from pathlib import Path
from datetime import timedelta
import shutil
import yaml
import pandas as pd
import xarray as xr
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
from pathlib import Path
from datetime import timedelta
import shutil
import yaml
import pandas as pd
import xarray as xr
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
The YAML Configuration¶
The configuration file defines all aspects of the model:
- run_id and output_dir - Run identification and output location
- period - Simulation time range
- config - Complete XBeach configuration (grid, bathy, forcing, physics, output)
In [2]:
Copied!
# View the YAML configuration
yaml_file = Path("example-declarative.yml")
print(yaml_file.read_text())
# View the YAML configuration
yaml_file = Path("example-declarative.yml")
print(yaml_file.read_text())
# XBeach Declarative Configuration Example
#
# This YAML file defines a complete XBeach model configuration.
# It can be loaded directly by rompy to generate the model workspace.
run_id: declarative_example
output_dir: example-declarative-output
period:
start: 2023-01-01T00:00
end: 2023-01-01T12:00
interval: 1h
config:
model_type: xbeach
# ===================
# Grid Definition
# ===================
grid:
model_type: regular
ori:
x: 115.594239
y: -32.641104
crs: EPSG:4326
alfa: 347.0
dx: 10.0
dy: 15.0
nx: 230
ny: 220
crs: EPSG:28350
# ===================
# Bathymetry
# ===================
bathy:
model_type: xbeach_bathy
source:
model_type: geotiff
filename: /source/csiro/rompy-xbeach/tests/data/bathy.tif
posdwn: false
interpolator:
model_type: scipy_regular_grid
kwargs:
method: linear
fill_value: null
extension:
model_type: linear
depth: 25.0
slope: 0.1
left: 5
right: 5
# ===================
# Input Data
# ===================
input:
# Wave boundary - SWAN spectral format
wave:
model_type: station_spectra_swan
source:
model_type: wavespectra
uri: /source/csiro/rompy-xbeach/tests/data/ww3-spectra-20230101-short.nc
reader: read_ww3
# Wind forcing
wind:
model_type: wind_station
source:
model_type: file
uri: /source/csiro/rompy-xbeach/tests/data/smc-params-20230101.nc
crs: 4326
coords:
s: seapoint
wind_vars:
model_type: wind_vector
u: uwnd
v: vwnd
# Tide forcing
tide:
model_type: tide_cons_grid
source:
model_type: oceantide
reader: read_otis_binary
kwargs:
gfile: /source/csiro/rompy-xbeach/tests/data/swaus_tide_cons/grid_m2s2n2k2k1o1p1q1mmmf
hfile: /source/csiro/rompy-xbeach/tests/data/swaus_tide_cons/h_m2s2n2k2k1o1p1q1mmmf
ufile: /source/csiro/rompy-xbeach/tests/data/swaus_tide_cons/u_m2s2n2k2k1o1p1q1mmmf
crs: 4326
coords:
x: lon
y: lat
# ===================
# Flow Boundary Conditions
# ===================
flow_boundary:
front: abs_2d
back: abs_2d
left: neumann
right: neumann
# ===================
# Tide Boundary
# ===================
tide_boundary:
zs0: 0.0
paulrevere: land
# ===================
# Output Configuration
# ===================
output:
outputformat: netcdf
ncfilename: xboutput.nc
tstart: 0.0
tintm: 3600.0
YAML Structure Overview¶
run_id: my_run # Unique run identifier
output_dir: ./output # Output directory
period:
start: 2023-01-01T00:00 # Simulation start
end: 2023-01-01T12:00 # Simulation end
interval: 1h # Time interval for forcing
config:
model_type: xbeach # Model type (required)
grid: {...} # Grid definition
bathy: {...} # Bathymetry configuration
input: # Forcing data
wave: {...} # Wave boundary
wind: {...} # Wind forcing
tide: {...} # Tide forcing
flow_boundary: {...} # Flow boundary conditions
tide_boundary: {...} # Tide boundary settings
output: {...} # Output configuration
Load and Instantiate the Model¶
In [3]:
Copied!
from rompy.model import ModelRun
# Load YAML configuration
with open(yaml_file) as f:
conf = yaml.safe_load(f)
# Create ModelRun from configuration
modelrun = ModelRun(**conf)
print(f"Run ID: {modelrun.run_id}")
print(f"Output directory: {modelrun.output_dir}")
print(f"Period: {modelrun.period.start} to {modelrun.period.end}")
from rompy.model import ModelRun
# Load YAML configuration
with open(yaml_file) as f:
conf = yaml.safe_load(f)
# Create ModelRun from configuration
modelrun = ModelRun(**conf)
print(f"Run ID: {modelrun.run_id}")
print(f"Output directory: {modelrun.output_dir}")
print(f"Period: {modelrun.period.start} to {modelrun.period.end}")
Run ID: declarative_example Output directory: example-declarative-output Period: 2023-01-01 00:00:00 to 2023-01-01 12:00:00
Quality Control (Optional)¶
With the declarative approach, you can generate the workspace directly without intermediate inspection. However, for illustration, we can inspect the grid and bathymetry before generating the full workspace.
Inspect Grid¶
In [4]:
Copied!
ax = modelrun.config.grid.plot(scale="f")
ax.set_title("Model Grid")
ax = modelrun.config.grid.plot(scale="f")
ax.set_title("Model Grid")
Out[4]:
Text(0.5, 1.0, 'Model Grid')
Inspect Bathymetry¶
In [5]:
Copied!
# Generate bathymetry to a temporary directory for inspection
tmpdir = Path("tmp_bathy_check")
tmpdir.mkdir(exist_ok=True)
xfile, yfile, depfile, grid_extended = modelrun.config.bathy.get(
destdir=tmpdir,
grid=modelrun.config.grid,
)
# Load and plot
dset = xr.Dataset.xbeach.from_xbeach(depfile, grid_extended)
dset.xbeach.plot_model_bathy(grid_extended, posdwn=False)
plt.title("Model Bathymetry")
# Cleanup
shutil.rmtree(tmpdir)
# Generate bathymetry to a temporary directory for inspection
tmpdir = Path("tmp_bathy_check")
tmpdir.mkdir(exist_ok=True)
xfile, yfile, depfile, grid_extended = modelrun.config.bathy.get(
destdir=tmpdir,
grid=modelrun.config.grid,
)
# Load and plot
dset = xr.Dataset.xbeach.from_xbeach(depfile, grid_extended)
dset.xbeach.plot_model_bathy(grid_extended, posdwn=False)
plt.title("Model Bathymetry")
# Cleanup
shutil.rmtree(tmpdir)
In [6]:
Copied!
# Clean output directory if it exists
output_dir = Path(modelrun.output_dir)
if output_dir.exists():
shutil.rmtree(output_dir)
# Generate the workspace
rundir = modelrun()
# Clean output directory if it exists
output_dir = Path(modelrun.output_dir)
if output_dir.exists():
shutil.rmtree(output_dir)
# Generate the workspace
rundir = modelrun()
2026-01-11 12:51:27 [INFO] rompy.model : ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2026-01-11 12:51:27 [INFO] rompy.model : ┃ MODEL RUN CONFIGURATION ┃
2026-01-11 12:51:27 [INFO] rompy.model : ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
2026-01-11 12:51:27 [INFO] rompy.model : Run ID : declarative_example
2026-01-11 12:51:27 [INFO] rompy.model : Model Type : Config
2026-01-11 12:51:27 [INFO] rompy.model : Start Time : 2023-01-01T00:00:00
2026-01-11 12:51:27 [INFO] rompy.model : End Time : 2023-01-01T12:00:00
2026-01-11 12:51:27 [INFO] rompy.model : Duration : 12 hours
2026-01-11 12:51:27 [INFO] rompy.model : Time Interval : 1:00:00
2026-01-11 12:51:27 [INFO] rompy.model : Output Directory : example-declarative-output
2026-01-11 12:51:27 [INFO] rompy.model : ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2026-01-11 12:51:27 [INFO] rompy.model : ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
2026-01-11 12:51:27 [INFO] rompy.model :
2026-01-11 12:51:27 [INFO] root : ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2026-01-11 12:51:27 [INFO] root : ┃ MODEL CONFIGURATION (Config) ┃
2026-01-11 12:51:27 [INFO] root : ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
2026-01-11 12:51:27 [INFO] root :
2026-01-11 12:51:27 [INFO] rompy.model : Config:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: xbeach
2026-01-11 12:51:27 [INFO] rompy.model : template: /source/csiro/rompy-xbeach/src/rompy_xbeach/templates/base
2026-01-11 12:51:27 [INFO] rompy.model : checkout: main
2026-01-11 12:51:27 [INFO] rompy.model : grid:
2026-01-11 12:51:27 [INFO] rompy.model : grid_type: base
2026-01-11 12:51:27 [INFO] rompy.model : model_type: regular
2026-01-11 12:51:27 [INFO] rompy.model : ori:
2026-01-11 12:51:27 [INFO] rompy.model : x: 115.594239
2026-01-11 12:51:27 [INFO] rompy.model : y: -32.641104
2026-01-11 12:51:27 [INFO] rompy.model : crs: EPSG:4326
2026-01-11 12:51:27 [INFO] rompy.model : alfa: 347.0
2026-01-11 12:51:27 [INFO] rompy.model : dx: 10.0
2026-01-11 12:51:27 [INFO] rompy.model : dy: 15.0
2026-01-11 12:51:27 [INFO] rompy.model : nx: 230
2026-01-11 12:51:27 [INFO] rompy.model : ny: 220
2026-01-11 12:51:27 [INFO] rompy.model : crs: EPSG:28350
2026-01-11 12:51:27 [INFO] rompy.model : bathy:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: xbeach_bathy
2026-01-11 12:51:27 [INFO] rompy.model : id: data
2026-01-11 12:51:27 [INFO] rompy.model : source:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: geotiff
2026-01-11 12:51:27 [INFO] rompy.model : filename: /source/csiro/rompy-xbeach/tests/data/bathy.tif
2026-01-11 12:51:27 [INFO] rompy.model : band: 1
2026-01-11 12:51:27 [INFO] rompy.model : kwargs: {}
2026-01-11 12:51:27 [INFO] rompy.model : filter:
2026-01-11 12:51:27 [INFO] rompy.model : sort: {}
2026-01-11 12:51:27 [INFO] rompy.model : subset: {}
2026-01-11 12:51:27 [INFO] rompy.model : crop: {}
2026-01-11 12:51:27 [INFO] rompy.model : timenorm: {}
2026-01-11 12:51:27 [INFO] rompy.model : rename: {}
2026-01-11 12:51:27 [INFO] rompy.model : derived: {}
2026-01-11 12:51:27 [INFO] rompy.model : variables:
2026-01-11 12:51:27 [INFO] rompy.model : [0]: data
2026-01-11 12:51:27 [INFO] rompy.model : coords:
2026-01-11 12:51:27 [INFO] rompy.model : t: time
2026-01-11 12:51:27 [INFO] rompy.model : x: longitude
2026-01-11 12:51:27 [INFO] rompy.model : y: latitude
2026-01-11 12:51:27 [INFO] rompy.model : z: None
2026-01-11 12:51:27 [INFO] rompy.model : s: None
2026-01-11 12:51:27 [INFO] rompy.model : crop_data: True
2026-01-11 12:51:27 [INFO] rompy.model : buffer: 0.0
2026-01-11 12:51:27 [INFO] rompy.model : time_buffer:
2026-01-11 12:51:27 [INFO] rompy.model : [0]: 0
2026-01-11 12:51:27 [INFO] rompy.model : [1]: 0
2026-01-11 12:51:27 [INFO] rompy.model : interpolator:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: scipy_regular_grid
2026-01-11 12:51:27 [INFO] rompy.model : kwargs:
2026-01-11 12:51:27 [INFO] rompy.model : method: linear
2026-01-11 12:51:27 [INFO] rompy.model : fill_value: None
2026-01-11 12:51:27 [INFO] rompy.model : posdwn: False
2026-01-11 12:51:27 [INFO] rompy.model : left: 5
2026-01-11 12:51:27 [INFO] rompy.model : right: 5
2026-01-11 12:51:27 [INFO] rompy.model : extension:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: linear
2026-01-11 12:51:27 [INFO] rompy.model : depth: 25.0
2026-01-11 12:51:27 [INFO] rompy.model : slope: 0.1
2026-01-11 12:51:27 [INFO] rompy.model : interpolate_na: True
2026-01-11 12:51:27 [INFO] rompy.model : interpolate_na_kwargs: {}
2026-01-11 12:51:27 [INFO] rompy.model : input:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: data
2026-01-11 12:51:27 [INFO] rompy.model : wave: {}
2026-01-11 12:51:27 [INFO] rompy.model : wind:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: wind_station
2026-01-11 12:51:27 [INFO] rompy.model : id: wind
2026-01-11 12:51:27 [INFO] rompy.model : source:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: file
2026-01-11 12:51:27 [INFO] rompy.model : uri: /source/csiro/rompy-xbeach/tests/data/smc-params-20230101.nc
2026-01-11 12:51:27 [INFO] rompy.model : kwargs: {}
2026-01-11 12:51:27 [INFO] rompy.model : variable: None
2026-01-11 12:51:27 [INFO] rompy.model : crs: EPSG:4326
2026-01-11 12:51:27 [INFO] rompy.model : x_dim: x
2026-01-11 12:51:27 [INFO] rompy.model : y_dim: y
2026-01-11 12:51:27 [INFO] rompy.model : filter:
2026-01-11 12:51:27 [INFO] rompy.model : sort: {}
2026-01-11 12:51:27 [INFO] rompy.model : subset: {}
2026-01-11 12:51:27 [INFO] rompy.model : crop: {}
2026-01-11 12:51:27 [INFO] rompy.model : timenorm: {}
2026-01-11 12:51:27 [INFO] rompy.model : rename: {}
2026-01-11 12:51:27 [INFO] rompy.model : derived: {}
2026-01-11 12:51:27 [INFO] rompy.model : variables:
2026-01-11 12:51:27 [INFO] rompy.model : [0]: longitude
2026-01-11 12:51:27 [INFO] rompy.model : [1]: latitude
2026-01-11 12:51:27 [INFO] rompy.model : [2]: uwnd
2026-01-11 12:51:27 [INFO] rompy.model : [3]: vwnd
2026-01-11 12:51:27 [INFO] rompy.model : coords:
2026-01-11 12:51:27 [INFO] rompy.model : t: time
2026-01-11 12:51:27 [INFO] rompy.model : x: longitude
2026-01-11 12:51:27 [INFO] rompy.model : y: latitude
2026-01-11 12:51:27 [INFO] rompy.model : z: None
2026-01-11 12:51:27 [INFO] rompy.model : s: seapoint
2026-01-11 12:51:27 [INFO] rompy.model : crop_data: True
2026-01-11 12:51:27 [INFO] rompy.model : buffer: 0.0
2026-01-11 12:51:27 [INFO] rompy.model : time_buffer:
2026-01-11 12:51:27 [INFO] rompy.model : [0]: 1
2026-01-11 12:51:27 [INFO] rompy.model : [1]: 1
2026-01-11 12:51:27 [INFO] rompy.model : location: centre
2026-01-11 12:51:27 [INFO] rompy.model : sel_method: idw
2026-01-11 12:51:27 [INFO] rompy.model : sel_method_kwargs: {}
2026-01-11 12:51:27 [INFO] rompy.model : wind_vars:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: wind_vector
2026-01-11 12:51:27 [INFO] rompy.model : u: uwnd
2026-01-11 12:51:27 [INFO] rompy.model : v: vwnd
2026-01-11 12:51:27 [INFO] rompy.model : tide:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: tide_cons_grid
2026-01-11 12:51:27 [INFO] rompy.model : id: tide
2026-01-11 12:51:27 [INFO] rompy.model : source:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: oceantide
2026-01-11 12:51:27 [INFO] rompy.model : reader: read_otis_binary
2026-01-11 12:51:27 [INFO] rompy.model : kwargs:
2026-01-11 12:51:27 [INFO] rompy.model : gfile: /source/csiro/rompy-xbeach/tests/data/swaus_tide_cons/grid_m2s2n2k2k1o1p1q1mmmf
2026-01-11 12:51:27 [INFO] rompy.model : hfile: /source/csiro/rompy-xbeach/tests/data/swaus_tide_cons/h_m2s2n2k2k1o1p1q1mmmf
2026-01-11 12:51:27 [INFO] rompy.model : ufile: /source/csiro/rompy-xbeach/tests/data/swaus_tide_cons/u_m2s2n2k2k1o1p1q1mmmf
2026-01-11 12:51:27 [INFO] rompy.model : crs: EPSG:4326
2026-01-11 12:51:27 [INFO] rompy.model : x_dim: lon
2026-01-11 12:51:27 [INFO] rompy.model : y_dim: lat
2026-01-11 12:51:27 [INFO] rompy.model : filter:
2026-01-11 12:51:27 [INFO] rompy.model : sort: {}
2026-01-11 12:51:27 [INFO] rompy.model : subset: {}
2026-01-11 12:51:27 [INFO] rompy.model : crop: {}
2026-01-11 12:51:27 [INFO] rompy.model : timenorm: {}
2026-01-11 12:51:27 [INFO] rompy.model : rename: {}
2026-01-11 12:51:27 [INFO] rompy.model : derived: {}
2026-01-11 12:51:27 [INFO] rompy.model : variables:
2026-01-11 12:51:27 [INFO] rompy.model : [0]: h
2026-01-11 12:51:27 [INFO] rompy.model : coords:
2026-01-11 12:51:27 [INFO] rompy.model : t: time
2026-01-11 12:51:27 [INFO] rompy.model : x: lon
2026-01-11 12:51:27 [INFO] rompy.model : y: lat
2026-01-11 12:51:27 [INFO] rompy.model : z: None
2026-01-11 12:51:27 [INFO] rompy.model : s: None
2026-01-11 12:51:27 [INFO] rompy.model : crop_data: True
2026-01-11 12:51:27 [INFO] rompy.model : buffer: 0.0
2026-01-11 12:51:27 [INFO] rompy.model : time_buffer:
2026-01-11 12:51:27 [INFO] rompy.model : [0]: 1
2026-01-11 12:51:27 [INFO] rompy.model : [1]: 1
2026-01-11 12:51:27 [INFO] rompy.model : location: centre
2026-01-11 12:51:27 [INFO] rompy.model : sel_method: sel
2026-01-11 12:51:27 [INFO] rompy.model : sel_method_kwargs:
2026-01-11 12:51:27 [INFO] rompy.model : method: nearest
2026-01-11 12:51:27 [INFO] rompy.model : tideloc: 1
2026-01-11 12:51:27 [INFO] rompy.model : freq: 1h
2026-01-11 12:51:27 [INFO] rompy.model : physics:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: physics
2026-01-11 12:51:27 [INFO] rompy.model : wavemodel: None
2026-01-11 12:51:27 [INFO] rompy.model : advection: None
2026-01-11 12:51:27 [INFO] rompy.model : avalanching: None
2026-01-11 12:51:27 [INFO] rompy.model : bedfriction: None
2026-01-11 12:51:27 [INFO] rompy.model : cyclic: None
2026-01-11 12:51:27 [INFO] rompy.model : flow: None
2026-01-11 12:51:27 [INFO] rompy.model : gwflow: None
2026-01-11 12:51:27 [INFO] rompy.model : lwave: None
2026-01-11 12:51:27 [INFO] rompy.model : roller: None
2026-01-11 12:51:27 [INFO] rompy.model : setbathy: None
2026-01-11 12:51:27 [INFO] rompy.model : ships: None
2026-01-11 12:51:27 [INFO] rompy.model : single_dir: None
2026-01-11 12:51:27 [INFO] rompy.model : snells: None
2026-01-11 12:51:27 [INFO] rompy.model : swave: None
2026-01-11 12:51:27 [INFO] rompy.model : swrunup: None
2026-01-11 12:51:27 [INFO] rompy.model : vegetation: None
2026-01-11 12:51:27 [INFO] rompy.model : viscosity: None
2026-01-11 12:51:27 [INFO] rompy.model : wci: None
2026-01-11 12:51:27 [INFO] rompy.model : wind: None
2026-01-11 12:51:27 [INFO] rompy.model : flow_numerics: None
2026-01-11 12:51:27 [INFO] rompy.model : wave_numerics: None
2026-01-11 12:51:27 [INFO] rompy.model : constants: None
2026-01-11 12:51:27 [INFO] rompy.model : coriolis: None
2026-01-11 12:51:27 [INFO] rompy.model : sediment:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: sediment
2026-01-11 12:51:27 [INFO] rompy.model : sedtrans: None
2026-01-11 12:51:27 [INFO] rompy.model : numerics: None
2026-01-11 12:51:27 [INFO] rompy.model : morphology: None
2026-01-11 12:51:27 [INFO] rompy.model : bed_composition: None
2026-01-11 12:51:27 [INFO] rompy.model : bed_update: None
2026-01-11 12:51:27 [INFO] rompy.model : groundwater: None
2026-01-11 12:51:27 [INFO] rompy.model : q3d: None
2026-01-11 12:51:27 [INFO] rompy.model : mpi:
2026-01-11 12:51:27 [INFO] rompy.model : mmpi: None
2026-01-11 12:51:27 [INFO] rompy.model : mpiboundary: None
2026-01-11 12:51:27 [INFO] rompy.model : nmpi: None
2026-01-11 12:51:27 [INFO] rompy.model : output:
2026-01-11 12:51:27 [INFO] rompy.model : model_type: output
2026-01-11 12:51:27 [INFO] rompy.model : outputformat: netcdf
2026-01-11 12:51:27 [INFO] rompy.model : outputprecision: None
2026-01-11 12:51:27 [INFO] rompy.model : ncfilename: xboutput.nc
2026-01-11 12:51:27 [INFO] rompy.model : nrugdepth: None
2026-01-11 12:51:27 [INFO] rompy.model : rugdepth: None
2026-01-11 12:51:27 [INFO] rompy.model : timings: None
2026-01-11 12:51:27 [INFO] rompy.model : tstart: 0.0
2026-01-11 12:51:27 [INFO] rompy.model : tintc: None
2026-01-11 12:51:27 [INFO] rompy.model : tintg: None
2026-01-11 12:51:27 [INFO] rompy.model : tintm: 3600.0
2026-01-11 12:51:27 [INFO] rompy.model : tintp: None
2026-01-11 12:51:27 [INFO] rompy.model : tinth: None
2026-01-11 12:51:27 [INFO] rompy.model : writehotstart: None
2026-01-11 12:51:27 [INFO] rompy.model : tsglobal: None
2026-01-11 12:51:27 [INFO] rompy.model : tsmean: None
2026-01-11 12:51:27 [INFO] rompy.model : tspoint: None
2026-01-11 12:51:27 [INFO] rompy.model : projection: None
2026-01-11 12:51:27 [INFO] rompy.model : remdryoutput: None
2026-01-11 12:51:27 [INFO] rompy.model : rotate: None
2026-01-11 12:51:27 [INFO] rompy.model : flow_boundary:
2026-01-11 12:51:27 [INFO] rompy.model : front: abs_2d
2026-01-11 12:51:27 [INFO] rompy.model : back: abs_2d
2026-01-11 12:51:27 [INFO] rompy.model : left: neumann
2026-01-11 12:51:27 [INFO] rompy.model : right: neumann
2026-01-11 12:51:27 [INFO] rompy.model : lateralwave: None
2026-01-11 12:51:27 [INFO] rompy.model : nc: None
2026-01-11 12:51:27 [INFO] rompy.model : highcomp: None
2026-01-11 12:51:27 [INFO] rompy.model : tide_boundary:
2026-01-11 12:51:27 [INFO] rompy.model : tideloc: None
2026-01-11 12:51:27 [INFO] rompy.model : tidetype: None
2026-01-11 12:51:27 [INFO] rompy.model : zs0: 0.0
2026-01-11 12:51:27 [INFO] rompy.model : paulrevere: land
2026-01-11 12:51:27 [INFO] rompy.model : hotstart: None
2026-01-11 12:51:27 [INFO] rompy.model : tunits: None
2026-01-11 12:51:27 [INFO] rompy.model :
2026-01-11 12:51:27 [INFO] rompy.model : ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2026-01-11 12:51:27 [INFO] rompy.model : ┃ STARTING MODEL GENERATION ┃
2026-01-11 12:51:27 [INFO] rompy.model : ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
2026-01-11 12:51:27 [INFO] rompy.model : Preparing input files in example-declarative-output
2026-01-11 12:51:27 [INFO] rompy.model : Processing model configuration...
2026-01-11 12:51:27 [INFO] rompy.model : Running configuration callable...
2026-01-11 12:51:27 [INFO] rompy_xbeach.config : Generating wave boundary data
2026-01-11 12:51:27 [INFO] rompy_xbeach.config : Generating wind forcing data
2026-01-11 12:51:27 [INFO] rompy_xbeach.config : Generating tide forcing data
2026-01-11 12:51:29 [INFO] rompy.model : Rendering model templates to example-declarative-output/declarative_example...
2026-01-11 12:51:29 [INFO] rompy.core.render : Template source: /source/csiro/rompy-xbeach/src/rompy_xbeach/templates/base
2026-01-11 12:51:29 [INFO] rompy.core.render : Output directory: example-declarative-output
2026-01-11 12:51:29 [INFO] rompy.core.render : Using template version: main
2026-01-11 12:51:29 [INFO] rompy.core.render : • Locating template repository...
2026-01-11 12:51:29 [INFO] rompy.core.render : Template repository located at: /source/csiro/rompy-xbeach/src/rompy_xbeach/templates/base
2026-01-11 12:51:29 [INFO] rompy.core.render : • Generating files from template...
2026-01-11 12:51:29 [INFO] rompy.core.render : • Rendering time: 0.02 seconds
2026-01-11 12:51:29 [INFO] rompy.core.render : • Total process time: 0.03 seconds
2026-01-11 12:51:29 [INFO] rompy.core.render : • Files created: 7
2026-01-11 12:51:29 [INFO] rompy.core.render : • Output location: /source/csiro/rompy-notebooks/notebooks/xbeach/as_python_script/example-declarative-output/declarative_example
2026-01-11 12:51:29 [INFO] rompy.model :
2026-01-11 12:51:29 [INFO] rompy.model : ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2026-01-11 12:51:29 [INFO] rompy.model : ┃ MODEL GENERATION COMPLETE ┃
2026-01-11 12:51:29 [INFO] rompy.model : ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
2026-01-11 12:51:29 [INFO] rompy.model : Model files generated at: /source/csiro/rompy-notebooks/notebooks/xbeach/as_python_script/example-declarative-output/declarative_example
Inspect Generated Files¶
In [7]:
Copied!
# List generated files
modeldir = Path(modelrun.output_dir) / modelrun.run_id
print("Generated files:")
for f in sorted(modeldir.glob("*")):
print(f" {f.name}")
# List generated files
modeldir = Path(modelrun.output_dir) / modelrun.run_id
print("Generated files:")
for f in sorted(modeldir.glob("*")):
print(f" {f.name}")
Generated files: bathy.txt params.txt swan-20230101T000000.txt tide-20230101T000000-20230101T120000.txt wind-20230101T000000-20230101T120000.txt xdata.txt ydata.txt
In [8]:
Copied!
# View params.txt
params_file = modeldir / "params.txt"
print(params_file.read_text()[:2000])
# View params.txt
params_file = modeldir / "params.txt"
print(params_file.read_text()[:2000])
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% XBeach parameter settings input file %%% %%% Date: 2026-01-10 23:51:27.428827+00:00 %%% User: rguedes-XPS-13-9350 %%% Template: /source/csiro/rompy-xbeach/src/rompy_xbeach/templates/base %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% tstop = 43200.0 tunits = seconds since 2023-01-01 00:00:00 wbctype = swan bcfile = swan-20230101T000000.txt windfile = wind-20230101T000000-20230101T120000.txt zs0file = tide-20230101T000000-20230101T120000.txt tideloc = 1 tidelen = 13 front = abs_2d back = abs_2d left = neumann right = neumann zs0 = 0.0 paulrevere = land posdwn = -1 nx = 241 ny = 229 dx = 10.0 dy = 15.0 xori = 368011.2066131959 yori = 6387580.505638544 alfa = 347.0 projection = +proj=utm +zone=50 +south +ellps=GRS80 +units=m +no_defs +type=crs depfile = bathy.txt outputformat = netcdf ncfilename = xboutput.nc tstart = 0.0 tintm = 3600.0
Inspect Forcing Files¶
In [9]:
Copied!
def read_forcing(filepath, cols):
"""Read XBeach forcing file."""
df = pd.read_csv(filepath, header=None, sep=r"\s+", names=cols)
if "tsec" in cols:
df["time"] = [modelrun.period.start + timedelta(seconds=s) for s in df.tsec]
df.set_index("time", inplace=True)
return df
def read_forcing(filepath, cols):
"""Read XBeach forcing file."""
df = pd.read_csv(filepath, header=None, sep=r"\s+", names=cols)
if "tsec" in cols:
df["time"] = [modelrun.period.start + timedelta(seconds=s) for s in df.tsec]
df.set_index("time", inplace=True)
return df
Wind Forcing¶
In [10]:
Copied!
windfile = list(modeldir.glob("wind-*.txt"))
if windfile:
df_wind = read_forcing(windfile[0], ["tsec", "wspd", "wdir"])
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 5), sharex=True)
df_wind.wspd.plot(ax=ax1, marker="o")
ax1.set_ylabel("Wind Speed (m/s)")
ax1.grid(True, alpha=0.3)
df_wind.wdir.plot(ax=ax2, marker="o")
ax2.set_ylabel("Wind Direction (°)")
ax2.grid(True, alpha=0.3)
plt.suptitle("Generated Wind Forcing")
plt.tight_layout()
windfile = list(modeldir.glob("wind-*.txt"))
if windfile:
df_wind = read_forcing(windfile[0], ["tsec", "wspd", "wdir"])
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 5), sharex=True)
df_wind.wspd.plot(ax=ax1, marker="o")
ax1.set_ylabel("Wind Speed (m/s)")
ax1.grid(True, alpha=0.3)
df_wind.wdir.plot(ax=ax2, marker="o")
ax2.set_ylabel("Wind Direction (°)")
ax2.grid(True, alpha=0.3)
plt.suptitle("Generated Wind Forcing")
plt.tight_layout()
Tide Forcing¶
In [11]:
Copied!
tidefile = list(modeldir.glob("tide-*.txt"))
if tidefile:
df_tide = read_forcing(tidefile[0], ["tsec", "zs"])
fig, ax = plt.subplots(figsize=(12, 4))
df_tide.zs.plot(ax=ax, marker="o")
ax.set_ylabel("Water Level (m)")
ax.set_title("Generated Tide Forcing")
ax.grid(True, alpha=0.3)
tidefile = list(modeldir.glob("tide-*.txt"))
if tidefile:
df_tide = read_forcing(tidefile[0], ["tsec", "zs"])
fig, ax = plt.subplots(figsize=(12, 4))
df_tide.zs.plot(ax=ax, marker="o")
ax.set_ylabel("Water Level (m)")
ax.set_title("Generated Tide Forcing")
ax.grid(True, alpha=0.3)
Wave Boundary¶
In [12]:
Copied!
bcfile = list(modeldir.glob("swan-*.txt"))[0]
if bcfile:
print(f"Wave boundary file: {bcfile.name}")
print(bcfile.read_text()[:500])
bcfile = list(modeldir.glob("swan-*.txt"))[0]
if bcfile:
print(f"Wave boundary file: {bcfile.name}")
print(bcfile.read_text()[:500])
Wave boundary file: swan-20230101T000000.txt
SWAN 1 Swan standard spectral file
$ Created by wavespectra
$
LONLAT locations in spherical coordinates
1 number of locations
115.598402 -32.626715
AFREQ absolute frequencies in Hz
31 number of frequencies
0.03700
0.04070
0.04477
0.04925
0.05417
0.05959
0.06555
0.07210
0.07931
In [13]:
Copied!
from wavespectra import read_swan
ds = read_swan(bcfile)
display(ds)
ds.squeeze().spec.plot()
from wavespectra import read_swan
ds = read_swan(bcfile)
display(ds)
ds.squeeze().spec.plot()
<xarray.Dataset> Size: 6kB
Dimensions: (time: 1, lat: 1, lon: 1, freq: 31, dir: 24)
Coordinates:
* time (time) datetime64[ns] 8B 2026-01-11T12:51:00
* lat (lat) float64 8B -32.63
* lon (lon) float64 8B 115.6
* freq (freq) float64 248B 0.037 0.0407 0.04477 ... 0.5336 0.5869 0.6456
* dir (dir) float64 192B 0.0 15.0 30.0 45.0 ... 300.0 315.0 330.0 345.0
Data variables:
efth (time, lat, lon, freq, dir) float64 6kB 0.0 0.0 0.0 ... 0.0 0.0 0.0Out[13]:
<matplotlib.contour.QuadContourSet at 0x7af69ae1a300>
Summary¶
This notebook demonstrated the declarative workflow for XBeach:
- Define configuration in YAML - All settings in one file
- Load with ModelRun - Validate and instantiate
- Quality control - Inspect grid and bathymetry
- Generate workspace - Create all XBeach input files
Advantages of Declarative Approach¶
| Aspect | Benefit |
|---|---|
| Version control | Track configuration changes in git |
| Reproducibility | Same YAML = same model setup |
| Automation | Easy to use in scripts and pipelines |
| Sharing | Share configurations with collaborators |
| Validation | Pydantic validates all fields |
Next Steps¶
- See Example Procedural for step-by-step Python approach
- See component tutorials for detailed parameter options
- See data interface tutorials for forcing options
Running XBeach¶
cd example-declarative-output/declarative_example
xbeach params.txt