Skip to main content

deep_time/sidereal/
earth.rs

1//! Earth equinox sidereal time (IAU 2000/2006).
2//!
3//! [`Sidereal`](../struct.Sidereal.html) is a prime-meridian clock. On Earth that clock is the Earth
4//! Rotation Angle (ERA, CIO origin). This module adds the IAU equinox readout
5//! of that clock as methods on [`Sidereal`](../struct.Sidereal.html):
6//!
7//! ```text
8//! GAST = ERA − eo06a(TT)                 // true equinox
9//! GMST = ERA − eo06a(TT) − ee06a(TT)     // mean equinox
10//! LAST = GAST + λ                        // east longitude, radians
11//! LMST = GMST + λ
12//! ```
13//!
14//! ERA / GMST / GAST take **UT1** MJD. The Equation of the Origins (`eo`) and
15//! Equation of the Equinoxes (`ee`) take **TT** MJD. These quantities are
16//! Earth-only; they are not a generic mode of [`Sidereal`](../struct.Sidereal.html).
17//!
18//! With matching UT1 and TT, results agree with Astropy mean/apparent sidereal
19//! time and ERFA `eo06a` / `ee06a` (see tests).
20
21use super::earth_eo_ee::{earth_ee, earth_eo};
22use super::{Sidereal, wrap_angle};
23use crate::Real;
24
25/// Earth equinox sidereal time.
26///
27/// Greenwich forms (`era`, `gmst`, `gast`, `eo`, `ee`) always use the IAU ERA
28/// ([`Sidereal::EARTH`](../struct.Sidereal.html#associatedconstant.EARTH)), not this instance's `rate` or `correction_rad`.
29/// Local forms (`lmst`, `last`) add this instance's [`Sidereal::longitude_rad`](../struct.Sidereal.html#structfield.longitude_rad)
30/// (east positive).
31impl Sidereal {
32    /// Earth Rotation Angle at **UT1** MJD, radians in `[0, 2π)`.
33    ///
34    /// Same as [`Sidereal::EARTH`](../struct.Sidereal.html#associatedconstant.EARTH).[`Sidereal::rotation_angle`](../struct.Sidereal.html#method.rotation_angle).
35    #[inline]
36    pub const fn era(ut1_mjd: Real) -> Real {
37        Self::EARTH.rotation_angle(ut1_mjd)
38    }
39
40    /// Equation of the Origins at **TT** MJD (`eo06a`): `EO = ERA − GAST`.
41    #[inline]
42    pub const fn eo(tt_mjd: Real) -> Real {
43        earth_eo(2_400_000.5, tt_mjd)
44    }
45
46    /// Equation of the Equinoxes at **TT** MJD (`ee06a`): `EE = GAST − GMST`.
47    #[inline]
48    pub const fn ee(tt_mjd: Real) -> Real {
49        earth_ee(2_400_000.5, tt_mjd)
50    }
51
52    /// Greenwich Mean Sidereal Time (radians): `ERA(UT1) − eo(TT) − ee(TT)`.
53    ///
54    /// ## Examples
55    ///
56    /// ```rust
57    /// # #[cfg(all(feature = "eop", feature = "std", feature = "sidereal-earth"))] {
58    /// use deep_time::eop::{EopData, EopFormat, Separator};
59    /// use deep_time::{Dt, Scale, Sidereal};
60    ///
61    /// let eop = EopData::from_text_file(
62    ///     "tests/assets/EOP_20u24_C04_one_file_1962-now.txt",
63    ///     EopFormat::C04,
64    ///     Separator::Whitespace,
65    /// ).unwrap();
66    /// let utc = Dt::from_mjd_f(56879.0, Scale::UTC);
67    /// let ut1 = utc.to_ut1(&eop).unwrap().to_mjd_f_raw();
68    /// let tt = utc.to(Scale::TT).to_mjd_f_raw();
69    ///
70    /// let gmst = Sidereal::gmst(ut1, tt);
71    /// let _ = gmst;
72    /// # }
73    /// ```
74    #[inline]
75    pub const fn gmst(ut1_mjd: Real, tt_mjd: Real) -> Real {
76        wrap_angle(Self::era(ut1_mjd) - Self::eo(tt_mjd) - Self::ee(tt_mjd))
77    }
78
79    /// Greenwich Apparent Sidereal Time (radians): `ERA(UT1) − eo(TT)`.
80    #[inline]
81    pub const fn gast(ut1_mjd: Real, tt_mjd: Real) -> Real {
82        wrap_angle(Self::era(ut1_mjd) - Self::eo(tt_mjd))
83    }
84
85    /// Local Mean Sidereal Time (radians): `GMST + longitude_rad`.
86    ///
87    /// Always uses IAU Earth ERA
88    /// ([`Sidereal::gmst`](../struct.Sidereal.html#method.gmst)). Only
89    /// [`Sidereal::longitude_rad`](../struct.Sidereal.html#structfield.longitude_rad) (east positive) is taken from this instance.
90    ///
91    /// ```text
92    /// HA = lmst(ut1, tt) − RA   // mean-equinox RA
93    /// ```
94    #[inline]
95    pub const fn lmst(&self, ut1_mjd: Real, tt_mjd: Real) -> Real {
96        wrap_angle(Self::gmst(ut1_mjd, tt_mjd) + self.longitude_rad)
97    }
98
99    /// Local Apparent Sidereal Time (radians): `GAST + longitude_rad`.
100    ///
101    /// Always uses IAU Earth ERA
102    /// ([`Sidereal::gast`](../struct.Sidereal.html#method.gast)). Only
103    /// [`Sidereal::longitude_rad`](../struct.Sidereal.html#structfield.longitude_rad) (east positive) is taken from this instance.
104    ///
105    /// ```text
106    /// HA = last(ut1, tt) − RA   // true-equinox RA
107    /// ```
108    #[inline]
109    pub const fn last(&self, ut1_mjd: Real, tt_mjd: Real) -> Real {
110        wrap_angle(Self::gast(ut1_mjd, tt_mjd) + self.longitude_rad)
111    }
112}