earths 0.0.4

High-fidelity Earth simulation engine — orbit, atmosphere, geology, hydrology, biosphere, terrain, lighting, rendering, satellites, and temporal systems with full scientific coupling
Documentation
pub struct OceanEndpoint {
    pub wind_speed_m_s: f64,
    pub wind_direction: [f64; 2],
    pub fetch_km: f64,
    pub mean_depth_m: f64,
    pub salinity_psu: f64,
    pub surface_temperature_k: f64,
    pub surface_gravity_m_s2: f64,
    pub ior: f64,
    pub absorption_coefficients_rgb_m: [f64; 3],
    pub foam_threshold_wind_m_s: f64,
    pub grid_size: u32,
    pub patch_size_m: f64,
}

impl OceanEndpoint {
    pub fn earth_atlantic() -> Self {
        Self {
            wind_speed_m_s: 10.0,
            wind_direction: [1.0, 0.0],
            fetch_km: 500.0,
            mean_depth_m: 3_646.0,
            salinity_psu: 35.0,
            surface_temperature_k: 290.0,
            surface_gravity_m_s2: 9.806_65,
            ior: 1.333,
            absorption_coefficients_rgb_m: [0.45, 0.063, 0.019],
            foam_threshold_wind_m_s: 7.0,
            grid_size: 512,
            patch_size_m: 1_000.0,
        }
    }
    pub fn earth_pacific() -> Self {
        Self {
            wind_speed_m_s: 8.0,
            wind_direction: [0.7, 0.7],
            fetch_km: 800.0,
            mean_depth_m: 4_280.0,
            salinity_psu: 34.5,
            surface_temperature_k: 293.0,
            surface_gravity_m_s2: 9.806_65,
            ior: 1.333,
            absorption_coefficients_rgb_m: [0.45, 0.063, 0.019],
            foam_threshold_wind_m_s: 7.0,
            grid_size: 512,
            patch_size_m: 1_000.0,
        }
    }
    pub fn earth_arctic() -> Self {
        Self {
            wind_speed_m_s: 12.0,
            wind_direction: [0.5, -0.5],
            fetch_km: 200.0,
            mean_depth_m: 1_205.0,
            salinity_psu: 30.0,
            surface_temperature_k: 271.5,
            surface_gravity_m_s2: 9.806_65,
            ior: 1.309,
            absorption_coefficients_rgb_m: [0.42, 0.058, 0.017],
            foam_threshold_wind_m_s: 6.0,
            grid_size: 512,
            patch_size_m: 1_000.0,
        }
    }

    pub fn fresnel_r0(&self) -> f64 {
        ((self.ior - 1.0) / (self.ior + 1.0)).powi(2)
    }

    pub fn wave_amplitude(&self) -> f64 {
        let w = self.wind_speed_m_s.max(0.1);
        let grav = self.surface_gravity_m_s2;
        let fetch_m = self.fetch_km * 1000.0;
        let alpha_pm = 8.1e-3;
        let beta_pm = 0.74;
        let omega_p = grav / w * (beta_pm * (grav * fetch_m / (w * w)).powf(-0.33));
        let k_peak = omega_p * omega_p / grav;
        let pm_peak = alpha_pm * grav * grav / omega_p.powi(5)
            * (-beta_pm * (grav / (omega_p * w)).powi(4)).exp();
        let ocean_dx = self.patch_size_m / self.grid_size as f64;
        let nyquist_k = std::f64::consts::PI / ocean_dx;
        (2.0 * pm_peak / k_peak.min(nyquist_k))
            .sqrt()
            .clamp(0.01, 20.0)
    }

    pub fn depth_color(&self, depth: f64) -> [f64; 3] {
        let d = depth.min(200.0);
        [
            (-self.absorption_coefficients_rgb_m[0] * d).exp(),
            (-self.absorption_coefficients_rgb_m[1] * d).exp(),
            (-self.absorption_coefficients_rgb_m[2] * d).exp(),
        ]
    }
}