dwarfplanetsfactory 0.0.2

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 dwarfplanetsfactory::engine::evolution;
use dwarfplanetsfactory::engine::orbits;
use dwarfplanetsfactory::engine::resonance;
use dwarfplanetsfactory::observables::lightcurve;
use dwarfplanetsfactory::observables::photometry;

fn main() {
    // Orbital mechanics for Pluto-like
    let a_pluto: f64 = 39.5;
    let e_pluto: f64 = 0.25;
    let i_pluto: f64 = 17.0;

    let period = orbits::period_years(a_pluto);
    assert!((period - 248.0).abs() < 5.0);

    let tj = orbits::tisserand_neptune(a_pluto, e_pluto, i_pluto);
    assert!(tj > 0.0);

    let ecc_anom = orbits::kepler_solve(1.0, e_pluto);
    let check = ecc_anom - e_pluto * ecc_anom.sin();
    assert!((check - 1.0).abs() < 1.0e-10);

    let nu = orbits::true_anomaly(ecc_anom, e_pluto);
    let r = orbits::heliocentric_distance(a_pluto, e_pluto, nu);
    assert!(r > 0.0);

    let syn = orbits::synodic_period_neptune(a_pluto);
    assert!(syn > 0.0);

    // Resonance identification
    let a_res_23 = resonance::resonance_semi_major_axis(2, 3);
    assert!((a_res_23 - 39.4).abs() < 1.0);

    let near = resonance::is_near_resonance(39.5, 2, 3, 1.0);
    assert!(near);

    let width = resonance::resonance_width(2, 3, e_pluto);
    assert!(width > 0.0);

    let lib_p = resonance::libration_period_years(2, 3, e_pluto);
    assert!(lib_p > 0.0);

    let closest = resonance::closest_resonance(39.5, 1.0);
    assert!(closest.is_some());

    // Evolution
    let coll_lt = evolution::collisional_lifetime_years(5.0e5, 43.0);
    assert!(coll_lt > 0.0);

    let weather = evolution::weathering_timescale_years(43.0);
    assert!(weather > 0.0);

    let refresh = evolution::surface_refreshed_fraction(4.5e9, 43.0);
    assert!((0.0..=1.0).contains(&refresh));

    // Photometry
    let h_mag = photometry::absolute_magnitude(5.88e5, 0.1);
    assert!(h_mag < 10.0); // Pluto-sized → reasonably bright

    let app_mag = photometry::apparent_magnitude(h_mag, 39.5, 38.5, 1.0);
    assert!(app_mag > h_mag);

    let flux = photometry::thermal_flux(5.88e5, 0.1, 39.5, 38.5);
    assert!(flux > 0.0);

    let bv = photometry::color_index_bv(0.1, true);
    assert!(bv > 1.0); // ultra-red

    let ang = photometry::angular_diameter(5.88e5, 38.5);
    assert!(ang > 0.0);

    // Lightcurve
    let amp = lightcurve::amplitude_from_axis_ratio(1.2);
    assert!(amp > 0.0);

    let ratio = lightcurve::axis_ratio_from_amplitude(amp);
    assert!((ratio - 1.2).abs() < 1.0e-6);

    let omega = lightcurve::spin_rate(6.39 * 3600.0);
    assert!(omega > 0.0);

    let omega_crit = lightcurve::critical_spin_rate(1800.0);
    assert!(omega_crit > omega);

    let stable = lightcurve::is_rotationally_stable(6.39 * 3600.0, 1800.0);
    assert!(stable);

    let beta = lightcurve::phase_coefficient(0.1);
    assert!(beta > 0.0);
}