marss 0.0.3

Mars celestial simulation crate for the MilkyWay SolarSystem workspace
Documentation
use sciforge::hub::domain::common::constants::DEGREE_TO_RAD;

pub const SIDEREAL_DAY_S: f64 = crate::SIDEREAL_DAY_S;
pub const SOL_S: f64 = crate::SOL_S;
pub const AXIAL_TILT_DEG: f64 = crate::AXIAL_TILT_DEG;
pub const AXIAL_TILT_RAD: f64 = AXIAL_TILT_DEG * DEGREE_TO_RAD;
pub const PRECESSION_PERIOD_YEARS: f64 = 170_000.0;

pub struct MarsRotation {
    pub angular_velocity_rad_s: f64,
    pub axial_tilt_rad: f64,
}

impl Default for MarsRotation {
    fn default() -> Self {
        Self::new()
    }
}

impl MarsRotation {
    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 * crate::MARS_EQUATORIAL_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 {
        crate::MOI_FACTOR * crate::MARS_MASS * crate::MARS_RADIUS * crate::MARS_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 solar_declination(&self, areocentric_longitude_deg: f64) -> f64 {
        let ls_rad = areocentric_longitude_deg.to_radians();
        (self.axial_tilt_rad.sin() * ls_rad.sin()).asin()
    }

    pub fn day_length_hours(&self, latitude_deg: f64, areocentric_longitude_deg: f64) -> f64 {
        let lat_rad = latitude_deg.to_radians();
        let decl = self.solar_declination(areocentric_longitude_deg);
        let cos_ha = -(lat_rad.tan() * decl.tan());
        if cos_ha > 1.0 {
            return 0.0;
        }
        if cos_ha < -1.0 {
            return 24.0 * SOL_S / 86400.0;
        }
        2.0 * cos_ha.acos() / (2.0 * std::f64::consts::PI) * SOL_S / 3600.0
    }
}