Skip to main content

sciforge_lib/astronomy/
celestial.rs

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}