#[derive(Debug, Clone, Copy)]
pub struct StokesParameters {
pub q: f64, pub u: f64, }
impl StokesParameters {
pub fn polarization_fraction(&self, intensity: f64) -> f64 {
((self.q.powi(2) + self.u.powi(2)).sqrt()) / intensity
}
pub fn angle(&self) -> f64 {
0.5 * self.u.atan2(self.q)
}
}
pub fn decompose_eb(
q_map: &[f64],
u_map: &[f64],
_n_side: usize,
) -> (Vec<f64>, Vec<f64>) {
let mut e_map = vec![0.0; q_map.len()];
let mut b_map = vec![0.0; u_map.len()];
for i in 0..q_map.len() {
e_map[i] = q_map[i]; b_map[i] = u_map[i]; }
(e_map, b_map)
}
pub struct PolarizationSpectrum {
pub l_max: usize,
pub c_l_ee: Vec<f64>, pub c_l_bb: Vec<f64>, pub c_l_te: Vec<f64>, }
impl PolarizationSpectrum {
pub fn new(l_max: usize) -> Self {
PolarizationSpectrum {
l_max,
c_l_ee: vec![0.0; l_max + 1],
c_l_bb: vec![0.0; l_max + 1],
c_l_te: vec![0.0; l_max + 1],
}
}
pub fn from_boltzmann(
_universe: &crate::dynamics::Universe,
l_max: usize,
) -> Self {
let mut spectrum = Self::new(l_max);
for l in 2..=l_max {
spectrum.c_l_ee[l] = 5000.0 * (l as f64 / 1000.0).powi(-1);
spectrum.c_l_bb[l] = 0.001 * (l as f64 / 100.0).powi(-2);
spectrum.c_l_te[l] = -50.0 * (l as f64 / 100.0).powi(-1);
}
spectrum
}
pub fn tensor_to_scalar_ratio(&self) -> f64 {
let l_pivot = 80;
if l_pivot < self.c_l_bb.len() {
self.c_l_bb[l_pivot] / 5000.0
} else {
0.0
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stokes_parameters() {
let stokes = StokesParameters { q: 3.0, u: 4.0 };
let frac = stokes.polarization_fraction(10.0);
assert!((frac - 0.5).abs() < 1e-10);
}
#[test]
fn test_polarization_spectrum() {
use crate::dynamics::Universe;
let universe = Universe::benchmark();
let spectrum = PolarizationSpectrum::from_boltzmann(&universe, 100);
assert!(spectrum.c_l_ee[50] > 0.0);
assert!(spectrum.c_l_bb[50] > 0.0);
}
#[test]
fn test_eb_decomposition() {
let q_map = vec![1.0, 2.0, 3.0];
let u_map = vec![4.0, 5.0, 6.0];
let (e_map, b_map) = decompose_eb(&q_map, &u_map, 1);
assert_eq!(e_map.len(), 3);
assert_eq!(b_map.len(), 3);
}
}