diff --git a/lib/microwaveprop/backtest/features.ex b/lib/microwaveprop/backtest/features.ex index 00c26c7a..0903d88c 100644 --- a/lib/microwaveprop/backtest/features.ex +++ b/lib/microwaveprop/backtest/features.ex @@ -113,6 +113,52 @@ defmodule Microwaveprop.Backtest.Features do end end + @doc """ + Bulk Richardson number at the inversion top from the nearest native profile. + + Ri < 0.25 β†’ turbulent (bad for propagation) + Ri > 1.0 β†’ laminar (good for propagation) + + Returns nil if no inversion detected or no native profile available. + """ + @spec bulk_richardson(float, float, DateTime.t()) :: float | nil + def bulk_richardson(lat, lon, valid_time) do + with %HrrrNativeProfile{bulk_richardson: ri} when is_float(ri) <- + find_nearest_native(lat, lon, valid_time) do + ri + else + _ -> nil + end + end + + @doc """ + ΞΈβ‚‘ jump (K) across the inversion from the nearest native profile. + + Larger positive values indicate stronger thermodynamic decoupling. + """ + @spec theta_e_jump(float, float, DateTime.t()) :: float | nil + def theta_e_jump(lat, lon, valid_time) do + with %HrrrNativeProfile{theta_e_jump_k: jump} when is_float(jump) <- + find_nearest_native(lat, lon, valid_time) do + jump + else + _ -> nil + end + end + + @doc """ + Wind shear magnitude (m/s) at the inversion top from the nearest native profile. + """ + @spec shear_at_top(float, float, DateTime.t()) :: float | nil + def shear_at_top(lat, lon, valid_time) do + with %HrrrNativeProfile{shear_at_top_ms: shear} when is_float(shear) <- + find_nearest_native(lat, lon, valid_time) do + shear + else + _ -> nil + end + end + defp find_nearest_native(lat, lon, valid_time) do dlat = 0.07 dlon = 0.07