use crate::config::parameters::{G, SIGMA_SB};
use std::f64::consts::PI;
#[derive(Debug, Clone, Copy)]
pub enum DiskModel {
ShakuraSunyaev,
Adaf,
Slim,
}
#[derive(Debug, Clone)]
pub struct AccretionDisk {
pub black_hole_mass: f64,
pub accretion_rate: f64,
pub alpha_viscosity: f64,
pub inner_radius: f64,
pub outer_radius: f64,
pub model: DiskModel,
}
impl AccretionDisk {
pub fn new(bh_mass: f64, accretion_rate: f64) -> Self {
let rs = sciforge::hub::prelude::astronomy::stellar::schwarzschild_radius(bh_mass);
Self {
black_hole_mass: bh_mass,
accretion_rate,
alpha_viscosity: 0.1,
inner_radius: 3.0 * rs,
outer_radius: 1000.0 * rs,
model: DiskModel::ShakuraSunyaev,
}
}
pub fn with_alpha(mut self, alpha: f64) -> Self {
self.alpha_viscosity = alpha.clamp(0.001, 1.0);
self
}
pub fn with_model(mut self, model: DiskModel) -> Self {
self.model = model;
self
}
pub fn with_outer_radius(mut self, r: f64) -> Self {
self.outer_radius = r;
self
}
pub fn temperature_profile(&self, r: f64) -> f64 {
if r < self.inner_radius {
return 0.0;
}
let factor = 3.0 * G * self.black_hole_mass * self.accretion_rate
/ (8.0 * PI * SIGMA_SB * r.powi(3));
let correction = 1.0 - (self.inner_radius / r).sqrt();
let f_rad = match self.model {
DiskModel::ShakuraSunyaev => 1.0,
DiskModel::Adaf => self.alpha_viscosity * 0.1,
DiskModel::Slim => 0.5,
};
(f_rad * factor * correction).powf(0.25)
}
pub fn surface_density(&self, r: f64) -> f64 {
if r < self.inner_radius {
return 0.0;
}
let correction = 1.0 - (self.inner_radius / r).sqrt();
self.accretion_rate * correction / (3.0 * PI * self.viscosity_at(r))
}
pub fn viscosity_at(&self, r: f64) -> f64 {
let cs = self.sound_speed(r);
let h = self.scale_height(r);
self.alpha_viscosity * cs * h
}
pub fn sound_speed(&self, r: f64) -> f64 {
let t = self.temperature_profile(r);
let mu = 0.6;
let m_p = 1.672_621e-27;
(sciforge::hub::prelude::constants::K_B * t / (mu * m_p)).sqrt()
}
pub fn scale_height(&self, r: f64) -> f64 {
let cs = self.sound_speed(r);
let omega = self.orbital_frequency(r);
if omega < 1e-30 {
return 0.0;
}
cs / omega
}
pub fn orbital_frequency(&self, r: f64) -> f64 {
(G * self.black_hole_mass / (r * r * r)).sqrt()
}
pub fn luminosity(&self) -> f64 {
G * self.black_hole_mass * self.accretion_rate / (2.0 * self.inner_radius)
}
pub fn radiative_efficiency(&self) -> f64 {
let rs =
sciforge::hub::prelude::astronomy::stellar::schwarzschild_radius(self.black_hole_mass);
rs / (4.0 * self.inner_radius)
}
pub fn radial_profile(&self, n_points: usize) -> Vec<(f64, f64)> {
let log_rin = self.inner_radius.ln();
let log_rout = self.outer_radius.ln();
let dlog = (log_rout - log_rin) / n_points as f64;
(0..n_points)
.map(|i| {
let r = (log_rin + (i as f64 + 0.5) * dlog).exp();
(r, self.temperature_profile(r))
})
.collect()
}
pub fn total_mass(&self) -> f64 {
let n = 500;
let dr = (self.outer_radius - self.inner_radius) / n as f64;
(0..n)
.map(|i| {
let r = self.inner_radius + (i as f64 + 0.5) * dr;
2.0 * PI * r * self.surface_density(r) * dr
})
.sum()
}
}