satellitesfactory 0.0.2

Satellite factory — classify, build and catalogue natural satellites for any planetary system: Solar System moons (Moon, Galileans, Titan, Triton…) or custom configurations.
Documentation
use crate::config::parameters::*;
use crate::engine::orbits::OrbitalElements;

pub type Vec3 = [f64; 3];

#[derive(Debug, Clone)]
pub struct Exomoon {
    pub name: String,
    pub parent: String,
    pub mass: f64,
    pub radius: f64,
    pub j2: f64,
    pub obliquity: f64,
    pub elements: OrbitalElements,
    pub albedo: f64,
    pub parent_mass: f64,
    pub star_mass: f64,
    pub star_planet_distance: f64,
}

impl Exomoon {
    pub fn new(
        name: &str,
        parent: &str,
        mass: f64,
        radius: f64,
        j2: f64,
        obliquity: f64,
        elements: OrbitalElements,
    ) -> Self {
        Self {
            name: name.to_string(),
            parent: parent.to_string(),
            mass,
            radius,
            j2,
            obliquity,
            elements,
            albedo: 0.30,
            parent_mass: 1.898e27,
            star_mass: M_SUN,
            star_planet_distance: AU,
        }
    }

    pub fn with_system(
        mut self,
        albedo: f64,
        parent_mass: f64,
        star_mass: f64,
        star_planet_distance: f64,
    ) -> Self {
        self.albedo = albedo;
        self.parent_mass = parent_mass;
        self.star_mass = star_mass;
        self.star_planet_distance = star_planet_distance;
        self
    }

    pub fn surface_gravity(&self) -> f64 {
        surface_gravity(self.mass, self.radius)
    }

    pub fn escape_velocity(&self) -> f64 {
        escape_velocity(self.mass, self.radius)
    }

    pub fn mean_density(&self) -> f64 {
        mean_density(self.mass, self.radius)
    }

    pub fn period(&self) -> f64 {
        self.elements.period(G * (self.parent_mass + self.mass))
    }

    pub fn to_cartesian(&self) -> (Vec3, Vec3) {
        crate::engine::orbits::elements_to_state(&self.elements, self.parent_mass + self.mass)
    }

    pub fn hill_radius(&self) -> f64 {
        self.star_planet_distance * (self.parent_mass / (3.0 * self.star_mass)).cbrt()
    }

    pub fn hill_stability_ratio(&self) -> f64 {
        self.elements.a / self.hill_radius()
    }

    pub fn is_hill_stable(&self) -> bool {
        self.hill_stability_ratio() < 0.49
    }

    pub fn transit_depth(&self) -> f64 {
        let r_star = (self.star_mass / M_SUN).powf(0.8) * R_SUN;
        (self.radius / r_star).powi(2)
    }

    pub fn transit_timing_variation(&self) -> f64 {
        let p_planet =
            (4.0 * std::f64::consts::PI * std::f64::consts::PI * self.star_planet_distance.powi(3)
                / (G * (self.star_mass + self.parent_mass)))
                .sqrt();
        let ratio = self.mass / self.parent_mass;
        p_planet * ratio * (self.elements.a / self.star_planet_distance)
    }

    pub fn equilibrium_temperature(&self) -> f64 {
        let l_star = L_SUN * (self.star_mass / M_SUN).powf(3.5);
        let factor = l_star * (1.0 - self.albedo)
            / (16.0
                * std::f64::consts::PI
                * STEFAN_BOLTZMANN
                * self.star_planet_distance
                * self.star_planet_distance);
        factor.powf(0.25)
    }

    pub fn tidal_locking_timescale(&self) -> f64 {
        let q = 100.0;
        let k2 = 0.03;
        let omega0 = 2.0 * std::f64::consts::PI / 36000.0;
        let prefactor = omega0 * self.elements.a.powi(6) * q;
        let denom = 3.0 * k2 * G * self.parent_mass * self.parent_mass * self.radius.powi(3);
        prefactor / denom
    }
}