rf: derive the rain height from P.839 in the path method
This commit is contained in:
parent
b298a00651
commit
a0730cfb33
|
|
@ -65,7 +65,7 @@ pub use geometry::{air_mass, elevation_from_zenith, zenith_to_elevation};
|
|||
pub use p839::{RAIN_HEIGHT_OFFSET_KM, grid_step_degrees, rain_height, zero_isotherm_height};
|
||||
pub use rain::{
|
||||
DEFAULT_RAIN_HEIGHT_KM, RainAttenuation, polarisation_tilt, rain_attenuation,
|
||||
rain_coefficients, specific_rain_attenuation,
|
||||
rain_attenuation_at, rain_coefficients, specific_rain_attenuation,
|
||||
};
|
||||
|
||||
pub use apsis_rf::Decibel;
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ use apsis_rf::Decibel;
|
|||
/// which makes the Earth appear larger than it is.
|
||||
const EFFECTIVE_EARTH_RADIUS_KM: f64 = 8_500.0;
|
||||
|
||||
/// The default height of the rain layer above sea level, in kilometers.
|
||||
/// A mid latitude rain height, in kilometers above sea level.
|
||||
///
|
||||
/// Recommendation P.618 takes this from the zero degree isotherm height,
|
||||
/// which depends on latitude and season and is tabulated separately. This
|
||||
/// value is representative of mid latitudes; a caller working in the tropics
|
||||
/// should raise it and one in polar regions should lower it.
|
||||
/// Recommendation P.618 takes the rain height from the zero degree isotherm
|
||||
/// height of Recommendation P.839, which is tabulated as a function of
|
||||
/// latitude and longitude. Prefer [`rain_attenuation_at`], which looks the
|
||||
/// value up, over [`rain_attenuation`] with this constant.
|
||||
pub const DEFAULT_RAIN_HEIGHT_KM: f64 = 3.0;
|
||||
|
||||
/// One term of a P.838-3 curve fit.
|
||||
|
|
@ -435,3 +435,39 @@ pub fn rain_attenuation(
|
|||
pub const fn polarisation_tilt(degrees_from_horizontal: f64) -> f64 {
|
||||
degrees_from_horizontal * core::f64::consts::PI / 180.0
|
||||
}
|
||||
|
||||
/// Returns the total rain attenuation along a slant path, taking the rain
|
||||
/// height from the Recommendation P.839 model.
|
||||
///
|
||||
/// This is the same calculation as [`rain_attenuation`], with the rain layer
|
||||
/// height looked up from the tabulated zero degree isotherm height at the
|
||||
/// given latitude and longitude rather than supplied by the caller. It is
|
||||
/// the form to use unless a locally measured isotherm height is available.
|
||||
///
|
||||
/// The station height must be given; pass zero for a station at sea level.
|
||||
///
|
||||
/// Returns `None` when the coordinates are not usable, or when any of the
|
||||
/// other arguments is rejected by [`rain_attenuation`].
|
||||
///
|
||||
/// Source: the rain height is from ITU-R Recommendation P.839-4 and the path
|
||||
/// method from ITU-R Recommendation P.618-13.
|
||||
pub fn rain_attenuation_at(
|
||||
rain_rate: f64,
|
||||
frequency: f64,
|
||||
polarisation: f64,
|
||||
elevation: f64,
|
||||
station_height_km: f64,
|
||||
latitude: f64,
|
||||
longitude: f64,
|
||||
) -> Option<RainAttenuation> {
|
||||
let rain_height_km = crate::p839::rain_height(latitude, longitude)?;
|
||||
rain_attenuation(
|
||||
rain_rate,
|
||||
frequency,
|
||||
polarisation,
|
||||
elevation,
|
||||
station_height_km,
|
||||
rain_height_km,
|
||||
latitude,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -393,3 +393,44 @@ fn polarisation_tilt_converts_degrees() {
|
|||
"forty five degrees",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_integrated_path_uses_the_p839_rain_height() {
|
||||
use apsis_atmosphere::{rain_attenuation_at, rain_height};
|
||||
let latitude = 45.0;
|
||||
let longitude = 0.0;
|
||||
let integrated = rain_attenuation_at(
|
||||
20.0,
|
||||
12.0e9,
|
||||
HORIZONTAL,
|
||||
THIRTY_DEGREES,
|
||||
0.0,
|
||||
latitude,
|
||||
longitude,
|
||||
)
|
||||
.expect("valid");
|
||||
let explicit = rain_attenuation(
|
||||
20.0,
|
||||
12.0e9,
|
||||
HORIZONTAL,
|
||||
THIRTY_DEGREES,
|
||||
0.0,
|
||||
rain_height(latitude, longitude).expect("valid coordinates"),
|
||||
latitude,
|
||||
)
|
||||
.expect("valid");
|
||||
assert!((integrated.attenuation_db - explicit.attenuation_db).abs() < 1e-12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_integrated_path_rejects_unusable_coordinates() {
|
||||
use apsis_atmosphere::rain_attenuation_at;
|
||||
assert_eq!(
|
||||
rain_attenuation_at(20.0, 12.0e9, HORIZONTAL, THIRTY_DEGREES, 0.0, 91.0, 0.0),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
rain_attenuation_at(20.0, 12.0e9, HORIZONTAL, THIRTY_DEGREES, 0.0, 0.0, f64::NAN),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue