Spaces:
Sleeping
Sleeping
| """Kinetic-to-Potential Energy Transfer Ratio (KPR) | |
| Tracks the partition between kinetic and potential wave energy, | |
| identifying bore formation and nonlinear energy transfer. | |
| KPR = E_K / E_P = (H·u²) / (g·η²) | |
| """ | |
| import numpy as np | |
| class KineticPotentialRatio: | |
| """ | |
| Kinetic-to-Potential Energy Transfer Ratio - Parameter 2 of 7 | |
| Thresholds: | |
| SAFE: KPR < 1.2 (dispersive propagation) | |
| MONITOR: 1.2 ≤ KPR < 1.6 (moderate nonlinear shoaling) | |
| ALERT: 1.6 ≤ KPR < 2.0 (kinetic dominance) | |
| CRITICAL: KPR ≥ 2.0 (hydraulic bore formation) | |
| Linear equipartition: KPR = 1.0 | |
| """ | |
| def __init__(self, g=9.81, rho=1025): | |
| self.g = g | |
| self.rho = rho | |
| self.thresholds = { | |
| 'safe': 1.2, | |
| 'alert': 1.6, | |
| 'critical': 2.0 | |
| } | |
| def compute_kinetic_energy(self, H, u): | |
| """Depth-integrated kinetic energy per unit width | |
| E_K = ½·ρ·H·u² | |
| Args: | |
| H: water depth [m] | |
| u: depth-averaged velocity [m/s] | |
| Returns: | |
| E_K: kinetic energy per unit width [J/m] | |
| """ | |
| return 0.5 * self.rho * H * u**2 | |
| def compute_potential_energy(self, eta): | |
| """Potential energy from surface displacement | |
| E_P = ½·ρ·g·η² | |
| Args: | |
| eta: wave amplitude [m] | |
| Returns: | |
| E_P: potential energy per unit width [J/m] | |
| """ | |
| return 0.5 * self.rho * self.g * eta**2 | |
| def compute_kpr(self, H, u, eta): | |
| """Compute Kinetic-to-Potential Energy Ratio | |
| KPR = E_K / E_P = (H·u²) / (g·η²) | |
| Args: | |
| H: water depth [m] | |
| u: depth-averaged velocity [m/s] | |
| eta: wave amplitude [m] | |
| Returns: | |
| dict with KPR value, status, and energy components | |
| """ | |
| E_K = self.compute_kinetic_energy(H, u) | |
| E_P = self.compute_potential_energy(eta) | |
| kpr = E_K / E_P if E_P > 0 else float('inf') | |
| return { | |
| 'value': float(kpr), | |
| 'status': self.get_status(kpr), | |
| 'kinetic_energy': float(E_K), | |
| 'potential_energy': float(E_P), | |
| 'total_energy': float(E_K + E_P) | |
| } | |
| def get_status(self, kpr): | |
| """Get alert status based on KPR value""" | |
| if kpr < self.thresholds['safe']: | |
| return 'SAFE' | |
| elif kpr < self.thresholds['alert']: | |
| return 'MONITOR' | |
| elif kpr < self.thresholds['critical']: | |
| return 'ALERT' | |
| else: | |
| return 'CRITICAL' | |
| def compute_energy_flux(self, H, eta, c): | |
| """Compute energy flux (power per unit crest width) | |
| P_flux = ρ·g·η²·c [W/m] | |
| Args: | |
| H: water depth [m] | |
| eta: wave amplitude [m] | |
| c: wave celerity [m/s] | |
| Returns: | |
| P: energy flux [W/m] | |
| """ | |
| return self.rho * self.g * eta**2 * c | |
| def compute_concentration_factor(self, P_deep, P_shore): | |
| """Compute energy concentration factor | |
| Args: | |
| P_deep: deep ocean energy flux [W/m] | |
| P_shore: nearshore energy flux [W/m] | |
| Returns: | |
| concentration: factor | |
| """ | |
| return P_shore / P_deep | |
| def validate_event(self, H, u, eta, expected_kpr=None): | |
| """Validate KPR against expected values""" | |
| result = self.compute_kpr(H, u, eta) | |
| validation = { | |
| 'kpr': result, | |
| 'validation': {} | |
| } | |
| if expected_kpr is not None: | |
| error = abs(result['value'] - expected_kpr) / expected_kpr * 100 | |
| validation['validation']['expected'] = expected_kpr | |
| validation['validation']['error_percent'] = error | |
| return validation | |