europas 0.0.3

Europa celestial simulation crate for the MilkyWay SolarSystem workspace
Documentation
// ── ExosphereEndpoint ──

#[test]
fn europa_exosphere_species_count() {
    let exo = europas::rendering::ice_shell::ExosphereEndpoint::europa();
    assert!(exo.species.len() >= 6);
}

#[test]
fn europa_o2_dominant() {
    let exo = europas::rendering::ice_shell::ExosphereEndpoint::europa();
    let o2 = exo.species.iter().find(|s| s.symbol == "O2").unwrap();
    assert!(o2.column_density_m2 > 1e18);
}

#[test]
fn europa_density_decreases() {
    let exo = europas::rendering::ice_shell::ExosphereEndpoint::europa();
    assert!(exo.density_at_altitude("O2", 100_000.0) < exo.density_at_altitude("O2", 0.0));
}

#[test]
fn europa_total_column_density() {
    let exo = europas::rendering::ice_shell::ExosphereEndpoint::europa();
    assert!(exo.total_column_density() > 1e18);
}

#[test]
fn europa_molar_masses_positive() {
    let exo = europas::rendering::ice_shell::ExosphereEndpoint::europa();
    for sp in &exo.species {
        assert!(
            sp.molar_mass_kg_mol > 0.0,
            "{} has zero molar mass",
            sp.name
        );
    }
}

// ── IceShellEndpoint ──

#[test]
fn europa_ice_shell_thickness() {
    let ice = europas::rendering::ice_shell::IceShellEndpoint::europa_default();
    assert!((ice.shell_thickness_m - 20_000.0).abs() < 1.0);
}

#[test]
fn europa_thermal_gradient_positive() {
    let ice = europas::rendering::ice_shell::IceShellEndpoint::europa_default();
    assert!(ice.thermal_gradient_k_per_m() > 0.0);
}

#[test]
fn europa_temperature_at_depth() {
    let ice = europas::rendering::ice_shell::IceShellEndpoint::europa_default();
    let t_surface = ice.temperature_at_depth(0.0);
    let t_deep = ice.temperature_at_depth(20_000.0);
    assert!(t_deep > t_surface);
    assert!((t_deep - 273.0).abs() < 1.0);
}

#[test]
fn europa_ice_conductivity() {
    let ice = europas::rendering::ice_shell::IceShellEndpoint::europa_default();
    assert!(ice.ice_conductivity_w_m_k() > 5.0);
}

#[test]
fn europa_surface_heat_flux() {
    let ice = europas::rendering::ice_shell::IceShellEndpoint::europa_default();
    assert!(ice.surface_heat_flux_w_m2() > 0.0);
}

// ── ShaderEndpoint ──

#[test]
fn europa_terrain_shader() {
    let s = europas::rendering::shaders::ShaderEndpoint::terrain();
    assert!(s.uniforms.len() >= 5);
    assert_eq!(s.name, "europa_terrain_pbr");
}

#[test]
fn europa_ice_surface_shader() {
    let s = europas::rendering::shaders::ShaderEndpoint::ice_surface();
    assert!(s.uniforms.len() >= 4);
    assert_eq!(s.name, "europa_ice_subsurface");
}

#[test]
fn europa_eclipse_shader() {
    let s = europas::rendering::shaders::ShaderEndpoint::eclipse();
    assert!(s.uniforms.len() >= 3);
}

// ── DustScattering (kept) ──

#[test]
fn ice_sputter_opacity() {
    let d = europas::rendering::dust::SputterSpriteRenderer::ice_sputter();
    assert!(d.opacity_at_height(0.0) > 0.0);
}

// ── PbrMaterial (kept) ──

#[test]
fn pristine_ice_material() {
    let m = europas::rendering::materials::PbrMaterial::pristine_ice();
    assert!(m.albedo[0] > 0.5);
}

#[test]
fn chaos_terrain_material() {
    let m = europas::rendering::materials::PbrMaterial::chaos_terrain();
    assert!(m.roughness > 0.5);
}

#[test]
fn lineae_crack_material() {
    let m = europas::rendering::materials::PbrMaterial::lineae_crack();
    assert!(m.roughness > 0.8);
}