Boundary Conditions Tutorial¶
This tutorial introduces the boundary condition components in rompy-xbeach, which control how flow and tides interact with the domain boundaries.
What You'll Learn¶
- Flow boundary conditions (front, back, lateral)
- Tide/surge boundary conditions
- Boundary type options and when to use them
- Integration with Config
Prerequisites¶
- Basic familiarity with XBeach concepts
- rompy-xbeach installed (
pip install rompy-xbeach)
Important Note on Wave Boundaries¶
Wave boundary conditions are NOT covered in this tutorial.
Wave boundary parameters (e.g.,
wbctype,bcfile, spectral settings) are defined in the wave boundary data classes (BoundaryJons,BoundaryJonstable,BoundaryStationSpectraSwan, etc.) withinrompy_xbeach.data.boundary.This tutorial covers only flow and tide boundary conditions, which are parameter-only components that don't require external data files.
See the Wave Boundary Data Tutorial for wave boundaries.
1. Introduction¶
XBeach has three types of boundary conditions:
| Type | Component | Purpose |
|---|---|---|
| Flow | FlowBoundaryConditions |
Shallow water equation boundaries |
| Tide | TideBoundaryConditions |
Water level / surge boundaries |
| Wave | Data classes in rompy_xbeach.data.boundary |
Wave forcing (not covered here) |
Domain Boundaries¶
XBeach uses a coordinate system where:
- Front (seaward): Offshore boundary where waves enter
- Back (landward): Bay/land side boundary
- Left/Right: Lateral boundaries (alongshore)
Left (ny+1)
┌─────────┐
Front │ │ Back
(sea) │ Domain │ (land)
│ │
└─────────┘
Right (0)
from rompy_xbeach.components.boundary.parameters import (
FlowBoundaryConditions,
TideBoundaryConditions,
)
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) if lines else 0
max_width = max(len(filename), max_content_width)
box_width = max_width + 2
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)
def print_warning(text):
"""Print text with warning-style highlighting."""
print(f"\033[48;5;224m\033[30m {text} \033[0m")
2. Flow Boundary Conditions¶
Flow boundary conditions control how the shallow water equations behave at
domain boundaries. The default absorbing-generating (abs_2d) boundary is
recommended for most applications.
2.1 Default Configuration¶
# Default flow boundaries - uses XBeach defaults
flow_default = FlowBoundaryConditions()
show_params(flow_default)
┌────────────┐ │ params.txt │ ├────────────┤ │ │ └────────────┘
Empty output means XBeach defaults are used:
front:abs_2d(absorbing-generating)back:abs_2dleft/right:neumann(zero gradient)
2.2 Front (Seaward) Boundary¶
The front boundary is where waves and flow enter the domain.
| Type | Description | Use Case |
|---|---|---|
abs_2d |
2D absorbing-generating | General use (default) |
abs_1d |
1D absorbing-generating | Cross-shore only |
wall |
No flux (reflective) | Closed boundaries |
wlevel |
Water level specification | Tide-driven models |
nonh_1d |
Non-hydrostatic | Short waves |
waveflume |
Wave flume | Lab experiments |
# Absorbing-generating boundary (recommended)
flow_abs = FlowBoundaryConditions(
front="abs_2d",
)
show_params(flow_abs)
┌────────────────┐ │ params.txt │ ├────────────────┤ │ front = abs_2d │ └────────────────┘
# Water level boundary (for tide-driven simulations)
flow_wlevel = FlowBoundaryConditions(
front="wlevel",
)
show_params(flow_wlevel)
┌────────────────┐ │ params.txt │ ├────────────────┤ │ front = wlevel │ └────────────────┘
2.3 Back (Landward) Boundary¶
The back boundary represents the landward or bay side of the domain.
| Type | Description | Use Case |
|---|---|---|
abs_2d |
Absorbing-generating | Open back boundary (default) |
abs_1d |
1D absorbing | Cross-shore only |
wall |
No flux | Closed lagoon/bay |
wlevel |
Water level | Back bay water level |
# Wall boundary (closed back)
flow_wall = FlowBoundaryConditions(
back="wall",
)
show_params(flow_wall)
┌─────────────┐ │ params.txt │ ├─────────────┤ │ back = wall │ └─────────────┘
2.4 Lateral Boundaries¶
Lateral boundaries (left and right) control alongshore behavior.
| Type | Description | Use Case |
|---|---|---|
neumann |
Zero gradient | General use (default) |
wall |
No flux | Closed lateral |
no_advec |
Advective terms only | Special cases |
neumann_v |
Copy velocity | Improved outflow |
abs_1d |
Absorbing | Reduce reflections |
# Absorbing lateral boundaries (reduce edge effects)
flow_lateral = FlowBoundaryConditions(
left="abs_1d",
right="abs_1d",
)
show_params(flow_lateral)
┌────────────────┐ │ params.txt │ ├────────────────┤ │ left = abs_1d │ │ right = abs_1d │ └────────────────┘
2.5 Lateral Wave Boundary¶
Controls how waves behave at lateral boundaries:
| Type | Description | Use Case |
|---|---|---|
neumann |
Zero longshore gradient | Default (may cause shadow zones) |
wavecrest |
Zero gradient along crest | Better for surfbeat mode |
cyclic |
Periodic boundary | Alongshore uniform conditions |
flow_wavecrest = FlowBoundaryConditions(
lateralwave="wavecrest",
)
show_params(flow_wavecrest)
┌─────────────────────────┐ │ params.txt │ ├─────────────────────────┤ │ lateralwave = wavecrest │ └─────────────────────────┘
2.6 Complete Flow Configuration¶
flow_complete = FlowBoundaryConditions(
front="abs_2d", # Absorbing offshore
back="wall", # Closed landward
left="neumann", # Zero gradient lateral
right="neumann",
lateralwave="wavecrest",
highcomp=True, # High-order compensation
)
show_params(flow_complete)
┌─────────────────────────┐ │ params.txt │ ├─────────────────────────┤ │ front = abs_2d │ │ back = wall │ │ left = neumann │ │ right = neumann │ │ lateralwave = wavecrest │ │ highcomp = 1 │ └─────────────────────────┘
3. Tide Boundary Conditions¶
Tide boundary conditions control how water levels (tide and surge) are applied at the domain boundaries.
3.1 Uniform Water Level (tideloc=0)¶
The simplest case: constant water level everywhere.
tide_uniform = TideBoundaryConditions(
tideloc=0, # Uniform water level
zs0=1.5, # Water level = 1.5m
)
show_params(tide_uniform)
┌─────────────┐ │ params.txt │ ├─────────────┤ │ tideloc = 0 │ │ zs0 = 1.5 │ └─────────────┘
3.2 Single Tide Signal (tideloc=1)¶
One time-varying tide signal applied at the offshore boundary.
The zs0 value is used at the back boundary.
tide_single = TideBoundaryConditions(
tideloc=1, # One tide signal at offshore
zs0=0.0, # Back boundary water level
)
show_params(tide_single)
┌─────────────┐ │ params.txt │ ├─────────────┤ │ tideloc = 1 │ │ zs0 = 0.0 │ └─────────────┘
3.3 Two Tide Signals (tideloc=2)¶
Two time-varying signals. The paulrevere parameter controls which
corners receive which signal.
tide_two = TideBoundaryConditions(
tideloc=2, # Two tide signals
paulrevere="land", # Signal assignment (default)
)
show_params(tide_two)
┌───────────────────┐ │ params.txt │ ├───────────────────┤ │ tideloc = 2 │ │ paulrevere = land │ └───────────────────┘
paulrevere options:
land: One signal to land corners, one to sea cornerssea: Opposite assignment
3.4 Four Tide Signals (tideloc=4)¶
Four independent time-varying signals, one per corner. Useful for large domains with significant tidal gradients.
tide_four = TideBoundaryConditions(
tideloc=4, # Four tide signals (one per corner)
)
show_params(tide_four)
┌─────────────┐ │ params.txt │ ├─────────────┤ │ tideloc = 4 │ └─────────────┘
3.5 Tide Type¶
Controls how tide is applied:
| Type | Description |
|---|---|
velocity |
Velocity boundary (default) |
instant |
Instantaneous water level |
hybrid |
Combination |
tide_instant = TideBoundaryConditions(
tideloc=1,
tidetype="instant",
)
show_params(tide_instant)
┌────────────────────┐ │ params.txt │ ├────────────────────┤ │ tideloc = 1 │ │ tidetype = instant │ └────────────────────┘
4. Combining Flow and Tide Boundaries¶
In practice, you'll often configure both flow and tide boundaries together.
# Typical storm surge configuration
flow_storm = FlowBoundaryConditions(
front="abs_2d",
back="wall",
lateralwave="wavecrest",
)
tide_storm = TideBoundaryConditions(
tideloc=1,
tidetype="velocity",
zs0=0.0,
)
print("Flow boundaries:")
show_params(flow_storm)
print("\nTide boundaries:")
show_params(tide_storm)
Flow boundaries: ┌─────────────────────────┐ │ params.txt │ ├─────────────────────────┤ │ front = abs_2d │ │ back = wall │ │ lateralwave = wavecrest │ └─────────────────────────┘ Tide boundaries: ┌─────────────────────┐ │ params.txt │ ├─────────────────────┤ │ tideloc = 1 │ │ tidetype = velocity │ │ zs0 = 0.0 │ └─────────────────────┘
config_example = """
from rompy_xbeach import Config
from rompy_xbeach.components.boundary.parameters import (
FlowBoundaryConditions,
TideBoundaryConditions,
)
config = Config(
project="storm_simulation",
grid=grid,
bathy=bathy,
# Flow boundary conditions
flow_boundary=FlowBoundaryConditions(
front="abs_2d",
back="wall",
lateralwave="wavecrest",
),
# Tide boundary conditions
tide_boundary=TideBoundaryConditions(
tideloc=1,
zs0=0.0,
),
# Wave boundaries are specified via input.wave data classes
# input=DataInterface(
# wave=BoundaryJonstable(...), # Wave boundary with data
# ),
# ... other components ...
)
config.generate(destdir="./model_run")
"""
print(config_example)
from rompy_xbeach import Config
from rompy_xbeach.components.boundary.parameters import (
FlowBoundaryConditions,
TideBoundaryConditions,
)
config = Config(
project="storm_simulation",
grid=grid,
bathy=bathy,
# Flow boundary conditions
flow_boundary=FlowBoundaryConditions(
front="abs_2d",
back="wall",
lateralwave="wavecrest",
),
# Tide boundary conditions
tide_boundary=TideBoundaryConditions(
tideloc=1,
zs0=0.0,
),
# Wave boundaries are specified via input.wave data classes
# input=DataInterface(
# wave=BoundaryJonstable(...), # Wave boundary with data
# ),
# ... other components ...
)
config.generate(destdir="./model_run")
6. Wave Boundaries (Reference)¶
As mentioned at the start, wave boundary conditions are handled separately through data classes that generate boundary files.
Wave Boundary Data Classes¶
| Class | Description |
|---|---|
BoundaryJons |
Single JONSWAP spectrum |
BoundaryJonstable |
Time-varying JONSWAP parameters |
BoundaryStationSpectraSwan |
SWAN spectral files |
BoundaryReuse |
Reuse existing boundary files |
Example (for reference only)¶
from rompy_xbeach.data.boundary import BoundaryJonstable
# Wave boundary with time-varying parameters
wave_boundary = BoundaryJonstable(
id="waves",
source=intake_catalog,
hm0_var="hs",
tp_var="tp",
dir_var="dir",
)
# Used in Config via input.wave
config = Config(
input=DataInterface(wave=wave_boundary),
...
)
See the wave boundary tutorials for detailed examples.
Summary¶
Key Takeaways¶
Flow boundaries control shallow water equation behavior at domain edges
Tide boundaries control water level forcing (tide/surge)
Wave boundaries are handled separately via data classes (not covered here)
Default boundaries (
abs_2d,neumann) work well for most casesUse
wallfor closed boundaries,abs_*for open boundaries
Flow Boundary Summary¶
| Boundary | Default | Common Alternatives |
|---|---|---|
front |
abs_2d |
wlevel, nonh_1d |
back |
abs_2d |
wall |
left/right |
neumann |
abs_1d, wall |
lateralwave |
neumann |
wavecrest, cyclic |
Tide Boundary Summary¶
| tideloc | Signals | Description |
|---|---|---|
| 0 | 0 | Uniform water level (zs0) |
| 1 | 1 | Offshore signal + zs0 at back |
| 2 | 2 | Two signals (paulrevere controls assignment) |
| 4 | 4 | Four signals (one per corner) |
Next Steps¶
- See the Physics Tutorial for hydrodynamics
- See the Output Tutorial for output configuration
- See the Wave Boundary Tutorial for wave forcing