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

Reflective_boundary

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.

Dirichlet_boundary

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.

Time_boundary

Like Dirichlet_boundary but the conserved quantities are specified as a Python function of simulation time t. Use this when you want a time-varying stage or discharge that you can express as a formula (e.g. a tide signal or a gate opening schedule).

Transmissive_n_momentum_zero_t_momentum_set_stage_boundary

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.

Flather_external_stage_zero_velocity_boundary

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.

File_boundary

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.

Field_boundary

A thin wrapper around File_boundary that additionally applies a mean_stage offset to the stage read from the SWW file. Useful when you want to re-use one boundary SWW file across multiple tide scenarios without regenerating the file.

Absorbing_wave_boundary

Active-absorption open boundary that simultaneously prescribes an incoming wave and absorbs outgoing (reflected) waves. The ghost-cell stage is set to 2 × wave(t) stage_interior so that the boundary face always sees exactly wave(t) regardless of what is propagating back from the interior. Suitable for tsunami or storm-wave inflow on open-ocean boundaries where reflections must not re-enter the domain. Fully supported in GPU mode (multiprocessor_mode=2).

Characteristic_wave_boundary

Nonlinear characteristic open boundary that prescribes the incoming Riemann invariant from a stage perturbation above a specified background_stage and extrapolates the outgoing Riemann invariant from the interior without linearisation. Preferred over Absorbing_wave_boundary when wave amplitudes are comparable to the water depth (η ~ h) and linearisation error would be significant. Fully supported in GPU mode (multiprocessor_mode=2).

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

  1. The exterior stage is set from function(t); exterior velocity is zero; interior stage and velocity are taken from the domain edge values.

  2. Characteristic-like variables are computed depending on whether flow is incoming or outgoing (see Blayo & Debreu 2005).

  3. 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 a file_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.0 corresponds to ambient sea level / no wave forcing. Default 0.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). None means read to the end.

boundary_polygonlist or None, optional

Clip the SWW points to this polygon. None means use all points.

default_boundaryfloat or None, optional

Stage returned when model time exceeds the file’s time range. None raises 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 to ghost_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 0 at 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 a file_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_stage at 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.