venuss 0.0.2

Venus celestial simulation crate for the MilkyWay SolarSystem workspace
Documentation
use venuss::physics::collisions::{Impactor, mead_impactor, typical_venus_crosser};
use venuss::physics::orbit::VenusOrbit;
use venuss::physics::rotation::VenusRotation;
use venuss::physics::tides::{SolarTide, perihelion_aphelion_tide_ratio};

// ── Orbit ──

#[test]
fn orbital_period_about_225_days() {
    let o = VenusOrbit::new();
    assert!((o.orbital_period_days() - 224.7).abs() < 2.0);
}

#[test]
fn orbital_period_seconds_consistent() {
    let o = VenusOrbit::new();
    let days_from_s = o.orbital_period_s() / 86400.0;
    assert!((days_from_s - o.orbital_period_days()).abs() < 0.01);
}

#[test]
fn perihelion_less_than_aphelion() {
    let o = VenusOrbit::new();
    assert!(o.perihelion_m() < o.aphelion_m());
}

#[test]
fn semi_major_axis_between_peri_apo() {
    let o = VenusOrbit::new();
    assert!(o.perihelion_m() < o.semi_major_axis_m);
    assert!(o.semi_major_axis_m < o.aphelion_m());
}

#[test]
fn eccentricity_very_small() {
    let o = VenusOrbit::new();
    assert!(o.eccentricity < 0.01);
}

#[test]
fn escape_velocity_reasonable() {
    let v = VenusOrbit::escape_velocity_at_surface() / 1000.0;
    assert!(v > 9.0 && v < 11.0);
}

#[test]
fn velocity_at_perihelion_positive() {
    let o = VenusOrbit::new();
    let v = o.velocity_at_distance(o.perihelion_m());
    assert!(v > 0.0);
}

#[test]
fn velocity_faster_at_perihelion() {
    let o = VenusOrbit::new();
    let vp = o.velocity_at_distance(o.perihelion_m());
    let va = o.velocity_at_distance(o.aphelion_m());
    assert!(vp > va);
}

#[test]
fn gravitational_force_sun_positive() {
    let o = VenusOrbit::new();
    assert!(o.gravitational_force_sun() > 0.0);
}

#[test]
fn true_anomaly_finite() {
    let o = VenusOrbit::new();
    assert!(o.true_anomaly_rad().is_finite());
    assert!(o.true_anomaly_deg().is_finite());
}

#[test]
fn current_radius_positive() {
    let o = VenusOrbit::new();
    assert!(o.current_radius() > 0.0);
}

#[test]
fn mean_orbital_velocity_about_35kms() {
    let o = VenusOrbit::new();
    let v = o.mean_orbital_velocity() / 1000.0;
    assert!(v > 30.0 && v < 40.0);
}

#[test]
fn position_nonzero() {
    let o = VenusOrbit::new();
    let (x, y, z) = o.position();
    assert!(x * x + y * y + z * z > 0.0);
}

#[test]
fn solar_irradiance_positive() {
    let o = VenusOrbit::new();
    assert!(o.solar_irradiance() > 0.0);
}

#[test]
fn orbit_step_changes_anomaly() {
    let mut o = VenusOrbit::new();
    let a0 = o.mean_anomaly_rad;
    o.step(86400.0);
    assert!((o.mean_anomaly_rad - a0).abs() > 1e-10);
}

#[test]
fn orbit_default_same_as_new() {
    let d = VenusOrbit::default();
    let n = VenusOrbit::new();
    assert!((d.semi_major_axis_m - n.semi_major_axis_m).abs() < 1.0);
}

// ── Rotation ──

#[test]
fn rotation_is_retrograde() {
    let r = VenusRotation::new();
    assert!(r.angular_velocity_rad_s < 0.0);
}

#[test]
fn rotation_default_same_as_new() {
    let d = VenusRotation::default();
    let n = VenusRotation::new();
    assert!((d.angular_velocity_rad_s - n.angular_velocity_rad_s).abs() < 1e-15);
}

#[test]
fn axial_tilt_nearly_180() {
    let r = VenusRotation::new();
    assert!(r.axial_tilt_rad.to_degrees() > 170.0);
}

#[test]
fn surface_velocity_at_equator_slow() {
    let r = VenusRotation::new();
    let v = r.surface_velocity_at_latitude(0.0).abs();
    assert!(v > 0.0 && v < 10.0);
}

#[test]
fn surface_velocity_zero_at_pole() {
    let r = VenusRotation::new();
    let v = r.surface_velocity_at_latitude(90.0);
    assert!(v.abs() < 0.1);
}

#[test]
fn coriolis_negative_for_retrograde() {
    let r = VenusRotation::new();
    let c = r.coriolis_parameter(45.0);
    assert!(c < 0.0);
}

#[test]
fn moment_of_inertia_positive() {
    let r = VenusRotation::new();
    assert!(r.moment_of_inertia() > 0.0);
}

#[test]
fn rotational_kinetic_energy_positive() {
    let r = VenusRotation::new();
    assert!(r.rotational_kinetic_energy() > 0.0);
}

#[test]
fn angular_momentum_nonzero() {
    let r = VenusRotation::new();
    assert!(r.angular_momentum().abs() > 0.0);
}

#[test]
fn precession_rate_finite() {
    let r = VenusRotation::new();
    assert!(r.precession_rate_rad_per_year().is_finite());
}

#[test]
fn solar_declination_finite() {
    let r = VenusRotation::new();
    assert!(r.solar_declination(0.0).is_finite());
}

#[test]
fn day_length_hours_finite() {
    let r = VenusRotation::new();
    let h = r.day_length_hours(0.0, 0.0);
    assert!(h.is_finite() && h >= 0.0);
}

// ── Tides ──

#[test]
fn solar_tide_positive() {
    let t = SolarTide::at_mean_distance();
    assert!(t.tidal_acceleration() > 0.0);
}

#[test]
fn tidal_bulge_positive() {
    let t = SolarTide::at_mean_distance();
    assert!(t.tidal_bulge_height() > 0.0);
}

#[test]
fn tide_stronger_at_perihelion() {
    let p = SolarTide::at_perihelion().tidal_acceleration();
    let a = SolarTide::at_aphelion().tidal_acceleration();
    assert!(p > a);
}

#[test]
fn tidal_force_positive() {
    let t = SolarTide::at_mean_distance();
    assert!(t.gravitational_force() > 0.0);
}

#[test]
fn tide_at_custom_distance() {
    let t = SolarTide::at_distance(1.0e11);
    assert!(t.tidal_acceleration() > 0.0);
}

#[test]
fn perihelion_aphelion_ratio_gt_1() {
    assert!(perihelion_aphelion_tide_ratio() > 1.0);
}

// ── Collisions ──

#[test]
fn mead_impactor_energy_large() {
    let imp = mead_impactor();
    assert!(imp.kinetic_energy_j() > 1.0e20);
}

#[test]
fn mead_crater_positive() {
    let imp = mead_impactor();
    assert!(imp.crater_diameter_m() > 0.0);
}

#[test]
fn typical_venus_crosser_velocity_positive() {
    let imp = typical_venus_crosser();
    assert!(imp.velocity_m_s > 0.0);
}

#[test]
fn asteroid_mass_positive() {
    let imp = Impactor::asteroid(100.0, 25_000.0);
    assert!(imp.mass_kg() > 0.0);
}

#[test]
fn iron_asteroid_heavier() {
    let s = Impactor::asteroid(100.0, 25_000.0);
    let i = Impactor::iron_asteroid(100.0, 25_000.0);
    assert!(i.mass_kg() > s.mass_kg());
}

#[test]
fn impact_velocity_exceeds_initial() {
    let imp = Impactor::asteroid(100.0, 25_000.0);
    assert!(imp.impact_velocity() >= imp.velocity_m_s);
}

#[test]
fn kinetic_energy_mt_positive() {
    let imp = Impactor::asteroid(100.0, 25_000.0);
    assert!(imp.kinetic_energy_mt() > 0.0);
}

#[test]
fn ejecta_volume_positive() {
    let imp = Impactor::asteroid(100.0, 25_000.0);
    assert!(imp.ejecta_volume_m3() > 0.0);
}

// ── Constants ──

#[test]
fn venus_mass_close_to_earth() {
    const { assert!(venuss::VENUS_MASS > 4.0e24) };
    const { assert!(venuss::VENUS_MASS < 5.0e24) };
}

#[test]
fn venus_radius_about_6052km() {
    assert!((venuss::VENUS_RADIUS - 6_051_800.0).abs() < 1000.0);
}

#[test]
fn surface_gravity_about_8_87() {
    assert!((venuss::SURFACE_GRAVITY - 8.87).abs() < 0.1);
}

#[test]
fn semi_major_axis_about_0_72au() {
    assert!((venuss::SEMI_MAJOR_AXIS_AU - 0.723).abs() < 0.01);
}

#[test]
fn sidereal_day_negative_retrograde() {
    const { assert!(venuss::SIDEREAL_DAY_S < 0.0) };
}

#[test]
fn sol_positive() {
    const { assert!(venuss::SOL_S > 0.0) };
}

#[test]
fn axial_tilt_nearly_inverted() {
    const { assert!(venuss::AXIAL_TILT_DEG > 170.0) };
}

#[test]
fn omega_negative_retrograde() {
    const { assert!(venuss::OMEGA_VENUS < 0.0) };
}