Skip to main content

lox_frames/iers/nutation/
iau1980.rs

1// SPDX-FileCopyrightText: 2023 Angus Morrison <github@angus-morrison.com>
2// SPDX-FileCopyrightText: 2024 Helge Eichhorn <git@helgeeichhorn.de>
3//
4// SPDX-License-Identifier: MPL-2.0
5
6use std::f64::consts::TAU;
7
8use lox_core::types::units::{Arcseconds, JulianCenturies};
9use lox_core::units::{Angle, AngleUnits};
10use lox_time::{Time, julian_dates::JulianDate, time_scales::Tdb};
11
12use crate::iers::nutation::Nutation;
13
14struct Coefficients {
15    /// Coefficients of l, l', F, D and Ω.
16    l: f64,
17    lp: f64,
18    f: f64,
19    d: f64,
20    om: f64,
21
22    /// Coefficients of longitude, ψ.
23    sin_psi: f64,
24    sin_psi_t: f64,
25
26    /// Coefficients of obliquity, ε.
27    cos_eps: f64,
28    cos_eps_t: f64,
29}
30
31impl Nutation {
32    /// Computes nutation using the IAU 1980 model.
33    pub fn iau1980(time: Time<Tdb>) -> Self {
34        let t = time.centuries_since_j2000();
35        let l = l(t);
36        let lp = lp(t);
37        let f = f(t);
38        let d = d(t);
39        let om = omega(t);
40
41        let (dpsi, deps) = COEFFICIENTS
42            .iter()
43            // The coefficients are given by descending magnitude but folded by ascending
44            // magnitude to minimise floating-point error.
45            .rev()
46            .fold((0.0, 0.0), |(mut dpsi, mut deps), coeff| {
47                // Form argument for current term.
48                let arg = coeff.l * l + coeff.lp * lp + coeff.f * f + coeff.d * d + coeff.om * om;
49
50                // Accumulate current term.
51                let sin = coeff.sin_psi + coeff.sin_psi_t * t;
52                let cos = coeff.cos_eps + coeff.cos_eps_t * t;
53                dpsi += sin * arg.sin();
54                deps += cos * arg.cos();
55
56                (dpsi, deps)
57            });
58
59        Self {
60            dpsi: (1e-1 * dpsi).mas(),
61            deps: (1e-1 * deps).mas(),
62        }
63    }
64}
65
66/// `l`, the mean longitude of the Moon measured from the mean position of the perigee,
67/// normalized to the range [0, 2π).
68fn l(centuries_since_j2000_tdb: JulianCenturies) -> Angle {
69    let l_poly: Arcseconds = fast_polynomial::poly_array(
70        centuries_since_j2000_tdb,
71        &[485866.733, 715922.633, 31.31, 0.064],
72    );
73    (l_poly.arcsec() + ((1325.0 * centuries_since_j2000_tdb % 1.0) * TAU).rad())
74        .normalize_two_pi(Angle::ZERO)
75}
76
77/// `l'`, the mean longitude of the Sun measured from the mean position of the perigee,
78/// normalized to the range [0, 2π).
79fn lp(centuries_since_j2000_tdb: JulianCenturies) -> Angle {
80    let lp_poly: Arcseconds = fast_polynomial::poly_array(
81        centuries_since_j2000_tdb,
82        &[1287099.804, 1292581.224, -0.577, -0.012],
83    );
84    (lp_poly.arcsec() + ((99.0 * centuries_since_j2000_tdb % 1.0) * TAU).rad())
85        .normalize_two_pi(Angle::ZERO)
86}
87
88/// `F`, the mean longitude of the Moon minus the mean longitude of the Moon's ascending node,
89/// normalized to the range [0, 2π).
90fn f(centuries_since_j2000_tdb: JulianCenturies) -> Angle {
91    let f_poly: Arcseconds = fast_polynomial::poly_array(
92        centuries_since_j2000_tdb,
93        &[335778.877, 295263.137, -13.257, 0.011],
94    );
95    (f_poly.arcsec() + ((1342.0 * centuries_since_j2000_tdb % 1.0) * TAU).rad())
96        .normalize_two_pi(Angle::ZERO)
97}
98
99/// `D`, the mean elongation of the Moon from the Sun, normalized to the range [0, 2π).
100fn d(centuries_since_j2000_tdb: JulianCenturies) -> Angle {
101    let d_poly: Arcseconds = fast_polynomial::poly_array(
102        centuries_since_j2000_tdb,
103        &[1072261.307, 1105601.328, -6.891, 0.019],
104    );
105    (d_poly.arcsec() + ((1236.0 * centuries_since_j2000_tdb % 1.0) * TAU).rad())
106        .normalize_two_pi(Angle::ZERO)
107}
108
109/// `Ω`, the longitude of the mean ascending node of the lunar orbit on the ecliptic, measured from
110/// the mean equinox of date.
111fn omega(centuries_since_j2000_tdb: JulianCenturies) -> Angle {
112    let om_poly: Arcseconds = fast_polynomial::poly_array(
113        centuries_since_j2000_tdb,
114        &[450160.280, -482890.539, 7.455, 0.008],
115    );
116    (om_poly.arcsec() + ((-5.0 * centuries_since_j2000_tdb % 1.0) * TAU).rad())
117        .normalize_two_pi(Angle::ZERO)
118}
119
120#[rustfmt::skip]
121// @formatter:off (sometimes RustRover ignores rustfmt::skip)
122const COEFFICIENTS: [Coefficients; 106] = [
123    Coefficients{ l: 0.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 1.0,	sin_psi:-171996.0,	sin_psi_t:-174.2,	cos_eps: 92025.0,	cos_eps_t:  8.9 },
124    Coefficients{ l: 0.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 2.0,	sin_psi:   2062.0,	sin_psi_t:   0.2,	cos_eps:  -895.0,	cos_eps_t:  0.5 },
125    Coefficients{ l: -2.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 1.0,	sin_psi:     46.0,	sin_psi_t:   0.0,	cos_eps:   -24.0,	cos_eps_t:  0.0 },
126    Coefficients{ l: 2.0,	lp: 0.0,	f:-2.0,	d: 0.0,	om: 0.0,	sin_psi:     11.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
127    Coefficients{ l: -2.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:     -3.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
128    Coefficients{ l: 1.0,	lp:-1.0,	f: 0.0,	d:-1.0,	om: 0.0,	sin_psi:     -3.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
129    Coefficients{ l: 0.0,	lp:-2.0,	f: 2.0,	d:-2.0,	om: 1.0,	sin_psi:     -2.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
130    Coefficients{ l: 2.0,	lp: 0.0,	f:-2.0,	d: 0.0,	om: 1.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
131    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 2.0,	sin_psi: -13187.0,	sin_psi_t:  -1.6,	cos_eps:  5736.0,	cos_eps_t: -3.1 },
132    Coefficients{ l: 0.0,	lp: 1.0,	f: 0.0,	d: 0.0,	om: 0.0,	sin_psi:   1426.0,	sin_psi_t:  -3.4,	cos_eps:    54.0,	cos_eps_t: -0.1 },
133    Coefficients{ l: 0.0,	lp: 1.0,	f: 2.0,	d:-2.0,	om: 2.0,	sin_psi:   -517.0,	sin_psi_t:   1.2,	cos_eps:   224.0,	cos_eps_t: -0.6 },
134    Coefficients{ l: 0.0,	lp:-1.0,	f: 2.0,	d:-2.0,	om: 2.0,	sin_psi:    217.0,	sin_psi_t:  -0.5,	cos_eps:   -95.0,	cos_eps_t:  0.3 },
135    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 1.0,	sin_psi:    129.0,	sin_psi_t:   0.1,	cos_eps:   -70.0,	cos_eps_t:  0.0 },
136    Coefficients{ l: 2.0,	lp: 0.0,	f: 0.0,	d:-2.0,	om: 0.0,	sin_psi:     48.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
137    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 0.0,	sin_psi:    -22.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
138    Coefficients{ l: 0.0,	lp: 2.0,	f: 0.0,	d: 0.0,	om: 0.0,	sin_psi:     17.0,	sin_psi_t:  -0.1,	cos_eps:     0.0,	cos_eps_t:  0.0 },
139    Coefficients{ l: 0.0,	lp: 1.0,	f: 0.0,	d: 0.0,	om: 1.0,	sin_psi:    -15.0,	sin_psi_t:   0.0,	cos_eps:     9.0,	cos_eps_t:  0.0 },
140    Coefficients{ l: 0.0,	lp: 2.0,	f: 2.0,	d:-2.0,	om: 2.0,	sin_psi:    -16.0,	sin_psi_t:   0.1,	cos_eps:     7.0,	cos_eps_t:  0.0 },
141    Coefficients{ l: 0.0,	lp:-1.0,	f: 0.0,	d: 0.0,	om: 1.0,	sin_psi:    -12.0,	sin_psi_t:   0.0,	cos_eps:     6.0,	cos_eps_t:  0.0 },
142    Coefficients{ l: -2.0,	lp: 0.0,	f: 0.0,	d: 2.0,	om: 1.0,	sin_psi:     -6.0,	sin_psi_t:   0.0,	cos_eps:     3.0,	cos_eps_t:  0.0 },
143    Coefficients{ l: 0.0,	lp:-1.0,	f: 2.0,	d:-2.0,	om: 1.0,	sin_psi:     -5.0,	sin_psi_t:   0.0,	cos_eps:     3.0,	cos_eps_t:  0.0 },
144    Coefficients{ l: 2.0,	lp: 0.0,	f: 0.0,	d:-2.0,	om: 1.0,	sin_psi:      4.0,	sin_psi_t:   0.0,	cos_eps:    -2.0,	cos_eps_t:  0.0 },
145    Coefficients{ l: 0.0,	lp: 1.0,	f: 2.0,	d:-2.0,	om: 1.0,	sin_psi:      4.0,	sin_psi_t:   0.0,	cos_eps:    -2.0,	cos_eps_t:  0.0 },
146    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d:-1.0,	om: 0.0,	sin_psi:     -4.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
147    Coefficients{ l: 2.0,	lp: 1.0,	f: 0.0,	d:-2.0,	om: 0.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
148    Coefficients{ l: 0.0,	lp: 0.0,	f:-2.0,	d: 2.0,	om: 1.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
149    Coefficients{ l: 0.0,	lp: 1.0,	f:-2.0,	d: 2.0,	om: 0.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
150    Coefficients{ l: 0.0,	lp: 1.0,	f: 0.0,	d: 0.0,	om: 2.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
151    Coefficients{ l: -1.0,	lp: 0.0,	f: 0.0,	d: 1.0,	om: 1.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
152    Coefficients{ l: 0.0,	lp: 1.0,	f: 2.0,	d:-2.0,	om: 0.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
153    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:  -2274.0,	sin_psi_t:  -0.2,	cos_eps:   977.0,	cos_eps_t: -0.5 },
154    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 0.0,	sin_psi:    712.0,	sin_psi_t:   0.1,	cos_eps:    -7.0,	cos_eps_t:  0.0 },
155    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 1.0,	sin_psi:   -386.0,	sin_psi_t:  -0.4,	cos_eps:   200.0,	cos_eps_t:  0.0 },
156    Coefficients{ l: 1.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:   -301.0,	sin_psi_t:   0.0,	cos_eps:   129.0,	cos_eps_t: -0.1 },
157    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d:-2.0,	om: 0.0,	sin_psi:   -158.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
158    Coefficients{ l: -1.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:    123.0,	sin_psi_t:   0.0,	cos_eps:   -53.0,	cos_eps_t:  0.0 },
159    Coefficients{ l: 0.0,	lp: 0.0,	f: 0.0,	d: 2.0,	om: 0.0,	sin_psi:     63.0,	sin_psi_t:   0.0,	cos_eps:    -2.0,	cos_eps_t:  0.0 },
160    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 1.0,	sin_psi:     63.0,	sin_psi_t:   0.1,	cos_eps:   -33.0,	cos_eps_t:  0.0 },
161    Coefficients{ l: -1.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 1.0,	sin_psi:    -58.0,	sin_psi_t:  -0.1,	cos_eps:    32.0,	cos_eps_t:  0.0 },
162    Coefficients{ l: -1.0,	lp: 0.0,	f: 2.0,	d: 2.0,	om: 2.0,	sin_psi:    -59.0,	sin_psi_t:   0.0,	cos_eps:    26.0,	cos_eps_t:  0.0 },
163    Coefficients{ l: 1.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 1.0,	sin_psi:    -51.0,	sin_psi_t:   0.0,	cos_eps:    27.0,	cos_eps_t:  0.0 },
164    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d: 2.0,	om: 2.0,	sin_psi:    -38.0,	sin_psi_t:   0.0,	cos_eps:    16.0,	cos_eps_t:  0.0 },
165    Coefficients{ l: 2.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 0.0,	sin_psi:     29.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
166    Coefficients{ l: 1.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 2.0,	sin_psi:     29.0,	sin_psi_t:   0.0,	cos_eps:   -12.0,	cos_eps_t:  0.0 },
167    Coefficients{ l: 2.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:    -31.0,	sin_psi_t:   0.0,	cos_eps:    13.0,	cos_eps_t:  0.0 },
168    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 0.0,	sin_psi:     26.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
169    Coefficients{ l: -1.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 1.0,	sin_psi:     21.0,	sin_psi_t:   0.0,	cos_eps:   -10.0,	cos_eps_t:  0.0 },
170    Coefficients{ l: -1.0,	lp: 0.0,	f: 0.0,	d: 2.0,	om: 1.0,	sin_psi:     16.0,	sin_psi_t:   0.0,	cos_eps:    -8.0,	cos_eps_t:  0.0 },
171    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d:-2.0,	om: 1.0,	sin_psi:    -13.0,	sin_psi_t:   0.0,	cos_eps:     7.0,	cos_eps_t:  0.0 },
172    Coefficients{ l: -1.0,	lp: 0.0,	f: 2.0,	d: 2.0,	om: 1.0,	sin_psi:    -10.0,	sin_psi_t:   0.0,	cos_eps:     5.0,	cos_eps_t:  0.0 },
173    Coefficients{ l: 1.0,	lp: 1.0,	f: 0.0,	d:-2.0,	om: 0.0,	sin_psi:     -7.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
174    Coefficients{ l: 0.0,	lp: 1.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:      7.0,	sin_psi_t:   0.0,	cos_eps:    -3.0,	cos_eps_t:  0.0 },
175    Coefficients{ l: 0.0,	lp:-1.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:     -7.0,	sin_psi_t:   0.0,	cos_eps:     3.0,	cos_eps_t:  0.0 },
176    Coefficients{ l: 1.0,	lp: 0.0,	f: 2.0,	d: 2.0,	om: 2.0,	sin_psi:     -8.0,	sin_psi_t:   0.0,	cos_eps:     3.0,	cos_eps_t:  0.0 },
177    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d: 2.0,	om: 0.0,	sin_psi:      6.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
178    Coefficients{ l: 2.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 2.0,	sin_psi:      6.0,	sin_psi_t:   0.0,	cos_eps:    -3.0,	cos_eps_t:  0.0 },
179    Coefficients{ l: 0.0,	lp: 0.0,	f: 0.0,	d: 2.0,	om: 1.0,	sin_psi:     -6.0,	sin_psi_t:   0.0,	cos_eps:     3.0,	cos_eps_t:  0.0 },
180    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d: 2.0,	om: 1.0,	sin_psi:     -7.0,	sin_psi_t:   0.0,	cos_eps:     3.0,	cos_eps_t:  0.0 },
181    Coefficients{ l: 1.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 1.0,	sin_psi:      6.0,	sin_psi_t:   0.0,	cos_eps:    -3.0,	cos_eps_t:  0.0 },
182    Coefficients{ l: 0.0,	lp: 0.0,	f: 0.0,	d:-2.0,	om: 1.0,	sin_psi:     -5.0,	sin_psi_t:   0.0,	cos_eps:     3.0,	cos_eps_t:  0.0 },
183    Coefficients{ l: 1.0,	lp:-1.0,	f: 0.0,	d: 0.0,	om: 0.0,	sin_psi:      5.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
184    Coefficients{ l: 2.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 1.0,	sin_psi:     -5.0,	sin_psi_t:   0.0,	cos_eps:     3.0,	cos_eps_t:  0.0 },
185    Coefficients{ l: 0.0,	lp: 1.0,	f: 0.0,	d:-2.0,	om: 0.0,	sin_psi:     -4.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
186    Coefficients{ l: 1.0,	lp: 0.0,	f:-2.0,	d: 0.0,	om: 0.0,	sin_psi:      4.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
187    Coefficients{ l: 0.0,	lp: 0.0,	f: 0.0,	d: 1.0,	om: 0.0,	sin_psi:     -4.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
188    Coefficients{ l: 1.0,	lp: 1.0,	f: 0.0,	d: 0.0,	om: 0.0,	sin_psi:     -3.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
189    Coefficients{ l: 1.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 0.0,	sin_psi:      3.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
190    Coefficients{ l: 1.0,	lp:-1.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:     -3.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
191    Coefficients{ l: -1.0,	lp:-1.0,	f: 2.0,	d: 2.0,	om: 2.0,	sin_psi:     -3.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
192    Coefficients{ l: -2.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 1.0,	sin_psi:     -2.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
193    Coefficients{ l: 3.0,	lp: 0.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:     -3.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
194    Coefficients{ l: 0.0,	lp:-1.0,	f: 2.0,	d: 2.0,	om: 2.0,	sin_psi:     -3.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
195    Coefficients{ l: 1.0,	lp: 1.0,	f: 2.0,	d: 0.0,	om: 2.0,	sin_psi:      2.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
196    Coefficients{ l: -1.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 1.0,	sin_psi:     -2.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
197    Coefficients{ l: 2.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 1.0,	sin_psi:      2.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
198    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 2.0,	sin_psi:     -2.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
199    Coefficients{ l: 3.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 0.0,	sin_psi:      2.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
200    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d: 1.0,	om: 2.0,	sin_psi:      2.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
201    Coefficients{ l: -1.0,	lp: 0.0,	f: 0.0,	d: 0.0,	om: 2.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
202    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d:-4.0,	om: 0.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
203    Coefficients{ l: -2.0,	lp: 0.0,	f: 2.0,	d: 2.0,	om: 2.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
204    Coefficients{ l: -1.0,	lp: 0.0,	f: 2.0,	d: 4.0,	om: 2.0,	sin_psi:     -2.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
205    Coefficients{ l: 2.0,	lp: 0.0,	f: 0.0,	d:-4.0,	om: 0.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
206    Coefficients{ l: 1.0,	lp: 1.0,	f: 2.0,	d:-2.0,	om: 2.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
207    Coefficients{ l: 1.0,	lp: 0.0,	f: 2.0,	d: 2.0,	om: 1.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
208    Coefficients{ l: -2.0,	lp: 0.0,	f: 2.0,	d: 4.0,	om: 2.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     1.0,	cos_eps_t:  0.0 },
209    Coefficients{ l: -1.0,	lp: 0.0,	f: 4.0,	d: 0.0,	om: 2.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
210    Coefficients{ l: 1.0,	lp:-1.0,	f: 0.0,	d:-2.0,	om: 0.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
211    Coefficients{ l: 2.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 1.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:    -1.0,	cos_eps_t:  0.0 },
212    Coefficients{ l: 2.0,	lp: 0.0,	f: 2.0,	d: 2.0,	om: 2.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
213    Coefficients{ l: 1.0,	lp: 0.0,	f: 0.0,	d: 2.0,	om: 1.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
214    Coefficients{ l: 0.0,	lp: 0.0,	f: 4.0,	d:-2.0,	om: 2.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
215    Coefficients{ l: 3.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 2.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
216    Coefficients{ l: 1.0,	lp: 0.0,	f: 2.0,	d:-2.0,	om: 0.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
217    Coefficients{ l: 0.0,	lp: 1.0,	f: 2.0,	d: 0.0,	om: 1.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
218    Coefficients{ l: -1.0,	lp:-1.0,	f: 0.0,	d: 2.0,	om: 1.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
219    Coefficients{ l: 0.0,	lp: 0.0,	f:-2.0,	d: 0.0,	om: 1.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
220    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d:-1.0,	om: 2.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
221    Coefficients{ l: 0.0,	lp: 1.0,	f: 0.0,	d: 2.0,	om: 0.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
222    Coefficients{ l: 1.0,	lp: 0.0,	f:-2.0,	d:-2.0,	om: 0.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
223    Coefficients{ l: 0.0,	lp:-1.0,	f: 2.0,	d: 0.0,	om: 1.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
224    Coefficients{ l: 1.0,	lp: 1.0,	f: 0.0,	d:-2.0,	om: 1.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
225    Coefficients{ l: 1.0,	lp: 0.0,	f:-2.0,	d: 2.0,	om: 0.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
226    Coefficients{ l: 2.0,	lp: 0.0,	f: 0.0,	d: 2.0,	om: 0.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
227    Coefficients{ l: 0.0,	lp: 0.0,	f: 2.0,	d: 4.0,	om: 2.0,	sin_psi:     -1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
228    Coefficients{ l: 0.0,	lp: 1.0,	f: 0.0,	d: 1.0,	om: 0.0,	sin_psi:      1.0,	sin_psi_t:   0.0,	cos_eps:     0.0,	cos_eps_t:  0.0 },
229];
230// @formatter:on
231
232#[cfg(test)]
233mod tests {
234    use lox_test_utils::assert_approx_eq;
235
236    use super::*;
237
238    #[test]
239    fn test_nutation_iau1980() {
240        let time = Time::from_two_part_julian_date(Tdb, 2400000.5, 53736.0);
241        let actual = Nutation::iau1980(time);
242        let expected = Nutation {
243            dpsi: -9.643_658_353_226_563e-6.rad(),
244            deps: 4.060_051_006_879_713e-5.rad(),
245        };
246        assert_approx_eq!(expected, actual, rtol <= 1e-13);
247    }
248}