Source code for wavespectra.construct.direction

import numpy as np
import xarray as xr
from scipy.constants import pi

from wavespectra import SpecArray
from wavespectra.core.utils import R2D, check_same_coordinates, to_coords
from wavespectra.core.attributes import attrs


[docs] def cartwright(dir, dm, dspr, under_90=False, **kwargs): """Cosine-squared directional spreading of Cartwright (1963). :math:`G(\\theta,f)=F(s)cos^{2}\\frac{1}{2}(\\theta-\\theta_{m})` Args: - dir (DataArray, 1darray, list): Wave direction coords (degree). - dm: (DataArray, float): Mean wave direction (degree). - dspr (DataArray, float): Directional spreading (degree). - under_90 (bool): Zero the spreading curve above 90 degrees range from dm. Returns: - gth (DataArray): Normalised spreading function :math:`g(\\theta)`. Note: - If `dm` and `dspr` are DataArrays they must share the same coordinates. """ check_same_coordinates(dm, dspr) if not isinstance(dir, xr.DataArray): dir = to_coords(dir, "dir") # Angular difference from mean direction: dth = np.abs(dir - dm) dth = dth.where(dth <= 180, 360.0 - dth) # for directional wrapping # spread function: s = 2.0 / (np.deg2rad(dspr) ** 2) - 1 gth = np.cos(0.5 * np.deg2rad(dth)) ** (2 * s) # mask directions +-90 deg from mean if under_90: gth = gth.where(np.abs(dth) <= 90.0, 0.0) # normalise gsum = 1.0 / (gth.sum(attrs.DIRNAME) * (2 * pi / dir.size)) gth = gth * gsum return gth / R2D
[docs] def asymmetric(dir, freq, dm, dpm, dspr, dpspr, fm, fp, **kwargs): """Asymmetric directional spreading of Bunney et al. (2014). Args: - dir (DataArray, 1darray, list): Wave direction coords (degree). - freq (DataArray, 1darray, list): Wave frequency coords (Hz). - dm: (DataArray, float): Mean wave direction (degree). - dpm: (DataArray, float): Peak wave direction (degree). - dspr (DataArray, float) Mean directional spreading (degree). - dpspr (DataArray, float) Peak directional spreading (degree). - fm (DataArray, float) Mean wave frequency (Hz). - fp (DataArray, float) Peak wave frequency (Hz). Returns: - gfth (DataArray): Modified normalised spreading function :math:`g(f,\\theta)`. Note: - If arguments other than `dir` and `freq` are DataArrays they must share the same coordinates. """ check_same_coordinates(dm, dpm, dspr, dpspr, fm, fp) if not isinstance(freq, xr.DataArray): freq = to_coords(freq, "freq") if not isinstance(dir, xr.DataArray): dir = to_coords(dir, "dir") # Gradients # ========== # Limiters to avoid negative and large numbers dd = dm - dpm ds = np.maximum(dspr - dpspr, 0) df = np.maximum(fm - fp, 0.001) dddf = dd / df dsdf = ds / df # Modified peak direction # ======================== # Limiter for frequency band peak directon (30% peak spread) theta = dpm + dddf * (freq - fp) theta = np.minimum(1.5 * dpm, np.maximum(0.5 * dpm, theta)) # Modified spread parameter # ========================== # Limiter for frequency band spreading, 0.14 limits s to ~100 for narrow beamwidths sigma = dpspr + dsdf * (freq - fp) sigma = np.maximum(0.5 * dspr, np.minimum(1.5 * np.maximum(dspr, dpspr), sigma)) sigma = sigma.where(sigma >= 0.14, 0.14) # Apply cosine-square to modified parameters # =========================================== gfth = cartwright(dir, theta, sigma, under_90=False) return gfth