1use crate::constants::{
2 ADRASTEA_MASS, ADRASTEA_RADIUS, AMALTHEA_MASS, AMALTHEA_RADIUS, ATLAS_MASS, ATLAS_RADIUS, AU,
3 CALLISTO_MASS, CALLISTO_RADIUS, DEGREE_TO_RAD, DEIMOS_MASS, DEIMOS_RADIUS, DIONE_MASS,
4 DIONE_RADIUS, EARTH_MOON_DISTANCE, ENCELADUS_MASS, ENCELADUS_RADIUS, EPIMETHEUS_MASS,
5 EPIMETHEUS_RADIUS, EUROPA_MASS, EUROPA_RADIUS, G, GANYMEDE_MASS, GANYMEDE_RADIUS,
6 HABITABLE_ZONE_INNER_FLUX, HABITABLE_ZONE_OUTER_FLUX, HIMALIA_MASS, HIMALIA_RADIUS,
7 HYPERION_MASS, HYPERION_RADIUS, IAPETUS_MASS, IAPETUS_RADIUS, IO_MASS, IO_RADIUS,
8 J2000_EPOCH_JD, JANUS_MASS, JANUS_RADIUS, JULIAN_CENTURY_DAYS, LIGHT_YEAR, LUNAR_MASS,
9 LUNAR_ORBITAL_PERIOD, LUNAR_RADIUS, METIS_MASS, METIS_RADIUS, MIMAS_MASS, MIMAS_RADIUS,
10 NUTATION_AMPLITUDE_ARCSEC, OBERON_MASS, OBERON_RADIUS, PAN_MASS, PAN_RADIUS, PANDORA_MASS,
11 PANDORA_RADIUS, PHOBOS_MASS, PHOBOS_RADIUS, PROMETHEUS_MASS, PROMETHEUS_RADIUS, RAD_TO_DEGREE,
12 RHEA_MASS, RHEA_RADIUS, SECONDS_PER_DAY, SIDEREAL_YEAR, TETHYS_MASS, TETHYS_RADIUS, THEBE_MASS,
13 THEBE_RADIUS, TIDAL_DISSIPATION_COEFF, TITAN_MASS, TITAN_RADIUS, TITANIA_MASS, TITANIA_RADIUS,
14 TRITON_MASS, TRITON_RADIUS, TROPICAL_YEAR, VERNAL_EQUINOX_DOY,
15};
16
17pub fn gravitational_force(m1: f64, m2: f64, r: f64) -> f64 {
18 G * m1 * m2 / (r * r)
19}
20
21pub fn tidal_force(m: f64, r: f64, delta_r: f64) -> f64 {
22 2.0 * G * m * delta_r / (r * r * r)
23}
24
25pub fn synodic_period(p1: f64, p2: f64) -> f64 {
26 (1.0 / p1 - 1.0 / p2).abs().recip()
27}
28
29pub fn apparent_angular_size(diameter: f64, distance: f64) -> f64 {
30 2.0 * (diameter / (2.0 * distance)).atan()
31}
32
33pub fn parallax_distance(parallax_arcsec: f64) -> f64 {
34 1.0 / parallax_arcsec
35}
36
37pub fn barycenter(m1: f64, m2: f64, d: f64) -> f64 {
38 d * m2 / (m1 + m2)
39}
40
41pub fn lagrange_l1(d: f64, m1: f64, m2: f64) -> f64 {
42 d * (m2 / (3.0 * m1)).powf(1.0 / 3.0)
43}
44
45pub fn hill_sphere(a: f64, m: f64, m_star: f64, e: f64) -> f64 {
46 a * (1.0 - e) * (m / (3.0 * m_star)).powf(1.0 / 3.0)
47}
48
49pub fn surface_gravity(m: f64, r: f64) -> f64 {
50 G * m / (r * r)
51}
52
53pub fn sidereal_to_solar(sidereal_period: f64, orbital_period: f64) -> f64 {
54 1.0 / (1.0 / sidereal_period - 1.0 / orbital_period)
55}
56
57pub fn habitable_zone_inner(luminosity_solar: f64) -> f64 {
58 (luminosity_solar / HABITABLE_ZONE_INNER_FLUX).sqrt()
59}
60
61pub fn habitable_zone_outer(luminosity_solar: f64) -> f64 {
62 (luminosity_solar / HABITABLE_ZONE_OUTER_FLUX).sqrt()
63}
64
65pub fn julian_date_to_j2000_century(jd: f64) -> f64 {
66 (jd - J2000_EPOCH_JD) / JULIAN_CENTURY_DAYS
67}
68
69pub fn j2000_century_to_julian_date(t: f64) -> f64 {
70 t * JULIAN_CENTURY_DAYS + J2000_EPOCH_JD
71}
72
73pub fn mean_obliquity_ecliptic(t_century: f64) -> f64 {
74 let epsilon_arcsec = 84381.448 - 46.8150 * t_century - 0.000_59 * t_century * t_century
75 + 0.001_813 * t_century.powi(3);
76 epsilon_arcsec / 3600.0 * DEGREE_TO_RAD
77}
78
79pub fn nutation_longitude(omega: f64) -> f64 {
80 -NUTATION_AMPLITUDE_ARCSEC * omega.sin() / 3600.0 * DEGREE_TO_RAD
81}
82
83pub fn precession_rate_arcsec_per_year(t_century: f64) -> f64 {
84 50.290_966 + 0.022_222 * t_century
85}
86
87pub fn equation_of_time(day_of_year: f64) -> f64 {
88 let b = 2.0 * std::f64::consts::PI * (day_of_year - VERNAL_EQUINOX_DOY) / 365.25;
89 -7.655 * b.sin() + 9.873 * (2.0 * b).sin() + 3.334 * (3.0 * b).sin()
90}
91
92pub fn sidereal_year_seconds() -> f64 {
93 SIDEREAL_YEAR
94}
95
96pub fn tropical_year_seconds() -> f64 {
97 TROPICAL_YEAR
98}
99
100pub fn precession_period() -> f64 {
101 360.0 * 3600.0 / 50.290_966 * TROPICAL_YEAR
102}
103
104pub fn day_length_seconds() -> f64 {
105 SECONDS_PER_DAY
106}
107
108pub fn solar_day_to_sidereal_day(solar_day_s: f64, orbital_period_s: f64) -> f64 {
109 1.0 / (1.0 / solar_day_s + 1.0 / orbital_period_s)
110}
111
112pub fn degrees_to_radians(deg: f64) -> f64 {
113 deg * DEGREE_TO_RAD
114}
115
116pub fn radians_to_degrees(rad: f64) -> f64 {
117 rad * RAD_TO_DEGREE
118}
119
120pub fn tidal_dissipation_factor() -> f64 {
121 TIDAL_DISSIPATION_COEFF
122}
123
124pub fn tidal_quality_factor(specific_dissipation: f64) -> f64 {
125 1.0 / (2.0 * specific_dissipation * TIDAL_DISSIPATION_COEFF)
126}
127
128pub fn tidal_heating(mass_primary: f64, radius: f64, eccentricity: f64, a: f64, n: f64) -> f64 {
129 TIDAL_DISSIPATION_COEFF
130 * G
131 * mass_primary
132 * mass_primary
133 * radius.powi(5)
134 * n
135 * eccentricity
136 * eccentricity
137 / a.powi(6)
138}
139
140pub fn au_to_meters(au: f64) -> f64 {
141 au * AU
142}
143
144pub fn meters_to_au(m: f64) -> f64 {
145 m / AU
146}
147
148pub fn light_years_to_meters(ly: f64) -> f64 {
149 ly * LIGHT_YEAR
150}
151
152pub fn meters_to_light_years(m: f64) -> f64 {
153 m / LIGHT_YEAR
154}
155
156pub fn au_to_light_years(au: f64) -> f64 {
157 au * AU / LIGHT_YEAR
158}
159
160pub fn light_years_to_au(ly: f64) -> f64 {
161 ly * LIGHT_YEAR / AU
162}
163
164pub fn earth_moon_distance() -> f64 {
165 EARTH_MOON_DISTANCE
166}
167
168pub fn lunar_orbital_period() -> f64 {
169 LUNAR_ORBITAL_PERIOD
170}
171
172pub struct MoonData {
173 pub mass: f64,
174 pub radius: f64,
175}
176
177pub fn moon_data(name: &str) -> Option<MoonData> {
178 match name.to_ascii_lowercase().as_str() {
179 "moon" | "luna" => Some(MoonData {
180 mass: LUNAR_MASS,
181 radius: LUNAR_RADIUS,
182 }),
183 "io" => Some(MoonData {
184 mass: IO_MASS,
185 radius: IO_RADIUS,
186 }),
187 "europa" => Some(MoonData {
188 mass: EUROPA_MASS,
189 radius: EUROPA_RADIUS,
190 }),
191 "ganymede" => Some(MoonData {
192 mass: GANYMEDE_MASS,
193 radius: GANYMEDE_RADIUS,
194 }),
195 "callisto" => Some(MoonData {
196 mass: CALLISTO_MASS,
197 radius: CALLISTO_RADIUS,
198 }),
199 "titan" => Some(MoonData {
200 mass: TITAN_MASS,
201 radius: TITAN_RADIUS,
202 }),
203 "enceladus" => Some(MoonData {
204 mass: ENCELADUS_MASS,
205 radius: ENCELADUS_RADIUS,
206 }),
207 "triton" => Some(MoonData {
208 mass: TRITON_MASS,
209 radius: TRITON_RADIUS,
210 }),
211 "phobos" => Some(MoonData {
212 mass: PHOBOS_MASS,
213 radius: PHOBOS_RADIUS,
214 }),
215 "deimos" => Some(MoonData {
216 mass: DEIMOS_MASS,
217 radius: DEIMOS_RADIUS,
218 }),
219 "oberon" => Some(MoonData {
220 mass: OBERON_MASS,
221 radius: OBERON_RADIUS,
222 }),
223 "titania" => Some(MoonData {
224 mass: TITANIA_MASS,
225 radius: TITANIA_RADIUS,
226 }),
227 "tethys" => Some(MoonData {
228 mass: TETHYS_MASS,
229 radius: TETHYS_RADIUS,
230 }),
231 "dione" => Some(MoonData {
232 mass: DIONE_MASS,
233 radius: DIONE_RADIUS,
234 }),
235 "rhea" => Some(MoonData {
236 mass: RHEA_MASS,
237 radius: RHEA_RADIUS,
238 }),
239 "iapetus" => Some(MoonData {
240 mass: IAPETUS_MASS,
241 radius: IAPETUS_RADIUS,
242 }),
243 "hyperion" => Some(MoonData {
244 mass: HYPERION_MASS,
245 radius: HYPERION_RADIUS,
246 }),
247 "mimas" => Some(MoonData {
248 mass: MIMAS_MASS,
249 radius: MIMAS_RADIUS,
250 }),
251 "prometheus" => Some(MoonData {
252 mass: PROMETHEUS_MASS,
253 radius: PROMETHEUS_RADIUS,
254 }),
255 "pandora" => Some(MoonData {
256 mass: PANDORA_MASS,
257 radius: PANDORA_RADIUS,
258 }),
259 "atlas" => Some(MoonData {
260 mass: ATLAS_MASS,
261 radius: ATLAS_RADIUS,
262 }),
263 "pan" => Some(MoonData {
264 mass: PAN_MASS,
265 radius: PAN_RADIUS,
266 }),
267 "epimetheus" => Some(MoonData {
268 mass: EPIMETHEUS_MASS,
269 radius: EPIMETHEUS_RADIUS,
270 }),
271 "janus" => Some(MoonData {
272 mass: JANUS_MASS,
273 radius: JANUS_RADIUS,
274 }),
275 "amalthea" => Some(MoonData {
276 mass: AMALTHEA_MASS,
277 radius: AMALTHEA_RADIUS,
278 }),
279 "thebe" => Some(MoonData {
280 mass: THEBE_MASS,
281 radius: THEBE_RADIUS,
282 }),
283 "himalia" => Some(MoonData {
284 mass: HIMALIA_MASS,
285 radius: HIMALIA_RADIUS,
286 }),
287 "metis" => Some(MoonData {
288 mass: METIS_MASS,
289 radius: METIS_RADIUS,
290 }),
291 "adrastea" => Some(MoonData {
292 mass: ADRASTEA_MASS,
293 radius: ADRASTEA_RADIUS,
294 }),
295 _ => None,
296 }
297}
298
299pub fn moon_mass(name: &str) -> Option<f64> {
300 moon_data(name).map(|m| m.mass)
301}
302
303pub fn moon_radius(name: &str) -> Option<f64> {
304 moon_data(name).map(|m| m.radius)
305}
306
307pub fn moon_surface_gravity(name: &str) -> Option<f64> {
308 moon_data(name).map(|m| G * m.mass / (m.radius * m.radius))
309}
310
311pub fn moon_escape_velocity(name: &str) -> Option<f64> {
312 moon_data(name).map(|m| (2.0 * G * m.mass / m.radius).sqrt())
313}
314
315pub fn moon_volume(name: &str) -> Option<f64> {
316 moon_data(name).map(|m| 4.0 / 3.0 * std::f64::consts::PI * m.radius.powi(3))
317}
318
319pub fn moon_mean_density(name: &str) -> Option<f64> {
320 moon_data(name).map(|m| m.mass / (4.0 / 3.0 * std::f64::consts::PI * m.radius.powi(3)))
321}