use blackholesfactory::config::parameters::*;
use blackholesfactory::engine::accretion_disk::{AccretionDisk, DiskModel};
use blackholesfactory::engine::evaporation::HawkingEvaporation;
use blackholesfactory::engine::jet_dynamics::RelativisticJet;
use blackholesfactory::engine::spacetime::{KerrSpacetime, SpacetimePoint};
use std::f64::consts::FRAC_PI_2;
#[test]
fn accretion_disk_inner_at_isco() {
let mass = 10.0 * SOLAR_MASS;
let mdot = 1e15;
let d = AccretionDisk::new(mass, mdot);
let r_isco = isco_radius(mass, 0.0);
let diff = (d.inner_radius - r_isco).abs() / r_isco;
assert!(diff < 0.01);
}
#[test]
fn temperature_positive_outside_isco() {
let d = AccretionDisk::new(10.0 * SOLAR_MASS, 1e15);
let t = d.temperature_profile(d.inner_radius * 2.0);
assert!(t > 0.0);
}
#[test]
fn temperature_zero_inside_isco() {
let d = AccretionDisk::new(10.0 * SOLAR_MASS, 1e15);
let t = d.temperature_profile(d.inner_radius * 0.5);
assert!(t == 0.0);
}
#[test]
fn adaf_cooler_than_ss() {
let mass = 10.0 * SOLAR_MASS;
let mdot = 1e15;
let ss = AccretionDisk::new(mass, mdot);
let adaf = AccretionDisk::new(mass, mdot).with_model(DiskModel::Adaf);
let r = ss.inner_radius * 3.0;
assert!(adaf.temperature_profile(r) < ss.temperature_profile(r));
}
#[test]
fn luminosity_positive() {
let d = AccretionDisk::new(10.0 * SOLAR_MASS, 1e15);
assert!(d.luminosity() > 0.0);
}
#[test]
fn radiative_efficiency_bounded() {
let d = AccretionDisk::new(10.0 * SOLAR_MASS, 1e15);
let eff = d.radiative_efficiency();
assert!(eff > 0.0 && eff < 1.0);
}
#[test]
fn radial_profile_correct_length() {
let d = AccretionDisk::new(10.0 * SOLAR_MASS, 1e15);
let profile = d.radial_profile(50);
assert_eq!(profile.len(), 50);
}
#[test]
fn total_mass_positive() {
let d = AccretionDisk::new(10.0 * SOLAR_MASS, 1e15);
assert!(d.total_mass() > 0.0);
}
#[test]
fn bz_power_positive() {
let j = RelativisticJet::new(10.0 * SOLAR_MASS, 0.9);
assert!(j.blandford_znajek_power() > 0.0);
}
#[test]
fn kinetic_luminosity_less_than_bz() {
let j = RelativisticJet::new(10.0 * SOLAR_MASS, 0.9);
assert!(j.kinetic_luminosity() < j.blandford_znajek_power());
}
#[test]
fn apparent_superluminal_velocity() {
let j = RelativisticJet::new(10.0 * SOLAR_MASS, 0.9).with_lorentz_factor(10.0);
assert!(j.max_apparent_velocity() > C);
}
#[test]
fn doppler_boosting_at_optimal_angle() {
let j = RelativisticJet::new(10.0 * SOLAR_MASS, 0.9).with_lorentz_factor(5.0);
let optimal = (1.0 / j.bulk_lorentz_factor).asin();
let d = j.doppler_factor(optimal);
assert!(d > 1.0);
}
#[test]
fn synchrotron_cooling_time_positive() {
let j = RelativisticJet::new(10.0 * SOLAR_MASS, 0.9).with_magnetic_field(1.0);
let t = j.synchrotron_cooling_time(1e4);
assert!(t > 0.0);
}
#[test]
fn kerr_event_horizon_positive() {
let ks = KerrSpacetime::new(10.0 * SOLAR_MASS, 0.9);
assert!(ks.event_horizon() > 0.0);
}
#[test]
fn kerr_cauchy_less_than_event_horizon() {
let ks = KerrSpacetime::new(10.0 * SOLAR_MASS, 0.9);
assert!(ks.cauchy_horizon() < ks.event_horizon());
}
#[test]
fn kerr_ergosphere_ge_horizon_at_equator() {
let ks = KerrSpacetime::new(10.0 * SOLAR_MASS, 0.9);
assert!(ks.ergosphere(FRAC_PI_2) >= ks.event_horizon());
}
#[test]
fn photon_trace_terminates() {
let ks = KerrSpacetime::new(10.0 * SOLAR_MASS, 0.9);
let rh = ks.event_horizon();
let traj = ks.trace_photon(
SpacetimePoint::new(0.0, 50.0 * rh, FRAC_PI_2, 0.0),
[C, 0.0, C / (50.0 * rh)],
500,
0.01,
);
assert!(traj.len() > 1 && traj.len() <= 501);
}
#[test]
fn orbital_frequency_decreases_with_radius() {
let ks = KerrSpacetime::new(10.0 * SOLAR_MASS, 0.9);
let rh = ks.event_horizon();
let f1 = ks.orbital_frequency(10.0 * rh);
let f2 = ks.orbital_frequency(100.0 * rh);
assert!(f1 > f2);
}
#[test]
fn hawking_temperature_positive() {
let h = HawkingEvaporation::new(1e12);
assert!(h.temperature() > 0.0);
}
#[test]
fn evaporation_time_finite() {
let h = HawkingEvaporation::new(1e12);
let t = h.evaporation_time();
assert!(t > 0.0 && t < f64::INFINITY);
}
#[test]
fn page_time_less_than_evaporation() {
let h = HawkingEvaporation::new(1e12);
assert!(h.page_time() < h.evaporation_time());
}
#[test]
fn evolve_decreases_mass() {
let mut h = HawkingEvaporation::new(1e12);
h.evolve(1e10);
assert!(h.mass_fraction_remaining() < 1.0);
}
#[test]
fn entropy_decreases_after_evaporation() {
let h0 = HawkingEvaporation::new(1e12);
let s0 = h0.entropy();
let mut h1 = HawkingEvaporation::new(1e12);
h1.evolve(1e10);
assert!(h1.entropy() < s0);
}
#[test]
fn stellar_bh_evaporates_slower_than_micro() {
let micro = HawkingEvaporation::new(1e12);
let stellar = HawkingEvaporation::new(10.0 * SOLAR_MASS);
assert!(stellar.evaporation_time() > micro.evaporation_time());
}