use crate::constants::T_CMB;
use std::f64::consts::PI;
pub fn primordial_power_spectrum(
k: f64,
amplitude: f64,
spectral_index: f64,
k_pivot: f64,
) -> f64 {
amplitude * (k / k_pivot).powf(spectral_index - 1.0)
}
pub fn transfer_function_eh(k: f64, omega_m: f64, omega_b: f64, h: f64) -> f64 {
let omega_m_h2 = omega_m * h * h;
let omega_b_h2 = omega_b * h * h;
let theta_cmb = T_CMB / 2.7;
let _s = 44.5 * (omega_m_h2 / theta_cmb.powi(4)).ln()
/ (1.0 + 10.0 * omega_b_h2.powf(0.75)).sqrt();
let _k_silk = 1.6 * omega_b_h2.powf(0.52) * omega_m_h2.powf(0.73)
* (1.0 + (10.4 * omega_m_h2).powf(-0.95));
let q = k / (13.41 * omega_m_h2.powf(0.5));
let l = (2.0 * 2.718 + 1.8 * q).ln();
let c = 14.2 + 731.0 / (1.0 + 62.5 * q);
let t = l / (l + c * q * q);
t
}
pub fn matter_power_spectrum(
k: f64,
z: f64,
omega_m: f64,
omega_b: f64,
h: f64,
amplitude: f64,
spectral_index: f64,
) -> f64 {
let p_prim = primordial_power_spectrum(k, amplitude, spectral_index, 0.05);
let t = transfer_function_eh(k, omega_m, omega_b, h);
let d = 1.0 / (1.0 + z);
let factor = 2.0 * PI * PI / (k * k * k);
p_prim * t * t * d * d * factor
}
pub fn dimensionless_power(
k: f64,
z: f64,
omega_m: f64,
omega_b: f64,
h: f64,
amplitude: f64,
spectral_index: f64,
) -> f64 {
let p_k = matter_power_spectrum(k, z, omega_m, omega_b, h, amplitude, spectral_index);
k * k * k * p_k / (2.0 * PI * PI)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_primordial_power_at_pivot() {
let p = primordial_power_spectrum(0.05, 2.1e-9, 0.96, 0.05);
assert!((p - 2.1e-9).abs() < 1e-15);
}
#[test]
fn test_transfer_function_limiting_cases() {
let t_large = transfer_function_eh(1e-4, 0.3, 0.05, 0.7);
assert!(t_large > 0.9 && t_large <= 1.0);
let t_small = transfer_function_eh(10.0, 0.3, 0.05, 0.7);
assert!(t_small < 0.5);
}
}