Skip to main content

Fast nearshore spectral wave transformation: backward ray-traced transfer operators with refraction, shoaling, bottom friction and depth-limited breaking

Project description

waveray

Docs CI PyPI License

Fast last-stage nearshore spectral wave transformation: precomputed backward ray-traced linear transfer operators over local bathymetry, with parametric depth-limited wave breaking at the target.

📖 Documentation: https://oceanum.github.io/waveray/

Built to downscale directional wave spectra from SWAN (or WW3) hindcasts and nowcasts through the final nearshore transformation to a target site — decades of hourly spectra in seconds, no wave model in the runtime loop.

Install

pip install waveray                # core
pip install "waveray[datamesh]"    # + Oceanum Datamesh bathymetry/spectra access

Documentation

Full docs: https://oceanum.github.io/waveray/

Guide Read it for
Installation Install, extras, environment
Quickstart A working example in 20 lines
Concepts What the operator is, and the physics inside it
User guide Bathymetry, boundary points, tide, breaking, persistence, ray export
wavespectra interop Spectral conventions and the .spec accessor
Validation Measured skill against parent SWAN models
Limitations What waveray does not model
API reference Every public function and its arguments

The pages are plain Markdown in docs/ and render on GitHub too.

Method

Setup, once per site:

  1. Pull local bathymetry (e.g. from an Oceanum Datamesh datasource) into a LocalGrid on a local tangent plane.
  2. For every (frequency, direction) bin, trace ray bundles backward from the target over the 2D bathymetry (O'Reilly & Guza style spectral refraction). Each sub-ray records where and in what direction it exits the domain, or whether it runs aground (island/headland sheltering).
  3. Assemble a linear operator T[f, dir_t, bp, dir_b] mapping K boundary spectra (the SWAN output points around the domain perimeter — alongshore inhomogeneity is handled by exit-point interpolation) to the target spectrum. The per-ray coefficient is the exact linear invariant E(f, theta) * c * cg = const, which reproduces Snell refraction and energy-flux shoaling identically (validated against analytic plane-beach solutions in the test suite).

Runtime, per hindcast:

  1. E_t = einsum(T, E_b) over all timesteps at once.
  2. Depth-limited breaking as a nonlinear post-step: transformed Hm0 is capped at a Miche-type (Battjes-Janssen) or gamma * d limit with optional tide-modulated depth; the cap scales the spectrum proportionally, matching how SWAN distributes surf-breaking dissipation over the spectrum.

The stationary, linear-propagation assumption (no temporal nonlinear evolution, no quadruplets/triads) is deliberate: over a last-mile nearshore domain the propagation time is minutes and the transformation is dominated by refraction, shoaling, sheltering and breaking.

Quickstart

import numpy as np
from waveray import SiteModel, fetch_datamesh_bathymetry

bathy = fetch_datamesh_bathymetry(
    "gebco_2025", bbox=(114.35, -28.95, 114.65, -28.60), positive="up"
)
model = SiteModel.build(
    bathy=bathy,
    target=(114.58, -28.77),                     # lon, lat
    boundary_points=[(114.35, -28.90), (114.35, -28.65)],  # SWAN output sites
    freqs=efth_boundary.freq.values,
    dirs=efth_boundary.dir.values,
)
efth_near = model.transform(efth_boundary, tide=tide_series)   # (time, freq, dir)
model.to_netcdf("geraldton_berth.nc")            # reuse without rebuilding

efth follows the wavespectra convention: dims (time, [site,] freq, dir), dir = coming-from nautical degrees, density per Hz per degree. The site dimension (K boundary points, same order as boundary_points) is required when K > 1.

Ray paths can be exported for inspection (QGIS, EIDOS, any web map) as a GeoJSON FeatureCollection — one MultiLineString per (freq, dir) bin, with period, direction, per-ray status and friction decay in the properties:

from waveray import ray_paths_geojson

x, y = bathy_grid.to_local(lon, lat)
ray_paths_geojson(bathy_grid, (x[0], y[0]), freqs=[0.06, 0.1],
                  dirs=np.arange(0, 360, 15), path="rays.geojson")

Notebooks

Two executed, illustrated notebooks (plots included in the committed output):

Notebook What it shows
notebooks/01_holland_downscaling.ipynb End-to-end downscaling of a SWAN 1 km hindcast to a point off Noordwijk aan Zee through storms Pia and Henk: bathymetry, ray geometry and the arrival cone, offshore vs nearshore Hs, the directional spectrum before/after, validation against SWAN (r ≈ 0.99), and what depth-limited breaking contributes.
notebooks/02_abrolhos_validation.ipynb Held-out validation on a reef-fronted WA coast, and an ablation isolating JONSWAP bottom friction (Hm0 bias +1.11 m → +0.18 m when friction is on).
uv sync --extra datamesh --extra notebooks
DATAMESH_TOKEN=... uv run jupyter lab notebooks/

Limitations (v0)

  • No diffraction: accuracy degrades inside harbours / behind breakwaters, and island shadows are sharper than reality (rays block, they do not leak).
  • Island / headland sheltering is included — a ray grounding on any land carries no energy — but blocking is binary and only as good as the bathymetry: a feature smaller than ~2 grid cells is smoothed away by the bilinear depth sampling and will not shelter (GEBCO at ~450 m cannot shelter behind a small reef or islet). See tests/test_island.py.
  • Bottom friction IS included (JONSWAP, integrated along ray paths) and is ON by default with the SWAN swell coefficient cf_jonswap=0.038; pass cf_jonswap=None for pure refraction + shoaling. No triad interactions.
  • Breaking is an endpoint cap, not accumulated dissipation along the approach — appropriate at berths and outside the inner surf zone; tune gamma per site against observations.
  • The operator is built at a fixed water level; tide only modulates the breaking cap. For strongly tide-dependent refraction, build operators per tide stage.
  • Boundary spectra quality bounds achievable skill — nested-model literature consistently finds offshore directional accuracy, not nearshore resolution, is the limiting factor.

Development

uv sync                     # or: uv sync --extra datamesh
uv run pytest               # physics-validation suite
uv run ruff check . && uv run ruff format --check .

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

waveray-0.1.0.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

waveray-0.1.0-py3-none-any.whl (29.8 kB view details)

Uploaded Python 3

File details

Details for the file waveray-0.1.0.tar.gz.

File metadata

  • Download URL: waveray-0.1.0.tar.gz
  • Upload date:
  • Size: 24.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for waveray-0.1.0.tar.gz
Algorithm Hash digest
SHA256 63db4d0f2abb958f44b00d5856967bc6352d7f9edae2da76b24da533a8e53bdf
MD5 0e47c98620a102a9c015ab71cf28e56c
BLAKE2b-256 d730100aaf0c53024951f3dd812f010cba2574a325a975f4dcf4a5d5dd91853a

See more details on using hashes here.

Provenance

The following attestation bundles were made for waveray-0.1.0.tar.gz:

Publisher: publish.yml on oceanum/waveray

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file waveray-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: waveray-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 29.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for waveray-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0d24e4bff31a9c03c4f68fa0d888c39cfe371b8df54bb08a838d17d9d838e3a4
MD5 90df4d7b188363e27c0e769ac5127ff1
BLAKE2b-256 faaa575050dde968e64a183fad4556fae7a9d13a26f4eccba89beb1a6e905589

See more details on using hashes here.

Provenance

The following attestation bundles were made for waveray-0.1.0-py3-none-any.whl:

Publisher: publish.yml on oceanum/waveray

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page