HansenTesseralLinear.java

  1. /* Copyright 2002-2024 CS GROUP
  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.propagation.semianalytical.dsst.utilities.hansen;

  18. import org.hipparchus.analysis.differentiation.Gradient;
  19. import org.hipparchus.analysis.polynomials.PolynomialFunction;
  20. import org.hipparchus.util.FastMath;
  21. import org.orekit.propagation.semianalytical.dsst.utilities.NewcombOperators;

  22. /**
  23.  * Hansen coefficients K(t,n,s) for t!=0 and n < 0.
  24.  * <p>
  25.  * Implements Collins 4-236 or Danielson 2.7.3-(9) for Hansen Coefficients and
  26.  * Collins 4-240 for derivatives. The recursions are transformed into
  27.  * composition of linear transformations to obtain the associated polynomials
  28.  * for coefficients and their derivatives - see Petre's paper
  29.  *
  30.  * @author Petre Bazavan
  31.  * @author Lucian Barbulescu
  32.  */
  33. public class HansenTesseralLinear {

  34.     /** The number of coefficients that will be computed with a set of roots. */
  35.     private static final int SLICE = 10;

  36.     /**
  37.      * The first vector of polynomials associated to Hansen coefficients and
  38.      * derivatives.
  39.      */
  40.     private PolynomialFunction[][] mpvec;

  41.     /** The second vector of polynomials associated only to derivatives. */
  42.     private PolynomialFunction[][] mpvecDeriv;

  43.     /** The Hansen coefficients used as roots. */
  44.     private final double[][] hansenRoot;

  45.     /** The derivatives of the Hansen coefficients used as roots. */
  46.     private final double[][] hansenDerivRoot;

  47.     /** The minimum value for the order. */
  48.     private final int Nmin;

  49.     /** The index of the initial condition, Petre's paper. */
  50.     private final int N0;

  51.     /** The number of slices needed to compute the coefficients. */
  52.     private final int numSlices;

  53.     /**
  54.      * The offset used to identify the polynomial that corresponds to a negative.
  55.      * value of n in the internal array that starts at 0
  56.      */
  57.     private final int offset;

  58.     /** The objects used to calculate initial data by means of Newcomb operators. */
  59.     private final HansenCoefficientsBySeries[] hansenInit;

  60.     /**
  61.      * Constructor.
  62.      *
  63.      * @param nMax the maximum (absolute) value of n parameter
  64.      * @param s s parameter
  65.      * @param j j parameter
  66.      * @param n0 the minimum (absolute) value of n
  67.      * @param maxHansen maximum power of e2 in Hansen expansion
  68.      */
  69.     public HansenTesseralLinear(final int nMax, final int s, final int j, final int n0, final int maxHansen) {
  70.         //Initialize the fields
  71.         this.offset = nMax + 1;
  72.         this.Nmin = -nMax - 1;
  73.         this.N0 = -n0 - 4;

  74.         //Ensure that only the needed terms are computed
  75.         final int maxRoots = FastMath.min(4, N0 - Nmin + 4);
  76.         this.hansenInit = new HansenCoefficientsBySeries[maxRoots];
  77.         for (int i = 0; i < maxRoots; i++) {
  78.             this.hansenInit[i] = new HansenCoefficientsBySeries(N0 - i + 3, s, j, maxHansen);
  79.         }

  80.         // The first 4 values are computed with series. No linear combination is needed.
  81.         final int size = N0 - Nmin;
  82.         this.numSlices = (int) FastMath.max(FastMath.ceil(((double) size) / SLICE), 1);
  83.         hansenRoot = new double[numSlices][4];
  84.         hansenDerivRoot = new double[numSlices][4];
  85.         if (size > 0) {
  86.             mpvec = new PolynomialFunction[size][];
  87.             mpvecDeriv = new PolynomialFunction[size][];

  88.             // Prepare the database of the associated polynomials
  89.             HansenUtilities.generateTesseralPolynomials(N0, Nmin, offset, SLICE, j, s,
  90.                                                         mpvec, mpvecDeriv);
  91.         }

  92.     }

  93.     /**
  94.      * Compute the values for the first four coefficients and their derivatives by means of series.
  95.      *
  96.      * @param e2 e²
  97.      * @param chi &Chi;
  98.      * @param chi2 &Chi;²
  99.      */
  100.     public void computeInitValues(final double e2, final double chi, final double chi2) {
  101.         // compute the values for n, n+1, n+2 and n+3 by series
  102.         // See Danielson 2.7.3-(10)
  103.         //Ensure that only the needed terms are computed
  104.         final int maxRoots = FastMath.min(4, N0 - Nmin + 4);
  105.         for (int i = 0; i < maxRoots; i++) {
  106.             final Gradient hansenKernel = hansenInit[i].getValueGradient(e2, chi, chi2);
  107.             this.hansenRoot[0][i] = hansenKernel.getValue();
  108.             this.hansenDerivRoot[0][i] = hansenKernel.getPartialDerivative(0);
  109.         }

  110.         for (int i = 1; i < numSlices; i++) {
  111.             for (int k = 0; k < 4; k++) {
  112.                 final PolynomialFunction[] mv = mpvec[N0 - (i * SLICE) - k + 3 + offset];
  113.                 final PolynomialFunction[] sv = mpvecDeriv[N0 - (i * SLICE) - k + 3 + offset];

  114.                 hansenDerivRoot[i][k] = mv[3].value(chi) * hansenDerivRoot[i - 1][3] +
  115.                                         mv[2].value(chi) * hansenDerivRoot[i - 1][2] +
  116.                                         mv[1].value(chi) * hansenDerivRoot[i - 1][1] +
  117.                                         mv[0].value(chi) * hansenDerivRoot[i - 1][0] +
  118.                                         sv[3].value(chi) * hansenRoot[i - 1][3] +
  119.                                         sv[2].value(chi) * hansenRoot[i - 1][2] +
  120.                                         sv[1].value(chi) * hansenRoot[i - 1][1] +
  121.                                         sv[0].value(chi) * hansenRoot[i - 1][0];

  122.                 hansenRoot[i][k] =  mv[3].value(chi) * hansenRoot[i - 1][3] +
  123.                                     mv[2].value(chi) * hansenRoot[i - 1][2] +
  124.                                     mv[1].value(chi) * hansenRoot[i - 1][1] +
  125.                                     mv[0].value(chi) * hansenRoot[i - 1][0];
  126.             }
  127.         }
  128.     }

  129.     /**
  130.      * Compute the value of the Hansen coefficient K<sub>j</sub><sup>-n-1, s</sup>.
  131.      *
  132.      * @param mnm1 -n-1
  133.      * @param chi χ
  134.      * @return the coefficient K<sub>j</sub><sup>-n-1, s</sup>
  135.      */
  136.     public double getValue(final int mnm1, final double chi) {
  137.         //Compute n
  138.         final int n = -mnm1 - 1;

  139.         //Compute the potential slice
  140.         int sliceNo = (n + N0 + 4) / SLICE;
  141.         if (sliceNo < numSlices) {
  142.             //Compute the index within the slice
  143.             final int indexInSlice = (n + N0 + 4) % SLICE;

  144.             //Check if a root must be returned
  145.             if (indexInSlice <= 3) {
  146.                 return hansenRoot[sliceNo][indexInSlice];
  147.             }
  148.         } else {
  149.             //the value was a potential root for a slice, but that slice was not required
  150.             //Decrease the slice number
  151.             sliceNo--;
  152.         }

  153.         // Computes the coefficient by linear transformation
  154.         // Danielson 2.7.3-(9) or Collins 4-236 and Petre's paper
  155.         final PolynomialFunction[] v = mpvec[mnm1 + offset];
  156.         return v[3].value(chi) * hansenRoot[sliceNo][3] +
  157.                v[2].value(chi) * hansenRoot[sliceNo][2] +
  158.                v[1].value(chi) * hansenRoot[sliceNo][1] +
  159.                v[0].value(chi) * hansenRoot[sliceNo][0];

  160.     }

  161.     /**
  162.      * Compute the value of the derivative dK<sub>j</sub><sup>-n-1, s</sup> / de².
  163.      *
  164.      * @param mnm1 -n-1
  165.      * @param chi χ
  166.      * @return the derivative dK<sub>j</sub><sup>-n-1, s</sup> / de²
  167.      */
  168.     public double getDerivative(final int mnm1, final double chi) {

  169.         //Compute n
  170.         final int n = -mnm1 - 1;

  171.         //Compute the potential slice
  172.         int sliceNo = (n + N0 + 4) / SLICE;
  173.         if (sliceNo < numSlices) {
  174.             //Compute the index within the slice
  175.             final int indexInSlice = (n + N0 + 4) % SLICE;

  176.             //Check if a root must be returned
  177.             if (indexInSlice <= 3) {
  178.                 return hansenDerivRoot[sliceNo][indexInSlice];
  179.             }
  180.         } else {
  181.             //the value was a potential root for a slice, but that slice was not required
  182.             //Decrease the slice number
  183.             sliceNo--;
  184.         }

  185.         // Computes the coefficient by linear transformation
  186.         // Danielson 2.7.3-(9) or Collins 4-236 and Petre's paper
  187.         final PolynomialFunction[] v = mpvec[mnm1 + this.offset];
  188.         final PolynomialFunction[] vv = mpvecDeriv[mnm1 + this.offset];

  189.         return v[3].value(chi)  * hansenDerivRoot[sliceNo][3] +
  190.                v[2].value(chi)  * hansenDerivRoot[sliceNo][2] +
  191.                v[1].value(chi)  * hansenDerivRoot[sliceNo][1] +
  192.                v[0].value(chi)  * hansenDerivRoot[sliceNo][0] +
  193.                vv[3].value(chi) * hansenRoot[sliceNo][3] +
  194.                vv[2].value(chi) * hansenRoot[sliceNo][2] +
  195.                vv[1].value(chi) * hansenRoot[sliceNo][1] +
  196.                vv[0].value(chi) * hansenRoot[sliceNo][0];

  197.     }

  198.     /**
  199.      * Compute a Hansen coefficient with series.
  200.      * <p>
  201.      * This class implements the computation of the Hansen kernels
  202.      * through a power series in e² and that is using
  203.      * modified Newcomb operators. The reference formulae can be found
  204.      * in Danielson 2.7.3-10 and 3.3-5
  205.      * </p>
  206.      */
  207.     private static class HansenCoefficientsBySeries {

  208.         /** -n-1 coefficient. */
  209.         private final int mnm1;

  210.         /** s coefficient. */
  211.         private final int s;

  212.         /** j coefficient. */
  213.         private final int j;

  214.         /** Max power in e² for the Newcomb's series expansion. */
  215.         private final int maxNewcomb;

  216.         /** Polynomial representing the serie. */
  217.         private final PolynomialFunction polynomial;

  218.         /**
  219.          * Class constructor.
  220.          *
  221.          * @param mnm1 -n-1 value
  222.          * @param s s value
  223.          * @param j j value
  224.          * @param maxHansen max power of e² in series expansion
  225.          */
  226.         HansenCoefficientsBySeries(final int mnm1, final int s,
  227.                                           final int j, final int maxHansen) {
  228.             this.mnm1 = mnm1;
  229.             this.s = s;
  230.             this.j = j;
  231.             this.maxNewcomb = maxHansen;
  232.             this.polynomial = generatePolynomial();
  233.         }

  234.         /** Computes the value of Hansen kernel and its derivative at e².
  235.          * <p>
  236.          * The formulae applied are described in Danielson 2.7.3-10 and
  237.          * 3.3-5
  238.          * </p>
  239.          * @param e2 e²
  240.          * @param chi &Chi;
  241.          * @param chi2 &Chi;²
  242.          * @return the value of the Hansen coefficient and its derivative for e²
  243.          */
  244.         public Gradient getValueGradient(final double e2, final double chi, final double chi2) {

  245.             //Estimation of the serie expansion at e2
  246.             final Gradient serie = polynomial.value(Gradient.variable(1, 0, e2));

  247.             final double value      =  FastMath.pow(chi2, -mnm1 - 1) * serie.getValue() / chi;
  248.             final double coef       = -(mnm1 + 1.5);
  249.             final double derivative = coef * chi2 * value +
  250.                                       FastMath.pow(chi2, -mnm1 - 1) * serie.getPartialDerivative(0) / chi;
  251.             return new Gradient(value, derivative);
  252.         }

  253.         /** Generate the serie expansion in e².
  254.          * <p>
  255.          * Generate the series expansion in e² used in the formulation
  256.          * of the Hansen kernel (see Danielson 2.7.3-10):
  257.          * &Sigma; Y<sup>ns</sup><sub>α+a,α+b</sub>
  258.          * *e<sup>2α</sup>
  259.          * </p>
  260.          * @return polynomial representing the power serie expansion
  261.          */
  262.         private PolynomialFunction generatePolynomial() {
  263.             // Initialization
  264.             final int aHT = FastMath.max(j - s, 0);
  265.             final int bHT = FastMath.max(s - j, 0);

  266.             final double[] coefficients = new double[maxNewcomb + 1];

  267.             //Loop for getting the Newcomb operators
  268.             for (int alphaHT = 0; alphaHT <= maxNewcomb; alphaHT++) {
  269.                 coefficients[alphaHT] =
  270.                         NewcombOperators.getValue(alphaHT + aHT, alphaHT + bHT, mnm1, s);
  271.             }

  272.             //Creation of the polynomial
  273.             return new PolynomialFunction(coefficients);
  274.         }
  275.     }

  276. }