All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.orekit.data.FundamentalNutationArguments Maven / Gradle / Ivy

Go to download

OREKIT (ORbits Extrapolation KIT) is a low level space dynamics library. It provides basic elements (orbits, dates, attitude, frames ...) and various algorithms to handle them (conversions, analytical and numerical propagation, pointing ...).

There is a newer version: 12.2
Show newest version
/* Copyright 2002-2022 CS GROUP
 * Licensed to CS GROUP (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.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.hipparchus.CalculusFieldElement;
import org.hipparchus.exception.DummyLocalizable;
import org.hipparchus.util.FastMath;
import org.orekit.annotation.DefaultDataContext;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitInternalError;
import org.orekit.errors.OrekitMessages;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
import org.orekit.time.TimeScalarFunction;
import org.orekit.time.TimeScale;
import org.orekit.time.TimeScales;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;

/**
 * Class computing the fundamental arguments for nutation and tides.
 * 

* The fundamental arguments are split in two sets: *

*
    *
  • the Delaunay arguments for Moon and Sun effects
  • *
  • the planetary arguments for other planets
  • *
* * @author Luc Maisonobe * @see SeriesTerm * @see PoissonSeries * @see BodiesElements */ public class FundamentalNutationArguments implements Serializable { /** Serializable UID. */ private static final long serialVersionUID = 20131209L; /** IERS conventions to use. */ private final IERSConventions conventions; /** Time scale for GMST computation. */ private final TimeScale timeScale; /** Function computing Greenwich Mean Sidereal Time. */ private final transient TimeScalarFunction gmstFunction; /** Function computing Greenwich Mean Sidereal Time rate. */ private final transient TimeScalarFunction gmstRateFunction; // luni-solar Delaunay arguments /** Coefficients for mean anomaly of the Moon. */ private final double[] lCoefficients; /** Coefficients for mean anomaly of the Sun. */ private final double[] lPrimeCoefficients; /** Coefficients for L - Ω where L is the mean longitude of the Moon. */ private final double[] fCoefficients; /** Coefficients for mean elongation of the Moon from the Sun. */ private final double[] dCoefficients; /** Coefficients for mean longitude of the ascending node of the Moon. */ private final double[] omegaCoefficients; // planetary nutation arguments /** Coefficients for mean Mercury longitude. */ private final double[] lMeCoefficients; /** Coefficients for mean Venus longitude. */ private final double[] lVeCoefficients; /** Coefficients for mean Earth longitude. */ private final double[] lECoefficients; /** Coefficients for mean Mars longitude. */ private final double[] lMaCoefficients; /** Coefficients for mean Jupiter longitude. */ private final double[] lJCoefficients; /** Coefficients for mean Saturn longitude. */ private final double[] lSaCoefficients; /** Coefficients for mean Uranus longitude. */ private final double[] lUCoefficients; /** Coefficients for mean Neptune longitude. */ private final double[] lNeCoefficients; /** Coefficients for general accumulated precession. */ private final double[] paCoefficients; /** Set of time scales to use in computations. */ private final transient TimeScales timeScales; /** Build a model of fundamental arguments from an IERS table file. * *

This method uses the {@link DataContext#getDefault() default data context}. * * @param conventions IERS conventions to use * @param timeScale time scale for GMST computation * (may be null if tide parameter γ = GMST + π is not needed) * @param stream stream containing the IERS table * @param name name of the resource file (for error messages only) * @see #FundamentalNutationArguments(IERSConventions, TimeScale, List, TimeScales) * @see #FundamentalNutationArguments(IERSConventions, TimeScale, InputStream, String, TimeScales) */ @DefaultDataContext public FundamentalNutationArguments(final IERSConventions conventions, final TimeScale timeScale, final InputStream stream, final String name) { this(conventions, timeScale, stream, name, DataContext.getDefault().getTimeScales()); } /** * Build a model of fundamental arguments from an IERS table file. * * @param conventions IERS conventions to use * @param timeScale time scale for GMST computation (may be null if tide parameter γ * = GMST + π is not needed) * @param stream stream containing the IERS table * @param name name of the resource file (for error messages only) * @param timeScales TAI time scale * @see #FundamentalNutationArguments(IERSConventions, TimeScale, List, TimeScales) * @since 10.1 */ public FundamentalNutationArguments(final IERSConventions conventions, final TimeScale timeScale, final InputStream stream, final String name, final TimeScales timeScales) { this(conventions, timeScale, parseCoefficients(stream, name), timeScales); } /** Build a model of fundamental arguments from an IERS table file. * *

This method uses the {@link DataContext#getDefault() default data context}. * * @param conventions IERS conventions to use * @param timeScale time scale for GMST computation * (may be null if tide parameter γ = GMST + π is not needed) * @param coefficients list of coefficients arrays (all 14 arrays must be provided, * the 5 Delaunay first and the 9 planetary afterwards) * @since 6.1 * @see #FundamentalNutationArguments(IERSConventions, TimeScale, List, TimeScales) */ @DefaultDataContext public FundamentalNutationArguments(final IERSConventions conventions, final TimeScale timeScale, final List coefficients) { this(conventions, timeScale, coefficients, DataContext.getDefault().getTimeScales()); } /** Build a model of fundamental arguments from an IERS table file. * @param conventions IERS conventions to use * @param timeScale time scale for GMST computation * (may be null if tide parameter γ = GMST + π is not needed) * @param coefficients list of coefficients arrays (all 14 arrays must be provided, * the 5 Delaunay first and the 9 planetary afterwards) * @param timeScales used in the computation. * @since 10.1 */ public FundamentalNutationArguments(final IERSConventions conventions, final TimeScale timeScale, final List coefficients, final TimeScales timeScales) { this.conventions = conventions; this.timeScale = timeScale; this.timeScales = timeScales; this.gmstFunction = (timeScale == null) ? null : conventions.getGMSTFunction(timeScale, timeScales); this.gmstRateFunction = (timeScale == null) ? null : conventions.getGMSTRateFunction(timeScale, timeScales); this.lCoefficients = coefficients.get( 0); this.lPrimeCoefficients = coefficients.get( 1); this.fCoefficients = coefficients.get( 2); this.dCoefficients = coefficients.get( 3); this.omegaCoefficients = coefficients.get( 4); this.lMeCoefficients = coefficients.get( 5); this.lVeCoefficients = coefficients.get( 6); this.lECoefficients = coefficients.get( 7); this.lMaCoefficients = coefficients.get( 8); this.lJCoefficients = coefficients.get( 9); this.lSaCoefficients = coefficients.get(10); this.lUCoefficients = coefficients.get(11); this.lNeCoefficients = coefficients.get(12); this.paCoefficients = coefficients.get(13); } /** Parse coefficients. * @param stream stream containing the IERS table * @param name name of the resource file (for error messages only) * @return list of coefficients arrays */ private static List parseCoefficients(final InputStream stream, final String name) { if (stream == null) { throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, name); } // setup the reader try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { final DefinitionParser definitionParser = new DefinitionParser(); int lineNumber = 0; // look for the reference date and the 14 polynomials final int n = FundamentalName.values().length; final Map polynomials = new HashMap(n); for (String line = reader.readLine(); line != null; line = reader.readLine()) { lineNumber++; if (definitionParser.parseDefinition(line, lineNumber, name)) { polynomials.put(definitionParser.getParsedName(), definitionParser.getParsedPolynomial()); } } final List coefficients = new ArrayList(n); coefficients.add(getCoefficients(FundamentalName.L, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.L_PRIME, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.F, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.D, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.OMEGA, polynomials, name)); if (polynomials.containsKey(FundamentalName.L_ME)) { // IERS conventions 2003 and later provide planetary nutation arguments coefficients.add(getCoefficients(FundamentalName.L_ME, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.L_VE, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.L_E, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.L_MA, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.L_J, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.L_SA, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.L_U, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.L_NE, polynomials, name)); coefficients.add(getCoefficients(FundamentalName.PA, polynomials, name)); } else { // IERS conventions 1996 and earlier don't provide planetary nutation arguments final double[] zero = new double[] { 0.0 }; while (coefficients.size() < n) { coefficients.add(zero); } } return coefficients; } catch (IOException ioe) { throw new OrekitException(ioe, new DummyLocalizable(ioe.getMessage())); } } /** Get the coefficients for a fundamental argument. * @param argument fundamental argument * @param polynomials map of the polynomials * @param fileName name of the file from which the coefficients have been read * @return polynomials coefficients (ordered from high degrees to low degrees) */ private static double[] getCoefficients(final FundamentalName argument, final Map polynomials, final String fileName) { if (!polynomials.containsKey(argument)) { throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, fileName); } return polynomials.get(argument); } /** Evaluate a polynomial. * @param tc offset in Julian centuries * @param coefficients polynomial coefficients (ordered from low degrees to high degrees) * @return value of the polynomial */ private double value(final double tc, final double[] coefficients) { double value = 0; for (int i = coefficients.length - 1; i >= 0; --i) { value = coefficients[i] + tc * value; } return value; } /** Evaluate a polynomial time derivative. * @param tc offset in Julian centuries * @param coefficients polynomial coefficients (ordered from low degrees to high degrees) * @return time derivative of the polynomial */ private double derivative(final double tc, final double[] coefficients) { double derivative = 0; for (int i = coefficients.length - 1; i > 0; --i) { derivative = i * coefficients[i] + tc * derivative; } return derivative / Constants.JULIAN_CENTURY; } /** Evaluate a polynomial. * @param tc offset in Julian centuries * @param type of the field elements * @param coefficients polynomial coefficients (ordered from low degrees to high degrees) * @return value of the polynomial */ private > T value(final T tc, final double[] coefficients) { T value = tc.getField().getZero(); for (int i = coefficients.length - 1; i >= 0; --i) { value = tc.multiply(value).add(coefficients[i]); } return value; } /** Evaluate a polynomial time derivative. * @param tc offset in Julian centuries * @param type of the field elements * @param coefficients polynomial coefficients (ordered from low degrees to high degrees) * @return time derivative of the polynomial */ private > T derivative(final T tc, final double[] coefficients) { T derivative = tc.getField().getZero(); for (int i = coefficients.length - 1; i > 0; --i) { derivative = tc.multiply(derivative).add(i * coefficients[i]); } return derivative.divide(Constants.JULIAN_CENTURY); } /** Evaluate all fundamental arguments for the current date (Delaunay plus planetary). * @param date current date * @return all fundamental arguments for the current date (Delaunay plus planetary) */ public BodiesElements evaluateAll(final AbsoluteDate date) { final double tc = conventions.evaluateTC(date, timeScales); final double gamma = gmstFunction == null ? Double.NaN : gmstFunction.value(date) + FastMath.PI; final double gammaDot = gmstRateFunction == null ? Double.NaN : gmstRateFunction.value(date); return new BodiesElements(date, tc, gamma, gammaDot, value(tc, lCoefficients), // mean anomaly of the Moon derivative(tc, lCoefficients), // mean anomaly of the Moon time derivative value(tc, lPrimeCoefficients), // mean anomaly of the Sun derivative(tc, lPrimeCoefficients), // mean anomaly of the Sun time derivative value(tc, fCoefficients), // L - Ω where L is the mean longitude of the Moon derivative(tc, fCoefficients), // L - Ω where L is the mean longitude of the Moon time derivative value(tc, dCoefficients), // mean elongation of the Moon from the Sun derivative(tc, dCoefficients), // mean elongation of the Moon from the Sun time derivative value(tc, omegaCoefficients), // mean longitude of the ascending node of the Moon derivative(tc, omegaCoefficients), // mean longitude of the ascending node of the Moon time derivative value(tc, lMeCoefficients), // mean Mercury longitude derivative(tc, lMeCoefficients), // mean Mercury longitude time derivative value(tc, lVeCoefficients), // mean Venus longitude derivative(tc, lVeCoefficients), // mean Venus longitude time derivative value(tc, lECoefficients), // mean Earth longitude derivative(tc, lECoefficients), // mean Earth longitude time derivative value(tc, lMaCoefficients), // mean Mars longitude derivative(tc, lMaCoefficients), // mean Mars longitude time derivative value(tc, lJCoefficients), // mean Jupiter longitude derivative(tc, lJCoefficients), // mean Jupiter longitude time derivative value(tc, lSaCoefficients), // mean Saturn longitude derivative(tc, lSaCoefficients), // mean Saturn longitude time derivative value(tc, lUCoefficients), // mean Uranus longitude derivative(tc, lUCoefficients), // mean Uranus longitude time derivative value(tc, lNeCoefficients), // mean Neptune longitude derivative(tc, lNeCoefficients), // mean Neptune longitude time derivative value(tc, paCoefficients), // general accumulated precession in longitude derivative(tc, paCoefficients)); // general accumulated precession in longitude time derivative } /** Evaluate all fundamental arguments for the current date (Delaunay plus planetary). * @param date current date * @param type of the field elements * @return all fundamental arguments for the current date (Delaunay plus planetary) */ public > FieldBodiesElements evaluateAll(final FieldAbsoluteDate date) { final T tc = conventions.evaluateTC(date, timeScales); final T gamma = gmstFunction == null ? tc.getField().getZero().add(Double.NaN) : gmstFunction.value(date).add(tc.getPi()); final T gammaDot = gmstRateFunction == null ? tc.getField().getZero().add(Double.NaN) : gmstRateFunction.value(date); return new FieldBodiesElements<>(date, tc, gamma, gammaDot, value(tc, lCoefficients), // mean anomaly of the Moon derivative(tc, lCoefficients), // mean anomaly of the Moon time derivative value(tc, lPrimeCoefficients), // mean anomaly of the Sun derivative(tc, lPrimeCoefficients), // mean anomaly of the Sun time derivative value(tc, fCoefficients), // L - Ω where L is the mean longitude of the Moon derivative(tc, fCoefficients), // L - Ω where L is the mean longitude of the Moon time derivative value(tc, dCoefficients), // mean elongation of the Moon from the Sun derivative(tc, dCoefficients), // mean elongation of the Moon from the Sun time derivative value(tc, omegaCoefficients), // mean longitude of the ascending node of the Moon derivative(tc, omegaCoefficients), // mean longitude of the ascending node of the Moon time derivative value(tc, lMeCoefficients), // mean Mercury longitude derivative(tc, lMeCoefficients), // mean Mercury longitude time derivative value(tc, lVeCoefficients), // mean Venus longitude derivative(tc, lVeCoefficients), // mean Venus longitude time derivative value(tc, lECoefficients), // mean Earth longitude derivative(tc, lECoefficients), // mean Earth longitude time derivative value(tc, lMaCoefficients), // mean Mars longitude derivative(tc, lMaCoefficients), // mean Mars longitude time derivative value(tc, lJCoefficients), // mean Jupiter longitude derivative(tc, lJCoefficients), // mean Jupiter longitude time derivative value(tc, lSaCoefficients), // mean Saturn longitude derivative(tc, lSaCoefficients), // mean Saturn longitude time derivative value(tc, lUCoefficients), // mean Uranus longitude derivative(tc, lUCoefficients), // mean Uranus longitude time derivative value(tc, lNeCoefficients), // mean Neptune longitude derivative(tc, lNeCoefficients), // mean Neptune longitude time derivative value(tc, paCoefficients), // general accumulated precession in longitude derivative(tc, paCoefficients)); // general accumulated precession in longitude time derivative } /** Replace the instance with a data transfer object for serialization. *

* This intermediate class serializes only the frame key. *

* @return data transfer object that will be serialized */ @DefaultDataContext private Object writeReplace() { return new DataTransferObject(conventions, timeScale, Arrays.asList(lCoefficients, lPrimeCoefficients, fCoefficients, dCoefficients, omegaCoefficients, lMeCoefficients, lVeCoefficients, lECoefficients, lMaCoefficients, lJCoefficients, lSaCoefficients, lUCoefficients, lNeCoefficients, paCoefficients)); } /** Internal class used only for serialization. */ @DefaultDataContext private static class DataTransferObject implements Serializable { /** Serializable UID. */ private static final long serialVersionUID = 20131209L; /** IERS conventions to use. */ private final IERSConventions conventions; /** Time scale for GMST computation. */ private final TimeScale timeScale; /** All coefficients. */ private final List coefficients; /** Simple constructor. * @param conventions IERS conventions to use * @param timeScale time scale for GMST computation * @param coefficients all coefficients */ DataTransferObject(final IERSConventions conventions, final TimeScale timeScale, final List coefficients) { this.conventions = conventions; this.timeScale = timeScale; this.coefficients = coefficients; } /** Replace the deserialized data transfer object with a {@link TIRFProvider}. * @return replacement {@link TIRFProvider} */ private Object readResolve() { try { // retrieve a managed frame return new FundamentalNutationArguments(conventions, timeScale, coefficients); } catch (OrekitException oe) { throw new OrekitInternalError(oe); } } } /** Enumerate for the fundamental names. */ private enum FundamentalName { /** Constant for Mean anomaly of the Moon. */ L() { /** {@inheritDoc} */ public String getArgumentName() { return "l"; } }, /** Constant for Mean anomaly of the Sun. */ L_PRIME() { /** {@inheritDoc} */ public String getArgumentName() { return "l'"; } }, /** Constant for L - Ω where L is the mean longitude of the Moon. */ F() { /** {@inheritDoc} */ public String getArgumentName() { return "F"; } }, /** Constant for mean elongation of the Moon from the Sun. */ D() { /** {@inheritDoc} */ public String getArgumentName() { return "D"; } }, /** Constant for longitude of the ascending node of the Moon. */ OMEGA() { /** {@inheritDoc} */ public String getArgumentName() { return "\u03a9"; } }, /** Constant for mean Mercury longitude. */ L_ME() { /** {@inheritDoc} */ public String getArgumentName() { return "LMe"; } }, /** Constant for mean Venus longitude. */ L_VE() { /** {@inheritDoc} */ public String getArgumentName() { return "LVe"; } }, /** Constant for mean Earth longitude. */ L_E() { /** {@inheritDoc} */ public String getArgumentName() { return "LE"; } }, /** Constant for mean Mars longitude. */ L_MA() { /** {@inheritDoc} */ public String getArgumentName() { return "LMa"; } }, /** Constant for mean Jupiter longitude. */ L_J() { /** {@inheritDoc} */ public String getArgumentName() { return "LJ"; } }, /** Constant for mean Saturn longitude. */ L_SA() { /** {@inheritDoc} */ public String getArgumentName() { return "LSa"; } }, /** Constant for mean Uranus longitude. */ L_U() { /** {@inheritDoc} */ public String getArgumentName() { return "LU"; } }, /** Constant for mean Neptune longitude. */ L_NE() { /** {@inheritDoc} */ public String getArgumentName() { return "LNe"; } }, /** Constant for general accumulated precession in longitude. */ PA() { /** {@inheritDoc} */ public String getArgumentName() { return "pA"; } }; /** Get the fundamental name. * @return fundamental name */ public abstract String getArgumentName(); } /** Local parser for argument definition lines. */ private static class DefinitionParser { /** Regular expression pattern for definitions. */ private final Pattern pattern; /** Parser for polynomials. */ private PolynomialParser polynomialParser; /** Last parsed fundamental name. */ private FundamentalName parsedName; /** Last parsed polynomial. */ private double[] parsedPolynomial; /** Simple constructor. */ DefinitionParser() { // the luni-solar Delaunay arguments polynomial parts should read something like: // F5 ≡ Ω = 125.04455501° − 6962890.5431″t + 7.4722″t² + 0.007702″t³ − 0.00005939″t⁴ // whereas the planetary arguments polynomial parts should read something like: // F14 ≡ pA = 0.02438175 × t + 0.00000538691 × t² final String unicodeIdenticalTo = "\u2261"; // pattern for the global line final StringBuilder builder = new StringBuilder(); for (final FundamentalName fn : FundamentalName.values()) { if (builder.length() > 0) { builder.append('|'); } builder.append(fn.getArgumentName()); } final String fundamentalName = "\\p{Space}*((?:" + builder.toString() + ")+)"; pattern = Pattern.compile("\\p{Space}*F\\p{Digit}+\\p{Space}*" + unicodeIdenticalTo + fundamentalName + "\\p{Space}*=\\p{Space}*(.*)"); polynomialParser = new PolynomialParser('t', PolynomialParser.Unit.NO_UNITS); } /** Parse a definition line. * @param line line to parse * @param lineNumber line number * @param fileName name of the file * @return true if a definition has been parsed */ public boolean parseDefinition(final String line, final int lineNumber, final String fileName) { parsedName = null; parsedPolynomial = null; final Matcher matcher = pattern.matcher(line); if (matcher.matches()) { for (FundamentalName fn : FundamentalName.values()) { if (fn.getArgumentName().equals(matcher.group(1))) { parsedName = fn; } } // parse the polynomial parsedPolynomial = polynomialParser.parse(matcher.group(2)); return true; } else { return false; } } /** Get the last parsed fundamental name. * @return last parsed fundamental name */ public FundamentalName getParsedName() { return parsedName; } /** Get the last parsed polynomial. * @return last parsed polynomial */ public double[] getParsedPolynomial() { return parsedPolynomial.clone(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy