Physics Component Tutorial¶
This tutorial introduces the Physics component in rompy-xbeach, which controls wave propagation, flow computation, bed friction, and other physical processes in XBeach.
What You'll Learn¶
- What components are and why they exist
- How to configure the Physics component
- Wave model selection (Surfbeat, Stationary, Non-hydrostatic)
- Bed friction formulations
- Numerical parameters and advanced options
- How validation and constraints work
Prerequisites¶
- Basic familiarity with XBeach concepts
- rompy-xbeach installed (
pip install rompy-xbeach)
1. Introduction to Components¶
What Are Components?¶
In rompy-xbeach, components are Pydantic models that group related XBeach parameters
together. Instead of managing ~250 flat parameters in a params.txt file, components
provide:
- Discoverability: Find related parameters in one place
- Validation: Catch errors before running XBeach
- Type safety: IDE autocomplete and type hints
- Documentation: Built-in descriptions for every parameter
Available Components¶
| Component | Purpose |
|---|---|
Physics |
Wave models, flow, friction, viscosity, numerics |
Sediment |
Sediment transport, morphology, bed composition |
Output |
Output format, timing, variables |
FlowBoundaryConditions |
Flow boundary types |
TideBoundaryConditions |
Tide/water level boundaries |
Hotstart |
Initialize from previous simulation |
Mpi |
Parallel execution settings |
How Components Integrate with Config¶
Components are fields on the main Config class:
from rompy_xbeach import Config
config = Config(
grid=..., # Grid definition
bathy=..., # Bathymetry data
physics=Physics(), # <-- Physics component
sediment=Sediment(),
output=Output(),
# ...
)
When you call config.generate(), each component's parameters are written to params.txt.
from rompy_xbeach.components.physics import Physics
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)
max_width = max(len(filename), max_content_width)
box_width = max_width + 2 # +2 for padding on both sides
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():
content.append(f"{key} = {value}")
print_params(content)
# Create Physics with all defaults
physics = Physics()
show_params(physics)
┌────────────┐ │ params.txt │ ├────────────┤ │ │ └────────────┘
An empty Physics() produces no output parameters - XBeach will use its built-in defaults.
This is intentional: only specify what you want to change.
XBeach Default Behavior¶
When you don't specify a parameter, XBeach uses sensible defaults:
| Parameter | Default | Meaning |
|---|---|---|
wavemodel |
surfbeat | Wave-group resolving mode |
flow |
1 (enabled) | Flow computation on |
swave |
1 (enabled) | Short waves on |
lwave |
1 (enabled) | Long wave forcing on |
bedfriction |
manning | Manning friction formulation |
bedfriccoef |
0.02 | Manning coefficient |
3. Wave Models¶
XBeach has three wave models, each suited for different applications. The choice of wave model is the most important physics decision.
3.1 Surfbeat Mode (Default)¶
Best for: Most coastal applications, storm impact, dune erosion
Surfbeat mode resolves:
- Wave groups (short wave envelope)
- Infragravity waves (long waves bound to wave groups)
- Wave-driven currents
It does NOT resolve individual waves - instead it tracks wave energy.
from rompy_xbeach.components.physics.wavemodel import Surfbeat
# Explicit surfbeat configuration
physics_surfbeat = Physics(
wavemodel=Surfbeat()
)
print("Surfbeat mode:")
show_params(physics_surfbeat)
Surfbeat mode: ┌──────────────────────┐ │ params.txt │ ├──────────────────────┤ │ wavemodel = surfbeat │ └──────────────────────┘
3.2 Stationary Mode¶
Best for: Quick calculations, mild conditions, wave transformation studies
Stationary mode:
- Solves time-averaged wave equations
- No infragravity waves
- Much faster than surfbeat
- Good for small waves or preliminary studies
from rompy_xbeach.components.physics.wavemodel import Stationary
physics_stationary = Physics(
wavemodel=Stationary()
)
show_params(physics_stationary)
┌────────────────────────┐ │ params.txt │ ├────────────────────────┤ │ wavemodel = stationary │ └────────────────────────┘
3.3 Non-Hydrostatic Mode¶
Best for: Laboratory studies, detailed wave-by-wave analysis, wave overtopping
Non-hydrostatic mode:
- Resolves individual waves
- Phase-resolving (not phase-averaged)
- Most computationally expensive
- Required for wave-resolving simulations
Important: When using non-hydrostatic mode, you must disable short waves (swave=False).
from rompy_xbeach.components.physics.wavemodel import Nonh
physics_nonh = Physics(
wavemodel=Nonh(),
swave=False, # Required for non-hydrostatic mode
)
show_params(physics_nonh)
┌──────────────────┐ │ params.txt │ ├──────────────────┤ │ wavemodel = nonh │ │ swave = 0 │ └──────────────────┘
Wave Model Comparison¶
| Feature | Stationary | Surfbeat | Non-hydrostatic |
|---|---|---|---|
| Individual waves | No | No | Yes |
| Wave groups | No | Yes | Yes |
| Infragravity waves | No | Yes | Yes |
| Computation speed | Fast | Medium | Slow |
| Typical use | Mild conditions | Storm impact | Lab studies |
4. Breaker Formulations¶
Each wave model uses specific breaker formulations to calculate wave dissipation. The breaker model controls how waves break and dissipate energy.
4.1 Surfbeat Breakers¶
Surfbeat mode supports Roelvink-family breakers:
from rompy_xbeach.components.physics.wavemodel import Surfbeat, Roelvink1, Roelvink2, RoelvinkDaly
# Roelvink (1993) - the classic formulation
physics_roelvink1 = Physics(
wavemodel=Surfbeat(
breaktype=Roelvink1(
gamma=0.55, # Breaker parameter (default: 0.46)
alpha=1.0, # Dissipation coefficient (default: 1.38)
n=10.0, # Power in dissipation (default: 10.0)
)
)
)
show_params(physics_roelvink1)
┌──────────────────────┐ │ params.txt │ ├──────────────────────┤ │ wavemodel = surfbeat │ │ break = roelvink1 │ │ alpha = 1.0 │ │ gamma = 0.55 │ │ n = 10.0 │ └──────────────────────┘
# Roelvink-Daly - includes breaking cessation
physics_daly = Physics(
wavemodel=Surfbeat(
breaktype=RoelvinkDaly(
gamma2=0.3, # End-of-breaking parameter
)
)
)
show_params(physics_daly)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ wavemodel = surfbeat │ │ break = roelvink_daly │ │ gamma2 = 0.3 │ └───────────────────────┘
4.2 Stationary Breakers¶
Stationary mode uses Baldock or Janssen breakers:
from rompy_xbeach.components.physics.wavemodel import Stationary, Baldock, Janssen
physics_baldock = Physics(
wavemodel=Stationary(
breaktype=Baldock(
gamma=0.5, # Breaker parameter
)
)
)
show_params(physics_baldock)
┌────────────────────────┐ │ params.txt │ ├────────────────────────┤ │ wavemodel = stationary │ │ break = baldock │ │ gamma = 0.5 │ └────────────────────────┘
5. Bed Friction¶
Bed friction controls energy dissipation at the seabed. XBeach supports several friction formulations, each with different physical interpretations.
5.1 Available Friction Formulations¶
| Formulation | Coefficient | Typical Values | Use Case |
|---|---|---|---|
Manning |
n (s/m^1/3) | 0.01 - 0.03 | General purpose (default) |
Chezy |
C (m^1/2/s) | 40 - 70 | Uniform flow |
Cf |
cf (-) | 0.001 - 0.01 | Dimensionless |
WhiteColebrook |
ks (m) | 0.01 - 0.15 | Roughness-based |
WhiteColebrookGrainsize |
(from D90) | - | Sediment-based |
from rompy_xbeach.components.physics.friction import (
Manning, Chezy, Cf, WhiteColebrook, WhiteColebrookGrainsize
)
# Manning friction (XBeach default)
physics_manning = Physics(
bedfriction=Manning(bedfriccoef=0.02)
)
show_params(physics_manning)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ bedfriction = manning │ │ bedfriccoef = 0.02 │ └───────────────────────┘
# Chezy friction
physics_chezy = Physics(
bedfriction=Chezy(bedfriccoef=55.0)
)
show_params(physics_chezy)
┌─────────────────────┐ │ params.txt │ ├─────────────────────┤ │ bedfriction = chezy │ │ bedfriccoef = 55.0 │ └─────────────────────┘
# White-Colebrook (roughness-based)
physics_wc = Physics(
bedfriction=WhiteColebrook(bedfriccoef=0.05) # ks in meters
)
show_params(physics_wc)
┌───────────────────────────────┐ │ params.txt │ ├───────────────────────────────┤ │ bedfriction = white-colebrook │ │ bedfriccoef = 0.05 │ └───────────────────────────────┘
# White-Colebrook from grain size (no coefficient needed)
# Friction is computed from sediment D90
physics_wcg = Physics(
bedfriction=WhiteColebrookGrainsize()
)
show_params(physics_wcg)
┌─────────────────────────────────────────┐ │ params.txt │ ├─────────────────────────────────────────┤ │ bedfriction = white-colebrook-grainsize │ └─────────────────────────────────────────┘
5.2 Friction Limits¶
Manning and White-Colebrook formulations support min/max friction limits to prevent unrealistic values in very shallow water:
physics_manning_limits = Physics(
bedfriction=Manning(
bedfriccoef=0.02,
mincf=0.001, # Minimum dimensionless friction
maxcf=0.1, # Maximum dimensionless friction
)
)
show_params(physics_manning_limits)
┌───────────────────────┐ │ params.txt │ ├───────────────────────┤ │ bedfriction = manning │ │ bedfriccoef = 0.02 │ │ mincf = 0.001 │ │ maxcf = 0.1 │ └───────────────────────┘
6. Viscosity¶
Horizontal viscosity accounts for momentum exchange at sub-grid scales. XBeach uses the Smagorinsky model by default.
from rompy_xbeach.components.physics.friction import Viscosity
# Enable viscosity with Smagorinsky model (default)
physics_visc_smag = Physics(
viscosity=Viscosity(
smag=True, # Use Smagorinsky model
nuh=0.1, # Smagorinsky constant (dimensionless)
)
)
show_params(physics_visc_smag)
┌───────────────┐ │ params.txt │ ├───────────────┤ │ viscosity = 1 │ │ smag = 1 │ │ nuh = 0.1 │ └───────────────┘
# Constant viscosity (disable Smagorinsky)
physics_visc_const = Physics(
viscosity=Viscosity(
smag=False, # Disable Smagorinsky
nuh=1.0, # Constant viscosity in m²/s
)
)
show_params(physics_visc_const)
┌───────────────┐ │ params.txt │ ├───────────────┤ │ viscosity = 1 │ │ smag = 0 │ │ nuh = 1.0 │ └───────────────┘
Disabling Viscosity¶
You can disable viscosity entirely by setting viscosity=False:
physics_no_visc = Physics(
viscosity=False
)
show_params(physics_no_visc)
┌───────────────┐ │ params.txt │ ├───────────────┤ │ viscosity = 0 │ └───────────────┘
7.1 Flow Numerics¶
These parameters control the shallow water equation solver:
from rompy_xbeach.components.physics.numerics import FlowNumerics
physics_flow_num = Physics(
flow_numerics=FlowNumerics(
eps=0.005, # Wet/dry threshold depth (m)
hmin=0.1, # Min depth for Stokes drift (m)
cfl=0.7, # CFL number for stability
secorder=True, # Second-order advection
)
)
show_params(physics_flow_num)
┌──────────────┐ │ params.txt │ ├──────────────┤ │ eps = 0.005 │ │ hmin = 0.1 │ │ secorder = 1 │ │ cfl = 0.7 │ └──────────────┘
7.2 Wave Numerics¶
These parameters control the wave action balance solver:
from rompy_xbeach.components.physics.numerics import WaveNumerics
physics_wave_num = Physics(
wave_numerics=WaveNumerics(
scheme="warmbeam", # Numerical scheme (default)
maxiter=500, # Max iterations for stationary solver
maxerror=0.0005, # Convergence criterion (m)
)
)
show_params(physics_wave_num)
┌───────────────────┐ │ params.txt │ ├───────────────────┤ │ scheme = warmbeam │ │ maxiter = 500 │ │ maxerror = 0.0005 │ └───────────────────┘
8. Process Switches¶
XBeach has many physical processes that can be enabled or disabled. Most are enabled by default.
# Explicitly control process switches
physics_switches = Physics(
# Wave processes
swave=True, # Short waves (default: on)
lwave=True, # Long wave forcing (default: on)
# Flow processes
flow=True, # Flow computation (default: on)
advection=True, # Advection in flow (default: on)
# Other processes
avalanching=True, # Slope avalanching (default: on)
wind=False, # Wind forcing (default: on) - disabled here
gwflow=False, # Groundwater (default: off)
ships=False, # Ship waves (default: off)
)
show_params(physics_switches)
┌─────────────────┐ │ params.txt │ ├─────────────────┤ │ advection = 1 │ │ avalanching = 1 │ │ flow = 1 │ │ gwflow = 0 │ │ lwave = 1 │ │ ships = 0 │ │ swave = 1 │ │ wind = 0 │ └─────────────────┘
Default-Enabled vs Default-Disabled Processes¶
| Process | Default | Description |
|---|---|---|
swave |
On | Short wave action balance |
lwave |
On | Long wave forcing |
flow |
On | Flow computation |
advection |
On | Advection in momentum |
avalanching |
On | Slope failure |
wind |
On | Wind forcing |
viscosity |
On | Horizontal viscosity |
gwflow |
Off | Groundwater flow |
ships |
Off | Ship-induced waves |
vegetation |
Off | Wave-vegetation interaction |
wci |
Off | Wave-current interaction |
9. Validation and Constraints¶
rompy-xbeach validates your configuration and warns about potential issues.
9.1 Type Validation¶
Parameters are validated against their expected types and ranges:
def print_warning(text):
print(f"\033[48;5;224m\033[30m {text} \033[0m")
from pydantic import ValidationError
# This will raise an error - gamma must be between 0.4 and 0.9
try:
invalid_physics = Physics(
wavemodel=Surfbeat(
breaktype=Roelvink1(gamma=2.0) # Invalid: too high
)
)
except ValidationError as e:
print_warning(f"{e.errors()[0]['msg']}")
print("\n(Validation error caught)\n")
Input should be less than or equal to 0.9
(Validation error caught)
9.2 Cross-Parameter Validation¶
Some parameters have dependencies. For example, non-hydrostatic mode
requires swave=False:
import logging
# Enable logging to see warnings
logging.basicConfig(level=logging.WARNING)
# This will generate a warning
physics_nonh_warning = Physics(
wavemodel=Nonh(),
swave=True, # This conflicts with non-hydrostatic mode!
)
print("\n(A warning was logged above)")
2026-01-10 15:25:11 [WARNING] rompy_xbeach.components.physics.physics: ! Parameter 'swave' should not be True when using Nonh wavemodel. XBeach requires swave=0 for non-hydrostatic mode.
(A warning was logged above)
9.3 Mutual Exclusivity¶
Some parameters are mutually exclusive:
# Friction coefficient vs friction file - can't specify both
try:
from rompy_xbeach.types import XBeachDataBlob
invalid_friction = Manning(
bedfriccoef=0.02,
bedfricfile=XBeachDataBlob(source="friction.dep"), # Can't have both!
)
except ValidationError as e:
print_warning(f"{e.errors()[0]['msg']}")
print("\n(Mutual exclusivity error caught)")
Value error, Only one of bedfriccoef or bedfricfile can be specified.
(Mutual exclusivity error caught)
10. Physical Constants¶
You can override physical constants if needed (e.g., for laboratory experiments):
from rompy_xbeach.components.physics.constants import PhysicalConstants, Coriolis
physics_constants = Physics(
constants=PhysicalConstants(
g=9.81, # Gravitational acceleration (m/s²)
rho=1025.0, # Water density (kg/m³)
depthscale=1, # Depth scale factor (for lab experiments)
),
coriolis=Coriolis(
lat=-33.9, # Latitude for Coriolis force
)
)
show_params(physics_constants)
┌──────────────────┐ │ params.txt │ ├──────────────────┤ │ lat = -33.9 │ │ depthscale = 1.0 │ │ g = 9.81 │ │ rho = 1025.0 │ └──────────────────┘
# Storm impact simulation configuration
physics_storm = Physics(
# Wave model: surfbeat for storm conditions
wavemodel=Surfbeat(
breaktype=Roelvink1(
gamma=0.55,
alpha=1.0,
)
),
# Bed friction: Manning with typical sandy beach value
bedfriction=Manning(
bedfriccoef=0.02,
mincf=0.001,
),
# Viscosity: Smagorinsky subgrid model
viscosity=Viscosity(
smag=True,
nuh=0.1,
),
# Flow numerics: slightly conservative CFL
flow_numerics=FlowNumerics(
cfl=0.7,
eps=0.005,
),
# Process switches
flow=True,
swave=True,
lwave=True,
avalanching=True,
wind=True,
)
show_params(physics_storm)
┌────────────────────┐ │ params.txt │ ├────────────────────┤ │ alpha = 1.0 │ │ gamma = 0.55 │ │ avalanching = 1 │ │ bedfriccoef = 0.02 │ │ mincf = 0.001 │ │ flow = 1 │ │ lwave = 1 │ │ swave = 1 │ │ wind = 1 │ │ viscosity = 1 │ │ smag = 1 │ │ nuh = 0.1 │ │ eps = 0.005 │ │ cfl = 0.7 │ └────────────────────┘
# Example of how Physics integrates with Config
# (This is illustrative - would need grid/bathy to actually run)
config_example = """
from rompy_xbeach import Config
from rompy_xbeach.components.physics import Physics
from rompy_xbeach.components.physics.wavemodel import Surfbeat
from rompy_xbeach.components.physics.friction import Manning
from rompy_xbeach.components.sediment import Sediment
from rompy_xbeach.components.output import Output
config = Config(
project="storm_impact",
grid=grid, # Your grid definition
bathy=bathy, # Your bathymetry data
# Physics configuration
physics=Physics(
wavemodel=Surfbeat(),
bedfriction=Manning(bedfriccoef=0.02),
flow=True,
swave=True,
),
# Sediment transport (separate component)
sediment=Sediment(
morphology=True,
morfac=10,
),
# Output configuration
output=Output(
outputformat="netcdf",
tintg=3600,
),
)
# Generate model files
config.generate(destdir="./model_run")
"""
print("Config integration example:")
print(config_example)
Config integration example:
from rompy_xbeach import Config
from rompy_xbeach.components.physics import Physics
from rompy_xbeach.components.physics.wavemodel import Surfbeat
from rompy_xbeach.components.physics.friction import Manning
from rompy_xbeach.components.sediment import Sediment
from rompy_xbeach.components.output import Output
config = Config(
project="storm_impact",
grid=grid, # Your grid definition
bathy=bathy, # Your bathymetry data
# Physics configuration
physics=Physics(
wavemodel=Surfbeat(),
bedfriction=Manning(bedfriccoef=0.02),
flow=True,
swave=True,
),
# Sediment transport (separate component)
sediment=Sediment(
morphology=True,
morfac=10,
),
# Output configuration
output=Output(
outputformat="netcdf",
tintg=3600,
),
)
# Generate model files
config.generate(destdir="./model_run")
Summary¶
Key Takeaways¶
Start simple: Use
Physics()for defaults, add only what you need to changeWave model choice is the most important decision:
Surfbeat: Most coastal applications (default)Stationary: Quick calculations, mild conditionsNonh: Wave-resolving, laboratory studies
Bed friction controls energy dissipation:
Manning: General purpose (default)WhiteColebrookGrainsize: Automatic from sediment
Validation catches errors early - trust the error messages
Components group related parameters - explore with IDE autocomplete
Next Steps¶
- See the Sediment Tutorial for morphology configuration
- See the Output Tutorial for output configuration
- See the Full Example for a complete workflow