sciforge-lib 0.0.4

Scientific computing library — mathematics, physics, chemistry, biology, astronomy, geology, meteorology.
Documentation
use crate::constants::{C, G, K_B, MU_0, SIGMA_SB};

pub fn schwarzschild_radius(mass: f64) -> f64 {
    2.0 * G * mass / (C * C)
}

pub fn kerr_event_horizon(mass: f64, spin_parameter: f64) -> f64 {
    let rg = G * mass / (C * C);
    rg + (rg * rg - spin_parameter * spin_parameter).sqrt()
}

pub fn kerr_ergosphere(mass: f64, spin_parameter: f64, theta: f64) -> f64 {
    let rg = G * mass / (C * C);
    rg + (rg * rg - spin_parameter * spin_parameter * theta.cos().powi(2)).sqrt()
}

pub fn isco_radius(mass: f64, spin_parameter: f64) -> f64 {
    let rg = G * mass / (C * C);
    let a_star = spin_parameter / rg;
    if a_star.abs() < 1e-10 {
        return 6.0 * rg;
    }
    let z1 = 1.0
        + (1.0 - a_star * a_star).powf(1.0 / 3.0)
            * ((1.0 + a_star).powf(1.0 / 3.0) + (1.0 - a_star).powf(1.0 / 3.0));
    let z2 = (3.0 * a_star * a_star + z1 * z1).sqrt();
    let sign = if a_star >= 0.0 { 1.0 } else { -1.0 };
    rg * (3.0 + z2 - sign * ((3.0 - z1) * (3.0 + z1 + 2.0 * z2)).sqrt())
}

pub fn accretion_disk_temperature(mass: f64, accretion_rate: f64, r: f64, r_inner: f64) -> f64 {
    if r <= r_inner {
        return 0.0;
    }
    let correction = 1.0 - (r_inner / r).sqrt();
    let factor =
        3.0 * G * mass * accretion_rate / (8.0 * std::f64::consts::PI * SIGMA_SB * r.powi(3));
    (factor * correction).powf(0.25)
}

pub fn accretion_disk_luminosity(mass: f64, accretion_rate: f64, r_inner: f64) -> f64 {
    G * mass * accretion_rate / (2.0 * r_inner)
}

pub fn radiative_efficiency(r_isco: f64, mass: f64) -> f64 {
    let rg = G * mass / (C * C);
    1.0 - (1.0 - 2.0 * rg / (3.0 * r_isco)).sqrt()
}

pub fn eddington_accretion_rate(mass: f64) -> f64 {
    let l_edd = 4.0 * std::f64::consts::PI * G * mass * C / 0.2;
    l_edd / (0.1 * C * C)
}

pub fn disk_surface_density(accretion_rate: f64, viscosity: f64, r: f64, r_inner: f64) -> f64 {
    let correction = 1.0 - (r_inner / r).sqrt();
    accretion_rate * correction / (3.0 * std::f64::consts::PI * viscosity)
}

pub fn alpha_viscosity(alpha: f64, sound_speed: f64, scale_height: f64) -> f64 {
    alpha * sound_speed * scale_height
}

pub fn disk_scale_height(sound_speed: f64, orbital_frequency: f64) -> f64 {
    sound_speed / orbital_frequency
}

pub fn orbital_frequency_kerr(mass: f64, r: f64, spin_parameter: f64) -> f64 {
    let rg = G * mass / (C * C);
    let r_32 = r.powf(1.5);
    C * (rg).sqrt() / (r_32 + spin_parameter * (rg).sqrt())
}

pub fn gravitational_redshift(mass: f64, r: f64) -> f64 {
    let rs = schwarzschild_radius(mass);
    if r <= rs {
        return f64::INFINITY;
    }
    1.0 / (1.0 - rs / r).sqrt() - 1.0
}

pub fn doppler_beaming_factor(velocity_los: f64, bulk_lorentz: f64) -> f64 {
    let beta = velocity_los / C;
    1.0 / (bulk_lorentz * (1.0 - beta))
}

pub fn apparent_superluminal_velocity(beta: f64, viewing_angle: f64) -> f64 {
    beta * viewing_angle.sin() / (1.0 - beta * viewing_angle.cos())
}

pub fn blandford_znajek_power(
    magnetic_field: f64,
    event_horizon_radius: f64,
    spin_parameter: f64,
    mass: f64,
) -> f64 {
    let rg = G * mass / (C * C);
    let a_star = spin_parameter / rg;
    let omega_h = a_star * C / (4.0 * event_horizon_radius);
    let phi = magnetic_field.powi(2) * event_horizon_radius.powi(2);
    phi * (omega_h * event_horizon_radius / C).powi(2) / (6.0 * MU_0)
}

pub fn jet_lorentz_factor_from_ratio(jet_power: f64, mass_loading_rate: f64) -> f64 {
    jet_power / (mass_loading_rate * C * C)
}

pub fn synchrotron_cooling_time(electron_gamma: f64, magnetic_field: f64) -> f64 {
    let mu_0 = MU_0;
    let sigma_t = 6.652_458_7e-29;
    let m_e = 9.109_383_7e-31;
    let u_b = magnetic_field.powi(2) / (2.0 * mu_0);
    6.0 * std::f64::consts::PI * m_e * C / (sigma_t * u_b * electron_gamma)
}

pub fn photon_ring_radius(mass: f64) -> f64 {
    3.0 * G * mass / (C * C)
}

pub fn shadow_angular_radius(mass: f64, distance: f64) -> f64 {
    let r_ph = photon_ring_radius(mass);
    let critical_impact = r_ph * 3.0_f64.sqrt();
    critical_impact / distance
}

pub fn advection_dominated_temperature(proton_mass: f64, r: f64, mass: f64) -> f64 {
    let rg = G * mass / (C * C);
    proton_mass * C * C * rg / (3.0 * K_B * r)
}

pub fn comptonization_parameter(electron_temperature: f64, optical_depth: f64) -> f64 {
    let m_e_c2 = 9.109_383_7e-31 * C * C;
    4.0 * K_B * electron_temperature / m_e_c2 * (optical_depth + optical_depth.powi(2))
}

pub fn bondi_accretion_rate(mass: f64, ambient_density: f64, sound_speed: f64) -> f64 {
    4.0 * std::f64::consts::PI * G.powi(2) * mass.powi(2) * ambient_density / sound_speed.powi(3)
}

pub fn tidal_disruption_radius(bh_mass: f64, star_mass: f64, star_radius: f64) -> f64 {
    star_radius * (bh_mass / star_mass).powf(1.0 / 3.0)
}