DSSTTesseralContext.java

  1. /* Copyright 2002-2020 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.forces;

  18. import java.util.ArrayList;
  19. import java.util.List;

  20. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  21. import org.hipparchus.util.FastMath;
  22. import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
  23. import org.orekit.frames.Frame;
  24. import org.orekit.frames.Transform;
  25. import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;

  26. /**
  27.  * This class is a container for the common parameters used in {@link DSSTTesseral}.
  28.  * <p>
  29.  * It performs parameters initialization at each integration step for the Tesseral contribution
  30.  * to the central body gravitational perturbation.
  31.  * <p>
  32.  * @author Bryan Cazabonne
  33.  * @since 10.0
  34.  */
  35. class DSSTTesseralContext extends ForceModelContext {

  36.     /** Retrograde factor I.
  37.      *  <p>
  38.      *  DSST model needs equinoctial orbit as internal representation.
  39.      *  Classical equinoctial elements have discontinuities when inclination
  40.      *  is close to zero. In this representation, I = +1. <br>
  41.      *  To avoid this discontinuity, another representation exists and equinoctial
  42.      *  elements can be expressed in a different way, called "retrograde" orbit.
  43.      *  This implies I = -1. <br>
  44.      *  As Orekit doesn't implement the retrograde orbit, I is always set to +1.
  45.      *  But for the sake of consistency with the theory, the retrograde factor
  46.      *  has been kept in the formulas.
  47.      *  </p>
  48.      */
  49.     private static final int I = 1;

  50.     /** Minimum period for analytically averaged high-order resonant
  51.      *  central body spherical harmonics in seconds.
  52.      */
  53.     private static final double MIN_PERIOD_IN_SECONDS = 864000.;

  54.     /** Minimum period for analytically averaged high-order resonant
  55.      *  central body spherical harmonics in satellite revolutions.
  56.      */
  57.     private static final double MIN_PERIOD_IN_SAT_REV = 10.;

  58.     /** A = sqrt(μ * a). */
  59.     private double A;

  60.     // Common factors for potential computation
  61.     /** &Chi; = 1 / sqrt(1 - e²) = 1 / B. */
  62.     private double chi;

  63.     /** &Chi;². */
  64.     private double chi2;

  65.     /** Central body rotation angle θ. */
  66.     private double theta;

  67.     // Common factors from equinoctial coefficients
  68.     /** 2 * a / A .*/
  69.     private double ax2oA;

  70.     /** 1 / (A * B) .*/
  71.     private double ooAB;

  72.     /** B / A .*/
  73.     private double BoA;

  74.     /** B / (A * (1 + B)) .*/
  75.     private double BoABpo;

  76.     /** C / (2 * A * B) .*/
  77.     private double Co2AB;

  78.     /** μ / a .*/
  79.     private double moa;

  80.     /** R / a .*/
  81.     private double roa;

  82.     /** ecc². */
  83.     private double e2;

  84.     /** Maximum power of the eccentricity to use in summation over s. */
  85.     private int maxEccPow;

  86.     /** Keplerian mean motion. */
  87.     private double n;

  88.     /** Keplerian period. */
  89.     private double period;

  90.     /** Ratio of satellite period to central body rotation period. */
  91.     private double ratio;

  92.     /** List of resonant orders. */
  93.     private final List<Integer> resOrders;

  94.     /**
  95.      * Simple constructor.
  96.      *
  97.      * @param auxiliaryElements auxiliary elements related to the current orbit
  98.      * @param centralBodyFrame rotating body frame
  99.      * @param provider provider for spherical harmonics
  100.      * @param maxFrequencyShortPeriodics maximum value for j
  101.      * @param bodyPeriod central body rotation period (seconds)
  102.      * @param parameters values of the force model parameters
  103.      */
  104.     DSSTTesseralContext(final AuxiliaryElements auxiliaryElements,
  105.                         final Frame centralBodyFrame,
  106.                         final UnnormalizedSphericalHarmonicsProvider provider,
  107.                         final int maxFrequencyShortPeriodics,
  108.                         final double bodyPeriod,
  109.                         final double[] parameters) {

  110.         super(auxiliaryElements);

  111.         this.maxEccPow = 0;
  112.         this.resOrders = new ArrayList<Integer>();

  113.         final double mu = parameters[0];

  114.         // Keplerian Mean Motion
  115.         final double absA = FastMath.abs(auxiliaryElements.getSma());
  116.         n = FastMath.sqrt(mu / absA) / absA;

  117.         // Keplerian period
  118.         final double a = auxiliaryElements.getSma();
  119.         period = (a < 0) ? Double.POSITIVE_INFINITY : 2.0 * FastMath.PI * a * FastMath.sqrt(a / mu);

  120.         A = FastMath.sqrt(mu * auxiliaryElements.getSma());

  121.         // Eccentricity square
  122.         e2 = auxiliaryElements.getEcc() * auxiliaryElements.getEcc();

  123.         // Central body rotation angle from equation 2.7.1-(3)(4).
  124.         final Transform t = centralBodyFrame.getTransformTo(auxiliaryElements.getFrame(), auxiliaryElements.getDate());
  125.         final Vector3D xB = t.transformVector(Vector3D.PLUS_I);
  126.         final Vector3D yB = t.transformVector(Vector3D.PLUS_J);
  127.         theta = FastMath.atan2(-auxiliaryElements.getVectorF().dotProduct(yB) + I * auxiliaryElements.getVectorG().dotProduct(xB),
  128.                                auxiliaryElements.getVectorF().dotProduct(xB) + I * auxiliaryElements.getVectorG().dotProduct(yB));

  129.         // Common factors from equinoctial coefficients
  130.         // 2 * a / A
  131.         ax2oA  = 2. * auxiliaryElements.getSma() / A;
  132.         // B / A
  133.         BoA    = auxiliaryElements.getB() / A;
  134.         // 1 / AB
  135.         ooAB   = 1. / (A * auxiliaryElements.getB());
  136.         // C / 2AB
  137.         Co2AB  = auxiliaryElements.getC() * ooAB / 2.;
  138.         // B / (A * (1 + B))
  139.         BoABpo = BoA / (1. + auxiliaryElements.getB());
  140.         // &mu / a
  141.         moa    = mu / auxiliaryElements.getSma();
  142.         // R / a
  143.         roa    = provider.getAe() / auxiliaryElements.getSma();

  144.         // &Chi; = 1 / B
  145.         chi  = 1. / auxiliaryElements.getB();
  146.         chi2 = chi * chi;

  147.         // Set the highest power of the eccentricity in the analytical power
  148.         // series expansion for the averaged high order resonant central body
  149.         // spherical harmonic perturbation
  150.         final double e = auxiliaryElements.getEcc();
  151.         if (e <= 0.005) {
  152.             maxEccPow = 3;
  153.         } else if (e <= 0.02) {
  154.             maxEccPow = 4;
  155.         } else if (e <= 0.1) {
  156.             maxEccPow = 7;
  157.         } else if (e <= 0.2) {
  158.             maxEccPow = 10;
  159.         } else if (e <= 0.3) {
  160.             maxEccPow = 12;
  161.         } else if (e <= 0.4) {
  162.             maxEccPow = 15;
  163.         } else {
  164.             maxEccPow = 20;
  165.         }

  166.         // Ratio of satellite to central body periods to define resonant terms
  167.         ratio = period / bodyPeriod;

  168.         // Compute natural resonant terms
  169.         final double tolerance = 1. / FastMath.max(MIN_PERIOD_IN_SAT_REV,
  170.                                                    MIN_PERIOD_IN_SECONDS / period);

  171.         // Search the resonant orders in the tesseral harmonic field
  172.         resOrders.clear();
  173.         for (int m = 1; m <= provider.getMaxOrder(); m++) {
  174.             final double resonance = ratio * m;
  175.             final int jComputedRes = (int) FastMath.round(resonance);
  176.             if (jComputedRes > 0 && jComputedRes <= maxFrequencyShortPeriodics && FastMath.abs(resonance - jComputedRes) <= tolerance) {
  177.                 // Store each resonant index and order
  178.                 this.resOrders.add(m);
  179.             }
  180.         }

  181.     }

  182.     /** Get the list of resonant orders.
  183.      * @return resOrders
  184.      */
  185.     public List<Integer> getResOrders() {
  186.         return resOrders;
  187.     }

  188.     /** Get ecc².
  189.      * @return e2
  190.      */
  191.     public double getE2() {
  192.         return e2;
  193.     }

  194.     /** Get Central body rotation angle θ.
  195.      * @return theta
  196.      */
  197.     public double getTheta() {
  198.         return theta;
  199.     }

  200.     /** Get ax2oA = 2 * a / A .
  201.      * @return ax2oA
  202.      */
  203.     public double getAx2oA() {
  204.         return ax2oA;
  205.     }

  206.     /** Get &Chi; = 1 / sqrt(1 - e²) = 1 / B.
  207.      * @return chi
  208.      */
  209.     public double getChi() {
  210.         return chi;
  211.     }

  212.     /** Get &Chi;².
  213.      * @return chi2
  214.      */
  215.     public double getChi2() {
  216.         return chi2;
  217.     }

  218.     /** Get B / A.
  219.      * @return BoA
  220.      */
  221.     public double getBoA() {
  222.         return BoA;
  223.     }

  224.     /** Get ooAB = 1 / (A * B).
  225.      * @return ooAB
  226.      */
  227.     public double getOoAB() {
  228.         return ooAB;
  229.     }

  230.     /** Get Co2AB = C / 2AB.
  231.      * @return Co2AB
  232.      */
  233.     public double getCo2AB() {
  234.         return Co2AB;
  235.     }

  236.     /** Get BoABpo = B / A(1 + B).
  237.      * @return BoABpo
  238.      */
  239.     public double getBoABpo() {
  240.         return BoABpo;
  241.     }

  242.     /** Get μ / a .
  243.      * @return moa
  244.      */
  245.     public double getMoa() {
  246.         return moa;
  247.     }

  248.     /** Get roa = R / a.
  249.      * @return roa
  250.      */
  251.     public double getRoa() {
  252.         return roa;
  253.     }

  254.     /** Get the maximum power of the eccentricity to use in summation over s.
  255.      * @return maxEccPow
  256.      */
  257.     public int getMaxEccPow() {
  258.         return maxEccPow;
  259.     }

  260.     /** Get the Keplerian period.
  261.      * <p>The Keplerian period is computed directly from semi major axis
  262.      * and central acceleration constant.</p>
  263.      * @return Keplerian period in seconds, or positive infinity for hyperbolic orbits
  264.      */
  265.     public double getOrbitPeriod() {
  266.         return period;
  267.     }

  268.     /** Get the Keplerian mean motion.
  269.      * <p>The Keplerian mean motion is computed directly from semi major axis
  270.      * and central acceleration constant.</p>
  271.      * @return Keplerian mean motion in radians per second
  272.      */
  273.     public double getMeanMotion() {
  274.         return n;
  275.     }

  276.     /** Get the ratio of satellite period to central body rotation period.
  277.      * @return ratio
  278.      */
  279.     public double getRatio() {
  280.         return ratio;
  281.     }

  282. }