pub const ALPHA_OMEGA_CRITICAL: f64 = 2.0;
pub const LAB_THRESHOLDS: [(&str, f64, &str); 7] = [
("Ponomarenko flow", 17.7, "Rm, theory"),
("Riga, optimised profile (convective)", 14.3, "Rm, theory"),
("Riga, optimised profile (absolute)", 17.6, "Rm, theory"),
("Karlsruhe (predicted)", 8.12, "α-number C, mean-field theory; measured 8.4–9.3"),
("VKS2 (measured)", 31.0, "Rm, lower edge of 31–35; predicted 48–133"),
("Roberts flow", 3.49, "Rm, k_z-optimised"),
("Small-scale dynamo at Pm = 1", 35.0, "Rm, simulations"),
];
pub fn dynamo_number(alpha: f64, shear: f64, eta: f64, k: f64) -> f64 {
alpha * shear / (eta * eta * k.powi(3))
}
pub fn alpha_omega_growth(alpha: f64, shear: f64, eta: f64, k: f64) -> (f64, f64) {
let (a, b) = (alpha * alpha * k * k, -alpha * shear * k);
let modulus = a.hypot(b);
let (re, im) = (((modulus + a) / 2.0).sqrt(), ((modulus - a) / 2.0).sqrt().copysign(b));
(re - eta * k * k, im.abs())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn onset_at_dynamo_number_two() {
let shear = (2.0f64 / 1e-4).sqrt();
let alpha = 1e-4 * shear;
assert!((dynamo_number(alpha, shear, 1.0, 1.0) - 2.0).abs() < 1e-12);
let (growth, frequency) = alpha_omega_growth(alpha, shear, 1.0, 1.0);
assert!(growth.abs() < 2e-4 && (frequency - 1.0).abs() < 2e-4, "{growth} {frequency}");
assert!(alpha_omega_growth(0.5 * alpha, shear, 1.0, 1.0).0 < 0.0 && alpha_omega_growth(2.0 * alpha, shear, 1.0, 1.0).0 > 0.0);
assert!((alpha_omega_growth(2.0, 0.0, 1.0, 1.0).0 - 1.0).abs() < 1e-12);
}
}