asteroidsfactory 0.0.2

Asteroid factory — classify, build and catalogue asteroids of any type: near-Earth, main belt, trojan, centaur, binary, rubble pile, metallic, and potentially hazardous.
Documentation
use crate::config::parameters::*;

pub struct MetallicAsteroid {
    pub radius: f64,
    pub density: f64,
    pub mass: f64,
    pub iron_fraction: f64,
    pub nickel_fraction: f64,
    pub semi_major_axis: f64,
    pub eccentricity: f64,
    pub albedo: f64,
    pub radar_albedo: f64,
    pub thermal_inertia: f64,
}

impl MetallicAsteroid {
    pub fn new(radius_m: f64, iron_fraction: f64) -> Self {
        let radius = radius_m.clamp(MIN_ASTEROID_RADIUS, MAX_ASTEROID_RADIUS);
        let iron_fraction = iron_fraction.clamp(0.3, 0.95);
        let nickel_fraction = (1.0 - iron_fraction) * 0.3;
        let density = 3500.0 + 4500.0 * iron_fraction;
        let mass = sphere_mass(radius, density);

        Self {
            radius,
            density,
            mass,
            iron_fraction,
            nickel_fraction,
            semi_major_axis: 2.7,
            eccentricity: 0.15,
            albedo: 0.12,
            radar_albedo: 0.30 + 0.20 * iron_fraction,
            thermal_inertia: 100.0 + 300.0 * iron_fraction,
        }
    }

    pub fn with_orbit(mut self, semi_major_au: f64, ecc: f64) -> Self {
        self.semi_major_axis = semi_major_au.max(0.1);
        self.eccentricity = ecc.clamp(0.0, 0.999);
        self
    }

    pub fn with_nickel_fraction(mut self, ni: f64) -> Self {
        self.nickel_fraction = ni.clamp(0.01, 1.0 - self.iron_fraction);
        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 orbital_period(&self) -> f64 {
        orbital_period(self.semi_major_axis, SOLAR_MASS)
    }

    pub fn orbital_period_years(&self) -> f64 {
        self.orbital_period() / YEAR
    }

    pub fn metal_content_mass(&self) -> f64 {
        self.mass * (self.iron_fraction + self.nickel_fraction)
    }

    pub fn silicate_fraction(&self) -> f64 {
        1.0 - self.iron_fraction - self.nickel_fraction
    }

    pub fn is_differentiated(&self) -> bool {
        self.radius > 50000.0
    }

    pub fn core_radius_estimate(&self) -> f64 {
        self.radius * self.iron_fraction.powf(1.0 / 3.0)
    }

    pub fn magnetic_remanence_possible(&self) -> bool {
        self.iron_fraction > 0.5 && self.radius > 10000.0
    }

    pub fn thermal_conductivity_estimate(&self) -> f64 {
        10.0 + 50.0 * self.iron_fraction
    }

    pub fn absolute_magnitude(&self) -> f64 {
        let diameter_km = 2.0 * self.radius / 1000.0;
        15.618 - 5.0 * diameter_km.log10() - 2.5 * self.albedo.log10()
    }

    pub fn equilibrium_temperature(&self) -> f64 {
        equilibrium_temperature(SOLAR_LUMINOSITY, self.semi_major_axis * AU, self.albedo)
    }
}