FieldHansenZonalLinear.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.Field;
  19. import org.hipparchus.CalculusFieldElement;
  20. import org.hipparchus.analysis.polynomials.PolynomialFunction;
  21. import org.hipparchus.util.FastMath;
  22. import org.hipparchus.util.MathArrays;

  23. /**
  24.  * Hansen coefficients K(t,n,s) for t=0 and n < 0.
  25.  * <p>
  26.  *Implements Collins 4-242 or echivalently, Danielson 2.7.3-(6) for Hansen Coefficients and
  27.  * Collins 4-245 or Danielson 3.1-(7) for derivatives. The recursions are transformed into
  28.  * composition of linear transformations to obtain the associated polynomials
  29.  * for coefficients and their derivatives - see Petre's paper
  30.  *
  31.  * @author Petre Bazavan
  32.  * @author Lucian Barbulescu
  33.  * @author Bryan Cazabonne
  34.  * @param <T> type of the field elements
  35.  */
  36. public class FieldHansenZonalLinear <T extends CalculusFieldElement<T>> {

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

  39.     /**
  40.      * The first vector of polynomials associated to Hansen coefficients and
  41.      * derivatives.
  42.      */
  43.     private PolynomialFunction[][] mpvec;

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

  46.     /** The Hansen coefficients used as roots. */
  47.     private T[][] hansenRoot;

  48.     /** The derivatives of the Hansen coefficients used as roots. */
  49.     private T[][] hansenDerivRoot;

  50.     /** The minimum value for the order. */
  51.     private int Nmin;


  52.     /** The index of the initial condition, Petre's paper. */
  53.     private int N0;

  54.     /** The s coefficient. */
  55.     private int s;

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

  61.     /** The number of slices needed to compute the coefficients. */
  62.     private int numSlices;

  63.     /** 2<sup>s</sup>. */
  64.     private double twots;

  65.     /** 2*s+1. */
  66.     private int twosp1;

  67.     /** 2*s. */
  68.     private int twos;

  69.     /** (2*s+1) / 2<sup>s</sup>. */
  70.     private double twosp1otwots;

  71.     /**
  72.      * Constructor.
  73.      *
  74.      * @param nMax the maximum (absolute) value of n coefficient
  75.      * @param s s coefficient
  76.      * @param field field used by default
  77.      */
  78.     public FieldHansenZonalLinear(final int nMax, final int s, final Field<T> field) {
  79.         //Initialize fields
  80.         this.offset = nMax + 1;
  81.         this.Nmin = -nMax - 1;
  82.         N0 = -(s + 2);
  83.         this.s = s;
  84.         this.twots = FastMath.pow(2., s);
  85.         this.twos = 2 * s;
  86.         this.twosp1 = this.twos + 1;
  87.         this.twosp1otwots = (double) this.twosp1 / this.twots;

  88.         // prepare structures for stored data
  89.         final int size = nMax - s - 1;
  90.         mpvec      = new PolynomialFunction[size][];
  91.         mpvecDeriv = new PolynomialFunction[size][];

  92.         this.numSlices  = FastMath.max((int) FastMath.ceil(((double) size) / SLICE), 1);
  93.         hansenRoot      = MathArrays.buildArray(field, numSlices, 2);
  94.         hansenDerivRoot = MathArrays.buildArray(field, numSlices, 2);

  95.         // Prepare the data base of associated polynomials
  96.         generatePolynomials();

  97.     }

  98.     /**
  99.      * Compute polynomial coefficient a.
  100.      *
  101.      *  <p>
  102.      *  It is used to generate the coefficient for K₀<sup>-n, s</sup> when computing K₀<sup>-n-1, s</sup>
  103.      *  and the coefficient for dK₀<sup>-n, s</sup> / de² when computing dK₀<sup>-n-1, s</sup> / de²
  104.      *  </p>
  105.      *
  106.      *  <p>
  107.      *  See Danielson 2.7.3-(6) and Collins 4-242 and 4-245
  108.      *  </p>
  109.      *
  110.      * @param mnm1 -n-1 value
  111.      * @return the polynomial
  112.      */
  113.     private PolynomialFunction a(final int mnm1) {
  114.         // from recurence Collins 4-242
  115.         final double d1 = (mnm1 + 2) * (2 * mnm1 + 5);
  116.         final double d2 = (mnm1 + 2 - s) * (mnm1 + 2 + s);
  117.         return new PolynomialFunction(new double[] {
  118.             0.0, 0.0, d1 / d2
  119.         });
  120.     }

  121.     /**
  122.      * Compute polynomial coefficient b.
  123.      *
  124.      *  <p>
  125.      *  It is used to generate the coefficient for K₀<sup>-n+1, s</sup> when computing K₀<sup>-n-1, s</sup>
  126.      *  and the coefficient for dK₀<sup>-n+1, s</sup> / de² when computing dK₀<sup>-n-1, s</sup> / de²
  127.      *  </p>
  128.      *
  129.      *  <p>
  130.      *  See Danielson 2.7.3-(6) and Collins 4-242 and 4-245
  131.      *  </p>
  132.      *
  133.      * @param mnm1 -n-1 value
  134.      * @return the polynomial
  135.      */
  136.     private PolynomialFunction b(final int mnm1) {
  137.         // from recurence Collins 4-242
  138.         final double d1 = (mnm1 + 2) * (mnm1 + 3);
  139.         final double d2 = (mnm1 + 2 - s) * (mnm1 + 2 + s);
  140.         return new PolynomialFunction(new double[] {
  141.             0.0, 0.0, -d1 / d2
  142.         });
  143.     }

  144.     /**
  145.      * Generate the polynomials needed in the linear transformation.
  146.      *
  147.      * <p>
  148.      * See Petre's paper
  149.      * </p>
  150.      */
  151.     private void generatePolynomials() {

  152.         int sliceCounter = 0;
  153.         int index;

  154.         // Initialisation of matrix for linear transformmations
  155.         // The final configuration of these matrix are obtained by composition
  156.         // of linear transformations
  157.         PolynomialFunctionMatrix A = HansenUtilities.buildIdentityMatrix2();
  158.         PolynomialFunctionMatrix D = HansenUtilities.buildZeroMatrix2();
  159.         PolynomialFunctionMatrix E = HansenUtilities.buildIdentityMatrix2();

  160.         // generation of polynomials associated to Hansen coefficients and to
  161.         // their derivatives
  162.         final PolynomialFunctionMatrix a = HansenUtilities.buildZeroMatrix2();
  163.         a.setElem(0, 1, HansenUtilities.ONE);

  164.         //The B matrix is constant.
  165.         final PolynomialFunctionMatrix B = HansenUtilities.buildZeroMatrix2();
  166.         // from Collins 4-245 and Petre's paper
  167.         B.setElem(1, 1, new PolynomialFunction(new double[] {
  168.             2.0
  169.         }));

  170.         for (int i = N0 - 1; i > Nmin - 1; i--) {
  171.             index = i + offset;
  172.             // Matrix of the current linear transformation
  173.             // Petre's paper
  174.             a.setMatrixLine(1, new PolynomialFunction[] {
  175.                 b(i), a(i)
  176.             });
  177.             // composition of linear transformations
  178.             // see Petre's paper
  179.             A = A.multiply(a);
  180.             // store the polynomials for Hansen coefficients
  181.             mpvec[index] = A.getMatrixLine(1);

  182.             D = D.multiply(a);
  183.             E = E.multiply(a);
  184.             D = D.add(E.multiply(B));

  185.             // store the polynomials for Hansen coefficients from the expressions
  186.             // of derivatives
  187.             mpvecDeriv[index] = D.getMatrixLine(1);

  188.             if (++sliceCounter % SLICE == 0) {
  189.                 // Re-Initialisation of matrix for linear transformmations
  190.                 // The final configuration of these matrix are obtained by composition
  191.                 // of linear transformations
  192.                 A = HansenUtilities.buildIdentityMatrix2();
  193.                 D = HansenUtilities.buildZeroMatrix2();
  194.                 E = HansenUtilities.buildIdentityMatrix2();
  195.             }

  196.         }
  197.     }

  198.     /**
  199.      * Compute the roots for the Hansen coefficients and their derivatives.
  200.      *
  201.      * @param chi 1 / sqrt(1 - e²)
  202.      */
  203.     public void computeInitValues(final T chi) {
  204.         final Field<T> field = chi.getField();
  205.         final T zero = field.getZero();
  206.         // compute the values for n=s and n=s+1
  207.         // See Danielson 2.7.3-(6a,b)
  208.         hansenRoot[0][0] = zero;
  209.         hansenRoot[0][1] = FastMath.pow(chi, this.twosp1).divide(this.twots);
  210.         hansenDerivRoot[0][0] = zero;
  211.         hansenDerivRoot[0][1] = FastMath.pow(chi, this.twos).multiply(this.twosp1otwots);

  212.         final int st = -s - 1;
  213.         for (int i = 1; i < numSlices; i++) {
  214.             for (int j = 0; j < 2; j++) {
  215.                 // Get the required polynomials
  216.                 final PolynomialFunction[] mv = mpvec[st - (i * SLICE) - j + offset];
  217.                 final PolynomialFunction[] sv = mpvecDeriv[st - (i * SLICE) - j + offset];

  218.                 //Compute the root derivatives
  219.                 hansenDerivRoot[i][j] = mv[1].value(chi).multiply(hansenDerivRoot[i - 1][1]).
  220.                                         add(mv[0].value(chi).multiply(hansenDerivRoot[i - 1][0])).
  221.                                         add((sv[1].value(chi).multiply(hansenRoot[i - 1][1]).
  222.                                         add(sv[0].value(chi).multiply(hansenRoot[i - 1][0]))
  223.                                         ).divide(chi));
  224.                 hansenRoot[i][j] =     mv[1].value(chi).multiply(hansenRoot[i - 1][1]).
  225.                                        add(mv[0].value(chi).multiply(hansenRoot[i - 1][0]));

  226.             }

  227.         }
  228.     }

  229.     /**
  230.      * Get the K₀<sup>-n-1,s</sup> coefficient value.
  231.      *
  232.      * <p> The s value is given in the class constructor
  233.      *
  234.      * @param mnm1 (-n-1) coefficient
  235.      * @param chi The value of χ
  236.      * @return K₀<sup>-n-1,s</sup>
  237.      */
  238.     public T getValue(final int mnm1, final T chi) {
  239.         //Compute n
  240.         final int n = -mnm1 - 1;

  241.         //Compute the potential slice
  242.         int sliceNo = (n - s) / SLICE;
  243.         if (sliceNo < numSlices) {
  244.             //Compute the index within the slice
  245.             final int indexInSlice = (n - s) % SLICE;

  246.             //Check if a root must be returned
  247.             if (indexInSlice <= 1) {
  248.                 return hansenRoot[sliceNo][indexInSlice];
  249.             }
  250.         } else {
  251.             //the value was a potential root for a slice, but that slice was not required
  252.             //Decrease the slice number
  253.             sliceNo--;
  254.         }

  255.         // Danielson 2.7.3-(6c)/Collins 4-242 and Petre's paper
  256.         final PolynomialFunction[] v = mpvec[mnm1 + offset];
  257.         T ret = v[1].value(chi).multiply(hansenRoot[sliceNo][1]);
  258.         if (hansenRoot[sliceNo][0].getReal() != 0) {
  259.             ret = ret.add(v[0].value(chi).multiply(hansenRoot[sliceNo][0]));
  260.         }
  261.         return  ret;
  262.     }

  263.     /**
  264.      * Get the dK₀<sup>-n-1,s</sup> / d&Chi; coefficient derivative.
  265.      *
  266.      * <p> The s value is given in the class constructor.
  267.      *
  268.      * @param mnm1 (-n-1) coefficient
  269.      * @param chi The value of χ
  270.      * @return dK₀<sup>-n-1,s</sup> / d&Chi;
  271.      */
  272.     public T getDerivative(final int mnm1, final T chi) {
  273.         //Compute n
  274.         final int n = -mnm1 - 1;

  275.         //Compute the potential slice
  276.         int sliceNo = (n - s) / SLICE;
  277.         if (sliceNo < numSlices) {
  278.             //Compute the index within the slice
  279.             final int indexInSlice = (n - s) % SLICE;

  280.             //Check if a root must be returned
  281.             if (indexInSlice <= 1) {
  282.                 return hansenDerivRoot[sliceNo][indexInSlice];
  283.             }
  284.         } else {
  285.             //the value was a potential root for a slice, but that slice was not required
  286.             //Decrease the slice number
  287.             sliceNo--;
  288.         }

  289.         // Danielson 3.1-(7c) and Petre's paper
  290.         final PolynomialFunction[] v = mpvec[mnm1 + offset];
  291.         T ret = v[1].value(chi).multiply(hansenDerivRoot[sliceNo][1]);
  292.         if (hansenDerivRoot[sliceNo][0].getReal() != 0) {
  293.             ret = ret.add(v[0].value(chi).multiply(hansenDerivRoot[sliceNo][0]));
  294.         }

  295.         // Danielson 2.7.3-(6b)
  296.         final PolynomialFunction[] v1 = mpvecDeriv[mnm1 + offset];
  297.         T hret = v1[1].value(chi).multiply(hansenRoot[sliceNo][1]);
  298.         if (hansenRoot[sliceNo][0].getReal() != 0) {
  299.             hret = hret.add(v1[0].value(chi).multiply(hansenRoot[sliceNo][0]));
  300.         }
  301.         ret = ret.add(hret.divide(chi));

  302.         return ret;

  303.     }

  304. }