|
| 1 | +# This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | +# License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 | +# file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| 4 | + |
| 5 | +import random |
| 6 | + |
| 7 | +import erfa |
| 8 | +import numpy as np |
| 9 | + |
| 10 | +from TerraFrame.PrecessionNutation import SeriesExpansion |
| 11 | +from TerraFrame.Utilities import TransformationMatrices, Conversions |
| 12 | +from TerraFrame.Utilities.Time import JulianDate |
| 13 | + |
| 14 | + |
| 15 | +def test_cirs_to_gcrs_calculation(): |
| 16 | + se_cip_x = SeriesExpansion.cip_x() |
| 17 | + se_cip_y = SeriesExpansion.cip_y() |
| 18 | + se_cip_sxy2 = SeriesExpansion.cip_sxy2() |
| 19 | + |
| 20 | + val = random.uniform(0, 100.0) |
| 21 | + jd_tt = (JulianDate.JulianDate.j2000( |
| 22 | + time_scale=JulianDate.TimeScales.TT) + val) |
| 23 | + jdc_tt = JulianDate.julian_day_datetime_to_century_datetime(jd_tt) |
| 24 | + |
| 25 | + cip_x = se_cip_x.compute(jdc_tt) |
| 26 | + cip_y = se_cip_y.compute(jdc_tt) |
| 27 | + sxy2 = se_cip_sxy2.compute(jdc_tt) |
| 28 | + cip_s = sxy2 - cip_x * cip_y / 2.0 |
| 29 | + |
| 30 | + t_gc = TransformationMatrices.cirs_to_gcrs(cip_x, cip_y, cip_s) |
| 31 | + |
| 32 | + jd1, jd2 = jd_tt.integer_part(), jd_tt.fraction_part() |
| 33 | + |
| 34 | + # Get X, Y, s using IAU 2006/2000A model |
| 35 | + x, y, s = erfa.xys06a(jd1, jd2) |
| 36 | + |
| 37 | + # ERFA/SOFA computes the inverse transform, so we need to take the transpose |
| 38 | + t_cg_erfa = erfa.c2ixys(x, y, s) |
| 39 | + t_gc_erfa = t_cg_erfa.T |
| 40 | + |
| 41 | + assert abs(cip_x - x) < 1e-8 |
| 42 | + assert abs(cip_y - y) < 1e-8 |
| 43 | + assert abs(cip_s - s) < 1e-8 |
| 44 | + |
| 45 | + assert (np.max(np.abs(t_gc - t_gc_erfa)) < 1e-10) |
| 46 | + |
| 47 | + |
| 48 | +def test_cirs_to_gcrs_derivative_calculation(): |
| 49 | + se_cip_x = SeriesExpansion.cip_x() |
| 50 | + se_cip_y = SeriesExpansion.cip_y() |
| 51 | + se_cip_sxy2 = SeriesExpansion.cip_sxy2() |
| 52 | + |
| 53 | + dt = 1e-6 |
| 54 | + |
| 55 | + val = random.uniform(0, 100.0) |
| 56 | + jd_tt = (JulianDate.JulianDate.j2000( |
| 57 | + time_scale=JulianDate.TimeScales.TT) + val) |
| 58 | + jdc_tt = JulianDate.julian_day_datetime_to_century_datetime(jd_tt) |
| 59 | + |
| 60 | + cip_x, d_cip_x_dt = se_cip_x.compute(jdc_tt, derivative=True) |
| 61 | + cip_y, d_cip_y_dt = se_cip_y.compute(jdc_tt, derivative=True) |
| 62 | + sxy2, d_cip_sxy2_dt = se_cip_sxy2.compute(jdc_tt, derivative=True) |
| 63 | + cip_s = sxy2 - cip_x * cip_y / 2.0 |
| 64 | + d_cip_s_dt = (d_cip_sxy2_dt - 0.5 * cip_y * d_cip_x_dt - |
| 65 | + 0.5 * cip_x * d_cip_y_dt) |
| 66 | + |
| 67 | + d_t_gc_dt = (TransformationMatrices. |
| 68 | + cirs_to_gcrs_derivative(cip_x, cip_y, cip_s, |
| 69 | + d_cip_x_dt, d_cip_y_dt, d_cip_s_dt)) |
| 70 | + |
| 71 | + cip_x2 = se_cip_x.compute(jdc_tt + dt) |
| 72 | + cip_y2 = se_cip_y.compute(jdc_tt + dt) |
| 73 | + sxy22 = se_cip_sxy2.compute(jdc_tt + dt) |
| 74 | + cip_s2 = sxy22 - cip_x2 * cip_y2 / 2.0 |
| 75 | + |
| 76 | + cip_x1 = se_cip_x.compute(jdc_tt - dt) |
| 77 | + cip_y1 = se_cip_y.compute(jdc_tt - dt) |
| 78 | + sxy21 = se_cip_sxy2.compute(jdc_tt - dt) |
| 79 | + cip_s1 = sxy21 - cip_x1 * cip_y1 / 2.0 |
| 80 | + |
| 81 | + t_gc2 = TransformationMatrices.cirs_to_gcrs(cip_x2, cip_y2, cip_s2) |
| 82 | + t_gc1 = TransformationMatrices.cirs_to_gcrs(cip_x1, cip_y1, cip_s1) |
| 83 | + |
| 84 | + d_t_gc_dt_fd = (t_gc2 - t_gc1) / (2 * dt) |
| 85 | + d_t_gc_dt_fd *= Conversions.seconds_to_centuries(1.0) |
| 86 | + |
| 87 | + error = np.abs(d_t_gc_dt - d_t_gc_dt_fd) |
| 88 | + |
| 89 | + assert np.max(error) < 1e-15 |
0 commit comments