earths 0.0.3

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::SECONDSPERDAY;
use sciforge::hub::domain::common::constants::{DEGREE_TO_RAD, EARTH_MASS, EARTH_RADIUS};
pub const SIDEREALDAYS: f64 = 86164.0905;
pub const SOLARDAYS: f64 = SECONDSPERDAY;
pub const AXIALTILTDEG: f64 = 23.4392811;
pub const AXIALTILTRAD: f64 = AXIALTILTDEG * DEGREE_TO_RAD;
pub const PRECESSIONPERIODYEARS: f64 = 25772.0;
pub const NUTATIONAMPLITUDEARCSEC: f64 = 9.2;
pub struct EarthRotation {
    pub angularvelocityrads: f64,
    pub axialtiltrad: f64,
}
impl Default for EarthRotation {
    fn default() -> Self {
        Self::new()
    }
}
impl EarthRotation {
    pub fn new() -> Self {
        Self {
            angularvelocityrads: 2.0 * std::f64::consts::PI / SIDEREALDAYS,
            axialtiltrad: AXIALTILTRAD,
        }
    }
    pub fn surfacevelocityatlatitude(&self, latitudedeg: f64) -> f64 {
        let latrad = latitudedeg.to_radians();
        self.angularvelocityrads * EARTH_RADIUS * latrad.cos()
    }
    pub fn centripetalaccelerationatlatitude(&self, latitudedeg: f64) -> f64 {
        let latrad = latitudedeg.to_radians();
        let omega = self.angularvelocityrads;
        omega * omega * EARTH_RADIUS * latrad.cos()
    }
    pub fn coriolisparameter(&self, latitudedeg: f64) -> f64 {
        let latrad = latitudedeg.to_radians();
        2.0 * self.angularvelocityrads * latrad.sin()
    }
    pub fn momentofinertia(&self) -> f64 {
        0.3307 * EARTH_MASS * EARTH_RADIUS * EARTH_RADIUS
    }
    pub fn rotationalkineticenergy(&self) -> f64 {
        0.5 * self.momentofinertia() * self.angularvelocityrads.powi(2)
    }
    pub fn angular_momentum(&self) -> f64 {
        self.momentofinertia() * self.angularvelocityrads
    }
    pub fn precession_rate_rad_per_year(&self) -> f64 {
        2.0 * std::f64::consts::PI / PRECESSIONPERIODYEARS
    }
    pub fn nutation_obliquity_rad(&self, juliancenturiessincej2000: f64) -> f64 {
        let t = juliancenturiessincej2000;
        let omegadeg = 125.04452 - 1934.136261 * t;
        let omegarad = omegadeg.to_radians();
        let deltaepsilonarcsec = NUTATIONAMPLITUDEARCSEC * omegarad.cos();
        deltaepsilonarcsec / 3600.0 * sciforge::hub::prelude::constants::DEGREE_TO_RAD
    }
    pub fn effective_tilt_rad(&self, juliancenturiessincej2000: f64) -> f64 {
        self.axialtiltrad + self.nutation_obliquity_rad(juliancenturiessincej2000)
    }
    pub fn day_length_variation_due_to_tilt(&self, dayofyear: u32, latitudedeg: f64) -> f64 {
        let latrad = latitudedeg.to_radians();
        let declination = self.axialtiltrad
            * (2.0 * std::f64::consts::PI * (dayofyear as f64 - 81.0)
                / crate::lighting::seasons::TROPICALYEARDAYS)
                .sin();
        let coshourangle = -(latrad.tan() * declination.tan());
        if coshourangle > 1.0 {
            return 0.0;
        }
        if coshourangle < -1.0 {
            return 24.0;
        }
        2.0 * coshourangle.acos() * 12.0 / std::f64::consts::PI
    }
}