HansenZonalLinear.java

  1. /* Copyright 2002-2025 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.polynomials.PolynomialFunction;
  19. import org.hipparchus.util.FastMath;

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

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

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

  39.     /** The second vector of polynomials associated only to derivatives. */
  40.     private final PolynomialFunction[][] mpvecDeriv;

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

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

  45.     /** The s coefficient. */
  46.     private final int s;

  47.     /**
  48.      * The offset used to identify the polynomial that corresponds to a negative
  49.      * value of n in the internal array that starts at 0.
  50.      */
  51.     private final int offset;

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

  54.     /** 2<sup>s</sup>. */
  55.     private final double twots;

  56.     /** 2*s+1. */
  57.     private final int twosp1;

  58.     /** 2*s. */
  59.     private final int twos;

  60.     /** (2*s+1) / 2<sup>s</sup>. */
  61.     private final double twosp1otwots;

  62.     /**
  63.      * Constructor.
  64.      *
  65.      * @param nMax the maximum (absolute) value of n coefficient
  66.      * @param s s coefficient
  67.      */
  68.     public HansenZonalLinear(final int nMax, final int s) {

  69.         //Initialize fields
  70.         final int Nmin = -nMax - 1;
  71.         final int N0 = -(s + 2);
  72.         this.offset = nMax + 1;
  73.         this.s = s;
  74.         this.twots = FastMath.pow(2., s);
  75.         this.twos = 2 * s;
  76.         this.twosp1 = this.twos + 1;
  77.         this.twosp1otwots = (double) this.twosp1 / this.twots;

  78.         // prepare structures for stored data
  79.         final int size = nMax - s - 1;
  80.         mpvec      = new PolynomialFunction[size][];
  81.         mpvecDeriv = new PolynomialFunction[size][];

  82.         this.numSlices  = FastMath.max((int) FastMath.ceil(((double) size) / SLICE), 1);
  83.         hansenRoot      = new double[numSlices][2];
  84.         hansenDerivRoot = new double[numSlices][2];

  85.         // Prepare the data base of associated polynomials
  86.         HansenUtilities.generateZonalPolynomials(N0, Nmin, offset, SLICE, s,
  87.                                                  mpvec, mpvecDeriv);

  88.     }

  89.     /**
  90.      * Compute the roots for the Hansen coefficients and their derivatives.
  91.      *
  92.      * @param chi 1 / sqrt(1 - e²)
  93.      */
  94.     public void computeInitValues(final double chi) {
  95.         // compute the values for n=s and n=s+1
  96.         // See Danielson 2.7.3-(6a,b)
  97.         hansenRoot[0][0] = 0;
  98.         hansenRoot[0][1] = FastMath.pow(chi, this.twosp1) / this.twots;
  99.         hansenDerivRoot[0][0] = 0;
  100.         hansenDerivRoot[0][1] = this.twosp1otwots * FastMath.pow(chi, this.twos);

  101.         final int st = -s - 1;
  102.         for (int i = 1; i < numSlices; i++) {
  103.             for (int j = 0; j < 2; j++) {
  104.                 // Get the required polynomials
  105.                 final PolynomialFunction[] mv = mpvec[st - (i * SLICE) - j + offset];
  106.                 final PolynomialFunction[] sv = mpvecDeriv[st - (i * SLICE) - j + offset];

  107.                 //Compute the root derivatives
  108.                 hansenDerivRoot[i][j] = mv[1].value(chi) * hansenDerivRoot[i - 1][1] +
  109.                                         mv[0].value(chi) * hansenDerivRoot[i - 1][0] +
  110.                                         (sv[1].value(chi) * hansenRoot[i - 1][1] +
  111.                                          sv[0].value(chi) * hansenRoot[i - 1][0]
  112.                                         ) / chi;
  113.                 hansenRoot[i][j] =     mv[1].value(chi) * hansenRoot[i - 1][1] +
  114.                                        mv[0].value(chi) * hansenRoot[i - 1][0];

  115.             }

  116.         }
  117.     }

  118.     /**
  119.      * Get the K₀<sup>-n-1,s</sup> coefficient value.
  120.      *
  121.      * <p> The s value is given in the class constructor
  122.      *
  123.      * @param mnm1 (-n-1) coefficient
  124.      * @param chi The value of χ
  125.      * @return K₀<sup>-n-1,s</sup>
  126.      */
  127.     public double getValue(final int mnm1, final double chi) {

  128.         //Compute n
  129.         final int n = -mnm1 - 1;

  130.         //Compute the potential slice
  131.         int sliceNo = (n - s) / SLICE;
  132.         if (sliceNo < numSlices) {
  133.             //Compute the index within the slice
  134.             final int indexInSlice = (n - s) % SLICE;

  135.             //Check if a root must be returned
  136.             if (indexInSlice <= 1) {
  137.                 return hansenRoot[sliceNo][indexInSlice];
  138.             }
  139.         } else {
  140.             //the value was a potential root for a slice, but that slice was not required
  141.             //Decrease the slice number
  142.             sliceNo--;
  143.         }

  144.         // Danielson 2.7.3-(6c)/Collins 4-242 and Petre's paper
  145.         final PolynomialFunction[] v = mpvec[mnm1 + offset];
  146.         double ret = v[1].value(chi) * hansenRoot[sliceNo][1];
  147.         if (hansenRoot[sliceNo][0] != 0) {
  148.             ret += v[0].value(chi) * hansenRoot[sliceNo][0];
  149.         }
  150.         return  ret;
  151.     }

  152.     /**
  153.      * Get the dK₀<sup>-n-1,s</sup> / d&Chi; coefficient derivative.
  154.      *
  155.      * <p> The s value is given in the class constructor.
  156.      *
  157.      * @param mnm1 (-n-1) coefficient
  158.      * @param chi The value of χ
  159.      * @return dK₀<sup>-n-1,s</sup> / d&Chi;
  160.      */
  161.     public double getDerivative(final int mnm1, final double chi) {

  162.         //Compute n
  163.         final int n = -mnm1 - 1;

  164.         //Compute the potential slice
  165.         int sliceNo = (n - s) / SLICE;
  166.         if (sliceNo < numSlices) {
  167.             //Compute the index within the slice
  168.             final int indexInSlice = (n - s) % SLICE;

  169.             //Check if a root must be returned
  170.             if (indexInSlice <= 1) {
  171.                 return hansenDerivRoot[sliceNo][indexInSlice];
  172.             }
  173.         } else {
  174.             //the value was a potential root for a slice, but that slice was not required
  175.             //Decrease the slice number
  176.             sliceNo--;
  177.         }

  178.         // Danielson 3.1-(7c) and Petre's paper
  179.         final PolynomialFunction[] v = mpvec[mnm1 + offset];
  180.         double ret = v[1].value(chi) * hansenDerivRoot[sliceNo][1];
  181.         if (hansenDerivRoot[sliceNo][0] != 0) {
  182.             ret += v[0].value(chi) * hansenDerivRoot[sliceNo][0];
  183.         }

  184.         // Danielson 2.7.3-(6b)
  185.         final PolynomialFunction[] v1 = mpvecDeriv[mnm1 + offset];
  186.         double hret = v1[1].value(chi) * hansenRoot[sliceNo][1];
  187.         if (hansenRoot[sliceNo][0] != 0) {
  188.             hret += v1[0].value(chi) * hansenRoot[sliceNo][0];
  189.         }
  190.         ret += hret / chi;

  191.         return ret;

  192.     }

  193. }