use crate::config::parameters::{C, G, SOLAR_MASS};
use std::f64::consts::PI;
#[derive(Clone, Copy)]
pub enum JetLaunchMechanism {
BlandfordZnajek,
BlandfordPayne,
}
pub struct RelativisticJet {
pub mass: f64,
pub spin: f64,
pub magnetic_field: f64,
pub bulk_lorentz_factor: f64,
pub opening_angle: f64,
pub mechanism: JetLaunchMechanism,
}
impl RelativisticJet {
pub fn new(mass: f64, spin: f64) -> Self {
Self {
mass,
spin: spin.clamp(-1.0, 1.0),
magnetic_field: 100.0,
bulk_lorentz_factor: 5.0,
opening_angle: 0.1,
mechanism: JetLaunchMechanism::BlandfordZnajek,
}
}
pub fn with_magnetic_field(mut self, b: f64) -> Self {
self.magnetic_field = b.max(1e-10);
self
}
pub fn with_lorentz_factor(mut self, gamma: f64) -> Self {
self.bulk_lorentz_factor = gamma.max(1.0);
self
}
pub fn with_opening_angle(mut self, angle: f64) -> Self {
self.opening_angle = angle.clamp(0.001, PI / 4.0);
self
}
pub fn with_mechanism(mut self, mech: JetLaunchMechanism) -> Self {
self.mechanism = mech;
self
}
pub fn blandford_znajek_power(&self) -> f64 {
let rg = G * self.mass / (C * C);
let rh = rg + (rg * rg - (self.spin * rg).powi(2)).max(0.0).sqrt();
let omega_h = self.spin * C / (2.0 * rh);
let b2 = self.magnetic_field * self.magnetic_field;
let area = 4.0 * PI * rh * rh;
b2 * area * rh * rh * omega_h * omega_h / (6.0 * C)
}
pub fn kinetic_luminosity(&self) -> f64 {
let bz = self.blandford_znajek_power();
let eta = 1.0 - 1.0 / self.bulk_lorentz_factor;
bz * eta
}
pub fn doppler_factor(&self, viewing_angle: f64) -> f64 {
let beta = (1.0 - 1.0 / (self.bulk_lorentz_factor * self.bulk_lorentz_factor))
.max(0.0)
.sqrt();
1.0 / (self.bulk_lorentz_factor * (1.0 - beta * viewing_angle.cos()))
}
pub fn apparent_velocity(&self, viewing_angle: f64) -> f64 {
let beta = (1.0 - 1.0 / (self.bulk_lorentz_factor * self.bulk_lorentz_factor))
.max(0.0)
.sqrt();
beta * C * viewing_angle.sin() / (1.0 - beta * viewing_angle.cos())
}
pub fn max_apparent_velocity(&self) -> f64 {
let beta = (1.0 - 1.0 / (self.bulk_lorentz_factor * self.bulk_lorentz_factor))
.max(0.0)
.sqrt();
let gamma = self.bulk_lorentz_factor;
beta * gamma * C
}
pub fn synchrotron_cooling_time(&self, electron_gamma: f64) -> f64 {
let sigma_t = 6.652e-29;
let me = 9.109e-31;
let u_b = self.magnetic_field * self.magnetic_field / (2.0 * 4.0 * PI * 1e-7);
6.0 * PI * me * C / (sigma_t * electron_gamma * u_b)
}
pub fn magnetic_field_at(&self, distance: f64) -> f64 {
let r0 = G * self.mass / (C * C);
self.magnetic_field * (r0 / distance).max(0.0)
}
pub fn beam_radius_at(&self, distance: f64) -> f64 {
distance * self.opening_angle.tan()
}
pub fn mass_solar(&self) -> f64 {
self.mass / SOLAR_MASS
}
}