Setting up the Boundaries
Boundaries are an important part of the ANUGA model. They are used to set the boundary conditions for the model.
To set up the boundaries you first need to create boundary objects. These boundary objects are then
assigned to the edges of the domain using the set_boundary method of the Domain class.
For example, to set up reflective boundaries on all sides of a rectangular domain, you would do the following:
from anuga import Domain, Reflective_boundary
# Create a rectangular domain
domain = Domain(...)
# Create a reflective boundary object
Br = Reflective_boundary(domain)
# Set the boundaries of the domain
domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
Standard Boundary Types
Class |
Description |
|---|---|
Returns the same conserved quantities as the neighbouring interior triangle but with the normal momentum negated, so that no mass crosses the boundary (a “wall”). Suitable for closed edges such as coastlines and levees. |
|
Holds stage and momenta at fixed, constant values for the full simulation. Useful for specifying a steady inflow or maintaining a constant water level on an open boundary. |
|
Like |
|
Sets the stage from a user-supplied function of time, transmits the normal momentum from the adjacent interior cell, and zeros the tangential momentum. Approximates a weakly-reflective open boundary where the outgoing signal can leave with minimal reflection. |
|
Implements a Flather-type radiation condition (Blayo & Debreu 2005): the external stage is set by a function of time and the external velocity is zero, but the boundary flux is blended with the interior state using characteristic-like variables. Useful as a weakly reflecting open-ocean boundary where the stage should be approximately specified but outgoing waves are allowed to leave. |
|
Reads stage and momentum time series from an SWW file and interpolates them spatially to each boundary midpoint and linearly in time. Used to nest a fine-resolution domain inside a coarser simulation. |
|
A thin wrapper around |
|
Active-absorption open boundary that simultaneously prescribes an
incoming wave and absorbs outgoing (reflected) waves. The ghost-cell
stage is set to |
|
Nonlinear characteristic open boundary that prescribes the incoming
Riemann invariant from a stage perturbation above a specified
|
Usage examples
Reflective boundary (closed wall)
import anuga
Br = anuga.Reflective_boundary(domain)
domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
Dirichlet boundary (fixed values)
import anuga
# stage = 0.5 m, xmomentum = 0, ymomentum = 0
Bd = anuga.Dirichlet_boundary([0.5, 0.0, 0.0])
Br = anuga.Reflective_boundary(domain)
domain.set_boundary({'left': Bd, 'right': Br, 'top': Br, 'bottom': Br})
Time boundary (time-varying stage)
import anuga
import math
def tide(t):
"""Sinusoidal tide with 12-hour period and 1 m amplitude."""
return [math.sin(2 * math.pi * t / 43200.0), 0.0, 0.0]
Bt = anuga.Time_boundary(domain, function=tide)
domain.set_boundary({'ocean': Bt, 'land': anuga.Reflective_boundary(domain)})
File boundary (nesting from an SWW file)
import anuga
Bf = anuga.File_boundary('coarse_run.sww', domain)
Br = anuga.Reflective_boundary(domain)
domain.set_boundary({'ocean': Bf, 'land': Br})
Field boundary (SWW file with tide offset)
import anuga
# Reuse an SWW file generated at mean sea level; add 0.8 m for high tide
Bff = anuga.Field_boundary('boundary_msl.sww', domain, mean_stage=0.8)
domain.set_boundary({'ocean': Bff, 'land': anuga.Reflective_boundary(domain)})
Flather boundary (weakly reflecting open ocean)
import anuga
sea_level = 0.0
def waveform(t):
return sea_level + 0.5 / math.cosh(t - 25.0) ** 2
Bfl = anuga.Flather_external_stage_zero_velocity_boundary(domain, waveform)
domain.set_boundary({'ocean': Bfl, 'land': anuga.Reflective_boundary(domain)})
Absorbing wave boundary (active-absorption open boundary)
import anuga
# Prescribe a Gaussian wave pulse arriving at t = 25 s
def wave(t):
return 0.5 / math.cosh(t - 25.0) ** 2
Ba = anuga.Absorbing_wave_boundary(domain, function=wave)
domain.set_boundary({'ocean': Ba, 'land': anuga.Reflective_boundary(domain)})
Characteristic wave boundary (nonlinear characteristic open boundary)
import anuga
# Stage perturbation (above background_stage) arriving at t = 25 s
def perturbation(t):
return 0.5 / math.cosh(t - 25.0) ** 2
Bc = anuga.Characteristic_wave_boundary(
domain,
function=perturbation,
background_stage=0.0, # still-water level
)
domain.set_boundary({'ocean': Bc, 'land': anuga.Reflective_boundary(domain)})
See also
ANUGA User Manual — Chapter 9: Boundary Conditions and set_boundary gives extended examples of each boundary type, discusses time-varying stage specifications in detail, and explains how to diagnose common boundary-tag errors.
Reference
- class anuga.Reflective_boundary(domain=None)[source]
Reflective boundary condition.
Returns the same conserved quantities as the neighbour volume edge but with the normal momentum component negated, so the net mass flux through the boundary is zero (wall / no-slip analogue for the shallow-water equations).
Parameters
- domainanuga.Domain
The domain to which this boundary is attached.
Examples
>>> import anuga >>> domain = anuga.rectangular_cross_domain(10, 10) >>> Br = anuga.Reflective_boundary(domain) >>> domain.set_boundary({'left': Br, 'right': Br, 'top': Br, 'bottom': Br})
- class anuga.Dirichlet_boundary(dirichlet_values=None)[source]
Dirichlet boundary returns constant values for the conserved quantities
- class anuga.Time_boundary(domain=None, function=None, default_boundary=None, verbose=False)[source]
Time dependent boundary returns values for the conserved quantities as a function of time. Must specify domain to get access to model time and a function of t which must return conserved quantities as a function time.
- Example:
- B = Time_boundary(domain,
function=lambda t: [(60<t<3660)*2, 0, 0])
This will produce a boundary condition with is a 2m high square wave starting 60 seconds into the simulation and lasting one hour. Momentum applied will be 0 at all times.
- class anuga.Transmissive_n_momentum_zero_t_momentum_set_stage_boundary(domain=None, function=None, default_boundary=0.0)[source]
Transmissive normal momentum, zero tangential momentum, prescribed stage.
Returns the same momentum component normal to the boundary as the neighbour volume edge. The tangential momentum component is zeroed. Stage is set by a caller-supplied function of time.
Parameters
- domainanuga.Domain
The domain to which this boundary is attached.
- functioncallable
A function
f(t)returning the stage at time t.- default_boundaryfloat, optional
Stage value returned when model time exceeds the range of function. Default is
0.0.
Examples
>>> import anuga >>> domain = anuga.rectangular_cross_domain(10, 10) >>> BC = anuga.Transmissive_n_momentum_zero_t_momentum_set_stage_boundary( ... domain, lambda t: 0.5) >>> domain.set_boundary({'left': BC, 'right': BC, 'top': BC, 'bottom': BC})
- class anuga.Flather_external_stage_zero_velocity_boundary(domain=None, function=None, default_boundary=0.0)[source]
Weakly-reflecting open boundary using a Flather-type characteristic approach.
Sets the exterior stage via a function of time and assumes zero exterior velocity. Interior values are taken from the domain. The boundary conserved quantities are then computed from characteristic-like variables, making this boundary weakly reflecting — outgoing waves leave with minimal spurious reflection while incoming wave forcing is prescribed.
The approach is similar (but not identical) to that described on page 239 of:
@Article{blayo05, title = {Revisiting open boundary conditions from the point of view of characteristic variables}, author = {Blayo, E. and Debreu, L.}, journal = {Ocean Modelling}, year = {2005}, volume = {9}, pages = {231--252}, }
Algorithm
The exterior stage is set from function(t); exterior velocity is zero; interior stage and velocity are taken from the domain edge values.
Characteristic-like variables are computed depending on whether flow is incoming or outgoing (see Blayo & Debreu 2005).
The boundary conserved quantities (stage, x-momentum, y-momentum) are recovered from these characteristic variables.
Parameters
- domainanuga.Domain
The domain to which this boundary is attached.
- functioncallable
A function
f(t)returning the exterior stage at model time t. Typically afile_function()time series.- default_boundaryfloat, optional
Stage value returned when model time exceeds the range of function (e.g. when a file-function time series ends).
0.0corresponds to ambient sea level / no wave forcing. Default0.0.
Examples
>>> import anuga >>> domain = anuga.rectangular_cross_domain(10, 10) >>> Bf = anuga.Flather_external_stage_zero_velocity_boundary( ... domain, lambda t: 0.1, default_boundary=0.0) >>> domain.set_boundary({'left': Bf, 'right': Bf, 'top': Bf, 'bottom': Bf})
- class anuga.File_boundary(filename, domain, time_thinning=1, time_limit=None, boundary_polygon=None, default_boundary=None, use_cache=False, verbose=False)[source]
The File_boundary reads values for the conserved quantities from an sww NetCDF file, and returns interpolated values at the midpoints of each associated boundary segment. Time dependency is interpolated linearly.
Assumes that file contains a time series and possibly also spatial info. See docstring for File_function in util.py for details about admissible file formats
File boundary must read and interpolate from smoothed version as stored in sww and cannot work with the discontinuous triangles.
Example: Bf = File_boundary(‘source_file.sww’, domain)
Note that the resulting solution history is not exactly the same as if the models were coupled as there is no feedback into the source model.
Optional keyword argument default_boundary must be either None or an instance of class descending from class Boundary. This will be used in case model time exceeds that available in the underlying data.
- class anuga.Field_boundary(filename, domain, mean_stage=0.0, time_thinning=1, time_limit=None, boundary_polygon=None, default_boundary=None, use_cache=False, verbose=False)[source]
Boundary condition driven by an SWW field file with optional stage offset.
Reads stage, x-momentum and y-momentum time series from an SWW file and applies them as a boundary condition, linearly interpolating in time. An optional mean_stage offset can be added to the stage values, which avoids regenerating the SWW file when running at different tide levels.
This is a thin wrapper around
File_boundary; the only difference is the mean_stage offset capability.Parameters
- filenamestr
Path to the SWW file containing stage and momentum time series.
- domainanuga.Domain
The domain to which this boundary is attached.
- mean_stagefloat, optional
Constant offset added to the stage read from the file. Useful for running at different tidal datums without recreating the SWW file. Default
0.0.- time_thinningint, optional
Read every time_thinning-th time step from the file. Larger values speed up model setup at the cost of temporal resolution. Default
1(all steps).- time_limitfloat or None, optional
Stop reading the file after this time (seconds).
Nonemeans read to the end.- boundary_polygonlist or None, optional
Clip the SWW points to this polygon.
Nonemeans use all points.- default_boundaryfloat or None, optional
Stage returned when model time exceeds the file’s time range.
Noneraises an exception on out-of-range.- use_cachebool, optional
Cache the interpolated field function. Default
False.- verbosebool, optional
Emit progress messages. Default
False.
Examples
>>> import anuga >>> domain = anuga.rectangular_cross_domain(10, 10) >>> Bf = anuga.Field_boundary('boundary.sww', domain, mean_stage=0.5) >>> domain.set_boundary({'left': Bf, 'right': Bf, 'top': Bf, 'bottom': Bf})
- class anuga.Absorbing_wave_boundary(domain=None, function=None, default_boundary=0.0)[source]
Active-absorption open boundary with prescribed incoming wave.
Simultaneously prescribes an incoming wave and absorbs outgoing (reflected) waves by setting the ghost-cell stage to:
stage_ghost = 2 * wave(t) - stage_interior
so that the boundary face always sees exactly
wave(t)regardless of what is propagating back from inside the domain. The ghost normal momentum is set toghost_depth × interior_velocity(velocity- preserving transmissive): this keeps the ghost velocity bounded when ghost depth is small (e.g. after bed-clamping) and gives the correct incoming-wave energy flux. Zero ghost momentum would halve the incoming wave amplitude. Tangential momentum is zeroed. When the ghost cell is dry (bed-clamped to zero depth), both momentum components are set to zero to avoid a pathological dry-ghost state in the Riemann solver.This is the numerical equivalent of an active-absorption wavemaker used in physical wave-tank experiments: the paddle continuously adjusts to cancel any reflected wave arriving at the boundary while still generating the desired incoming signal.
Note
Absorption efficiency depends on the phase of the standing-wave cycle. At a standing-wave antinode (
u ≈ 0at the boundary) the net momentum flux is zero and energy drains slowly over multiple wave periods. For highly reflective short-domain problems (e.g. the Okushiri benchmark) this is still preferable to a pure Flather condition, which can exhibit 2× stage amplification at the boundary gauge.Parameters
- domainanuga.Domain
The domain to which this boundary is attached.
- functioncallable
A function
f(t)returning the prescribed stage at model time t. Typically afile_function()time series.- default_boundaryfloat, optional
Stage returned when model time exceeds the range of function. Defaults to
0.0.
Examples
>>> import anuga >>> domain = anuga.rectangular_cross_domain(10, 10) >>> Ba = anuga.Absorbing_wave_boundary(domain, lambda t: 0.1 * (t < 5)) >>> domain.set_boundary({'left': Ba, 'right': Ba, 'top': Ba, 'bottom': Ba})
- class anuga.Characteristic_wave_boundary(domain=None, function=None, background_stage=0.0, default_boundary=0.0)[source]
Nonlinear characteristic open boundary with prescribed incoming wave.
Prescribes the incoming Riemann invariant from a wave perturbation and extrapolates the outgoing Riemann invariant from the interior, solving the characteristic equations exactly (no linearisation).
The ghost state is derived from:
c_ghost = (v_n_int + 2*c_int - 2*c0 + 4*c_wave) / 4 v_n_ghost = c0 - 2*c_wave + v_n_int/2 + c_int h_ghost = c_ghost**2 / g stage_ghost = h_ghost + bed
where c0 = sqrt(g*h0) is the background wave speed (computed from
background_stageat each cell), c_wave = sqrt(g*h_wave) is the prescribed wave speed, and v_n is the outward-normal velocity.The wave function returns a perturbation from
background_stage(not an absolute stage). This is important: the background depth h0 =background_stage− bed is used to set the incoming Riemann invariant assuming no outgoing wave at the exterior.Compared to
Absorbing_wave_boundary:Better for large-amplitude waves (η ~ h) where linearisation error in the Flather form is significant.
The face stage is not guaranteed to equal wave(t) exactly; the characteristic condition controls energy transport rather than stage directly.
For small-amplitude waves (η ≪ h) both classes give similar results.
Parameters
- domainanuga.Domain
The domain to which this boundary is attached.
- functioncallable
f(t)returning the stage perturbation at time t.- background_stagefloat, optional
Still-water stage around which the perturbation is measured. Defaults to
0.0(sea level).- default_boundaryfloat, optional
Perturbation returned when model time is out of range. Default
0.0.