docs: bilingual comments for the atmosphere attenuation models
The P.838 rain curves, the P.676 gaseous lines, the P.839 isotherm table and the P.835 layered refraction.
This commit is contained in:
parent
f3cf18df41
commit
cfe8d72bb2
|
|
@ -28,42 +28,89 @@ use core::f64::consts::E;
|
||||||
/// The coefficients are the ones tabulated in table 1 of ITU-R P.676-12. The
|
/// The coefficients are the ones tabulated in table 1 of ITU-R P.676-12. The
|
||||||
/// first field is the line frequency in gigahertz and the rest are the
|
/// first field is the line frequency in gigahertz and the rest are the
|
||||||
/// dimensionless coefficients of the line.
|
/// dimensionless coefficients of the line.
|
||||||
|
///
|
||||||
|
/// 一条氧吸收谱线。
|
||||||
|
///
|
||||||
|
/// 各系数即 ITU-R P.676-12 表 1 所列。第一个字段是线频率,以吉赫兹计;
|
||||||
|
/// 其余为谱线的无量纲系数。
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct OxygenLine {
|
struct OxygenLine {
|
||||||
/// The line frequency, in gigahertz.
|
/// The line frequency, in gigahertz.
|
||||||
|
///
|
||||||
|
/// 线频率,以吉赫兹计。
|
||||||
|
///
|
||||||
|
/// 线频率,以吉赫兹计。
|
||||||
f0: f64,
|
f0: f64,
|
||||||
/// Line strength coefficient.
|
/// Line strength coefficient.
|
||||||
|
///
|
||||||
|
/// 谱线强度系数。
|
||||||
|
///
|
||||||
|
/// 谱线强度系数。
|
||||||
a1: f64,
|
a1: f64,
|
||||||
/// Temperature dependence of the line strength.
|
/// Temperature dependence of the line strength.
|
||||||
|
///
|
||||||
|
/// 谱线强度的温度依赖。
|
||||||
|
///
|
||||||
|
/// 谱线强度的温度依赖。
|
||||||
a2: f64,
|
a2: f64,
|
||||||
/// Line width coefficient.
|
/// Line width coefficient.
|
||||||
|
///
|
||||||
|
/// 谱线宽度系数。
|
||||||
|
///
|
||||||
|
/// 谱线宽度系数。
|
||||||
a3: f64,
|
a3: f64,
|
||||||
/// Pressure dependence of the line width.
|
/// Pressure dependence of the line width.
|
||||||
|
///
|
||||||
|
/// 谱线宽度的气压依赖。
|
||||||
|
///
|
||||||
|
/// 谱线宽度的气压依赖。
|
||||||
a4: f64,
|
a4: f64,
|
||||||
/// Pressure shift coefficient.
|
/// Pressure shift coefficient.
|
||||||
|
///
|
||||||
|
/// 气压频移系数。
|
||||||
a5: f64,
|
a5: f64,
|
||||||
/// Mixing ratio dependence of the pressure shift.
|
/// Mixing ratio dependence of the pressure shift.
|
||||||
|
///
|
||||||
|
/// 气压频移的混合比依赖。
|
||||||
a6: f64,
|
a6: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// One water vapour absorption line.
|
/// One water vapour absorption line.
|
||||||
///
|
///
|
||||||
/// The coefficients are the ones tabulated in table 2 of ITU-R P.676-12.
|
/// The coefficients are the ones tabulated in table 2 of ITU-R P.676-12.
|
||||||
|
///
|
||||||
|
/// 一条水汽吸收谱线。
|
||||||
|
///
|
||||||
|
/// 各系数即 ITU-R P.676-12 表 2 所列。
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct WaterLine {
|
struct WaterLine {
|
||||||
/// The line frequency, in gigahertz.
|
/// The line frequency, in gigahertz.
|
||||||
|
///
|
||||||
|
/// 线频率,以吉赫兹计。
|
||||||
f0: f64,
|
f0: f64,
|
||||||
/// Line strength coefficient.
|
/// Line strength coefficient.
|
||||||
|
///
|
||||||
|
/// 谱线强度系数。
|
||||||
b1: f64,
|
b1: f64,
|
||||||
/// Temperature dependence of the line strength.
|
/// Temperature dependence of the line strength.
|
||||||
|
///
|
||||||
|
/// 谱线强度的温度依赖。
|
||||||
b2: f64,
|
b2: f64,
|
||||||
/// Line width coefficient.
|
/// Line width coefficient.
|
||||||
|
///
|
||||||
|
/// 谱线宽度系数。
|
||||||
b3: f64,
|
b3: f64,
|
||||||
/// Pressure dependence of the line width.
|
/// Pressure dependence of the line width.
|
||||||
|
///
|
||||||
|
/// 谱线宽度的气压依赖。
|
||||||
b4: f64,
|
b4: f64,
|
||||||
/// Water vapour dependence of the line width.
|
/// Water vapour dependence of the line width.
|
||||||
|
///
|
||||||
|
/// 谱线宽度的水汽依赖。
|
||||||
b5: f64,
|
b5: f64,
|
||||||
/// Temperature dependence of the water vapour term.
|
/// Temperature dependence of the water vapour term.
|
||||||
|
///
|
||||||
|
/// 水汽项的温度依赖。
|
||||||
b6: f64,
|
b6: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,6 +119,11 @@ struct WaterLine {
|
||||||
/// The first thirty seven entries are the fine structure of the 60 GHz
|
/// The first thirty seven entries are the fine structure of the 60 GHz
|
||||||
/// complex, followed by the isolated line at 118.75 GHz and six lines in the
|
/// complex, followed by the isolated line at 118.75 GHz and six lines in the
|
||||||
/// submillimetre region.
|
/// submillimetre region.
|
||||||
|
///
|
||||||
|
/// ITU-R P.676-12 表 1 的氧吸收谱线。
|
||||||
|
///
|
||||||
|
/// 前三十七项是 60 GHz 复合体的精细结构,其后是 118.75 GHz 处的孤立线
|
||||||
|
/// 以及亚毫米波段的六条线。
|
||||||
const OXYGEN_LINES: &[OxygenLine] = &[
|
const OXYGEN_LINES: &[OxygenLine] = &[
|
||||||
OxygenLine {
|
OxygenLine {
|
||||||
f0: 50.474_214,
|
f0: 50.474_214,
|
||||||
|
|
@ -472,6 +524,8 @@ const OXYGEN_LINES: &[OxygenLine] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The water vapour absorption lines of table 2 of ITU-R P.676-12.
|
/// The water vapour absorption lines of table 2 of ITU-R P.676-12.
|
||||||
|
///
|
||||||
|
/// ITU-R P.676-12 表 2 的水汽吸收谱线。
|
||||||
const WATER_LINES: &[WaterLine] = &[
|
const WATER_LINES: &[WaterLine] = &[
|
||||||
WaterLine {
|
WaterLine {
|
||||||
f0: 22.235_080,
|
f0: 22.235_080,
|
||||||
|
|
@ -795,13 +849,24 @@ const WATER_LINES: &[WaterLine] = &[
|
||||||
/// The pressure is the dry air pressure, as the recommendation specifies. The
|
/// The pressure is the dry air pressure, as the recommendation specifies. The
|
||||||
/// water vapour density is separate because the partial pressure of water
|
/// water vapour density is separate because the partial pressure of water
|
||||||
/// vapour is derived from it.
|
/// vapour is derived from it.
|
||||||
|
///
|
||||||
|
/// 气体衰减所依赖的大气状态。
|
||||||
|
///
|
||||||
|
/// 气压是干空气气压,如建议书所规定。水汽密度单列,因为水汽分压由它
|
||||||
|
/// 导出。
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Atmosphere {
|
pub struct Atmosphere {
|
||||||
/// The dry air pressure, in hectopascals.
|
/// The dry air pressure, in hectopascals.
|
||||||
|
///
|
||||||
|
/// 干空气气压,以百帕计。
|
||||||
pub pressure_hpa: f64,
|
pub pressure_hpa: f64,
|
||||||
/// The water vapour density, in grams per cubic meter.
|
/// The water vapour density, in grams per cubic meter.
|
||||||
|
///
|
||||||
|
/// 水汽密度,以克每立方米计。
|
||||||
pub water_vapour_density: f64,
|
pub water_vapour_density: f64,
|
||||||
/// The temperature, in kelvin.
|
/// The temperature, in kelvin.
|
||||||
|
///
|
||||||
|
/// 温度,以开尔文计。
|
||||||
pub temperature_k: f64,
|
pub temperature_k: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -811,6 +876,11 @@ impl Atmosphere {
|
||||||
/// The values are the ones the recommendation uses for its reference
|
/// The values are the ones the recommendation uses for its reference
|
||||||
/// curves: a dry air pressure of 1013.25 hPa, a water vapour density of
|
/// curves: a dry air pressure of 1013.25 hPa, a water vapour density of
|
||||||
/// 7.5 g/m^3, and a temperature of 288.15 K.
|
/// 7.5 g/m^3, and a temperature of 288.15 K.
|
||||||
|
///
|
||||||
|
/// 平均海平面处的 ITU-R 参考大气。
|
||||||
|
///
|
||||||
|
/// 各值即该建议书用于其参考曲线者:干空气气压 1013.25 hPa,水汽
|
||||||
|
/// 密度 7.5 g/m^3,温度 288.15 K。
|
||||||
pub const REFERENCE: Self = Self {
|
pub const REFERENCE: Self = Self {
|
||||||
pressure_hpa: 1_013.25,
|
pressure_hpa: 1_013.25,
|
||||||
water_vapour_density: 7.5,
|
water_vapour_density: 7.5,
|
||||||
|
|
@ -818,6 +888,8 @@ impl Atmosphere {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Creates an atmosphere from its three parameters.
|
/// Creates an atmosphere from its three parameters.
|
||||||
|
///
|
||||||
|
/// 由其三个参数创建大气。
|
||||||
pub const fn new(pressure_hpa: f64, water_vapour_density: f64, temperature_k: f64) -> Self {
|
pub const fn new(pressure_hpa: f64, water_vapour_density: f64, temperature_k: f64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pressure_hpa,
|
pressure_hpa,
|
||||||
|
|
@ -830,11 +902,18 @@ impl Atmosphere {
|
||||||
///
|
///
|
||||||
/// The relation is `e = rho T / 216.7`, which follows from the ideal gas
|
/// The relation is `e = rho T / 216.7`, which follows from the ideal gas
|
||||||
/// law with the molar masses of water and dry air.
|
/// law with the molar masses of water and dry air.
|
||||||
|
///
|
||||||
|
/// 返回水汽分压,以百帕计。
|
||||||
|
///
|
||||||
|
/// 关系为 `e = rho T / 216.7`,它由理想气体定律连同水与干空气的摩尔
|
||||||
|
/// 质量得出。
|
||||||
pub fn water_vapour_partial_pressure(self) -> f64 {
|
pub fn water_vapour_partial_pressure(self) -> f64 {
|
||||||
self.water_vapour_density * self.temperature_k / 216.7
|
self.water_vapour_density * self.temperature_k / 216.7
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` when the state describes a physical atmosphere.
|
/// Returns `true` when the state describes a physical atmosphere.
|
||||||
|
///
|
||||||
|
/// 当该状态描述一个物理大气时返回 `true`。
|
||||||
pub fn is_valid(self) -> bool {
|
pub fn is_valid(self) -> bool {
|
||||||
self.pressure_hpa.is_finite()
|
self.pressure_hpa.is_finite()
|
||||||
&& self.pressure_hpa > 0.0
|
&& self.pressure_hpa > 0.0
|
||||||
|
|
@ -869,11 +948,13 @@ pub fn specific_attenuation_dry_air(frequency_ghz: f64, atmosphere: Atmosphere)
|
||||||
let mut sum = 0.0;
|
let mut sum = 0.0;
|
||||||
for line in OXYGEN_LINES {
|
for line in OXYGEN_LINES {
|
||||||
// Equations 5 and 6: the line width and the pressure shift.
|
// Equations 5 and 6: the line width and the pressure shift.
|
||||||
|
// 式 5 与式 6:谱线宽度与气压频移。
|
||||||
let width = line.a3 * 1.0e-4 * (p * theta.powf(0.8 - line.a4) + 1.1 * e * theta);
|
let width = line.a3 * 1.0e-4 * (p * theta.powf(0.8 - line.a4) + 1.1 * e * theta);
|
||||||
let width = (width * width + 2.25e-6).sqrt();
|
let width = (width * width + 2.25e-6).sqrt();
|
||||||
let shift = (line.a5 + line.a6 * theta) * 1.0e-4 * (p + e) * theta.powf(0.8);
|
let shift = (line.a5 + line.a6 * theta) * 1.0e-4 * (p + e) * theta.powf(0.8);
|
||||||
|
|
||||||
// Equation 4: the line shape factor.
|
// Equation 4: the line shape factor.
|
||||||
|
// 式 4:线型因子。
|
||||||
let shape = frequency_ghz / line.f0
|
let shape = frequency_ghz / line.f0
|
||||||
* ((width - shift * (line.f0 - frequency_ghz))
|
* ((width - shift * (line.f0 - frequency_ghz))
|
||||||
/ ((line.f0 - frequency_ghz).powi(2) + width * width)
|
/ ((line.f0 - frequency_ghz).powi(2) + width * width)
|
||||||
|
|
@ -881,11 +962,13 @@ pub fn specific_attenuation_dry_air(frequency_ghz: f64, atmosphere: Atmosphere)
|
||||||
/ ((line.f0 + frequency_ghz).powi(2) + width * width));
|
/ ((line.f0 + frequency_ghz).powi(2) + width * width));
|
||||||
|
|
||||||
// Equation 3: the line strength.
|
// Equation 3: the line strength.
|
||||||
|
// 式 3:谱线强度。
|
||||||
let strength = line.a1 * 1.0e-7 * p * theta.powi(3) * E.powf(line.a2 * (1.0 - theta));
|
let strength = line.a1 * 1.0e-7 * p * theta.powi(3) * E.powf(line.a2 * (1.0 - theta));
|
||||||
sum += strength * shape;
|
sum += strength * shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The non-resonant Debye spectrum, equation 8.
|
// The non-resonant Debye spectrum, equation 8.
|
||||||
|
// 非共振 Debye 谱,式 8。
|
||||||
let d = 5.6e-4 * (p + e) * theta.powf(0.8);
|
let d = 5.6e-4 * (p + e) * theta.powf(0.8);
|
||||||
let debye = frequency_ghz
|
let debye = frequency_ghz
|
||||||
* p
|
* p
|
||||||
|
|
@ -924,6 +1007,7 @@ pub fn specific_attenuation_water_vapour(
|
||||||
for line in WATER_LINES {
|
for line in WATER_LINES {
|
||||||
// Equation 7: the line width, which has a different form from the
|
// Equation 7: the line width, which has a different form from the
|
||||||
// oxygen case.
|
// oxygen case.
|
||||||
|
// 式 7:谱线宽度,其形式与氧的情形不同。
|
||||||
let width =
|
let width =
|
||||||
line.b3 * 1.0e-4 * (p * theta.powf(line.b4) + line.b5 * e * theta.powf(line.b6));
|
line.b3 * 1.0e-4 * (p * theta.powf(line.b4) + line.b5 * e * theta.powf(line.b6));
|
||||||
let width = 0.535 * width
|
let width = 0.535 * width
|
||||||
|
|
@ -934,6 +1018,7 @@ pub fn specific_attenuation_water_vapour(
|
||||||
+ width / ((line.f0 + frequency_ghz).powi(2) + width * width));
|
+ width / ((line.f0 + frequency_ghz).powi(2) + width * width));
|
||||||
|
|
||||||
// Equation 3 for the water vapour lines.
|
// Equation 3 for the water vapour lines.
|
||||||
|
// 对水汽谱线的式 3。
|
||||||
let strength = line.b1 * 1.0e-1 * e * theta.powf(3.5) * E.powf(line.b2 * (1.0 - theta));
|
let strength = line.b1 * 1.0e-1 * e * theta.powf(3.5) * E.powf(line.b2 * (1.0 - theta));
|
||||||
sum += strength * shape;
|
sum += strength * shape;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ use crate::gaseous::{Atmosphere, specific_attenuation_dry_air, specific_attenuat
|
||||||
/// The coefficients of the dry air equivalent height, table 3 of P.676-12.
|
/// The coefficients of the dry air equivalent height, table 3 of P.676-12.
|
||||||
///
|
///
|
||||||
/// Each entry is the coefficient and the line frequency in gigahertz.
|
/// Each entry is the coefficient and the line frequency in gigahertz.
|
||||||
|
///
|
||||||
|
/// 干空气等效高度的系数,P.676-12 表 3。
|
||||||
|
///
|
||||||
|
/// 每项是系数与线频率,后者以吉赫兹计。
|
||||||
const DRY_HEIGHT_TERMS: &[(f64, f64)] = &[
|
const DRY_HEIGHT_TERMS: &[(f64, f64)] = &[
|
||||||
(0.159_7, 118.750_334),
|
(0.159_7, 118.750_334),
|
||||||
(0.106_6, 368.498_246),
|
(0.106_6, 368.498_246),
|
||||||
|
|
@ -34,6 +38,10 @@ const DRY_HEIGHT_TERMS: &[(f64, f64)] = &[
|
||||||
///
|
///
|
||||||
/// Each entry is the line frequency in gigahertz, a coefficient, and a
|
/// Each entry is the line frequency in gigahertz, a coefficient, and a
|
||||||
/// width-like parameter.
|
/// width-like parameter.
|
||||||
|
///
|
||||||
|
/// 水汽等效高度的系数,P.676-12 表 4。
|
||||||
|
///
|
||||||
|
/// 每项是线频率(以吉赫兹计)、一个系数,以及一个类宽度参数。
|
||||||
const WET_HEIGHT_TERMS: &[(f64, f64, f64)] = &[
|
const WET_HEIGHT_TERMS: &[(f64, f64, f64)] = &[
|
||||||
(22.235_08, 1.52, 2.56),
|
(22.235_08, 1.52, 2.56),
|
||||||
(183.310_087, 7.62, 10.2),
|
(183.310_087, 7.62, 10.2),
|
||||||
|
|
@ -52,11 +60,17 @@ const WET_HEIGHT_TERMS: &[(f64, f64, f64)] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The equivalent height of dry air and of water vapour, in kilometers.
|
/// The equivalent height of dry air and of water vapour, in kilometers.
|
||||||
|
///
|
||||||
|
/// 干空气与水汽的等效高度,单位为千米。
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct EquivalentHeights {
|
pub struct EquivalentHeights {
|
||||||
/// The equivalent height of dry air, in kilometers.
|
/// The equivalent height of dry air, in kilometers.
|
||||||
|
///
|
||||||
|
/// 干空气的等效高度,单位为千米。
|
||||||
pub dry_km: f64,
|
pub dry_km: f64,
|
||||||
/// The equivalent height of water vapour, in kilometers.
|
/// The equivalent height of water vapour, in kilometers.
|
||||||
|
///
|
||||||
|
/// 水汽的等效高度,单位为千米。
|
||||||
pub wet_km: f64,
|
pub wet_km: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,10 +100,12 @@ pub fn equivalent_heights(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<
|
||||||
let rp = (atmosphere.pressure_hpa + e) / 1_013.25;
|
let rp = (atmosphere.pressure_hpa + e) / 1_013.25;
|
||||||
|
|
||||||
// Equation 31, the resonance term centred just below 60 GHz.
|
// Equation 31, the resonance term centred just below 60 GHz.
|
||||||
|
// 式 31,中心略低于 60 GHz 的共振项。
|
||||||
let term1 = 5.104_0 / (1.0 + 0.066 * rp.powf(-2.3))
|
let term1 = 5.104_0 / (1.0 + 0.066 * rp.powf(-2.3))
|
||||||
* (-((frequency_ghz - 59.7) / (2.87 + 12.4 * (-7.9 * rp).exp())).powi(2)).exp();
|
* (-((frequency_ghz - 59.7) / (2.87 + 12.4 * (-7.9 * rp).exp())).powi(2)).exp();
|
||||||
|
|
||||||
// Equation 32, the residual contribution of the submillimetre lines.
|
// Equation 32, the residual contribution of the submillimetre lines.
|
||||||
|
// 式 32,亚毫米波各线的残余贡献。
|
||||||
let term2: f64 = DRY_HEIGHT_TERMS
|
let term2: f64 = DRY_HEIGHT_TERMS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(coefficient, line_frequency)| {
|
.map(|&(coefficient, line_frequency)| {
|
||||||
|
|
@ -99,6 +115,7 @@ pub fn equivalent_heights(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
// Equation 33, the far wing correction.
|
// Equation 33, the far wing correction.
|
||||||
|
// 式 33,远翼修正。
|
||||||
let term3 = 0.011_4 * frequency_ghz / (1.0 + 0.14 * rp.powf(-2.6))
|
let term3 = 0.011_4 * frequency_ghz / (1.0 + 0.14 * rp.powf(-2.6))
|
||||||
* (15.02 * frequency_ghz.powi(2) - 1_353.0 * frequency_ghz + 5.333e4)
|
* (15.02 * frequency_ghz.powi(2) - 1_353.0 * frequency_ghz + 5.333e4)
|
||||||
/ (frequency_ghz.powi(3) - 151.3 * frequency_ghz.powi(2) + 9_629.0 * frequency_ghz
|
/ (frequency_ghz.powi(3) - 151.3 * frequency_ghz.powi(2) + 9_629.0 * frequency_ghz
|
||||||
|
|
@ -108,6 +125,7 @@ pub fn equivalent_heights(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<
|
||||||
|
|
||||||
// Equation 30, with the pressure dependent cap that applies below
|
// Equation 30, with the pressure dependent cap that applies below
|
||||||
// 70 GHz.
|
// 70 GHz.
|
||||||
|
// 式 30,含适用于 70 GHz 以下、依赖气压的上限。
|
||||||
let dry = 6.1 * a / (1.0 + 0.17 * rp.powf(-1.1)) * (1.0 + term1 + term2 + term3);
|
let dry = 6.1 * a / (1.0 + 0.17 * rp.powf(-1.1)) * (1.0 + term1 + term2 + term3);
|
||||||
let dry = if frequency_ghz < 70.0 {
|
let dry = if frequency_ghz < 70.0 {
|
||||||
dry.min(10.7 * rp.powf(0.3))
|
dry.min(10.7 * rp.powf(0.3))
|
||||||
|
|
@ -116,6 +134,7 @@ pub fn equivalent_heights(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<
|
||||||
};
|
};
|
||||||
|
|
||||||
// Equations 36 through 38 and 35b.
|
// Equations 36 through 38 and 35b.
|
||||||
|
// 式 36 至式 38 以及式 35b。
|
||||||
let a_wet = 1.929_8 - 0.041_66 * (temperature - 273.15) + 0.051_7 * rho;
|
let a_wet = 1.929_8 - 0.041_66 * (temperature - 273.15) + 0.051_7 * rho;
|
||||||
let b_wet = 1.167_4 - 0.006_22 * (temperature - 273.15) + 0.006_3 * rho;
|
let b_wet = 1.167_4 - 0.006_22 * (temperature - 273.15) + 0.006_3 * rho;
|
||||||
let sigma = 1.013 / (1.0 + (-8.6 * (rp - 0.57)).exp());
|
let sigma = 1.013 / (1.0 + (-8.6 * (rp - 0.57)).exp());
|
||||||
|
|
@ -166,6 +185,15 @@ pub fn zenith_attenuation(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<
|
||||||
///
|
///
|
||||||
/// Returns `None` when the frequency or atmosphere is not usable, or when
|
/// Returns `None` when the frequency or atmosphere is not usable, or when
|
||||||
/// the elevation is at or below the horizon.
|
/// the elevation is at or below the horizon.
|
||||||
|
///
|
||||||
|
/// 返回某仰角下沿斜路径的衰减,单位为分贝。
|
||||||
|
///
|
||||||
|
/// 天顶衰减除以仰角的正弦。其使用的平面平行近似即建议书用于近似方法
|
||||||
|
/// 者;在约五度仰角以上是准确的。
|
||||||
|
///
|
||||||
|
/// 仰角以弧度计。
|
||||||
|
///
|
||||||
|
/// 频率或大气不可用,或仰角在地平及其以下时返回 `None`。
|
||||||
pub fn slant_path_attenuation(
|
pub fn slant_path_attenuation(
|
||||||
frequency_ghz: f64,
|
frequency_ghz: f64,
|
||||||
elevation: f64,
|
elevation: f64,
|
||||||
|
|
@ -184,6 +212,12 @@ pub fn slant_path_attenuation(
|
||||||
/// boundaries. The layers between them are thin near the surface and grow
|
/// boundaries. The layers between them are thin near the surface and grow
|
||||||
/// with height, so the integration resolves the dense lower atmosphere where
|
/// with height, so the integration resolves the dense lower atmosphere where
|
||||||
/// the absorption is concentrated.
|
/// the absorption is concentrated.
|
||||||
|
///
|
||||||
|
/// 精确斜路径积分所用的层界数。
|
||||||
|
///
|
||||||
|
/// 建议书 P.676 以 `delta_i = 1e-4 exp(i / 100)`(`i` 从零到 921)定义
|
||||||
|
/// 层界,共得 922 个层界。其间的层在地表附近很薄并随高度增厚,故该积分
|
||||||
|
/// 能分辨吸收集中的稠密低层大气。
|
||||||
const EXACT_BOUNDARY_COUNT: usize = 922;
|
const EXACT_BOUNDARY_COUNT: usize = 922;
|
||||||
|
|
||||||
/// The Earth radius used by the ray trace, in kilometers.
|
/// The Earth radius used by the ray trace, in kilometers.
|
||||||
|
|
@ -191,6 +225,11 @@ const EXACT_BOUNDARY_COUNT: usize = 922;
|
||||||
/// The recommendation uses the mean radius, not the geopotential radius of
|
/// The recommendation uses the mean radius, not the geopotential radius of
|
||||||
/// the standard atmosphere, because this value enters the geometry of the
|
/// the standard atmosphere, because this value enters the geometry of the
|
||||||
/// ray rather than the definition of the height.
|
/// ray rather than the definition of the height.
|
||||||
|
///
|
||||||
|
/// 射线追踪所用的地球半径,单位为千米。
|
||||||
|
///
|
||||||
|
/// 建议书用的是平均半径,而非标准大气的地势半径,因为该值进入射线的
|
||||||
|
/// 几何,而非高度的定义。
|
||||||
const RAY_TRACE_EARTH_RADIUS_KM: f64 = 6_371.0;
|
const RAY_TRACE_EARTH_RADIUS_KM: f64 = 6_371.0;
|
||||||
|
|
||||||
/// Returns the attenuation along a slant path by the exact method of
|
/// Returns the attenuation along a slant path by the exact method of
|
||||||
|
|
@ -219,6 +258,25 @@ const RAY_TRACE_EARTH_RADIUS_KM: f64 = 6_371.0;
|
||||||
///
|
///
|
||||||
/// Source: ITU-R Recommendation P.676-12, equations 13 through 19, with the
|
/// Source: ITU-R Recommendation P.676-12, equations 13 through 19, with the
|
||||||
/// layered atmosphere of ITU-R Recommendation P.835-6.
|
/// layered atmosphere of ITU-R Recommendation P.835-6.
|
||||||
|
///
|
||||||
|
/// 以建议书 P.676 的精确方法返回沿斜路径的衰减。
|
||||||
|
///
|
||||||
|
/// 精确方法把大气分成厚度随高度指数增长的一叠层,计算每层的比衰减,
|
||||||
|
/// 并按射线穿过该层的路径长度对每层的贡献加权求和。由于射线发生折射,
|
||||||
|
/// 路径长度以射线追踪求得,其中对相邻层折射率之比施加 Snell 定律,而
|
||||||
|
/// 近似方法忽略这一点。
|
||||||
|
///
|
||||||
|
/// 这是低仰角下宜用的形式,此时 [`slant_path_attenuation`] 所用的平面
|
||||||
|
/// 平行近似不准确。它的代价高得多,故近似形式仍可供其足够胜任的高仰角
|
||||||
|
/// 情形使用。
|
||||||
|
///
|
||||||
|
/// 频率以吉赫兹计,仰角以弧度计,地表大气提供地面处的气压、水汽密度与
|
||||||
|
/// 温度。地表水汽密度缩放指数水汽廓线,故该大气界定了整叠层。
|
||||||
|
///
|
||||||
|
/// 频率、仰角或大气不可用时返回 `None`。
|
||||||
|
///
|
||||||
|
/// 出处:ITU-R 建议书 P.676-12,式 13 至式 19,分层大气取自 ITU-R
|
||||||
|
/// 建议书 P.835-6。
|
||||||
pub fn slant_path_attenuation_exact(
|
pub fn slant_path_attenuation_exact(
|
||||||
frequency_ghz: f64,
|
frequency_ghz: f64,
|
||||||
elevation: f64,
|
elevation: f64,
|
||||||
|
|
@ -233,6 +291,7 @@ pub fn slant_path_attenuation_exact(
|
||||||
|
|
||||||
// Build the stack of layer boundaries. Each entry holds the geometric
|
// Build the stack of layer boundaries. Each entry holds the geometric
|
||||||
// height, the thickness, the profile values, and the refractive index.
|
// height, the thickness, the profile values, and the refractive index.
|
||||||
|
// 构建层界叠层。每项保存几何高度、厚度、廓线值与折射率。
|
||||||
let thickness_step = (1.0_f64 / 100.0).exp();
|
let thickness_step = (1.0_f64 / 100.0).exp();
|
||||||
let mut heights = [0.0_f64; EXACT_BOUNDARY_COUNT];
|
let mut heights = [0.0_f64; EXACT_BOUNDARY_COUNT];
|
||||||
let mut thicknesses = [0.0_f64; EXACT_BOUNDARY_COUNT];
|
let mut thicknesses = [0.0_f64; EXACT_BOUNDARY_COUNT];
|
||||||
|
|
@ -245,6 +304,7 @@ pub fn slant_path_attenuation_exact(
|
||||||
let exponent = index as f64 / 100.0;
|
let exponent = index as f64 / 100.0;
|
||||||
thicknesses[index] = 1.0e-4 * exponent.exp();
|
thicknesses[index] = 1.0e-4 * exponent.exp();
|
||||||
// Equation 15: the geometric height of the boundary.
|
// Equation 15: the geometric height of the boundary.
|
||||||
|
// 式 15:层界的几何高度。
|
||||||
heights[index] = 1.0e-4 * (exponent.exp() - 1.0) / (thickness_step - 1.0);
|
heights[index] = 1.0e-4 * (exponent.exp() - 1.0) / (thickness_step - 1.0);
|
||||||
|
|
||||||
let temperature = crate::p835::standard_temperature(heights[index]);
|
let temperature = crate::p835::standard_temperature(heights[index]);
|
||||||
|
|
@ -259,6 +319,7 @@ pub fn slant_path_attenuation_exact(
|
||||||
|
|
||||||
// The refractive index takes the total pressure, as the
|
// The refractive index takes the total pressure, as the
|
||||||
// recommendation specifies, not the dry air pressure.
|
// recommendation specifies, not the dry air pressure.
|
||||||
|
// 折射率取总气压,如建议书所规定,而非干空气气压。
|
||||||
let vapour_pressure = density * temperature / 216.7;
|
let vapour_pressure = density * temperature / 216.7;
|
||||||
indices[index] =
|
indices[index] =
|
||||||
crate::p835::radio_refractive_index(pressure, vapour_pressure, temperature);
|
crate::p835::radio_refractive_index(pressure, vapour_pressure, temperature);
|
||||||
|
|
@ -266,6 +327,7 @@ pub fn slant_path_attenuation_exact(
|
||||||
|
|
||||||
// The ray starts below the local horizon by the complement of the
|
// The ray starts below the local horizon by the complement of the
|
||||||
// elevation, and is bent upward as it climbs.
|
// elevation, and is bent upward as it climbs.
|
||||||
|
// 射线自当地地平以下、低仰角的余角处开始,并随上升而向上弯折。
|
||||||
let mut angle = core::f64::consts::FRAC_PI_2 - elevation;
|
let mut angle = core::f64::consts::FRAC_PI_2 - elevation;
|
||||||
let mut total = 0.0;
|
let mut total = 0.0;
|
||||||
|
|
||||||
|
|
@ -275,6 +337,7 @@ pub fn slant_path_attenuation_exact(
|
||||||
let specific = crate::gaseous::specific_attenuation(frequency_ghz, layer_atmosphere)?;
|
let specific = crate::gaseous::specific_attenuation(frequency_ghz, layer_atmosphere)?;
|
||||||
|
|
||||||
// Equation 17: the path length through the layer.
|
// Equation 17: the path length through the layer.
|
||||||
|
// 式 17:穿过该层的路径长度。
|
||||||
let radius = RAY_TRACE_EARTH_RADIUS_KM + heights[index];
|
let radius = RAY_TRACE_EARTH_RADIUS_KM + heights[index];
|
||||||
let delta = thicknesses[index];
|
let delta = thicknesses[index];
|
||||||
let length = -radius * angle.cos()
|
let length = -radius * angle.cos()
|
||||||
|
|
@ -286,6 +349,7 @@ pub fn slant_path_attenuation_exact(
|
||||||
total += length * specific;
|
total += length * specific;
|
||||||
|
|
||||||
// Equation 18a: the angle at which the ray leaves the layer.
|
// Equation 18a: the angle at which the ray leaves the layer.
|
||||||
|
// 式 18a:射线离开该层的角度。
|
||||||
let cosine_argument = ((-length * length - 2.0 * radius * delta - delta * delta)
|
let cosine_argument = ((-length * length - 2.0 * radius * delta - delta * delta)
|
||||||
/ (2.0 * length * radius + 2.0 * length * delta))
|
/ (2.0 * length * radius + 2.0 * length * delta))
|
||||||
.clamp(-1.0, 1.0);
|
.clamp(-1.0, 1.0);
|
||||||
|
|
@ -294,6 +358,8 @@ pub fn slant_path_attenuation_exact(
|
||||||
// Equation 19a: Snell's law at the boundary, using the ratio of the
|
// Equation 19a: Snell's law at the boundary, using the ratio of the
|
||||||
// refractive index here to the one above. The topmost boundary has
|
// refractive index here to the one above. The topmost boundary has
|
||||||
// no layer above it, so its ratio is one.
|
// no layer above it, so its ratio is one.
|
||||||
|
// 式 19a:层界处的 Snell 定律,使用此处折射率与上方折射率之比。
|
||||||
|
// 最顶部的层界上方没有层,故其比为一。
|
||||||
let next = (index + 1).min(EXACT_BOUNDARY_COUNT - 1);
|
let next = (index + 1).min(EXACT_BOUNDARY_COUNT - 1);
|
||||||
let ratio = if next == index {
|
let ratio = if next == index {
|
||||||
1.0
|
1.0
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,17 @@ use core::f64::consts::PI;
|
||||||
///
|
///
|
||||||
/// The elevation is measured from the horizon and the zenith angle from the
|
/// The elevation is measured from the horizon and the zenith angle from the
|
||||||
/// vertical, so the two add to a right angle.
|
/// vertical, so the two add to a right angle.
|
||||||
|
///
|
||||||
|
/// 返回某天顶角对应的仰角。
|
||||||
|
///
|
||||||
|
/// 仰角自地平量起,天顶角自垂线量起,故两者相加为直角。
|
||||||
pub fn elevation_from_zenith(zenith_angle: f64) -> f64 {
|
pub fn elevation_from_zenith(zenith_angle: f64) -> f64 {
|
||||||
PI / 2.0 - zenith_angle
|
PI / 2.0 - zenith_angle
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the zenith angle for an elevation angle.
|
/// Returns the zenith angle for an elevation angle.
|
||||||
|
///
|
||||||
|
/// 返回某仰角对应的天顶角。
|
||||||
pub fn zenith_to_elevation(elevation: f64) -> f64 {
|
pub fn zenith_to_elevation(elevation: f64) -> f64 {
|
||||||
PI / 2.0 - elevation
|
PI / 2.0 - elevation
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +41,23 @@ pub fn zenith_to_elevation(elevation: f64) -> f64 {
|
||||||
/// parallel geometry it models.
|
/// parallel geometry it models.
|
||||||
///
|
///
|
||||||
/// Returns infinity at or below the horizon, where no direct path exists.
|
/// Returns infinity at or below the horizon, where no direct path exists.
|
||||||
|
///
|
||||||
|
/// 返回给定仰角下沿斜路径的大气质量。
|
||||||
|
///
|
||||||
|
/// 大气质量是穿过平坦大气的路径长度与垂直路径长度之比。对平面平行
|
||||||
|
/// 大气它是仰角的余割,
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// m = 1 / sin(elevation)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 故在天顶处为一,在地平处无界增长。平面平行假定在约十度仰角以下
|
||||||
|
/// 失效,那里地球曲率使路径比该式更短,真实大气质量更小。
|
||||||
|
///
|
||||||
|
/// 该值在低仰角处不被截断。需要在地平附近取有限上界的调用方应自行
|
||||||
|
/// 施加;本函数报告它所建模的平面平行几何。
|
||||||
|
///
|
||||||
|
/// 在地平及其以下不存在直接路径,返回无穷。
|
||||||
pub fn air_mass(elevation: f64) -> f64 {
|
pub fn air_mass(elevation: f64) -> f64 {
|
||||||
let sine = elevation.sin();
|
let sine = elevation.sin();
|
||||||
if sine <= 0.0 {
|
if sine <= 0.0 {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,11 @@
|
||||||
/// slightly different from the polar radius used elsewhere. It is the value
|
/// slightly different from the polar radius used elsewhere. It is the value
|
||||||
/// that makes the geopotential height consistent with the tabulated
|
/// that makes the geopotential height consistent with the tabulated
|
||||||
/// profiles.
|
/// profiles.
|
||||||
|
///
|
||||||
|
/// 用于势高转换的地球半径,单位为千米。
|
||||||
|
///
|
||||||
|
/// 建议书为标准大气固定了该值,它与别处所用的极半径略有不同。正是该值
|
||||||
|
/// 使势高与所列廓线一致。
|
||||||
const GEOPOTENTIAL_EARTH_RADIUS_KM: f64 = 6_356.766;
|
const GEOPOTENTIAL_EARTH_RADIUS_KM: f64 = 6_356.766;
|
||||||
|
|
||||||
/// Returns the geopotential height for a geometric height, in kilometers.
|
/// Returns the geopotential height for a geometric height, in kilometers.
|
||||||
|
|
@ -34,6 +39,17 @@ const GEOPOTENTIAL_EARTH_RADIUS_KM: f64 = 6_356.766;
|
||||||
/// with `R` the fixed Earth radius of the standard atmosphere and `H` the
|
/// with `R` the fixed Earth radius of the standard atmosphere and `H` the
|
||||||
/// geometric height. The geopotential height is always the smaller of the
|
/// geometric height. The geopotential height is always the smaller of the
|
||||||
/// two.
|
/// two.
|
||||||
|
///
|
||||||
|
/// 返回某几何高度对应的势高,单位为千米。
|
||||||
|
///
|
||||||
|
/// 关系为
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// h_p = R H / (R + H)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 其中 `R` 是标准大气固定的地球半径,`H` 是几何高度。势高总是两者中较
|
||||||
|
/// 小者。
|
||||||
pub fn geopotential_height(geometric_height_km: f64) -> f64 {
|
pub fn geopotential_height(geometric_height_km: f64) -> f64 {
|
||||||
GEOPOTENTIAL_EARTH_RADIUS_KM * geometric_height_km
|
GEOPOTENTIAL_EARTH_RADIUS_KM * geometric_height_km
|
||||||
/ (GEOPOTENTIAL_EARTH_RADIUS_KM + geometric_height_km)
|
/ (GEOPOTENTIAL_EARTH_RADIUS_KM + geometric_height_km)
|
||||||
|
|
@ -139,6 +155,21 @@ pub fn standard_water_vapour_density(geometric_height_km: f64, surface_density:
|
||||||
///
|
///
|
||||||
/// Source: ITU-R Recommendation P.453, which gives this expression for the
|
/// Source: ITU-R Recommendation P.453, which gives this expression for the
|
||||||
/// refractive index of moist air.
|
/// refractive index of moist air.
|
||||||
|
///
|
||||||
|
/// 返回湿空气的无线电折射率,无量纲。
|
||||||
|
///
|
||||||
|
/// 关系为
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// N = 77.6 P_d / T + 72 e / T + 3.75e5 e / T^2
|
||||||
|
/// n = 1 + N 1e-6
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 其中 `P_d` 是干空气气压,`e` 是水汽分压,两者均以百帕计;`T` 是
|
||||||
|
/// 温度,以开尔文计。前两项是非色散折射率,第三项是使水汽产生强烈效应
|
||||||
|
/// 的偶极项。
|
||||||
|
///
|
||||||
|
/// 出处:ITU-R 建议书 P.453,它给出湿空气折射率的这一表达式。
|
||||||
pub fn radio_refractive_index(
|
pub fn radio_refractive_index(
|
||||||
dry_pressure_hpa: f64,
|
dry_pressure_hpa: f64,
|
||||||
vapour_pressure_hpa: f64,
|
vapour_pressure_hpa: f64,
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,18 @@
|
||||||
use crate::p839_table::ZERO_ISOTHERM_HEIGHT_METRES;
|
use crate::p839_table::ZERO_ISOTHERM_HEIGHT_METRES;
|
||||||
|
|
||||||
/// The grid resolution of the tabulated isotherm height, in degrees.
|
/// The grid resolution of the tabulated isotherm height, in degrees.
|
||||||
|
///
|
||||||
|
/// 列表等温线高度的网格分辨率,单位为度。
|
||||||
const STEP_DEGREES: f64 = 1.5;
|
const STEP_DEGREES: f64 = 1.5;
|
||||||
|
|
||||||
/// The number of rows in the table, running from north to south.
|
/// The number of rows in the table, running from north to south.
|
||||||
|
///
|
||||||
|
/// 表中的行数,自北向南排列。
|
||||||
const ROWS: usize = 121;
|
const ROWS: usize = 121;
|
||||||
|
|
||||||
/// The number of columns in the table, running from east to east.
|
/// The number of columns in the table, running from east to east.
|
||||||
|
///
|
||||||
|
/// 表中的列数,自东向东排列。
|
||||||
const COLUMNS: usize = 241;
|
const COLUMNS: usize = 241;
|
||||||
|
|
||||||
/// The offset added to the isotherm height to obtain the rain height, in
|
/// The offset added to the isotherm height to obtain the rain height, in
|
||||||
|
|
@ -30,6 +36,11 @@ const COLUMNS: usize = 241;
|
||||||
/// The recommendation states that the rain height is the isotherm height
|
/// The recommendation states that the rain height is the isotherm height
|
||||||
/// plus 0.36 km, which represents the depth of the melting layer below the
|
/// plus 0.36 km, which represents the depth of the melting layer below the
|
||||||
/// isotherm.
|
/// isotherm.
|
||||||
|
///
|
||||||
|
/// 加到等温线高度上以获得雨顶高度的偏移,单位为千米。
|
||||||
|
///
|
||||||
|
/// 建议书指出雨顶高度是等温线高度加 0.36 km,它代表等温线以下融化层的
|
||||||
|
/// 深度。
|
||||||
pub const RAIN_HEIGHT_OFFSET_KM: f64 = 0.36;
|
pub const RAIN_HEIGHT_OFFSET_KM: f64 = 0.36;
|
||||||
|
|
||||||
/// Returns the height of the zero degree isotherm at a location, in
|
/// Returns the height of the zero degree isotherm at a location, in
|
||||||
|
|
@ -45,6 +56,15 @@ pub const RAIN_HEIGHT_OFFSET_KM: f64 = 0.36;
|
||||||
///
|
///
|
||||||
/// Source: ITU-R Recommendation P.839-4, equation 1 and the tabulated
|
/// Source: ITU-R Recommendation P.839-4, equation 1 and the tabulated
|
||||||
/// isotherm height.
|
/// isotherm height.
|
||||||
|
///
|
||||||
|
/// 返回某位置零度等温线的高度,以平均海平面以上千米计。
|
||||||
|
///
|
||||||
|
/// 纬度以度计、北正;经度以度计、东正。该值由列表网格双线性插值得到,
|
||||||
|
/// 经度先归约到 `[0, 360)`,故任何约定都被接受。
|
||||||
|
///
|
||||||
|
/// 任一坐标非有限,或纬度超出网格范围时返回 `None`。
|
||||||
|
///
|
||||||
|
/// 出处:ITU-R 建议书 P.839-4,式 1 及所列等温线高度。
|
||||||
pub fn zero_isotherm_height(latitude: f64, longitude: f64) -> Option<f64> {
|
pub fn zero_isotherm_height(latitude: f64, longitude: f64) -> Option<f64> {
|
||||||
if !latitude.is_finite() || !longitude.is_finite() {
|
if !latitude.is_finite() || !longitude.is_finite() {
|
||||||
return None;
|
return None;
|
||||||
|
|
@ -55,12 +75,14 @@ pub fn zero_isotherm_height(latitude: f64, longitude: f64) -> Option<f64> {
|
||||||
|
|
||||||
// The rows run from north to south, so the row index grows as the
|
// The rows run from north to south, so the row index grows as the
|
||||||
// latitude falls.
|
// latitude falls.
|
||||||
|
// 各行自北向南排列,故行下标随纬度下降而增大。
|
||||||
let row_position = (90.0 - latitude) / STEP_DEGREES;
|
let row_position = (90.0 - latitude) / STEP_DEGREES;
|
||||||
let row_lower = (row_position.floor() as usize).min(ROWS - 1);
|
let row_lower = (row_position.floor() as usize).min(ROWS - 1);
|
||||||
let row_upper = (row_lower + 1).min(ROWS - 1);
|
let row_upper = (row_lower + 1).min(ROWS - 1);
|
||||||
let row_fraction = row_position - row_lower as f64;
|
let row_fraction = row_position - row_lower as f64;
|
||||||
|
|
||||||
// The columns run from 0 to 360 degrees east, wrapping at the seam.
|
// The columns run from 0 to 360 degrees east, wrapping at the seam.
|
||||||
|
// 各列自东经 0 度到 360 度排列,在接缝处环绕。
|
||||||
let longitude = longitude.rem_euclid(360.0);
|
let longitude = longitude.rem_euclid(360.0);
|
||||||
let column_position = longitude / STEP_DEGREES;
|
let column_position = longitude / STEP_DEGREES;
|
||||||
let column_lower = (column_position.floor() as usize).min(COLUMNS - 1);
|
let column_lower = (column_position.floor() as usize).min(COLUMNS - 1);
|
||||||
|
|
@ -71,6 +93,7 @@ pub fn zero_isotherm_height(latitude: f64, longitude: f64) -> Option<f64> {
|
||||||
|row: usize, column: usize| f64::from(ZERO_ISOTHERM_HEIGHT_METRES[row][column]) / 1000.0;
|
|row: usize, column: usize| f64::from(ZERO_ISOTHERM_HEIGHT_METRES[row][column]) / 1000.0;
|
||||||
|
|
||||||
// Bilinear interpolation.
|
// Bilinear interpolation.
|
||||||
|
// 双线性插值。
|
||||||
let top = sample(row_lower, column_lower)
|
let top = sample(row_lower, column_lower)
|
||||||
+ (sample(row_lower, column_upper) - sample(row_lower, column_lower)) * column_fraction;
|
+ (sample(row_lower, column_upper) - sample(row_lower, column_lower)) * column_fraction;
|
||||||
let bottom = sample(row_upper, column_lower)
|
let bottom = sample(row_upper, column_lower)
|
||||||
|
|
@ -84,11 +107,19 @@ pub fn zero_isotherm_height(latitude: f64, longitude: f64) -> Option<f64> {
|
||||||
/// [`RAIN_HEIGHT_OFFSET_KM`], as the recommendation defines it.
|
/// [`RAIN_HEIGHT_OFFSET_KM`], as the recommendation defines it.
|
||||||
///
|
///
|
||||||
/// Returns `None` when the coordinates are not usable.
|
/// Returns `None` when the coordinates are not usable.
|
||||||
|
///
|
||||||
|
/// 返回某位置的雨顶高度,以平均海平面以上千米计。
|
||||||
|
///
|
||||||
|
/// 它是零度等温线高度加 [`RAIN_HEIGHT_OFFSET_KM`],如建议书所定义。
|
||||||
|
///
|
||||||
|
/// 坐标不可用时返回 `None`。
|
||||||
pub fn rain_height(latitude: f64, longitude: f64) -> Option<f64> {
|
pub fn rain_height(latitude: f64, longitude: f64) -> Option<f64> {
|
||||||
Some(zero_isotherm_height(latitude, longitude)? + RAIN_HEIGHT_OFFSET_KM)
|
Some(zero_isotherm_height(latitude, longitude)? + RAIN_HEIGHT_OFFSET_KM)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the grid resolution of the tabulated isotherm height, in degrees.
|
/// Returns the grid resolution of the tabulated isotherm height, in degrees.
|
||||||
|
///
|
||||||
|
/// 返回列表等温线高度的网格分辨率,单位为度。
|
||||||
pub const fn grid_step_degrees() -> f64 {
|
pub const fn grid_step_degrees() -> f64 {
|
||||||
STEP_DEGREES
|
STEP_DEGREES
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,15 @@
|
||||||
///
|
///
|
||||||
/// Source: ITU-R Recommendation P.839-4, *Rain height model for prediction
|
/// Source: ITU-R Recommendation P.839-4, *Rain height model for prediction
|
||||||
/// methods*, which tabulates the isotherm height on this grid.
|
/// methods*, which tabulates the isotherm height on this grid.
|
||||||
|
///
|
||||||
|
/// 零度等温线的高度,单位为米。
|
||||||
|
///
|
||||||
|
/// 网格在行方向上自北纬 90 度到南纬 90 度,在列方向上自东经 0 度到
|
||||||
|
/// 360 度,步长均为 1.5 度,故有 121 行 241 列。分数纬度或经度处的值
|
||||||
|
/// 由周围四点之间的双线性插值求得。
|
||||||
|
///
|
||||||
|
/// 出处:ITU-R 建议书 P.839-4,*Rain height model for prediction methods*,
|
||||||
|
/// 它在该网格上列出等温线高度。
|
||||||
pub static ZERO_ISOTHERM_HEIGHT_METRES: [[u16; 241]; 121] = [
|
pub static ZERO_ISOTHERM_HEIGHT_METRES: [[u16; 241]; 121] = [
|
||||||
[
|
[
|
||||||
2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096,
|
2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096, 2096,
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ use apsis_rf::Decibel;
|
||||||
///
|
///
|
||||||
/// The value accounts for the refraction of the ray in the lower atmosphere,
|
/// The value accounts for the refraction of the ray in the lower atmosphere,
|
||||||
/// which makes the Earth appear larger than it is.
|
/// which makes the Earth appear larger than it is.
|
||||||
|
///
|
||||||
|
/// 路径几何所用的地球有效半径,单位为千米。
|
||||||
|
///
|
||||||
|
/// 该值考虑了射线在低层大气中的折射,折射使地球显得比实际更大。
|
||||||
const EFFECTIVE_EARTH_RADIUS_KM: f64 = 8_500.0;
|
const EFFECTIVE_EARTH_RADIUS_KM: f64 = 8_500.0;
|
||||||
|
|
||||||
/// A mid latitude rain height, in kilometers above sea level.
|
/// A mid latitude rain height, in kilometers above sea level.
|
||||||
|
|
@ -37,20 +41,36 @@ const EFFECTIVE_EARTH_RADIUS_KM: f64 = 8_500.0;
|
||||||
/// height of Recommendation P.839, which is tabulated as a function of
|
/// height of Recommendation P.839, which is tabulated as a function of
|
||||||
/// latitude and longitude. Prefer [`rain_attenuation_at`], which looks the
|
/// latitude and longitude. Prefer [`rain_attenuation_at`], which looks the
|
||||||
/// value up, over [`rain_attenuation`] with this constant.
|
/// value up, over [`rain_attenuation`] with this constant.
|
||||||
|
///
|
||||||
|
/// 中纬度雨顶高度,以海拔千米计。
|
||||||
|
///
|
||||||
|
/// 建议书 P.618 从建议书 P.839 的零度等温线高度取雨顶高度,后者按纬度
|
||||||
|
/// 与经度列表给出。相较用本常量调用 [`rain_attenuation`],更宜用会查表
|
||||||
|
/// 的 [`rain_attenuation_at`]。
|
||||||
pub const DEFAULT_RAIN_HEIGHT_KM: f64 = 3.0;
|
pub const DEFAULT_RAIN_HEIGHT_KM: f64 = 3.0;
|
||||||
|
|
||||||
/// One term of a P.838-3 curve fit.
|
/// One term of a P.838-3 curve fit.
|
||||||
|
///
|
||||||
|
/// P.838-3 曲线拟合的一项。
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct CurveTerm {
|
struct CurveTerm {
|
||||||
/// The amplitude coefficient.
|
/// The amplitude coefficient.
|
||||||
|
///
|
||||||
|
/// 幅度系数。
|
||||||
amplitude: f64,
|
amplitude: f64,
|
||||||
/// The centre of the term, on a base ten logarithmic frequency axis.
|
/// The centre of the term, on a base ten logarithmic frequency axis.
|
||||||
|
///
|
||||||
|
/// 该项的中心,在十进对数频率轴上。
|
||||||
centre: f64,
|
centre: f64,
|
||||||
/// The width of the term, on a base ten logarithmic frequency axis.
|
/// The width of the term, on a base ten logarithmic frequency axis.
|
||||||
|
///
|
||||||
|
/// 该项的宽度,在十进对数频率轴上。
|
||||||
width: f64,
|
width: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The coefficients of the `k` curve fit for horizontal polarisation.
|
/// The coefficients of the `k` curve fit for horizontal polarisation.
|
||||||
|
///
|
||||||
|
/// 水平极化 `k` 曲线拟合的系数。
|
||||||
const K_HORIZONTAL_TERMS: &[CurveTerm] = &[
|
const K_HORIZONTAL_TERMS: &[CurveTerm] = &[
|
||||||
CurveTerm {
|
CurveTerm {
|
||||||
amplitude: -5.339_80,
|
amplitude: -5.339_80,
|
||||||
|
|
@ -75,6 +95,8 @@ const K_HORIZONTAL_TERMS: &[CurveTerm] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The coefficients of the `k` curve fit for vertical polarisation.
|
/// The coefficients of the `k` curve fit for vertical polarisation.
|
||||||
|
///
|
||||||
|
/// 垂直极化 `k` 曲线拟合的系数。
|
||||||
const K_VERTICAL_TERMS: &[CurveTerm] = &[
|
const K_VERTICAL_TERMS: &[CurveTerm] = &[
|
||||||
CurveTerm {
|
CurveTerm {
|
||||||
amplitude: -3.805_95,
|
amplitude: -3.805_95,
|
||||||
|
|
@ -99,6 +121,8 @@ const K_VERTICAL_TERMS: &[CurveTerm] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The coefficients of the `alpha` curve fit for horizontal polarisation.
|
/// The coefficients of the `alpha` curve fit for horizontal polarisation.
|
||||||
|
///
|
||||||
|
/// 水平极化 `alpha` 曲线拟合的系数。
|
||||||
const ALPHA_HORIZONTAL_TERMS: &[CurveTerm] = &[
|
const ALPHA_HORIZONTAL_TERMS: &[CurveTerm] = &[
|
||||||
CurveTerm {
|
CurveTerm {
|
||||||
amplitude: -0.143_18,
|
amplitude: -0.143_18,
|
||||||
|
|
@ -128,6 +152,8 @@ const ALPHA_HORIZONTAL_TERMS: &[CurveTerm] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The coefficients of the `alpha` curve fit for vertical polarisation.
|
/// The coefficients of the `alpha` curve fit for vertical polarisation.
|
||||||
|
///
|
||||||
|
/// 垂直极化 `alpha` 曲线拟合的系数。
|
||||||
const ALPHA_VERTICAL_TERMS: &[CurveTerm] = &[
|
const ALPHA_VERTICAL_TERMS: &[CurveTerm] = &[
|
||||||
CurveTerm {
|
CurveTerm {
|
||||||
amplitude: -0.077_71,
|
amplitude: -0.077_71,
|
||||||
|
|
@ -157,32 +183,58 @@ const ALPHA_VERTICAL_TERMS: &[CurveTerm] = &[
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The linear coefficients of the `k` curve fits.
|
/// The linear coefficients of the `k` curve fits.
|
||||||
|
///
|
||||||
|
/// `k` 曲线拟合的线性系数。
|
||||||
const K_SLOPE_HORIZONTAL: f64 = -0.189_61;
|
const K_SLOPE_HORIZONTAL: f64 = -0.189_61;
|
||||||
/// The constant of the horizontal `k` curve fit.
|
/// The constant of the horizontal `k` curve fit.
|
||||||
|
///
|
||||||
|
/// 水平 `k` 曲线拟合的常数。
|
||||||
const K_OFFSET_HORIZONTAL: f64 = 0.711_47;
|
const K_OFFSET_HORIZONTAL: f64 = 0.711_47;
|
||||||
/// The linear coefficient of the vertical `k` curve fit.
|
/// The linear coefficient of the vertical `k` curve fit.
|
||||||
|
///
|
||||||
|
/// 垂直 `k` 曲线拟合的线性系数。
|
||||||
const K_SLOPE_VERTICAL: f64 = -0.163_98;
|
const K_SLOPE_VERTICAL: f64 = -0.163_98;
|
||||||
/// The constant of the vertical `k` curve fit.
|
/// The constant of the vertical `k` curve fit.
|
||||||
|
///
|
||||||
|
/// 垂直 `k` 曲线拟合的常数。
|
||||||
const K_OFFSET_VERTICAL: f64 = 0.632_97;
|
const K_OFFSET_VERTICAL: f64 = 0.632_97;
|
||||||
/// The linear coefficient of the horizontal `alpha` curve fit.
|
/// The linear coefficient of the horizontal `alpha` curve fit.
|
||||||
|
///
|
||||||
|
/// 水平 `alpha` 曲线拟合的线性系数。
|
||||||
const ALPHA_SLOPE_HORIZONTAL: f64 = 0.678_49;
|
const ALPHA_SLOPE_HORIZONTAL: f64 = 0.678_49;
|
||||||
/// The constant of the horizontal `alpha` curve fit.
|
/// The constant of the horizontal `alpha` curve fit.
|
||||||
|
///
|
||||||
|
/// 水平 `alpha` 曲线拟合的常数。
|
||||||
const ALPHA_OFFSET_HORIZONTAL: f64 = -1.955_37;
|
const ALPHA_OFFSET_HORIZONTAL: f64 = -1.955_37;
|
||||||
/// The linear coefficient of the vertical `alpha` curve fit.
|
/// The linear coefficient of the vertical `alpha` curve fit.
|
||||||
|
///
|
||||||
|
/// 垂直 `alpha` 曲线拟合的线性系数。
|
||||||
const ALPHA_SLOPE_VERTICAL: f64 = -0.053_739;
|
const ALPHA_SLOPE_VERTICAL: f64 = -0.053_739;
|
||||||
/// The constant of the vertical `alpha` curve fit.
|
/// The constant of the vertical `alpha` curve fit.
|
||||||
|
///
|
||||||
|
/// 垂直 `alpha` 曲线拟合的常数。
|
||||||
const ALPHA_OFFSET_VERTICAL: f64 = 0.834_33;
|
const ALPHA_OFFSET_VERTICAL: f64 = 0.834_33;
|
||||||
|
|
||||||
/// A rain attenuation result at a given elevation.
|
/// A rain attenuation result at a given elevation.
|
||||||
|
///
|
||||||
|
/// 给定仰角下的降雨衰减结果。
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct RainAttenuation {
|
pub struct RainAttenuation {
|
||||||
/// The specific attenuation, in decibels per kilometer.
|
/// The specific attenuation, in decibels per kilometer.
|
||||||
|
///
|
||||||
|
/// 比衰减,单位为分贝每千米。
|
||||||
pub specific_db_per_km: f64,
|
pub specific_db_per_km: f64,
|
||||||
/// The effective path length through the rain, in kilometers.
|
/// The effective path length through the rain, in kilometers.
|
||||||
|
///
|
||||||
|
/// 穿过降雨的有效路径长度,单位为千米。
|
||||||
pub path_length_km: f64,
|
pub path_length_km: f64,
|
||||||
/// The total attenuation along the path, in decibels.
|
/// The total attenuation along the path, in decibels.
|
||||||
|
///
|
||||||
|
/// 沿路径的总衰减,单位为分贝。
|
||||||
pub attenuation_db: f64,
|
pub attenuation_db: f64,
|
||||||
/// The horizontal reduction factor, dimensionless and at most one.
|
/// The horizontal reduction factor, dimensionless and at most one.
|
||||||
|
///
|
||||||
|
/// 水平缩减因子,无量纲且至多为一。
|
||||||
pub horizontal_reduction: f64,
|
pub horizontal_reduction: f64,
|
||||||
/// The vertical adjustment factor, dimensionless.
|
/// The vertical adjustment factor, dimensionless.
|
||||||
///
|
///
|
||||||
|
|
@ -190,16 +242,26 @@ pub struct RainAttenuation {
|
||||||
/// of the two geometric path estimates. It is at most one when the path
|
/// of the two geometric path estimates. It is at most one when the path
|
||||||
/// meets the rain layer at a steep angle and can exceed one at a shallow
|
/// meets the rain layer at a steep angle and can exceed one at a shallow
|
||||||
/// angle, which is the behaviour Recommendation P.618 gives.
|
/// angle, which is the behaviour Recommendation P.618 gives.
|
||||||
|
///
|
||||||
|
/// 垂直调整因子,无量纲。
|
||||||
|
///
|
||||||
|
/// 该因子是有效路径长度与两个几何路径估计中较长者之比。当路径以陡
|
||||||
|
/// 角与雨层相交时至多为一,以浅角相交时可超过一,这正是建议书
|
||||||
|
/// P.618 所给出的行为。
|
||||||
pub vertical_adjustment: f64,
|
pub vertical_adjustment: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RainAttenuation {
|
impl RainAttenuation {
|
||||||
/// Returns the total attenuation.
|
/// Returns the total attenuation.
|
||||||
|
///
|
||||||
|
/// 返回总衰减。
|
||||||
pub fn attenuation(self) -> Decibel {
|
pub fn attenuation(self) -> Decibel {
|
||||||
Decibel::from_db(self.attenuation_db)
|
Decibel::from_db(self.attenuation_db)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` when every value is finite and not negative.
|
/// Returns `true` when every value is finite and not negative.
|
||||||
|
///
|
||||||
|
/// 当每个值有限且非负时返回 `true`。
|
||||||
pub fn is_valid(self) -> bool {
|
pub fn is_valid(self) -> bool {
|
||||||
self.specific_db_per_km.is_finite()
|
self.specific_db_per_km.is_finite()
|
||||||
&& self.specific_db_per_km >= 0.0
|
&& self.specific_db_per_km >= 0.0
|
||||||
|
|
@ -214,12 +276,18 @@ impl RainAttenuation {
|
||||||
///
|
///
|
||||||
/// The term is a Gaussian on a base ten logarithmic frequency axis, so the
|
/// The term is a Gaussian on a base ten logarithmic frequency axis, so the
|
||||||
/// frequency must be in gigahertz and positive.
|
/// frequency must be in gigahertz and positive.
|
||||||
|
///
|
||||||
|
/// 求一个 P.838-3 曲线项。
|
||||||
|
///
|
||||||
|
/// 该项是十进对数频率轴上的高斯,故频率必须以吉赫兹计且为正。
|
||||||
fn curve_term(term: CurveTerm, frequency_ghz: f64) -> f64 {
|
fn curve_term(term: CurveTerm, frequency_ghz: f64) -> f64 {
|
||||||
let logarithm = frequency_ghz.log10();
|
let logarithm = frequency_ghz.log10();
|
||||||
term.amplitude * (-((logarithm - term.centre) / term.width).powi(2)).exp()
|
term.amplitude * (-((logarithm - term.centre) / term.width).powi(2)).exp()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `k` for a polarisation, before the elevation correction.
|
/// Returns the `k` for a polarisation, before the elevation correction.
|
||||||
|
///
|
||||||
|
/// 返回某极化的 `k`,在仰角修正之前。
|
||||||
fn base_k(terms: &[CurveTerm], slope: f64, offset: f64, frequency_ghz: f64) -> f64 {
|
fn base_k(terms: &[CurveTerm], slope: f64, offset: f64, frequency_ghz: f64) -> f64 {
|
||||||
let gaussian: f64 = terms
|
let gaussian: f64 = terms
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -229,6 +297,8 @@ fn base_k(terms: &[CurveTerm], slope: f64, offset: f64, frequency_ghz: f64) -> f
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `alpha` for a polarisation, before the elevation correction.
|
/// Returns the `alpha` for a polarisation, before the elevation correction.
|
||||||
|
///
|
||||||
|
/// 返回某极化的 `alpha`,在仰角修正之前。
|
||||||
fn base_alpha(terms: &[CurveTerm], slope: f64, offset: f64, frequency_ghz: f64) -> f64 {
|
fn base_alpha(terms: &[CurveTerm], slope: f64, offset: f64, frequency_ghz: f64) -> f64 {
|
||||||
let gaussian: f64 = terms
|
let gaussian: f64 = terms
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -252,6 +322,19 @@ fn base_alpha(terms: &[CurveTerm], slope: f64, offset: f64, frequency_ghz: f64)
|
||||||
/// 1000 GHz.
|
/// 1000 GHz.
|
||||||
///
|
///
|
||||||
/// Source: ITU-R Recommendation P.838-3, equations 2 and 3.
|
/// Source: ITU-R Recommendation P.838-3, equations 2 and 3.
|
||||||
|
///
|
||||||
|
/// 返回比衰减幂律的 P.838-3 系数。
|
||||||
|
///
|
||||||
|
/// 极化是电场与水平方向之间以弧度计的角度,故零为水平、直角为垂直。
|
||||||
|
/// 仰角以弧度计。
|
||||||
|
///
|
||||||
|
/// 结果是关系 `gamma = k R^alpha` 中系数 `k` 与指数 `alpha` 的一对值,
|
||||||
|
/// 其中降雨率以毫米每小时计,结果以分贝每千米计。
|
||||||
|
///
|
||||||
|
/// 频率、极化或仰角不可用时返回 `None`。该建议书针对 1 GHz 至 1000 GHz
|
||||||
|
/// 的频率陈述。
|
||||||
|
///
|
||||||
|
/// 出处:ITU-R 建议书 P.838-3,式 2 与式 3。
|
||||||
pub fn rain_coefficients(frequency: f64, polarisation: f64, elevation: f64) -> Option<(f64, f64)> {
|
pub fn rain_coefficients(frequency: f64, polarisation: f64, elevation: f64) -> Option<(f64, f64)> {
|
||||||
let frequency_ghz = frequency / 1.0e9;
|
let frequency_ghz = frequency / 1.0e9;
|
||||||
if !frequency_ghz.is_finite() || !(1.0..=1_000.0).contains(&frequency_ghz) {
|
if !frequency_ghz.is_finite() || !(1.0..=1_000.0).contains(&frequency_ghz) {
|
||||||
|
|
@ -290,6 +373,8 @@ pub fn rain_coefficients(frequency: f64, polarisation: f64, elevation: f64) -> O
|
||||||
// of the elevation angle and the cosine of twice the polarisation tilt.
|
// of the elevation angle and the cosine of twice the polarisation tilt.
|
||||||
// The elevation term vanishes at the zenith, where the distinction
|
// The elevation term vanishes at the zenith, where the distinction
|
||||||
// between horizontal and vertical polarisation disappears.
|
// between horizontal and vertical polarisation disappears.
|
||||||
|
// 仰角与极化通过仰角余弦的平方以及二倍极化倾角的余弦进入。仰角项在
|
||||||
|
// 天顶处消失,那里水平与垂直极化之别不复存在。
|
||||||
let geometry_factor = elevation.cos().powi(2) * (2.0 * polarisation).cos();
|
let geometry_factor = elevation.cos().powi(2) * (2.0 * polarisation).cos();
|
||||||
let k = 0.5 * (k_horizontal + k_vertical + (k_horizontal - k_vertical) * geometry_factor);
|
let k = 0.5 * (k_horizontal + k_vertical + (k_horizontal - k_vertical) * geometry_factor);
|
||||||
let alpha = (k_horizontal * alpha_horizontal
|
let alpha = (k_horizontal * alpha_horizontal
|
||||||
|
|
@ -305,6 +390,12 @@ pub fn rain_coefficients(frequency: f64, polarisation: f64, elevation: f64) -> O
|
||||||
///
|
///
|
||||||
/// Returns `None` when the rain rate is negative, or when the coefficients
|
/// Returns `None` when the rain rate is negative, or when the coefficients
|
||||||
/// are not available.
|
/// are not available.
|
||||||
|
///
|
||||||
|
/// 返回雨中的比衰减,单位为分贝每千米。
|
||||||
|
///
|
||||||
|
/// 降雨率以毫米每小时计。
|
||||||
|
///
|
||||||
|
/// 降雨率为负,或系数不可用时返回 `None`。
|
||||||
pub fn specific_rain_attenuation(
|
pub fn specific_rain_attenuation(
|
||||||
rain_rate: f64,
|
rain_rate: f64,
|
||||||
frequency: f64,
|
frequency: f64,
|
||||||
|
|
@ -338,6 +429,22 @@ pub fn specific_rain_attenuation(
|
||||||
/// below the horizon.
|
/// below the horizon.
|
||||||
///
|
///
|
||||||
/// Source: ITU-R Recommendation P.618-13, equations 1 through 10.
|
/// Source: ITU-R Recommendation P.618-13, equations 1 through 10.
|
||||||
|
///
|
||||||
|
/// 返回沿斜路径的总降雨衰减。
|
||||||
|
///
|
||||||
|
/// 降雨率是在所关注时间百分比上被超过的值,以毫米每小时计。站的海拔
|
||||||
|
/// 高度与雨层高度以千米计;没有本地值时,后者传
|
||||||
|
/// [`DEFAULT_RAIN_HEIGHT_KM`]。
|
||||||
|
///
|
||||||
|
/// 方法即建议书 P.618 所述。斜路径长度由雨顶高度、站高与仰角得出,
|
||||||
|
/// 并作地球曲率修正。随后两个缩减因子计入降雨的不均匀性:一个水平
|
||||||
|
/// 因子,取决于比衰减、频率以及路径的水平投影;一个垂直因子,通过
|
||||||
|
/// 路径穿越雨层的角度取决于纬度。
|
||||||
|
///
|
||||||
|
/// 降雨率、频率或仰角不可用,站高于雨层,或仰角在地平及其以下时返回
|
||||||
|
/// `None`。
|
||||||
|
///
|
||||||
|
/// 出处:ITU-R 建议书 P.618-13,式 1 至式 10。
|
||||||
pub fn rain_attenuation(
|
pub fn rain_attenuation(
|
||||||
rain_rate: f64,
|
rain_rate: f64,
|
||||||
frequency: f64,
|
frequency: f64,
|
||||||
|
|
@ -362,9 +469,11 @@ pub fn rain_attenuation(
|
||||||
let specific = specific_rain_attenuation(rain_rate, frequency, polarisation, elevation)?;
|
let specific = specific_rain_attenuation(rain_rate, frequency, polarisation, elevation)?;
|
||||||
|
|
||||||
// Equation 2: the slant path length, with the Earth curvature term.
|
// Equation 2: the slant path length, with the Earth curvature term.
|
||||||
|
// 式 2:斜路径长度,含地球曲率项。
|
||||||
let height_difference = rain_height_km - station_height_km;
|
let height_difference = rain_height_km - station_height_km;
|
||||||
if height_difference <= 0.0 {
|
if height_difference <= 0.0 {
|
||||||
// The station is at or above the rain layer, so the path is empty.
|
// The station is at or above the rain layer, so the path is empty.
|
||||||
|
// 站在雨层处或其上,故路径为空。
|
||||||
return Some(RainAttenuation {
|
return Some(RainAttenuation {
|
||||||
specific_db_per_km: specific,
|
specific_db_per_km: specific,
|
||||||
path_length_km: 0.0,
|
path_length_km: 0.0,
|
||||||
|
|
@ -378,18 +487,22 @@ pub fn rain_attenuation(
|
||||||
/ ((sine * sine + 2.0 * height_difference / EFFECTIVE_EARTH_RADIUS_KM).sqrt() + sine);
|
/ ((sine * sine + 2.0 * height_difference / EFFECTIVE_EARTH_RADIUS_KM).sqrt() + sine);
|
||||||
|
|
||||||
// Equation 3: the horizontal projection of the slant path.
|
// Equation 3: the horizontal projection of the slant path.
|
||||||
|
// 式 3:斜路径的水平投影。
|
||||||
let horizontal_length = (slant_length * elevation.cos()).abs();
|
let horizontal_length = (slant_length * elevation.cos()).abs();
|
||||||
|
|
||||||
// Equation 6: the horizontal reduction factor.
|
// Equation 6: the horizontal reduction factor.
|
||||||
|
// 式 6:水平缩减因子。
|
||||||
let frequency_ghz = frequency / 1.0e9;
|
let frequency_ghz = frequency / 1.0e9;
|
||||||
let horizontal_reduction = 1.0
|
let horizontal_reduction = 1.0
|
||||||
/ (1.0 + 0.78 * (horizontal_length * specific / frequency_ghz).sqrt()
|
/ (1.0 + 0.78 * (horizontal_length * specific / frequency_ghz).sqrt()
|
||||||
- 0.38 * (1.0 - (-2.0 * horizontal_length).exp()));
|
- 0.38 * (1.0 - (-2.0 * horizontal_length).exp()));
|
||||||
|
|
||||||
// Equation 7: the angle at which the path crosses the rain layer.
|
// Equation 7: the angle at which the path crosses the rain layer.
|
||||||
|
// 式 7:路径穿越雨层的角度。
|
||||||
let eta = (height_difference / (horizontal_length * horizontal_reduction)).atan();
|
let eta = (height_difference / (horizontal_length * horizontal_reduction)).atan();
|
||||||
|
|
||||||
// Equation 8: the longer of the two path estimates.
|
// Equation 8: the longer of the two path estimates.
|
||||||
|
// 式 8:两个路径估计中较长者。
|
||||||
let path_length = if eta > elevation {
|
let path_length = if eta > elevation {
|
||||||
horizontal_length * horizontal_reduction / elevation.cos()
|
horizontal_length * horizontal_reduction / elevation.cos()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -397,10 +510,13 @@ pub fn rain_attenuation(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Equation 9: the vertical adjustment factor.
|
// Equation 9: the vertical adjustment factor.
|
||||||
|
// 式 9:垂直调整因子。
|
||||||
//
|
//
|
||||||
// The exponential takes the elevation in degrees, not radians, because
|
// The exponential takes the elevation in degrees, not radians, because
|
||||||
// the coefficients of 31 and 0.45 were fitted with degrees. The sine
|
// the coefficients of 31 and 0.45 were fitted with degrees. The sine
|
||||||
// takes the elevation in radians, as usual.
|
// takes the elevation in radians, as usual.
|
||||||
|
// 指数以度而非弧度接收仰角,因为 31 与 0.45 两个系数是以度拟合的。
|
||||||
|
// 正弦照常以弧度接收仰角。
|
||||||
let latitude_magnitude = latitude.abs();
|
let latitude_magnitude = latitude.abs();
|
||||||
let xi = if latitude_magnitude < 36.0 {
|
let xi = if latitude_magnitude < 36.0 {
|
||||||
36.0 - latitude_magnitude
|
36.0 - latitude_magnitude
|
||||||
|
|
@ -418,6 +534,7 @@ pub fn rain_attenuation(
|
||||||
- 0.45));
|
- 0.45));
|
||||||
|
|
||||||
// Equation 10: the effective path length and the attenuation.
|
// Equation 10: the effective path length and the attenuation.
|
||||||
|
// 式 10:有效路径长度与衰减。
|
||||||
let effective_length = path_length * vertical_adjustment;
|
let effective_length = path_length * vertical_adjustment;
|
||||||
Some(RainAttenuation {
|
Some(RainAttenuation {
|
||||||
specific_db_per_km: specific,
|
specific_db_per_km: specific,
|
||||||
|
|
@ -432,6 +549,10 @@ pub fn rain_attenuation(
|
||||||
/// horizontal.
|
/// horizontal.
|
||||||
///
|
///
|
||||||
/// This is a convenience for the two cases that are quoted by name.
|
/// This is a convenience for the two cases that are quoted by name.
|
||||||
|
///
|
||||||
|
/// 返回以相对水平倾角描述的极化所对应的弧度角。
|
||||||
|
///
|
||||||
|
/// 这是为两种常被具名引用的情形提供的便利。
|
||||||
pub const fn polarisation_tilt(degrees_from_horizontal: f64) -> f64 {
|
pub const fn polarisation_tilt(degrees_from_horizontal: f64) -> f64 {
|
||||||
degrees_from_horizontal * core::f64::consts::PI / 180.0
|
degrees_from_horizontal * core::f64::consts::PI / 180.0
|
||||||
}
|
}
|
||||||
|
|
@ -451,6 +572,19 @@ pub const fn polarisation_tilt(degrees_from_horizontal: f64) -> f64 {
|
||||||
///
|
///
|
||||||
/// Source: the rain height is from ITU-R Recommendation P.839-4 and the path
|
/// Source: the rain height is from ITU-R Recommendation P.839-4 and the path
|
||||||
/// method from ITU-R Recommendation P.618-13.
|
/// method from ITU-R Recommendation P.618-13.
|
||||||
|
///
|
||||||
|
/// 返回沿斜路径的总降雨衰减,雨顶高度取自建议书 P.839 模型。
|
||||||
|
///
|
||||||
|
/// 这与 [`rain_attenuation`] 是同一计算,只是雨层高度由给定纬经度处列表
|
||||||
|
/// 给出的零度等温线高度查得,而非由调用方提供。除非有本地实测的等温线
|
||||||
|
/// 高度,否则宜用此形式。
|
||||||
|
///
|
||||||
|
/// 站高必须给出;海拔为零的站传零。
|
||||||
|
///
|
||||||
|
/// 坐标不可用,或其他任何参数被 [`rain_attenuation`] 拒绝时返回 `None`。
|
||||||
|
///
|
||||||
|
/// 出处:雨顶高度来自 ITU-R 建议书 P.839-4,路径方法来自 ITU-R 建议书
|
||||||
|
/// P.618-13。
|
||||||
pub fn rain_attenuation_at(
|
pub fn rain_attenuation_at(
|
||||||
rain_rate: f64,
|
rain_rate: f64,
|
||||||
frequency: f64,
|
frequency: f64,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue