use crate::constants::physical::{C, G};
use std::f64::consts::PI;
pub fn circular_velocity_nfw(r: f64, rho_s: f64, r_s: f64) -> f64 {
let x = r / r_s;
let m_enc = 4.0 * PI * rho_s * r_s.powi(3) * ((1.0 + x).ln() - x / (1.0 + x));
(G * m_enc / r).sqrt()
}
pub fn circular_velocity_disk(r: f64, m_disk: f64, r_d: f64) -> f64 {
let y = r / (2.0 * r_d);
let v_sq = 4.0 * PI * G * m_disk / r_d
* y
* y
* (crate::utils::math::bessel_i0(y) * crate::utils::math::bessel_k0(y)
- crate::utils::math::bessel_i1(y) * crate::utils::math::bessel_k1(y));
v_sq.abs().sqrt()
}
pub fn circular_velocity_bulge(r: f64, m_bulge: f64, a: f64) -> f64 {
(G * m_bulge * r / ((r + a) * (r + a))).sqrt()
}
pub fn circular_velocity_gas(r: f64, m_gas: f64, r_gas: f64) -> f64 {
let y = r / (2.0 * r_gas);
let v_sq = 4.0 * PI * G * m_gas / r_gas
* y
* y
* (crate::utils::math::bessel_i0(y) * crate::utils::math::bessel_k0(y)
- crate::utils::math::bessel_i1(y) * crate::utils::math::bessel_k1(y));
v_sq.abs().sqrt()
}
pub fn total_rotation_curve(
r: f64,
rho_s: f64,
r_s: f64,
m_disk: f64,
r_d: f64,
m_bulge: f64,
a_bulge: f64,
) -> f64 {
let v_dm = circular_velocity_nfw(r, rho_s, r_s);
let v_disk = circular_velocity_disk(r, m_disk, r_d);
let v_bulge = circular_velocity_bulge(r, m_bulge, a_bulge);
(v_dm * v_dm + v_disk * v_disk + v_bulge * v_bulge).sqrt()
}
pub fn flat_rotation_velocity(v_outer: f64) -> f64 {
v_outer
}
pub fn dm_fraction_from_rotation(v_total: f64, v_baryon: f64) -> f64 {
let v_dm_sq = v_total * v_total - v_baryon * v_baryon;
if v_dm_sq > 0.0 {
v_dm_sq / (v_total * v_total)
} else {
0.0
}
}
pub fn mond_interpolation_simple(a: f64, a_0: f64) -> f64 {
let x = a / a_0;
x / (1.0 + x * x).sqrt()
}
pub const MOND_A0: f64 = 1.2e-10;
pub fn radial_acceleration_relation(g_obs: f64, g_bar: f64) -> f64 {
let a0 = MOND_A0;
let predicted = g_bar / (1.0 - (-((g_bar / a0).sqrt())).exp());
let residual = g_obs - predicted;
predicted + residual * 0.0
}
pub fn mond_effective_mass(g_obs: f64, r: f64) -> f64 {
g_obs * r * r / G
}
pub fn maximum_disk_mass(v_max: f64, r_d: f64) -> f64 {
0.85 * v_max * v_max * r_d / G
}
pub fn dm_halo_mass_from_flat_v(v_flat: f64, r_vir: f64) -> f64 {
v_flat * v_flat * r_vir / G
}
pub fn enclosed_mass_from_rotation(v_c: f64, r: f64) -> f64 {
v_c * v_c * r / G
}
pub fn asymptotic_velocity_nfw(rho_s: f64, r_s: f64) -> f64 {
(4.0 * PI * G * rho_s * r_s * r_s).sqrt()
}
pub fn v_max_nfw(rho_s: f64, r_s: f64) -> f64 {
let factor = (2.163_f64).ln() - 2.163 / 3.163;
(4.0 * PI * G * rho_s * r_s * r_s * factor / 2.163).sqrt()
}
pub fn relativistic_rotation_correction(v: f64) -> f64 {
let beta = v / C;
v / (1.0 - beta * beta).sqrt()
}