dwarfplanetsfactory 0.0.3

Dwarf planet factory — classify, build and catalogue dwarf planets of any type: Kuiper belt, scattered disk, plutino, cold classical, detached, binary, Ceres-type, and sednoid.
Documentation
use crate::config::parameters;

/// Collisional lifetime estimate (years) for a body in the Kuiper belt
/// Simplified model: t_coll ≈ k / (n σ v), expressed empirically.
pub fn collisional_lifetime_years(radius: f64, semi_major_au: f64) -> f64 {
    let cross_section = parameters::PI * radius * radius;
    if cross_section < 1.0 {
        return 0.0;
    }
    // Typical impactor number density scales as a^(-2.5)
    // Typical relative velocity ~ 1 km/s in the belt
    let n_density = 1.0e-25 * (40.0 / semi_major_au).powf(2.5);
    let v_rel = 1.0e3; // m/s
    let rate = n_density * cross_section * v_rel;
    if rate < 1.0e-30 {
        return f64::INFINITY;
    }
    (1.0 / rate) / parameters::YEAR
}

/// Space weathering timescale (years) — cosmic ray dose accumulation
/// Approximation: outer Solar System objects redden over ~1e8 years
pub fn weathering_timescale_years(semi_major_au: f64) -> f64 {
    // Farther objects have same CR flux but less solar wind contribution
    let base: f64 = 1.0e8; // years
    base * (semi_major_au / 40.0).sqrt()
}

/// Mass loss rate (kg/s) from sublimation of surface ices
/// at a given distance from the Sun
pub fn sublimation_mass_loss(radius: f64, albedo: f64, r_au: f64, ice_fraction: f64) -> f64 {
    let temp = parameters::equilibrium_temperature(r_au * parameters::AU, albedo);
    let sub_rate = crate::physics::thermal::n2_sublimation_rate(temp);
    let area = 4.0 * parameters::PI * radius * radius;
    area * sub_rate * ice_fraction.clamp(0.0, 1.0)
}

/// Timescale for significant volatile loss (years)
pub fn volatile_depletion_time_years(
    radius: f64,
    density: f64,
    albedo: f64,
    r_au: f64,
    ice_fraction: f64,
) -> f64 {
    let mass_loss = sublimation_mass_loss(radius, albedo, r_au, ice_fraction);
    if mass_loss < 1.0e-30 {
        return f64::INFINITY;
    }
    let ice_mass = parameters::sphere_mass(radius, density) * ice_fraction;
    (ice_mass / mass_loss) / parameters::YEAR
}

/// Surface rejuvenation: fraction of surface refreshed by
/// cryovolcanism or impact gardening over age (years)
pub fn surface_refreshed_fraction(age_years: f64, semi_major_au: f64) -> f64 {
    let coll_time = collisional_lifetime_years(5.0e5, semi_major_au);
    if coll_time <= 0.0 || coll_time.is_infinite() {
        return 0.0;
    }
    (1.0 - (-age_years / coll_time).exp()).clamp(0.0, 1.0)
}