pub const H_BAR: f32 = 1.054_571_817e-34_f32;
pub const K_B: f32 = 1.380_649e-23_f32;
const TWO_PI: f32 = 2.0 * core::f32::consts::PI;
#[inline]
pub fn shot_noise_power_w(f_hz: f32, bandwidth_hz: f32) -> f32 {
H_BAR * TWO_PI * f_hz * bandwidth_hz
}
#[inline]
pub fn shot_noise_variance(f_hz: f32, bandwidth_hz: f32) -> f32 {
shot_noise_power_w(f_hz, bandwidth_hz)
}
#[inline]
pub fn thermal_noise_power_w(temp_k: f32, bandwidth_hz: f32) -> f32 {
K_B * temp_k * bandwidth_hz
}
#[inline]
pub fn quantum_to_thermal_ratio(f_hz: f32, temp_k: f32) -> f32 {
(H_BAR * TWO_PI * f_hz) / (K_B * temp_k.max(1e-3))
}
pub fn thermal_photon_number(f_hz: f32, temp_k: f32) -> f32 {
let r = quantum_to_thermal_ratio(f_hz, temp_k);
if r > 50.0 {
crate::math::exp_f32(-r)
} else if r < 0.01 {
1.0 / r
} else {
1.0 / (crate::math::exp_f32(r) - 1.0).max(1e-9)
}
}
#[inline]
pub fn sql_fraction_of_thermal(f_hz: f32, temp_k: f32) -> f32 {
quantum_to_thermal_ratio(f_hz, temp_k)
}
#[derive(Debug, Clone, Copy)]
pub struct QuantumNoiseTwin {
pub carrier_hz: f32,
pub bandwidth_hz: f32,
pub temp_k: f32,
pub squeezing_r: f32,
pub shot_noise_w: f32,
pub thermal_noise_w: f32,
pub r_qt: f32,
pub effective_floor_w: f32,
pub regime: ReceiverRegime,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReceiverRegime {
DeepThermal,
TransitionRegime,
QuantumLimited,
BelowSQL,
}
#[inline]
fn squeeze_factor(squeezing_r: f32) -> f32 {
if squeezing_r > 0.0 {
crate::math::exp_f32(-2.0 * squeezing_r)
} else {
1.0
}
}
#[inline]
fn effective_floor_w(squeezing_r: f32, squeezed_shot: f32, thermal_noise_w: f32, r_qt: f32) -> f32 {
if squeezing_r > 0.0 && squeezed_shot < thermal_noise_w {
squeezed_shot
} else if r_qt >= 0.1 {
squeezed_shot
} else {
thermal_noise_w
}
}
#[inline]
fn classify_regime(squeezing_r: f32, squeezed_shot: f32, shot_noise_w: f32, r_qt: f32) -> ReceiverRegime {
if squeezing_r > 0.0 && squeezed_shot < shot_noise_w * 0.9 {
ReceiverRegime::BelowSQL
} else if r_qt >= 1.0 {
ReceiverRegime::QuantumLimited
} else if r_qt >= 0.01 {
ReceiverRegime::TransitionRegime
} else {
ReceiverRegime::DeepThermal
}
}
impl QuantumNoiseTwin {
pub fn new(
carrier_hz: f32,
bandwidth_hz: f32,
temp_k: f32,
squeezing_r: f32,
) -> Self {
debug_assert!(carrier_hz > 0.0, "carrier_hz must be positive");
debug_assert!(bandwidth_hz > 0.0, "bandwidth_hz must be positive");
debug_assert!(temp_k > 0.0, "temp_k must be positive (Kelvin)");
debug_assert!(squeezing_r >= 0.0, "squeezing_r must be non-negative");
let shot_noise_w = shot_noise_power_w(carrier_hz, bandwidth_hz);
let thermal_noise_w = thermal_noise_power_w(temp_k, bandwidth_hz);
let r_qt = quantum_to_thermal_ratio(carrier_hz, temp_k);
let squeeze_factor = squeeze_factor(squeezing_r);
let squeezed_shot = shot_noise_w * squeeze_factor;
let effective_floor_w = effective_floor_w(squeezing_r, squeezed_shot, thermal_noise_w, r_qt);
let regime = classify_regime(squeezing_r, squeezed_shot, shot_noise_w, r_qt);
Self {
carrier_hz, bandwidth_hz, temp_k, squeezing_r,
shot_noise_w, thermal_noise_w, r_qt,
effective_floor_w, regime,
}
}
#[inline]
pub fn sigma_sq_floor(&self) -> f32 {
self.effective_floor_w
}
#[inline]
pub fn sql_margin(&self) -> f32 {
self.effective_floor_w / self.shot_noise_w.max(1e-30)
}
pub const DISCLAIMER: &'static str =
"Quantum noise model is a physical reference bound. \
All current SDR/FPGA receivers operate at the DeepThermal regime \
(R_QT << 1). QuantumLimited regime requires cryogenic hardware \
not available in Phase I. Provided as calibration framework.";
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn shot_noise_increases_with_frequency() {
let p_uhf = shot_noise_power_w(435e6, 1e6);
let p_xband = shot_noise_power_w(10e9, 1e6);
assert!(p_xband > p_uhf, "higher carrier must give higher shot noise");
}
#[test]
fn thermal_noise_room_temp_1mhz() {
let p = thermal_noise_power_w(290.0, 1e6);
assert!(p > 3.5e-15 && p < 4.5e-15, "thermal: {:.3e}", p);
}
#[test]
fn rqt_deep_thermal_at_room_temp_ghz() {
let r = quantum_to_thermal_ratio(10e9, 290.0);
assert!(r < 0.01, "10 GHz at 290K is deep thermal: R_QT = {:.2e}", r);
}
#[test]
fn rqt_quantum_limited_at_cryo() {
let r = quantum_to_thermal_ratio(10e9, 0.010);
assert!(r > 1.0, "10 GHz at 10 mK must be quantum-limited: R_QT = {:.2}", r);
}
#[test]
fn quantum_noise_twin_deep_thermal_regime() {
let twin = QuantumNoiseTwin::new(10e9, 1e6, 290.0, 0.0);
assert_eq!(twin.regime, ReceiverRegime::DeepThermal,
"10 GHz / 290 K must be DeepThermal");
assert!(twin.sql_margin() > 100.0,
"room-temp receiver is far above SQL: {:.2}", twin.sql_margin());
}
#[test]
fn quantum_noise_twin_quantum_limited_at_cryo() {
let twin = QuantumNoiseTwin::new(10e9, 1e6, 0.01, 0.0);
assert!(
matches!(twin.regime, ReceiverRegime::QuantumLimited | ReceiverRegime::TransitionRegime),
"10 GHz / 10 mK: {:?}", twin.regime,
);
}
#[test]
fn squeezing_reduces_shot_noise() {
let twin_no_sq = QuantumNoiseTwin::new(10e9, 1e6, 0.01, 0.0);
let twin_sq = QuantumNoiseTwin::new(10e9, 1e6, 0.01, 2.0); assert!(twin_sq.effective_floor_w < twin_no_sq.effective_floor_w,
"squeezing must reduce noise floor");
}
#[test]
fn thermal_photon_number_classical_limit() {
let n = thermal_photon_number(10e9, 290.0);
assert!(n > 100.0 && n < 1e5,
"10 GHz at 290K: n_th = {:.1}", n);
}
}