use std::f64::consts::PI;
const HBAR: f64 = 1.054_571_817e-34; const EV_TO_J: f64 = 1.602_176_634e-19;
#[derive(Debug, Clone, Copy)]
pub struct TemporalInterface {
pub n_before: f64,
pub n_after: f64,
pub omega_incident: f64,
}
impl TemporalInterface {
pub fn transmitted_frequency(&self) -> f64 {
self.omega_incident * self.n_before / self.n_after
}
pub fn reflected_frequency(&self) -> f64 {
self.transmitted_frequency().abs()
}
pub fn transmission_amplitude(&self) -> f64 {
2.0 * self.n_before / (self.n_before + self.n_after)
}
pub fn reflection_amplitude(&self) -> f64 {
(self.n_before - self.n_after) / (self.n_before + self.n_after)
}
pub fn energy_change_ev(&self) -> f64 {
let delta_omega = self.transmitted_frequency() - self.omega_incident;
delta_omega * HBAR / EV_TO_J
}
pub fn verify_k_conservation(&self) -> bool {
let k_before = self.n_before * self.omega_incident;
let k_after = self.n_after * self.transmitted_frequency();
let rel_err = (k_before - k_after).abs() / k_before.abs().max(1e-100);
rel_err < 1e-10
}
pub fn intensity_transmission(&self) -> f64 {
(self.n_after / self.n_before) * self.transmission_amplitude().powi(2)
}
pub fn intensity_reflection(&self) -> f64 {
self.reflection_amplitude().powi(2)
}
pub fn energy_ratio(&self) -> f64 {
self.transmitted_frequency() / self.omega_incident
}
}
#[derive(Debug, Clone, Copy)]
pub struct TimeSlab {
pub n1: f64,
pub n2: f64,
pub duration_s: f64,
pub omega_inc: f64,
}
impl TimeSlab {
fn omega_inside(&self) -> f64 {
self.omega_inc * self.n1 / self.n2
}
pub fn output_frequencies(&self) -> (f64, f64) {
let omega_fwd = self.omega_inside() * self.n2 / self.n1;
let omega_bwd = self.omega_inside() * self.n2 / self.n1;
(omega_fwd, omega_bwd)
}
pub fn resonant_durations(&self, m: u32) -> f64 {
let delta_omega = (self.omega_inside() - self.omega_inc).abs();
if delta_omega == 0.0 {
return f64::INFINITY;
}
(m as f64) * PI / delta_omega
}
pub fn bandwidth_s(&self) -> f64 {
let delta_omega = (self.omega_inside() - self.omega_inc).abs();
if delta_omega == 0.0 {
return f64::INFINITY;
}
1.0 / delta_omega
}
pub fn accumulated_phase(&self) -> f64 {
self.omega_inside() * self.duration_s
}
pub fn total_transmission(&self) -> f64 {
let entry = TemporalInterface {
n_before: self.n1,
n_after: self.n2,
omega_incident: self.omega_inc,
};
let exit = TemporalInterface {
n_before: self.n2,
n_after: self.n1,
omega_incident: self.omega_inside(),
};
entry.intensity_transmission() * exit.intensity_transmission()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn air_glass() -> TemporalInterface {
TemporalInterface {
n_before: 1.5,
n_after: 2.0,
omega_incident: 2e15,
}
}
#[test]
fn temporal_k_conservation() {
let ti = air_glass();
assert!(
ti.verify_k_conservation(),
"k should be conserved across temporal interface"
);
}
#[test]
fn transmitted_frequency_ratio() {
let ti = air_glass();
let omega_t = ti.transmitted_frequency();
let expected = 2e15 * 1.5 / 2.0;
assert!(
(omega_t - expected).abs() < 1.0,
"transmitted frequency {omega_t} ≠ {expected}"
);
}
#[test]
fn reflection_amplitude_sign() {
let ti = air_glass();
assert!(ti.reflection_amplitude() < 0.0);
}
#[test]
fn energy_not_conserved() {
let ti = air_glass();
let ratio = ti.energy_ratio();
assert!(
(ratio - 1.0).abs() > 1e-10,
"energy should change at temporal interface"
);
}
#[test]
fn intensity_coefficients_sum() {
let ti = air_glass();
let tau_sq = ti.transmission_amplitude().powi(2);
let rho_sq = ti.reflection_amplitude().powi(2);
assert!(tau_sq > 0.0 && rho_sq >= 0.0);
}
#[test]
fn time_slab_output_frequencies() {
let slab = TimeSlab {
n1: 1.5,
n2: 2.0,
duration_s: 1e-12,
omega_inc: 2e15,
};
let (fwd, bwd) = slab.output_frequencies();
assert!(
(fwd - slab.omega_inc).abs() < 1.0,
"forward output should recover incident frequency: {fwd}"
);
assert!(bwd > 0.0);
}
#[test]
fn resonant_duration_m1() {
let slab = TimeSlab {
n1: 1.5,
n2: 2.0,
duration_s: 1e-12,
omega_inc: 2e15,
};
let t1 = slab.resonant_durations(1);
assert!(
t1 > 0.0 && t1.is_finite(),
"m=1 resonant duration should be positive finite: {t1}"
);
}
#[test]
fn bandwidth_inverse_delta_omega() {
let slab = TimeSlab {
n1: 1.0,
n2: 1.5,
duration_s: 1e-12,
omega_inc: 3e15,
};
let bw = slab.bandwidth_s();
let delta_omega = (slab.omega_inc * slab.n1 / slab.n2 - slab.omega_inc).abs();
let expected = 1.0 / delta_omega;
assert!((bw - expected).abs() / expected < 1e-10);
}
}