CoefficientsFactory.java

  1. /* Copyright 2002-2013 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.apache.commons.math3.util.FastMath;
  20. import org.orekit.errors.OrekitException;
  21. import org.orekit.errors.OrekitMessages;

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

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

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

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

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

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

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

  61.         // first element
  62.         Qns[0][0] = 1;

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

  76.         return Qns;
  77.     }

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

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

  104.         return GsHs;
  105.     }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  217.             return false;

  218.         }

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

  223.     }

  224.     /** MNS couple's key. */
  225.     public static class MNSKey implements Comparable<MNSKey> {

  226.         /** m value. */
  227.         private final int m;

  228.         /** n value. */
  229.         private final int n;

  230.         /** s value. */
  231.         private final int s;

  232.         /** Simpleconstructor.
  233.          * @param m m
  234.          * @param n n
  235.          * @param s s
  236.          */
  237.         public MNSKey(final int m, final int n, final int s) {
  238.             this.m = m;
  239.             this.n = n;
  240.             this.s = s;
  241.         }

  242.         /** {@inheritDoc} */
  243.         public int compareTo(final MNSKey key) {
  244.             int result = 1;
  245.             if (m == key.m) {
  246.                 if (n == key.n) {
  247.                     if (s < key.s) {
  248.                         result = -1;
  249.                     } else if (s == key.s) {
  250.                         result = 0;
  251.                     } else {
  252.                         result = 1;
  253.                     }
  254.                 } else if (n < key.n) {
  255.                     result = -1;
  256.                 } else {
  257.                     result = 1;
  258.                 }
  259.             } else if (m < key.m) {
  260.                 result = -1;
  261.             }
  262.             return result;
  263.         }

  264.         /** {@inheritDoc} */
  265.         public boolean equals(final Object key) {

  266.             if (key == this) {
  267.                 // first fast check
  268.                 return true;
  269.             }

  270.             if ((key != null) && (key instanceof MNSKey)) {
  271.                 return (m == ((MNSKey) key).m) &&
  272.                        (n == ((MNSKey) key).n) &&
  273.                        (s == ((MNSKey) key).s);
  274.             }

  275.             return false;

  276.         }

  277.         /** {@inheritDoc} */
  278.         public int hashCode() {
  279.             return 0x25baa451 ^ (m << 16) ^ (n << 8) ^ s;
  280.         }

  281.     }

  282. }