# SPDX-License-Identifier: GPL-3.0-or-later
import numpy as np
import numpy.typing as npt
import deltares_coastal_structures_toolbox.functions.core_physics as core_physics
import deltares_coastal_structures_toolbox.functions.core_utility as core_utility
[docs]
def check_validity_range(
Hm0: float | npt.NDArray[np.float64] = np.nan,
Hm0_deep: float | npt.NDArray[np.float64] = np.nan,
Tmm10: float | npt.NDArray[np.float64] = np.nan,
beta: float | npt.NDArray[np.float64] = np.nan,
h: float | npt.NDArray[np.float64] = np.nan,
cot_alpha: float | npt.NDArray[np.float64] = np.nan,
Dn50: float | npt.NDArray[np.float64] = np.nan,
Rc: float | npt.NDArray[np.float64] = np.nan,
Ac: float | npt.NDArray[np.float64] = np.nan,
Gc: float | npt.NDArray[np.float64] = np.nan,
B_berm: float | npt.NDArray[np.float64] = np.nan,
db: float | npt.NDArray[np.float64] = np.nan,
) -> None:
"""Check the parameter values vs the validity range of the Van Gent et al. (2025) formula.
For all parameters supplied, their values are checked versus the validity range. Not that this
range is wider than that specified in Table 1 (Van Gent et al., 2025), since that does not describe
the entire data set the formula is derived from. When parameters are nan (by default), they are
not checked.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Hm0 : float | npt.NDArray[np.float64], optional
Spectral significant wave height (m), by default np.nan
Hm0_deep : float | npt.NDArray[np.float64], optional
Spectral significant wave height on deep water (m), by default np.nan
Tmm10 : float | npt.NDArray[np.float64], optional
Spectral wave period Tm-1,0 (s), by default np.nan
beta : float | npt.NDArray[np.float64], optional
Angle of wave incidence (degrees), by default np.nan
h : float | npt.NDArray[np.float64], optional
Water depth at toe of the structure (m), by default np.nan
cot_alpha : float | npt.NDArray[np.float64], optional
Cotangent of the front-side slope of the structure (-), by default np.nan
Dn50 : float | npt.NDArray[np.float64], optional
Nominal rock diameter (m), by default np.nan
Rc : float | npt.NDArray[np.float64], optional
Crest freeboard of the structure (m), by default np.nan
Ac : float | npt.NDArray[np.float64], optional
Armour crest freeboard of the structure (m), by default np.nan
Gc : float | npt.NDArray[np.float64], optional
Width of the crest of the structure (m), by default np.nan
B_berm : float | npt.NDArray[np.float64], optional
Berm width of the structure (m), by default np.nan
db : float | npt.NDArray[np.float64], optional
Berm height of the structure (m), by default np.nan
"""
if not np.any(np.isnan(cot_alpha)):
core_utility.check_variable_validity_range(
"Cotangent alpha slope", "Van Gent et al. (2025)", cot_alpha, 1.5, 8.0
)
if not np.any(np.isnan(Hm0)) and not np.any(np.isnan(Tmm10)):
smm10 = core_physics.calculate_wave_steepness_s(Hm0, Tmm10)
core_utility.check_variable_validity_range(
"Wave steepness sm-1,0", "Van Gent et al. (2025)", smm10, 0.001, 0.042
)
if (
not np.any(np.isnan(Hm0))
and not np.any(np.isnan(Tmm10))
and not np.any(np.isnan(cot_alpha))
):
ksi_smm10 = core_physics.calculate_Iribarren_number_ksi(Hm0, Tmm10, cot_alpha)
core_utility.check_variable_validity_range(
"Iribarren number ksi_m-1,0",
"Van Gent et al. (2025)",
ksi_smm10,
0.05,
6.0,
)
if not np.any(np.isnan(Hm0)) and not np.any(np.isnan(h)):
core_utility.check_variable_validity_range(
"Relative water depth h / Hm0",
"Van Gent et al. (2025)",
h / Hm0,
0.6,
5.0,
)
if not np.any(np.isnan(Hm0_deep)) and not np.any(np.isnan(h)):
core_utility.check_variable_validity_range(
"Ratio Hm0_deep / h",
"Van Gent et al. (2025)",
Hm0_deep / h,
0.0,
1.0,
)
if not np.any(np.isnan(Hm0)) and not np.any(np.isnan(Rc)):
core_utility.check_variable_validity_range(
"Non-dimensional crest freeboard Rc / Hm0",
"Van Gent et al. (2025)",
Rc / Hm0,
0.6,
5.0,
)
if not np.any(np.isnan(Hm0)) and not np.any(np.isnan(Dn50)):
core_utility.check_variable_validity_range(
"Non-dimensional stone diameter Dn50 / Hm0",
"Van Gent et al. (2025)",
Dn50 / Hm0,
0.12,
0.9,
)
if (
not np.any(np.isnan(Hm0))
and not np.any(np.isnan(Rc))
and not np.any(np.isnan(Ac))
):
core_utility.check_variable_validity_range(
"Non-dimensional protruding part of crest wall (Rc - Ac) / Hm0",
"Van Gent et al. (2025)",
(Rc - Ac) / Hm0,
0.0,
0.68,
)
if not np.any(np.isnan(Hm0)) and not np.any(np.isnan(Gc)):
core_utility.check_variable_validity_range(
"Non-dimensional armour width in front of crest wall Gc / Hm0",
"Van Gent et al. (2025)",
Rc / Hm0,
0.6,
5.0,
)
if not np.any(np.isnan(Hm0)) and not np.any(np.isnan(Rc)):
core_utility.check_variable_validity_range(
"Non-dimensional Berm width B / Hm0",
"Van Gent et al. (2025)",
B_berm / Hm0,
0.6,
5.0,
)
if not np.any(np.isnan(Hm0)) and not np.any(np.isnan(Rc)):
core_utility.check_variable_validity_range(
"Non-dimensional Berm height db / Hm0",
"Van Gent et al. (2025)",
db / Hm0,
-1.7,
0.5,
)
if not np.any(np.isnan(beta)):
core_utility.check_variable_validity_range(
"Incident wave angle beta", "Van Gent et al. (2025)", beta, 0.0, 75.0
)
return
[docs]
def calculate_overtopping_discharge_q(
Hm0: float | npt.NDArray[np.float64],
Hm0_swell: float | npt.NDArray[np.float64],
Tmm10: float | npt.NDArray[np.float64],
Rc: float | npt.NDArray[np.float64],
Ac: float | npt.NDArray[np.float64],
cot_alpha: float | npt.NDArray[np.float64] = np.nan,
beta: float | npt.NDArray[np.float64] = np.nan,
B_berm: float | npt.NDArray[np.float64] = 0.0,
db: float | npt.NDArray[np.float64] = 0.0,
Dn50: float | npt.NDArray[np.float64] = np.nan,
gamma_f: float | npt.NDArray[np.float64] = np.nan,
gamma_b: float | npt.NDArray[np.float64] = np.nan,
gamma_v: float | npt.NDArray[np.float64] = np.nan,
gamma_beta: float | npt.NDArray[np.float64] = np.nan,
g: float = 9.81,
design_calculation: bool = True,
include_influence_wind: bool = False,
) -> tuple[float | npt.NDArray[np.float64], bool | npt.NDArray[np.bool]]:
"""Calculate the mean wave overtopping discharge q with the Van Gent et al. (2025) formula.
The mean wave overtopping discharge q (m^3/s/m) is calculated using the Van Gent et al. (2025) formula.
Here, eq. B1 from Van Gent et al. (2025) is implemented.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
Hm0_swell : float | npt.NDArray[np.float64]
Spectral significant wave height of swell or infragravity waves in case of a second wave field (m)
Tmm10 : float | npt.NDArray[np.float64]
Spectral wave period Tm-1,0 (s)
Rc : float | npt.NDArray[np.float64]
Crest freeboard of the structure (m)
Ac : float | npt.NDArray[np.float64]
Armour crest freeboard of the structure (m)
cot_alpha : float | npt.NDArray[np.float64], optional
Cotangent of the front-side slope of the structure (-), by default np.nan
beta : float | npt.NDArray[np.float64], optional
Angle of wave incidence (degrees), by default np.nan
B_berm : float | npt.NDArray[np.float64], optional
Berm width of the structure (m), by default 0.0
db : float | npt.NDArray[np.float64], optional
Berm height of the structure (m), by default 0.0
Dn50 : float | npt.NDArray[np.float64], optional
Nominal rock diameter (m), by default np.nan
gamma_f : float | npt.NDArray[np.float64], optional
Influence factor for surface roughness (-), by default np.nan
gamma_b : float | npt.NDArray[np.float64], optional
Influence factor for a berm (-), by default np.nan
gamma_v : float | npt.NDArray[np.float64], optional
Influence factor for a crest wall (-), by default np.nan
gamma_beta : float | npt.NDArray[np.float64], optional
Influence factor for oblique wave incidence (-), by default np.nan
g : float, optional
Gravitational constant (m/s^2), by default 9.81
design_calculation : bool, optional
Use the 95% confidence level for design calculations, by default True
include_influence_wind : bool, optional
Include influence of wind on wave overtopping, by default False
Returns
-------
tuple[float | npt.NDArray[np.float64], bool | npt.NDArray[np.bool]]
Mean wave overtopping discharge q (m^3/s/m) and a boolean indicating
whether the maximum value formula was used
"""
q_diml, max_reached = calculate_dimensionless_overtopping_discharge_q(
Hm0=Hm0,
Hm0_swell=Hm0_swell,
Tmm10=Tmm10,
Rc=Rc,
Ac=Ac,
cot_alpha=cot_alpha,
beta=beta,
B_berm=B_berm,
db=db,
Dn50=Dn50,
gamma_f=gamma_f,
gamma_b=gamma_b,
gamma_v=gamma_v,
gamma_beta=gamma_beta,
design_calculation=design_calculation,
include_influence_wind=include_influence_wind,
)
q = q_diml * np.sqrt(g * Hm0**3)
return q, max_reached
[docs]
def calculate_dimensionless_overtopping_discharge_q(
Hm0: float | npt.NDArray[np.float64],
Hm0_swell: float | npt.NDArray[np.float64],
Tmm10: float | npt.NDArray[np.float64],
Rc: float | npt.NDArray[np.float64],
Ac: float | npt.NDArray[np.float64],
cot_alpha: float | npt.NDArray[np.float64] = np.nan,
beta: float | npt.NDArray[np.float64] = np.nan,
B_berm: float | npt.NDArray[np.float64] = 0.0,
db: float | npt.NDArray[np.float64] = 0.0,
Dn50: float | npt.NDArray[np.float64] = np.nan,
gamma_f: float | npt.NDArray[np.float64] = np.nan,
gamma_b: float | npt.NDArray[np.float64] = np.nan,
gamma_v: float | npt.NDArray[np.float64] = np.nan,
gamma_beta: float | npt.NDArray[np.float64] = np.nan,
design_calculation: bool = True,
include_influence_wind: bool = False,
) -> tuple[float | npt.NDArray[np.float64], bool | npt.NDArray[np.bool]]:
"""Calculate the dimensionless mean wave overtopping discharge q with the Van Gent et al. (2025) formula.
The dimensionless mean wave overtopping discharge q/sqrt(g*Hm0^3) (-) is calculated using the
Van Gent et al. (2025) formula. Here, eq. B1 from Van Gent et al. (2025) is implemented.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
Hm0_swell : float | npt.NDArray[np.float64]
Spectral significant wave height of swell or infragravity waves in case of a second wave field (m)
Tmm10 : float | npt.NDArray[np.float64]
Spectral wave period Tm-1,0 (s)
Rc : float | npt.NDArray[np.float64]
Crest freeboard of the structure (m)
Ac : float | npt.NDArray[np.float64]
Armour crest freeboard of the structure (m)
cot_alpha : float | npt.NDArray[np.float64], optional
Cotangent of the front-side slope of the structure (-), by default np.nan
beta : float | npt.NDArray[np.float64], optional
Angle of wave incidence (degrees), by default np.nan
B_berm : float | npt.NDArray[np.float64], optional
Berm width of the structure (m), by default 0.0
db : float | npt.NDArray[np.float64], optional
Berm height of the structure (m), by default 0.0
Dn50 : float | npt.NDArray[np.float64], optional
Nominal rock diameter (m), by default np.nan
gamma_f : float | npt.NDArray[np.float64], optional
Influence factor for surface roughness (-), by default np.nan
gamma_b : float | npt.NDArray[np.float64], optional
Influence factor for a berm (-), by default np.nan
gamma_v : float | npt.NDArray[np.float64], optional
Influence factor for a crest wall (-), by default np.nan
gamma_beta : float | npt.NDArray[np.float64], optional
Influence factor for oblique wave incidence (-), by default np.nan
design_calculation : bool, optional
Use the 95% confidence level for design calculations, by default True
include_influence_wind : bool, optional
Include influence of wind on wave overtopping, by default False
Returns
-------
tuple[float | npt.NDArray[np.float64], bool | npt.NDArray[np.bool]]
Dimensionless mean wave overtopping discharge q/sqrt(g*Hm0^3) (-)
and a boolean indicating whether the maximum value formula was used
Raises
------
ValueError
Raise an error if gamma_f is not provided and Dn50 is not provided so it cannot be calculated.
"""
if np.isnan(gamma_beta):
gamma_beta = calculate_influence_oblique_waves_gamma_beta(beta=beta)
ksi_mm10 = core_physics.calculate_Iribarren_number_ksi(
H=Hm0, T=Tmm10, cot_alpha=cot_alpha
)
if np.isnan(gamma_b):
smm10 = core_physics.calculate_wave_steepness_s(H=Hm0, T=Tmm10)
gamma_b = calculate_influence_berm_gamma_b(
Hm0=Hm0,
smm10=smm10,
Ac=Ac,
B_berm=B_berm,
BL=Ac - db,
)
if np.isnan(gamma_f):
if np.isnan(Dn50):
raise ValueError("Either gamma_f or Dn50 should be provided")
smm10 = core_physics.calculate_wave_steepness_s(H=Hm0, T=Tmm10)
gamma_f = calculate_influence_friction_gamma_f(Dn50=Dn50, Hm0=Hm0, smm10=smm10)
q_diml_eqB1 = (
6.8
* np.power(cot_alpha, -1.0)
* np.exp(
-5.0
* (Rc - 0.4 * Hm0_swell)
/ (gamma_f * gamma_b * gamma_v * gamma_beta * ksi_mm10 * Hm0)
)
)
q_diml_max = q_diml_max_equation(
Hm0=Hm0,
Hm0_swell=Hm0_swell,
ksi_mm10=ksi_mm10,
cot_alpha=cot_alpha,
Rc=Rc,
gamma_f=gamma_f,
gamma_b=gamma_b,
gamma_v=gamma_v,
gamma_beta=gamma_beta,
)
q_diml = np.min([q_diml_eqB1, q_diml_max], axis=0)
max_reached = np.min([q_diml_eqB1, q_diml_max], axis=0) == q_diml_max
if include_influence_wind:
gamma_w = calculate_influence_wind_gamma_w(
Rc=Rc,
Ac=Ac,
Hm0=Hm0,
q_diml=q_diml,
)
q_diml = q_diml * gamma_w
if design_calculation:
q_diml = np.power(q_diml, 0.857)
check_validity_range(
Hm0=Hm0,
Tmm10=Tmm10,
beta=beta,
cot_alpha=cot_alpha,
Dn50=Dn50,
Rc=Rc,
Ac=Ac,
B_berm=B_berm,
db=db,
)
return q_diml, max_reached
[docs]
def q_diml_max_equation(
Hm0: float | npt.NDArray[np.float64],
Hm0_swell: float | npt.NDArray[np.float64],
ksi_mm10: float | npt.NDArray[np.float64],
cot_alpha: float | npt.NDArray[np.float64],
Rc: float | npt.NDArray[np.float64],
gamma_f: float | npt.NDArray[np.float64],
gamma_b: float | npt.NDArray[np.float64],
gamma_v: float | npt.NDArray[np.float64],
gamma_beta: float | npt.NDArray[np.float64],
c2: float = 0.8,
c3: float = -2.5,
) -> float | npt.NDArray[np.float64]:
"""Calculate the maximum dimensionless mean wave overtopping discharge q with the Van Gent et al. (2025) formula.
The maximum value for the dimensionless mean wave overtopping discharge q/sqrt(g*Hm0^3) (-) is calculated
using the Van Gent et al. (2025) formula. Here, eq. B2 from Van Gent et al. (2025) is implemented.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
Hm0_swell : float | npt.NDArray[np.float64]
Spectral significant wave height of swell or infragravity waves in case of a second wave field (m)
ksi_mm10 : float | npt.NDArray[np.float64]
The Iribarren number based on the spectral wave period Tm-1,0 (-)
cot_alpha : float | npt.NDArray[np.float64]
Cotangent of the front-side slope of the structure (-)
Rc : float | npt.NDArray[np.float64]
Crest freeboard of the structure (m)
gamma_f : float | npt.NDArray[np.float64]
Influence factor for surface roughness (-)
gamma_b : float | npt.NDArray[np.float64]
Influence factor for a berm (-)
gamma_v : float | npt.NDArray[np.float64]
Influence factor for a crest wall (-)
gamma_beta : float | npt.NDArray[np.float64]
Influence factor for oblique wave incidence (-)
c2 : float, optional
Coefficient in wave overtopping formula (-), by default 0.8
c3 : float, optional
Coefficient in wave overtopping formula (-), by default -2.5
Returns
-------
float | npt.NDArray[np.float64]
Maximum value of the dimensionless mean wave overtopping discharge q/sqrt(g*Hm0^3) (-)
"""
q_diml_max = (
c2
* np.power(cot_alpha, -1.0)
* np.exp(
c3
* (Rc - 0.4 * Hm0_swell)
/ (
gamma_f
* gamma_b
* gamma_v
* gamma_beta
* np.power(ksi_mm10, 0.24)
* Hm0
)
)
)
return q_diml_max
[docs]
def calculate_influence_friction_gamma_f(
Dn50: float | npt.NDArray[np.float64],
Hm0: float | npt.NDArray[np.float64],
smm10: float | npt.NDArray[np.float64],
c_f1: float = 0.70,
c_f2: float = 0.05,
smm10_lim: float = 0.012,
) -> float | npt.NDArray[np.float64]:
"""Calculate influence factor for surface roughness gamma_f
The influence factor gamma_f is determined using Van Gent et al. (2025) eq. B3a for sm-1,0 >= smm10__lim
(0.012 by default) and eq. B3b for sm-1,0 < smm10__lim.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Dn50 : float | npt.NDArray[np.float64]
Nominal rock diameter (m)
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
smm10 : float | npt.NDArray[np.float64]
Deep water wave steepness based on the spectral wave period Tm-1,0 (-)
c_f1 : float, optional
Coefficient in the gamma_f formula, by default 0.70
c_f2 : float, optional
Coefficient in the gamma_f formula, by default 0.05
smm10_lim : float, optional
Limit for the deep water wave steepness (-), by default 0.012
Returns
-------
float | npt.NDArray[np.float64]
The influence factor for surface roughness gamma_f (-)
"""
gamma_f1 = 1.0 - c_f1 * np.power(Dn50 / Hm0, c_f2)
gamma_f = np.where(
smm10 >= smm10_lim,
gamma_f1,
gamma_f1 + 12.0 * (smm10_lim - smm10) * (1.0 - gamma_f1),
)
return gamma_f
[docs]
def calculate_influence_berm_gamma_b(
Hm0: float | npt.NDArray[np.float64],
smm10: float | npt.NDArray[np.float64],
Ac: float | npt.NDArray[np.float64],
B_berm: float | npt.NDArray[np.float64],
BL: float | npt.NDArray[np.float64],
c_b1: float = 18.0,
c_b2: float = 1.3,
c_b3: float = 0.34,
c_b4: float = 0.2,
) -> float | npt.NDArray[np.float64]:
"""Calculate influence factor for a berm gamma_b
The influence factor gamma_b is determined using Van Gent et al. (2025) eq. B4.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
smm10 : float | npt.NDArray[np.float64]
The deep water wave steepness based on the spectral wave period Tm-1,0 (-)
Ac : float | npt.NDArray[np.float64]
Armour crest freeboard of the structure (m)
B_berm : float | npt.NDArray[np.float64]
Berm width of the structure (m)
BL : float | npt.NDArray[np.float64]
Vertical distance of the berm relative to the crest of the armour Ac (m)
c_b1 : float, optional
Coefficient in the gamma_b formula, by default 18.0
c_b2 : float, optional
Coefficient in the gamma_b formula, by default 1.3
c_b3 : float, optional
Coefficient in the gamma_b formula, by default 0.34
c_b4 : float, optional
Coefficient in the gamma_b formula, by default 0.2
Returns
-------
float | npt.NDArray[np.float64]
The influence factor for a berm gamma_b (-)
"""
gamma_b = 1.0 - c_b1 * np.power(smm10 * B_berm / Hm0, c_b2) * (
1.0 - c_b3 * np.power(BL / (smm10 * Ac), c_b4)
)
return gamma_b
[docs]
def calculate_influence_oblique_waves_gamma_beta(
beta: float | npt.NDArray[np.float64],
c_beta: float = 0.35,
) -> float | npt.NDArray[np.float64]:
"""Calculate the influence factor for oblique wave incidence gamma_beta
The influence factor gamma_beta is determined using Van Gent et al. (2025) eq. B6
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
beta : float | npt.NDArray[np.float64]
Angle of wave incidence (degrees)
c_beta : float, optional
Coefficient in the gamma_beta formula, by default 0.35
Returns
-------
float | npt.NDArray[np.float64]
The influence factor for oblique wave incidence gamma_beta (-)
"""
gamma_beta = (1 - c_beta) * np.power(np.cos(np.radians(beta)), 2) + c_beta
return gamma_beta
[docs]
def calculate_influence_crest_wall_gamma_v(
cot_alpha: float | npt.NDArray[np.float64],
Rc: float | npt.NDArray[np.float64],
Ac: float | npt.NDArray[np.float64],
c_v: float = 0.45,
) -> float | npt.NDArray[np.float64]:
"""Calculate the influence factor for a crest wall gamma_v
The influence factor gamma_v is determined using Van Gent et al. (2025) eq. B5a for cot_alpha <= 4.0
and B5b for cot_alpha > 4.0.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
cot_alpha : float | npt.NDArray[np.float64]
Cotangent of the front-side slope of the structure (-)
Rc : float | npt.NDArray[np.float64]
Crest freeboard of the structure (m)
Ac : float | npt.NDArray[np.float64]
Armour crest freeboard of the structure (m)
c_v : float, optional
Coefficient in the gamma_v formula, by default 0.45
Returns
-------
float | npt.NDArray[np.float64]
The influence factor for a crest wall gamma_v (-)
"""
gamma_v = np.where(
cot_alpha <= 4.0,
1.0 + c_v * (Rc - Ac) / Rc,
1.0 + 0.1125 * cot_alpha * (Rc - Ac) / Rc,
)
return gamma_v
[docs]
def calculate_influence_wind_gamma_w(
Rc: float | npt.NDArray[np.float64],
Ac: float | npt.NDArray[np.float64],
Hm0: float | npt.NDArray[np.float64],
q_diml: float | npt.NDArray[np.float64],
c_w1: float = 0.075,
c_w2: float = -0.3,
) -> float | npt.NDArray[np.float64]:
"""Calculate the influence factor for wind gamma_w
The influence factor gamma_w is determined using Van Gent et al. (2025) eq. B7
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
hc : float | npt.NDArray[np.float64]
protruding part of a crest wall, hc = Rc - Ac (m)
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
q_diml : float | npt.NDArray[np.float64]
Dimensionless mean wave overtopping discharge q/sqrt(g*Hm0^3) (-)
Returns
-------
float | npt.NDArray[np.float64]
The influence factor for wind gamma_w (-)
"""
hc = Rc - Ac
gamma_w = 1.0 + c_w1 * (hc / Hm0) * np.power(q_diml, c_w2)
return gamma_w
[docs]
def calculate_crest_freeboard_Rc(
Hm0: float | npt.NDArray[np.float64],
Hm0_swell: float | npt.NDArray[np.float64],
Tmm10: float | npt.NDArray[np.float64],
q: float | npt.NDArray[np.float64],
Ac: float | npt.NDArray[np.float64],
cot_alpha: float | npt.NDArray[np.float64] = np.nan,
beta: float | npt.NDArray[np.float64] = np.nan,
B_berm: float | npt.NDArray[np.float64] = 0.0,
db: float | npt.NDArray[np.float64] = 0.0,
Dn50: float | npt.NDArray[np.float64] = np.nan,
gamma_f: float | npt.NDArray[np.float64] = np.nan,
gamma_b: float | npt.NDArray[np.float64] = np.nan,
gamma_v: float | npt.NDArray[np.float64] = np.nan,
gamma_beta: float | npt.NDArray[np.float64] = np.nan,
design_calculation: bool = True,
include_influence_wind: bool = False,
) -> tuple[float | npt.NDArray[np.float64], bool | npt.NDArray[np.bool]]:
"""Calculate the crest freeboard Rc with the Van Gent et al. (2025) formula.
The crest freeboard Rc (m) is calculated using the Van Gent et al. (2025) formula.
Here, eq. B1 from Van Gent et al. (2025) is implemented.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
Hm0_swell : float | npt.NDArray[np.float64]
Spectral significant wave height of swell or infragravity waves in case of a second wave field (m)
Tmm10 : float | npt.NDArray[np.float64]
Spectral wave period Tm-1,0 (s)
q : float | npt.NDArray[np.float64]
Mean wave overtopping discharge (m^3/s/m)
Ac : float | npt.NDArray[np.float64]
Armour crest freeboard of the structure (m)
cot_alpha : float | npt.NDArray[np.float64], optional
Cotangent of the front-side slope of the structure (-), by default np.nan
beta : float | npt.NDArray[np.float64], optional
Angle of wave incidence (degrees), by default np.nan
B_berm : float | npt.NDArray[np.float64], optional
Berm width of the structure (m), by default 0.0
db : float | npt.NDArray[np.float64], optional
Berm height of the structure (m), by default 0.0
Dn50 : float | npt.NDArray[np.float64], optional
Nominal rock diameter (m), by default np.nan
gamma_f : float | npt.NDArray[np.float64], optional
Influence factor for surface roughness (-), by default np.nan
gamma_b : float | npt.NDArray[np.float64], optional
Influence factor for a berm (-), by default np.nan
gamma_v : float | npt.NDArray[np.float64], optional
Influence factor for a crest wall (-), by default np.nan
gamma_beta : float | npt.NDArray[np.float64], optional
Influence factor for oblique wave incidence (-), by default np.nan
design_calculation : bool, optional
Use the 95% confidence level for design calculations, by default True
include_influence_wind : bool, optional
Include influence of wind on wave overtopping, by default False
Returns
-------
tuple[float | npt.NDArray[np.float64], bool | npt.NDArray[np.bool]]
The crest freeboard of the structure Rc (m) and a boolean indicating
whether the maximum value formula was used
"""
Rc_diml, max_reached = calculate_dimensionless_crest_freeboard(
Hm0=Hm0,
Hm0_swell=Hm0_swell,
Tmm10=Tmm10,
q=q,
Ac=Ac,
cot_alpha=cot_alpha,
beta=beta,
B_berm=B_berm,
db=db,
Dn50=Dn50,
gamma_f=gamma_f,
gamma_b=gamma_b,
gamma_v=gamma_v,
gamma_beta=gamma_beta,
design_calculation=design_calculation,
include_influence_wind=include_influence_wind,
)
Rc = Rc_diml * Hm0
return Rc, max_reached
[docs]
def calculate_dimensionless_crest_freeboard(
Hm0: float | npt.NDArray[np.float64],
Hm0_swell: float | npt.NDArray[np.float64],
Tmm10: float | npt.NDArray[np.float64],
q: float | npt.NDArray[np.float64],
Ac: float | npt.NDArray[np.float64],
cot_alpha: float | npt.NDArray[np.float64] = np.nan,
beta: float | npt.NDArray[np.float64] = np.nan,
B_berm: float | npt.NDArray[np.float64] = 0.0,
db: float | npt.NDArray[np.float64] = 0.0,
Dn50: float | npt.NDArray[np.float64] = np.nan,
gamma_f: float | npt.NDArray[np.float64] = np.nan,
gamma_b: float | npt.NDArray[np.float64] = np.nan,
gamma_v: float | npt.NDArray[np.float64] = np.nan,
gamma_beta: float | npt.NDArray[np.float64] = np.nan,
g: float = 9.81,
design_calculation: bool = True,
include_influence_wind: bool = False,
max_iter: int = 1000,
tolerance: float = 1e-5,
) -> tuple[float | npt.NDArray[np.float64], bool | npt.NDArray[np.bool]]:
"""Calculate the dimensionless crest freeboard Rc/Hm0 with the Van Gent et al. (2025) formula.
The dimensionless crest freeboard Rc/Hm0 (-) is calculated using the Van Gent et al. (2025) formula.
Here, eq. B1 from Van Gent et al. (2025) is implemented.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
Hm0_swell : float | npt.NDArray[np.float64]
Spectral significant wave height of swell or infragravity waves in case of a second wave field (m)
Tmm10 : float | npt.NDArray[np.float64]
Spectral wave period Tm-1,0 (s)
q : float | npt.NDArray[np.float64]
Mean wave overtopping discharge (m^3/s/m)
Ac : float | npt.NDArray[np.float64]
Armour crest freeboard of the structure (m)
cot_alpha : float | npt.NDArray[np.float64], optional
Cotangent of the front-side slope of the structure (-), by default np.nan
beta : float | npt.NDArray[np.float64], optional
Angle of wave incidence (degrees), by default np.nan
B_berm : float | npt.NDArray[np.float64], optional
Berm width of the structure (m), by default 0.0
db : float | npt.NDArray[np.float64], optional
Berm height of the structure (m), by default 0.0
Dn50 : float | npt.NDArray[np.float64], optional
Nominal rock diameter (m), by default np.nan
gamma_f : float | npt.NDArray[np.float64], optional
Influence factor for surface roughness (-), by default np.nan
gamma_b : float | npt.NDArray[np.float64], optional
Influence factor for a berm (-), by default np.nan
gamma_v : float | npt.NDArray[np.float64], optional
Influence factor for a crest wall (-), by default np.nan
gamma_beta : float | npt.NDArray[np.float64], optional
Influence factor for oblique wave incidence (-), by default np.nan
g : float, optional
Gravitational constant (m/s^2), by default 9.81
design_calculation : bool, optional
Use the 95% confidence level for design calculations, by default True
include_influence_wind : bool, optional
Include influence of wind on wave overtopping, by default False
max_iter : int, optional
Maximum number of iterations, by default 1000
tolerance : float, optional
Tolerance for convergence of the iterative solution, by default 1e-5
Returns
-------
tuple[float | npt.NDArray[np.float64], bool | npt.NDArray[np.bool]]
The dimensionless crest freeboard of the structure Rc/Hm0 (-) and a boolean indicating
whether the maximum value formula was used
Raises
------
ValueError
Raise an error if gamma_f is not provided and Dn50 is not provided so it cannot be calculated.
"""
if np.isnan(gamma_beta):
gamma_beta = calculate_influence_oblique_waves_gamma_beta(beta=beta)
ksi_mm10 = core_physics.calculate_Iribarren_number_ksi(
H=Hm0, T=Tmm10, cot_alpha=cot_alpha
)
if np.isnan(gamma_b):
smm10 = core_physics.calculate_wave_steepness_s(Hm0, Tmm10)
gamma_b = calculate_influence_berm_gamma_b(
Hm0=Hm0,
smm10=smm10,
Ac=Ac,
B_berm=B_berm,
BL=Ac - db,
)
if np.isnan(gamma_f):
if np.isnan(Dn50):
raise ValueError("Either gamma_f or Dn50 should be provided")
smm10 = core_physics.calculate_wave_steepness_s(Hm0, Tmm10)
gamma_f = calculate_influence_friction_gamma_f(Dn50=Dn50, Hm0=Hm0, smm10=smm10)
q_diml = q / np.sqrt(g * Hm0**3)
if design_calculation:
q_diml = np.power(q_diml, 1.0 / 0.857)
Rc_diml = (
np.log((1.0 / 6.8) * cot_alpha * q_diml)
* (-1.0 / 5.0)
* gamma_f
* gamma_b
* gamma_v
* gamma_beta
* ksi_mm10
+ 0.4 * Hm0_swell / Hm0
)
if include_influence_wind:
Rc_diff = np.inf
n_iter = 0
while np.max(Rc_diff) > tolerance and n_iter < max_iter:
n_iter += 1
gamma_w = calculate_influence_wind_gamma_w(
Rc=Rc_diml * Hm0,
Ac=Ac,
Hm0=Hm0,
q_diml=q_diml,
)
q_diml_iter = q_diml / gamma_w
Rc_diml_prev = Rc_diml
Rc_diml = (
np.log((1.0 / 6.8) * cot_alpha * q_diml_iter)
* (-1.0 / 5.0)
* gamma_f
* gamma_b
* gamma_v
* gamma_beta
* ksi_mm10
+ 0.4 * Hm0_swell / Hm0
)
Rc_diff = np.abs(Rc_diml - Rc_diml_prev)
Rc_diml_max = Rc_diml_max_equation(
Hm0=Hm0,
Hm0_swell=Hm0_swell,
q=q,
cot_alpha=cot_alpha,
ksi_mm10=ksi_mm10,
gamma_f=gamma_f,
gamma_b=gamma_b,
gamma_v=gamma_v,
gamma_beta=gamma_beta,
)
Rc_diml = np.min([Rc_diml, Rc_diml_max], axis=0)
max_reached = np.min([Rc_diml, Rc_diml_max], axis=0) == Rc_diml_max
check_validity_range(
Hm0=Hm0,
Tmm10=Tmm10,
beta=beta,
cot_alpha=cot_alpha,
Dn50=Dn50,
Rc=Rc_diml * Hm0,
Ac=Ac,
B_berm=B_berm,
db=db,
)
return Rc_diml, max_reached
[docs]
def Rc_diml_max_equation(
Hm0: float | npt.NDArray[np.float64],
Hm0_swell: float | npt.NDArray[np.float64],
q: float | npt.NDArray[np.float64],
cot_alpha: float | npt.NDArray[np.float64],
ksi_mm10: float | npt.NDArray[np.float64],
gamma_f: float | npt.NDArray[np.float64],
gamma_b: float | npt.NDArray[np.float64],
gamma_v: float | npt.NDArray[np.float64],
gamma_beta: float | npt.NDArray[np.float64],
c2: float = 0.8,
c3: float = -2.5,
g: float = 9.81,
) -> float | npt.NDArray[np.float64]:
"""Calculate the maximum dimensionless crest freeboard Rc/Hm0 with the Van Gent et al. (2025) formula.
The maximum value for the dimensionless crest freeboard Rc/Hm0 (-) is calculated
using the Van Gent et al. (2025) formula. Here, eq. B2 from Van Gent et al. (2025) is implemented.
For more details, see: https://doi.org/10.59490/jchs.2025.0048
Parameters
----------
Hm0 : float | npt.NDArray[np.float64]
Spectral significant wave height (m)
Hm0_swell : float | npt.NDArray[np.float64]
Spectral significant wave height of swell or infragravity waves in case of a second wave field (m)
q : float | npt.NDArray[np.float64]
Mean wave overtopping discharge (m^3/s/m)
cot_alpha : float | npt.NDArray[np.float64]
Cotangent of the front-side slope of the structure (-)
ksi_mm10 : float | npt.NDArray[np.float64]
_description_
gamma_f : float | npt.NDArray[np.float64]
Influence factor for surface roughness (-)
gamma_b : float | npt.NDArray[np.float64]
Influence factor for a berm (-)
gamma_v : float | npt.NDArray[np.float64]
Influence factor for a crest wall (-)
gamma_beta : float | npt.NDArray[np.float64]
Influence factor for oblique wave incidence (-)
c2 : float, optional
_description_, by default 0.8
c3 : float, optional
_description_, by default -2.5
g : float, optional
Gravitational constant (m/s^2), by default 9.81
Returns
-------
float | npt.NDArray[np.float64]
The maximum value of the dimensionless crest freeboard of the structure Rc/Hm0 (-)
"""
Rc_diml_max = (
np.log((1.0 / c2) * cot_alpha * q / np.sqrt(g * Hm0**3))
* (1.0 / c3)
* gamma_f
* gamma_b
* gamma_v
* gamma_beta
* np.power(ksi_mm10, 0.24)
+ 0.4 * Hm0_swell / Hm0
)
return Rc_diml_max