FieldHansenThirdBodyLinear.java

  1. /* Copyright 2002-2022 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.  */
  35. public class FieldHansenThirdBodyLinear <T extends CalculusFieldElement<T>> {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  94.         // Prepare the database of the associated polynomials
  95.         generatePolynomials();

  96.     }

  97.     /**
  98.      * Compute polynomial coefficient a.
  99.      *
  100.      *  <p>
  101.      *  It is used to generate the coefficient for K₀<sup>n-1, s</sup> when computing K₀<sup>n, s</sup>
  102.      *  and the coefficient for dK₀<sup>n-1, s</sup> / d&Chi; when computing dK₀<sup>n, s</sup> / d&Chi;
  103.      *  </p>
  104.      *
  105.      *  <p>
  106.      *  See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
  107.      *  </p>
  108.      *
  109.      * @param n n value
  110.      * @return the polynomial
  111.      */
  112.     private PolynomialFunction a(final int n) {
  113.         // from recurrence Danielson 2.7.3-(7c), Collins 4-254
  114.         final double r1 = 2 * n + 1;
  115.         final double r2 = n + 1;

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

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

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

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

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

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

  173.         int sliceCounter = 0;

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

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

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

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

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

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

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

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

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

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

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

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

  266.     /**
  267.      * Compute the value of the Hansen coefficient K₀<sup>n, s</sup>.
  268.      *
  269.      * @param n n value
  270.      * @param chitm1 χ<sup>-1</sup>
  271.      * @return the coefficient K₀<sup>n, s</sup>
  272.      */
  273.     public T getValue(final int n, final T chitm1) {
  274.         //Compute the potential slice
  275.         int sliceNo = (n - s) / SLICE;
  276.         if (sliceNo < numSlices) {
  277.             //Compute the index within the slice
  278.             final int indexInSlice = (n - s) % SLICE;

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

  288.         // Danielson 2.7.3-(6c)/Collins 4-242 and Petre's paper
  289.         final PolynomialFunction[] v = mpvec[n];
  290.         T ret = v[1].value(chitm1).multiply(hansenRoot[sliceNo][1]);
  291.         if (hansenRoot[sliceNo][0].getReal() != 0) {
  292.             ret = ret.add(v[0].value(chitm1).multiply(hansenRoot[sliceNo][0]));
  293.         }

  294.         return ret;

  295.     }

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

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

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

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

  330.     }

  331. }