Source code for wavespectra.core.npstats

"""Wave spectra stats on numpy arrays sourced by apply_ufuncs."""

import numpy as np
from scipy.constants import g, pi

from wavespectra.core.utils import R2D


[docs] def mom1(spectrum, dir, theta=90.0): """First directional moment. Args: - spectrum (2darray): wave spectrum array. - dir (1darray): wave direction array. - theta (float): angle offset. Returns: - msin (float): Sin component of the 1st directional moment. - mcos (float): Cosine component of the 1st directional moment. """ dd = dir[1] - dir[0] cp = np.cos(np.radians(180 + theta - dir)) sp = np.sin(np.radians(180 + theta - dir)) msin = (dd * spectrum * sp).sum(axis=1) mcos = (dd * spectrum * cp).sum(axis=1) return msin, mcos
[docs] def dm(spectrum, dir): """Mean wave direction Dm. Args: - spectrum (2darray): wave spectrum array. - dir (1darray): wave direction array. Returns: - dm (float): Mean spectral period. """ moms, momc = mom1(spectrum, dir) dm = np.arctan2(moms.sum(axis=0), momc.sum(axis=0)) dm = (270 - R2D * dm) % 360.0 return dm
[docs] def hs(spectrum, freq, dir=None, tail=True): """Significant wave height Hmo. Args: - spectrum (2darray): wave spectrum array. - freq (1darray): wave frequency array. - dir (1darray): wave direction array. - tail (bool): if True fit high-frequency tail before integrating spectra. Returns: - hs (float): Significant wave height. """ df = abs(freq[1:] - freq[:-1]) if dir is not None and len(dir) > 1: ddir = abs(dir[1] - dir[0]) E = ddir * spectrum.sum(1) else: E = np.squeeze(spectrum) Etot = 0.5 * sum(df * (E[1:] + E[:-1])) if tail and freq[-1] > 0.333: Etot += 0.25 * E[-1] * freq[-1] return 4.0 * np.sqrt(Etot)
[docs] def dpm(ipeak, momsin, momcos): """Mean direction at the peak wave period Dpm. Args: - ipeak (int): Index of the maximum energy density in the frequency spectrum E(f). - momsin (1darray): Sin component of the 1st directional moment. - momcos (1darray): Cos component of the 1st directional moment. Returns: - dpm (float): Mean direction at the frequency peak of the spectrum. """ if not ipeak: return np.nan else: dpm = np.arctan2(momsin[ipeak], momcos[ipeak]) return np.float32((270 - R2D * dpm) % 360.0)
[docs] def dp(ipeak, dir): """Peak wave direction Dp. Args: - ipeak (int): Index of the maximum energy density in the direction spectrum E(d). - dir (1darray): Wave direction array. Returns: - dp (float): Direction of the maximum energy density in the frequency-integrated spectrum. """ return np.float32(dir[ipeak])
def alpha(spectrum, freq, fp): """Phillips fetch dependant scaling coefficient. Args: - spectrum (1darray): Direction-integrated wave spectrum array E(f). - freq (1darray): Wave frequency array. - fp (float): Peak wave frequency (Hz). Returns: - alpha (float): Phillips constant. """ # Positions for fitting high-frequency tail pos = np.where((freq > 1.35 * fp) & (freq < 2.0 * fp))[0] if pos.size == 0: pos = [freq.size - 2, freq.size - 1] elif pos.size == 1: if pos[0] == freq.size[-1]: pos = [pos[0] - 1, pos[0]] else: pos = [pos[0], pos[0] + 1] s = spectrum[pos] f = freq[pos] term1 = (2 * pi) ** 4 / g**2 / ((pos[-1] - pos[0]) + 1) term2 = np.sum(s * f**5 * np.exp(1.25 * (fp / f) ** 4)) return np.float32(term1 * term2)
[docs] def tps(ipeak, spectrum, freq): """Smooth peak wave period Tp. Args: - ipeak (int): Index of the maximum energy density in frequency spectrum E(f). - spectrum (1darray): Direction-integrated wave spectrum array E(f). - freq (1darray): Wave frequency array. Returns: - tp (float): Period of the maximum energy density in the smooth spectrum. Note: - The smooth peak period is the peak of a parabolic fit around the spectral peak. It is the period commonly defined in SWAN and WW3 model output. """ if not ipeak: return np.nan else: f1 = freq[ipeak - 1] f2 = freq[ipeak] f3 = freq[ipeak + 1] e1 = spectrum[ipeak - 1] e2 = spectrum[ipeak] e3 = spectrum[ipeak + 1] s12 = f1 + f2 q12 = (e1 - e2) / (f1 - f2) q13 = (e1 - e3) / (f1 - f3) qa = (q13 - q12) / (f3 - f2) fp = (s12 - q12 / qa) / 2.0 return np.float32(1.0 / fp)
[docs] def tp(ipeak, spectrum, freq): """Peak wave period Tp. Args: - ipeak (int): Index of the maximum energy density in frequency spectrum E(f). - spectrum (1darray): Frequency wave spectrum array E(f). - freq (1darray): Wave frequency array. Returns: - tp (float): Period of the maximum energy density in the frequency spectrum. Note: - Arg spectrum is only defined so the signature is consistent with tps function. """ if not ipeak: return np.nan else: return np.float32(1.0 / freq[ipeak])
[docs] def dpspr(ipeak, fdspr): """Peak directional wave spread Dpspr. Args: - ipeak (int): Index of the maximum energy density in the frequency spectrum E(f). - fdsprd (1darray): Direction spread as a function of frequency :math:`\\sigma(f)`. Returns: - dpspr (float): Directional wave spreading at the peak wave frequency. """ if not ipeak: return np.nan else: return fdspr[ipeak]
[docs] def jonswap(freq, fpeak, hsig, gamma=3.3, alpha=0.0081, sigma_a=0.07, sigma_b=0.09): """Jonswap frequency spectrum for developing seas (Hasselmann et al., 1973). Args: - freq (1darray): Frequency array (Hz). - fpeak (float): Peak wave frequency (Hz). - hsig (float): Significant wave height (m), if provided the Jonswap spectra are scaled so that :math:`4\\sqrt{m_0} = hs`. - gamma (float): Peak enhancement parameter. - alpha (float): Phillip's fetch-dependent scaling coefficient. - sigma_a (float): width of the peak enhancement parameter for f <= fp. - sigma_b (float): width of the peak enhancement parameter for f > fp. Returns: - efth (SpecArray): Jonswap spectrum E(f) (m2s). Note: - This function is a numpy version of the `wavespectra.frequency.jonswap` function and is primarily defined for spectral fitting. - If `hs` is provided than the scaling parameter `alpha` becomes irrelevant. """ sigma = np.where(freq <= fpeak, sigma_a, sigma_b) term1 = alpha * g**2 * (2 * pi) ** -4 * freq**-5 term2 = np.exp(-(5 / 4) * (freq / fpeak) ** -4) term3 = gamma ** np.exp(-((freq - fpeak) ** 2) / (2 * sigma**2 * fpeak**2)) dsout = term1 * term2 * term3 if hsig is not None: dsout = dsout * (hsig / hs(dsout, freq)) ** 2 return dsout
[docs] def gaussian(freq, fpeak, hsig, gw): """Gaussian frequency spectrum (Bunney et al., 2014). Args: - freq (1darray): Frequency array (Hz). - fpeak (float): Peak wave frequency (Hz). - hsig (float): Significant wave height (m). - gw (float): Gaussian width parameter :math:`\sigma` (m2s). Returns: - efth (SpecArray): Gaussian frequency spectrum E(f) (m2s). Note: - This function is a numpy version of the `wavespectra.frequency.gaussian` function and is primarily defined for spectral fitting. """ mo = (hsig / 4) ** 2 return mo / (gw * np.sqrt(2 * pi)) * np.exp(-0.5 * ((freq - fpeak) / gw) ** 2)