#[inline]
pub fn get_relative_airmass(zenith: f64) -> f64 {
let z = zenith;
let cos_z = z.to_radians().cos();
let c = 96.07995 - z;
if c <= 0.0 {
return f64::NAN; }
let term = 0.50572 * c.powf(-1.6364);
let am_rel = 1.0 / (cos_z + term);
if !(0.0..=100.0).contains(&am_rel) {
f64::NAN
} else {
am_rel
}
}
#[inline]
pub fn alt2pres(altitude: f64) -> f64 {
101325.0 * (1.0 - 2.25577e-5 * altitude).powf(5.25588)
}
#[inline]
pub fn get_absolute_airmass(airmass_relative: f64, pressure: f64) -> f64 {
airmass_relative * pressure / 101325.0
}
#[inline]
pub fn pres2alt(pressure: f64) -> f64 {
44331.5 - 4946.62 * pressure.powf(0.190263)
}
#[inline]
pub fn gueymard94_pw(temp_air: f64, relative_humidity: f64) -> f64 {
let t = temp_air + 273.15; let rh = relative_humidity;
let theta = t / 273.15;
let hv = 0.4976 + 1.5265 * theta
+ (13.6897 * theta - 14.9188 * theta.powi(3)).exp();
let es = (22.330 - 49.140 * (100.0 / t) - 10.922 * (100.0 / t).powi(2)
- 0.39015 * t / 100.0)
.exp();
let rho_v = 216.7 * rh / (100.0 * t) * es;
let pw = 0.1 * hv * rho_v;
pw.max(0.1)
}
#[inline]
pub fn tdew_from_rh(temperature: f64, rh: f64) -> f64 {
const B: f64 = 17.62;
const C: f64 = 243.12;
let ln_term = (B * temperature) / (C + temperature) + (rh / 100.0).ln();
C * ln_term / (B - ln_term)
}
#[inline]
pub fn rh_from_tdew(temperature: f64, temp_dew: f64) -> f64 {
const B: f64 = 17.62;
const C: f64 = 243.12;
let es = (B * temp_dew) / (C + temp_dew);
let e = (B * temperature) / (C + temperature);
100.0 * (es - e).exp()
}
#[inline]
pub fn bird_hulstrom80_aod_bb(aod380: f64, aod500: f64) -> f64 {
0.27583 * aod380 + 0.35 * aod500
}
#[inline]
pub fn kasten96_lt(airmass: f64, precipitable_water: f64, aod_bb: f64) -> f64 {
let delta_cda = -0.101 + 0.235 * airmass.powf(-0.16);
let delta_w = 0.112 * airmass.powf(-0.55) * precipitable_water.powf(0.34);
let delta_a = aod_bb;
-(9.4 + 0.9 * airmass)
* (-airmass * (delta_cda + delta_w + delta_a)).exp().ln()
/ airmass
}
#[inline]
pub fn angstrom_aod_at_lambda(aod0: f64, lambda0: f64, alpha: f64, lambda1: f64) -> f64 {
aod0 * (lambda1 / lambda0).powf(-alpha)
}
#[inline]
pub fn angstrom_alpha(aod1: f64, lambda1: f64, aod2: f64, lambda2: f64) -> f64 {
-(aod1 / aod2).ln() / (lambda1 / lambda2).ln()
}
#[inline]
pub fn windspeed_powerlaw(wind_speed: f64, height_ref: f64, height_desired: f64, alpha: f64) -> f64 {
if wind_speed < 0.0 || height_ref <= 0.0 || height_desired <= 0.0 {
return f64::NAN;
}
wind_speed * (height_desired / height_ref).powf(alpha)
}
#[inline]
pub fn get_refraction(true_elevation: f64) -> f64 {
let e = true_elevation;
if e >= 85.0 {
0.0
} else if e > -0.575 {
let r = 1.02 / (e + 10.3 / (e + 5.11)).to_radians().tan();
r / 60.0 } else {
34.5 / 60.0
}
}