use metrology::{C, E_CHARGE, EPS_0, EV, G, HBAR, K_B, M_E, MU_0};
use core::f64::consts::PI;
pub const CEILING_BBN_CMB: f64 = 1.1e-6;
pub const CEILING_CMB: f64 = 2.9e-7;
pub const CEILING_FUTURE: f64 = 5.6e-9;
pub fn ceiling_from_delta_neff(delta_neff: f64) -> f64 {
5.6e-6 * delta_neff
}
pub fn gertsenshtein_probability(b: f64, l: f64) -> f64 {
4.0 * PI * G * b * b * l * l / (MU_0 * C.powi(4))
}
pub fn stochastic_photon_rate(eff: f64, area: f64, b: f64, l: f64, hc: f64, df: f64) -> f64 {
eff * area * b * b * l * l * hc * hc * 2.0 * PI * df / (4.0 * MU_0 * C * HBAR)
}
pub fn stochastic_strain_for_rate(rate: f64, eff: f64, area: f64, b: f64, l: f64, df: f64) -> f64 {
(rate / stochastic_photon_rate(eff, area, b, l, 1.0, df)).sqrt()
}
pub fn coherent_photon_rate(eff: f64, area: f64, b: f64, l: f64, f: f64, h0: f64) -> f64 {
eff * area * b * b * l * l * 2.0 * PI * f * h0 * h0 / (8.0 * MU_0 * C * HBAR)
}
pub fn cavity_noise(t: f64, f: f64, eta: f64, q: f64, b: f64, l: f64) -> f64 {
let w = 2.0 * PI * f;
4.0 * K_B * t * MU_0 * C * C / (w.powi(3) * eta * eta * q * b * b * l.powi(5))
}
pub fn superradiance_frequency(mass_ev: f64) -> f64 {
2.0 * mass_ev * EV / (2.0 * PI * HBAR)
}
pub fn plasma_frequency(n_e: f64) -> f64 {
(n_e * E_CHARGE * E_CHARGE / (EPS_0 * M_E)).sqrt() / (2.0 * PI)
}
pub fn critical_density(f: f64) -> f64 {
(2.0 * PI * f).powi(2) * EPS_0 * M_E / (E_CHARGE * E_CHARGE)
}
pub fn plasma_index(n_e: f64, f: f64) -> Option<f64> {
let ratio = plasma_frequency(n_e) / f;
(ratio < 1.0).then(|| (1.0 - ratio * ratio).sqrt())
}
pub fn phase_transition_shape(x: f64) -> f64 {
x.powi(3) * (7.0 / (4.0 + 3.0 * x * x)).powf(3.5)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Status {
PublishedLimit,
Recast,
Contested,
Disputed,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Limit {
pub name: &'static str,
pub band: (f64, f64),
pub value: f64,
pub quantity: &'static str,
pub status: Status,
pub source: &'static str,
}
pub const REGISTRY: [Limit; 7] = [
Limit { name: "QUEST (twin Michelsons, Cardiff)", band: (13e6, 80e6), value: 3e-20, quantity: "√S_h Hz⁻¹ᐟ² near 40 MHz", status: Status::PublishedLimit, source: "https://arxiv.org/abs/2410.09175" },
Limit { name: "Fermilab Holometer", band: (1e6, 13e6), value: 1e-21, quantity: "√S_h Hz⁻¹ᐟ² (better than, 1–13 MHz)", status: Status::PublishedLimit, source: "https://arxiv.org/abs/1611.05560" },
Limit { name: "CAPP-12T axion haloscope", band: (5.310e9, 5.312e9), value: 3.9e-21, quantity: "h₀ (90% CL)", status: Status::Recast, source: "https://arxiv.org/abs/2511.17817" },
Limit { name: "Light shining through a wall (OSQAR, ALPS)", band: (2.7e14, 1.4e15), value: 6e-26, quantity: "h_c", status: Status::Contested, source: "https://arxiv.org/abs/1908.00232" },
Limit { name: "Helioscopes, X-ray (CAST)", band: (5e18, 1.2e19), value: 5e-28, quantity: "h_c", status: Status::Contested, source: "https://arxiv.org/abs/1908.00232" },
Limit { name: "MAGE quartz resonators", band: (4.993e6, 5.505e6), value: 1.35e-20, quantity: "√S_h Hz⁻¹ᐟ² measured at 4.993 MHz (1.10×10⁻²⁰ at 5.505 MHz)", status: Status::PublishedLimit, source: "https://arxiv.org/abs/2307.00715" },
Limit { name: "2021 quartz-resonator rare events", band: (5.5e6, 5.5e6), value: 1e8, quantity: "Ω_GW needed to explain them", status: Status::Disputed, source: "https://arxiv.org/abs/2110.13319" },
];
#[cfg(test)]
mod tests {
use super::*;
use crate::strain::{Convention, hc_from_omega};
#[test]
fn ceiling_in_strain() {
let hc = hc_from_omega(CEILING_BBN_CMB, 1e9, 1.0, Convention::OneSided);
assert!((hc / 1.33e-30 - 1.0).abs() < 0.01, "{hc:e}");
assert!((ceiling_from_delta_neff(0.2) / CEILING_BBN_CMB - 1.0).abs() < 0.02);
}
#[test]
fn photon_conversion_fixtures() {
assert!((gertsenshtein_probability(1.0, 1.0) / 8.263e-38 - 1.0).abs() < 1e-3);
assert!((gertsenshtein_probability(5.3, 106.0) / 2.61e-32 - 1.0).abs() < 0.01);
assert!((stochastic_photon_rate(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) / 3.954e31 - 1.0).abs() < 1e-3);
assert!((stochastic_strain_for_rate(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) / 1.590e-16 - 1.0).abs() < 1e-3);
assert!((coherent_photon_rate(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) / 1.977e31 - 1.0).abs() < 1e-3);
}
#[test]
fn cavity_and_sources() {
let asd = cavity_noise(0.6, 0.8e9, 0.1, 8e4, 7.5, 0.51).sqrt();
assert!((asd / (9.74e-23 * 2f64.sqrt()) - 1.0).abs() < 0.01, "{asd:e}");
assert!((superradiance_frequency(1.0) / 4.836e14 - 1.0).abs() < 1e-3);
assert!((phase_transition_shape(1.0) - 1.0).abs() < 1e-12);
}
#[test]
fn registry_values_are_the_published_ones() {
let value = |name: &str| REGISTRY.iter().find(|l| l.name.starts_with(name)).map(|l| l.value);
assert_eq!(value("QUEST"), Some(3e-20));
assert_eq!(value("Fermilab Holometer"), Some(1e-21)); assert_eq!(value("CAPP-12T"), Some(3.9e-21));
assert_eq!(value("MAGE"), Some(1.35e-20)); assert_eq!(value("Light shining"), Some(6e-26));
assert_eq!(value("Helioscopes"), Some(5e-28));
}
#[test]
fn registry_sits_far_above_the_ceiling() {
for l in REGISTRY.iter().filter(|l| l.quantity.starts_with("√S_h")) {
let f = (l.band.0 * l.band.1).sqrt();
let omega = crate::strain::omega_from_sh(l.value * l.value, f, 1.0);
assert!(omega > 1e10 * CEILING_BBN_CMB, "{}: {omega:e}", l.name);
}
}
#[test]
fn plasma_cutoff() {
assert!((plasma_frequency(1e6) / 8980.0 - 1.0).abs() < 1e-3);
assert!((plasma_frequency(3e4) / 1555.15 - 1.0).abs() < 1e-5);
}
#[test]
fn plasma_refraction() {
let nc = critical_density(10e9);
assert!((nc / 1.240_44e18 - 1.0).abs() < 1e-5);
assert!((plasma_frequency(nc) / 10e9 - 1.0).abs() < 1e-12);
assert!(plasma_index(nc, 10e9).is_none() && plasma_index(2.0 * nc, 10e9).is_none());
for (n_e, n) in [(1e17, 0.9588), (5e17, 0.7726), (1e18, 0.4403)] {
assert!((plasma_index(n_e, 10e9).unwrap() - n).abs() < 1e-4, "{n_e}");
}
}
}