FundamentalNutationArguments.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.data;

  18. import java.io.BufferedReader;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.InputStreamReader;
  22. import java.io.Serializable;
  23. import java.util.ArrayList;
  24. import java.util.Arrays;
  25. import java.util.HashMap;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.regex.Matcher;
  29. import java.util.regex.Pattern;

  30. import org.hipparchus.RealFieldElement;
  31. import org.hipparchus.exception.DummyLocalizable;
  32. import org.hipparchus.util.FastMath;
  33. import org.orekit.errors.OrekitException;
  34. import org.orekit.errors.OrekitInternalError;
  35. import org.orekit.errors.OrekitMessages;
  36. import org.orekit.time.AbsoluteDate;
  37. import org.orekit.time.FieldAbsoluteDate;
  38. import org.orekit.time.TimeScalarFunction;
  39. import org.orekit.time.TimeScale;
  40. import org.orekit.utils.Constants;
  41. import org.orekit.utils.IERSConventions;

  42. /**
  43.  * Class computing the fundamental arguments for nutation and tides.
  44.  * <p>
  45.  * The fundamental arguments are split in two sets:
  46.  * </p>
  47.  * <ul>
  48.  *   <li>the Delaunay arguments for Moon and Sun effects</li>
  49.  *   <li>the planetary arguments for other planets</li>
  50.  * </ul>
  51.  *
  52.  * @author Luc Maisonobe
  53.  * @see SeriesTerm
  54.  * @see PoissonSeries
  55.  * @see BodiesElements
  56.  */
  57. public class FundamentalNutationArguments implements Serializable {

  58.     /** Serializable UID. */
  59.     private static final long serialVersionUID = 20131209L;

  60.     /** IERS conventions to use. */
  61.     private final IERSConventions conventions;

  62.     /** Time scale for GMST computation. */
  63.     private final TimeScale timeScale;

  64.     /** Function computing Greenwich Mean Sidereal Time. */
  65.     private final transient TimeScalarFunction gmstFunction;

  66.     /** Function computing Greenwich Mean Sidereal Time rate. */
  67.     private final transient TimeScalarFunction gmstRateFunction;

  68.     // luni-solar Delaunay arguments

  69.     /** Coefficients for mean anomaly of the Moon. */
  70.     private final double[] lCoefficients;

  71.     /** Coefficients for mean anomaly of the Sun. */
  72.     private final double[] lPrimeCoefficients;

  73.     /** Coefficients for L - Ω where L is the mean longitude of the Moon. */
  74.     private final double[] fCoefficients;

  75.     /** Coefficients for mean elongation of the Moon from the Sun. */
  76.     private final double[] dCoefficients;

  77.     /** Coefficients for mean longitude of the ascending node of the Moon. */
  78.     private final double[] omegaCoefficients;

  79.     // planetary nutation arguments

  80.     /** Coefficients for mean Mercury longitude. */
  81.     private final double[] lMeCoefficients;

  82.     /** Coefficients for mean Venus longitude. */
  83.     private final double[] lVeCoefficients;

  84.     /** Coefficients for mean Earth longitude. */
  85.     private final double[] lECoefficients;

  86.     /** Coefficients for mean Mars longitude. */
  87.     private final double[] lMaCoefficients;

  88.     /** Coefficients for mean Jupiter longitude. */
  89.     private final double[] lJCoefficients;

  90.     /** Coefficients for mean Saturn longitude. */
  91.     private final double[] lSaCoefficients;

  92.     /** Coefficients for mean Uranus longitude. */
  93.     private final double[] lUCoefficients;

  94.     /** Coefficients for mean Neptune longitude. */
  95.     private final double[] lNeCoefficients;

  96.     /** Coefficients for general accumulated precession. */
  97.     private final double[] paCoefficients;

  98.     /** Build a model of fundamental arguments from an IERS table file.
  99.      * @param conventions IERS conventions to use
  100.      * @param timeScale time scale for GMST computation
  101.      * (may be null if tide parameter γ = GMST + π is not needed)
  102.      * @param stream stream containing the IERS table
  103.      * @param name name of the resource file (for error messages only)
  104.      * @exception OrekitException if stream is null or the table cannot be parsed
  105.      */
  106.     public FundamentalNutationArguments(final IERSConventions conventions,
  107.                                         final TimeScale timeScale,
  108.                                         final InputStream stream, final String name)
  109.         throws OrekitException {
  110.         this(conventions, timeScale, parseCoefficients(stream, name));
  111.     }

  112.     /** Build a model of fundamental arguments from an IERS table file.
  113.      * @param conventions IERS conventions to use
  114.      * @param timeScale time scale for GMST computation
  115.      * (may be null if tide parameter γ = GMST + π is not needed)
  116.      * @param coefficients list of coefficients arrays (all 14 arrays must be provided,
  117.      * the 5 Delaunay first and the 9 planetary afterwards)
  118.      * @exception OrekitException if GMST function cannot be retrieved
  119.      * @since 6.1
  120.      */
  121.     public FundamentalNutationArguments(final IERSConventions conventions, final TimeScale timeScale,
  122.                                         final List<double[]> coefficients)
  123.         throws OrekitException {
  124.         this.conventions        = conventions;
  125.         this.timeScale          = timeScale;
  126.         this.gmstFunction       = (timeScale == null) ? null : conventions.getGMSTFunction(timeScale);
  127.         this.gmstRateFunction   = (timeScale == null) ? null : conventions.getGMSTRateFunction(timeScale);
  128.         this.lCoefficients      = coefficients.get( 0);
  129.         this.lPrimeCoefficients = coefficients.get( 1);
  130.         this.fCoefficients      = coefficients.get( 2);
  131.         this.dCoefficients      = coefficients.get( 3);
  132.         this.omegaCoefficients  = coefficients.get( 4);
  133.         this.lMeCoefficients    = coefficients.get( 5);
  134.         this.lVeCoefficients    = coefficients.get( 6);
  135.         this.lECoefficients     = coefficients.get( 7);
  136.         this.lMaCoefficients    = coefficients.get( 8);
  137.         this.lJCoefficients     = coefficients.get( 9);
  138.         this.lSaCoefficients    = coefficients.get(10);
  139.         this.lUCoefficients     = coefficients.get(11);
  140.         this.lNeCoefficients    = coefficients.get(12);
  141.         this.paCoefficients     = coefficients.get(13);
  142.     }

  143.     /** Parse coefficients.
  144.      * @param stream stream containing the IERS table
  145.      * @param name name of the resource file (for error messages only)
  146.      * @return list of coefficients arrays
  147.      * @exception OrekitException if stream is null or the table cannot be parsed
  148.      */
  149.     private static List<double[]> parseCoefficients(final InputStream stream, final String name)
  150.         throws OrekitException {

  151.         if (stream == null) {
  152.             throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, name);
  153.         }

  154.         try {

  155.             final DefinitionParser definitionParser = new DefinitionParser();

  156.             // setup the reader
  157.             final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
  158.             int lineNumber = 0;

  159.             // look for the reference date and the 14 polynomials
  160.             final int n = FundamentalName.values().length;
  161.             final Map<FundamentalName, double[]> polynomials = new HashMap<FundamentalName, double[]>(n);
  162.             for (String line = reader.readLine(); line != null; line = reader.readLine()) {
  163.                 lineNumber++;
  164.                 if (definitionParser.parseDefinition(line, lineNumber, name)) {
  165.                     polynomials.put(definitionParser.getParsedName(),
  166.                                     definitionParser.getParsedPolynomial());
  167.                 }
  168.             }

  169.             final List<double[]> coefficients = new ArrayList<double[]>(n);
  170.             coefficients.add(getCoefficients(FundamentalName.L,       polynomials, name));
  171.             coefficients.add(getCoefficients(FundamentalName.L_PRIME, polynomials, name));
  172.             coefficients.add(getCoefficients(FundamentalName.F,       polynomials, name));
  173.             coefficients.add(getCoefficients(FundamentalName.D,       polynomials, name));
  174.             coefficients.add(getCoefficients(FundamentalName.OMEGA,   polynomials, name));
  175.             if (polynomials.containsKey(FundamentalName.L_ME)) {
  176.                 // IERS conventions 2003 and later provide planetary nutation arguments
  177.                 coefficients.add(getCoefficients(FundamentalName.L_ME,    polynomials, name));
  178.                 coefficients.add(getCoefficients(FundamentalName.L_VE,    polynomials, name));
  179.                 coefficients.add(getCoefficients(FundamentalName.L_E,     polynomials, name));
  180.                 coefficients.add(getCoefficients(FundamentalName.L_MA,    polynomials, name));
  181.                 coefficients.add(getCoefficients(FundamentalName.L_J,     polynomials, name));
  182.                 coefficients.add(getCoefficients(FundamentalName.L_SA,    polynomials, name));
  183.                 coefficients.add(getCoefficients(FundamentalName.L_U,     polynomials, name));
  184.                 coefficients.add(getCoefficients(FundamentalName.L_NE,    polynomials, name));
  185.                 coefficients.add(getCoefficients(FundamentalName.PA,      polynomials, name));
  186.             } else {
  187.                 // IERS conventions 1996 and earlier don't provide planetary nutation arguments
  188.                 final double[] zero = new double[] {
  189.                     0.0
  190.                 };
  191.                 while (coefficients.size() < n) {
  192.                     coefficients.add(zero);
  193.                 }
  194.             }

  195.             return coefficients;

  196.         } catch (IOException ioe) {
  197.             throw new OrekitException(ioe, new DummyLocalizable(ioe.getMessage()));
  198.         }

  199.     }

  200.     /** Get the coefficients for a fundamental argument.
  201.      * @param argument fundamental argument
  202.      * @param polynomials map of the polynomials
  203.      * @param fileName name of the file from which the coefficients have been read
  204.      * @return polynomials coefficients (ordered from high degrees to low degrees)
  205.      * @exception OrekitException if the argument is not found
  206.      */
  207.     private static double[] getCoefficients(final FundamentalName argument,
  208.                                             final Map<FundamentalName, double[]> polynomials,
  209.                                             final String fileName)
  210.         throws OrekitException {
  211.         if (!polynomials.containsKey(argument)) {
  212.             throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, fileName);
  213.         }
  214.         return polynomials.get(argument);
  215.     }

  216.     /** Evaluate a polynomial.
  217.      * @param tc offset in Julian centuries
  218.      * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
  219.      * @return value of the polynomial
  220.      */
  221.     private double value(final double tc, final double[] coefficients) {
  222.         double value = 0;
  223.         for (int i = coefficients.length - 1; i >= 0; --i) {
  224.             value = coefficients[i] + tc * value;
  225.         }
  226.         return value;
  227.     }

  228.     /** Evaluate a polynomial time derivative.
  229.      * @param tc offset in Julian centuries
  230.      * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
  231.      * @return time derivative of the polynomial
  232.      */
  233.     private double derivative(final double tc, final double[] coefficients) {
  234.         double derivative = 0;
  235.         for (int i = coefficients.length - 1; i > 0; --i) {
  236.             derivative = i * coefficients[i] + tc * derivative;
  237.         }
  238.         return derivative / Constants.JULIAN_CENTURY;
  239.     }

  240.     /** Evaluate a polynomial.
  241.      * @param tc offset in Julian centuries
  242.      * @param <T> type of the field elements
  243.      * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
  244.      * @return value of the polynomial
  245.      */
  246.     private <T extends RealFieldElement<T>> T value(final T tc, final double[] coefficients) {
  247.         T value = tc.getField().getZero();
  248.         for (int i = coefficients.length - 1; i >= 0; --i) {
  249.             value = tc.multiply(value).add(coefficients[i]);
  250.         }
  251.         return value;
  252.     }

  253.     /** Evaluate a polynomial time derivative.
  254.      * @param tc offset in Julian centuries
  255.      * @param <T> type of the field elements
  256.      * @param coefficients polynomial coefficients (ordered from low degrees to high degrees)
  257.      * @return time derivative of the polynomial
  258.      */
  259.     private <T extends RealFieldElement<T>> T derivative(final T tc, final double[] coefficients) {
  260.         T derivative = tc.getField().getZero();
  261.         for (int i = coefficients.length - 1; i > 0; --i) {
  262.             derivative = tc.multiply(derivative).add(i * coefficients[i]);
  263.         }
  264.         return derivative.divide(Constants.JULIAN_CENTURY);
  265.     }

  266.     /** Evaluate all fundamental arguments for the current date (Delaunay plus planetary).
  267.      * @param date current date
  268.      * @return all fundamental arguments for the current date (Delaunay plus planetary)
  269.      */
  270.     public BodiesElements evaluateAll(final AbsoluteDate date) {

  271.         final double tc       = conventions.evaluateTC(date);
  272.         final double gamma    = gmstFunction == null ?
  273.                                 Double.NaN : gmstFunction.value(date) + FastMath.PI;
  274.         final double gammaDot = gmstRateFunction == null ?
  275.                                 Double.NaN : gmstRateFunction.value(date);

  276.         return new BodiesElements(date, tc, gamma, gammaDot,
  277.                                   value(tc, lCoefficients),           // mean anomaly of the Moon
  278.                                   derivative(tc, lCoefficients),      // mean anomaly of the Moon time derivative
  279.                                   value(tc, lPrimeCoefficients),      // mean anomaly of the Sun
  280.                                   derivative(tc, lPrimeCoefficients), // mean anomaly of the Sun time derivative
  281.                                   value(tc, fCoefficients),           // L - Ω where L is the mean longitude of the Moon
  282.                                   derivative(tc, fCoefficients),      // L - Ω where L is the mean longitude of the Moon time derivative
  283.                                   value(tc, dCoefficients),           // mean elongation of the Moon from the Sun
  284.                                   derivative(tc, dCoefficients),      // mean elongation of the Moon from the Sun time derivative
  285.                                   value(tc, omegaCoefficients),       // mean longitude of the ascending node of the Moon
  286.                                   derivative(tc, omegaCoefficients),  // mean longitude of the ascending node of the Moon time derivative
  287.                                   value(tc, lMeCoefficients),         // mean Mercury longitude
  288.                                   derivative(tc, lMeCoefficients),    // mean Mercury longitude time derivative
  289.                                   value(tc, lVeCoefficients),         // mean Venus longitude
  290.                                   derivative(tc, lVeCoefficients),    // mean Venus longitude time derivative
  291.                                   value(tc, lECoefficients),          // mean Earth longitude
  292.                                   derivative(tc, lECoefficients),     // mean Earth longitude time derivative
  293.                                   value(tc, lMaCoefficients),         // mean Mars longitude
  294.                                   derivative(tc, lMaCoefficients),    // mean Mars longitude time derivative
  295.                                   value(tc, lJCoefficients),          // mean Jupiter longitude
  296.                                   derivative(tc, lJCoefficients),     // mean Jupiter longitude time derivative
  297.                                   value(tc, lSaCoefficients),         // mean Saturn longitude
  298.                                   derivative(tc, lSaCoefficients),    // mean Saturn longitude time derivative
  299.                                   value(tc, lUCoefficients),          // mean Uranus longitude
  300.                                   derivative(tc, lUCoefficients),     // mean Uranus longitude time derivative
  301.                                   value(tc, lNeCoefficients),         // mean Neptune longitude
  302.                                   derivative(tc, lNeCoefficients),    // mean Neptune longitude time derivative
  303.                                   value(tc, paCoefficients),          // general accumulated precession in longitude
  304.                                   derivative(tc, paCoefficients));    // general accumulated precession in longitude time derivative

  305.     }

  306.     /** Evaluate all fundamental arguments for the current date (Delaunay plus planetary).
  307.      * @param date current date
  308.      * @param <T> type of the field elements
  309.      * @return all fundamental arguments for the current date (Delaunay plus planetary)
  310.      */
  311.     public <T extends RealFieldElement<T>> FieldBodiesElements<T> evaluateAll(final FieldAbsoluteDate<T> date) {

  312.         final T tc       = conventions.evaluateTC(date);
  313.         final T gamma    = gmstFunction == null ?
  314.                            tc.getField().getZero().add(Double.NaN) : gmstFunction.value(date).add(FastMath.PI);
  315.         final T gammaDot = gmstRateFunction == null ?
  316.                            tc.getField().getZero().add(Double.NaN) : gmstRateFunction.value(date);

  317.         return new FieldBodiesElements<>(date, tc, gamma, gammaDot,
  318.                                          value(tc, lCoefficients),           // mean anomaly of the Moon
  319.                                          derivative(tc, lCoefficients),      // mean anomaly of the Moon time derivative
  320.                                          value(tc, lPrimeCoefficients),      // mean anomaly of the Sun
  321.                                          derivative(tc, lPrimeCoefficients), // mean anomaly of the Sun time derivative
  322.                                          value(tc, fCoefficients),           // L - Ω where L is the mean longitude of the Moon
  323.                                          derivative(tc, fCoefficients),      // L - Ω where L is the mean longitude of the Moon time derivative
  324.                                          value(tc, dCoefficients),           // mean elongation of the Moon from the Sun
  325.                                          derivative(tc, dCoefficients),      // mean elongation of the Moon from the Sun time derivative
  326.                                          value(tc, omegaCoefficients),       // mean longitude of the ascending node of the Moon
  327.                                          derivative(tc, omegaCoefficients),  // mean longitude of the ascending node of the Moon time derivative
  328.                                          value(tc, lMeCoefficients),         // mean Mercury longitude
  329.                                          derivative(tc, lMeCoefficients),    // mean Mercury longitude time derivative
  330.                                          value(tc, lVeCoefficients),         // mean Venus longitude
  331.                                          derivative(tc, lVeCoefficients),    // mean Venus longitude time derivative
  332.                                          value(tc, lECoefficients),          // mean Earth longitude
  333.                                          derivative(tc, lECoefficients),     // mean Earth longitude time derivative
  334.                                          value(tc, lMaCoefficients),         // mean Mars longitude
  335.                                          derivative(tc, lMaCoefficients),    // mean Mars longitude time derivative
  336.                                          value(tc, lJCoefficients),          // mean Jupiter longitude
  337.                                          derivative(tc, lJCoefficients),     // mean Jupiter longitude time derivative
  338.                                          value(tc, lSaCoefficients),         // mean Saturn longitude
  339.                                          derivative(tc, lSaCoefficients),    // mean Saturn longitude time derivative
  340.                                          value(tc, lUCoefficients),          // mean Uranus longitude
  341.                                          derivative(tc, lUCoefficients),     // mean Uranus longitude time derivative
  342.                                          value(tc, lNeCoefficients),         // mean Neptune longitude
  343.                                          derivative(tc, lNeCoefficients),    // mean Neptune longitude time derivative
  344.                                          value(tc, paCoefficients),          // general accumulated precession in longitude
  345.                                          derivative(tc, paCoefficients));    // general accumulated precession in longitude time derivative

  346.     }

  347.     /** Replace the instance with a data transfer object for serialization.
  348.      * <p>
  349.      * This intermediate class serializes only the frame key.
  350.      * </p>
  351.      * @return data transfer object that will be serialized
  352.      */
  353.     private Object writeReplace() {
  354.         return new DataTransferObject(conventions, timeScale,
  355.                                       Arrays.asList(lCoefficients, lPrimeCoefficients, fCoefficients,
  356.                                                     dCoefficients, omegaCoefficients,
  357.                                                     lMeCoefficients, lVeCoefficients, lECoefficients,
  358.                                                     lMaCoefficients, lJCoefficients, lSaCoefficients,
  359.                                                     lUCoefficients, lNeCoefficients, paCoefficients));
  360.     }

  361.     /** Internal class used only for serialization. */
  362.     private static class DataTransferObject implements Serializable {

  363.         /** Serializable UID. */
  364.         private static final long serialVersionUID = 20131209L;

  365.         /** IERS conventions to use. */
  366.         private final IERSConventions conventions;

  367.         /** Time scale for GMST computation. */
  368.         private final TimeScale timeScale;

  369.         /** All coefficients. */
  370.         private final List<double[]> coefficients;

  371.         /** Simple constructor.
  372.          * @param conventions IERS conventions to use
  373.          * @param timeScale time scale for GMST computation
  374.          * @param coefficients all coefficients
  375.          */
  376.         DataTransferObject(final IERSConventions conventions, final TimeScale timeScale,
  377.                                   final List<double[]> coefficients) {
  378.             this.conventions  = conventions;
  379.             this.timeScale    = timeScale;
  380.             this.coefficients = coefficients;
  381.         }

  382.         /** Replace the deserialized data transfer object with a {@link TIRFProvider}.
  383.          * @return replacement {@link TIRFProvider}
  384.          */
  385.         private Object readResolve() {
  386.             try {
  387.                 // retrieve a managed frame
  388.                 return new FundamentalNutationArguments(conventions, timeScale, coefficients);
  389.             } catch (OrekitException oe) {
  390.                 throw new OrekitInternalError(oe);
  391.             }
  392.         }

  393.     }

  394.     /** Enumerate for the fundamental names. */
  395.     private enum FundamentalName {

  396.         /** Constant for Mean anomaly of the Moon. */
  397.         L() {
  398.             /** {@inheritDoc} */
  399.             public String getArgumentName() {
  400.                 return "l";
  401.             }
  402.         },

  403.         /** Constant for Mean anomaly of the Sun. */
  404.         L_PRIME() {
  405.             /** {@inheritDoc} */
  406.             public String getArgumentName() {
  407.                 return "l'";
  408.             }
  409.         },

  410.         /** Constant for L - Ω where L is the mean longitude of the Moon. */
  411.         F() {
  412.             /** {@inheritDoc} */
  413.             public String getArgumentName() {
  414.                 return "F";
  415.             }
  416.         },

  417.         /** Constant for mean elongation of the Moon from the Sun. */
  418.         D() {
  419.             /** {@inheritDoc} */
  420.             public String getArgumentName() {
  421.                 return "D";
  422.             }
  423.         },

  424.         /** Constant for longitude of the ascending node of the Moon. */
  425.         OMEGA() {
  426.             /** {@inheritDoc} */
  427.             public String getArgumentName() {
  428.                 return "\u03a9";
  429.             }
  430.         },

  431.         /** Constant for mean Mercury longitude. */
  432.         L_ME() {
  433.             /** {@inheritDoc} */
  434.             public String getArgumentName() {
  435.                 return "LMe";
  436.             }
  437.         },

  438.         /** Constant for mean Venus longitude. */
  439.         L_VE() {
  440.             /** {@inheritDoc} */
  441.             public String getArgumentName() {
  442.                 return "LVe";
  443.             }
  444.         },

  445.         /** Constant for mean Earth longitude. */
  446.         L_E() {
  447.             /** {@inheritDoc} */
  448.             public String getArgumentName() {
  449.                 return "LE";
  450.             }
  451.         },

  452.         /** Constant for mean Mars longitude. */
  453.         L_MA() {
  454.             /** {@inheritDoc} */
  455.             public String getArgumentName() {
  456.                 return "LMa";
  457.             }
  458.         },

  459.         /** Constant for mean Jupiter longitude. */
  460.         L_J() {
  461.             /** {@inheritDoc} */
  462.             public String getArgumentName() {
  463.                 return "LJ";
  464.             }
  465.         },

  466.         /** Constant for mean Saturn longitude. */
  467.         L_SA() {
  468.             /** {@inheritDoc} */
  469.             public String getArgumentName() {
  470.                 return "LSa";
  471.             }
  472.         },

  473.         /** Constant for mean Uranus longitude. */
  474.         L_U() {
  475.             /** {@inheritDoc} */
  476.             public String getArgumentName() {
  477.                 return "LU";
  478.             }
  479.         },

  480.         /** Constant for mean Neptune longitude. */
  481.         L_NE() {
  482.             /** {@inheritDoc} */
  483.             public String getArgumentName() {
  484.                 return "LNe";
  485.             }
  486.         },

  487.         /** Constant for general accumulated precession in longitude. */
  488.         PA() {
  489.             /** {@inheritDoc} */
  490.             public String getArgumentName() {
  491.                 return "pA";
  492.             }
  493.         };

  494.         /** Get the fundamental name.
  495.          * @return fundamental name
  496.          */
  497.         public abstract String getArgumentName();

  498.     }

  499.     /** Local parser for argument definition lines. */
  500.     private static class DefinitionParser {

  501.         /** Regular expression pattern for definitions. */
  502.         private final Pattern pattern;

  503.         /** Parser for polynomials. */
  504.         private PolynomialParser polynomialParser;

  505.         /** Last parsed fundamental name. */
  506.         private FundamentalName parsedName;

  507.         /** Last parsed polynomial. */
  508.         private double[] parsedPolynomial;

  509.         /** Simple constructor. */
  510.         DefinitionParser() {

  511.             // the luni-solar Delaunay arguments polynomial parts should read something like:
  512.             // F5 ≡ Ω = 125.04455501° − 6962890.5431″t + 7.4722″t² + 0.007702″t³ − 0.00005939″t⁴
  513.             // whereas the planetary arguments polynomial parts should read something like:
  514.             // F14 ≡ pA  = 0.02438175 × t + 0.00000538691 × t²
  515.             final String unicodeIdenticalTo = "\u2261";

  516.             // pattern for the global line
  517.             final StringBuilder builder = new StringBuilder();
  518.             for (final FundamentalName fn : FundamentalName.values()) {
  519.                 if (builder.length() > 0) {
  520.                     builder.append('|');
  521.                 }
  522.                 builder.append(fn.getArgumentName());
  523.             }
  524.             final String fundamentalName = "\\p{Space}*((?:" + builder.toString() + ")+)";
  525.             pattern = Pattern.compile("\\p{Space}*F\\p{Digit}+\\p{Space}*" + unicodeIdenticalTo +
  526.                                       fundamentalName + "\\p{Space}*=\\p{Space}*(.*)");

  527.             polynomialParser = new PolynomialParser('t', PolynomialParser.Unit.NO_UNITS);

  528.         }

  529.         /** Parse a definition line.
  530.          * @param line line to parse
  531.          * @param lineNumber line number
  532.          * @param fileName name of the file
  533.          * @return true if a definition has been parsed
  534.          */
  535.         public boolean parseDefinition(final String line, final int lineNumber, final String fileName) {

  536.             parsedName       = null;
  537.             parsedPolynomial = null;

  538.             final Matcher matcher = pattern.matcher(line);
  539.             if (matcher.matches()) {
  540.                 for (FundamentalName fn : FundamentalName.values()) {
  541.                     if (fn.getArgumentName().equals(matcher.group(1))) {
  542.                         parsedName = fn;
  543.                     }
  544.                 }

  545.                 // parse the polynomial
  546.                 parsedPolynomial = polynomialParser.parse(matcher.group(2));

  547.                 return true;

  548.             } else {
  549.                 return false;
  550.             }

  551.         }

  552.         /** Get the last parsed fundamental name.
  553.          * @return last parsed fundamental name
  554.          */
  555.         public FundamentalName getParsedName() {
  556.             return parsedName;
  557.         }

  558.         /** Get the last parsed polynomial.
  559.          * @return last parsed polynomial
  560.          */
  561.         public double[] getParsedPolynomial() {
  562.             return parsedPolynomial.clone();
  563.         }

  564.     }

  565. }