use satellitesfactory::config::parameters::*;
use satellitesfactory::engine::orbits::OrbitalElements;
use satellitesfactory::types::captured::{CapturedComposition, CapturedSatellite};
use satellitesfactory::types::co_orbital_moon::{CoOrbitalMoon, CoOrbitalType};
use satellitesfactory::types::exomoon::Exomoon;
use satellitesfactory::types::icy_moon::IcyMoon;
use satellitesfactory::types::regular::{RegularSatellite, SatelliteClass};
use satellitesfactory::types::ring_moon::{RingAssociation, RingMoon};
use satellitesfactory::types::subsurface_ocean_moon::SubsurfaceOceanMoon;
use satellitesfactory::types::volcanic_moon::VolcanicMoon;
fn moon_elements() -> OrbitalElements {
OrbitalElements::from_km_deg(384_400.0, 0.054_9, 5.145, 125.08, 318.15, 135.27)
}
fn io_elements() -> OrbitalElements {
OrbitalElements::from_km_deg(421_700.0, 0.004_1, 0.05, 0.0, 0.0, 0.0)
}
fn europa_elements() -> OrbitalElements {
OrbitalElements::from_km_deg(671_100.0, 0.009_0, 0.47, 0.0, 0.0, 0.0)
}
fn ganymede_elements() -> OrbitalElements {
OrbitalElements::from_km_deg(1_070_400.0, 0.001_3, 0.18, 0.0, 0.0, 0.0)
}
fn triton_elements() -> OrbitalElements {
OrbitalElements::from_km_deg(354_759.0, 0.000_016, 156.865, 0.0, 0.0, 0.0)
}
fn phobos_elements() -> OrbitalElements {
OrbitalElements::from_km_deg(9_376.0, 0.015_1, 1.093, 0.0, 0.0, 0.0)
}
fn enceladus_elements() -> OrbitalElements {
OrbitalElements::from_km_deg(238_042.0, 0.004_7, 0.009, 0.0, 0.0, 0.0)
}
#[test]
fn regular_mass_ratio_is_one() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
)
.with_composition(SatelliteClass::Impact, 0.12, 0.0, 0.83);
assert!((moon.mass_moon() - 1.0).abs() < 1e-6);
}
#[test]
fn regular_radius_ratio_is_one() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
);
assert!((moon.radius_moon() - 1.0).abs() < 1e-6);
}
#[test]
fn regular_surface_gravity() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
);
let g = moon.surface_gravity();
assert!(g > 1.6 && g < 1.7);
}
#[test]
fn regular_escape_velocity() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
);
let v = moon.escape_velocity();
assert!(v > 2300.0 && v < 2400.0);
}
#[test]
fn regular_mean_density() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
);
let rho = moon.mean_density();
assert!(rho > 3300.0 && rho < 3400.0);
}
#[test]
fn regular_period_about_27_days() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
);
let p_days = moon.period(EARTH_MASS) / 86400.0;
assert!((p_days - 27.3).abs() < 0.5);
}
#[test]
fn regular_with_composition() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
)
.with_composition(SatelliteClass::Impact, 0.12, 0.0, 0.83);
assert_eq!(moon.class, SatelliteClass::Impact);
assert!(moon.ice_mass() == 0.0);
assert!(moon.rock_mass() > 0.0);
}
#[test]
fn regular_moment_of_inertia() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
)
.with_composition(SatelliteClass::Impact, 0.12, 0.0, 0.83);
let moi = moon.moment_of_inertia_factor();
assert!(moi > 0.3 && moi < 0.4);
}
#[test]
fn regular_cartesian_state() {
let moon = RegularSatellite::new(
"Moon",
"Earth",
MOON_MASS,
MOON_RADIUS,
2.034e-4,
6.687,
moon_elements(),
);
let (pos, vel) = moon.to_cartesian(EARTH_MASS);
let r = (pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]).sqrt();
let v = (vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]).sqrt();
assert!(r > 3.5e8 && r < 4.1e8);
assert!(v > 900.0 && v < 1200.0);
}
#[test]
fn regular_europa_has_ice() {
let europa = RegularSatellite::new(
"Europa",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_composition(SatelliteClass::Regular, 0.67, 0.08, 0.86);
assert!(europa.ice_fraction > 0.0);
assert!(europa.ice_mass() > 0.0);
}
#[test]
fn regular_ganymede_largest() {
let ganymede = RegularSatellite::new(
"Ganymede",
"Jupiter",
GANYMEDE_MASS,
GANYMEDE_RADIUS,
1.276e-4,
0.33,
ganymede_elements(),
);
let io = RegularSatellite::new(
"Io",
"Jupiter",
IO_MASS,
IO_RADIUS,
1.3e-3,
0.05,
io_elements(),
);
let europa = RegularSatellite::new(
"Europa",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
);
assert!(ganymede.radius > io.radius);
assert!(ganymede.radius > europa.radius);
}
#[test]
fn regular_io_denser_than_europa() {
let io = RegularSatellite::new(
"Io",
"Jupiter",
IO_MASS,
IO_RADIUS,
1.3e-3,
0.05,
io_elements(),
);
let europa = RegularSatellite::new(
"Europa",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
);
assert!(io.mean_density() > europa.mean_density());
}
#[test]
fn regular_positive_mass_and_radius() {
let sat = RegularSatellite::new(
"Test",
"Parent",
1e22,
1e6,
0.0,
0.0,
OrbitalElements::from_km_deg(400_000.0, 0.01, 1.0, 0.0, 0.0, 0.0),
);
assert!(sat.mass > 0.0);
assert!(sat.radius > 0.0);
assert!(sat.surface_gravity() > 0.0);
assert!(sat.escape_velocity() > 0.0);
}
#[test]
fn captured_retrograde() {
let triton = CapturedSatellite::new(
"Triton",
"Neptune",
TRITON_MASS,
TRITON_RADIUS,
0.0,
0.0,
triton_elements(),
)
.with_capture(0.76, true, 500.0, CapturedComposition::IceRich);
assert!(triton.is_retrograde());
}
#[test]
fn captured_ice_rich() {
let triton = CapturedSatellite::new(
"Triton",
"Neptune",
TRITON_MASS,
TRITON_RADIUS,
0.0,
0.0,
triton_elements(),
)
.with_capture(0.76, true, 500.0, CapturedComposition::IceRich);
assert_eq!(triton.composition, CapturedComposition::IceRich);
}
#[test]
fn captured_energy_positive() {
let triton = CapturedSatellite::new(
"Triton",
"Neptune",
TRITON_MASS,
TRITON_RADIUS,
0.0,
0.0,
triton_elements(),
)
.with_capture(0.76, true, 500.0, CapturedComposition::IceRich);
assert!(triton.capture_energy() > 0.0);
}
#[test]
fn captured_mass_ratio() {
let triton = CapturedSatellite::new(
"Triton",
"Neptune",
TRITON_MASS,
TRITON_RADIUS,
0.0,
0.0,
triton_elements(),
);
assert!(triton.mass_moon() > 0.2 && triton.mass_moon() < 0.4);
}
#[test]
fn captured_not_retrograde() {
let phobos = CapturedSatellite::new(
"Phobos",
"Mars",
PHOBOS_MASS,
PHOBOS_RADIUS,
0.0,
0.0,
phobos_elements(),
)
.with_capture(0.07, false, 200.0, CapturedComposition::Carbonaceous);
assert!(!phobos.is_retrograde());
}
#[test]
fn captured_carbonaceous() {
let phobos = CapturedSatellite::new(
"Phobos",
"Mars",
PHOBOS_MASS,
PHOBOS_RADIUS,
0.0,
0.0,
phobos_elements(),
)
.with_capture(0.07, false, 200.0, CapturedComposition::Carbonaceous);
assert_eq!(phobos.composition, CapturedComposition::Carbonaceous);
}
#[test]
fn captured_tiny() {
let phobos = CapturedSatellite::new(
"Phobos",
"Mars",
PHOBOS_MASS,
PHOBOS_RADIUS,
0.0,
0.0,
phobos_elements(),
);
assert!(phobos.mass_moon() < 0.001);
assert!(phobos.radius_moon() < 0.01);
}
#[test]
fn captured_tidal_circularization() {
let triton = CapturedSatellite::new(
"Triton",
"Neptune",
TRITON_MASS,
TRITON_RADIUS,
0.0,
0.0,
triton_elements(),
);
let t = triton.tidal_circularization_time(NEPTUNE_MASS, NEPTUNE_RADIUS, 100.0);
assert!(t.is_finite() && t > 0.0);
}
#[test]
fn captured_cartesian_state() {
let phobos = CapturedSatellite::new(
"Phobos",
"Mars",
PHOBOS_MASS,
PHOBOS_RADIUS,
0.0,
0.0,
phobos_elements(),
);
let (pos, vel) = phobos.to_cartesian(MARS_MASS);
let r = (pos[0] * pos[0] + pos[1] * pos[1] + pos[2] * pos[2]).sqrt();
assert!(r > 8e6 && r < 1e7);
let v = (vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]).sqrt();
assert!(v > 2000.0 && v < 2500.0);
}
#[test]
fn ring_moon_cryovolcanic() {
let enc = RingMoon::new(
"Enceladus",
"Saturn",
ENCELADUS_MASS,
ENCELADUS_RADIUS,
enceladus_elements(),
)
.with_ring(0.99, RingAssociation::Embedded, true, 0.57);
assert!(enc.is_cryovolcanic());
}
#[test]
fn ring_moon_plume_escape() {
let enc = RingMoon::new(
"Enceladus",
"Saturn",
ENCELADUS_MASS,
ENCELADUS_RADIUS,
enceladus_elements(),
)
.with_ring(0.99, RingAssociation::Embedded, true, 0.57);
let frac = enc.plume_escape_fraction();
assert!(frac > 0.0 && frac < 1.0);
}
#[test]
fn ring_moon_ice_and_rock() {
let enc = RingMoon::new(
"Enceladus",
"Saturn",
ENCELADUS_MASS,
ENCELADUS_RADIUS,
enceladus_elements(),
)
.with_ring(0.99, RingAssociation::Embedded, true, 0.57);
assert!(enc.ice_mass() > 0.0);
assert!(enc.rock_mass() > 0.0);
let total = enc.ice_mass() + enc.rock_mass();
assert!((total - enc.mass).abs() / enc.mass < 1e-12);
}
#[test]
fn ring_moon_gap_keeper() {
let mimas = RingMoon::new(
"Mimas",
"Saturn",
MIMAS_MASS,
MIMAS_RADIUS,
OrbitalElements::from_km_deg(185_520.0, 0.019_6, 1.574, 0.0, 0.0, 0.0),
)
.with_ring(0.96, RingAssociation::GapKeeper, false, 0.50);
assert_eq!(mimas.ring_association, RingAssociation::GapKeeper);
}
#[test]
fn ring_moon_not_cryovolcanic() {
let mimas = RingMoon::new(
"Mimas",
"Saturn",
MIMAS_MASS,
MIMAS_RADIUS,
OrbitalElements::from_km_deg(185_520.0, 0.019_6, 1.574, 0.0, 0.0, 0.0),
)
.with_ring(0.96, RingAssociation::GapKeeper, false, 0.50);
assert!(!mimas.is_cryovolcanic());
assert!(mimas.plume_escape_fraction() == 0.0);
}
#[test]
fn ring_moon_shepherd() {
let prom = RingMoon::new(
"Prometheus",
"Saturn",
PROMETHEUS_MASS,
PROMETHEUS_RADIUS,
OrbitalElements::from_km_deg(139_380.0, 0.002_2, 0.008, 0.0, 0.0, 0.0),
)
.with_ring(0.60, RingAssociation::Shepherd, false, 0.70);
assert_eq!(prom.ring_association, RingAssociation::Shepherd);
}
#[test]
fn ring_moon_density() {
let enc = RingMoon::new(
"Enceladus",
"Saturn",
ENCELADUS_MASS,
ENCELADUS_RADIUS,
enceladus_elements(),
);
let rho = enc.mean_density();
assert!(rho > 1000.0 && rho < 2000.0);
}
#[test]
fn ring_moon_positive() {
let m = RingMoon::new(
"TestRing",
"Parent",
1e18,
1e5,
OrbitalElements::from_km_deg(200_000.0, 0.001, 0.01, 0.0, 0.0, 0.0),
);
assert!(m.mass > 0.0);
assert!(m.radius > 0.0);
assert!(m.surface_gravity() > 0.0);
assert!(m.escape_velocity() > 0.0);
assert!(m.period(SATURN_MASS) > 0.0);
}
#[test]
fn volcanic_surface_gravity() {
let v = VolcanicMoon::new(
"Io-like",
"Jupiter",
IO_MASS,
IO_RADIUS,
1.3e-3,
0.05,
io_elements(),
)
.with_volcanism(0.63, 0.94, 100.0, 1e4);
let g = v.surface_gravity();
assert!(g > 1.7 && g < 1.9);
}
#[test]
fn volcanic_tidal_heating() {
let v = VolcanicMoon::new(
"Io-like",
"Jupiter",
IO_MASS,
IO_RADIUS,
1.3e-3,
0.05,
io_elements(),
)
.with_volcanism(0.63, 0.94, 100.0, 1e4);
let h = v.tidal_heating(JUPITER_MASS);
assert!(h > 0.0);
}
#[test]
fn volcanic_resurfacing() {
let v = VolcanicMoon::new(
"Io-like",
"Jupiter",
IO_MASS,
IO_RADIUS,
1.3e-3,
0.05,
io_elements(),
)
.with_volcanism(0.63, 0.94, 100.0, 1e4);
let t = v.resurfacing_timescale();
assert!(t > 0.0 && t.is_finite());
}
#[test]
fn volcanic_magma_ocean() {
let v = VolcanicMoon::new(
"Io-like",
"Jupiter",
IO_MASS,
IO_RADIUS,
1.3e-3,
0.05,
io_elements(),
)
.with_volcanism(0.63, 0.94, 100.0, 1e4);
let d = v.magma_ocean_depth(JUPITER_MASS);
assert!(d >= 0.0);
}
#[test]
fn volcanic_atmosphere() {
let v = VolcanicMoon::new(
"Io-like",
"Jupiter",
IO_MASS,
IO_RADIUS,
1.3e-3,
0.05,
io_elements(),
)
.with_volcanism(0.63, 0.94, 100.0, 1e4);
let col = v.atmosphere_column_density();
assert!(col > 0.0);
}
#[test]
fn icy_surface_gravity() {
let icy = IcyMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_surface(0.67, 0.08, 0.86, 102.0);
let g = icy.surface_gravity();
assert!(g > 1.2 && g < 1.5);
}
#[test]
fn icy_ice_shell() {
let icy = IcyMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_surface(0.67, 0.08, 0.86, 102.0);
let t = icy.ice_shell_thickness();
assert!(t > 0.0);
}
#[test]
fn icy_sublimation() {
let icy = IcyMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_surface(0.67, 0.50, 0.45, 102.0);
let rate = icy.sublimation_rate();
assert!(rate >= 0.0);
}
#[test]
fn icy_thermal_inertia() {
let icy = IcyMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_surface(0.67, 0.50, 0.45, 102.0);
let ti = icy.thermal_inertia();
assert!(ti > 0.0);
}
#[test]
fn icy_crater_age() {
let icy = IcyMoon::new(
"Test",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
0.0,
0.0,
europa_elements(),
)
.with_surface(0.67, 0.50, 0.45, 102.0);
let age = icy.crater_retention_age(1e-14);
assert!(age > 0.0);
}
#[test]
fn icy_ice_and_rock_mass() {
let icy = IcyMoon::new("Test", "Jupiter", 1e22, 1e6, 0.0, 0.0, europa_elements())
.with_surface(0.5, 0.40, 0.55, 100.0);
assert!(icy.ice_mass() > 0.0);
assert!(icy.rock_mass() > 0.0);
}
#[test]
fn ocean_depth_positive() {
let o = SubsurfaceOceanMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_ocean(0.67, 20.0e3, 35.0, 50.0);
let d = o.ocean_depth();
assert!(d >= 0.0);
}
#[test]
fn ocean_volume_positive() {
let o = SubsurfaceOceanMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_ocean(0.67, 20.0e3, 35.0, 50.0);
let v = o.ocean_volume();
assert!(v > 0.0);
}
#[test]
fn ocean_pressure_positive() {
let o = SubsurfaceOceanMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_ocean(0.67, 20.0e3, 35.0, 50.0);
let p = o.ocean_pressure_bottom();
assert!(p > 0.0);
}
#[test]
fn ocean_tidal_heating() {
let o = SubsurfaceOceanMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_ocean(0.67, 20.0e3, 35.0, 50.0);
let h = o.tidal_heating(JUPITER_MASS);
assert!(h > 0.0);
}
#[test]
fn ocean_heat_flux() {
let o = SubsurfaceOceanMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_ocean(0.67, 20.0e3, 35.0, 50.0);
let flux = o.heat_flux_through_ice();
assert!(flux > 0.0);
}
#[test]
fn ocean_habitability() {
let o = SubsurfaceOceanMoon::new(
"Europa-like",
"Jupiter",
EUROPA_MASS,
EUROPA_RADIUS,
4.355e-4,
0.1,
europa_elements(),
)
.with_ocean(0.67, 20.0e3, 35.0, 50.0);
let h = o.habitability_index(JUPITER_MASS);
assert!((0.0..=1.0).contains(&h));
}
#[test]
fn exomoon_hill_stable() {
let ex = Exomoon::new(
"Exo-1",
"HotJup",
1e23,
2e6,
0.0,
0.0,
OrbitalElements::from_km_deg(500_000.0, 0.01, 1.0, 0.0, 0.0, 0.0),
)
.with_system(0.30, JUPITER_MASS, M_SUN, AU);
assert!(ex.is_hill_stable());
}
#[test]
fn exomoon_transit_depth() {
let ex = Exomoon::new(
"Exo-1",
"HotJup",
1e23,
6.371e6,
0.0,
0.0,
OrbitalElements::from_km_deg(500_000.0, 0.01, 1.0, 0.0, 0.0, 0.0),
)
.with_system(0.30, JUPITER_MASS, M_SUN, AU);
let td = ex.transit_depth();
assert!(td > 0.0 && td < 1e-3);
}
#[test]
fn exomoon_ttv_small() {
let ex = Exomoon::new(
"Exo-1",
"HotJup",
1e22,
1e6,
0.0,
0.0,
OrbitalElements::from_km_deg(500_000.0, 0.01, 1.0, 0.0, 0.0, 0.0),
)
.with_system(0.30, JUPITER_MASS, M_SUN, AU);
let ttv = ex.transit_timing_variation();
assert!(ttv > 0.0);
}
#[test]
fn exomoon_equilibrium_temperature() {
let ex = Exomoon::new(
"Exo-1",
"HotJup",
1e23,
2e6,
0.0,
0.0,
OrbitalElements::from_km_deg(500_000.0, 0.01, 1.0, 0.0, 0.0, 0.0),
)
.with_system(0.30, JUPITER_MASS, M_SUN, AU);
let t = ex.equilibrium_temperature();
assert!(t > 200.0 && t < 400.0);
}
#[test]
fn exomoon_tidal_locking() {
let ex = Exomoon::new(
"Exo-1",
"HotJup",
1e23,
2e6,
0.0,
0.0,
OrbitalElements::from_km_deg(500_000.0, 0.01, 1.0, 0.0, 0.0, 0.0),
)
.with_system(0.30, JUPITER_MASS, M_SUN, AU);
let t = ex.tidal_locking_timescale();
assert!(t > 0.0 && t.is_finite());
}
#[test]
fn co_orbital_horseshoe() {
let co = CoOrbitalMoon::new(
"Janus-like",
"Saturn",
JANUS_MASS,
JANUS_RADIUS,
OrbitalElements::from_km_deg(151_460.0, 0.007, 0.163, 0.0, 0.0, 0.0),
)
.with_co_orbital(0.71, CoOrbitalType::Horseshoe, EPIMETHEUS_MASS, 0.3);
assert_eq!(co.co_type, CoOrbitalType::Horseshoe);
assert!(!co.is_tadpole());
}
#[test]
fn co_orbital_trojan() {
let co = CoOrbitalMoon::new(
"Trojan-like",
"Saturn",
1e16,
5e3,
OrbitalElements::from_km_deg(151_460.0, 0.003, 0.01, 0.0, 0.0, 0.0),
)
.with_co_orbital(0.50, CoOrbitalType::Trojan, 1e16, 0.5);
assert!(co.is_tadpole());
}
#[test]
fn co_orbital_swap_timescale() {
let co = CoOrbitalMoon::new(
"Janus-like",
"Saturn",
JANUS_MASS,
JANUS_RADIUS,
OrbitalElements::from_km_deg(151_460.0, 0.007, 0.163, 0.0, 0.0, 0.0),
)
.with_co_orbital(0.71, CoOrbitalType::Horseshoe, EPIMETHEUS_MASS, 0.3);
let t = co.swap_timescale(SATURN_MASS);
assert!(t > 0.0 && t.is_finite());
}
#[test]
fn co_orbital_trojan_no_swap() {
let co = CoOrbitalMoon::new(
"Trojan-like",
"Saturn",
1e16,
5e3,
OrbitalElements::from_km_deg(151_460.0, 0.003, 0.01, 0.0, 0.0, 0.0),
)
.with_co_orbital(0.50, CoOrbitalType::Trojan, 1e16, 0.5);
let t = co.swap_timescale(SATURN_MASS);
assert!(t.is_infinite());
}
#[test]
fn co_orbital_libration_period() {
let co = CoOrbitalMoon::new(
"Janus-like",
"Saturn",
JANUS_MASS,
JANUS_RADIUS,
OrbitalElements::from_km_deg(151_460.0, 0.007, 0.163, 0.0, 0.0, 0.0),
)
.with_co_orbital(0.71, CoOrbitalType::Horseshoe, EPIMETHEUS_MASS, 0.3);
let p = co.libration_period(SATURN_MASS);
assert!(p > 0.0 && p.is_finite());
}
#[test]
fn co_orbital_mass_ratio() {
let co = CoOrbitalMoon::new(
"Test",
"Saturn",
1e18,
5e4,
OrbitalElements::from_km_deg(151_460.0, 0.007, 0.163, 0.0, 0.0, 0.0),
)
.with_co_orbital(0.50, CoOrbitalType::Horseshoe, 1e18, 0.3);
let ratio = co.mass_ratio();
assert!((ratio - 0.5).abs() < 1e-10);
}