Source code for deltares_coastal_structures_toolbox.functions.structural.stability_rock_armour.vandermeer1988

# 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( Hs: float | npt.NDArray[np.float64] = np.nan, H2p: float | npt.NDArray[np.float64] = np.nan, Tp: float | npt.NDArray[np.float64] = np.nan, N_waves: int | npt.NDArray[np.int32] = np.nan, cot_alpha: float | npt.NDArray[np.float64] = np.nan, P: float | npt.NDArray[np.float64] = np.nan, rho_armour: float | npt.NDArray[np.float64] = np.nan, ) -> None: """Check the parameter values vs the validity range of the Van der Meer (1988) formula For all parameters supplied, their values are checked versus the range of test conditions specified by Van der Meer (1988). When parameters are nan (by default), they are not checked. For more details see Van der Meer (1988), available here https://resolver.tudelft.nl/uuid:67e5692c-0905-4ddd-8487-37fdda9af6b4 Parameters ---------- Hs : float | npt.NDArray[np.float64], optional Significant wave height (m), by default np.nan H2p : float | npt.NDArray[np.float64], optional Wave height exceeded by 2% of waves H2% (m), by default np.nan Tp : float | npt.NDArray[np.float64], optional Peak wave period (s), by default np.nan N_waves : int | npt.NDArray[np.int32], optional Number of waves (-), 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 P : float | npt.NDArray[np.float64], optional Notional permeability coefficient (-), by default np.nan rho_armour : float | npt.NDArray[np.float64], optional Armour rock density (kg/m^3), by default np.nan """ if not np.any(np.isnan(P)): core_utility.check_variable_validity_range( "Notional permeability P", "Van der Meer (1988)", P, 0.1, 0.6 ) if not np.any(np.isnan(cot_alpha)): core_utility.check_variable_validity_range( "Cotangent of outer structure slope cot_alpha", "Van der Meer (1988)", cot_alpha, 1.1, 7.0, ) # TODO double check this: in formula only Tm is used, not Tp if not np.any(np.isnan(Hs)) and not np.any(np.isnan(Tp)): s0p = core_physics.calculate_wave_steepness_s(H=Hs, T=Tp) core_utility.check_variable_validity_range( "Wave steepness s0p", "Van der Meer (1988)", s0p, 0.005, 0.06 ) if not np.any(np.isnan(N_waves)): core_utility.check_variable_validity_range( "Number of waves N_waves", "Van der Meer (1988)", N_waves, 0, 7500 ) if not np.any(np.isnan(Hs)) and not np.any(np.isnan(H2p)): core_utility.check_variable_validity_range( "Ratio H2%/Hs", "Van der Meer (1988)", H2p / Hs, 1.10, 1.40 ) if not np.any(np.isnan(rho_armour)): core_utility.check_variable_validity_range( "Density of armour layer rock rho_armour", "Van der Meer (1988)", rho_armour, 2000, 3100, ) return
[docs] def calculate_damage_number_S( Hs: float | npt.NDArray[np.float64], H2p: float | npt.NDArray[np.float64], Tm: float | npt.NDArray[np.float64], N_waves: float | npt.NDArray[np.float64], cot_alpha: float | npt.NDArray[np.float64], P: float | npt.NDArray[np.float64], rho_armour: float | npt.NDArray[np.float64], Dn50: float | npt.NDArray[np.float64] = np.nan, M50: float | npt.NDArray[np.float64] = np.nan, c_pl: float = 8.7, c_s: float = 1.4, rho_water: float = 1025.0, ) -> float | npt.NDArray[np.float64]: """Calculate the damage number S for rock armour layers with the Van der Meer (1988) formula. For more details see Van der Meer (1988), available here https://resolver.tudelft.nl/uuid:67e5692c-0905-4ddd-8487-37fdda9af6b4 Note that for cot_alpha >= 4.0, the formula for plunging waves is used as mentioned in Van der Meer (1993), available here (see Section 4.2): https://resolver.tudelft.nl/uuid:5a09837f-65b3-4ecf-92f1-aa3e6dc56d47 Parameters ---------- Hs : float | npt.NDArray[np.float64] Significant wave height (m) H2p : float | npt.NDArray[np.float64] Wave height exceeded by 2% of waves H2% (m) Tm : float | npt.NDArray[np.float64] Mean wave period (s) N_waves : float | npt.NDArray[np.float64] Number of waves (-) cot_alpha : float | npt.NDArray[np.float64] Cotangent of the front-side slope of the structure (-) P : float | npt.NDArray[np.float64] Notional permeability coefficient (-) rho_armour : float | npt.NDArray[np.float64] Armour rock density (kg/m^3) Dn50 : float | npt.NDArray[np.float64], optional Nominal rock diameter (m), by default np.nan M50 : float | npt.NDArray[np.float64], optional Median rock mass (kg), by default np.nan c_pl : float, optional Coefficient for plunging waves (-), by default 8.7 c_s : float, optional Coefficient for surging waves (-), by default 1.4 rho_water : float, optional Water density (kg/m^3), by default 1025.0 Returns ------- float | npt.NDArray[np.float64] The damage number S (-) """ Dn50 = core_physics.check_usage_Dn50_or_M50(Dn50=Dn50, M50=M50, rho_rock=rho_armour) ksi_0m = core_physics.calculate_Iribarren_number_ksi( H=Hs, T=Tm, cot_alpha=cot_alpha ) ksi_mc = core_physics.calculate_critical_Iribarren_number_ksi_mc( c_pl=c_pl, c_s=c_s, P=P, cot_alpha=cot_alpha ) gamma_N = calculate_correction_term_gamma_N(N_waves=N_waves) Ns = core_physics.calculate_stability_number_Ns( H=Hs, D=Dn50, rho_rock=rho_armour, rho_water=rho_water ) # Plunging waves S_pl = ( np.power( Ns * (H2p / Hs) * (1 / c_pl) * np.power(P, -0.18) * np.power(ksi_0m, 0.5), 5, ) * (1 / gamma_N) * np.sqrt(N_waves) ) # Surging waves S_s = ( np.power( Ns * (H2p / Hs) * (1 / c_s) * np.power(P, 0.13) * (1 / np.sqrt(cot_alpha)) * np.power(ksi_0m, -P), 5, ) * (1 / gamma_N) * np.sqrt(N_waves) ) S = np.where((ksi_0m < ksi_mc) | (cot_alpha >= 4.0), S_pl, S_s) check_validity_range( P=P, Hs=Hs, cot_alpha=cot_alpha, H2p=H2p, rho_armour=rho_armour, N_waves=N_waves, ) return S
[docs] def calculate_nominal_rock_diameter_Dn50( Hs: float | npt.NDArray[np.float64], H2p: float | npt.NDArray[np.float64], Tm: float | npt.NDArray[np.float64], N_waves: float | npt.NDArray[np.float64], cot_alpha: float | npt.NDArray[np.float64], P: float | npt.NDArray[np.float64], rho_armour: float | npt.NDArray[np.float64], S: float | npt.NDArray[np.float64], c_pl: float = 8.7, c_s: float = 1.4, rho_water: float = 1025.0, ) -> float | npt.NDArray[np.float64]: """Calculate the nominal rock diameter Dn50 for rock armour layers with the Van der Meer (1988) formula. For more details see Van der Meer (1988), available here https://resolver.tudelft.nl/uuid:67e5692c-0905-4ddd-8487-37fdda9af6b4 Note that for cot_alpha >= 4.0, the formula for plunging waves is used as mentioned in Van der Meer (1993), available here (see Section 4.2): https://resolver.tudelft.nl/uuid:5a09837f-65b3-4ecf-92f1-aa3e6dc56d47 Parameters ---------- Hs : float | npt.NDArray[np.float64] Significant wave height (m) H2p : float | npt.NDArray[np.float64] Wave height exceeded by 2% of waves H2% (m) Tm : float | npt.NDArray[np.float64] Mean wave period (s) N_waves : float | npt.NDArray[np.float64] Number of waves (-) cot_alpha : float | npt.NDArray[np.float64] Cotangent of the front-side slope of the structure (-) P : float | npt.NDArray[np.float64] Notional permeability coefficient (-) rho_armour : float | npt.NDArray[np.float64] Armour rock density (kg/m^3) S : float | npt.NDArray[np.float64] Damage number (-) c_pl : float, optional Coefficient for plunging waves (-), by default 8.7 c_s : float, optional Coefficient for surging waves (-), by default 1.4 rho_water : float, optional Water density (kg/m^3), by default 1025.0 Returns ------- float | npt.NDArray[np.float64] The nominal rock diameter Dn50 (m) """ ksi_0m = core_physics.calculate_Iribarren_number_ksi( H=Hs, T=Tm, cot_alpha=cot_alpha ) ksi_mc = core_physics.calculate_critical_Iribarren_number_ksi_mc( c_pl=c_pl, c_s=c_s, P=P, cot_alpha=cot_alpha ) gamma_N = calculate_correction_term_gamma_N(N_waves=N_waves) Delta = core_physics.calculate_buoyant_density_Delta( rho_rock=rho_armour, rho_water=rho_water ) # Plunging waves Dn50_pl = ( (Hs / Delta) * (H2p / Hs) * (1 / c_pl) * np.power(P, -0.18) * np.power(gamma_N * S / np.sqrt(N_waves), -0.2) * np.power(ksi_0m, 0.5) ) # Surging waves Dn50_s = ( (Hs / Delta) * (H2p / Hs) * (1 / c_s) * np.power(P, 0.13) * np.power(gamma_N * S / np.sqrt(N_waves), -0.2) * (1 / np.sqrt(cot_alpha)) * np.power(ksi_0m, -P) ) Dn50 = np.where((ksi_0m < ksi_mc) | (cot_alpha >= 4.0), Dn50_pl, Dn50_s) check_validity_range( P=P, Hs=Hs, cot_alpha=cot_alpha, H2p=H2p, rho_armour=rho_armour, N_waves=N_waves, ) return Dn50
[docs] def calculate_significant_wave_height_Hs( ratio_H2p_Hs: float | npt.NDArray[np.float64], Tm: float | npt.NDArray[np.float64], N_waves: float | npt.NDArray[np.float64], cot_alpha: float | npt.NDArray[np.float64], P: float | npt.NDArray[np.float64], rho_armour: float | npt.NDArray[np.float64], S: float | npt.NDArray[np.float64], Dn50: float | npt.NDArray[np.float64] = np.nan, M50: float | npt.NDArray[np.float64] = np.nan, c_pl: float = 8.7, c_s: float = 1.4, g: float = 9.81, rho_water: float = 1025.0, ) -> float | npt.NDArray[np.float64]: """Calculate the maximum significant wave height Hs for rock armour layers with the Van der Meer (1988) formula. For more details see Van der Meer (1988), available here https://resolver.tudelft.nl/uuid:67e5692c-0905-4ddd-8487-37fdda9af6b4 Note that for cot_alpha >= 4.0, the formula for plunging waves is used as mentioned in Van der Meer (1993), available here (see Section 4.2): https://resolver.tudelft.nl/uuid:5a09837f-65b3-4ecf-92f1-aa3e6dc56d47 Parameters ---------- ratio_H2p_Hs : float | npt.NDArray[np.float64] Ratio between the Wave height exceeded by 2% of waves H2% and the significant wave height Hs, H2% / Hs (-) Tm : float | npt.NDArray[np.float64] Mean wave period (s) N_waves : float | npt.NDArray[np.float64] Number of waves (-) cot_alpha : float | npt.NDArray[np.float64] Cotangent of the front-side slope of the structure (-) P : float | npt.NDArray[np.float64] Notional permeability coefficient (-) rho_armour : float | npt.NDArray[np.float64] Armour rock density (kg/m^3) S : float | npt.NDArray[np.float64] Damage number (-) Dn50 : float | npt.NDArray[np.float64], optional Nominal rock diameter (m), by default np.nan M50 : float | npt.NDArray[np.float64], optional Median rock mass (kg), by default np.nan c_pl : float, optional Coefficient for plunging waves (-), by default 8.7 c_s : float, optional Coefficient for surging waves (-), by default 1.4 g : float, optional Gravitational constant (m/s^2), by default 9.81 rho_water : float, optional Water density (kg/m^3), by default 1025.0 Returns ------- float | npt.NDArray[np.float64] The significant wave height Hs (m) """ Dn50 = core_physics.check_usage_Dn50_or_M50(Dn50=Dn50, M50=M50, rho_rock=rho_armour) ksi_mc = core_physics.calculate_critical_Iribarren_number_ksi_mc( c_pl=c_pl, c_s=c_s, P=P, cot_alpha=cot_alpha ) gamma_N = calculate_correction_term_gamma_N(N_waves=N_waves) Delta = core_physics.calculate_buoyant_density_Delta( rho_rock=rho_armour, rho_water=rho_water ) # Plunging waves Hs_pl = np.power( c_pl * np.power(P, 0.18) * np.power(gamma_N * S / np.sqrt(N_waves), 0.2) * np.power(1.0 / cot_alpha, -0.5) * np.power((2 * np.pi / g) * (1.0 / np.power(Tm, 2)), 0.25) * Delta * Dn50 * (1 / ratio_H2p_Hs), 1.0 / 0.75, ) # Surging waves Hs_s = np.power( c_s * np.power(P, -0.13) * np.power(gamma_N * S / np.sqrt(N_waves), 0.2) * np.power(1.0 / cot_alpha, P) * np.power((2 * np.pi / g) * (1.0 / np.power(Tm, 2)), -0.5 * P) * np.power(1.0 / cot_alpha, -0.5) * Delta * Dn50 * (1 / ratio_H2p_Hs), 1.0 / (1.0 + 0.5 * P), ) ksi_0m_pl = core_physics.calculate_Iribarren_number_ksi( H=Hs_pl, T=Tm, cot_alpha=cot_alpha ) ksi_0m_s = core_physics.calculate_Iribarren_number_ksi( H=Hs_s, T=Tm, cot_alpha=cot_alpha ) Hs = np.where( ((ksi_0m_pl < ksi_mc) & (ksi_0m_s < ksi_mc)) | (cot_alpha >= 4.0), Hs_pl, Hs_s ) check_validity_range( Hs=Hs, N_waves=N_waves, cot_alpha=cot_alpha, P=P, rho_armour=rho_armour, ) return Hs
[docs] def calculate_correction_term_gamma_N( N_waves: int | npt.NDArray[np.int32], ) -> float | npt.NDArray[np.float64]: """Calculate the correction term gamma_N for the number of waves for rock armour layers with the Van der Meer (1988) formula. For more details see Van der Meer (1988), available here https://resolver.tudelft.nl/uuid:67e5692c-0905-4ddd-8487-37fdda9af6b4 Parameters ---------- N_waves : int | npt.NDArray[np.int32] Number of waves (-) Returns ------- float | npt.NDArray[np.float64] The correction term for the number of waves gamma_N (-) """ gamma_N_few = np.sqrt(1000 / N_waves) gamma_N_many = np.sqrt(N_waves) / ( np.sqrt(5000) * (1.3 * (1 - np.exp(-0.00031 * N_waves))) ) gamma_N_tmp = np.where(N_waves < 1000, gamma_N_few, 1.0) gamma_N = np.where(N_waves > 5000, gamma_N_many, gamma_N_tmp) return gamma_N