use super::orbit::{MERCURY_MASS, MERCURY_RADIUS};
use sciforge::hub::domain::common::constants::DEGREE_TO_RAD;
pub struct MercuryRotation {
pub angular_velocity_rad_s: f64,
pub axial_tilt_rad: f64,
}
impl Default for MercuryRotation {
fn default() -> Self {
Self::new()
}
}
impl MercuryRotation {
pub fn new() -> Self {
Self {
angular_velocity_rad_s: crate::ANGULAR_VELOCITY,
axial_tilt_rad: crate::AXIAL_TILT_RAD,
}
}
pub fn surface_velocity_at_latitude(&self, latitude_deg: f64) -> f64 {
let lat_rad = latitude_deg.to_radians();
self.angular_velocity_rad_s * MERCURY_RADIUS * lat_rad.cos()
}
pub fn centripetal_acceleration_at_latitude(&self, latitude_deg: f64) -> f64 {
let lat_rad = latitude_deg.to_radians();
let omega = self.angular_velocity_rad_s;
omega * omega * MERCURY_RADIUS * lat_rad.cos()
}
pub fn coriolis_parameter(&self, latitude_deg: f64) -> f64 {
let lat_rad = latitude_deg.to_radians();
2.0 * self.angular_velocity_rad_s * lat_rad.sin()
}
pub fn moment_of_inertia(&self) -> f64 {
crate::MOI_FACTOR * MERCURY_MASS * MERCURY_RADIUS * MERCURY_RADIUS
}
pub fn rotational_kinetic_energy(&self) -> f64 {
0.5 * self.moment_of_inertia() * self.angular_velocity_rad_s.powi(2)
}
pub fn angular_momentum(&self) -> f64 {
self.moment_of_inertia() * self.angular_velocity_rad_s
}
pub fn spin_orbit_ratio() -> (u32, u32) {
(3, 2)
}
pub fn libration_amplitude_arcsec() -> f64 {
crate::LIBRATION_AMPLITUDE_ARCSEC
}
pub fn libration_amplitude_rad() -> f64 {
crate::LIBRATION_AMPLITUDE_ARCSEC / 3600.0 * DEGREE_TO_RAD
}
pub fn libration_angle_rad(&self, mean_anomaly_rad: f64) -> f64 {
Self::libration_amplitude_rad() * mean_anomaly_rad.sin()
}
pub fn subsolar_longitude_deg(&self, true_anomaly_rad: f64, elapsed_s: f64) -> f64 {
let rotation_angle = self.angular_velocity_rad_s * elapsed_s;
let mut lon = (rotation_angle - true_anomaly_rad).to_degrees() % 360.0;
if lon < 0.0 {
lon += 360.0;
}
lon
}
pub fn solar_day_s() -> f64 {
crate::SOLAR_DAY_S
}
pub fn sidereal_day_s() -> f64 {
crate::SIDEREAL_DAY_S
}
pub fn day_length_hours(&self, latitude_deg: f64) -> f64 {
let lat_rad = latitude_deg.to_radians();
let declination = self.axial_tilt_rad;
let cos_h = -(lat_rad.tan() * declination.tan());
if cos_h > 1.0 {
return 0.0;
}
if cos_h < -1.0 {
return 24.0;
}
2.0 * cos_h.acos() / std::f64::consts::PI * (crate::SOLAR_DAY_S / 3600.0 / 2.0)
}
}