use std::f64::consts::PI;
pub fn dn_dgamma_bb(e_gamma_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_gamma_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 {
return 0.0;
}
let a = 0.73;
let b = 7.64;
let c = 0.26;
let n0 = 0.42;
n0 * x.powf(-1.5) * (-b * x).exp() * (1.0 + a * x.ln()).powi(2)
/ (m_dm_gev * (1.0 + c * (-x.ln()).powi(2)))
}
pub fn dn_dgamma_tautau(e_gamma_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_gamma_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 {
return 0.0;
}
let n0 = 0.27;
let a = 2.2;
let b = 6.8;
n0 * x.powf(-1.3) * (-b * x.powf(0.7)).exp() * (1.0 + a * x) / m_dm_gev
}
pub fn dn_dgamma_ww(e_gamma_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_gamma_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 || m_dm_gev < 80.4 {
return 0.0;
}
let n0 = 0.50;
let b = 7.2;
n0 * x.powf(-1.5) * (-b * x).exp() / m_dm_gev
}
pub fn dn_dgamma_mumu(e_gamma_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_gamma_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 {
return 0.0;
}
let alpha = 1.0 / 137.0;
2.0 * alpha / (3.0 * PI * m_dm_gev) * ((1.0 - x) / x) * (1.0 + (1.0 - x).powi(2)) / (2.0 * x)
}
pub fn positron_spectrum_bb(e_positron_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_positron_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 {
return 0.0;
}
let n0 = 0.60;
let alpha_e = 1.8;
let beta_e = 5.5;
n0 * x.powf(-alpha_e) * (-beta_e * x).exp() / m_dm_gev
}
pub fn positron_spectrum_tautau(e_positron_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_positron_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 {
return 0.0;
}
let n0 = 0.33;
let a = 1.5;
let b = 4.6;
n0 * x.powf(-a) * (-b * x.powf(0.8)).exp() / m_dm_gev
}
pub fn antiproton_spectrum_bb(e_pbar_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_pbar_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 || m_dm_gev < 10.0 {
return 0.0;
}
let n0 = 0.17;
let a = 1.2;
let b = 9.0;
n0 * x.powf(-a) * (-b * x).exp() * (1.0 - x).powi(3) / m_dm_gev
}
pub fn antiproton_spectrum_ww(e_pbar_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_pbar_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 || m_dm_gev < 80.4 {
return 0.0;
}
let n0 = 0.20;
let a = 1.3;
let b = 8.5;
n0 * x.powf(-a) * (-b * x).exp() * (1.0 - x).powi(2) / m_dm_gev
}
pub fn neutrino_spectrum_bb(e_nu_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_nu_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 {
return 0.0;
}
let n0 = 0.55;
let a = 1.6;
let b = 6.0;
n0 * x.powf(-a) * (-b * x).exp() / m_dm_gev
}
pub fn neutrino_spectrum_tautau(e_nu_gev: f64, m_dm_gev: f64) -> f64 {
let x = e_nu_gev / m_dm_gev;
if x <= 0.0 || x >= 1.0 {
return 0.0;
}
0.18 * (1.0 - x).powi(2) * x.powf(-0.8) / m_dm_gev
}
pub fn total_photon_yield_bb(m_dm_gev: f64, n_steps: usize) -> f64 {
let e_min = 1e-3_f64;
let e_max = m_dm_gev * 0.999;
let d_log_e = (e_max / e_min).ln() / n_steps as f64;
let mut yield_total = 0.0;
for i in 0..n_steps {
let log_e = e_min.ln() + (i as f64 + 0.5) * d_log_e;
let e = log_e.exp();
let dn = dn_dgamma_bb(e, m_dm_gev);
yield_total += dn * e * d_log_e;
}
yield_total
}
pub fn total_photon_yield_tautau(m_dm_gev: f64, n_steps: usize) -> f64 {
let e_min = 1e-3_f64;
let e_max = m_dm_gev * 0.999;
let d_log_e = (e_max / e_min).ln() / n_steps as f64;
let mut yield_total = 0.0;
for i in 0..n_steps {
let log_e = e_min.ln() + (i as f64 + 0.5) * d_log_e;
let e = log_e.exp();
let dn = dn_dgamma_tautau(e, m_dm_gev);
yield_total += dn * e * d_log_e;
}
yield_total
}
pub fn differential_flux_gamma(
dn_de: f64,
sigma_v_cm3_s: f64,
j_factor_gev2_cm5: f64,
m_dm_gev: f64,
) -> f64 {
sigma_v_cm3_s * j_factor_gev2_cm5 * dn_de / (8.0 * PI * m_dm_gev * m_dm_gev)
}
pub fn differential_flux_decay(
dn_de: f64,
decay_rate_s: f64,
d_factor_gev_cm2: f64,
m_dm_gev: f64,
) -> f64 {
decay_rate_s * d_factor_gev_cm2 * dn_de / (4.0 * PI * m_dm_gev)
}
pub fn integrated_flux_above_threshold(
m_dm_gev: f64,
sigma_v_cm3_s: f64,
j_factor_gev2_cm5: f64,
e_threshold_gev: f64,
channel: &str,
n_steps: usize,
) -> f64 {
let e_max = m_dm_gev * 0.999;
if e_threshold_gev >= e_max {
return 0.0;
}
let d_log_e = (e_max / e_threshold_gev).ln() / n_steps as f64;
let mut flux = 0.0;
for i in 0..n_steps {
let log_e = e_threshold_gev.ln() + (i as f64 + 0.5) * d_log_e;
let e = log_e.exp();
let dn = match channel {
"bb" => dn_dgamma_bb(e, m_dm_gev),
"tautau" => dn_dgamma_tautau(e, m_dm_gev),
"ww" => dn_dgamma_ww(e, m_dm_gev),
"mumu" => dn_dgamma_mumu(e, m_dm_gev),
_ => 0.0,
};
flux +=
differential_flux_gamma(dn, sigma_v_cm3_s, j_factor_gev2_cm5, m_dm_gev) * e * d_log_e;
}
flux
}
pub fn branching_ratio_weighted_spectrum(
e_gamma_gev: f64,
m_dm_gev: f64,
br_bb: f64,
br_tautau: f64,
br_ww: f64,
) -> f64 {
br_bb * dn_dgamma_bb(e_gamma_gev, m_dm_gev)
+ br_tautau * dn_dgamma_tautau(e_gamma_gev, m_dm_gev)
+ br_ww * dn_dgamma_ww(e_gamma_gev, m_dm_gev)
}