/* Copyright 2002-2017 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.utils;
import org.hipparchus.analysis.UnivariateFunction;
import org.hipparchus.analysis.UnivariateVectorFunction;
import org.hipparchus.analysis.differentiation.DSFactory;
import org.hipparchus.analysis.differentiation.DerivativeStructure;
import org.hipparchus.analysis.differentiation.FiniteDifferencesDifferentiator;
import org.hipparchus.analysis.differentiation.UnivariateDifferentiableFunction;
import org.hipparchus.analysis.differentiation.UnivariateDifferentiableVectorFunction;
import org.hipparchus.util.Decimal64;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.MathUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.errors.OrekitException;
import org.orekit.frames.EOPHistory;
import org.orekit.frames.FramesFactory;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeVectorFunction;
import org.orekit.time.DateComponents;
import org.orekit.time.FieldAbsoluteDate;
import org.orekit.time.TimeScalarFunction;
import org.orekit.time.TimeScale;
import org.orekit.time.TimeScalesFactory;
import org.orekit.time.UT1Scale;
public class IERSConventionsTest {
@Test
public void testConventionsNumber() {
Assert.assertEquals(3, IERSConventions.values().length);
}
@Test
public void testIERS1996NutationAngles() throws OrekitException {
// the reference value has been computed using the March 2012 version of the SOFA library
// http://www.iausofa.org/2012_0301_C.html, with the following code
//
// double utc1, utc2, tai1, tai2, tt1, tt2, dpsi, deps, epsa;
//
// // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
// utc1 = DJM0 + 53049.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
//
// iauNut80(tt1, tt2, &dpsi, &deps);
// epsa = iauObl80(tt1, tt2);
//
// printf("iauNut80(%.20g, %.20g, dpsi, deps)\n --> %.20g %.20g\n",
// tt1, tt2, dpsi, deps);
// printf("iau0bl80(%.20g, %.20g)\n --> %.20g\n",
// tt1, tt2, epsa);
//
// the output of this test reads:
// iauNut80(2453049.5, 0.00074287037037037029902, dpsi, deps)
// --> -5.3059154211478291722e-05 3.2051803135750973851e-05
// iau0bl80(2453049.5, 0.00074287037037037029902)
// --> 0.40908345528446415917
// the thresholds below have been set up large enough to have the test pass with
// the default Orekit setting and the reference SOFA setting. There are implementation
// differences between the two libraries, as the Delaunay parameters are not the
// same (in Orekit, we are compliant with page 23 in chapter 5 of IERS conventions 1996.
// If the content of the IERS-conventions/1996/nutation-arguments.txt file by Orekit is
// changed to match SOFA setting instead of IERS conventions as follows:
//
// # Mean Anomaly of the Moon
// F1 ≡ l = 485866.733″ + 1717915922.633″t + 31.310″t² + 0.064″t³
//
// # Mean Anomaly of the Sun
// F2 ≡ l' = 1287099.804″ + 129596581.224″t − 0.577″t² − 0.012t³
//
// # L − Ω
// F3 ≡ F = 335778.877″ + 1739527263.137″t − 13.257″t² + 0.011″t³
//
// # Mean Elongation of the Moon from the Sun
// F4 ≡ D = 1072261.307″ + 1602961601.328″t − 6.891″t² + 0.019″t³
//
// # Mean Longitude of the Ascending Node of the Moon
// F5 ≡ Ω = 450160.280″ − 6962890.539″t + 7.455″t² + 0.008″t³
//
// then the thresholds for the test can be reduced to 3e-13 for ∆ψ and 7e-14 for ∆ε.
// We decided to stick with IERS published reference values for the default Orekit setting.
// The differences are nevertheless quite small (4.8e-11 radians is sub-millimeter level
// in low Earth orbit).
AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
double[] angles= IERSConventions.IERS_1996.getNutationFunction().value(date);
Assert.assertEquals(-5.3059154211478291722e-05, angles[0], 4.8e-11); // 3e-13 with SOFA values
Assert.assertEquals(3.2051803135750973851e-05, angles[1], 1.3e-11); // 7e-14 with SOFA values
double epsilonA = IERSConventions.IERS_1996.getMeanObliquityFunction().value(date);
Assert.assertEquals(0.40908345528446415917, epsilonA, 1.0e-16);
}
@Test
public void testGMST82FieldConsistency() throws OrekitException {
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_1996, true);
checkScalarFunctionConsistency(IERSConventions.IERS_1996.getGMSTFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 9.0e-16, 8.0e-13);
}
@Test
public void testGMST82Sofa() throws OrekitException {
// the reference value has been computed using the March 2012 version of the SOFA library
// http://www.iausofa.org/2012_0301_C.html, with the following code
//
// double utc1, utc2, ut11, ut12, gmst;
//
// // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
// utc1 = DJM0 + 53049.0;
// utc2 = 0.0;
// iauUtcut1(utc1, utc2, -0.4093509, &ut11, &ut12);
// gmst = iauGmst82(ut11, ut12);
// printf("iaugmst82(%.20g, %.20g)\n --> %.20g\n", ut11, ut12, gmst);
//
// // 2004-02-29:00:00:00Z, MJD = 53064, UT1-UTC = -0.4175723
// utc1 = DJM0 + 53064.0;
// utc2 = 0.0;
// iauUtcut1(utc1, utc2, -0.4175723, &ut11, &ut12);
// gmst = iauGmst82(ut11, ut12);
// printf("iaugmst82(%.20g, %.20g)\n --> %.20g\n", ut11, ut12, gmst);
//
// the output of this test reads:
// iaugmst82(2453049.5, -4.7378576388888813016e-06)
// --> 2.5021977627453466653
// iaugmst82(2453064.5, -4.8330127314815448519e-06)
// --> 2.7602390405411441066
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_1996, true);
final TimeScalarFunction gmst82 = IERSConventions.IERS_1996.getGMSTFunction(ut1);
AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
double gmst = MathUtils.normalizeAngle(gmst82.value(date), 0.0);
Assert.assertEquals(2.5021977627453466653, gmst, 2.0e-13);
date = new AbsoluteDate(2004, 2, 29, TimeScalesFactory.getUTC());
gmst = MathUtils.normalizeAngle(gmst82.value(date), 0.0);
Assert.assertEquals(2.7602390405411441066, gmst, 4.0e-13);
}
@Test
public void testGMST00FieldConsistency() throws OrekitException {
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2003, true);
checkScalarFunctionConsistency(IERSConventions.IERS_2003.getGMSTFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-15, 8.0e-13);
}
@Test
public void testGMST00Sofa() throws OrekitException {
// the reference value has been computed using the March 2012 version of the SOFA library
// http://www.iausofa.org/2012_0301_C.html, with the following code
//
// double utc1, utc2, tai1, tai2, tt1, tt2, ut11, ut12, gmst;
//
// // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
// utc1 = DJM0 + 53049.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// iauUtcut1(utc1, utc2, -0.4093509, &ut11, &ut12);
// gmst = iauGmst00(ut11, ut12, tt1, tt2);
// printf("iaugmst00(%.20g, %.20g, %.20g, %.20g)\n --> %.20g\n",
// ut11, ut12, tt1, tt2, gmst);
//
// // 2004-02-29:00:00:00Z, MJD = 53064, UT1-UTC = -0.4175723
// utc1 = DJM0 + 53064.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// iauUtcut1(utc1, utc2, -0.4175723, &ut11, &ut12);
// gmst = iauGmst00(ut11, ut12, tt1, tt2);
// printf("iaugmst00(%.20g, %.20g, %.20g, %.20g)\n --> %.20g\n",
// ut11, ut12, tt1, tt2, gmst);
//
// the output of this test reads:
// iaugmst00(2453049.5, -4.7378576388888813016e-06, 2453049.5, 0.00074287037037037029902)
// --> 2.5021977786243789765
// iaugmst00(2453064.5, -4.8330127314815448519e-06, 2453064.5, 0.00074287037037037029902)
// --> 2.7602390558728311376
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2003, true);
final TimeScalarFunction gmst00 = IERSConventions.IERS_2003.getGMSTFunction(ut1);
AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
double gmst = MathUtils.normalizeAngle(gmst00.value(date), 0.0);
Assert.assertEquals(2.5021977786243789765, gmst, 1.0e-15);
date = new AbsoluteDate(2004, 2, 29, TimeScalesFactory.getUTC());
gmst = MathUtils.normalizeAngle(gmst00.value(date), 0.0);
Assert.assertEquals(2.7602390558728311376, gmst, 1.0e-15);
}
@Test
public void testGMST06FieldConsistency() throws OrekitException {
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
checkScalarFunctionConsistency(IERSConventions.IERS_2010.getGMSTFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-15, 8.0e-13);
}
@Test
public void testGMST06Sofa() throws OrekitException {
// the reference value has been computed using the March 2012 version of the SOFA library
// http://www.iausofa.org/2012_0301_C.html, with the following code
//
// double utc1, utc2, tai1, tai2, tt1, tt2, ut11, ut12, gmst;
//
// // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
// utc1 = DJM0 + 53049.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// iauUtcut1(utc1, utc2, -0.4093509, &ut11, &ut12);
// gmst = iauGmst06(ut11, ut12, tt1, tt2);
// printf("iaugmst06(%.20g, %.20g, %.20g, %.20g)\n --> %.20g\n",
// ut11, ut12, tt1, tt2, gmst);
//
// // 2004-02-29:00:00:00Z, MJD = 53064, UT1-UTC = -0.4175723
// utc1 = DJM0 + 53064.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// iauUtcut1(utc1, utc2, -0.4175723, &ut11, &ut12);
// gmst = iauGmst06(ut11, ut12, tt1, tt2);
// printf("iaugmst06(%.20g, %.20g, %.20g, %.20g)\n --> %.20g\n",
// ut11, ut12, tt1, tt2, gmst);
//
// the output of this test reads:
// iaugmst06(2453049.5, -4.7378576388888813016e-06, 2453049.5, 0.00074287037037037029902)
// --> 2.5021977784096232078
// iaugmst06(2453064.5, -4.8330127314815448519e-06, 2453064.5, 0.00074287037037037029902)
// --> 2.7602390556555129741
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
final TimeScalarFunction gmst06 = IERSConventions.IERS_2010.getGMSTFunction(ut1);
AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
double gmst = MathUtils.normalizeAngle(gmst06.value(date), 0.0);
Assert.assertEquals(2.5021977784096232078, gmst, 1.0e-15);
date = new AbsoluteDate(2004, 2, 29, TimeScalesFactory.getUTC());
gmst = MathUtils.normalizeAngle(gmst06.value(date), 0.0);
Assert.assertEquals(2.7602390556555129741, gmst, 3.0e-15);
}
@Test
public void testERA1996FieldConsistency() throws OrekitException {
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_1996, true);
checkScalarFunctionConsistency(IERSConventions.IERS_1996.getEarthOrientationAngleFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 2.0e-15, 8.0e-13);
}
@Test
public void testERA2003FieldConsistency() throws OrekitException {
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2003, true);
checkScalarFunctionConsistency(IERSConventions.IERS_2003.getEarthOrientationAngleFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 2.0e-15, 8.0e-13);
}
@Test
public void testERA2010FieldConsistency() throws OrekitException {
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
checkScalarFunctionConsistency(IERSConventions.IERS_2010.getEarthOrientationAngleFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 2.0e-15, 8.0e-13);
}
@Test
public void testERASofa() throws OrekitException {
// the reference value has been computed using the March 2012 version of the SOFA library
// http://www.iausofa.org/2012_0301_C.html, with the following code
//
// double tai1, tai2, ut11, ut12, era, taiutc;
// taiutc = 32.0;
//
// // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
// tai1 = DJM0 + 53049.0;
// tai2 = taiutc / DAYSEC;
// iauTaiut1(tai1, tai2, -0.4093509 - taiutc, &ut11, &ut12);
// era = iauEra00(ut11, ut12);
// printf("iauera00(%.20g, %.20g)\n --> %.20g\n", ut11, ut12, era);
//
// // 2004-02-29:00:00:00Z, MJD = 53064, UT1-UTC = -0.4175723
// tai1 = DJM0 + 53064.0;
// tai2 = taiutc / DAYSEC;
// iauTaiut1(tai1, tai2, -0.4175723 - taiutc, &ut11, &ut12);
// era = iauEra00(ut11, ut12);
// printf("iauera00(%.20g, %.20g)\n --> %.20g\n", ut11, ut12, era);
//
// the output of this test reads:
// iauera00(2453049.5, -4.7378576388888813016e-06)
// --> 2.5012766511308228701
// iauera00(2453064.5, -4.8330127314815448519e-06)
// --> 2.7593087452455264952
final TimeScale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2003, true);
final TimeScalarFunction era00 =
IERSConventions.IERS_2003.getEarthOrientationAngleFunction(ut1);
AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
double era = MathUtils.normalizeAngle(era00.value(date), 0.0);
Assert.assertEquals(2.5012766511308228701, era, 1.0e-15);
date = new AbsoluteDate(2004, 2, 29, TimeScalesFactory.getUTC());
era = MathUtils.normalizeAngle(era00.value(date), 0.0);
Assert.assertEquals(2.7593087452455264952, era, 1.0e-15);
}
@Test
public void testGST94FieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_1996, true);
checkScalarFunctionConsistency(IERSConventions.IERS_1996.getGASTFunction(TimeScalesFactory.getUT1(eopHistory),
eopHistory),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 9.0e-16, 8.0e-13);
}
@Test
public void testGST94FieldConsistencyNoEOP() throws OrekitException {
checkScalarFunctionConsistency(IERSConventions.IERS_1996.getGASTFunction(TimeScalesFactory.getUT1(null), null),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 9.0e-16, 2.0e-16);
}
@Test
public void testGST94Sofa() throws OrekitException {
// the reference value has been computed using the March 2012 version of the SOFA library
// http://www.iausofa.org/2012_0301_C.html, with the following code
//
// double utc1, utc2, ut11, ut12, tai1, tai2, tt1, tt2, gmst82, eqeq94;
//
// // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
// utc1 = DJM0 + 53049.0;
// utc2 = 0.0;
// iauUtcut1(utc1, utc2, -0.4093509, &ut11, &ut12);
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// gmst82 = iauGmst82(ut11, ut12);
// eqeq94 = iauEqeq94(tt1, tt2);
// printf("iauGmst82(%.20g, %.20g)\n --> %.20g\n", ut11, ut12, gmst82);
// printf("iauEqeq94(%.20g, %.20g)\n --> %.20g\n", tt1, tt2, eqeq94);
// printf(" gmst82 + eqeq94 --> %.20g\n", gmst82 + eqeq94);
//
// // 2004-02-29:00:00:00Z, MJD = 53064, UT1-UTC = -0.4175723
// utc1 = DJM0 + 53064.0;
// utc2 = 0.0;
// iauUtcut1(utc1, utc2, -0.4175723, &ut11, &ut12);
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// gmst82 = iauGmst82(ut11, ut12);
// eqeq94 = iauEqeq94(tt1, tt2);
// printf("iauGmst82(%.20g, %.20g)\n --> %.20g\n", ut11, ut12, gmst82);
// printf("iauEqeq94(%.20g, %.20g)\n --> %.20g\n", tt1, tt2, eqeq94);
// printf(" gmst82 + eqeq94 --> %.20g\n", gmst82 + eqeq94);
//
// the output of this test reads:
// iauGmst82(2453049.5, -4.7378576388888813016e-06)
// --> 2.5021977627453466653
// iauEqeq94(2453049.5, 0.00074287037037037029902)
// --> -4.8671604682267536886e-05
// gmst82 + eqeq94 --> 2.5021490911406645274
// iauGmst82(2453064.5, -4.8330127314815448519e-06)
// --> 2.7602390405411441066
// iauEqeq94(2453064.5, 0.00074287037037037029902)
// --> -4.8893054690771762302e-05
// gmst82 + eqeq94 --> 2.7601901474864534158
// As can be seen in the code above, we didn't call iauGst94, because as
// stated in the function header comment in SOFA source files:
// "accuracy has been compromised for the sake of
// convenience in that UT is used instead of TDB (or TT) to compute
// the equation of the equinoxes."
// So we rather performed the date conversion and then called ourselves iauGmst82
// with a date in UTC and eqe94 with a date in TT, restoring full accuracy in the
// SOFA computation for this test.
// The thresholds below have been set up large enough to have the test pass with
// the default Orekit setting and the reference SOFA setting. There are implementation
// differences between the two libraries, as the Delaunay parameters are not the
// same (in Orekit, we are compliant with page 23 in chapter 5 of IERS conventions 1996.
// If the content of the IERS-conventions/1996/nutation-arguments.txt file by Orekit is
// changed to match SOFA setting instead of IERS conventions as follows:
//
// # Mean Anomaly of the Moon
// F1 ≡ l = 485866.733″ + 1717915922.633″t + 31.310″t² + 0.064″t³
//
// # Mean Anomaly of the Sun
// F2 ≡ l' = 1287099.804″ + 129596581.224″t − 0.577″t² − 0.012t³
//
// # L − Ω
// F3 ≡ F = 335778.877″ + 1739527263.137″t − 13.257″t² + 0.011″t³
//
// # Mean Elongation of the Moon from the Sun
// F4 ≡ D = 1072261.307″ + 1602961601.328″t − 6.891″t² + 0.019″t³
//
// # Mean Longitude of the Ascending Node of the Moon
// F5 ≡ Ω = 450160.280″ − 6962890.539″t + 7.455″t² + 0.008″t³
//
// then the thresholds for the test can be reduced to 4.2e-13 for the first test,
// and 4.7e-13 for the second test.
// We decided to stick with IERS published reference values for the default Orekit setting.
// The differences are nevertheless quite small (9e-11 radians is sub-millimeter level
// in low Earth orbit).
Utils.setLoaders(IERSConventions.IERS_1996,
Utils.buildEOPList(IERSConventions.IERS_1996, new double[][] {
{ 53047, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53048, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53049, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53050, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53051, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53052, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53053, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53054, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
// ...
{ 53059, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53060, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53061, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53062, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53063, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53064, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53065, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53066, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 }
}));
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_1996, true);
final TimeScalarFunction gst94 =
IERSConventions.IERS_1996.getGASTFunction(TimeScalesFactory.getUT1(eopHistory),
eopHistory);
AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
double gst = MathUtils.normalizeAngle(gst94.value(date), 0.0);
Assert.assertEquals(2.5021490911406645274, gst, 4.4e-11); // 4.2e-13 with SOFA values
date = new AbsoluteDate(2004, 2, 29, TimeScalesFactory.getUTC());
gst = MathUtils.normalizeAngle(gst94.value(date), 0.0);
Assert.assertEquals(2.7601901474864534158, gst, 9.0e-11); // 4.7e-13 with SOFA values
}
@Test
public void testGST00AFieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2003, true);
checkScalarFunctionConsistency(IERSConventions.IERS_2003.getGASTFunction(TimeScalesFactory.getUT1(eopHistory), eopHistory),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 2.0e-15, 8.0e-13);
}
@Test
public void testGST00AFieldConsistencyNoEOP() throws OrekitException {
checkScalarFunctionConsistency(IERSConventions.IERS_2003.getGASTFunction(TimeScalesFactory.getUT1(null), null),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 2.0e-15, 2.0e-16);
}
@Test
public void testGST00ASofa() throws OrekitException {
// the reference value has been computed using the March 2012 version of the SOFA library
// http://www.iausofa.org/2012_0301_C.html, with the following code
//
// double utc1, utc2, tai1, tai2, tt1, tt2, ut11, ut12, gst;
//
// // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
// utc1 = DJM0 + 53049.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// iauUtcut1(utc1, utc2, -0.4093509, &ut11, &ut12);
// gst = iauGst00a(ut11, ut12, tt1, tt2);
// printf("iaugst00a(%.20g, %.20g, %.20g, %.20g)\n --> %.20g\n",
// ut11, ut12, tt1, tt2, gst);
//
// // 2004-02-29:00:00:00Z, MJD = 53064, UT1-UTC = -0.4175723
// utc1 = DJM0 + 53064.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// iauUtcut1(utc1, utc2, -0.4175723, &ut11, &ut12);
// gst = iauGst00a(ut11, ut12, tt1, tt2);
// printf("iaugst00a(%.20g, %.20g, %.20g, %.20g)\n --> %.20g\n",
// ut11, ut12, tt1, tt2, gst);
//
// the output of this test reads:
// iaugst00a(2453049.5, -4.7378576388888813016e-06, 2453049.5, 0.00074287037037037029902)
// --> 2.5021491024360624778
// iaugst00a(2453064.5, -4.8330127314815448519e-06, 2453064.5, 0.00074287037037037029902)
// --> 2.7601901615614221619
Utils.setLoaders(IERSConventions.IERS_2003,
Utils.buildEOPList(IERSConventions.IERS_2003, new double[][] {
{ 53047, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53048, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53049, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53050, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53051, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53052, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53053, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53054, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
// ...
{ 53059, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53060, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53061, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53062, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53063, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53064, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53065, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53066, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 }
}));
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2003, true);
final TimeScalarFunction gst00a =
IERSConventions.IERS_2003.getGASTFunction(TimeScalesFactory.getUT1(eopHistory), eopHistory);
AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
double gst = MathUtils.normalizeAngle(gst00a.value(date), 0.0);
Assert.assertEquals(2.5021491024360624778, gst, 2.0e-13);
date = new AbsoluteDate(2004, 2, 29, TimeScalesFactory.getUTC());
gst = MathUtils.normalizeAngle(gst00a.value(date), 0.0);
Assert.assertEquals(2.7601901615614221619, gst, 3.0e-13);
}
@Test
public void testGST06FieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2010, true);
checkScalarFunctionConsistency(IERSConventions.IERS_2010.getGASTFunction(TimeScalesFactory.getUT1(eopHistory), eopHistory),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 2.0e-15, 8.0e-13);
}
@Test
public void testGST06FieldConsistencyNoEOP() throws OrekitException {
checkScalarFunctionConsistency(IERSConventions.IERS_2010.getGASTFunction(TimeScalesFactory.getUT1(null), null),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 1800.0, 10.0, 2.0e-15, 2.0e-16);
}
@Test
public void testGST06Sofa() throws OrekitException {
// the reference value has been computed using the March 2012 version of the SOFA library
// http://www.iausofa.org/2012_0301_C.html, with the following code
//
// double utc1, utc2, tai1, tai2, tt1, tt2, ut11, ut12, gst;
//
// // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
// utc1 = DJM0 + 53049.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// iauUtcut1(utc1, utc2, -0.4093509, &ut11, &ut12);
// gst = iauGst06a(ut11, ut12, tt1, tt2);
// printf("iaugst06a(%.20g, %.20g, %.20g, %.20g)\n --> %.20g\n",
// ut11, ut12, tt1, tt2, gst);
//
// // 2004-02-29:00:00:00Z, MJD = 53064, UT1-UTC = -0.4175723
// utc1 = DJM0 + 53064.0;
// utc2 = 0.0;
// iauUtctai(utc1, utc2, &tai1, &tai2);
// iauTaitt(tai1, tai2, &tt1, &tt2);
// iauUtcut1(utc1, utc2, -0.4175723, &ut11, &ut12);
// gst = iauGst06a(ut11, ut12, tt1, tt2);
// printf("iaugst06a(%.20g, %.20g, %.20g, %.20g)\n --> %.20g\n",
// ut11, ut12, tt1, tt2, gst);
//
// the output of this test reads:
// iaugst06a(2453049.5, -4.7378576388888813016e-06, 2453049.5, 0.00074287037037037029902)
// --> 2.5021491022006503435
// iaugst06a(2453064.5, -4.8330127314815448519e-06, 2453064.5, 0.00074287037037037029902)
// --> 2.7601901613234058885
Utils.setLoaders(IERSConventions.IERS_2010,
Utils.buildEOPList(IERSConventions.IERS_2010, new double[][] {
{ 53047, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53048, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53049, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53050, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53051, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53052, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53053, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53054, -0.4093509, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
// ...
{ 53059, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53060, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53061, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53062, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53063, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53064, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53065, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 },
{ 53066, -0.4175723, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 }
}));
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2010, true);
final TimeScalarFunction gst06 =
IERSConventions.IERS_2010.getGASTFunction(TimeScalesFactory.getUT1(eopHistory), eopHistory);
AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
double gst = MathUtils.normalizeAngle(gst06.value(date), 0.0);
Assert.assertEquals(2.5021491022006503435, gst, 1.3e-12);
date = new AbsoluteDate(2004, 2, 29, TimeScalesFactory.getUTC());
gst = MathUtils.normalizeAngle(gst06.value(date), 0.0);
Assert.assertEquals(2.7601901613234058885, gst, 1.2e-12);
}
@Test
public void testGMST2000vs82() throws OrekitException {
final TimeScalarFunction gmst82 =
IERSConventions.IERS_1996.getGMSTFunction(TimeScalesFactory.getUT1(IERSConventions.IERS_1996, true));
final TimeScalarFunction gmst00 =
IERSConventions.IERS_2003.getGMSTFunction(TimeScalesFactory.getUT1(IERSConventions.IERS_2003, true));
final DSFactory factory = new DSFactory(1, 1);
final FieldAbsoluteDate<DerivativeStructure> ds2000 =
FieldAbsoluteDate.getJ2000Epoch(factory.getDerivativeField());
for (double dt = 0; dt < 10 * Constants.JULIAN_YEAR; dt += 10 * Constants.JULIAN_DAY) {
FieldAbsoluteDate<DerivativeStructure> date = ds2000.shiftedBy(factory.variable(0, dt));
DerivativeStructure delta = gmst00.value(date).subtract(gmst82.value(date));
// GMST82 and GMST2000 are similar to about 15 milli-arcseconds between 2000 and 2010
Assert.assertEquals(0.0, MathUtils.normalizeAngle(delta.getValue(), 0.0), 7.1e-8);
Assert.assertEquals(0.0, delta.getPartialDerivative(1), 1.0e-15);
}
}
@Test
public void testGMST2000vs2006() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
final TimeScalarFunction gmst00 = IERSConventions.IERS_2003.getGMSTFunction(ut1);
final TimeScalarFunction gmst06 = IERSConventions.IERS_2010.getGMSTFunction(ut1);
final DSFactory factory = new DSFactory(1, 1);
final FieldAbsoluteDate<DerivativeStructure> ds2000 =
FieldAbsoluteDate.getJ2000Epoch(factory.getDerivativeField());
for (double dt = 0; dt < 10 * Constants.JULIAN_YEAR; dt += 10 * Constants.JULIAN_DAY) {
FieldAbsoluteDate<DerivativeStructure> date = ds2000.shiftedBy(factory.variable(0, dt));
DerivativeStructure delta = gmst06.value(date).subtract(gmst00.value(date));
// GMST2006 and GMST2000 are similar to about 0.15 milli-arcseconds between 2000 and 2010
Assert.assertEquals(0.0, MathUtils.normalizeAngle(delta.getValue(), 0.0), 7e-10);
Assert.assertEquals(0.0, delta.getPartialDerivative(1), 3.0e-18);
}
}
@Test
public void testIAU1994ResolutionC7Discontinuity() throws OrekitException {
TimeVectorFunction nutation = IERSConventions.IERS_1996.getNutationFunction();
AbsoluteDate switchDate = new AbsoluteDate(1997, 2, 27, TimeScalesFactory.getUTC());
double h = 0.01;
for (double dt = -1.0 - h / 2; dt <= 1.0 + h /2; dt += h) {
AbsoluteDate d = switchDate.shiftedBy(dt);
final double currentCorr = nutation.value(d)[2];
if (dt < 0) {
Assert.assertEquals(0.0, currentCorr, 1.0e-20);
} else {
Assert.assertEquals(-7.87098e-12, currentCorr, 1.0e-15);
}
}
}
@Test
public void testTidalCorrection1996() throws OrekitException {
// the reference value has been computed using interp_old.f from
// ftp://hpiers.obspm.fr/iers/models/ with the following driver program:
//
// PROGRAM OR_TEST
// IMPLICIT NONE
// INTEGER J, N
// PARAMETER (N = 4)
// INTEGER MJD(N)
// DOUBLE PRECISION TTTAI, TAIUTC
// PARAMETER (TAIUTC = 32.000D0)
// PARAMETER (TTTAI = 32.184D0)
// DOUBLE PRECISION RJD(N), X(N), Y(N), T(N), H(5)
// DOUBLE PRECISION RJDINT, XINT, YINT, TINT, CORX, CORY, CORT
// DATA(MJD(J), T(J), X(J), Y(J),
// & J=1,4)/
// & 52653, -0.2979055D0, -0.120344D0, 0.217095D0,
// & 52654, -0.2984238D0, -0.121680D0, 0.219400D0,
// & 52655, -0.2987682D0, -0.122915D0, 0.221760D0,
// & 52656, -0.2989957D0, -0.124248D0, 0.224294D0/
// C
// DATA(H(J),J=1,5)/0.0D0, 3600.0D0, 7200.0D0, 43200.0D0, 86400.0D0/
// C
// DO 10 J = 1, N
// RJD(J) = MJD(J) + (TTTAI + TAIUTC) / 86400.0D0
// 10 CONTINUE
// C
// DO 20 J = 1, 5
// RJDINT = RJD(2) + H(J) / 86400.0D0
// CALL INTERP(RJD,X,Y,T,N,RJDINT,XINT,YINT,TINT)
// WRITE(6, 30) H(J), TINT, XINT, YINT
// 20 CONTINUE
// 30 FORMAT(F7.1,3(1X, F20.17))
// C
// END PROGRAM
//
// the output of this test reads:
// 0.0 -0.29839889612705234 -0.12191552977388567 0.21921143351558756
// 3600.0 -0.29841696994736727 -0.12208276003864491 0.21925416583607277
// 7200.0 -0.29843402412052122 -0.12218102086455683 0.21930263880545320
// 43200.0 -0.29866785146390035 -0.12250027826538630 0.22103779809979979
// 86400.0 -0.29874248853173840 -0.12308592577174847 0.22161565557764881
Utils.setLoaders(IERSConventions.IERS_1996,
Utils.buildEOPList(IERSConventions.IERS_1996, new double[][] {
{ 52653, -0.2979055, 0.0005744, -0.120344, 0.217095, 0.0, 0.0, 0.0, 0.0 },
{ 52654, -0.2984238, 0.0004224, -0.121680, 0.219400, 0.0, 0.0, 0.0, 0.0 },
{ 52655, -0.2987682, 0.0002878, -0.122915, 0.221760, 0.0, 0.0, 0.0, 0.0 },
{ 52656, -0.2989957, 0.0001778, -0.124248, 0.224294, 0.0, 0.0, 0.0, 0.0 }
}));
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_1996, false);
final AbsoluteDate t0 = new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, 52654),
TimeScalesFactory.getUTC());
for (double[] row : new double[][] {
{ 0.0, -0.29839889612705234, -0.12191552977388567, 0.21921143351558756 },
{ 3600.0, -0.29841696994736727, -0.12208276003864491, 0.21925416583607277 },
{ 7200.0, -0.29843402412052122, -0.12218102086455683, 0.21930263880545320 },
{ 43200.0, -0.29866785146390035, -0.12250027826538630, 0.22103779809979979 },
{ 86400.0, -0.29874248853173840, -0.12308592577174847, 0.22161565557764881 }
}) {
AbsoluteDate date = t0.shiftedBy(row[0]);
Assert.assertEquals(row[1], eopHistory.getUT1MinusUTC(date), 8.8e-11);
Assert.assertEquals(row[2] * Constants.ARC_SECONDS_TO_RADIANS,
eopHistory.getPoleCorrection(date).getXp(),
3.2e-14);
Assert.assertEquals(row[3] * Constants.ARC_SECONDS_TO_RADIANS,
eopHistory.getPoleCorrection(date).getYp(),
8.2e-15);
}
}
@Test
public void testTidalCorrection2003() throws OrekitException {
// the reference value has been computed using the September 2007 version
// of interp.f from ftp://hpiers.obspm.fr/iers/models/ adding input/output
// parameters for LOD (which was already computed in the underlying routines),
// with the following driver program:
//
// PROGRAM OR_TEST
// IMPLICIT NONE
// INTEGER J, N
// PARAMETER (N = 4)
// INTEGER MJD(N)
// DOUBLE PRECISION TTTAI, TAIUTC
// PARAMETER (TAIUTC = 32.000D0)
// PARAMETER (TTTAI = 32.184D0)
// DOUBLE PRECISION RJD(N), UT1(N), LOD(N), X(N), Y(N), H(5)
// DOUBLE PRECISION RJD_INT, UT1_INT, LOD_INT, X_INT, Y_INT
// DATA(MJD(J), UT1(J), LOD(J), X(J), Y(J),
// & J=1,4)/
// & 52653, -0.2979055D0, 0.0005744D0, -0.120344D0, 0.217095D0,
// & 52654, -0.2984238D0, 0.0004224D0, -0.121680D0, 0.219400D0,
// & 52655, -0.2987682D0, 0.0002878D0, -0.122915D0, 0.221760D0,
// & 52656, -0.2989957D0, 0.0001778D0, -0.124248D0, 0.224294D0/
// C
// DATA(H(J),J=1,5)/0.0D0, 3600.0D0, 7200.0D0, 43200.0D0, 86400.0D0/
// C
// DO 10 J = 1, N
// RJD(J) = MJD(J) + (TTTAI + TAIUTC) / 86400.0D0
// 10 CONTINUE
// C
// DO 20 J = 1, 5
// RJD_INT = RJD(2) + H(J) / 86400.0D0
// CALL INTERP(RJD,X,Y,UT1,LOD,N,
// & RJD_INT,X_INT,Y_INT,UT1_INT,LOD_INT)
// WRITE(6, 30) H(J),UT1_INT,LOD_INT,X_INT,Y_INT
// 20 CONTINUE
// 30 FORMAT(F7.1,4(1X, F20.17))
// C
// END PROGRAM
//
// the output of this test reads:
// 0.0 -0.29840026968370659 0.00045312852893139 -0.12196223480123573 0.21922730818562719
// 3600.0 -0.29841834564816189 0.00041710864863793 -0.12213345007640604 0.21927433626001305
// 7200.0 -0.29843503870494986 0.00039207574457087 -0.12222881007999241 0.21932415788122142
// 43200.0 -0.29866930257052676 0.00042895046506082 -0.12247697694276605 0.22105450666130921
// 86400.0 -0.29874235341010519 0.00035460263868306 -0.12312252389660779 0.22161364352515728
Utils.setLoaders(IERSConventions.IERS_2003,
Utils.buildEOPList(IERSConventions.IERS_2003, new double[][] {
{ 52653, -0.2979055, 0.0005744, -0.120344, 0.217095, 0.0, 0.0, 0.0, 0.0 },
{ 52654, -0.2984238, 0.0004224, -0.121680, 0.219400, 0.0, 0.0, 0.0, 0.0 },
{ 52655, -0.2987682, 0.0002878, -0.122915, 0.221760, 0.0, 0.0, 0.0, 0.0 },
{ 52656, -0.2989957, 0.0001778, -0.124248, 0.224294, 0.0, 0.0, 0.0, 0.0 }
}));
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2003, false);
final AbsoluteDate t0 = new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, 52654),
TimeScalesFactory.getUTC());
for (double[] row : new double[][] {
{ 0.0, -0.29840026968370659, 0.00045312852893139, -0.12196223480123573, 0.21922730818562719 },
{ 3600.0, -0.29841834564816189, 0.00041710864863793, -0.12213345007640604, 0.21927433626001305 },
{ 7200.0, -0.29843503870494986, 0.00039207574457087, -0.12222881007999241, 0.21932415788122142 },
{ 43200.0, -0.29866930257052676, 0.00042895046506082, -0.12247697694276605, 0.22105450666130921 },
{ 86400.0, -0.29874235341010519, 0.00035460263868306, -0.12312252389660779, 0.22161364352515728 }
}) {
AbsoluteDate date = t0.shiftedBy(row[0]);
Assert.assertEquals(row[1], eopHistory.getUT1MinusUTC(date), 4.3e-8);
Assert.assertEquals(row[2], eopHistory.getLOD(date), 1.4e-7);
Assert.assertEquals(row[3] * Constants.ARC_SECONDS_TO_RADIANS,
eopHistory.getPoleCorrection(date).getXp(),
1.6e-10);
Assert.assertEquals(row[4] * Constants.ARC_SECONDS_TO_RADIANS,
eopHistory.getPoleCorrection(date).getYp(),
0.7e-10);
}
}
@Test
public void testTidalCorrection2010() throws OrekitException {
// the reference value has been computed using the September 2007 version
// of interp.f from ftp://hpiers.obspm.fr/iers/models/ adding input/output
// parameters for LOD (which was already computed in the underlying routines),
// with the following driver program:
//
// PROGRAM OR_TEST
// IMPLICIT NONE
// INTEGER J, N
// PARAMETER (N = 4)
// INTEGER MJD(N)
// DOUBLE PRECISION TTTAI, TAIUTC
// PARAMETER (TAIUTC = 32.000D0)
// PARAMETER (TTTAI = 32.184D0)
// DOUBLE PRECISION RJD(N), UT1(N), LOD(N), X(N), Y(N), H(5)
// DOUBLE PRECISION RJD_INT, UT1_INT, LOD_INT, X_INT, Y_INT
// DATA(MJD(J), UT1(J), LOD(J), X(J), Y(J),
// & J=1,4)/
// & 52653, -0.2979055D0, 0.0005744D0, -0.120344D0, 0.217095D0,
// & 52654, -0.2984238D0, 0.0004224D0, -0.121680D0, 0.219400D0,
// & 52655, -0.2987682D0, 0.0002878D0, -0.122915D0, 0.221760D0,
// & 52656, -0.2989957D0, 0.0001778D0, -0.124248D0, 0.224294D0/
// C
// DATA(H(J),J=1,5)/0.0D0, 3600.0D0, 7200.0D0, 43200.0D0, 86400.0D0/
// C
// DO 10 J = 1, N
// RJD(J) = MJD(J) + (TTTAI + TAIUTC) / 86400.0D0
// 10 CONTINUE
// C
// DO 20 J = 1, 5
// RJD_INT = RJD(2) + H(J) / 86400.0D0
// CALL INTERP(RJD,X,Y,UT1,LOD,N,
// & RJD_INT,X_INT,Y_INT,UT1_INT,LOD_INT)
// WRITE(6, 30) H(J),UT1_INT,LOD_INT,X_INT,Y_INT
// 20 CONTINUE
// 30 FORMAT(F7.1,4(1X, F20.17))
// C
// END PROGRAM
//
// the output of this test reads:
// 0.0 -0.29840026968370659 0.00045312852893139 -0.12196223480123573 0.21922730818562719
// 3600.0 -0.29841834564816189 0.00041710864863793 -0.12213345007640604 0.21927433626001305
// 7200.0 -0.29843503870494986 0.00039207574457087 -0.12222881007999241 0.21932415788122142
// 43200.0 -0.29866930257052676 0.00042895046506082 -0.12247697694276605 0.22105450666130921
// 86400.0 -0.29874235341010519 0.00035460263868306 -0.12312252389660779 0.22161364352515728
Utils.setLoaders(IERSConventions.IERS_2010,
Utils.buildEOPList(IERSConventions.IERS_2010, new double[][] {
{ 52653, -0.2979055, 0.0005744, -0.120344, 0.217095, 0.0, 0.0, 0.0, 0.0 },
{ 52654, -0.2984238, 0.0004224, -0.121680, 0.219400, 0.0, 0.0, 0.0, 0.0 },
{ 52655, -0.2987682, 0.0002878, -0.122915, 0.221760, 0.0, 0.0, 0.0, 0.0 },
{ 52656, -0.2989957, 0.0001778, -0.124248, 0.224294, 0.0, 0.0, 0.0, 0.0 }
}));
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2010, false);
final AbsoluteDate t0 = new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, 52654),
TimeScalesFactory.getUTC());
for (double[] row : new double[][] {
{ 0.0, -0.29840026968370659, 0.00045312852893139, -0.12196223480123573, 0.21922730818562719 },
{ 3600.0, -0.29841834564816189, 0.00041710864863793, -0.12213345007640604, 0.21927433626001305 },
{ 7200.0, -0.29843503870494986, 0.00039207574457087, -0.12222881007999241, 0.21932415788122142 },
{ 43200.0, -0.29866930257052676, 0.00042895046506082, -0.12247697694276605, 0.22105450666130921 },
{ 86400.0, -0.29874235341010519, 0.00035460263868306, -0.12312252389660779, 0.22161364352515728 }
}) {
AbsoluteDate date = t0.shiftedBy(row[0]);
Assert.assertEquals(row[1], eopHistory.getUT1MinusUTC(date), 2.5e-12);
Assert.assertEquals(row[2], eopHistory.getLOD(date), 4.3e-11);
Assert.assertEquals(row[3] * Constants.ARC_SECONDS_TO_RADIANS,
eopHistory.getPoleCorrection(date).getXp(),
1.6e-10);
Assert.assertEquals(row[4] * Constants.ARC_SECONDS_TO_RADIANS,
eopHistory.getPoleCorrection(date).getYp(),
0.7e-10);
}
}
@Test
public void testGMSTRate1996() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_1996, true);
checkGMSTRate(IERSConventions.IERS_1996.getGMSTFunction(ut1),
IERSConventions.IERS_1996.getGMSTRateFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 8.0e-13);
}
@Test
public void testGMSTRate2003() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2003, true);
checkGMSTRate(IERSConventions.IERS_2003.getGMSTFunction(ut1),
IERSConventions.IERS_2003.getGMSTRateFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 8.0e-13);
}
@Test
public void testGMSTRate2010() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
checkGMSTRate(IERSConventions.IERS_2010.getGMSTFunction(ut1),
IERSConventions.IERS_2010.getGMSTRateFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 8.0e-13);
}
private void checkGMSTRate(final TimeScalarFunction gmst, final TimeScalarFunction gmstRate,
final AbsoluteDate date, final double span, final double sampleStep,
final double h, final double tolerance)
throws OrekitException {
UnivariateDifferentiableFunction differentiated =
new FiniteDifferencesDifferentiator(4, h).differentiate(new UnivariateFunction() {
@Override
public double value(final double dt) {
return gmst.value(date.shiftedBy(dt));
}
});
DSFactory factory = new DSFactory(1, 1);
double maxRateError = 0;
for (double dt = 0; dt < span; dt += sampleStep) {
double rateRef = differentiated.value(factory.variable(0, dt)).getPartialDerivative(1);
double rate = gmstRate.value(date.shiftedBy(dt));
maxRateError = FastMath.max(maxRateError, FastMath.abs(rateRef - rate));
}
Assert.assertEquals(0, maxRateError, tolerance);
}
@Test
public void testFieldGMSTRate1996() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_1996, true);
checkFieldGMSTRate(IERSConventions.IERS_1996.getGMSTFunction(ut1),
IERSConventions.IERS_1996.getGMSTRateFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, Double.MIN_VALUE);
}
@Test
public void testFieldGMSTRate2003() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2003, true);
checkFieldGMSTRate(IERSConventions.IERS_2003.getGMSTFunction(ut1),
IERSConventions.IERS_2003.getGMSTRateFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, Double.MIN_VALUE);
}
@Test
public void testFieldGMSTRate2010() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
checkFieldGMSTRate(IERSConventions.IERS_2010.getGMSTFunction(ut1),
IERSConventions.IERS_2010.getGMSTRateFunction(ut1),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, Double.MIN_VALUE);
}
private void checkFieldGMSTRate(final TimeScalarFunction gmst, final TimeScalarFunction gmstRate,
final AbsoluteDate date, final double span, final double sampleStep,
final double h, final double tolerance)
throws OrekitException {
double maxError = 0;
for (double dt = 0; dt < span; dt += sampleStep) {
double rateDouble = gmstRate.value(date.shiftedBy(dt));
double rateDecimal64 = gmstRate.value(new FieldAbsoluteDate<>(date, new Decimal64(dt))).doubleValue();
maxError = FastMath.max(maxError, FastMath.abs(rateDouble - rateDecimal64));
}
Assert.assertEquals(0, maxError, tolerance);
}
@Test
public void testPrecessionFunction1996FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_1996.getPrecessionFunction(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-22, 3.0e-19);
}
@Test
public void testPrecessionFunction2003FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_2003.getPrecessionFunction(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 6.0e-17, 6.0e-18);
}
@Test
public void testPrecessionFunction2010FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_2010.getPrecessionFunction(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 6.0e-17, 6.0e-18);
}
@Test
public void testNutationFunction1996FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_1996.getNutationFunction(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-19, 4.0e-21);
}
@Test
public void testNutationFunction2003FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_2003.getNutationFunction(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 3.0e-19, 6.0e-21);
}
@Test
public void testNutationFunction2010FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_2010.getNutationFunction(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 5.0e-19, 6.0e-21);
}
@Test
public void testXYSpXY2Function1996FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_1996.getXYSpXY2Function(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 6.0e-20, 2.0e-21);
}
@Test
public void testXYSpXY2Function2003FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_2003.getXYSpXY2Function(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-19, 3.0e-21);
}
@Test
public void testXYSpXY2Function2010FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_2010.getXYSpXY2Function(), 3,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-19, 3.0e-21);
}
@Test
public void testMeanObliquityFunction1996FieldConsistency() throws OrekitException {
checkScalarFunctionConsistency(IERSConventions.IERS_1996.getMeanObliquityFunction(),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 6.0e-17, 6.0e-18);
}
@Test
public void testMeanObliquityFunction2003FieldConsistency() throws OrekitException {
checkScalarFunctionConsistency(IERSConventions.IERS_2003.getMeanObliquityFunction(),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 6.0e-17, 6.0e-18);
}
@Test
public void testMeanObliquityFunction2010FieldConsistency() throws OrekitException {
checkScalarFunctionConsistency(IERSConventions.IERS_2010.getMeanObliquityFunction(),
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 6.0e-17, 6.0e-18);
}
@Test
public void testEOPTidalCorrection1996FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_1996.getEOPTidalCorrection(), 4,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-17, 6.0e-20);
}
@Test
public void testEOPTidalCorrection2003FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_2003.getEOPTidalCorrection(), 4,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-17, 2.0e-19);
}
@Test
public void testEOPTidalCorrection2010FieldConsistency() throws OrekitException {
checkVectorFunctionConsistency(IERSConventions.IERS_2010.getEOPTidalCorrection(), 4,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-17, 2.0e-19);
}
@Test
public void testTideFrequencyDependenceFunction1996FieldConsistency() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_1996, true);
checkVectorFunctionConsistency(IERSConventions.IERS_1996.getTideFrequencyDependenceFunction(ut1), 5,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 4.0e-24, 4.0e-22);
}
@Test
public void testTideFrequencyDependenceFunction2003FieldConsistency() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2003, true);
checkVectorFunctionConsistency(IERSConventions.IERS_2003.getTideFrequencyDependenceFunction(ut1), 5,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 4.0e-24, 4.0e-22);
}
@Test
public void testTideFrequencyDependenceFunction2010FieldConsistency() throws OrekitException {
final UT1Scale ut1 = TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true);
checkVectorFunctionConsistency(IERSConventions.IERS_2010.getTideFrequencyDependenceFunction(ut1), 5,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 4.0e-24, 4.0e-22);
}
@Test
public void testSolidPoleTide1996FieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_1996, false);
checkVectorFunctionConsistency(IERSConventions.IERS_1996.getSolidPoleTide(eopHistory), 2,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 3.0e-25, 4.0e-26);
}
@Test
public void testSolidPoleTide2003FieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2003, false);
checkVectorFunctionConsistency(IERSConventions.IERS_2003.getSolidPoleTide(eopHistory), 2,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-25, 3.0e-26);
}
@Test
public void testSolidPoleTide2010FieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2010, false);
checkVectorFunctionConsistency(IERSConventions.IERS_2010.getSolidPoleTide(eopHistory), 2,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-25, 2.0e-26);
}
@Test
public void testOceanPoleTide1996FieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_1996, false);
checkVectorFunctionConsistency(IERSConventions.IERS_1996.getOceanPoleTide(eopHistory), 2,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, Double.MIN_VALUE, Double.MIN_VALUE);
}
@Test
public void testOceanPoleTide2003FieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2003, false);
checkVectorFunctionConsistency(IERSConventions.IERS_2003.getOceanPoleTide(eopHistory), 2,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, Double.MIN_VALUE, Double.MIN_VALUE);
}
@Test
public void testOceanPoleTide2010FieldConsistency() throws OrekitException {
EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2010, false);
checkVectorFunctionConsistency(IERSConventions.IERS_2010.getOceanPoleTide(eopHistory), 2,
AbsoluteDate.J2000_EPOCH.shiftedBy(-0.4 * Constants.JULIAN_DAY),
0.8 * Constants.JULIAN_DAY, 600.0, 10.0, 2.0e-26, 2.0e-27);
}
private void checkScalarFunctionConsistency(final TimeScalarFunction function,
final AbsoluteDate date, final double span, final double sampleStep,
final double h, final double valueTolerance, final double derivativeTolerance) {
UnivariateDifferentiableFunction differentiated =
new FiniteDifferencesDifferentiator(4, h).differentiate(new UnivariateFunction() {
@Override
public double value(final double dt) {
return function.value(date.shiftedBy(dt));
}
});
DSFactory factory = new DSFactory(1, 1);
FieldAbsoluteDate<DerivativeStructure> dsDate = new FieldAbsoluteDate<>(date, factory.constant(0.0));
double maxValueError = 0;
double maxDerivativeError = 0;
for (double dt = 0; dt < span; dt += sampleStep) {
DerivativeStructure dsdt = factory.variable(0, dt);
DerivativeStructure yRef = differentiated.value(dsdt);
DerivativeStructure y = function.value(dsDate.shiftedBy(dsdt));
maxValueError = FastMath.max(maxValueError,
FastMath.abs(yRef.getValue() - y.getValue()));
maxDerivativeError = FastMath.max(maxDerivativeError,
FastMath.abs(yRef.getPartialDerivative(1) - y.getPartialDerivative(1)));
}
Assert.assertEquals(0, maxValueError, valueTolerance);
Assert.assertEquals(0, maxDerivativeError, derivativeTolerance);
}
private void checkVectorFunctionConsistency(final TimeVectorFunction function, final int dimension,
final AbsoluteDate date, final double span, final double sampleStep,
final double h, final double valueTolerance, final double derivativeTolerance) {
UnivariateDifferentiableVectorFunction differentiated =
new FiniteDifferencesDifferentiator(4, h).differentiate(new UnivariateVectorFunction() {
@Override
public double[] value(final double dt) {
return function.value(date.shiftedBy(dt));
}
});
DSFactory factory = new DSFactory(1, 1);
FieldAbsoluteDate<DerivativeStructure> dsDate = new FieldAbsoluteDate<>(date, factory.constant(0.0));
double maxValueError = 0;
double maxDerivativeError = 0;
for (double dt = 0; dt < span; dt += sampleStep) {
DerivativeStructure dsdt = factory.variable(0, dt);
DerivativeStructure[] yRef = differentiated.value(dsdt);
DerivativeStructure[] y = function.value(dsDate.shiftedBy(dsdt));
Assert.assertEquals(dimension, yRef.length);
Assert.assertEquals(dimension, y.length);
for (int i = 0; i < dimension; ++i) {
maxValueError = FastMath.max(maxValueError,
FastMath.abs(yRef[i].getValue() - y[i].getValue()));
maxDerivativeError = FastMath.max(maxDerivativeError,
FastMath.abs(yRef[i].getPartialDerivative(1) - y[i].getPartialDerivative(1)));
}
}
Assert.assertEquals(0, maxValueError, valueTolerance);
Assert.assertEquals(0, maxDerivativeError, derivativeTolerance);
}
@Before
public void setUp() {
Utils.setDataRoot("compressed-data");
}
}