use std::f64::consts::{FRAC_PI_2, PI};
use std::process;
use sagittariusas::config::parameters::{
C, SGR_A_DISTANCE, SGR_A_MASS, SGR_A_SPIN, SIGMA_SB, SOLAR_MASS, isco_radius,
};
use sagittariusas::engine::accretion_disk::AccretionDisk;
use sagittariusas::engine::jet_dynamics::RelativisticJet;
use sagittariusas::engine::spacetime::{KerrSpacetime, SpacetimePoint};
use sagittariusas::observables::lensing::GravitationalLens;
use sagittariusas::observables::radiation::AccretionRadiation;
use sagittariusas::observables::shadows::{BlackHoleShadow, eht_expected_diameter_uas};
use sagittariusas::physics::relativity::{SchwarzschildMetric, gravitational_wave_power};
use sagittariusas::physics::singularity::Singularity;
use sagittariusas::utils::math::log_range;
struct Validation {
shadow_deviation: f64,
model_deviation: f64,
precession_deviation: f64,
sub_eddington: bool,
photon_captured: bool,
jet_efficiency: f64,
disk_luminosity: f64,
gw_power: f64,
einstein_radius: f64,
}
impl Validation {
fn passed(&self) -> bool {
self.shadow_deviation < 0.2
&& self.model_deviation < 0.3
&& self.precession_deviation < 0.2
&& self.sub_eddington
&& self.photon_captured
&& self.jet_efficiency > 0.0
&& self.jet_efficiency < 1.0
&& self.disk_luminosity > 0.0
&& self.gw_power > 0.0
&& self.einstein_radius > 0.0
}
}
fn main() {
let bh = Singularity::kerr(SGR_A_MASS, SGR_A_SPIN);
if bh.is_naked() {
process::exit(1);
}
let r_isco = isco_radius(SGR_A_MASS, SGR_A_SPIN);
let shadow = BlackHoleShadow::new(SGR_A_MASS, SGR_A_SPIN, 0.785);
let predicted_uas = shadow.shadow_diameter_uas(SGR_A_DISTANCE);
let model_uas = eht_expected_diameter_uas();
let shadow_deviation = (predicted_uas - 51.8).abs() / 51.8;
let model_deviation = (predicted_uas - model_uas).abs() / model_uas;
let schw = SchwarzschildMetric::new(SGR_A_MASS);
let s2_a = 970.0 * 1.496e11;
let s2_e = 0.8843;
let s2_peri = s2_a * (1.0 - s2_e);
let precession_arcmin = schw.perihelion_precession(s2_a, s2_e).to_degrees() * 60.0;
let precession_deviation = (precession_arcmin - 12.1).abs() / 12.1;
let mdot = 1e-9 * SOLAR_MASS / (365.25 * 86400.0);
let disk = AccretionDisk::new(SGR_A_MASS, mdot);
let accr = AccretionRadiation::new(SGR_A_MASS, mdot);
let radii = log_range(r_isco, 500.0 * bh.gravitational_radius(), 200);
let disk_lum: f64 = radii
.windows(2)
.map(|w| {
let r = 0.5 * (w[0] + w[1]);
let dr = w[1] - w[0];
SIGMA_SB * disk.temperature_profile(r).powi(4) * 4.0 * PI * r * dr
})
.sum();
let jet = RelativisticJet::new(SGR_A_MASS, SGR_A_SPIN);
let bz = jet.blandford_znajek_power();
let kin = jet.kinetic_luminosity();
let gw = gravitational_wave_power(SGR_A_MASS, 14.0 * SOLAR_MASS, s2_peri);
let ks = KerrSpacetime::new(SGR_A_MASS, SGR_A_SPIN);
let rh = ks.event_horizon();
let traj = ks.trace_photon(
SpacetimePoint::new(0.0, 10.0 * rh, FRAC_PI_2, 0.0),
[-C, 0.0, 0.0],
10000,
0.01,
);
let lens = GravitationalLens::new(SGR_A_MASS, SGR_A_DISTANCE, 2.0 * SGR_A_DISTANCE);
let v = Validation {
shadow_deviation,
model_deviation,
precession_deviation,
sub_eddington: accr.eddington_ratio() < 1.0,
photon_captured: traj.last().is_none_or(|p| p.r < rh * 1.1),
jet_efficiency: kin / bz,
disk_luminosity: disk_lum,
gw_power: gw,
einstein_radius: lens.einstein_radius(),
};
process::exit(if v.passed() { 0 } else { 1 });
}