use core::f64::consts::PI;
use metrology::MU_0;
pub const FKR_COEFFICIENT: f64 = 0.547_436_725;
pub fn sausage_stable(dlnp_dlnr: f64, beta: f64, gamma: f64) -> bool {
-dlnp_dlnr <= 4.0 * gamma / (2.0 + gamma * beta)
}
pub fn kink_stable(dlnp_dlnr: f64, beta: f64, m: f64) -> bool {
-dlnp_dlnr <= m * m / beta
}
pub fn rt_cutoff(b: f64, theta: f64, rho_h: f64, rho_l: f64, g: f64) -> f64 {
4.0 * PI * b * b * theta.cos().powi(2) / (MU_0 * g * (rho_h - rho_l))
}
pub fn fkr_growth(delta_prime_a: f64, s: f64) -> Option<f64> {
(delta_prime_a < s.cbrt() / 10.0).then(|| FKR_COEFFICIENT * delta_prime_a.powf(0.8) * s.powf(-0.6))
}
#[cfg(test)]
mod tests {
use super::*;
fn bennett(x: f64) -> (f64, f64) {
(-4.0 * x * x / (1.0 + x * x), 1.0 / (x * x))
}
#[test]
fn bennett_pinch() {
let (g, b) = bennett(3f64.sqrt());
assert!((-g - 1.0 / b).abs() < 1e-12 && (b - 1.0 / 3.0).abs() < 1e-12);
assert!(!kink_stable(bennett(1.5).0, bennett(1.5).1, 1.0) && kink_stable(bennett(2.0).0, bennett(2.0).1, 1.0));
for x in [0.5, 1.0, 3f64.sqrt(), 3.0] {
let (g, b) = bennett(x);
assert!(!sausage_stable(g, b, 5.0 / 3.0), "{x}");
assert!((-g - 8.0 / (2.0 + 2.0 * b)).abs() < 1e-12);
}
}
#[test]
fn prominence_rayleigh_taylor() {
let cut = |deg: f64| rt_cutoff(1e-3, deg.to_radians(), 2.9e-10, 3.7e-12, 274.0);
assert!((cut(89.0) / 38.827e3 - 1.0).abs() < 1e-4 && (cut(88.0) / 155.262e3 - 1.0).abs() < 1e-4);
}
#[test]
fn tearing() {
assert!((FKR_COEFFICIENT - (3.625_609_908_2 / (2.0 * PI * 1.225_416_702_5)).powf(0.8)).abs() < 1e-9);
assert!((fkr_growth(1.0, 1e6).unwrap() / 1.375_099e-4 - 1.0).abs() < 1e-6);
assert!((fkr_growth(1.0, 1e8).unwrap() / 8.676e-6 - 1.0).abs() < 1e-3);
assert!(fkr_growth(100.0, 1e6).is_none());
}
}