use crate::config::parameters::*;
pub struct SatelliteInterior {
pub mass: f64,
pub radius: f64,
pub ice_fraction: f64,
pub rock_fraction: f64,
pub core_density: f64,
pub mantle_density: f64,
}
impl SatelliteInterior {
pub fn new(mass: f64, radius: f64, ice_fraction: f64, rock_fraction: f64) -> Self {
let metal_fraction = (1.0 - ice_fraction - rock_fraction).max(0.0);
let core_density = IRON_DENSITY * metal_fraction + ROCK_DENSITY * (1.0 - metal_fraction);
let mantle_density = if ice_fraction > 0.01 {
ice_fraction * WATER_ICE_DENSITY + (1.0 - ice_fraction) * ROCK_DENSITY
} else {
ROCK_DENSITY
};
Self {
mass,
radius,
ice_fraction,
rock_fraction,
core_density,
mantle_density,
}
}
pub fn mean_density(&self) -> f64 {
mean_density(self.mass, self.radius)
}
pub fn core_radius(&self) -> f64 {
let metal_fraction = (1.0 - self.ice_fraction - self.rock_fraction).max(0.0);
self.radius * metal_fraction.cbrt()
}
pub fn mantle_thickness(&self) -> f64 {
self.radius - self.core_radius()
}
pub fn central_pressure(&self) -> f64 {
let rho = self.mean_density();
2.0 * std::f64::consts::PI / 3.0 * G * rho * rho * self.radius * self.radius
}
pub fn moment_of_inertia_factor(&self) -> f64 {
let r_c = self.core_radius();
let r = self.radius;
if r < 1e-3 {
return 0.4;
}
let x = r_c / r;
let rho_c = self.core_density;
let rho_m = self.mantle_density;
let top = rho_c * x.powi(5) + rho_m * (1.0 - x.powi(5));
let bot = rho_c * x.powi(3) + rho_m * (1.0 - x.powi(3));
0.4 * top / bot
}
pub fn gravitational_binding_energy(&self) -> f64 {
3.0 * G * self.mass * self.mass / (5.0 * self.radius)
}
pub fn ocean_depth_estimate(&self) -> f64 {
if self.ice_fraction < 0.01 {
return 0.0;
}
let ice_shell = 0.1 * self.radius * self.ice_fraction;
let ocean = self.radius * self.ice_fraction * 0.3;
if ocean > ice_shell { ocean } else { 0.0 }
}
}
pub fn differentiation_energy(mass: f64, radius: f64, core_fraction: f64) -> f64 {
let e_bind = 3.0 * G * mass * mass / (5.0 * radius);
e_bind * 0.1 * core_fraction
}
pub fn ice_melting_depth(surface_temp: f64, tidal_flux: f64) -> f64 {
if tidal_flux < 1e-10 {
return f64::INFINITY;
}
let k_ice = 2.2;
let t_melt = 273.0;
if surface_temp >= t_melt {
return 0.0;
}
k_ice * (t_melt - surface_temp) / tidal_flux
}
pub fn convective_vigor(tidal_flux: f64, viscosity: f64, alpha: f64, depth: f64) -> f64 {
let g_local = 1.0;
let rho = WATER_ICE_DENSITY;
let kappa = 1e-6;
let delta_t = tidal_flux * depth / 2.2;
rho * g_local * alpha * delta_t * depth.powi(3) / (viscosity * kappa)
}