/* 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.data; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.hipparchus.analysis.UnivariateFunction; 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.Decimal64Field; import org.hipparchus.util.FastMath; import org.junit.Assert; import org.junit.Test; import org.orekit.Utils; import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitMessages; import org.orekit.frames.FramesFactory; import org.orekit.time.AbsoluteDate; import org.orekit.time.FieldAbsoluteDate; import org.orekit.time.TimeScale; import org.orekit.time.TimeScalesFactory; import org.orekit.utils.Constants; import org.orekit.utils.IERSConventions; public class PoissonSeriesParserTest { @Test(expected=OrekitException.class) public void testEmptyData() throws OrekitException { buildData(""); } @Test(expected=OrekitException.class) public void testNoCoeffData() throws OrekitException { buildData("this is NOT an IERS nutation model file\n"); } @Test(expected=OrekitException.class) public void testEmptyArrayData() throws OrekitException { buildData(" 0.0 + 0.0 t - 0.0 t^2 - 0.0 t^3 - 0.0 t^4 + 0.0 t^5\n"); } @Test(expected=OrekitException.class) public void testMissingTermData() throws OrekitException { buildData(" 0.0 + 0.0 t - 0.0 t^2 - 0.0 t^3 - 0.0 t^4 + 0.0 t^5\n" + "j = 0 Nb of terms = 1\n"); } private PoissonSeries buildData(String data) throws OrekitException { return new PoissonSeriesParser(0). withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). parse(new ByteArrayInputStream(data.getBytes()), "<file-content>" + data + "</file-content>"); } @Test(expected=OrekitException.class) public void testNoFile() throws OrekitException { InputStream stream = PoissonSeriesParserTest.class.getResourceAsStream("/org/orekit/resources/missing"); new PoissonSeriesParser(17). withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4). withFirstPlanetary(9). withSinCos(0, 2, 1.0, 3, 1.0). parse(stream, "missing"); } @Test public void testMissingSeries() throws OrekitException { try { String data = " 0.0 + 0.0 x - 0.0 x^2 - 0.0 x^3 - 0.0 x^4 + 0.0 x^5\n" + "j = 0 Nb of terms = 1\n" + "1 1.0 0.0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + "j = 1 Nb of terms = 1\n" + "2 1.0 0.0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + "j = 3 Nb of terms = 1\n" + "3 1.0 0.0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n"; new PoissonSeriesParser(17). withPolynomialPart('x', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4). withFirstPlanetary(9). withSinCos(0, 2, 1.0, 3, 1.0). parse(new ByteArrayInputStream(data.getBytes()), ""); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { Assert.assertEquals(OrekitMessages.MISSING_SERIE_J_IN_FILE, oe.getSpecifier()); Assert.assertEquals(2, oe.getParts()[0]); Assert.assertEquals(6, oe.getParts()[2]); } } @Test public void testMissingTerms() throws OrekitException { try { String data = " 0.0 + 0.0 x - 0.0 x^2 - 0.0 x^3 - 0.0 x^4 + 0.0 x^5\n" + "j = 0 Nb of terms = 1\n" + "1 1.0 0.0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + "j = 1 Nb of terms = 3\n" + "2 1.0 0.0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + "3 1.0 0.0 0 0 0 0 0 2 0 0 0 0 0 0 0 0\n" + "j = 2 Nb of terms = 1\n" + "4 1.0 0.0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n"; new PoissonSeriesParser(17). withPolynomialPart('x', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4). withFirstPlanetary(9). withSinCos(0, 2, 1.0, 3, 1.0). parse(new ByteArrayInputStream(data.getBytes()), ""); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { Assert.assertEquals(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, oe.getSpecifier()); } } @Test public void testSmall() throws OrekitException { String data = " 0.0 + 0.0 x - 0.0 x^2 - 0.0 x^3 - 0.0 x^4 + 0.0 x^5\n" + "j = 0 Nb of terms = 1\n" + "1 1.0 0.0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n"; PoissonSeries nd = new PoissonSeriesParser(17). withPolynomialPart('x', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4). withFirstPlanetary(9). withSinCos(0, 2, 1.0, 3, 1.0). parse(new ByteArrayInputStream(data.getBytes()), ""); Assert.assertEquals(1, nd.getNonPolynomialSize()); } @Test public void testSecondsMarkers() throws OrekitException { String data = " 0''.0 + 0''.0 t - 0''.0 t^2 - 0''.0 t^3 - 0''.0 t^4 + 0''.0 t^5\n" + "j = 0 Nb of terms = 1\n" + "1 1.0 0.0 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n"; PoissonSeries nd = new PoissonSeriesParser(17). withFirstPlanetary(9). withSinCos(0, 2, 1.0, 3, 1.0). withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4). parse(new ByteArrayInputStream(data.getBytes()), ""); Assert.assertEquals(1, nd.getNonPolynomialSize()); } @Test public void testExtract() throws OrekitException { String data = "Expression for the X coordinate of the CIP in the GCRS based on the IAU2000A\n" + "precession-nutation model\n" + "\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "X = polynomial part + non-polynomial part\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "Polynomial part (unit microarcsecond)\n" + "\n" + " -16616.99 + 2004191742.88 t - 427219.05 t^2 - 198620.54 t^3 - 46.05 t^4 + 5.98 t^5\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "Non-polynomial part (unit microarcsecond)\n" + "(ARG being for various combination of the fundamental arguments of the nutation theory)\n" + "\n" + " Sum_i[a_{s,0})_i * sin(ARG) + a_{c,0})_i * cos(ARG)] \n" + "\n" + "+ Sum_i)j=1,4 [a_{s,j})_i * t^j * sin(ARG) + a_{c,j})_i * cos(ARG)] * t^j]\n" + "\n" + "The Table below provides the values for a_{s,j})_i and a_{c,j})_i\n" + "\n" + "The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part) \n" + "and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + " i a_{s,j})_i a_{c,j})_i l l' F D Om L_Me L_Ve L_E L_Ma L_J L_Sa L_U L_Ne p_A\n" + "\n" + "----------------------------------------------------------------------\n" + "-16616.99 + 2004191742.88 t - 427219.05 t^2 - 198620.54 t^3 - 46.05 t^4 + 5.98 t^5\n" + "j = 0 Nb of terms = 2\n" + "\n" + " 1 -6844318.44 1328.67 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 2 0.11 0.00 0 0 4 -4 4 0 0 0 0 0 0 0 0 0\n" + "\n" + "j = 1 Nb of terms = 2\n" + "\n" + " 3 -3328.48 205833.15 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 4 0.00 -0.10 1 -1 -2 -2 -1 0 0 0 0 0 0 0 0 0\n" + "\n" + " j = 2 Nb of terms = 2\n" + "\n" + " 5 2038.00 82.26 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 6 -0.12 0.00 1 0 -2 -2 -1 0 0 0 0 0 0 0 0 0\n" + " \n" + " j = 3 Nb of terms = 2\n" + "\n" + " 7 1.76 -20.39 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 8 0.00 0.20 0 0 0 0 2 0 0 0 0 0 0 0 0 0\n" + "\n" + " j = 4 Nb of terms = 1\n" + " \n" + " 9 -0.10 -0.02 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n"; // despite there are 9 data lines above, there are only 5 different terms, // as some terms share the same Delaunay and planetary coefficients and are // therefore grouped together. The Delaunay arguments for the 5 terms are: // Ω, 4(F-D+Ω), l-l'-2(F+D)-Ω, l-2(F+D)-Ω and 2Ω Assert.assertEquals(5, new PoissonSeriesParser(17). withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4). withFirstPlanetary(9). withSinCos(0, 2, 1.0, 3, 1.0). parse(new ByteArrayInputStream(data.getBytes()), "dummy").getNonPolynomialSize()); } @Test public void testWrongIndex() throws OrekitException { String data = "Expression for the X coordinate of the CIP in the GCRS based on the IAU2000A\n" + "precession-nutation model\n" + "\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "X = polynomial part + non-polynomial part\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "Polynomial part (unit microarcsecond)\n" + "\n" + " -16616.99 + 2004191742.88 t - 427219.05 t^2 - 198620.54 t^3 - 46.05 t^4 + 5.98 t^5\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "Non-polynomial part (unit microarcsecond)\n" + "(ARG being for various combination of the fundamental arguments of the nutation theory)\n" + "\n" + " Sum_i[a_{s,0})_i * sin(ARG) + a_{c,0})_i * cos(ARG)] \n" + "\n" + "+ Sum_i)j=1,4 [a_{s,j})_i * t^j * sin(ARG) + a_{c,j})_i * cos(ARG)] * t^j]\n" + "\n" + "The Table below provides the values for a_{s,j})_i and a_{c,j})_i\n" + "\n" + "The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part) \n" + "and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + " i a_{s,j})_i a_{c,j})_i l l' F D Om L_Me L_Ve L_E L_Ma L_J L_Sa L_U L_Ne p_A\n" + "\n" + "----------------------------------------------------------------------\n" + "-16616.99 + 2004191742.88 t - 427219.05 t^2 - 198620.54 t^3 - 46.05 t^4 + 5.98 t^5\n" + "j = 0 Nb of terms = 2\n" + "\n" + " 1 -6844318.44 1328.67 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 2 0.11 0.00 0 0 4 -4 4 0 0 0 0 0 0 0 0 0\n" + "\n" + "j = 1 Nb of terms = 2\n" + "\n" + " 3 -3328.48 205833.15 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 4 0.00 -0.10 1 -1 -2 -2 -1 0 0 0 0 0 0 0 0 0\n" + "\n" + " j = 2 Nb of terms = 2\n" + "\n" + " 5 2038.00 82.26 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 6 -0.12 0.00 1 0 -2 -2 -1 0 0 0 0 0 0 0 0 0\n" + " \n" + " j = 3 Nb of terms = 2\n" + "\n" + " 7 1.76 -20.39 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 999 0.00 0.20 0 0 0 0 2 0 0 0 0 0 0 0 0 0\n" + "\n" + " j = 4 Nb of terms = 1\n" + " \n" + " 9 -0.10 -0.02 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n"; try { new PoissonSeriesParser(17). withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4). withFirstPlanetary(9). withSinCos(0, 2, 1.0, 3, 1.0). parse(new ByteArrayInputStream(data.getBytes()), "dummy"); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier()); Assert.assertEquals(53, oe.getParts()[0]); Assert.assertTrue(((String) oe.getParts()[2]).startsWith(" 999 0.00")); } } @Test public void testTruncated() throws OrekitException { String data = "Expression for the X coordinate of the CIP in the GCRS based on the IAU2000A\n" + "precession-nutation model\n" + "\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "X = polynomial part + non-polynomial part\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "Polynomial part (unit microarcsecond)\n" + "\n" + " -16616.99 + 2004191742.88 t - 427219.05 t^2 - 198620.54 t^3 - 46.05 t^4 + 5.98 t^5\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + "Non-polynomial part (unit microarcsecond)\n" + "(ARG being for various combination of the fundamental arguments of the nutation theory)\n" + "\n" + " Sum_i[a_{s,0})_i * sin(ARG) + a_{c,0})_i * cos(ARG)] \n" + "\n" + "+ Sum_i)j=1,4 [a_{s,j})_i * t^j * sin(ARG) + a_{c,j})_i * cos(ARG)] * t^j]\n" + "\n" + "The Table below provides the values for a_{s,j})_i and a_{c,j})_i\n" + "\n" + "The expressions for the fundamental arguments appearing in columns 4 to 8 (luni-solar part) \n" + "and in columns 6 to 17 (planetary part) are those of the IERS Conventions 2000\n" + "\n" + "----------------------------------------------------------------------\n" + "\n" + " i a_{s,j})_i a_{c,j})_i l l' F D Om L_Me L_Ve L_E L_Ma L_J L_Sa L_U L_Ne p_A\n" + "\n" + "----------------------------------------------------------------------\n" + "-16616.99 + 2004191742.88 t - 427219.05 t^2 - 198620.54 t^3 - 46.05 t^4 + 5.98 t^5\n" + "j = 0 Nb of terms = 2\n" + "\n" + " 1 -6844318.44 1328.67 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n" + " 2 0.11 0.00 0 0 4 -4 4 0 0 0 0 0 0 0 0 0\n" + "\n" + "j = 1 Nb of terms = 2\n" + "\n" + " 3 -3328.48 205833.15 0 0 0 0 1 0 0 0 0 0 0 0 0 0\n"; try { new PoissonSeriesParser(17). withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4). withFirstPlanetary(9). withSinCos(0, 2, 1.0, 3, 1.0). parse(new ByteArrayInputStream(data.getBytes()), "dummy"); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { Assert.assertEquals(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, oe.getSpecifier()); } } @Test public void testTrue1996Files() throws OrekitException { String directory = "/assets/org/orekit/IERS-conventions/"; PoissonSeriesParser parser = new PoissonSeriesParser(10). withFirstDelaunay(1). withSinCos(0, 7, 1.0, -1, 1.0). withSinCos(1, 8, 1.0, -1, 1.0); InputStream psiStream = getClass().getResourceAsStream(directory + "1996/tab5.1.txt"); Assert.assertEquals(106, parser.parse(psiStream, "1996/tab5.1.txt").getNonPolynomialSize()); parser = parser.withSinCos(0, -1, 1.0, 9, 1.0).withSinCos(1, -1, 1.0, 10, 1.0); InputStream epsilonStream = getClass().getResourceAsStream(directory + "1996/tab5.1.txt"); Assert.assertNotNull(parser.parse(epsilonStream, "1996/tab5.1.txt")); } @Test public void testTrue2003Files() throws OrekitException { String directory = "/assets/org/orekit/IERS-conventions/"; PoissonSeriesParser parser = new PoissonSeriesParser(17).withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4).withFirstPlanetary(9).withSinCos(0, 2, 1.0, 3, 1.0); InputStream xStream = getClass().getResourceAsStream(directory + "2003/tab5.2a.txt"); Assert.assertNotNull(parser.parse(xStream, "2003/tab5.2a.txt")); InputStream yStream = getClass().getResourceAsStream(directory + "2003/tab5.2b.txt"); Assert.assertNotNull(parser.parse(yStream, "2003/tab5.2b.txt")); InputStream zStream = getClass().getResourceAsStream(directory + "2003/tab5.2c.txt"); Assert.assertNotNull(parser.parse(zStream, "2003/tab5.2c.txt")); } @Test public void testTrue2010Files() throws OrekitException { String directory = "/assets/org/orekit/IERS-conventions/"; PoissonSeriesParser parser = new PoissonSeriesParser(17).withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4).withFirstPlanetary(9).withSinCos(0, 2, 1.0, 3, 1.0); InputStream xStream = getClass().getResourceAsStream(directory + "2010/tab5.2a.txt"); Assert.assertNotNull(parser.parse(xStream, "2010/tab5.2a.txt")); InputStream yStream = getClass().getResourceAsStream(directory + "2010/tab5.2b.txt"); Assert.assertNotNull(parser.parse(yStream, "2010/tab5.2b.txt")); InputStream zStream = getClass().getResourceAsStream(directory + "2010/tab5.2d.txt"); Assert.assertNotNull(parser.parse(zStream, "2010/tab5.2d.txt")); PoissonSeriesParser correctionParser = new PoissonSeriesParser(14).withFirstDelaunay(4).withSinCos(0, 11, 1.0, 12, 1.0); InputStream xCorrectionStream = getClass().getResourceAsStream(directory + "2010/tab5.1a.txt"); Assert.assertNotNull(correctionParser.parse(xCorrectionStream, "2010/tab5.1a.txt")); correctionParser = correctionParser.withSinCos(0, 13, 1.0, 14, 1.0); InputStream yCorrectionStream = getClass().getResourceAsStream(directory + "2010/tab5.1a.txt"); Assert.assertNotNull(correctionParser.parse(yCorrectionStream, "2010/tab5.1a.txt")); } @Test public void testCorruptedLDelaunayMultiplier() { checkCorrupted("/tides/tab6.5a-corrupted-l-Delaunay-multiplier.txt", "σ₁"); } @Test public void testCorruptedLPrimeDelaunayMultiplier() { checkCorrupted("/tides/tab6.5a-corrupted-lPrime-Delaunay-multiplier.txt", "Q₁"); } @Test public void testCorruptedFDelaunayMultiplier() { checkCorrupted("/tides/tab6.5a-corrupted-F-Delaunay-multiplier.txt", "Nτ₁"); } @Test public void testCorruptedDDelaunayMultiplier() { checkCorrupted("/tides/tab6.5a-corrupted-D-Delaunay-multiplier.txt", "2Q₁"); } @Test public void testCorruptedOmegaDelaunayMultiplier() { checkCorrupted("/tides/tab6.5a-corrupted-Omega-Delaunay-multiplier.txt", "τ₁"); } @Test public void testCorruptedDoodsonMultiplier() { checkCorrupted("/tides/tab6.5a-corrupted-Doodson-multiplier.txt", "Lk₁"); } @Test public void testCorruptedDoodsonNumber() { checkCorrupted("/tides/tab6.5a-corrupted-Doodson-number.txt", "No₁"); } private void checkCorrupted(String resourceName, String lineStart) { try { PoissonSeriesParser parser = new PoissonSeriesParser(18). withOptionalColumn(1). withDoodson(4, 3). withFirstDelaunay(10). withSinCos(0, 18, 1.0e-12, 17, 1.0e-12); parser.parse(getClass().getResourceAsStream(resourceName), resourceName); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { if (lineStart == null) { Assert.assertEquals(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, oe.getSpecifier()); } else { Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier()); Assert.assertTrue(((String) oe.getParts()[2]).trim().startsWith(lineStart)); } } catch (Exception e) { Assert.fail("wrong exception caught: " + e); } } @Test public void testGammaTauForbidden() throws OrekitException { try { new PoissonSeriesParser(18).withGamma(4).withDoodson(4, 3); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { Assert.assertEquals(OrekitMessages.CANNOT_PARSE_BOTH_TAU_AND_GAMMA, oe.getSpecifier()); } } @Test public void testTauGammaForbidden() throws OrekitException { try { new PoissonSeriesParser(18).withDoodson(4, 3).withGamma(4); Assert.fail("an exception should have been thrown"); } catch (OrekitException oe) { Assert.assertEquals(OrekitMessages.CANNOT_PARSE_BOTH_TAU_AND_GAMMA, oe.getSpecifier()); } } @Test public void testCompile() throws OrekitException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { String directory = "/assets/org/orekit/IERS-conventions/"; PoissonSeriesParser parser = new PoissonSeriesParser(17).withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4).withFirstPlanetary(9).withSinCos(0, 2, 1.0, 3, 1.0); InputStream xStream = getClass().getResourceAsStream(directory + "2010/tab5.2a.txt"); PoissonSeries xSeries = parser.parse(xStream, "2010/tab5.2a.txt"); InputStream yStream = getClass().getResourceAsStream(directory + "2010/tab5.2b.txt"); PoissonSeries ySeries = parser.parse(yStream, "2010/tab5.2b.txt"); InputStream zStream = getClass().getResourceAsStream(directory + "2010/tab5.2d.txt"); PoissonSeries sSeries = parser.parse(zStream, "2010/tab5.2d.txt"); PoissonSeries.CompiledSeries xysSeries = PoissonSeries.compile(xSeries, ySeries, sSeries); Method m = IERSConventions.class.getDeclaredMethod("getNutationArguments", TimeScale.class); m.setAccessible(true); FundamentalNutationArguments arguments = (FundamentalNutationArguments) m.invoke(IERSConventions.IERS_2010, (TimeScale) null); for (double dt = 0; dt < Constants.JULIAN_YEAR; dt += Constants.JULIAN_DAY) { AbsoluteDate date = AbsoluteDate.J2000_EPOCH.shiftedBy(dt); BodiesElements elements = arguments.evaluateAll(date); double x = xSeries.value(elements); double y = ySeries.value(elements); double s = sSeries.value(elements); double[] xys = xysSeries.value(elements); Assert.assertEquals(x, xys[0], 1.0e-15 * FastMath.abs(x)); Assert.assertEquals(y, xys[1], 1.0e-15 * FastMath.abs(y)); Assert.assertEquals(s, xys[2], 1.0e-15 * FastMath.abs(s)); } } @Test public void testDerivativesAsField() throws OrekitException { Utils.setDataRoot("regular-data"); String directory = "/assets/org/orekit/IERS-conventions/"; PoissonSeriesParser parser = new PoissonSeriesParser(17).withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4).withFirstPlanetary(9).withSinCos(0, 2, 1.0, 3, 1.0); PoissonSeries xSeries = parser.parse(getClass().getResourceAsStream(directory + "2010/tab5.2a.txt"), "2010/tab5.2a.txt"); PoissonSeries ySeries = parser.parse(getClass().getResourceAsStream(directory + "2010/tab5.2b.txt"), "2010/tab5.2b.txt"); PoissonSeries zSeries = parser.parse(getClass().getResourceAsStream(directory + "2010/tab5.2d.txt"), "2010/tab5.2d.txt"); TimeScale ut1 = TimeScalesFactory.getUT1(FramesFactory.getEOPHistory(IERSConventions.IERS_2010, true)); FundamentalNutationArguments arguments = IERSConventions.IERS_2010.getNutationArguments(ut1); Coordinate xCoordinate = new Coordinate(xSeries, arguments); Coordinate yCoordinate = new Coordinate(ySeries, arguments); Coordinate zCoordinate = new Coordinate(zSeries, arguments); UnivariateDifferentiableFunction dx = new FiniteDifferencesDifferentiator(4, 0.4).differentiate(xCoordinate); UnivariateDifferentiableFunction dy = new FiniteDifferencesDifferentiator(4, 0.4).differentiate(yCoordinate); UnivariateDifferentiableFunction dz = new FiniteDifferencesDifferentiator(4, 0.4).differentiate(zCoordinate); DSFactory factory = new DSFactory(1, 1); FieldAbsoluteDate<DerivativeStructure> ds2000 = FieldAbsoluteDate.getJ2000Epoch(factory.getDerivativeField()); for (double t = 0; t < Constants.JULIAN_DAY; t += 120) { final FieldAbsoluteDate<DerivativeStructure> date = ds2000.shiftedBy(factory.variable(0, t)); // direct computation of derivatives FieldBodiesElements<DerivativeStructure> elements = arguments.evaluateAll(date); Assert.assertEquals(0.0, elements.getDate().durationFrom(date).getValue(), 1.0e-15); DerivativeStructure xDirect = xSeries.value(elements); DerivativeStructure yDirect = ySeries.value(elements); DerivativeStructure zDirect = zSeries.value(elements); // finite differences computation of derivatives DerivativeStructure zero = factory.variable(0, 0.0); xCoordinate.setDate(date.toAbsoluteDate()); DerivativeStructure xFinite = dx.value(zero); yCoordinate.setDate(date.toAbsoluteDate()); DerivativeStructure yFinite = dy.value(zero); zCoordinate.setDate(date.toAbsoluteDate()); DerivativeStructure zFinite = dz.value(zero); Assert.assertEquals(xFinite.getValue(), xDirect.getValue(), FastMath.abs(7.0e-15 * xFinite.getValue())); Assert.assertEquals(xFinite.getPartialDerivative(1), xDirect.getPartialDerivative(1), FastMath.abs(2.0e-07 * xFinite.getPartialDerivative(1))); Assert.assertEquals(yFinite.getValue(), yDirect.getValue(), FastMath.abs(7.0e-15 * yFinite.getValue())); Assert.assertEquals(yFinite.getPartialDerivative(1), yDirect.getPartialDerivative(1), FastMath.abs(2.0e-07 * yFinite.getPartialDerivative(1))); Assert.assertEquals(zFinite.getValue(), zDirect.getValue(), FastMath.abs(7.0e-15 * zFinite.getValue())); Assert.assertEquals(zFinite.getPartialDerivative(1), zDirect.getPartialDerivative(1), FastMath.abs(2.0e-07 * zFinite.getPartialDerivative(1))); } } @Test public void testDerivativesFromDoubleAPI() throws OrekitException { Utils.setDataRoot("regular-data"); String directory = "/assets/org/orekit/IERS-conventions/"; PoissonSeriesParser parser = new PoissonSeriesParser(17).withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4).withFirstPlanetary(9).withSinCos(0, 2, 1.0, 3, 1.0); InputStream xStream = getClass().getResourceAsStream(directory + "2010/tab5.2a.txt"); PoissonSeries xSeries = parser.parse(xStream, "2010/tab5.2a.txt"); InputStream yStream = getClass().getResourceAsStream(directory + "2010/tab5.2b.txt"); PoissonSeries ySeries = parser.parse(yStream, "2010/tab5.2b.txt"); InputStream zStream = getClass().getResourceAsStream(directory + "2010/tab5.2d.txt"); PoissonSeries zSeries = parser.parse(zStream, "2010/tab5.2d.txt"); final PoissonSeries.CompiledSeries compiled = PoissonSeries.compile(xSeries, ySeries, zSeries); TimeScale ut1 = TimeScalesFactory.getUT1(FramesFactory.getEOPHistory(IERSConventions.IERS_2010, true)); final FundamentalNutationArguments arguments = IERSConventions.IERS_2010.getNutationArguments(ut1); UnivariateDifferentiableVectorFunction finite = new FiniteDifferencesDifferentiator(4, 0.4).differentiate((double t) -> compiled.value(arguments.evaluateAll(AbsoluteDate.J2000_EPOCH.shiftedBy(t)))); DSFactory factory = new DSFactory(1, 1); for (double t = 0; t < Constants.JULIAN_DAY; t += 120) { // computation of derivatives from API double[] dAPI = compiled.derivative(arguments.evaluateAll(AbsoluteDate.J2000_EPOCH.shiftedBy(t))); // finite differences computation of derivatives DerivativeStructure[] d = finite.value(factory.variable(0, t)); Assert.assertEquals(d.length, dAPI.length); for (int i = 0; i < d.length; ++i) { Assert.assertEquals(d[i].getPartialDerivative(1), dAPI[i], FastMath.abs(2.0e-7 * d[i].getPartialDerivative(1))); } } } @Test public void testDerivativesFromFieldAPI() throws OrekitException { Utils.setDataRoot("regular-data"); String directory = "/assets/org/orekit/IERS-conventions/"; PoissonSeriesParser parser = new PoissonSeriesParser(17).withPolynomialPart('t', PolynomialParser.Unit.NO_UNITS). withFirstDelaunay(4).withFirstPlanetary(9).withSinCos(0, 2, 1.0, 3, 1.0); InputStream xStream = getClass().getResourceAsStream(directory + "2010/tab5.2a.txt"); PoissonSeries xSeries = parser.parse(xStream, "2010/tab5.2a.txt"); InputStream yStream = getClass().getResourceAsStream(directory + "2010/tab5.2b.txt"); PoissonSeries ySeries = parser.parse(yStream, "2010/tab5.2b.txt"); InputStream zStream = getClass().getResourceAsStream(directory + "2010/tab5.2d.txt"); PoissonSeries zSeries = parser.parse(zStream, "2010/tab5.2d.txt"); final PoissonSeries.CompiledSeries compiled = PoissonSeries.compile(xSeries, ySeries, zSeries); TimeScale ut1 = TimeScalesFactory.getUT1(FramesFactory.getEOPHistory(IERSConventions.IERS_2010, true)); final FundamentalNutationArguments arguments = IERSConventions.IERS_2010.getNutationArguments(ut1); UnivariateDifferentiableVectorFunction finite = new FiniteDifferencesDifferentiator(4, 0.4).differentiate((double t) -> compiled.value(arguments.evaluateAll(AbsoluteDate.J2000_EPOCH.shiftedBy(t)))); DSFactory factory = new DSFactory(1, 1); for (double t = 0; t < Constants.JULIAN_DAY; t += 120) { // computation of derivatives from API Decimal64[] dAPI = compiled.derivative(arguments.evaluateAll(FieldAbsoluteDate.getJ2000Epoch(Decimal64Field.getInstance()).shiftedBy(t))); // finite differences computation of derivatives DerivativeStructure[] d = finite.value(factory.variable(0, t)); Assert.assertEquals(d.length, dAPI.length); for (int i = 0; i < d.length; ++i) { Assert.assertEquals(d[i].getPartialDerivative(1), dAPI[i].getReal(), FastMath.abs(2.0e-7 * d[i].getPartialDerivative(1))); } } } private static class Coordinate implements UnivariateFunction { private final PoissonSeries series; private final FundamentalNutationArguments arguments; private AbsoluteDate date; Coordinate(PoissonSeries series, FundamentalNutationArguments arguments) { this.series = series; this.arguments = arguments; this.date = AbsoluteDate.J2000_EPOCH; } void setDate(AbsoluteDate date) { this.date = date; } public double value(double x) { return series.value(arguments.evaluateAll(date.shiftedBy(x))); } } }