use sciforge::hub::domain::meteorology::radiation::{solar_constant, stefan_boltzmann_flux};
use sciforge::hub::prelude::constants::R_GAS;
pub const ONEBARPRESSURE: f64 = crate::ONEBARPRESSURE;
pub const ONEBARTEMPK: f64 = crate::ONEBARTEMPK;
pub fn atmospheremolarmass() -> f64 {
crate::matmosphere()
}
pub const LAPSERATETROPOSPHERE: f64 = 0.002;
pub struct AtmosphericLayer {
pub name: &'static str,
pub basealtitudem: f64,
pub topaltitudem: f64,
pub basetemperaturek: f64,
pub lapseratekperm: f64,
}
impl AtmosphericLayer {
pub fn temperatureat(&self, altitudem: f64) -> f64 {
let h = (altitudem - self.basealtitudem)
.max(0.0)
.min(self.topaltitudem - self.basealtitudem);
self.basetemperaturek - self.lapseratekperm * h
}
pub fn pressureat(&self, altitudem: f64) -> f64 {
let t = self.temperatureat(altitudem);
let h = altitudem - self.basealtitudem;
let g0 = *crate::SURFACEGRAVITY;
if self.lapseratekperm.abs() < 1e-10 {
let pbase = barometricpressure(self.basealtitudem);
pbase * (-g0 * atmospheremolarmass() * h / (R_GAS * self.basetemperaturek)).exp()
} else {
let pbase = barometricpressure(self.basealtitudem);
pbase
* (t / self.basetemperaturek)
.powf(g0 * atmospheremolarmass() / (R_GAS * self.lapseratekperm))
}
}
pub fn densityat(&self, altitudem: f64) -> f64 {
let p = self.pressureat(altitudem);
let t = self.temperatureat(altitudem);
p * atmospheremolarmass() / (R_GAS * t)
}
}
pub fn troposphere() -> AtmosphericLayer {
AtmosphericLayer {
name: "Troposphere",
basealtitudem: 0.0,
topaltitudem: 50000.0,
basetemperaturek: 165.0,
lapseratekperm: 0.002,
}
}
pub fn stratosphere() -> AtmosphericLayer {
AtmosphericLayer {
name: "Stratosphere",
basealtitudem: 50000.0,
topaltitudem: 320000.0,
basetemperaturek: 110.0,
lapseratekperm: -0.0003,
}
}
pub fn thermosphere() -> AtmosphericLayer {
AtmosphericLayer {
name: "Thermosphere",
basealtitudem: 320000.0,
topaltitudem: 1000000.0,
basetemperaturek: 190.0,
lapseratekperm: -0.0008,
}
}
pub fn barometricpressure(altitudem: f64) -> f64 {
let g0 = *crate::SURFACEGRAVITY;
if altitudem <= 50000.0 {
let t = ONEBARTEMPK - LAPSERATETROPOSPHERE * altitudem;
ONEBARPRESSURE
* (t / ONEBARTEMPK).powf(g0 * atmospheremolarmass() / (R_GAS * LAPSERATETROPOSPHERE))
} else {
let ptropo = barometricpressure(50000.0);
let ttropo = 110.0;
ptropo * (-g0 * atmospheremolarmass() * (altitudem - 50000.0) / (R_GAS * ttropo)).exp()
}
}
pub fn scaleheight() -> f64 {
*crate::SCALEHEIGHT
}
pub fn meansolarirradiance() -> f64 {
solar_constant() / (5.2044 * 5.2044)
}
pub fn effectivetemp() -> f64 {
let flux = meansolarirradiance() * (1.0 - crate::BONDALBEDO) / 4.0 + crate::INTERNALHEATINGWM2;
(flux / sciforge::hub::prelude::constants::SIGMA_SB).powf(0.25)
}
pub fn olr() -> f64 {
stefan_boltzmann_flux(crate::ONEBARTEMPK)
}