FieldHansenThirdBodyLinear.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-254 or Danielson 2.7.3-(7) for Hansen Coefficients and
  27.  * Danielson 3.2-(3) 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 FieldHansenThirdBodyLinear <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 number of slices needed to compute the coefficients. */
  51.     private int numSlices;

  52.     /** The maximum order of n indexes. */
  53.     private int nMax;

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

  56.     /** The s index. */
  57.     private int s;

  58.     /** (-1)<sup>s</sup> * (2*s + 1)!! / (s+1)!  */
  59.     private double twosp1dfosp1f;

  60.     /** (-1)<sup>s</sup> * (2*s + 1)!! / (s+2)!  */
  61.     private double twosp1dfosp2f;

  62.     /** (-1)<sup>s</sup> * 2 * (2*s + 1)!! / (s+2)!  */
  63.     private double two2sp1dfosp2f;

  64.     /** (2*s + 3). */
  65.     private double twosp3;

  66.     /**
  67.      * Constructor.
  68.      *
  69.      * @param nMax the maximum value of n
  70.      * @param s the value of s
  71.      * @param field field used by default
  72.      */
  73.     public FieldHansenThirdBodyLinear(final int nMax, final int s, final Field<T> field) {
  74.         // initialise fields
  75.         this.nMax = nMax;
  76.         N0 = s;
  77.         this.s = s;

  78.         // initialization of structures for stored data
  79.         mpvec = new PolynomialFunction[this.nMax + 1][];
  80.         mpvecDeriv = new PolynomialFunction[this.nMax + 1][];

  81.         //Compute the fields that will be used to determine the initial values for the coefficients
  82.         this.twosp1dfosp1f = (s % 2 == 0) ? 1.0 : -1.0;
  83.         for (int i = s; i >= 1; i--) {
  84.             this.twosp1dfosp1f *= (2.0 * i + 1.0) / (i + 1.0);
  85.         }

  86.         this.twosp1dfosp2f = this.twosp1dfosp1f / (s + 2.);
  87.         this.twosp3 = 2 * s + 3;
  88.         this.two2sp1dfosp2f = 2 * this.twosp1dfosp2f;

  89.         // initialization of structures for stored data
  90.         mpvec = new PolynomialFunction[this.nMax + 1][];
  91.         mpvecDeriv = new PolynomialFunction[this.nMax + 1][];

  92.         this.numSlices  = FastMath.max(1, (nMax - s + SLICE - 2) / SLICE);

  93.         hansenRoot      = MathArrays.buildArray(field, numSlices, 2);
  94.         hansenDerivRoot = MathArrays.buildArray(field, numSlices, 2);

  95.         // Prepare the database of the 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-1, s</sup> when computing K₀<sup>n, s</sup>
  103.      *  and the coefficient for dK₀<sup>n-1, s</sup> / d&Chi; when computing dK₀<sup>n, s</sup> / d&Chi;
  104.      *  </p>
  105.      *
  106.      *  <p>
  107.      *  See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
  108.      *  </p>
  109.      *
  110.      * @param n n value
  111.      * @return the polynomial
  112.      */
  113.     private PolynomialFunction a(final int n) {
  114.         // from recurrence Danielson 2.7.3-(7c), Collins 4-254
  115.         final double r1 = 2 * n + 1;
  116.         final double r2 = n + 1;

  117.         return new PolynomialFunction(new double[] {
  118.             r1 / r2
  119.         });
  120.     }

  121.     /**
  122.      * Compute polynomial coefficient b.
  123.      *
  124.      *  <p>
  125.      *  It is used to generate the coefficient for K₀<sup>n-2, s</sup> when computing K₀<sup>n, s</sup>
  126.      *  and the coefficient for dK₀<sup>n-2, s</sup> / d&Chi; when computing dK₀<sup>n, s</sup> / d&Chi;
  127.      *  </p>
  128.      *
  129.      *  <p>
  130.      *  See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
  131.      *  </p>
  132.      *
  133.      * @param n n value
  134.      * @return the polynomial
  135.      */
  136.     private PolynomialFunction b(final int n) {
  137.         // from recurrence Danielson 2.7.3-(7c), Collins 4-254
  138.         final double r1 = (n + s) * (n - s);
  139.         final double r2 = n * (n + 1);

  140.         return new PolynomialFunction(new double[] {
  141.             0.0, 0.0, -r1 / r2
  142.         });
  143.     }

  144.     /**
  145.      * Compute polynomial coefficient d.
  146.      *
  147.      *  <p>
  148.      *  It is used to generate the coefficient for K₀<sup>n-2, s</sup> when computing dK₀<sup>n, s</sup> / d&Chi;
  149.      *  </p>
  150.      *
  151.      *  <p>
  152.      *  See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
  153.      *  </p>
  154.      *
  155.      * @param n n value
  156.      * @return the polynomial
  157.      */
  158.     private PolynomialFunction d(final int n) {
  159.         // from Danielson 3.2-(3b)
  160.         final double r1 = 2 * (n + s) * (n - s);
  161.         final double r2 = n * (n + 1);

  162.         return new PolynomialFunction(new double[] {
  163.             0.0, 0.0, 0.0, r1 / r2
  164.         });
  165.     }

  166.     /**
  167.      * Generate the polynomials needed in the linear transformation.
  168.      *
  169.      * <p>
  170.      * See Petre's paper
  171.      * </p>
  172.      */
  173.     private void generatePolynomials() {

  174.         int sliceCounter = 0;

  175.         // Initialization of the matrices for linear transformations
  176.         // The final configuration of these matrices are obtained by composition
  177.         // of linear transformations

  178.         // the matrix A for the polynomials associated
  179.         // to Hansen coefficients, Petre's pater
  180.         PolynomialFunctionMatrix A = HansenUtilities.buildIdentityMatrix2();

  181.         // the matrix D for the polynomials associated
  182.         // to derivatives, Petre's paper
  183.         final PolynomialFunctionMatrix B = HansenUtilities.buildZeroMatrix2();
  184.         PolynomialFunctionMatrix D = HansenUtilities.buildZeroMatrix2();
  185.         PolynomialFunctionMatrix E = HansenUtilities.buildIdentityMatrix2();

  186.         // The matrix that contains the coefficients at each step
  187.         final PolynomialFunctionMatrix a = HansenUtilities.buildZeroMatrix2();
  188.         a.setElem(0, 1, HansenUtilities.ONE);

  189.         // The generation process
  190.         for (int i = N0 + 2; i <= nMax; i++) {
  191.             // Collins 4-254 or Danielson 2.7.3-(7)
  192.             // Petre's paper
  193.             // The matrix of the current linear transformation is actualized
  194.             a.setMatrixLine(1, new PolynomialFunction[] {
  195.                 b(i), a(i)
  196.             });

  197.             // composition of the linear transformations to calculate
  198.             // the polynomials associated to Hansen coefficients
  199.             A = A.multiply(a);
  200.             // store the polynomials associated to Hansen coefficients
  201.             this.mpvec[i] = A.getMatrixLine(1);
  202.             // composition of the linear transformations to calculate
  203.             // the polynomials associated to derivatives
  204.             // Danielson 3.2-(3b) and Petre's paper
  205.             D = D.multiply(a);
  206.             if (sliceCounter % SLICE != 0) {
  207.                 a.setMatrixLine(1, new PolynomialFunction[] {
  208.                     b(i - 1), a(i - 1)
  209.                 });
  210.                 E = E.multiply(a);
  211.             }

  212.             B.setElem(1, 0, d(i));
  213.             // F = E.prod(B);
  214.             D = D.add(E.multiply(B));
  215.             // store the polynomials associated to the derivatives
  216.             this.mpvecDeriv[i] = D.getMatrixLine(1);

  217.             if (++sliceCounter % SLICE == 0) {
  218.                 // Re-Initialization of the matrices for linear transformations
  219.                 // The final configuration of these matrices are obtained by composition
  220.                 // of linear transformations
  221.                 A = HansenUtilities.buildIdentityMatrix2();
  222.                 D = HansenUtilities.buildZeroMatrix2();
  223.                 E = HansenUtilities.buildIdentityMatrix2();
  224.             }
  225.         }
  226.     }

  227.     /**
  228.      * Compute the initial values (see Collins, 4-255, 4-256 and 4.259)
  229.      * <p>
  230.      * K₀<sup>s, s</sup> = (-1)<sup>s</sup> * ( (2*s+1)!! / (s+1)! )
  231.      * </p>
  232.      * <p>
  233.      * K₀<sup>s+1, s</sup> = (-1)<sup>s</sup> * ( (2*s+1)!! / (s+2)!
  234.      * ) * (2*s+3 - χ<sup>-2</sup>)
  235.      * </p>
  236.      * <p>
  237.      * dK₀<sup>s+1, s</sup> / dχ = = (-1)<sup>s</sup> * 2 * (
  238.      * (2*s+1)!! / (s+2)! ) * χ<sup>-3</sup>
  239.      * </p>
  240.      * @param chitm1 sqrt(1 - e²)
  241.      * @param chitm2 sqrt(1 - e²)²
  242.      * @param chitm3 sqrt(1 - e²)³
  243.      */
  244.     public void computeInitValues(final T chitm1, final T chitm2, final T chitm3) {
  245.         final Field<T> field = chitm2.getField();
  246.         final T zero = field.getZero();
  247.         this.hansenRoot[0][0] = zero.add(twosp1dfosp1f);
  248.         this.hansenRoot[0][1] = (chitm2.negate().add(this.twosp3)).multiply(this.twosp1dfosp2f);
  249.         this.hansenDerivRoot[0][0] = zero;
  250.         this.hansenDerivRoot[0][1] = chitm3.multiply(two2sp1dfosp2f);

  251.         for (int i = 1; i < numSlices; i++) {
  252.             for (int j = 0; j < 2; j++) {
  253.                 // Get the required polynomials
  254.                 final PolynomialFunction[] mv = mpvec[s + (i * SLICE) + j];
  255.                 final PolynomialFunction[] sv = mpvecDeriv[s + (i * SLICE) + j];

  256.                 //Compute the root derivatives
  257.                 hansenDerivRoot[i][j] = mv[1].value(chitm1).multiply(hansenDerivRoot[i - 1][1]).
  258.                                     add(mv[0].value(chitm1).multiply(hansenDerivRoot[i - 1][0])).
  259.                                     add(sv[1].value(chitm1).multiply(hansenRoot[i - 1][1])).
  260.                                     add(sv[0].value(chitm1).multiply(hansenRoot[i - 1][0]));

  261.                 //Compute the root Hansen coefficients
  262.                 hansenRoot[i][j] =  mv[1].value(chitm1).multiply(hansenRoot[i - 1][1]).
  263.                                 add(mv[0].value(chitm1).multiply(hansenRoot[i - 1][0]));
  264.             }
  265.         }
  266.     }

  267.     /**
  268.      * Compute the value of the Hansen coefficient K₀<sup>n, s</sup>.
  269.      *
  270.      * @param n n value
  271.      * @param chitm1 χ<sup>-1</sup>
  272.      * @return the coefficient K₀<sup>n, s</sup>
  273.      */
  274.     public T getValue(final int n, final T chitm1) {
  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 hansenRoot[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 2.7.3-(6c)/Collins 4-242 and Petre's paper
  290.         final PolynomialFunction[] v = mpvec[n];
  291.         T ret = v[1].value(chitm1).multiply(hansenRoot[sliceNo][1]);
  292.         if (hansenRoot[sliceNo][0].getReal() != 0) {
  293.             ret = ret.add(v[0].value(chitm1).multiply(hansenRoot[sliceNo][0]));
  294.         }

  295.         return ret;

  296.     }

  297.     /**
  298.      * Compute the value of the Hansen coefficient dK₀<sup>n, s</sup> / d&Chi;.
  299.      *
  300.      * @param n n value
  301.      * @param chitm1 χ<sup>-1</sup>
  302.      * @return the coefficient dK₀<sup>n, s</sup> / d&Chi;
  303.      */
  304.     public T getDerivative(final int n, final T chitm1) {
  305.         //Compute the potential slice
  306.         int sliceNo = (n - s) / SLICE;
  307.         if (sliceNo < numSlices) {
  308.             //Compute the index within the slice
  309.             final int indexInSlice = (n - s) % SLICE;

  310.             //Check if a root must be returned
  311.             if (indexInSlice <= 1) {
  312.                 return hansenDerivRoot[sliceNo][indexInSlice];
  313.             }
  314.         } else {
  315.             //the value was a potential root for a slice, but that slice was not required
  316.             //Decrease the slice number
  317.             sliceNo--;
  318.         }

  319.         final PolynomialFunction[] v = mpvec[n];
  320.         T ret = v[1].value(chitm1).multiply(hansenDerivRoot[sliceNo][1]);
  321.         if (hansenDerivRoot[sliceNo][0].getReal() != 0) {
  322.             ret = ret.add(v[0].value(chitm1).multiply(hansenDerivRoot[sliceNo][0]));
  323.         }

  324.         // Danielson 2.7.3-(7c)/Collins 4-254 and Petre's paper
  325.         final PolynomialFunction[] v1 = mpvecDeriv[n];
  326.         ret = ret.add(v1[1].value(chitm1).multiply(hansenRoot[sliceNo][1]));
  327.         if (hansenRoot[sliceNo][0].getReal() != 0) {
  328.             ret = ret.add(v1[0].value(chitm1).multiply(hansenRoot[sliceNo][0]));
  329.         }
  330.         return ret;

  331.     }

  332. }