FieldDSSTTesseralContext.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.Field;
  21. import org.hipparchus.RealFieldElement;
  22. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  23. import org.hipparchus.util.FastMath;
  24. import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
  25. import org.orekit.frames.FieldTransform;
  26. import org.orekit.frames.Frame;
  27. import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;

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

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

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

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

  60.     /** A = sqrt(μ * a). */
  61.     private T A;

  62.     // Common factors for potential computation
  63.     /** &Chi; = 1 / sqrt(1 - e²) = 1 / B. */
  64.     private T chi;

  65.     /** &Chi;². */
  66.     private T chi2;

  67.     /** Central body rotation angle θ. */
  68.     private T theta;

  69.     // Common factors from equinoctial coefficients
  70.     /** 2 * a / A .*/
  71.     private T ax2oA;

  72.     /** 1 / (A * B) .*/
  73.     private T ooAB;

  74.     /** B / A .*/
  75.     private T BoA;

  76.     /** B / (A * (1 + B)) .*/
  77.     private T BoABpo;

  78.     /** C / (2 * A * B) .*/
  79.     private T Co2AB;

  80.     /** μ / a .*/
  81.     private T moa;

  82.     /** R / a .*/
  83.     private T roa;

  84.     /** ecc². */
  85.     private T e2;

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

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

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

  92.     /** Ratio of satellite period to central body rotation period. */
  93.     private T ratio;

  94.     /** List of resonant orders. */
  95.     private final List<Integer> resOrders;

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

  112.         super(auxiliaryElements);

  113.         final Field<T> field = auxiliaryElements.getDate().getField();
  114.         final T zero = field.getZero();

  115.         this.maxEccPow = 0;
  116.         this.resOrders = new ArrayList<Integer>();

  117.         final T mu = parameters[0];

  118.         // Keplerian mean motion
  119.         final T absA = FastMath.abs(auxiliaryElements.getSma());
  120.         n = FastMath.sqrt(mu.divide(absA)).divide(absA);

  121.         // Keplerian period
  122.         final T a = auxiliaryElements.getSma();
  123.         period = (a.getReal() < 0) ? zero.add(Double.POSITIVE_INFINITY) : a.multiply(2.0 * FastMath.PI).multiply(a.divide(mu).sqrt());

  124.         A = FastMath.sqrt(mu.multiply(auxiliaryElements.getSma()));

  125.         // Eccentricity square
  126.         e2 = auxiliaryElements.getEcc().multiply(auxiliaryElements.getEcc());

  127.         // Central body rotation angle from equation 2.7.1-(3)(4).
  128.         final FieldTransform<T> t = centralBodyFrame.getTransformTo(auxiliaryElements.getFrame(), auxiliaryElements.getDate());
  129.         final FieldVector3D<T> xB = t.transformVector(FieldVector3D.getPlusI(field));
  130.         final FieldVector3D<T> yB = t.transformVector(FieldVector3D.getPlusJ(field));
  131.         theta = FastMath.atan2(auxiliaryElements.getVectorF().dotProduct(yB).negate().add((auxiliaryElements.getVectorG().dotProduct(xB)).multiply(I)),
  132.                                auxiliaryElements.getVectorF().dotProduct(xB).add(auxiliaryElements.getVectorG().dotProduct(yB).multiply(I)));

  133.         // Common factors from equinoctial coefficients
  134.         // 2 * a / A
  135.         ax2oA  = auxiliaryElements.getSma().divide(A).multiply(2.);
  136.         // B / A
  137.         BoA    = auxiliaryElements.getB().divide(A);
  138.         // 1 / AB
  139.         ooAB   = A.multiply(auxiliaryElements.getB()).reciprocal();
  140.         // C / 2AB
  141.         Co2AB  = auxiliaryElements.getC().multiply(ooAB).divide(2.);
  142.         // B / (A * (1 + B))
  143.         BoABpo = BoA.divide(auxiliaryElements.getB().add(1.));
  144.         // &mu / a
  145.         moa    = mu.divide(auxiliaryElements.getSma());
  146.         // R / a
  147.         roa    = auxiliaryElements.getSma().divide(provider.getAe()).reciprocal();

  148.         // &Chi; = 1 / B
  149.         chi  = auxiliaryElements.getB().reciprocal();
  150.         chi2 = chi.multiply(chi);

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

  170.         // Ratio of satellite to central body periods to define resonant terms
  171.         ratio = period.divide(bodyPeriod);

  172.         // Compute natural resonant terms
  173.         final T tolerance = FastMath.max(zero.add(MIN_PERIOD_IN_SAT_REV),
  174.                                                    period.divide(MIN_PERIOD_IN_SECONDS).reciprocal()).reciprocal();

  175.         // Search the resonant orders in the tesseral harmonic field
  176.         resOrders.clear();
  177.         for (int m = 1; m <= provider.getMaxOrder(); m++) {
  178.             final T resonance = ratio.multiply(m);
  179.             final int jComputedRes = (int) FastMath.round(resonance);
  180.             if (jComputedRes > 0 && jComputedRes <= maxFrequencyShortPeriodics && FastMath.abs(resonance.subtract(jComputedRes)).getReal() <= tolerance.getReal()) {
  181.                 // Store each resonant index and order
  182.                 this.resOrders.add(m);
  183.             }
  184.         }

  185.     }

  186.     /** Get the list of resonant orders.
  187.      * @return resOrders
  188.      */
  189.     public List<Integer> getResOrders() {
  190.         return resOrders;
  191.     }

  192.     /** Get ecc².
  193.      * @return e2
  194.      */
  195.     public T getE2() {
  196.         return e2;
  197.     }

  198.     /** Get Central body rotation angle θ.
  199.      * @return theta
  200.      */
  201.     public T getTheta() {
  202.         return theta;
  203.     }

  204.     /** Get ax2oA = 2 * a / A .
  205.      * @return ax2oA
  206.      */
  207.     public T getAx2oA() {
  208.         return ax2oA;
  209.     }

  210.     /** Get &Chi; = 1 / sqrt(1 - e²) = 1 / B.
  211.      * @return chi
  212.      */
  213.     public T getChi() {
  214.         return chi;
  215.     }

  216.     /** Get &Chi;².
  217.      * @return chi2
  218.      */
  219.     public T getChi2() {
  220.         return chi2;
  221.     }

  222.     /** Get B / A.
  223.      * @return BoA
  224.      */
  225.     public T getBoA() {
  226.         return BoA;
  227.     }

  228.     /** Get ooAB = 1 / (A * B).
  229.      * @return ooAB
  230.      */
  231.     public T getOoAB() {
  232.         return ooAB;
  233.     }

  234.     /** Get Co2AB = C / 2AB.
  235.      * @return Co2AB
  236.      */
  237.     public T getCo2AB() {
  238.         return Co2AB;
  239.     }

  240.     /** Get BoABpo = B / A(1 + B).
  241.      * @return BoABpo
  242.      */
  243.     public T getBoABpo() {
  244.         return BoABpo;
  245.     }

  246.     /** Get μ / a .
  247.      * @return moa
  248.      */
  249.     public T getMoa() {
  250.         return moa;
  251.     }

  252.     /** Get roa = R / a.
  253.      * @return roa
  254.      */
  255.     public T getRoa() {
  256.         return roa;
  257.     }

  258.     /** Get the maximum power of the eccentricity to use in summation over s.
  259.      * @return roa
  260.      */
  261.     public int getMaxEccPow() {
  262.         return maxEccPow;
  263.     }

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

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

  280.     /** Get the ratio of satellite period to central body rotation period.
  281.      * @return ratio
  282.      */
  283.     public T getRatio() {
  284.         return ratio;
  285.     }

  286. }