use std::f64::consts::PI;
const HBAR: f64 = 1.054571817e-34;
const EPS0: f64 = 8.854187817e-12;
const C_LIGHT: f64 = 2.99792458e8;
#[derive(Debug, Clone)]
pub struct EitLambda {
pub gamma_ge: f64,
pub gamma_se: f64,
pub gamma_gs: f64,
pub omega_c: f64,
pub delta_p: f64,
pub delta_c: f64,
}
impl EitLambda {
#[inline]
pub fn two_photon_detuning(&self) -> f64 {
self.delta_p - self.delta_c
}
pub fn susceptibility(&self, atomic_density: f64, dipole_moment_cm: f64) -> (f64, f64) {
let d = dipole_moment_cm;
let delta = self.two_photon_detuning();
let gamma_e = self.gamma_ge + self.gamma_se;
let a_re = self.delta_p;
let a_im = -gamma_e / 2.0;
let b_re = delta;
let b_im = -self.gamma_gs;
let ab_re = a_re * b_re - a_im * b_im;
let ab_im = a_re * b_im + a_im * b_re;
let denom_re = ab_re - self.omega_c * self.omega_c / 4.0;
let denom_im = ab_im;
let num_re = delta;
let num_im = -self.gamma_gs;
let denom_sq = denom_re * denom_re + denom_im * denom_im;
let ratio_re = (num_re * denom_re + num_im * denom_im) / denom_sq.max(f64::MIN_POSITIVE);
let ratio_im = (num_im * denom_re - num_re * denom_im) / denom_sq.max(f64::MIN_POSITIVE);
let prefactor = atomic_density * d * d / (EPS0 * HBAR);
(prefactor * ratio_re, prefactor * ratio_im)
}
pub fn eit_window_width(&self) -> f64 {
self.omega_c * self.omega_c / self.gamma_ge.max(f64::MIN_POSITIVE)
}
pub fn group_velocity(&self, atomic_density: f64, dipole_moment_cm: f64) -> f64 {
let dw = 1e3_f64; let mut eit_lo = self.clone();
eit_lo.delta_p = self.delta_p - dw / 2.0;
let mut eit_hi = self.clone();
eit_hi.delta_p = self.delta_p + dw / 2.0;
let (chi_re_lo, _) = eit_lo.susceptibility(atomic_density, dipole_moment_cm);
let (chi_re_hi, _) = eit_hi.susceptibility(atomic_density, dipole_moment_cm);
let d_chi_d_omega = (chi_re_hi - chi_re_lo) / dw;
let omega_p = 2.0 * PI * 3.84e14;
let n_group = 1.0 + 0.5 * omega_p * d_chi_d_omega;
C_LIGHT / n_group.max(1.0)
}
pub fn group_delay(
&self,
length_m: f64,
atomic_density: f64,
dipole_moment_cm: f64,
) -> f64 {
let v_g = self.group_velocity(atomic_density, dipole_moment_cm);
length_m / v_g - length_m / C_LIGHT
}
pub fn optical_depth(
&self,
length_m: f64,
atomic_density: f64,
dipole_moment_cm: f64,
) -> f64 {
let mut bare = self.clone();
bare.omega_c = 0.0;
bare.delta_p = 0.0;
let (_, chi_im) = bare.susceptibility(atomic_density, dipole_moment_cm);
let omega_p = 2.0 * PI * 3.84e14;
(omega_p * chi_im.abs() / C_LIGHT) * length_m
}
pub fn transmission(
&self,
delta_p: f64,
length_m: f64,
atomic_density: f64,
dipole_moment_cm: f64,
) -> f64 {
let mut eit = self.clone();
eit.delta_p = delta_p;
let (_, chi_im) = eit.susceptibility(atomic_density, dipole_moment_cm);
let omega_p = 2.0 * PI * 3.84e14;
let exponent = chi_im.abs() * omega_p * length_m / C_LIGHT;
(-exponent).exp()
}
pub fn absorption_spectrum(
&self,
delta_range: (f64, f64),
n_points: usize,
length_m: f64,
atomic_density: f64,
dipole_moment_cm: f64,
) -> Vec<(f64, f64)> {
let n = n_points.max(2);
let (d_lo, d_hi) = delta_range;
let step = (d_hi - d_lo) / (n - 1) as f64;
(0..n)
.map(|i| {
let dp = d_lo + i as f64 * step;
let t = self.transmission(dp, length_m, atomic_density, dipole_moment_cm);
(dp, t)
})
.collect()
}
}
#[derive(Debug, Clone)]
pub struct EitMemory {
pub eit: EitLambda,
pub length_m: f64,
pub atomic_density: f64,
pub dipole_moment_cm: f64,
}
impl EitMemory {
pub fn storage_efficiency(&self) -> f64 {
let od = self
.eit
.optical_depth(self.length_m, self.atomic_density, self.dipole_moment_cm);
let absorption_factor = 1.0 - (-od).exp();
absorption_factor * absorption_factor }
pub fn retrieval_efficiency(&self, control_pulse_area: f64) -> f64 {
let od = self
.eit
.optical_depth(self.length_m, self.atomic_density, self.dipole_moment_cm);
let pulse_factor = (control_pulse_area / 2.0).sin().powi(2).clamp(0.0, 1.0);
let base_efficiency = od / (1.0 + od);
base_efficiency * pulse_factor
}
pub fn coherence_time(&self) -> f64 {
1.0 / self.eit.gamma_gs.max(f64::MIN_POSITIVE)
}
pub fn bandwidth_hz(&self) -> f64 {
self.eit.omega_c * self.eit.omega_c / (2.0 * PI * self.eit.gamma_ge.max(f64::MIN_POSITIVE))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::f64::consts::PI;
fn rb87_eit() -> EitLambda {
EitLambda {
gamma_ge: 2.0 * PI * 6e6, gamma_se: 2.0 * PI * 6e6,
gamma_gs: 1e3, omega_c: 2.0 * PI * 2e6, delta_p: 0.0,
delta_c: 0.0,
}
}
#[test]
fn eit_window_width_rb87() {
let eit = EitLambda {
gamma_ge: 2e7,
gamma_se: 2e7,
gamma_gs: 1e3,
omega_c: 1e7,
delta_p: 0.0,
delta_c: 0.0,
};
let width = eit.eit_window_width();
assert!(
width > 1e5 && width < 1e9,
"EIT window width out of range: {}",
width
);
}
#[test]
fn two_photon_detuning_on_resonance() {
let eit = rb87_eit();
let delta = eit.two_photon_detuning();
assert!(delta.abs() < 1e-10, "Expected δ=0, got {}", delta);
}
#[test]
fn susceptibility_eit_window_vanishes() {
let eit = rb87_eit();
let n_at = 1e18_f64; let d = 1.0e-29_f64; let (_, chi_im_eit) = eit.susceptibility(n_at, d);
let mut bare = eit.clone();
bare.omega_c = 0.0;
let (_, chi_im_bare) = bare.susceptibility(n_at, d);
assert!(
chi_im_eit.abs() < chi_im_bare.abs(),
"EIT should reduce absorption: |Im χ_eit|={} |Im χ_bare|={}",
chi_im_eit.abs(),
chi_im_bare.abs()
);
}
#[test]
fn group_velocity_slow_light() {
let eit = rb87_eit();
let n_at = 1e18_f64;
let d = 1.0e-29_f64;
let v_g = eit.group_velocity(n_at, d);
assert!(v_g > 0.0 && v_g <= C_LIGHT, "v_g={}", v_g);
}
#[test]
fn transmission_at_resonance_is_high() {
let eit = rb87_eit();
let n_at = 1e14_f64; let d = 1.0e-29_f64;
let l = 1e-3_f64; let t = eit.transmission(0.0, l, n_at, d);
assert!(t > 0.0 && t <= 1.0, "Transmission={}", t);
}
#[test]
fn memory_coherence_time_microseconds() {
let mem = EitMemory {
eit: rb87_eit(),
length_m: 1e-2,
atomic_density: 1e18,
dipole_moment_cm: 1e-29,
};
let t_mem = mem.coherence_time();
assert!(t_mem > 1e-4 && t_mem < 10.0, "T_mem={}", t_mem);
}
#[test]
fn memory_bandwidth_mhz_range() {
let mem = EitMemory {
eit: rb87_eit(),
length_m: 1e-2,
atomic_density: 1e18,
dipole_moment_cm: 1e-29,
};
let bw = mem.bandwidth_hz();
assert!(bw > 1e3 && bw < 1e12, "bandwidth={} Hz", bw);
}
#[test]
fn absorption_spectrum_length() {
let eit = rb87_eit();
let spec = eit.absorption_spectrum(
(-1e8, 1e8),
100,
1e-2,
1e18,
1e-29,
);
assert_eq!(spec.len(), 100);
for (_, t) in &spec {
assert!(*t > 0.0 && *t <= 1.0, "T out of range: {}", t);
}
}
}