cometsfactory 0.0.3

Comet factory — classify, build and catalogue comets of any type: short-period, long-period, Halley-type, sungrazer, interstellar, main-belt comet, centaur-transition, and extinct.
Documentation
use crate::config::parameters;

/// Sun-grazing comets with extremely small perihelion distances.
/// Includes Kreutz, Marsden, Kracht, and Meyer groups.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SungrazerGroup {
    Kreutz,
    Marsden,
    Kracht,
    Meyer,
    Other,
}

#[derive(Debug)]
pub struct Sungrazer {
    pub nucleus_radius: f64,
    pub density: f64,
    pub albedo: f64,
    pub semi_major_axis: f64,
    pub eccentricity: f64,
    pub inclination: f64,
    pub group: SungrazerGroup,
    pub perihelion_distance_solar_radii: f64,
}

impl Sungrazer {
    pub fn new(nucleus_radius: f64, semi_major_axis: f64, eccentricity: f64) -> Self {
        let e = eccentricity.clamp(0.99, 0.99999);
        let a = semi_major_axis.max(10.0);
        let q_au = parameters::perihelion_au(a, e);
        let solar_radius_au = 0.00465;
        let q_solar_radii = q_au / solar_radius_au;
        Self {
            nucleus_radius: nucleus_radius.max(1.0),
            density: parameters::COMET_NUCLEUS_DENSITY,
            albedo: parameters::COMET_ALBEDO,
            semi_major_axis: a,
            eccentricity: e,
            inclination: 144.0,
            group: SungrazerGroup::Kreutz,
            perihelion_distance_solar_radii: q_solar_radii,
        }
    }

    pub fn with_density(mut self, density: f64) -> Self {
        self.density = density.clamp(100.0, 2000.0);
        self
    }

    pub fn with_albedo(mut self, albedo: f64) -> Self {
        self.albedo = albedo.clamp(0.01, 0.5);
        self
    }

    pub fn with_inclination(mut self, inclination: f64) -> Self {
        self.inclination = inclination.clamp(0.0, 180.0);
        self
    }

    pub fn with_group(mut self, group: SungrazerGroup) -> Self {
        self.group = group;
        self
    }

    pub fn mass(&self) -> f64 {
        parameters::sphere_mass(self.nucleus_radius, self.density)
    }

    pub fn perihelion(&self) -> f64 {
        parameters::perihelion_au(self.semi_major_axis, self.eccentricity)
    }

    pub fn aphelion(&self) -> f64 {
        parameters::aphelion_au(self.semi_major_axis, self.eccentricity)
    }

    /// Whether the comet passes inside the Roche limit for a fluid body
    /// (approx 2.5 solar radii).
    pub fn will_tidally_disrupt(&self) -> bool {
        self.perihelion_distance_solar_radii < 2.5
    }

    /// Equilibrium temperature at perihelion (K)
    pub fn perihelion_temperature(&self) -> f64 {
        let r_m = self.perihelion() * parameters::AU;
        parameters::equilibrium_temperature(r_m, self.albedo)
    }

    pub fn surface_gravity(&self) -> f64 {
        parameters::surface_gravity(self.mass(), self.nucleus_radius)
    }

    pub fn escape_velocity(&self) -> f64 {
        parameters::escape_velocity(self.mass(), self.nucleus_radius)
    }
}