ShortPeriodicsInterpolatedCoefficient.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.propagation.semianalytical.dsst.utilities;

  18. import java.io.Serializable;
  19. import java.util.ArrayList;

  20. import org.hipparchus.analysis.interpolation.HermiteInterpolator;
  21. import org.hipparchus.util.FastMath;
  22. import org.orekit.time.AbsoluteDate;

  23. /** Interpolated short periodics coefficients.
  24.  * <p>
  25.  * Representation of a coefficient that need to be interpolated over time.
  26.  * </p><p>
  27.  * The short periodics coefficients can be interpolated for faster computation.
  28.  * This class stores computed values of the coefficients through the method
  29.  * {@link #addGridPoint} and gives an interpolated result through the method
  30.  * {@link #value}.
  31.  * </p>
  32.  * @author Nicolas Bernard
  33.  *
  34.  */
  35. public class ShortPeriodicsInterpolatedCoefficient implements Serializable {

  36.     /** Serializable UID. */
  37.     private static final long serialVersionUID = 20160319L;

  38.     /**Values of the already computed coefficients.*/
  39.     private ArrayList<double[]> values;

  40.     /**Grid points.*/
  41.     private ArrayList<AbsoluteDate> abscissae;

  42.     /**Number of points used in the interpolation.*/
  43.     private int interpolationPoints;

  44.     /**Index of the latest closest neighbor.*/
  45.     private int latestClosestNeighbor;

  46.     /**Simple constructor.
  47.      * @param interpolationPoints number of points used in the interpolation
  48.      */
  49.     public ShortPeriodicsInterpolatedCoefficient(final int interpolationPoints) {
  50.         this.interpolationPoints = interpolationPoints;
  51.         this.abscissae = new ArrayList<AbsoluteDate>();
  52.         this.values = new ArrayList<double[]>();
  53.         this.latestClosestNeighbor = 0;
  54.     }

  55.     /**Compute the value of the coefficient.
  56.      * @param date date at which the coefficient should be computed
  57.      * @return value of the coefficient
  58.      */
  59.     public double[] value(final AbsoluteDate date) {
  60.         //Get the closest points from the input date
  61.         final int[] neighbors = getNeighborsIndices(date);

  62.         //Creation and set up of the interpolator
  63.         final HermiteInterpolator interpolator = new HermiteInterpolator();
  64.         for (int i : neighbors) {
  65.             interpolator.addSamplePoint(abscissae.get(i).durationFrom(date), values.get(i));
  66.         }

  67.         //interpolation
  68.         return interpolator.value(0.0);

  69.     }

  70.     /**Find the closest available points from the specified date.
  71.      * @param date date of interest
  72.      * @return indices corresponding to the closest points on the time scale
  73.      */
  74.     private int[] getNeighborsIndices(final AbsoluteDate date) {
  75.         final int sizeofNeighborhood = FastMath.min(interpolationPoints, abscissae.size());
  76.         final int[] neighborsIndices = new int[sizeofNeighborhood];

  77.         //If the size of the complete sample is less than
  78.         //the desired number of interpolation points,
  79.         //then the entire sample is considered as the neighborhood
  80.         if (interpolationPoints >= abscissae.size()) {
  81.             for (int i = 0; i < sizeofNeighborhood; i++) {
  82.                 neighborsIndices[i] = i;
  83.             }
  84.         } else {
  85.             // get indices around closest neighbor
  86.             int inf = getClosestNeighbor(date);
  87.             int sup = inf + 1;

  88.             while (sup - inf < interpolationPoints) {
  89.                 if (inf == 0) { //This means that we have reached the earliest date
  90.                     sup++;
  91.                 } else if (sup >= abscissae.size()) { //This means that we have reached the latest date
  92.                     inf--;
  93.                 } else { //the choice is made between the two next neighbors
  94.                     final double lowerNeighborDistance = FastMath.abs(abscissae.get(inf - 1).durationFrom(date));
  95.                     final double upperNeighborDistance = FastMath.abs(abscissae.get(sup).durationFrom(date));

  96.                     if (lowerNeighborDistance <= upperNeighborDistance) {
  97.                         inf--;
  98.                     } else {
  99.                         sup++;
  100.                     }
  101.                 }
  102.             }

  103.             for (int i = 0; i < interpolationPoints; ++i) {
  104.                 neighborsIndices[i] = inf + i;
  105.             }

  106.         }

  107.         return neighborsIndices;
  108.     }

  109.     /**Find the closest point from a specific date amongst the available points.
  110.      * @param date date of interest
  111.      * @return index of the closest abscissa from the date of interest
  112.      */
  113.     private int getClosestNeighbor(final AbsoluteDate date) {
  114.         //the starting point is the latest result of a call to this method.
  115.         //Indeed, as this class is meant to be called during an integration process
  116.         //with an input date evolving often continuously in time, there is a high
  117.         //probability that the result will be the same as for last call of
  118.         //this method.
  119.         int closestNeighbor = latestClosestNeighbor;

  120.         //case where the date is before the available points
  121.         if (date.compareTo(abscissae.get(0)) <= 0) {
  122.             closestNeighbor = 0;
  123.         }
  124.         //case where the date is after the available points
  125.         else if (date.compareTo(abscissae.get(abscissae.size() - 1)) >= 0) {
  126.             closestNeighbor = abscissae.size() - 1;
  127.         }
  128.         //general case: one is looking for the two consecutives entries that surround the input date
  129.         //then one choose the closest one
  130.         else {
  131.             int lowerBorder = latestClosestNeighbor;
  132.             int upperBorder = latestClosestNeighbor;

  133.             final int searchDirection = date.compareTo(abscissae.get(latestClosestNeighbor));
  134.             if (searchDirection > 0) {
  135.                 upperBorder++;
  136.                 while (date.compareTo(abscissae.get(upperBorder)) > 0) {
  137.                     upperBorder++;
  138.                     lowerBorder++;
  139.                 }
  140.             }
  141.             else {
  142.                 lowerBorder--;
  143.                 while (date.compareTo(abscissae.get(lowerBorder)) < 0) {
  144.                     upperBorder--;
  145.                     lowerBorder--;
  146.                 }
  147.             }

  148.             final double lowerDistance = FastMath.abs(date.durationFrom(abscissae.get(lowerBorder)));
  149.             final double upperDistance = FastMath.abs(date.durationFrom(abscissae.get(upperBorder)));

  150.             closestNeighbor = (lowerDistance < upperDistance) ? lowerBorder : upperBorder;
  151.         }

  152.         //The result is stored in order to speed up the next call to the function
  153.         //Indeed, it is highly likely that the requested result will be the same
  154.         this.latestClosestNeighbor = closestNeighbor;
  155.         return closestNeighbor;
  156.     }

  157.     /** Clear the recorded values from the interpolation grid.
  158.      */
  159.     public void clearHistory() {
  160.         abscissae.clear();
  161.         values.clear();
  162.     }

  163.     /** Add a point to the interpolation grid.
  164.      * @param date abscissa of the point
  165.      * @param value value of the element
  166.      */
  167.     public void addGridPoint(final AbsoluteDate date, final double[] value) {
  168.         //If the grid is empty, the value is directly added to both arrays
  169.         if (abscissae.isEmpty()) {
  170.             abscissae.add(date);
  171.             values.add(value);
  172.         }
  173.         //If the grid already contains this point, only its value is changed
  174.         else if (abscissae.contains(date)) {
  175.             values.set(abscissae.indexOf(date), value);
  176.         }
  177.         //If the grid does not contain this point, the position of the point
  178.         //in the grid is computed first
  179.         else {
  180.             final int closestNeighbor = getClosestNeighbor(date);
  181.             final int index = (date.compareTo(abscissae.get(closestNeighbor)) < 0) ? closestNeighbor : closestNeighbor + 1;
  182.             abscissae.add(index, date);
  183.             values.add(index, value);
  184.         }
  185.     }
  186. }