use core::f64::consts::{PI, SQRT_2};
use metrology::{C, G};
pub const PLANCK_LUMINOSITY: f64 = C * C * C * C * C / G;
pub fn strain_from_luminosity(fraction: f64, f: f64, r: f64) -> f64 {
2.0 * SQRT_2 * fraction.sqrt() * C / (2.0 * PI * f * r)
}
pub fn circular_flux(eta: f64, x: f64) -> f64 {
32.0 / 5.0 * eta * eta * x.powi(5)
}
pub fn energy_flux_coefficients(l: u32) -> (f64, f64) {
let factorial = |n: u32| (1..=n).map(f64::from).product::<f64>();
let double_factorial = |n: u32| (1..=n).rev().step_by(2).map(f64::from).product::<f64>();
let l_f = f64::from(l);
let a = (l_f + 1.0) * (l_f + 2.0) / ((l_f - 1.0) * l_f * factorial(l) * double_factorial(2 * l + 1));
let b = 4.0 * l_f * (l_f + 2.0) / ((l_f - 1.0) * factorial(l + 1) * double_factorial(2 * l + 1));
(a, b)
}
pub fn peters_enhancement(e: f64) -> f64 {
let e2 = e * e;
(1.0 + 73.0 / 24.0 * e2 + 37.0 / 96.0 * e2 * e2) / (1.0 - e2).powf(3.5)
}
pub fn peters_pbdot(mp: f64, mc: f64, pb: f64, e: f64) -> f64 {
-192.0 * PI / 5.0 * (G / C.powi(3)).powf(5.0 / 3.0) * (pb / (2.0 * PI)).powf(-5.0 / 3.0) * peters_enhancement(e) * mp * mc
/ (mp + mc).cbrt()
}
#[cfg(test)]
mod tests {
use super::*;
use metrology::{MPC, SOLAR_MASS};
fn close(a: f64, b: f64, rel: f64) -> bool {
(a / b - 1.0).abs() < rel
}
#[test]
fn luminosity_and_strain() {
assert!(close(PLANCK_LUMINOSITY, 3.62825e52, 1e-5) && close(PLANCK_LUMINOSITY / 4.0, 9.07064e51, 1e-5));
assert!(close(3.7e49 / PLANCK_LUMINOSITY, 1.01977e-3, 1e-5)); assert!(close(strain_from_luminosity(1e-3, 250.0, 410.0 * MPC), 1.34931e-21, 1e-5));
assert!(close(strain_from_luminosity(1.0, 1.0, C), 0.450158, 1e-5));
assert!(close(circular_flux(0.25, 1.0 / 6.0), 5.14403e-5, 1e-5));
}
#[test]
fn multipole_coefficients() {
for (l, a, b) in [(2, 1.0 / 5.0, 16.0 / 45.0), (3, 1.0 / 189.0, 1.0 / 84.0), (4, 1.0 / 9072.0, 4.0 / 14175.0)] {
let (al, bl) = energy_flux_coefficients(l);
assert!(close(al, a, 1e-12) && close(bl, b, 1e-12), "{l}: {al} {bl}");
}
}
#[test]
fn binary_pulsars() {
assert!(close(peters_enhancement(0.6171340), 11.8568, 1e-5));
let day = 86_400.0;
let b1913 = peters_pbdot(1.438 * SOLAR_MASS, 1.390 * SOLAR_MASS, 0.322997448918 * day, 0.6171340);
assert!(close(b1913, -2.40210e-12, 1e-5) && close(b1913, -2.40263e-12, 1e-3));
let j0737 = peters_pbdot(1.338185 * SOLAR_MASS, 1.248868 * SOLAR_MASS, 0.1022515592973 * day, 0.087777023);
assert!(close(j0737, -1.24781e-12, 1e-5));
}
}