Physics¶
What this shows: the options of the Physics component: wave models and
breakers, bed friction, viscosity, the roller, vegetation, wave-current interaction,
numerics and physical constants.
Prerequisites: Tutorial 5: Choosing model settings.
You will learn:
- which breaker formulations go with each wave model
- how to choose and limit bed friction, including spatially varying friction files
- how to configure the optional processes and the flow and wave numerics
Data used: small input files created in the notebook.
Setup¶
import shutil
from pathlib import Path
import numpy as np
from rompy.logging import config as logging_config
from rompy_xbeach.components.physics import Physics
from rompy_xbeach.components.physics.wavemodel import Nonh, Stationary, Surfbeat
from rompy_xbeach.types import XBeachDataBlob
logging_config.update(level="WARNING") # rompy logs every step, show warnings only
OUT_DIR = Path("_output") / "physics"
shutil.rmtree(OUT_DIR, ignore_errors=True)
OUT_DIR.mkdir(parents=True)
def show(component):
"""Print the XBeach parameters a component writes to params.txt."""
for key, value in component.get(destdir=OUT_DIR).items():
print(f"{key} = {value}")
1. Wave models and breakers¶
Each wave model accepts only the breaker formulations that XBeach supports for it:
| Wave model | Breakers |
|---|---|
Stationary |
Baldock (default), Janssen |
Surfbeat |
Roelvink1, Roelvink2 (default), RoelvinkDaly |
Nonh |
Its own steepness-based breaking settings |
from rompy_xbeach.components.physics.wavemodel import Janssen
show(Physics(wavemodel=Stationary(breaktype=Janssen())))
wavemodel = stationary break = janssen
from rompy_xbeach.components.physics.wavemodel import RoelvinkDaly
show(Physics(wavemodel=Surfbeat(breaktype=RoelvinkDaly(gamma2=0.3))))
wavemodel = surfbeat break = roelvink_daly gamma2 = 0.3
The non-hydrostatic model resolves individual waves, so the short-wave driver is switched off. Its breaking is controlled by wave steepness.
show(Physics(wavemodel=Nonh(maxbrsteep=0.6, nhbreaker=2), swave=False))
wavemodel = nonh maxbrsteep = 0.6 nhbreaker = 2 swave = 0
Wave energy dissipation by bottom friction can be added to any breaker:
from rompy_xbeach.components.physics.wavemodel import Roelvink2, ShortWaveFriction
show(
Physics(
wavemodel=Surfbeat(
breaktype=Roelvink2(wavfric=ShortWaveFriction(wavfriccoef=0.05))
)
)
)
wavemodel = surfbeat break = roelvink2 wavfriccoef = 0.05
2. Bed friction¶
Five formulations are available. Each has its own coefficient meaning and range:
| Class | bedfriccoef |
|---|---|
Chezy |
Chezy value C (m$^{1/2}$/s) |
Cf |
Dimensionless friction coefficient |
Manning |
Manning n (s/m$^{1/3}$) |
WhiteColebrook |
Nikuradse roughness ks (m) |
WhiteColebrookGrainsize |
None, computed from the sediment D90 |
from rompy_xbeach.components.physics.friction import (
Chezy,
Manning,
WhiteColebrookGrainsize,
)
show(Physics(wavemodel=Surfbeat(), bedfriction=Chezy(bedfriccoef=55.0)))
wavemodel = surfbeat bedfriction = chezy bedfriccoef = 55.0
Friction can be bounded with mincf and maxcf, which avoids unrealistic values in
very shallow water. All formulations can also include the effects of acceleration,
infiltration and turbulence on bed roughness.
show(
Physics(
wavemodel=Surfbeat(),
bedfriction=Manning(bedfriccoef=0.02, mincf=0.001, maxcf=0.05),
)
)
wavemodel = surfbeat bedfriction = manning bedfriccoef = 0.02 mincf = 0.001 maxcf = 0.05
show(
Physics(
wavemodel=Surfbeat(),
bedfriction=WhiteColebrookGrainsize(friction_turbulence=True, gamma_turb=1.0),
)
)
wavemodel = surfbeat bedfriction = white-colebrook-grainsize friction_turbulence = 1 gamma_turb = 1.0
Spatially varying friction is read from a file with one value per grid point, for example rougher values on a reef. The file is copied into the workspace. A coefficient and a file cannot be given together.
friction_map = OUT_DIR / "source_friction.txt"
values = np.full((110, 115), 0.02)
values[40:70, 60:90] = 0.06 # a rough patch
np.savetxt(friction_map, values, fmt="%.3f")
show(
Physics(
wavemodel=Surfbeat(),
bedfriction=Manning(bedfricfile=XBeachDataBlob(source=friction_map)),
)
)
wavemodel = surfbeat bedfriction = manning bedfricfile = source_friction.txt
from rompy_xbeach.components.physics.friction import Viscosity
show(Physics(wavemodel=Surfbeat(), viscosity=Viscosity(smag=True, nuh=0.15)))
wavemodel = surfbeat viscosity = 1 smag = 1 nuh = 0.15
Roller¶
The roller model transfers breaking wave energy to a surface roller before it dissipates, which shifts wave-driven setup and currents shorewards.
from rompy_xbeach.components.physics.wavemodel import Roller
show(Physics(wavemodel=Surfbeat(), roller=Roller(beta=0.1)))
wavemodel = surfbeat roller = 1 beta = 0.1
Wave-current interaction¶
Refraction of waves by currents, such as at rip channels or tidal inlets.
from rompy_xbeach.components.physics.wci import WaveCurrentInteraction
show(Physics(wavemodel=Surfbeat(), wci=WaveCurrentInteraction(cats=4.0, hwci=0.1)))
wavemodel = surfbeat wci = 1 cats = 4.0 hwci = 0.1
Vegetation¶
Vegetation damps waves and flow. XBeach reads a list of species files and a map giving the species number at each grid point (0 = none). The files are copied into the workspace.
from rompy_xbeach.components.physics.vegetation import Vegetation
species = OUT_DIR / "seagrass.txt"
species.write_text("nsec = 1\nah = 0.2\nbv = 0.005\nN = 1000\nCd = 1.0\n")
species_list = OUT_DIR / "veggiefile.txt"
species_list.write_text("seagrass.txt\n")
vegetation_map = OUT_DIR / "vegmap.txt"
np.savetxt(vegetation_map, (values > 0.02).astype(int), fmt="%d")
show(
Physics(
wavemodel=Surfbeat(),
vegetation=Vegetation(
nveg=1,
veggiefile=XBeachDataBlob(source=species_list),
veggiemapfile=XBeachDataBlob(source=vegetation_map),
),
)
)
wavemodel = surfbeat vegetation = 1 nveg = 1 veggiefile = veggiefile.txt veggiemapfile = vegmap.txt
The species list names the species files, so copy those into the workspace as well,
for example with an XBeachDataBlob for each one or by keeping them next to the
generated files.
4. Numerics¶
Flow and wave numerics have their own components. The defaults suit most cases.
Common adjustments are the CFL number, the wet-dry threshold eps and the wave
advection scheme.
from rompy_xbeach.components.physics.numerics import FlowNumerics, WaveNumerics
show(
Physics(
wavemodel=Surfbeat(),
flow_numerics=FlowNumerics(cfl=0.7, eps=0.005),
wave_numerics=WaveNumerics(scheme="warmbeam"),
)
)
wavemodel = surfbeat scheme = warmbeam eps = 0.005 cfl = 0.7
5. Physical constants and Coriolis¶
Useful for laboratory-scale models (depthscale) or large domains where Coriolis
matters.
from rompy_xbeach.components.physics.constants import Coriolis, PhysicalConstants
show(
Physics(
wavemodel=Surfbeat(),
constants=PhysicalConstants(rho=1025.0, depthscale=1.0),
coriolis=Coriolis(lat=-32.6),
)
)
wavemodel = surfbeat lat = -32.6 depthscale = 1.0 rho = 1025.0
6. Process switches¶
Simple on/off switches for whole processes. XBeach defaults differ between versions, so set the ones that matter explicitly:
| Switch | XBeach v1.24 default |
|---|---|
swave, lwave, flow, advection, viscosity |
on |
avalanching |
on when morphology is on |
wind, wci, gwflow, ships, snells, cyclic |
off |
single_dir |
on for surfbeat on 2D grids |
show(Physics(wavemodel=Surfbeat(), wind=True, avalanching=True, single_dir=False))
wavemodel = surfbeat avalanching = 1 single_dir = 0 wind = 1
Summary¶
- Breakers belong to their wave model, so only valid combinations can be built.
- Friction takes a coefficient or a spatially varying file, not both.
- Optional processes take
True,Falseor a component with settings.