use core::f64::consts::PI;
use metrology::{C, E_CHARGE, G, G0, M_E, MU_0};
pub const TAJMAR_REPORTED: f64 = 2.63e-5;
pub const PODKLETNOV_REPORTED: f64 = 2.1e-2;
pub const WEIGHT_BOUNDS: [(&str, f64); 4] = [
("Li et al. 1997, NASA Marshall", 2e-8),
("Tajmar et al. 2006", 5e-6),
("Hathaway et al. 2003", 1e-5),
("Woods et al. 2001", 4e-5),
];
pub fn london_moment(omega: f64) -> f64 {
2.0 * M_E * omega / E_CHARGE
}
pub fn ring_frame_dragging(mass: f64, r_out: f64, r_in: f64) -> f64 {
4.0 * G * mass / (C * C * (r_out + r_in))
}
pub fn cooper_pair_density(london_depth: f64) -> f64 {
M_E * M_E / (MU_0 * E_CHARGE * E_CHARGE * london_depth * london_depth)
}
pub fn gravitational_london_depth(rho_star: f64) -> f64 {
C / (4.0 * PI * G * rho_star).sqrt()
}
pub fn shadow_fraction(radius: f64, height: f64) -> f64 {
1.0 - (radius / height).atan().cos().powi(3)
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Swing {
pub rise: f64,
pub energy: f64,
pub speed: f64,
pub acceleration: f64,
}
pub fn pendulum_impulse(length: f64, deflection: f64, mass: f64, pulse: f64) -> Swing {
let rise = length - (length * length - deflection * deflection).sqrt();
let speed = (2.0 * G0 * rise).sqrt();
Swing { rise, energy: mass * G0 * rise, speed, acceleration: speed / pulse }
}
pub fn marx_bank(capacitance: f64, stages: f64, voltage: f64) -> (f64, f64) {
(stages * 0.5 * capacitance * voltage * voltage, capacitance * voltage)
}
#[cfg(test)]
mod tests {
use super::*;
fn close(a: f64, b: f64, rel: f64) -> bool {
(a / b - 1.0).abs() < rel
}
#[test]
fn tajmar_against_general_relativity() {
let gr = ring_frame_dragging(0.349, 0.075, 0.069);
assert!(close(gr, 7.20e-27, 2e-3));
assert!(close(TAJMAR_REPORTED / gr, 3.65e21, 5e-3));
assert!(close(cooper_pair_density(39e-9) / 8570.0, 1.974e-6, 2e-3));
assert!(close(2.0 * cooper_pair_density(39e-9) / 8570.0, 3.947e-6, 2e-3));
assert!(close(gravitational_london_depth(cooper_pair_density(39e-9)), 7.96e13, 5e-3));
assert!(close(london_moment(650.0), 7.39e-9, 2e-3));
}
#[test]
fn podkletnov_against_replications_and_geometry() {
let strictest = WEIGHT_BOUNDS.iter().map(|b| b.1).fold(f64::INFINITY, f64::min);
assert!(close(PODKLETNOV_REPORTED / strictest, 1.05e6, 1e-9));
assert!(close(shadow_fraction(0.1375, 3.0), 3.14e-3, 2e-3));
assert!((shadow_fraction(0.1375, 1e-9) - 1.0).abs() < 1e-12);
}
#[test]
fn impulse_generator_tables_reproduce() {
let s = pendulum_impulse(0.8, 0.142, 0.0185, 1e-4);
assert!(close(s.rise, 12.70e-3, 1e-3));
assert!(close(s.energy, 2.305e-3, 1e-3));
assert!(close(s.speed, 0.499, 1e-3));
assert!(close(s.acceleration, 4.99e3, 1e-3)); assert!(close(0.0185 * s.speed * C / s.energy, 1.2e9, 0.01));
let (energy, charge) = marx_bank(25e-9, 20.0, 1e5);
assert!(close(energy, 2500.0, 1e-12) && close(0.1 / charge, 40.0, 1e-12));
}
}