satellitesfactory 0.0.3

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::*;

pub struct TidalSystem {
    pub satellite_mass: f64,
    pub satellite_radius: f64,
    pub parent_mass: f64,
    pub parent_radius: f64,
    pub semi_major_axis: f64,
    pub eccentricity: f64,
    pub tidal_q: f64,
    pub love_number_k2: f64,
}

impl TidalSystem {
    pub fn new(
        satellite_mass: f64,
        satellite_radius: f64,
        parent_mass: f64,
        semi_major_axis: f64,
        eccentricity: f64,
    ) -> Self {
        Self {
            satellite_mass,
            satellite_radius,
            parent_mass,
            parent_radius: 7.1492e7,
            semi_major_axis,
            eccentricity,
            tidal_q: 100.0,
            love_number_k2: 0.025,
        }
    }

    pub fn with_tidal(mut self, parent_radius: f64, tidal_q: f64, love_number_k2: f64) -> Self {
        self.parent_radius = parent_radius;
        self.tidal_q = tidal_q;
        self.love_number_k2 = love_number_k2;
        self
    }

    pub fn tidal_heating_rate(&self) -> f64 {
        let n = (G * self.parent_mass / self.semi_major_axis.powi(3)).sqrt();
        let e2 = self.eccentricity * self.eccentricity;
        21.0 / 2.0 * self.love_number_k2 / self.tidal_q
            * G
            * self.parent_mass
            * self.parent_mass
            * self.satellite_radius.powi(5)
            * n
            * e2
            / self.semi_major_axis.powi(6)
    }

    pub fn tidal_heating_flux(&self) -> f64 {
        self.tidal_heating_rate()
            / (4.0 * std::f64::consts::PI * self.satellite_radius * self.satellite_radius)
    }

    pub fn tidal_locking_timescale(&self) -> f64 {
        let omega_0 = 2.0 * std::f64::consts::PI / (10.0 * 3600.0);
        let coeff = self.tidal_q * self.satellite_radius.powi(3) * self.semi_major_axis.powi(6)
            / (3.0
                * self.love_number_k2
                * G
                * self.parent_mass
                * self.parent_mass
                * self.satellite_radius.powi(2));
        coeff * self.satellite_mass * omega_0
    }

    pub fn orbital_decay_rate(&self) -> f64 {
        let n = (G * self.parent_mass / self.semi_major_axis.powi(3)).sqrt();
        -3.0 * self.love_number_k2 * self.satellite_mass * n * self.parent_radius.powi(5)
            / (self.tidal_q * self.parent_mass * self.semi_major_axis.powi(4))
    }

    pub fn circularization_timescale(&self) -> f64 {
        let n = (G * self.parent_mass / self.semi_major_axis.powi(3)).sqrt();
        if n < 1e-30 {
            return f64::INFINITY;
        }
        (2.0 * self.tidal_q * self.satellite_mass * self.semi_major_axis.powi(5) * n)
            / (63.0 * G * self.parent_mass * self.parent_mass * self.satellite_radius.powi(5))
    }

    pub fn equilibrium_temperature_from_tidal(&self) -> f64 {
        let flux = self.tidal_heating_flux();
        (flux / STEFAN_BOLTZMANN).powf(0.25)
    }
}

pub fn tidal_bulge_height(parent_mass: f64, satellite_radius: f64, distance: f64) -> f64 {
    parent_mass * satellite_radius.powi(4) / (G * distance.powi(3)) * G
}

pub fn dissipation_function(q: f64) -> f64 {
    1.0 / q
}

pub fn love_number_homogeneous(
    rigidity: f64,
    surface_gravity: f64,
    radius: f64,
    density: f64,
) -> f64 {
    let mu_tilde = 19.0 * rigidity / (2.0 * density * surface_gravity * radius);
    3.0 / (2.0 + mu_tilde)
}

pub fn resonance_width(m1: f64, m2: f64, parent_mass: f64, a: f64) -> f64 {
    a * 1.46 * ((m1 + m2) / parent_mass).powf(2.0 / 7.0)
}