Wave boundaries from wave parameters¶
What this shows: how to build JONSWAP boundaries from integrated wave parameters (Hs, Tp, direction, peak enhancement and spreading) at stations, on a grid, or from a single timeseries such as a buoy record.
Prerequisites: Tutorial 4: Adding forcing.
You will learn:
- how the
..._varfields map dataset variables to JONSWAP parameters - how to mix dataset variables with constant values
- how to use station, gridded and point (CSV or NetCDF) parameter data
- the difference between the
JonsandJonstablevariants
Data used: smc-params-20230101.nc (parameters at wave model sites),
gridded_wave_parameters.nc (gridded parameters) and wave-params-20230101.csv (a
timeseries at one location).
Setup¶
import shutil
from pathlib import Path
import pandas as pd
from rompy.core.time import TimeRange
from rompy.logging import config as logging_config
from rompy_xbeach.grid import RegularGrid
logging_config.update(level="WARNING") # rompy logs every step, show warnings only
DATA_DIR = Path("../data")
OUT_DIR = Path("_output") / "waves_from_parameters"
shutil.rmtree(OUT_DIR, ignore_errors=True)
grid = RegularGrid(
ori={"x": 115.594239, "y": -32.641104, "crs": 4326},
alfa=347.0,
dx=10.0,
dy=15.0,
nx=230,
ny=220,
crs=28350,
)
period = TimeRange(start="2023-01-01T00", end="2023-01-01T03", interval="1h")
DIRECTIONS = {"thetamin": -90.0, "thetamax": 90.0, "dtheta": 10.0}
def generate(boundary, name):
"""Write a boundary to its own folder, print the parameters and the boundary file."""
destdir = OUT_DIR / name
destdir.mkdir(parents=True)
params = boundary.get(destdir=destdir, grid=grid, time=period)
for key, value in params.items():
print(f"{key} = {value}")
print(f"\n{params['bcfile']}:\n{(destdir / params['bcfile']).read_text()}")
1. Mapping variables to JONSWAP parameters¶
Parameter boundaries need five values per time step. Each ..._var field takes either
the name of a variable in the dataset or a constant number:
| Field | JONSWAP parameter |
|---|---|
hm0_var |
Significant wave height Hm0 (m) |
tp_var |
Peak period Tp (s) |
mainang_var |
Mean or peak direction (nautical, coming from) |
gammajsp_var |
Peak enhancement factor gamma |
dspr_var |
Directional spread in degrees, converted to the JONSWAP s for XBeach |
The datasets here come from WAVEWATCH III, where phs1, ptp1, pdp1, ppe1 and
pspr1 are the parameters of the main swell partition.
2. Parameters at stations¶
BoundaryStationParamJons interpolates between the wave model sites nearest the
boundary, like the spectral station classes. The site dimension is named in coords.
from rompy_xbeach.data.boundary import BoundaryStationParamJons
from rompy_xbeach.source import SourceCRSFile
station_source = SourceCRSFile(uri=DATA_DIR / "smc-params-20230101.nc", crs=4326)
generate(
BoundaryStationParamJons(
source=station_source,
coords={"s": "seapoint"},
location="offshore",
hm0_var="phs1",
tp_var="ptp1",
mainang_var="pdp1",
gammajsp_var="ppe1",
dspr_var="pspr1",
**DIRECTIONS,
),
"station_jons",
)
wbctype = parametric bcfile = parametric-20230101T000000.txt thetamin = -90.0 thetamax = 90.0 dtheta = 10.0 dtbc = 1.0 parametric-20230101T000000.txt: Tp = 13.1659 s = 21.9514 Hm0 = 0.875435 gammajsp = 2.68225 mainang = 254.158
3. Mixing variables and constants¶
When a dataset lacks a parameter, give a constant instead. Here the peak enhancement and spreading are fixed.
generate(
BoundaryStationParamJons(
source=station_source,
coords={"s": "seapoint"},
location="offshore",
hm0_var="phs1",
tp_var="ptp1",
mainang_var="pdp1",
gammajsp_var=3.3,
dspr_var=20.0,
**DIRECTIONS,
),
"station_jons_constants",
)
wbctype = parametric bcfile = parametric-20230101T000000.txt thetamin = -90.0 thetamax = 90.0 dtheta = 10.0 dtbc = 1.0 parametric-20230101T000000.txt: Tp = 13.1659 s = 15.414 Hm0 = 0.875435 gammajsp = 3.3 mainang = 254.158
4. Gridded parameters¶
BoundaryGridParamJons interpolates gridded fields to the boundary point. The
Jonstable variant writes every time step into a single table.
from rompy_xbeach.data.boundary import BoundaryGridParamJonstable
grid_source = SourceCRSFile(
uri=DATA_DIR / "gridded_wave_parameters.nc",
crs=4326,
x_dim="longitude",
y_dim="latitude",
)
generate(
BoundaryGridParamJonstable(
source=grid_source,
location="offshore",
hm0_var="phs1",
tp_var="ptp1",
mainang_var="pdp1",
gammajsp_var="ppe1",
dspr_var="pspr1",
**DIRECTIONS,
),
"grid_jonstable",
)
wbctype = jonstable bcfile = jonstable-20230101T000000-20230101T030000.txt thetamin = -90.0 thetamax = 90.0 dtheta = 10.0 dtbc = 1.0 jonstable-20230101T000000-20230101T030000.txt: 0.59286 15.326 256.055 3.61135 39.4458 3600 1 0.634844 15.24 256.115 3.71929 38.8198 3600 1 0.676148 15.1233 255.98 3.52664 39.3134 3600 1 0.701835 16.1724 259.39 3.69853 38.1915 3600 1
5. A single timeseries¶
The ...Point... classes use a timeseries directly, with no spatial selection. A
buoy record in a CSV file only needs the name of the time column.
from rompy.core.source import SourceTimeseriesCSV
from rompy_xbeach.data.boundary import BoundaryPointParamJonstable
csv_file = DATA_DIR / "wave-params-20230101.csv"
generate(
BoundaryPointParamJonstable(
source=SourceTimeseriesCSV(filename=csv_file, tcol="time"),
hm0_var="phs1",
tp_var="ptp1",
mainang_var="pdp1",
gammajsp_var="ppe1",
dspr_var="pspr1",
**DIRECTIONS,
),
"point_jonstable_csv",
)
wbctype = jonstable bcfile = jonstable-20230101T000000-20230101T030000.txt thetamin = -90.0 thetamax = 90.0 dtheta = 10.0 dtbc = 1.0 jonstable-20230101T000000-20230101T030000.txt: 1.01011 12.2993 244.342 2.52055 33.9251 3600 1 0.968176 13.7877 247.584 3.02407 41.2201 3600 1 0.994085 14.1542 248.386 3.02558 48.7203 3600 1 1.07939 13.5109 246.407 2.65635 46.7938 3600 1
The same classes read NetCDF timeseries through rompy's SourceFile. Here the CSV is
converted to a small NetCDF file with only Hs, peak period and direction, and the
missing parameters are given as constants.
from rompy.core.source import SourceFile
from rompy_xbeach.data.boundary import BoundaryPointParamJons
df = pd.read_csv(csv_file, parse_dates=["time"]).set_index("time")
ds = df[["hs", "dp"]].to_xarray()
ds["tp"] = 1 / df["fp"].to_xarray()
nc_file = OUT_DIR / "wave-params-20230101.nc"
ds.to_netcdf(nc_file)
generate(
BoundaryPointParamJons(
source=SourceFile(uri=nc_file),
hm0_var="hs",
tp_var="tp",
mainang_var="dp",
gammajsp_var=3.3,
dspr_var=25.0,
**DIRECTIONS,
),
"point_jons_netcdf",
)
wbctype = parametric bcfile = parametric-20230101T000000.txt thetamin = -90.0 thetamax = 90.0 dtheta = 10.0 dtbc = 1.0 parametric-20230101T000000.txt: Tp = 16.6301 s = 9.50498 Hm0 = 1.70782 gammajsp = 3.3 mainang = 252.736
Summary¶
| Data | JONSWAP file per time | JONSWAP table |
|---|---|---|
| Stations | BoundaryStationParamJons |
BoundaryStationParamJonstable |
| Grid | BoundaryGridParamJons |
BoundaryGridParamJonstable |
| Single timeseries | BoundaryPointParamJons |
BoundaryPointParamJonstable |
The Jons classes also accept filelist=True for one file per time step, as in
waves from spectra.