152 lines
4.9 KiB
Rust
152 lines
4.9 KiB
Rust
//! Tests for the parabolic aperture model.
|
||
//!
|
||
//! 抛物面孔径模型的测试。
|
||
|
||
use apsis_antenna::{ParabolicAperture, beam_width};
|
||
use core::f64::consts::PI;
|
||
|
||
/// A three meter dish with a typical aperture efficiency.
|
||
///
|
||
/// 一面三米天线,具有典型孔径效率。
|
||
const DISH: ParabolicAperture = ParabolicAperture {
|
||
diameter: 3.0,
|
||
efficiency: 0.65,
|
||
};
|
||
|
||
#[test]
|
||
fn aperture_area_follows_from_the_diameter() {
|
||
let expected = PI * 1.5 * 1.5;
|
||
assert!((DISH.area() - expected).abs() < 1e-12);
|
||
assert!((DISH.effective_area() - expected * 0.65).abs() < 1e-12);
|
||
}
|
||
|
||
#[test]
|
||
fn peak_gain_matches_the_closed_form() {
|
||
// At 12 GHz the wavelength is 0.02498 m, and the gain is
|
||
// eta (pi D / lambda)^2.
|
||
// 12 GHz 下波长为 0.02498 m,增益为 eta (pi D / lambda)^2。
|
||
let wavelength = 0.024_982_710_7;
|
||
let gain = DISH.peak_gain(wavelength).expect("valid");
|
||
let expected = 0.65 * (PI * 3.0 / wavelength).powi(2);
|
||
assert!((gain.ratio() - expected).abs() < 1e-6);
|
||
// The result is about 49.66 dBi.
|
||
// 结果约为 49.66 dBi。
|
||
assert!(
|
||
(gain.dbi().expect("positive") - 49.661_764_937_398_814).abs() < 1e-9,
|
||
"dBi {}",
|
||
gain.dbi().expect("positive")
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn a_larger_dish_has_more_gain() {
|
||
let small = ParabolicAperture {
|
||
diameter: 1.0,
|
||
efficiency: 0.65,
|
||
};
|
||
let large = ParabolicAperture {
|
||
diameter: 2.0,
|
||
efficiency: 0.65,
|
||
};
|
||
let wavelength = 0.025;
|
||
let small_gain = small.peak_gain(wavelength).expect("valid");
|
||
let large_gain = large.peak_gain(wavelength).expect("valid");
|
||
// Doubling the diameter quadruples the gain, which is six decibels.
|
||
// 直径加倍使增益变为四倍,即六分贝。
|
||
assert!(
|
||
(large_gain.dbi().expect("positive") - small_gain.dbi().expect("positive") - 6.020_6).abs()
|
||
< 1e-6
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn a_higher_aperture_efficiency_adds_gain() {
|
||
let low = ParabolicAperture {
|
||
diameter: 3.0,
|
||
efficiency: 0.5,
|
||
};
|
||
let high = ParabolicAperture {
|
||
diameter: 3.0,
|
||
efficiency: 0.7,
|
||
};
|
||
let wavelength = 0.025;
|
||
assert!(
|
||
high.peak_gain(wavelength).expect("valid").ratio()
|
||
> low.peak_gain(wavelength).expect("valid").ratio()
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn the_beam_width_follows_the_wavelength_over_diameter() {
|
||
let wavelength = 0.025;
|
||
let uniform = DISH.uniform_beam_width(wavelength).expect("valid");
|
||
let tapered = DISH.half_power_beam_width(wavelength).expect("valid");
|
||
assert!((uniform - 1.02 * wavelength / 3.0).abs() < 1e-12);
|
||
// A tapered illumination widens the beam.
|
||
// 锥削照射使波束变宽。
|
||
assert!(tapered > uniform);
|
||
assert!((tapered - 1.15 * wavelength / 3.0).abs() < 1e-12);
|
||
}
|
||
|
||
#[test]
|
||
fn the_uniform_beam_width_matches_a_known_value() {
|
||
// A 3 m dish at 12 GHz has a half power beam width near 0.0085 radians,
|
||
// which is about 0.49 degrees.
|
||
// 12 GHz 下的 3 m 天线半功率波束宽度约为 0.0085 弧度,即约 0.49 度。
|
||
let width = DISH.uniform_beam_width(0.024_982_710_7).expect("valid");
|
||
assert!((width - 0.008_494).abs() < 1e-5, "width {width}");
|
||
assert!((width.to_degrees() - 0.486_7).abs() < 0.001);
|
||
}
|
||
|
||
#[test]
|
||
fn beam_width_helper_validates_its_arguments() {
|
||
assert!(beam_width(3.0, 0.025, 1.02).is_some());
|
||
assert_eq!(beam_width(0.0, 0.025, 1.02), None);
|
||
assert_eq!(beam_width(-1.0, 0.025, 1.02), None);
|
||
assert_eq!(beam_width(3.0, 0.0, 1.02), None);
|
||
assert_eq!(beam_width(3.0, -0.025, 1.02), None);
|
||
assert_eq!(beam_width(3.0, 0.025, 0.0), None);
|
||
assert_eq!(beam_width(f64::NAN, 0.025, 1.02), None);
|
||
assert_eq!(beam_width(3.0, f64::INFINITY, 1.02), None);
|
||
}
|
||
|
||
#[test]
|
||
fn an_invalid_aperture_produces_no_result() {
|
||
let zero_diameter = ParabolicAperture {
|
||
diameter: 0.0,
|
||
efficiency: 0.65,
|
||
};
|
||
assert!(!zero_diameter.is_valid());
|
||
assert_eq!(zero_diameter.peak_gain(0.025), None);
|
||
assert_eq!(zero_diameter.half_power_beam_width(0.025), None);
|
||
|
||
let bad_efficiency = ParabolicAperture {
|
||
diameter: 3.0,
|
||
efficiency: 1.5,
|
||
};
|
||
assert!(!bad_efficiency.is_valid());
|
||
assert_eq!(bad_efficiency.peak_gain(0.025), None);
|
||
|
||
let zero_efficiency = ParabolicAperture {
|
||
diameter: 3.0,
|
||
efficiency: 0.0,
|
||
};
|
||
assert!(!zero_efficiency.is_valid());
|
||
|
||
let non_finite = ParabolicAperture {
|
||
diameter: f64::NAN,
|
||
efficiency: 0.65,
|
||
};
|
||
assert!(!non_finite.is_valid());
|
||
}
|
||
|
||
#[test]
|
||
fn the_aperture_and_gain_conversions_are_consistent() {
|
||
// The peak gain and the effective area must describe the same antenna.
|
||
// 峰值增益与有效面积必须描述同一面天线。
|
||
let wavelength = 0.025;
|
||
let gain = DISH.peak_gain(wavelength).expect("valid");
|
||
let aperture = gain.effective_aperture(wavelength).expect("valid");
|
||
assert!((aperture - DISH.effective_area()).abs() < 1e-9);
|
||
}
|