CoefficientsFactory.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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;

  18. import java.util.TreeMap;

  19. import org.hipparchus.util.CombinatoricsUtils;
  20. import org.hipparchus.util.FastMath;
  21. import org.orekit.errors.OrekitException;
  22. import org.orekit.errors.OrekitMessages;

  23. /**
  24.  * This class is designed to provide coefficient from the DSST theory.
  25.  *
  26.  * @author Romain Di Costanzo
  27.  */
  28. public class CoefficientsFactory {

  29.     /** Internal storage of the polynomial values. Reused for further computation. */
  30.     private static TreeMap<NSKey, Double> VNS = new TreeMap<NSKey, Double>();

  31.     /** Last computed order for V<sub>ns</sub> coefficients. */
  32.     private static int         LAST_VNS_ORDER = 2;

  33.     /** Static initialization for the V<sub>ns</sub> coefficient. */
  34.     static {
  35.         // Initialization
  36.         VNS.put(new NSKey(0, 0), 1.);
  37.         VNS.put(new NSKey(1, 0), 0.);
  38.         VNS.put(new NSKey(1, 1), 0.5);
  39.     }

  40.     /** Private constructor as the class is a utility class.
  41.      */
  42.     private CoefficientsFactory() {
  43.     }

  44.     /** Compute the Q<sub>n,s</sub> coefficients evaluated at γ from the recurrence formula 2.8.3-(2).
  45.      *  <p>
  46.      *  Q<sub>n,s</sub> coefficients are computed for n = 0 to nMax
  47.      *  and s = 0 to sMax + 1 in order to also get the derivative dQ<sub>n,s</sub>/dγ = Q(n, s + 1)
  48.      *  </p>
  49.      *  @param gamma γ angle
  50.      *  @param nMax n max value
  51.      *  @param sMax s max value
  52.      *  @return Q<sub>n,s</sub> coefficients array
  53.      */
  54.     public static double[][] computeQns(final double gamma, final int nMax, final int sMax) {

  55.         // Initialization
  56.         final int sDim = FastMath.min(sMax + 1, nMax) + 1;
  57.         final int rows = nMax + 1;
  58.         final double[][] Qns = new double[rows][];
  59.         for (int i = 0; i <= nMax; i++) {
  60.             final int snDim = FastMath.min(i + 1, sDim);
  61.             Qns[i] = new double[snDim];
  62.         }

  63.         // first element
  64.         Qns[0][0] = 1;

  65.         for (int n = 1; n <= nMax; n++) {
  66.             final int snDim = FastMath.min(n + 1, sDim);
  67.             for (int s = 0; s < snDim; s++) {
  68.                 if (n == s) {
  69.                     Qns[n][s] = (2. * s - 1.) * Qns[s - 1][s - 1];
  70.                 } else if (n == (s + 1)) {
  71.                     Qns[n][s] = (2. * s + 1.) * gamma * Qns[s][s];
  72.                 } else {
  73.                     Qns[n][s] = (2. * n - 1.) * gamma * Qns[n - 1][s] - (n + s - 1.) * Qns[n - 2][s];
  74.                     Qns[n][s] /= n - s;
  75.                 }
  76.             }
  77.         }

  78.         return Qns;
  79.     }

  80.     /** Compute recursively G<sub>s</sub> and H<sub>s</sub> polynomials from equation 3.1-(5).
  81.      *  @param k x-component of the eccentricity vector
  82.      *  @param h y-component of the eccentricity vector
  83.      *  @param alpha 1st direction cosine
  84.      *  @param beta 2nd direction cosine
  85.      *  @param order development order
  86.      *  @return Array of G<sub>s</sub> and H<sub>s</sub> polynomials for s from 0 to order.<br>
  87.      *          The 1st column contains the G<sub>s</sub> values.
  88.      *          The 2nd column contains the H<sub>s</sub> values.
  89.      */
  90.     public static double[][] computeGsHs(final double k, final double h,
  91.                                          final double alpha, final double beta,
  92.                                          final int order) {
  93.         // Constant terms
  94.         final double hamkb = h * alpha - k * beta;
  95.         final double kaphb = k * alpha + h * beta;
  96.         // Initialization
  97.         final double[][] GsHs = new double[2][order + 1];
  98.         GsHs[0][0] = 1.;
  99.         GsHs[1][0] = 0.;

  100.         for (int s = 1; s <= order; s++) {
  101.             // Gs coefficient
  102.             GsHs[0][s] = kaphb * GsHs[0][s - 1] - hamkb * GsHs[1][s - 1];
  103.             // Hs coefficient
  104.             GsHs[1][s] = hamkb * GsHs[0][s - 1] + kaphb * GsHs[1][s - 1];
  105.         }

  106.         return GsHs;
  107.     }

  108.     /** Compute the V<sub>n,s</sub> coefficients from 2.8.2-(1)(2).
  109.      * @param order Order of the computation. Computation will be done from 0 to order -1
  110.      * @return Map of the V<sub>n, s</sub> coefficients
  111.      */
  112.     public static TreeMap<NSKey, Double> computeVns(final int order) {

  113.         if (order > LAST_VNS_ORDER) {
  114.             // Compute coefficient
  115.             // Need previous computation as recurrence relation is done at s + 1 and n + 2
  116.             final int min = (LAST_VNS_ORDER - 2 < 0) ? 0 : (LAST_VNS_ORDER - 2);
  117.             for (int n = min; n < order; n++) {
  118.                 for (int s = 0; s < n + 1; s++) {
  119.                     if ((n - s) % 2 != 0) {
  120.                         VNS.put(new NSKey(n, s), 0.);
  121.                     } else {
  122.                         // s = n
  123.                         if (n == s && (s + 1) < order) {
  124.                             VNS.put(new NSKey(s + 1, s + 1), VNS.get(new NSKey(s, s)) / (2 * s + 2.));
  125.                         }
  126.                         // otherwise
  127.                         if ((n + 2) < order) {
  128.                             VNS.put(new NSKey(n + 2, s), VNS.get(new NSKey(n, s)) * (-n + s - 1.) / (n + s + 2.));
  129.                         }
  130.                     }
  131.                 }
  132.             }
  133.             LAST_VNS_ORDER = order;
  134.         }
  135.         return VNS;
  136.     }

  137.     /** Get the V<sub>n,s</sub><sup>m</sup> coefficient from V<sub>n,s</sub>.
  138.      *  <br>See § 2.8.2 in Danielson paper.
  139.      * @param m m
  140.      * @param n n
  141.      * @param s s
  142.      * @return The V<sub>n, s</sub> <sup>m</sup> coefficient
  143.      * @throws OrekitException if m &gt; n
  144.      */
  145.     public static double getVmns(final int m, final int n, final int s)
  146.         throws OrekitException {
  147.         if (m > n) {
  148.             throw new OrekitException(OrekitMessages.DSST_VMNS_COEFFICIENT_ERROR_MS, m, n);
  149.         }
  150.         final double fns = CombinatoricsUtils.factorialDouble(n + FastMath.abs(s));
  151.         final double fnm = CombinatoricsUtils.factorialDouble(n  - m);

  152.         double result = 0;
  153.         // If (n - s) is odd, the Vmsn coefficient is null
  154.         if ((n - s) % 2 == 0) {
  155.             // Update the Vns coefficient
  156.             if ((n + 1) > LAST_VNS_ORDER) {
  157.                 computeVns(n + 1);
  158.             }
  159.             if (s >= 0) {
  160.                 result = fns  * VNS.get(new NSKey(n, s)) / fnm;
  161.             } else {
  162.                 // If s < 0 : Vmn-s = (-1)^(-s) Vmns
  163.                 final int mops = (s % 2 == 0) ? 1 : -1;
  164.                 result = mops * fns * VNS.get(new NSKey(n, -s)) / fnm;
  165.             }
  166.         }
  167.         return result;
  168.     }

  169.     /** Key formed by two integer values. */
  170.     public static class NSKey implements Comparable<NSKey> {

  171.         /** n value. */
  172.         private final int n;

  173.         /** s value. */
  174.         private final int s;

  175.         /** Simple constructor.
  176.          * @param n n
  177.          * @param s s
  178.          */
  179.         public NSKey(final int n, final int s) {
  180.             this.n = n;
  181.             this.s = s;
  182.         }

  183.         /** Get n.
  184.          * @return n
  185.          */
  186.         public int getN() {
  187.             return n;
  188.         }

  189.         /** Get s.
  190.          * @return s
  191.          */
  192.         public int getS() {
  193.             return s;
  194.         }

  195.         /** {@inheritDoc} */
  196.         public int compareTo(final NSKey key) {
  197.             int result = 1;
  198.             if (n == key.n) {
  199.                 if (s < key.s) {
  200.                     result = -1;
  201.                 } else if (s == key.s) {
  202.                     result = 0;
  203.                 }
  204.             } else if (n < key.n) {
  205.                 result = -1;
  206.             }
  207.             return result;
  208.         }

  209.         /** {@inheritDoc} */
  210.         public boolean equals(final Object key) {

  211.             if (key == this) {
  212.                 // first fast check
  213.                 return true;
  214.             }

  215.             if ((key != null) && (key instanceof NSKey)) {
  216.                 return (n == ((NSKey) key).n) && (s == ((NSKey) key).s);
  217.             }

  218.             return false;

  219.         }

  220.         /** {@inheritDoc} */
  221.         public int hashCode() {
  222.             return 0x998493a6 ^ (n << 8) ^ s;
  223.         }

  224.     }

  225. }