# # XBeach Physics Configuration Tutorial
#
# A comprehensive guide to configuring physical processes in XBeach using rompy-xbeach.
# We'll start with simple switches and progressively build to complex component models.
Overview¶
XBeach physics configuration has two types of parameters:
Simple switches/values: Boolean flags or single numeric values
- Example:
flow=True,morphology=False,eps=0.01
- Example:
Component models: Groups of related parameters organized into classes
- Example:
wavemodel=Surfbeat(...),bedfriction=Manning(...) - These use discriminated unions for type safety
- Example:
This architecture makes it easy to configure related parameters together while maintaining flexibility for simple cases.
Setup¶
from rompy_xbeach.components.physics.physics import Physics
print("Physics component loaded successfully!")
Physics component loaded successfully!
Part 1: Simple Configuration¶
Start with basic process switches and simple parameters.
Example 1.1: Minimal Configuration¶
Use XBeach defaults for everything.
# Most minimal - all defaults
physics = Physics()
print("Minimal physics configuration:")
print(f" All parameters use XBeach defaults")
print(f" Model type: {physics.model_type}")
# Serialize to see what gets written to params.txt
params = physics.get(destdir=None)
print(f"\nParameters written to params.txt: {params}")
print(" (Empty dict means all XBeach defaults)")
Minimal physics configuration:
All parameters use XBeach defaults
Model type: physics
Parameters written to params.txt: {}
(Empty dict means all XBeach defaults)
Example 1.2: Simple Process Switches¶
Turn processes on/off with boolean flags.
# Basic process control
physics = Physics(
flow=True, # Enable flow (default: True)
avalanching=True, # Enable avalanching (default: True)
gwflow=False, # Disable groundwater (default: False)
wind=True, # Enable wind (default: True)
advection=True, # Enable advection (default: True)
)
print("\nSimple switches configuration:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Simple switches configuration: advection = 1 avalanching = 1 flow = 1 gwflow = 0 wind = 1
Example 1.3: Simple Numeric Parameters¶
Some parameters are just single values.
# Note: Most numeric parameters are in component models (see Part 2)
# Here we show simple turbulence parameter
physics = Physics(
turb="wave_averaged", # Turbulence model (default: wave_averaged)
lwave=True, # Long wave forcing (default: True)
swave=True, # Short waves (default: True)
)
print("\nPhysics with turbulence configuration:")
print(f" turb = {physics.turb}")
print(f" lwave = {physics.lwave}")
print(f" swave = {physics.swave}")
Physics with turbulence configuration: turb = wave_averaged lwave = True swave = True
Part 2: Component Models¶
Component models group related parameters together. They use discriminated unions for type safety - XBeach knows which formulation you're using.
Wave Models¶
XBeach has three wave models: Surfbeat, Stationary, and Non-hydrostatic.
Surfbeat Mode (Default)¶
For infragravity waves and wave groups.
from rompy_xbeach.components.physics.wavemodel import Surfbeat
# Basic surfbeat
physics = Physics(
wavemodel=Surfbeat() # Uses all defaults
)
print("\nSurfbeat wave model (defaults):")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Surfbeat wave model (defaults): wavemodel = surfbeat
Surfbeat with Wave Breaking¶
Configure wave breaking formulation using the 'break' alias.
from rompy_xbeach.components.physics.wavemodel import Roelvink1
# Surfbeat with Roelvink1 breaking
physics = Physics(
wavemodel=Surfbeat(
**{"break": Roelvink1( # Use 'break' alias (breaktype is the field name)
gamma=0.55, # Breaking parameter
alpha=1.0, # Wave dissipation coefficient
n=10.0, # Power in dissipation model
)}
)
)
print("\nSurfbeat with Roelvink1 breaking:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Surfbeat with Roelvink1 breaking: wavemodel = surfbeat break = roelvink1 alpha = 1.0 gamma = 0.55 n = 10.0
Stationary Mode¶
For time-invariant wave conditions.
from rompy_xbeach.components.physics.wavemodel import Stationary
physics = Physics(
wavemodel=Stationary()
)
print("\nStationary wave model:")
params = physics.get(destdir=None)
print(f" wavemodel = {params.get('wavemodel', 'surfbeat (default)')}")
Stationary wave model: wavemodel = stationary
Non-Hydrostatic Mode¶
For wave-resolving simulations.
from rompy_xbeach.components.physics.wavemodel import Nonh
# Non-hydrostatic mode requires swave=False
physics = Physics(
wavemodel=Nonh(
nhq3d=True, # Use reduced two-layer model
),
swave=False, # REQUIRED with nonh
)
print("\nNon-hydrostatic wave model:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Non-hydrostatic wave model: wavemodel = nonh nhq3d = 1 swave = 0
Bed Friction Models¶
Multiple friction formulations available.
Manning Friction¶
from rompy_xbeach.components.physics.friction import Manning
physics = Physics(
bedfriction=Manning(
bedfriccoef=0.02, # Manning coefficient
)
)
print("\nManning friction:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Manning friction: bedfriction = manning bedfriccoef = 0.02
Chézy Friction¶
from rompy_xbeach.components.physics.friction import Chezy
physics = Physics(
bedfriction=Chezy(
bedfriccoef=55.0, # Chézy coefficient
)
)
print("\nChézy friction:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Chézy friction: bedfriction = chezy bedfriccoef = 55.0
Constant Cf¶
from rompy_xbeach.components.physics.friction import Cf
physics = Physics(
bedfriction=Cf(
bedfriccoef=0.003, # Friction coefficient
)
)
print("\nConstant Cf friction:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Constant Cf friction: bedfriction = cf bedfriccoef = 0.003
White-Colebrook¶
from rompy_xbeach.components.physics.friction import WhiteColebrook
physics = Physics(
bedfriction=WhiteColebrook(
bedfriccoef=0.01, # Nikuradse roughness height (m)
)
)
print("\nWhite-Colebrook friction:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
White-Colebrook friction: bedfriction = white-colebrook bedfriccoef = 0.01
Roller Model¶
Surface roller energy balance.
from rompy_xbeach.components.physics.wavemodel import Roller
# Enable roller with parameters
physics = Physics(
roller=Roller(
beta=0.1, # Breaker slope coefficient
)
)
print("\nRoller model:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
# Can also use simple boolean
physics_simple = Physics(
roller=True # Enable with defaults
)
print("\nRoller (simple boolean):")
print(f" roller = {physics_simple.roller}")
Roller model: roller = 1 beta = 0.1 Roller (simple boolean): roller = True
Vegetation¶
Wave and flow interaction with vegetation.
from rompy_xbeach.components.physics.vegetation import Vegetation
# Vegetation requires external files (veggiefile and veggiemapfile)
# For simple cases, just enable it with a boolean
physics = Physics(
vegetation=True # Enable vegetation (files specified elsewhere)
)
print("\nVegetation enabled:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
# Or use Vegetation component for advanced options
physics = Physics(
vegetation=Vegetation(
nveg=2, # Number of vegetation species
vegcanflo=True, # Include in-canopy flow
vegnonlin=False, # Non-linear wave effects
# veggiefile and veggiemapfile would be specified here
)
)
print("\nVegetation with options:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Vegetation enabled: vegetation = 1 Vegetation with options: vegetation = 1 nveg = 2 vegcanflo = 1 vegnonlin = 0
Wave-Current Interaction¶
Enhanced wave-current interaction model.
from rompy_xbeach.components.physics.wci import WaveCurrentInteraction
physics = Physics(
wci=WaveCurrentInteraction(
cats=5.0, # Time scale for wave-current interaction (s)
hwci=0.15, # Minimum depth for WCI (m)
hwcimax=80.0, # Maximum depth for WCI (m)
)
)
print("\nWave-current interaction:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
# Can also use simple boolean
physics_simple = Physics(
wci=True # Enable with defaults
)
Wave-current interaction: wci = 1 cats = 5.0 hwci = 0.15 hwcimax = 80.0
Part 3: Parameter Groups¶
Some parameters are organized into logical groups.
Horizontal Viscosity¶
from rompy_xbeach.components.physics.friction import HorizontalViscosity
physics = Physics(
viscosity=True, # Enable viscosity
viscosity_params=HorizontalViscosity(
nuh=0.1, # Horizontal background viscosity (m²/s)
nuhv=2.0, # Horizontal viscosity for velocity (m²/s)
smag=True, # Use Smagorinsky model
gamma_turb=1.2, # Calibration factor for turbulence
)
)
print("\nHorizontal viscosity:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Horizontal viscosity: viscosity = 1 smag = 1 nuh = 0.1 nuhv = 2.0 gamma_turb = 1.2
Flow Numerics¶
from rompy_xbeach.components.physics.numerics import FlowNumerics
physics = Physics(
flow=True,
flow_numerics=FlowNumerics(
eps=0.005, # Threshold water depth (m)
hmin=0.05, # Minimum water depth (m)
deltahmin=0.1, # Minimum depth for velocity points (m)
umin=0.01, # Threshold velocity (m/s)
secorder=False, # Second-order corrections
)
)
print("\nFlow numerics:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Flow numerics: flow = 1 eps = 0.005 hmin = 0.05 secorder = 0 umin = 0.01 deltahmin = 0.1
Wave Numerics¶
from rompy_xbeach.components.physics.numerics import WaveNumerics
physics = Physics(
wave_numerics=WaveNumerics(
scheme="warmbeam", # Numerical scheme
maxiter=500, # Maximum iterations
maxerror=0.0005, # Maximum error
wavint=3600.0, # Wave interval (s)
)
)
print("\nWave numerics:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Wave numerics: scheme = warmbeam maxiter = 500 maxerror = 0.0005 wavint = 3600.0
Non-Hydrostatic Numerics¶
from rompy_xbeach.components.physics.numerics import NonHydrostaticNumerics
physics = Physics(
nonh=True,
swave=False,
nonhydrostatic_numerics=NonHydrostaticNumerics(
solver="tridiag", # Solver type
solver_acc=0.005, # Solver accuracy
solver_maxit=50, # Maximum iterations
maxbrsteep=0.4, # Maximum breaking steepness
reformsteep=0.33, # Wave reformation steepness
)
)
print("\nNon-hydrostatic numerics:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Non-hydrostatic numerics: nonh = 1 swave = 0 solver = tridiag solver_acc = 0.005 solver_maxit = 50 maxbrsteep = 0.4 reformsteep = 0.33
Physical Constants¶
from rompy_xbeach.components.physics.constants import PhysicalConstants
physics = Physics(
constants=PhysicalConstants(
g=9.81, # Gravitational acceleration (m/s²)
rho=1025.0, # Water density (kg/m³)
depthscale=1.0, # Depth scale factor
)
)
print("\nPhysical constants:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Physical constants: depthscale = 1.0 g = 9.81 rho = 1025.0
Coriolis Force¶
from rompy_xbeach.components.physics.constants import Coriolis
physics = Physics(
coriolis=Coriolis(
lat=-32.0, # Latitude (degrees)
wearth=True, # Include earth rotation
)
)
print("\nCoriolis force:")
params = physics.get(destdir=None)
for key, value in params.items():
print(f" {key} = {value}")
Coriolis force: lat = -32.0 wearth = 1.0
Part 4: Complete Configurations¶
Real-world examples combining multiple components.
Example 4.1: Coastal Wave Simulation¶
Surfbeat mode with full wave-flow interaction.
physics = Physics(
# Process switches
flow=True,
avalanching=True,
wind=True,
# Wave model
wavemodel=Surfbeat(
**{"break": Roelvink1(
gamma=0.55,
alpha=1.0,
n=10.0,
)}
),
# Bed friction
bedfriction=Manning(
bedfriccoef=0.02,
),
# Roller model
roller=Roller(
beta=0.1,
),
# Horizontal viscosity
viscosity_params=HorizontalViscosity(
nuh=0.1,
smag=True,
),
# Flow numerics
flow_numerics=FlowNumerics(
eps=0.005,
hmin=0.05,
),
)
print("\nCoastal wave configuration:")
params = physics.get(destdir=None)
print(f" Total parameters: {len(params)}")
for key, value in params.items():
print(f" {key} = {value}")
Coastal wave configuration: Total parameters: 13 alpha = 1.0 gamma = 0.55 n = 10.0 avalanching = 1 bedfriccoef = 0.02 flow = 1 wind = 1 roller = 1 beta = 0.1 smag = 1 nuh = 0.1 eps = 0.005 hmin = 0.05
Example 4.2: Wave-Resolving Simulation¶
Non-hydrostatic mode for detailed wave dynamics.
physics = Physics(
# Non-hydrostatic mode
nonh=True,
swave=False, # Required
flow=True,
# Wave model
wavemodel=Nonh(
nhq3d=True,
),
# Bed friction
bedfriction=Chezy(
bedfriccoef=55.0,
),
# Non-hydrostatic solver
nonhydrostatic_numerics=NonHydrostaticNumerics(
solver="tridiag",
solver_acc=0.005,
maxbrsteep=0.4,
),
# Flow numerics
flow_numerics=FlowNumerics(
eps=0.01,
hmin=0.1,
),
)
print("\nWave-resolving configuration:")
params = physics.get(destdir=None)
print(f" Total parameters: {len(params)}")
for key, value in params.items():
print(f" {key} = {value}")
Wave-resolving configuration: Total parameters: 10 nhq3d = 1 bedfriccoef = 55.0 flow = 1 nonh = 1 swave = 0 solver = tridiag solver_acc = 0.005 maxbrsteep = 0.4 eps = 0.01 hmin = 0.1
Example 4.3: Coastal Vegetation Study¶
Wave attenuation through vegetation.
physics = Physics(
# Enable vegetation (simple boolean)
vegetation=True,
# Wave model
wavemodel=Surfbeat(
**{"break": Roelvink1(gamma=0.55)}
),
# Bed friction
bedfriction=Manning(
bedfriccoef=0.03, # Higher for vegetated bed
),
# Wave-current interaction
wci=WaveCurrentInteraction(
cats=5.0,
hwci=0.1,
),
)
print("\nVegetation study configuration:")
params = physics.get(destdir=None)
print(f" Total parameters: {len(params)}")
for key, value in params.items():
print(f" {key} = {value}")
Vegetation study configuration: Total parameters: 6 gamma = 0.55 bedfriccoef = 0.03 vegetation = 1 wci = 1 cats = 5.0 hwci = 0.1
Example 4.4: Storm Surge with Coriolis¶
Large-scale coastal flooding with earth rotation.
physics = Physics(
# Process switches
flow=True,
wind=True,
# Wave model
wavemodel=Surfbeat(),
# Bed friction
bedfriction=Manning(
bedfriccoef=0.02,
),
# Coriolis force
coriolis=Coriolis(
lat=-32.0, # Southern hemisphere
wearth=True,
),
# Physical constants
constants=PhysicalConstants(
rho=1025.0, # Seawater density
),
# Viscosity
viscosity_params=HorizontalViscosity(
nuh=0.5, # Higher for large-scale
smag=True,
),
)
print("\nStorm surge configuration:")
params = physics.get(destdir=None)
print(f" Total parameters: {len(params)}")
for key, value in params.items():
print(f" {key} = {value}")
Storm surge configuration: Total parameters: 8 bedfriccoef = 0.02 flow = 1 wind = 1 lat = -32.0 wearth = 1.0 smag = 1 nuh = 0.5 rho = 1025.0
Summary¶
Two Types of Parameters¶
Simple switches/values:
- Boolean flags:
flow=True,morphology=False - Single values: Set directly in Physics
- Use for enabling/disabling processes
- Boolean flags:
Component models:
- Groups of related parameters
- Type-safe discriminated unions
- Examples:
wavemodel,bedfriction,vegetation - Use for complex formulations
Key Component Models¶
- Wave models:
Surfbeat,Stationary,Nonh - Friction:
Manning,Chezy,Cf,WhiteColebrook - Breaking:
Roelvink1,Roelvink2,RoelvinkDaly - Roller:
Roller(or boolean) - Vegetation:
Vegetation - WCI:
WaveCurrentInteraction(or boolean)
Parameter Groups¶
- Viscosity:
HorizontalViscosity - Flow numerics:
FlowNumerics - Wave numerics:
WaveNumerics - Non-hydrostatic:
NonHydrostaticNumerics - Constants:
PhysicalConstants,Coriolis
Important Notes¶
Sediment and Morphology: These are NOT in Physics! They're in the Sediment component:
from rompy_xbeach.components.sediment import Sediment
from rompy_xbeach.components.sediment.transport import SedimentTransport
from rompy_xbeach.components.sediment.morphology import Morphology
sediment = Sediment(
sedtrans=SedimentTransport(form="vanthiel_vanrijn"),
morphology=Morphology(morfac=10.0),
)
See sediment_comprehensive_example.py for sediment configuration.
Best Practices¶
- Start simple - use defaults when possible
- Group related parameters in component models
- Use discriminated unions for type safety
- Check validators - some combinations are invalid
- Use
get()to see final params.txt output - Remember: Physics is for physical processes, Sediment is for morphology