moons 0.0.3

Moon celestial simulation crate for the MilkyWay SolarSystem workspace
Documentation
use moons::physics::collisions::{basin_forming_impactor, micrometeorite};
use moons::physics::orbit::LunarOrbit;
use moons::physics::rotation::MoonRotation;
use moons::physics::tides::{TidalResponse, earth_tidal_acceleration};

fn ensure_earth_binary() {
    let earth = moons::interactions::earths::ensure_earths_binary_or_simulate();
    assert!(earth.orbital_radius_km > 147_000_000.0);
    assert!(earth.orbital_radius_km < 152_500_000.0);
    assert!(earth.rotation_period_h > 23.0);
    assert!(earth.rotation_period_h < 25.0);
    assert!(earth.axial_tilt_deg > 20.0);
}

#[test]
fn earth_binary_is_available_for_physics_suite() {
    ensure_earth_binary();
}

#[test]
fn simulated_earth_fallback_has_orbit_and_rotation() {
    let earth = moons::interactions::earths::simulated_earth_context();
    assert_eq!(
        earth.mode,
        moons::interactions::earths::EarthRuntimeMode::Simulated
    );
    assert!((0.0..360.0).contains(&earth.orbital_angle_deg));
    assert!((0.0..360.0).contains(&earth.rotation_angle_deg));
    assert!(earth.surface_speed_m_s > 400.0);
}

#[test]
fn orbital_period_is_about_one_sidereal_month() {
    ensure_earth_binary();
    let orbit = LunarOrbit::new();
    let days = orbit.orbital_period_s() / 86_400.0;
    assert!((days - 27.32).abs() < 0.2);
}

#[test]
fn periapsis_is_smaller_than_apoapsis() {
    ensure_earth_binary();
    let orbit = LunarOrbit::new();
    assert!(orbit.periapsis_m() < orbit.apoapsis_m());
}

#[test]
fn rotation_is_synchronous_and_nonzero() {
    ensure_earth_binary();
    let rotation = MoonRotation::new();
    assert!(rotation.synchronous);
    assert!(rotation.equatorial_speed_m_s() > 0.0);
}

#[test]
fn tidal_acceleration_changes_sign_across_moon() {
    ensure_earth_binary();
    assert!(earth_tidal_acceleration(0.0) > 0.0);
    assert!(earth_tidal_acceleration(180.0) < 0.0);
}

#[test]
fn large_impactor_releases_more_energy() {
    ensure_earth_binary();
    let micro = micrometeorite();
    let basin = basin_forming_impactor();
    assert!(basin.kinetic_energy_j() > micro.kinetic_energy_j());
    assert!(TidalResponse::current().mean_displacement_m > 0.0);
}