DSSTThirdBodyContext.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 org.hipparchus.geometry.euclidean.threed.Vector3D;
  19. import org.hipparchus.util.CombinatoricsUtils;
  20. import org.hipparchus.util.FastMath;
  21. import org.orekit.bodies.CelestialBody;
  22. import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
  23. import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory;
  24. import org.orekit.propagation.semianalytical.dsst.utilities.UpperBounds;

  25. /**
  26.  * This class is a container for the common parameters used in {@link DSSTThirdBody}.
  27.  * <p>
  28.  * It performs parameters initialization at each integration step for the third
  29.  * body attraction perturbation.
  30.  * <p>
  31.  * @author Bryan Cazabonne
  32.  * @since 10.0
  33.  */
  34. class DSSTThirdBodyContext extends ForceModelContext {

  35.     /** Max power for summation. */
  36.     private static final int    MAX_POWER = 22;

  37.     /** Truncation tolerance for big, eccentric  orbits. */
  38.     private static final double BIG_TRUNCATION_TOLERANCE = 1.e-1;

  39.     /** Truncation tolerance for small orbits. */
  40.     private static final double SMALL_TRUNCATION_TOLERANCE = 1.9e-6;

  41.     /** Maximum power for eccentricity used in short periodic computation. */
  42.     private static final int    MAX_ECCPOWER_SP = 4;

  43.     /** Max power for a/R3 in the serie expansion. */
  44.     private int    maxAR3Pow;

  45.     /** Max power for e in the serie expansion. */
  46.     private int    maxEccPow;

  47.     /** a / R3 up to power maxAR3Pow. */
  48.     private double[] aoR3Pow;

  49.     /** Max power for e in the serie expansion (for short periodics). */
  50.     private int    maxEccPowShort;

  51.     /** Max frequency of F. */
  52.     private int    maxFreqF;

  53.     /** Qns coefficients. */
  54.     private double[][] Qns;

  55.     /** Standard gravitational parameter μ for the body in m³/s². */
  56.     private final double gm;

  57.     /** Distance from center of mass of the central body to the 3rd body. */
  58.     private double R3;

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

  61.     // Direction cosines of the symmetry axis
  62.     /** α. */
  63.     private double alpha;
  64.     /** β. */
  65.     private double beta;
  66.     /** γ. */
  67.     private double gamma;

  68.     /** B². */
  69.     private double BB;
  70.     /** B³. */
  71.     private double BBB;

  72.     /** &Chi; = 1 / sqrt(1 - e²) = 1 / B. */
  73.     private double X;
  74.     /** &Chi;². */
  75.     private double XX;
  76.     /** &Chi;³. */
  77.     private double XXX;
  78.     /** -2 * a / A. */
  79.     private double m2aoA;
  80.     /** B / A. */
  81.     private double BoA;
  82.     /** 1 / (A * B). */
  83.     private double ooAB;
  84.     /** -C / (2 * A * B). */
  85.     private double mCo2AB;
  86.     /** B / A(1 + B). */
  87.     private double BoABpo;

  88.     /** mu3 / R3. */
  89.     private double muoR3;

  90.     /** b = 1 / (1 + sqrt(1 - e²)) = 1 / (1 + B).*/
  91.     private double b;

  92.     /** h * &Chi;³. */
  93.     private double hXXX;
  94.     /** k * &Chi;³. */
  95.     private double kXXX;

  96.     /** Keplerian mean motion. */
  97.     private final double motion;

  98.     /**
  99.      * Simple constructor.
  100.      *
  101.      * @param auxiliaryElements auxiliary elements related to the current orbit
  102.      * @param thirdBody body the 3rd body to consider
  103.      * @param parameters values of the force model parameters
  104.      */
  105.     DSSTThirdBodyContext(final AuxiliaryElements auxiliaryElements, final CelestialBody thirdBody, final double[] parameters) {

  106.         super(auxiliaryElements);

  107.         final double mu = parameters[1];
  108.         A = FastMath.sqrt(mu * auxiliaryElements.getSma());
  109.         this.gm = parameters[0];

  110.         // Keplerian Mean Motion
  111.         final double absA = FastMath.abs(auxiliaryElements.getSma());
  112.         motion = FastMath.sqrt(mu / absA) / absA;

  113.         // Distance from center of mass of the central body to the 3rd body
  114.         final Vector3D bodyPos = thirdBody.getPVCoordinates(auxiliaryElements.getDate(), auxiliaryElements.getFrame()).getPosition();
  115.         R3 = bodyPos.getNorm();

  116.         // Direction cosines
  117.         final Vector3D bodyDir = bodyPos.normalize();
  118.         alpha = bodyDir.dotProduct(auxiliaryElements.getVectorF());
  119.         beta  = bodyDir.dotProduct(auxiliaryElements.getVectorG());
  120.         gamma = bodyDir.dotProduct(auxiliaryElements.getVectorW());

  121.         //&Chi;<sup>-2</sup>.
  122.         BB = auxiliaryElements.getB() * auxiliaryElements.getB();
  123.         //&Chi;<sup>-3</sup>.
  124.         BBB = BB * auxiliaryElements.getB();

  125.         //b = 1 / (1 + B)
  126.         b = 1. / (1. + auxiliaryElements.getB());

  127.         // &Chi;
  128.         X = 1. / auxiliaryElements.getB();
  129.         XX = X * X;
  130.         XXX = X * XX;
  131.         // -2 * a / A
  132.         m2aoA = -2. * auxiliaryElements.getSma() / A;
  133.         // B / A
  134.         BoA = auxiliaryElements.getB() / A;
  135.         // 1 / AB
  136.         ooAB = 1. / (A * auxiliaryElements.getB());
  137.         // -C / 2AB
  138.         mCo2AB = -auxiliaryElements.getC() * ooAB / 2.;
  139.         // B / A(1 + B)
  140.         BoABpo = BoA / (1. + auxiliaryElements.getB());

  141.         // mu3 / R3
  142.         muoR3 = gm / R3;

  143.         //h * &Chi;³
  144.         hXXX = auxiliaryElements.getH() * XXX;
  145.         //k * &Chi;³
  146.         kXXX = auxiliaryElements.getK() * XXX;

  147.         // Truncation tolerance.
  148.         final double aoR3 = auxiliaryElements.getSma() / R3;
  149.         final double tol = ( aoR3 > .3 || (aoR3 > .15  && auxiliaryElements.getEcc() > .25) ) ? BIG_TRUNCATION_TOLERANCE : SMALL_TRUNCATION_TOLERANCE;

  150.         // Utilities for truncation
  151.         // Set a lower bound for eccentricity
  152.         final double eo2  = FastMath.max(0.0025, auxiliaryElements.getEcc() / 2.);
  153.         final double x2o2 = XX / 2.;
  154.         final double[] eccPwr = new double[MAX_POWER];
  155.         final double[] chiPwr = new double[MAX_POWER];
  156.         eccPwr[0] = 1.;
  157.         chiPwr[0] = X;
  158.         for (int i = 1; i < MAX_POWER; i++) {
  159.             eccPwr[i] = eccPwr[i - 1] * eo2;
  160.             chiPwr[i] = chiPwr[i - 1] * x2o2;
  161.         }

  162.         // Auxiliary quantities.
  163.         final double ao2rxx = aoR3 / (2. * XX);
  164.         double xmuarn       = ao2rxx * ao2rxx * gm / (X * R3);
  165.         double term         = 0.;

  166.         // Compute max power for a/R3 and e.
  167.         maxAR3Pow = 2;
  168.         maxEccPow = 0;
  169.         int n     = 2;
  170.         int m     = 2;
  171.         int nsmd2 = 0;

  172.         do {
  173.             // Upper bound for Tnm.
  174.             term =  xmuarn *
  175.                             (CombinatoricsUtils.factorialDouble(n + m) / (CombinatoricsUtils.factorialDouble(nsmd2) * CombinatoricsUtils.factorialDouble(nsmd2 + m))) *
  176.                             (CombinatoricsUtils.factorialDouble(n + m + 1) / (CombinatoricsUtils.factorialDouble(m) * CombinatoricsUtils.factorialDouble(n + 1))) *
  177.                             (CombinatoricsUtils.factorialDouble(n - m + 1) / CombinatoricsUtils.factorialDouble(n + 1)) *
  178.                             eccPwr[m] * UpperBounds.getDnl(XX, chiPwr[m], n + 2, m);

  179.             if (term < tol) {
  180.                 if (m == 0) {
  181.                     break;
  182.                 } else if (m < 2) {
  183.                     xmuarn *= ao2rxx;
  184.                     m = 0;
  185.                     n++;
  186.                     nsmd2++;
  187.                 } else {
  188.                     m -= 2;
  189.                     nsmd2++;
  190.                 }
  191.             } else {
  192.                 maxAR3Pow = n;
  193.                 maxEccPow = FastMath.max(m, maxEccPow);
  194.                 xmuarn *= ao2rxx;
  195.                 m++;
  196.                 n++;
  197.             }
  198.         } while (n < MAX_POWER);

  199.         maxEccPow = FastMath.min(maxAR3Pow, maxEccPow);

  200.         // allocate the array aoR3Pow
  201.         aoR3Pow = new double[maxAR3Pow + 1];

  202.         aoR3Pow[0] = 1.;
  203.         for (int i = 1; i <= maxAR3Pow; i++) {
  204.             aoR3Pow[i] = aoR3 * aoR3Pow[i - 1];
  205.         }

  206.         maxFreqF = maxAR3Pow + 1;
  207.         maxEccPowShort = MAX_ECCPOWER_SP;

  208.         Qns = CoefficientsFactory.computeQns(gamma, maxAR3Pow, FastMath.max(maxEccPow, maxEccPowShort));

  209.     }

  210.     /** Get A = sqrt(μ * a).
  211.      * @return A
  212.      */
  213.     public double getA() {
  214.         return A;
  215.     }

  216.     /** Get direction cosine α for central body.
  217.      * @return α
  218.      */
  219.     public double getAlpha() {
  220.         return alpha;
  221.     }

  222.     /** Get direction cosine β for central body.
  223.      * @return β
  224.      */
  225.     public double getBeta() {
  226.         return beta;
  227.     }

  228.     /** Get direction cosine γ for central body.
  229.      * @return γ
  230.      */
  231.     public double getGamma() {
  232.         return gamma;
  233.     }

  234.     /** Get B².
  235.      * @return B²
  236.      */
  237.     public double getBB() {
  238.         return BB;
  239.     }

  240.     /** Get B³.
  241.      * @return B³
  242.      */
  243.     public double getBBB() {
  244.         return BBB;
  245.     }

  246.     /** Get b = 1 / (1 + sqrt(1 - e²)) = 1 / (1 + B).
  247.      * @return b
  248.      */
  249.     public double getb() {
  250.         return b;
  251.     }

  252.     /** Get &Chi; = 1 / sqrt(1 - e²) = 1 / B.
  253.      * @return &Chi;
  254.      */
  255.     public double getX() {
  256.         return X;
  257.     }

  258.     /** Get m2aoA = -2 * a / A.
  259.      * @return m2aoA
  260.      */
  261.     public double getM2aoA() {
  262.         return m2aoA;
  263.     }

  264.     /** Get B / A.
  265.      * @return BoA
  266.      */
  267.     public double getBoA() {
  268.         return BoA;
  269.     }

  270.     /** Get ooAB = 1 / (A * B).
  271.      * @return ooAB
  272.      */
  273.     public double getOoAB() {
  274.         return ooAB;
  275.     }

  276.     /** Get mCo2AB = -C / 2AB.
  277.      * @return mCo2AB
  278.      */
  279.     public double getMCo2AB() {
  280.         return mCo2AB;
  281.     }

  282.     /** Get BoABpo = B / A(1 + B).
  283.      * @return BoABpo
  284.      */
  285.     public double getBoABpo() {
  286.         return BoABpo;
  287.     }

  288.     /** Get muoR3 = mu3 / R3.
  289.      * @return muoR3
  290.      */
  291.     public double getMuoR3() {
  292.         return muoR3;
  293.     }

  294.     /** Get hXXX = h * &Chi;³.
  295.      * @return hXXX
  296.      */
  297.     public double getHXXX() {
  298.         return hXXX;
  299.     }

  300.     /** Get kXXX = h * &Chi;³.
  301.      * @return kXXX
  302.      */
  303.     public double getKXXX() {
  304.         return kXXX;
  305.     }

  306.     /** Get the value of max power for a/R3 in the serie expansion.
  307.      * @return maxAR3Pow
  308.      */
  309.     public int getMaxAR3Pow() {
  310.         return maxAR3Pow;
  311.     }

  312.     /** Get the value of max power for e in the serie expansion.
  313.      * @return maxEccPow
  314.      */
  315.     public int getMaxEccPow() {
  316.         return maxEccPow;
  317.     }

  318.     /** Get the value of a / R3 up to power maxAR3Pow.
  319.      * @return aoR3Pow
  320.      */
  321.     public double[] getAoR3Pow() {
  322.         return aoR3Pow;
  323.     }

  324.    /** Get the value of max frequency of F.
  325.      * @return maxFreqF
  326.      */
  327.     public int getMaxFreqF() {
  328.         return maxFreqF;
  329.     }

  330.     /** Get the Keplerian mean motion.
  331.      * <p>The Keplerian mean motion is computed directly from semi major axis
  332.      * and central acceleration constant.</p>
  333.      * @return Keplerian mean motion in radians per second
  334.      */
  335.     public double getMeanMotion() {
  336.         return motion;
  337.     }

  338.     /** Get the value of Qns coefficients.
  339.      * @return Qns
  340.      */
  341.     public double[][] getQns() {
  342.         return Qns;
  343.     }

  344. }