apsis-rs/crates/rf/apsis-noise/tests/temperature.rs

176 lines
6.2 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Tests for noise temperature and thermal noise power.
//!
//! 噪声温度与热噪声功率的测试。
use apsis_core::constant::BOLTZMANN;
use apsis_noise::{NoiseTemperature, REFERENCE_TEMPERATURE_K, thermal_noise_power};
const TOLERANCE: f64 = 1e-12;
#[test]
fn the_reference_temperature_is_290_kelvin() {
assert_eq!(REFERENCE_TEMPERATURE_K, 290.0);
assert_eq!(NoiseTemperature::REFERENCE.kelvin(), 290.0);
}
#[test]
fn a_zero_temperature_has_unit_noise_factor() {
let quiet = NoiseTemperature::from_kelvin(0.0);
assert_eq!(quiet.noise_factor(), 1.0);
assert_eq!(quiet.noise_figure_db(), Some(0.0));
}
#[test]
fn the_reference_temperature_is_a_noise_figure_of_three_decibels() {
// A noise figure is defined as the ratio of the total noise to the
// noise of a source at the reference temperature, so a stage whose
// excess noise equals the reference temperature has a factor of two,
// which is 3.01 dB.
// 噪声系数定义为总噪声与参考温度下源的噪声之比,故超额噪声等于参考温度的级其
// 因子为二,即 3.01 dB。
let value = NoiseTemperature::from_kelvin(REFERENCE_TEMPERATURE_K);
assert!((value.noise_factor() - 2.0).abs() < TOLERANCE);
assert!((value.noise_figure_db().expect("valid") - 3.010_299_956_639_812).abs() < 1e-12);
}
#[test]
fn noise_figure_and_temperature_round_trip() {
for figure in [0.0, 0.5, 1.0, 3.0, 10.0, 20.0] {
let temperature = NoiseTemperature::from_noise_figure_db(figure).expect("finite figure");
let recovered = temperature.noise_figure_db().expect("valid temperature");
assert!((recovered - figure).abs() < 1e-9, "figure {figure}");
}
}
#[test]
fn noise_factor_and_temperature_round_trip() {
for factor in [1.0, 1.5, 2.0, 10.0, 100.0] {
let temperature = NoiseTemperature::from_noise_factor(factor).expect("valid factor");
assert!(
(temperature.noise_factor() - factor).abs() < 1e-9,
"factor {factor}"
);
}
}
#[test]
fn a_known_noise_figure_gives_a_known_temperature() {
// A noise figure of 1 dB is a factor of 1.2589, so the temperature is
// 290 * 0.2589, about 75.1 K.
// 1 dB 的噪声系数其因子为 1.2589,故温度为 290 * 0.2589,约 75.1 K。
let temperature = NoiseTemperature::from_noise_figure_db(1.0).expect("finite");
assert!(
(temperature.kelvin() - 75.09).abs() < 0.01,
"{}",
temperature.kelvin()
);
}
#[test]
fn invalid_inputs_are_rejected() {
assert_eq!(NoiseTemperature::from_noise_figure_db(f64::NAN), None);
assert_eq!(NoiseTemperature::from_noise_figure_db(f64::INFINITY), None);
assert_eq!(NoiseTemperature::from_noise_factor(0.5), None);
assert_eq!(NoiseTemperature::from_noise_factor(f64::NAN), None);
}
#[test]
fn temperatures_add() {
let first = NoiseTemperature::from_kelvin(50.0);
let second = NoiseTemperature::from_kelvin(25.0);
assert_eq!((first + second).kelvin(), 75.0);
assert_eq!(first.plus(second).kelvin(), 75.0);
}
#[test]
fn validity_is_reported() {
assert!(NoiseTemperature::from_kelvin(0.0).is_valid());
assert!(NoiseTemperature::from_kelvin(290.0).is_valid());
assert!(!NoiseTemperature::from_kelvin(-1.0).is_valid());
assert!(!NoiseTemperature::from_kelvin(f64::NAN).is_valid());
}
#[test]
fn thermal_noise_power_follows_the_boltzmann_relation() {
let temperature = NoiseTemperature::from_kelvin(290.0);
let bandwidth = 1.0e6;
let power = thermal_noise_power(temperature, bandwidth).expect("valid");
let expected = BOLTZMANN * 290.0 * bandwidth;
assert!((power.watts() - expected).abs() < 1e-30);
}
#[test]
fn a_one_hertz_bandwidth_at_290_kelvin_is_minus_204_dbw() {
// k T B with T = 290 K and B = 1 Hz is 4.0e-21 W, which is -203.98 dBW.
// k T B,取 T = 290 K、B = 1 Hz,为 4.0e-21 W,即 -203.98 dBW。
let power = thermal_noise_power(NoiseTemperature::from_kelvin(290.0), 1.0).expect("valid");
assert!(
(power.dbw().expect("positive") + 203.98).abs() < 0.01,
"{} dBW",
power.dbw().expect("positive")
);
}
#[test]
fn a_thirty_six_megahertz_transponder_is_about_minus_128_dbw() {
// k T B with T = 290 K and B = 36 MHz is 1.44e-13 W, which is
// -128.41 dBW. A one hertz bandwidth at the same temperature is
// -203.98 dBW, and 36 MHz is 75.56 dB above one hertz.
// k T B,取 T = 290 K、B = 36 MHz,为 1.44e-13 W,即 -128.41 dBW。同一温度下
// 一赫兹带宽为 -203.98 dBW,而 36 MHz 比一赫兹高 75.56 dB。
let power = thermal_noise_power(NoiseTemperature::from_kelvin(290.0), 36.0e6).expect("valid");
let dbw = power.dbw().expect("positive");
assert!((dbw + 128.41).abs() < 0.01, "{dbw} dBW");
}
#[test]
fn noise_power_scales_with_temperature_and_bandwidth() {
let one_hertz = thermal_noise_power(NoiseTemperature::from_kelvin(100.0), 1.0).expect("valid");
let hundred_hertz =
thermal_noise_power(NoiseTemperature::from_kelvin(100.0), 100.0).expect("valid");
let double_temperature =
thermal_noise_power(NoiseTemperature::from_kelvin(200.0), 1.0).expect("valid");
// Each doubling of either factor adds three decibels.
// 任一因子每加倍一次加三分贝。
assert!(
(hundred_hertz.dbw().expect("positive") - one_hertz.dbw().expect("positive") - 20.0).abs()
< 1e-9
);
assert!(
(double_temperature.dbw().expect("positive")
- one_hertz.dbw().expect("positive")
- 3.010_299_956_639_812)
.abs()
< 1e-9
);
}
#[test]
fn a_zero_bandwidth_produces_no_noise() {
assert_eq!(
thermal_noise_power(NoiseTemperature::from_kelvin(290.0), 0.0),
None
);
}
#[test]
fn invalid_arguments_are_rejected() {
assert_eq!(
thermal_noise_power(NoiseTemperature::from_kelvin(-1.0), 1.0e6),
None
);
assert_eq!(
thermal_noise_power(NoiseTemperature::from_kelvin(290.0), -1.0),
None
);
assert_eq!(
thermal_noise_power(NoiseTemperature::from_kelvin(290.0), f64::NAN),
None
);
}
#[test]
fn display_includes_the_unit() {
assert_eq!(NoiseTemperature::from_kelvin(290.0).to_string(), "290 K");
}