use satellitesfactory::config::parameters::*;
use satellitesfactory::physics::gravitation::*;
use satellitesfactory::physics::interiors::*;
use satellitesfactory::physics::tidal_dynamics::*;
#[test]
fn satellite_gravity_surface_acceleration() {
let g = SatelliteGravity::new(MOON_MASS, MOON_RADIUS);
let acc = g.surface_acceleration();
assert!(acc > 1.6 && acc < 1.7);
}
#[test]
fn satellite_gravity_escape_velocity() {
let g = SatelliteGravity::new(MOON_MASS, MOON_RADIUS);
let v = g.escape_velocity();
assert!(v > 2300.0 && v < 2400.0);
}
#[test]
fn satellite_gravity_orbital_velocity() {
let g = SatelliteGravity::new(EARTH_MASS, EARTH_RADIUS);
let v = g.orbital_velocity(384_400.0e3);
assert!(v > 1000.0 && v < 1100.0);
}
#[test]
fn satellite_gravity_orbital_period() {
let g = SatelliteGravity::new(EARTH_MASS, EARTH_RADIUS);
let p_days = g.orbital_period(384_400.0e3) / 86400.0;
assert!((p_days - 27.3).abs() < 0.5);
}
#[test]
fn satellite_gravity_synchronous_orbit() {
let g = SatelliteGravity::new(EARTH_MASS, EARTH_RADIUS);
let r = g.synchronous_orbit_radius(86400.0);
assert!(r > 4.0e7 && r < 4.5e7);
}
#[test]
fn satellite_gravity_sphere_of_influence() {
let g = SatelliteGravity::new(MOON_MASS, MOON_RADIUS);
let soi = g.sphere_of_influence(EARTH_MASS, 384_400.0e3);
assert!(soi > 5.0e7 && soi < 7.0e7);
}
#[test]
fn two_body_force_earth_moon() {
let f = two_body_force(EARTH_MASS, MOON_MASS, 384_400.0e3);
assert!(f > 1.9e20 && f < 2.1e20);
}
#[test]
fn hill_sphere_moon() {
let h = hill_sphere(384_400.0e3, MOON_MASS, EARTH_MASS);
assert!(h > 5.0e7 && h < 7.0e7);
}
#[test]
fn roche_limit_fluid() {
let rl = satellitesfactory::physics::gravitation::roche_limit(SATURN_RADIUS, 687.0, 917.0);
assert!(rl > SATURN_RADIUS);
assert!(rl < 3.0 * SATURN_RADIUS);
}
#[test]
fn roche_limit_rigid_less_than_fluid() {
let r_fluid = satellitesfactory::physics::gravitation::roche_limit(SATURN_RADIUS, 687.0, 917.0);
let r_rigid = roche_limit_rigid(SATURN_RADIUS, 687.0, 917.0);
assert!(r_rigid < r_fluid);
}
#[test]
fn gravitational_binding_energy_positive() {
let e = gravitational_binding_energy(MOON_MASS, MOON_RADIUS);
assert!(e > 0.0);
}
#[test]
fn mutual_hill_positive() {
let mh = mutual_hill_radius(421_700.0e3, IO_MASS, 671_100.0e3, EUROPA_MASS, JUPITER_MASS);
assert!(mh > 0.0);
}
#[test]
fn tisserand_parameter_value() {
let tp = tisserand_parameter(1.0e9, 5.2 * AU, 0.05, 0.1);
assert!(tp > 0.0 && tp.is_finite());
}
#[test]
fn io_tidal_heating_rate() {
let tidal = TidalSystem::new(IO_MASS, IO_RADIUS, JUPITER_MASS, 421_700.0e3, 0.004_1)
.with_tidal(JUPITER_RADIUS, 100.0, 0.015);
let power = tidal.tidal_heating_rate();
assert!(power > 1e10);
}
#[test]
fn io_tidal_heating_flux_positive() {
let tidal = TidalSystem::new(IO_MASS, IO_RADIUS, JUPITER_MASS, 421_700.0e3, 0.004_1)
.with_tidal(JUPITER_RADIUS, 100.0, 0.015);
let flux = tidal.tidal_heating_flux();
assert!(flux > 0.0);
}
#[test]
fn io_equilibrium_temperature_positive() {
let tidal = TidalSystem::new(IO_MASS, IO_RADIUS, JUPITER_MASS, 421_700.0e3, 0.004_1)
.with_tidal(JUPITER_RADIUS, 100.0, 0.015);
let t = tidal.equilibrium_temperature_from_tidal();
assert!(t > 0.0);
}
#[test]
fn europa_less_heating_than_io() {
let io = TidalSystem::new(IO_MASS, IO_RADIUS, JUPITER_MASS, 421_700.0e3, 0.004_1).with_tidal(
JUPITER_RADIUS,
100.0,
0.015,
);
let europa = TidalSystem::new(
EUROPA_MASS,
EUROPA_RADIUS,
JUPITER_MASS,
671_100.0e3,
0.009_0,
)
.with_tidal(JUPITER_RADIUS, 100.0, 0.025);
assert!(europa.tidal_heating_rate() < io.tidal_heating_rate());
}
#[test]
fn enceladus_tidal_heating() {
let enc = TidalSystem::new(
ENCELADUS_MASS,
ENCELADUS_RADIUS,
SATURN_MASS,
238_042.0e3,
0.004_7,
)
.with_tidal(SATURN_RADIUS, 20.0, 0.01);
assert!(enc.tidal_heating_rate() > 0.0);
assert!(enc.tidal_heating_flux() > 0.0);
}
#[test]
fn moon_earth_less_than_io() {
let me = TidalSystem::new(MOON_MASS, MOON_RADIUS, EARTH_MASS, 384_400.0e3, 0.054_9).with_tidal(
EARTH_RADIUS,
27.0,
0.025,
);
let io = TidalSystem::new(IO_MASS, IO_RADIUS, JUPITER_MASS, 421_700.0e3, 0.004_1).with_tidal(
JUPITER_RADIUS,
100.0,
0.015,
);
assert!(me.tidal_heating_rate() < io.tidal_heating_rate());
}
#[test]
fn tidal_locking_timescale_positive() {
let tidal = TidalSystem::new(IO_MASS, IO_RADIUS, JUPITER_MASS, 421_700.0e3, 0.004_1)
.with_tidal(JUPITER_RADIUS, 100.0, 0.015);
let t = tidal.tidal_locking_timescale();
assert!(t > 0.0 && t.is_finite());
}
#[test]
fn orbital_decay_rate_negative() {
let tidal = TidalSystem::new(IO_MASS, IO_RADIUS, JUPITER_MASS, 421_700.0e3, 0.004_1)
.with_tidal(JUPITER_RADIUS, 100.0, 0.015);
let rate = tidal.orbital_decay_rate();
assert!(rate < 0.0);
}
#[test]
fn circularization_timescale_positive() {
let tidal = TidalSystem::new(IO_MASS, IO_RADIUS, JUPITER_MASS, 421_700.0e3, 0.004_1)
.with_tidal(JUPITER_RADIUS, 100.0, 0.015);
let t = tidal.circularization_timescale();
assert!(t > 0.0 && t.is_finite());
}
#[test]
fn tidal_bulge_height_positive() {
let h = tidal_bulge_height(JUPITER_MASS, IO_RADIUS, 421_700.0e3);
assert!(h > 0.0);
}
#[test]
fn dissipation_function_inverse_q() {
let d = dissipation_function(100.0);
assert!((d - 0.01).abs() < 1e-10);
}
#[test]
fn love_number_homogeneous_range() {
let k2 = love_number_homogeneous(4e9, 1.315, EUROPA_RADIUS, 3013.0);
assert!(k2 > 0.0 && k2 < 1.5);
}
#[test]
fn resonance_width_positive() {
let rw = resonance_width(IO_MASS, EUROPA_MASS, JUPITER_MASS, 550_000.0e3);
assert!(rw > 0.0);
}
#[test]
fn moon_interior_no_ocean() {
let mi = SatelliteInterior::new(MOON_MASS, MOON_RADIUS, 0.0, 0.83);
assert!(mi.ocean_depth_estimate() == 0.0);
}
#[test]
fn europa_interior_has_ocean() {
let ei = SatelliteInterior::new(EUROPA_MASS, EUROPA_RADIUS, 0.08, 0.86);
assert!(ei.ocean_depth_estimate() > 0.0);
}
#[test]
fn ganymede_interior_has_ocean() {
let gi = SatelliteInterior::new(GANYMEDE_MASS, GANYMEDE_RADIUS, 0.40, 0.55);
assert!(gi.ocean_depth_estimate() > 0.0);
}
#[test]
fn titan_interior_has_ocean() {
let ti = SatelliteInterior::new(TITAN_MASS, TITAN_RADIUS, 0.45, 0.50);
assert!(ti.ocean_depth_estimate() > 0.0);
}
#[test]
fn io_interior_no_ocean() {
let ii = SatelliteInterior::new(IO_MASS, IO_RADIUS, 0.0, 0.94);
assert!(ii.ocean_depth_estimate() == 0.0);
}
#[test]
fn enceladus_interior_has_ocean() {
let ei = SatelliteInterior::new(ENCELADUS_MASS, ENCELADUS_RADIUS, 0.57, 0.40);
assert!(ei.ocean_depth_estimate() > 0.0);
}
#[test]
fn interior_mean_density_consistent() {
let ei = SatelliteInterior::new(EUROPA_MASS, EUROPA_RADIUS, 0.08, 0.86);
let rho = ei.mean_density();
assert!(rho > 2500.0 && rho < 3500.0);
}
#[test]
fn interior_core_radius_less_than_total() {
let ei = SatelliteInterior::new(EUROPA_MASS, EUROPA_RADIUS, 0.08, 0.86);
assert!(ei.core_radius() < ei.radius);
}
#[test]
fn interior_mantle_plus_core_equals_radius() {
let ei = SatelliteInterior::new(EUROPA_MASS, EUROPA_RADIUS, 0.08, 0.86);
let sum = ei.core_radius() + ei.mantle_thickness();
assert!((sum - ei.radius).abs() / ei.radius < 1e-12);
}
#[test]
fn interior_central_pressure_positive() {
let gi = SatelliteInterior::new(GANYMEDE_MASS, GANYMEDE_RADIUS, 0.40, 0.55);
assert!(gi.central_pressure() > 0.0);
}
#[test]
fn interior_moment_of_inertia() {
let gi = SatelliteInterior::new(GANYMEDE_MASS, GANYMEDE_RADIUS, 0.40, 0.55);
let moi = gi.moment_of_inertia_factor();
assert!(moi > 0.2 && moi < 0.4);
}
#[test]
fn interior_binding_energy_positive() {
let ti = SatelliteInterior::new(TITAN_MASS, TITAN_RADIUS, 0.45, 0.50);
assert!(ti.gravitational_binding_energy() > 0.0);
}
#[test]
fn io_densest_then_europa_then_ganymede() {
let io = SatelliteInterior::new(IO_MASS, IO_RADIUS, 0.0, 0.94);
let eu = SatelliteInterior::new(EUROPA_MASS, EUROPA_RADIUS, 0.08, 0.86);
let ga = SatelliteInterior::new(GANYMEDE_MASS, GANYMEDE_RADIUS, 0.40, 0.55);
assert!(io.mean_density() > eu.mean_density());
assert!(eu.mean_density() > ga.mean_density());
}
#[test]
fn differentiation_energy_positive() {
let e = differentiation_energy(GANYMEDE_MASS, GANYMEDE_RADIUS, 0.3);
assert!(e > 0.0);
}
#[test]
fn ice_melting_depth_finite() {
let d = ice_melting_depth(100.0, 0.05);
assert!(d > 0.0 && d.is_finite());
}
#[test]
fn ice_melting_depth_zero_when_warm() {
let d = ice_melting_depth(300.0, 0.05);
assert!(d == 0.0);
}
#[test]
fn ice_melting_depth_infinite_no_flux() {
let d = ice_melting_depth(100.0, 0.0);
assert!(d.is_infinite());
}
#[test]
fn convective_vigor_positive() {
let ra = convective_vigor(0.05, 1e14, 1.6e-4, 100_000.0);
assert!(ra > 0.0);
}