starfall/astronomy/moon/
mod.rs

1use crate::astronomy::host_star::HostStar;
2use crate::astronomy::planet::Planet;
3
4pub mod constants;
5pub mod constraints;
6pub mod error;
7use error::Error;
8pub mod math;
9use math::tides::{
10  get_lunar_tide, get_neap_tide, get_planetary_tide, get_solar_tide, get_spring_tide, is_moon_tidally_locked,
11  is_planet_tidally_locked,
12};
13pub mod rotation_direction;
14use rotation_direction::RotationDirection;
15
16/// A `Moon`, mercifully, is a fairly simple concept.
17///
18/// It's possible that at some point, we might make moons habitable.
19///
20/// For instance, a habitable moon of a hot jupiter gas giant.
21///
22/// But for now, we're just staying with terrestrial planets, and we'll assume
23/// that moons are just celestial features.
24#[derive(Clone, Debug, PartialEq)]
25pub struct Moon {
26  /// The mass of this moon, in Mmoon.
27  pub mass: f64,
28  /// The density of this moon, in Dmoon.
29  pub density: f64,
30  /// The radius of this moon, in Rmoon.
31  pub radius: f64,
32  /// The gravity of this moon, in Gearth (not Gmoon).
33  pub gravity: f64,
34  /// The escape velocity of this moon, in KM/sec.
35  pub escape_velocity: f64,
36  /// The Bond albedo of this moon.
37  pub bond_albedo: f64,
38  /// Semi-major axis, in KM.
39  pub semi_major_axis: f64,
40  /// Orbital eccentricity.
41  pub orbital_eccentricity: f64,
42  /// Periapsis.
43  pub periapsis: f64,
44  /// Apoapsis.
45  pub apoapsis: f64,
46  /// Orbital inclination.
47  pub orbital_inclination: f64,
48  /// Rotation direction.
49  pub rotation_direction: RotationDirection,
50  /// Sidereal orbital period.
51  pub sidereal_orbital_period: f64,
52  /// Normal orbital period.
53  pub orbital_period: f64,
54  /// Rotational period.
55  pub rotation_period: f64,
56  /// Lunar tide.
57  pub lunar_tide: f64,
58  /// Solar tide.
59  pub solar_tide: f64,
60  /// Planetary tide.
61  pub planetary_tide: f64,
62  /// Spring tides.
63  pub spring_tide_magnitude: f64,
64  /// Neap tide magnitude.
65  pub neap_tide_magnitude: f64,
66  /// If the planet is tidally locked to this moon.
67  pub is_planet_tidally_locked: bool,
68  /// If the moon is tidally locked to the planet.
69  pub is_moon_tidally_locked: bool,
70}
71
72impl Moon {
73  #[named]
74  pub fn from_environment(
75    mass: f64,
76    host_star: &HostStar,
77    star_distance: f64,
78    planet: &Planet,
79    planet_distance: f64,
80  ) -> Result<Moon, Error> {
81    trace_enter!();
82    trace_var!(host_star);
83    trace_var!(star_distance);
84    trace_var!(planet);
85    trace_var!(planet_distance);
86    let density = 3.34;
87    trace_var!(density);
88    let radius = (mass / (density / 3.34)).powf(1.0 / 3.0);
89    trace_var!(radius);
90    // This gives gravity in Earth equivalents, since other units are relative
91    // to the Moon, and Gmoon is 0.1654 * Gearth.
92    let gravity = (mass / radius.powf(2.0)) * 0.1654;
93    trace_var!(gravity);
94    // This is in KM/sec.
95    let escape_velocity = (mass / radius).sqrt() * 2.380;
96    trace_var!(escape_velocity);
97    // Peg this to the albedo of the Moon for the time being.
98    let bond_albedo = 0.136;
99    trace_var!(bond_albedo);
100    let semi_major_axis = planet_distance;
101    trace_var!(semi_major_axis);
102    // Pegged for the time being.
103    let orbital_eccentricity = 0.05;
104    trace_var!(orbital_eccentricity);
105    let periapsis = (1.0 - orbital_eccentricity) * semi_major_axis;
106    trace_var!(periapsis);
107    let apoapsis = (1.0 + orbital_eccentricity) * semi_major_axis;
108    trace_var!(apoapsis);
109    // Pegged.
110    let orbital_inclination = 5.15;
111    trace_var!(orbital_inclination);
112    let rotation_direction = RotationDirection::Prograde;
113    trace_var!(rotation_direction);
114    let sidereal_orbital_period =
115      0.0588 * ((semi_major_axis / 12_742.0 * 2.0).powf(3.0) / (planet.get_mass() + mass * 0.0123)).sqrt();
116    trace_var!(sidereal_orbital_period);
117    let earth_orbital_period = planet.get_orbital_period() * 365.265;
118    trace_var!(earth_orbital_period);
119    let orbital_period = earth_orbital_period / (earth_orbital_period / sidereal_orbital_period - 1.0);
120    trace_var!(orbital_period);
121    let lunar_tide = get_lunar_tide(mass, planet.get_radius(), semi_major_axis);
122    trace_var!(lunar_tide);
123    let solar_tide = get_solar_tide(host_star.get_stellar_mass(), planet.get_radius(), star_distance);
124    trace_var!(solar_tide);
125    let planetary_tide = get_planetary_tide(mass, radius, semi_major_axis);
126    trace_var!(planetary_tide);
127    let spring_tide_magnitude = get_spring_tide(lunar_tide, solar_tide);
128    trace_var!(spring_tide_magnitude);
129    let neap_tide_magnitude = get_neap_tide(lunar_tide, solar_tide);
130    trace_var!(neap_tide_magnitude);
131    let is_planet_tidally_locked =
132      is_planet_tidally_locked(lunar_tide, solar_tide, host_star.get_current_age(), planet.get_mass());
133    trace_var!(is_planet_tidally_locked);
134    let is_moon_tidally_locked = is_moon_tidally_locked(solar_tide, planetary_tide, host_star.get_current_age(), mass);
135    trace_var!(is_moon_tidally_locked);
136    let rotation_period = if is_moon_tidally_locked { orbital_period } else { 3.0 };
137    trace_var!(rotation_period);
138    let result = Moon {
139      mass,
140      density,
141      radius,
142      gravity,
143      escape_velocity,
144      bond_albedo,
145      semi_major_axis,
146      orbital_eccentricity,
147      periapsis,
148      apoapsis,
149      orbital_inclination,
150      rotation_direction,
151      sidereal_orbital_period,
152      orbital_period,
153      rotation_period,
154      lunar_tide,
155      solar_tide,
156      planetary_tide,
157      spring_tide_magnitude,
158      neap_tide_magnitude,
159      is_planet_tidally_locked,
160      is_moon_tidally_locked,
161    };
162    trace_var!(result);
163    trace_exit!();
164    Ok(result)
165  }
166}