use crate::constants::physical::{C, G, HBAR};
use std::f64::consts::PI;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct FuzzyDarkMatter {
pub mass_ev: f64,
}
impl FuzzyDarkMatter {
pub fn mass_kg(&self) -> f64 {
self.mass_ev * 1.782_661_92e-36
}
pub fn m22(&self) -> f64 {
self.mass_ev / 1e-22
}
pub fn compton_wavelength_m(&self) -> f64 {
HBAR / (self.mass_kg() * C)
}
pub fn de_broglie_wavelength_kpc(&self, v_km_s: f64) -> f64 {
let v = v_km_s * 1e3;
HBAR / (self.mass_kg() * v) / 3.0857e19
}
pub fn jeans_length_kpc(&self, rho_kg_m3: f64) -> f64 {
let m = self.mass_kg();
let lambda_j = (PI * HBAR * HBAR / (m * m * G * rho_kg_m3)).powf(0.25);
lambda_j / 3.0857e19
}
pub fn jeans_mass_solar(&self, rho_kg_m3: f64) -> f64 {
let l_j = self.jeans_length_kpc(rho_kg_m3) * 3.0857e19;
4.0 / 3.0 * PI * rho_kg_m3 * (l_j / 2.0).powi(3) / 1.989e30
}
pub fn half_mode_mass_solar(&self) -> f64 {
let m22 = self.m22();
4.4e7 * m22.powf(-4.0 / 3.0)
}
pub fn soliton_core_radius_kpc(&self, m_halo_solar: f64) -> f64 {
let m22 = self.m22();
1.6 * m22.powf(-1.0) * (m_halo_solar / 1e9).powf(-1.0 / 3.0)
}
}
pub fn soliton_density_profile(r_kpc: f64, rho_c: f64, r_c_kpc: f64) -> f64 {
let x = r_kpc / r_c_kpc;
rho_c / (1.0 + 0.091 * x * x).powf(8.0)
}
pub fn soliton_central_density(mass_ev: f64, r_c_kpc: f64) -> f64 {
let m22 = mass_ev / 1e-22;
let r_c_pc = r_c_kpc * 1e3;
1.9e7 * m22.powf(-2.0) * (r_c_pc / 100.0).powf(-4.0) * 1.989e30 / 3.0857e19_f64.powi(3)
}
pub fn soliton_mass_solar(rho_c: f64, r_c_kpc: f64) -> f64 {
let r_c = r_c_kpc * 3.0857e19;
let volume_factor = 4.0 * PI * r_c.powi(3) * 2.42;
rho_c * volume_factor / 1.989e30
}
pub fn core_halo_mass_relation_solar(mass_ev: f64, m_halo_solar: f64) -> f64 {
let m22 = mass_ev / 1e-22;
1.4e9 * m22.powf(-1.0) * (m_halo_solar / 1e12).powf(1.0 / 3.0)
}
pub fn quantum_pressure(mass_ev: f64, rho_kg_m3: f64, r_m: f64) -> f64 {
let m = mass_ev * 1.782_661_92e-36;
HBAR * HBAR / (2.0 * m * m) * rho_kg_m3 / (r_m * r_m)
}
pub fn gravitational_pressure(rho_kg_m3: f64, r_m: f64) -> f64 {
G * rho_kg_m3 * rho_kg_m3 * r_m * r_m
}
pub fn quantum_jeans_wavenumber(mass_ev: f64, rho_kg_m3: f64) -> f64 {
let m = mass_ev * 1.782_661_92e-36;
(16.0 * PI * G * rho_kg_m3 * m * m / (HBAR * HBAR)).powf(0.25)
}
pub fn suppression_transfer_function(k_mpc: f64, mass_ev: f64) -> f64 {
let m22 = mass_ev / 1e-22;
let k_j = 9.0 * m22.powf(0.5);
let x = k_mpc / k_j;
(1.0 + x.powi(2)).powf(-4.0).cos().powi(2) + (-(x / 3.0).powi(2)).exp() * 0.5
}
pub fn interference_fringe_scale_kpc(mass_ev: f64, v_km_s: f64) -> f64 {
let m = mass_ev * 1.782_661_92e-36;
let v = v_km_s * 1e3;
let lambda_db = HBAR / (m * v);
lambda_db / 3.0857e19
}
pub fn granule_mass_solar(mass_ev: f64, rho_kg_m3: f64, v_km_s: f64) -> f64 {
let l = interference_fringe_scale_kpc(mass_ev, v_km_s) * 3.0857e19;
4.0 / 3.0 * PI * rho_kg_m3 * (l / 2.0).powi(3) / 1.989e30
}
pub fn dynamical_heating_rate(mass_ev: f64, rho_dm_kg_m3: f64, v_km_s: f64) -> f64 {
let m = mass_ev * 1.782_661_92e-36;
let v = v_km_s * 1e3;
let t_relax = m * v * v / (G * G * rho_dm_kg_m3 * rho_dm_kg_m3) * v / HBAR;
if t_relax < 1e-50 {
return f64::INFINITY;
}
v * v / t_relax
}
pub fn superradiance_rate(mass_ev: f64, m_bh_solar: f64, spin_bh: f64) -> f64 {
let m = mass_ev * 1.782_661_92e-36;
let m_bh = m_bh_solar * 1.989e30;
let r_g = G * m_bh / (C * C);
let alpha = G * m_bh * m / (HBAR * C);
if alpha > 0.5 {
return 0.0;
}
let omega_h = spin_bh * C / (2.0 * r_g * (1.0 + (1.0 - spin_bh * spin_bh).sqrt()));
let omega_r = alpha * alpha * m * C * C / (2.0 * HBAR);
if omega_r >= omega_h {
return 0.0;
}
alpha.powf(7.0) * (omega_h - omega_r)
}
pub fn occupation_number(rho_kg_m3: f64, mass_ev: f64, v_km_s: f64) -> f64 {
let m = mass_ev * 1.782_661_92e-36;
let v = v_km_s * 1e3;
let n_density = rho_kg_m3 / m;
let p = m * v;
let phase_vol = (2.0 * PI * HBAR).powi(3);
n_density * phase_vol / (4.0 * PI * p * p * p / 3.0)
}
pub fn condensation_fraction(t_k: f64, t_c_k: f64) -> f64 {
if t_k >= t_c_k {
return 0.0;
}
1.0 - (t_k / t_c_k).powf(1.5)
}