earths 0.0.1

High-fidelity Earth simulation engine — orbit, atmosphere, geology, hydrology, biosphere, terrain, lighting, rendering, satellites, and temporal systems with full scientific coupling
Documentation
use crate::temporal::calendar::SECONDS_PER_DAY;
use sciforge::hub::domain::common::constants::{DEGREE_TO_RAD, EARTH_MASS, EARTH_RADIUS};
pub const SIDEREAL_DAY_S: f64 = 86164.0905;
pub const SOLAR_DAY_S: f64 = SECONDS_PER_DAY;
pub const AXIAL_TILT_DEG: f64 = 23.4392811;
pub const AXIAL_TILT_RAD: f64 = AXIAL_TILT_DEG * DEGREE_TO_RAD;
pub const PRECESSION_PERIOD_YEARS: f64 = 25_772.0;
pub const NUTATION_AMPLITUDE_ARCSEC: f64 = 9.2;
pub struct EarthRotation {
    pub angular_velocity_rad_s: f64,
    pub axial_tilt_rad: f64,
}
impl Default for EarthRotation {
    fn default() -> Self {
        Self::new()
    }
}
impl EarthRotation {
    pub fn new() -> Self {
        Self {
            angular_velocity_rad_s: 2.0 * std::f64::consts::PI / SIDEREAL_DAY_S,
            axial_tilt_rad: AXIAL_TILT_RAD,
        }
    }
    pub fn surface_velocity_at_latitude(&self, latitude_deg: f64) -> f64 {
        let lat_rad = latitude_deg.to_radians();
        self.angular_velocity_rad_s * EARTH_RADIUS * lat_rad.cos()
    }
    pub fn centripetal_acceleration_at_latitude(&self, latitude_deg: f64) -> f64 {
        let lat_rad = latitude_deg.to_radians();
        let omega = self.angular_velocity_rad_s;
        omega * omega * EARTH_RADIUS * lat_rad.cos()
    }
    pub fn coriolis_parameter(&self, latitude_deg: f64) -> f64 {
        let lat_rad = latitude_deg.to_radians();
        2.0 * self.angular_velocity_rad_s * lat_rad.sin()
    }
    pub fn moment_of_inertia(&self) -> f64 {
        0.3307 * EARTH_MASS * EARTH_RADIUS * EARTH_RADIUS
    }
    pub fn rotational_kinetic_energy(&self) -> f64 {
        0.5 * self.moment_of_inertia() * self.angular_velocity_rad_s.powi(2)
    }
    pub fn angular_momentum(&self) -> f64 {
        self.moment_of_inertia() * self.angular_velocity_rad_s
    }
    pub fn precession_rate_rad_per_year(&self) -> f64 {
        2.0 * std::f64::consts::PI / PRECESSION_PERIOD_YEARS
    }
    pub fn nutation_obliquity_rad(&self, julian_centuries_since_j2000: f64) -> f64 {
        let t = julian_centuries_since_j2000;
        let omega_deg = 125.04452 - 1934.136261 * t;
        let omega_rad = omega_deg.to_radians();
        let delta_epsilon_arcsec = NUTATION_AMPLITUDE_ARCSEC * omega_rad.cos();
        delta_epsilon_arcsec / 3600.0 * sciforge::hub::prelude::constants::DEGREE_TO_RAD
    }
    pub fn effective_tilt_rad(&self, julian_centuries_since_j2000: f64) -> f64 {
        self.axial_tilt_rad + self.nutation_obliquity_rad(julian_centuries_since_j2000)
    }
    pub fn day_length_variation_due_to_tilt(&self, day_of_year: u32, latitude_deg: f64) -> f64 {
        let lat_rad = latitude_deg.to_radians();
        let declination = self.axial_tilt_rad
            * (2.0 * std::f64::consts::PI * (day_of_year as f64 - 81.0)
                / crate::lighting::seasons::TROPICAL_YEAR_DAYS)
                .sin();
        let cos_hour_angle = -(lat_rad.tan() * declination.tan());
        if cos_hour_angle > 1.0 {
            return 0.0;
        }
        if cos_hour_angle < -1.0 {
            return 24.0;
        }
        2.0 * cos_hour_angle.acos() * 12.0 / std::f64::consts::PI
    }
}