176 lines
6.2 KiB
Rust
176 lines
6.2 KiB
Rust
//! 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");
|
||
}
|