PredictedEOPHistory.java

  1. /* Copyright 2022-2025 Luc Maisonobe
  2.  * Licensed to CS GROUP (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.frames;

  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.List;

  21. import org.hipparchus.util.FastMath;
  22. import org.orekit.time.AbsoluteDate;
  23. import org.orekit.utils.Constants;
  24. import org.orekit.utils.IERSConventions.NutationCorrectionConverter;
  25. import org.orekit.utils.SecularAndHarmonic;

  26. /** This class extends an {@link EOPHistory} for some weeks using fitting.
  27.  * <p>
  28.  * The goal of this class is to provide a reasonable prediction of
  29.  * Earth Orientation Parameters past the last date available in
  30.  * regular {@link EOPHistory}, which just generated corrections set
  31.  * to 0 when they have no data.
  32.  * </p>
  33.  * <p>
  34.  * The prediction is based on fitting of last data, with both
  35.  * {@link SecularAndHarmonic secular (polynomial) and harmonic (periodic)}
  36.  * terms. The extended entries are generated at one point per day
  37.  * and are continuous (i.e. no leap seconds are introduced)
  38.  * </p>
  39.  * <p>
  40.  * After construction, the history contains both the initial
  41.  * raw history and an extension part appended after it.
  42.  * </p>
  43.  * @see EOPFitter
  44.  * @see SecularAndHarmonic
  45.  * @since 12.0
  46.  * @author Luc Maisonobe
  47.  */
  48. public class PredictedEOPHistory extends EOPHistory {

  49.     /** Raw EOP history to extend. */
  50.     private final EOPHistory rawHistory;

  51.     /** Duration of the extension period (s). */
  52.     private final double extensionDuration;

  53.     /** Fitter for all Earth Orientation Parameters. */
  54.     private final EOPFitter fitter;

  55.     /** Simple constructor.
  56.      * @param rawHistory raw EOP history to extend.
  57.      * @param extensionDuration duration of the extension period (s)
  58.      * @param fitter fitter for all Earth Orientation Parameters
  59.      */
  60.     public PredictedEOPHistory(final EOPHistory rawHistory, final double extensionDuration,
  61.                                final EOPFitter fitter) {
  62.         super(rawHistory.getConventions(), rawHistory.getInterpolationDegree(),
  63.               extendHistory(rawHistory, extensionDuration, fitter),
  64.               rawHistory.isSimpleEop(), rawHistory.getTimeScales());
  65.         this.rawHistory        = rawHistory;
  66.         this.extensionDuration = extensionDuration;
  67.         this.fitter            = fitter;
  68.     }

  69.     /** Extends raw history.
  70.      * @param rawHistory raw EOP history to extend.
  71.      * @param extensionDuration duration of the extension period (s)
  72.      * @param fitter fitter for all Earth Orientation Parameters
  73.      * @return extended history
  74.      */
  75.     private static Collection<? extends EOPEntry> extendHistory(final EOPHistory rawHistory,
  76.                                                                 final double extensionDuration,
  77.                                                                 final EOPFitter fitter) {


  78.         // fit model
  79.         final EOPFittedModel model = fitter.fit(rawHistory);

  80.         // create a converter for nutation corrections
  81.         final NutationCorrectionConverter converter =
  82.                         rawHistory.getConventions().getNutationCorrectionConverter(rawHistory.getTimeScales());

  83.         // generate extension entries
  84.         final List<EOPEntry> rawEntries = rawHistory.getEntries();
  85.         final EOPEntry       last       = rawEntries.get(rawEntries.size() - 1);
  86.         final int n = (int) FastMath.rint(extensionDuration / Constants.JULIAN_DAY);
  87.         final List<EOPEntry> entries = new ArrayList<>(rawEntries.size() + n);
  88.         entries.addAll(rawEntries);
  89.         for (int i = 0; i < n; ++i) {
  90.             final AbsoluteDate date = last.getDate().shiftedBy((i + 1) * Constants.JULIAN_DAY);
  91.             final double dut1   = model.getDUT1().osculatingValue(date);
  92.             final double lod    = -Constants.JULIAN_DAY * model.getDUT1().osculatingDerivative(date);
  93.             final double xp     = model.getXp().osculatingValue(date);
  94.             final double yp     = model.getYp().osculatingValue(date);
  95.             final double xpRate = model.getXp().osculatingDerivative(date);
  96.             final double ypRate = model.getYp().osculatingDerivative(date);
  97.             final double dx     = model.getDx().osculatingValue(date);
  98.             final double dy     = model.getDy().osculatingValue(date);
  99.             final double[] equinox = converter.toEquinox(date, dx, dy);
  100.             entries.add(new EOPEntry(last.getMjd() + i + 1, dut1, lod, xp, yp, xpRate, ypRate,
  101.                                      equinox[0], equinox[1], dx, dy,
  102.                                      last.getITRFType(), date));
  103.         }

  104.         return entries;

  105.     }

  106. }