use std::f64::consts::PI;
pub fn freeze_out_temperature(m_dm_gev: f64, sigma_v: f64) -> f64 {
let xf = freeze_out_xf(m_dm_gev, sigma_v);
m_dm_gev / xf
}
pub fn freeze_out_xf(m_dm_gev: f64, sigma_v: f64) -> f64 {
let mpl_gev = 1.22e19;
let g_star = effective_dof(m_dm_gev);
let c0 = 0.038 * mpl_gev * m_dm_gev * sigma_v / g_star.sqrt();
let log_c0 = c0.ln();
let mut xf = log_c0;
for _ in 0..20 {
let new_xf = log_c0 - 0.5 * xf.ln();
if (new_xf - xf).abs() < 0.001 {
break;
}
xf = new_xf;
}
xf.max(1.0)
}
pub fn relic_density_omega_h2(m_dm_gev: f64, sigma_v: f64) -> f64 {
let xf = freeze_out_xf(m_dm_gev, sigma_v);
let mpl = 1.22e19;
let g_star_s = effective_dof(m_dm_gev / xf);
let numerator = 1.07e9 * xf;
let denominator = mpl * g_star_s.sqrt() * sigma_v * 1e36;
numerator / denominator
}
pub fn thermal_cross_section_for_omega(omega_h2: f64) -> f64 {
3e-26 * 0.12 / omega_h2
}
pub fn effective_dof(t_gev: f64) -> f64 {
if t_gev > 300.0 {
106.75
} else if t_gev > 100.0 {
96.25
} else if t_gev > 10.0 {
86.25
} else if t_gev > 1.0 {
75.75
} else if t_gev > 0.2 {
61.75
} else if t_gev > 0.1 {
17.25
} else if t_gev > 1e-3 {
10.75
} else if t_gev > 1e-4 {
3.91
} else {
3.36
}
}
pub fn entropy_dof(t_gev: f64) -> f64 {
effective_dof(t_gev)
}
pub fn number_density_equilibrium(m_gev: f64, t_gev: f64, g_internal: f64) -> f64 {
let x = m_gev / t_gev;
if x > 30.0 {
return 0.0;
}
if x < 0.1 {
return g_internal * 1.2 * t_gev * t_gev * t_gev / (PI * PI) * 1e27;
}
g_internal * (m_gev * t_gev / (2.0 * PI)).powf(1.5) * (-x).exp() * 1e27
}
pub fn entropy_density(t_gev: f64) -> f64 {
let gs = entropy_dof(t_gev);
2.0 * PI * PI / 45.0 * gs * t_gev * t_gev * t_gev
}
pub fn yield_equilibrium(m_gev: f64, t_gev: f64, g_internal: f64) -> f64 {
let n = number_density_equilibrium(m_gev, t_gev, g_internal);
let s = entropy_density(t_gev);
if s > 0.0 { n / s } else { 0.0 }
}
pub fn boltzmann_suppression(m_gev: f64, t_gev: f64) -> f64 {
(-m_gev / t_gev).exp()
}
pub fn yield_today_from_freeze_out(m_gev: f64, sigma_v: f64) -> f64 {
let xf = freeze_out_xf(m_gev, sigma_v);
let s0 = entropy_density(1e-13);
let mpl = 1.22e19;
let gs = entropy_dof(m_gev / xf);
xf / (0.264 * mpl * gs.sqrt() * sigma_v * s0)
}
pub fn coannihilation_effective_sigma_v(
sigmas: &[(f64, f64, f64)],
m_lightest: f64,
t_gev: f64,
) -> f64 {
let mut numerator = 0.0;
let mut denominator = 0.0;
for &(gi, mi, sigma_vi) in sigmas {
let weight = gi * (-(mi - m_lightest) / t_gev).exp();
numerator += weight * sigma_vi;
denominator += weight;
}
if denominator > 0.0 {
numerator / denominator
} else {
0.0
}
}