pub const K_EFF_RB87: f64 = 4.0 * core::f64::consts::PI / 780.241e-9;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct AtomInterferometer {
pub t: f64,
pub contrast: f64,
pub atoms: f64,
pub cycle: f64,
}
impl AtomInterferometer {
pub fn phase(&self, a: f64) -> f64 {
2.0 * K_EFF_RB87 * a * self.t * self.t
}
pub fn phase_noise(&self) -> f64 {
1.0 / (self.contrast * self.atoms.sqrt())
}
pub fn acceleration_noise(&self) -> f64 {
self.phase_noise() / (2.0 * K_EFF_RB87 * self.t * self.t)
}
pub fn acceleration_asd(&self) -> f64 {
self.acceleration_noise() * self.cycle.sqrt()
}
pub fn gradient_noise(&self, baseline: f64) -> f64 {
std::f64::consts::SQRT_2 * self.phase_noise() / (2.0 * K_EFF_RB87 * baseline * self.t * self.t)
}
pub fn gradient_asd(&self, baseline: f64) -> f64 {
self.gradient_noise(baseline) * self.cycle.sqrt()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn close(a: f64, b: f64, rel: f64) -> bool {
(a - b).abs() <= rel * b.abs()
}
#[test]
fn published_instruments() {
let carioqa = AtomInterferometer { t: 1.0, contrast: 0.8, atoms: 1e5, cycle: 3.5 };
assert!(close(carioqa.phase_noise(), 3.95e-3, 0.01));
assert!(close(carioqa.acceleration_asd(), 2.3e-10, 0.01));
assert!(close(AtomInterferometer { atoms: 1e6, ..carioqa }.acceleration_asd(), 7.3e-11, 0.01));
let grice = AtomInterferometer { t: 0.5, contrast: 0.43, atoms: 5e5, cycle: 2.0 };
assert!(close(grice.acceleration_asd(), 5.8e-10, 0.01));
let tri = AtomInterferometer { t: 5.0, contrast: 1.0, atoms: 1e6, cycle: 1.0 };
assert!(close(tri.gradient_noise(0.5), 3.5e-12, 0.01));
assert!(close(tri.phase(2.7e-6 * 0.5), 1087.0, 0.001));
}
}