pub struct CloudLayer {
pub name: &'static str,
pub base_altitude_m: f64,
pub top_altitude_m: f64,
pub optical_depth: f64,
pub composition: &'static str,
pub particle_radius_um: f64,
pub single_scatter_albedo: f64,
}
pub struct CloudSystemEndpoint {
pub layers: Vec<CloudLayer>,
pub total_optical_depth: f64,
}
impl CloudSystemEndpoint {
pub fn venus_default() -> Self {
let layers = vec![
CloudLayer {
name: "lower_cloud",
base_altitude_m: 47_500.0,
top_altitude_m: 50_000.0,
optical_depth: 6.0,
composition: "H2SO4 (75-85 wt%)",
particle_radius_um: 3.5,
single_scatter_albedo: 0.999,
},
CloudLayer {
name: "middle_cloud",
base_altitude_m: 50_000.0,
top_altitude_m: 57_000.0,
optical_depth: 10.0,
composition: "H2SO4 + S8 particles",
particle_radius_um: 2.5,
single_scatter_albedo: 0.998,
},
CloudLayer {
name: "upper_cloud",
base_altitude_m: 57_000.0,
top_altitude_m: 70_000.0,
optical_depth: 9.0,
composition: "H2SO4 fine mist",
particle_radius_um: 1.0,
single_scatter_albedo: 0.997,
},
];
let total = layers.iter().map(|l| l.optical_depth).sum();
Self {
layers,
total_optical_depth: total,
}
}
pub fn cloud_top_altitude_m(&self) -> f64 {
self.layers
.iter()
.map(|l| l.top_altitude_m)
.fold(0.0_f64, f64::max)
}
pub fn cloud_base_altitude_m(&self) -> f64 {
self.layers
.iter()
.map(|l| l.base_altitude_m)
.fold(f64::MAX, f64::min)
}
pub fn transmission(&self) -> f64 {
(-self.total_optical_depth).exp()
}
pub fn layer_at_altitude(&self, altitude_m: f64) -> Option<&CloudLayer> {
self.layers
.iter()
.find(|l| altitude_m >= l.base_altitude_m && altitude_m <= l.top_altitude_m)
}
}
pub fn cloud_top_altitude_m() -> f64 {
65_000.0
}
pub fn cloud_base_altitude_m() -> f64 {
45_000.0
}