FieldDSSTThirdBodyContext.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.Field;
  19. import org.hipparchus.RealFieldElement;
  20. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  21. import org.hipparchus.util.CombinatoricsUtils;
  22. import org.hipparchus.util.FastMath;
  23. import org.hipparchus.util.MathArrays;
  24. import org.orekit.bodies.CelestialBody;
  25. import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory;
  26. import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
  27. import org.orekit.propagation.semianalytical.dsst.utilities.UpperBounds;

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

  38.     /** Max power for summation. */
  39.     private static final int    MAX_POWER = 22;

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

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

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

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

  48.     /** Max power for e in the serie expansion. */
  49.     private int maxEccPow;

  50.     /** a / R3 up to power maxAR3Pow. */
  51.     private T[] aoR3Pow;

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

  54.     /** Max frequency of F. */
  55.     private int maxFreqF;

  56.     /** Qns coefficients. */
  57.     private T[][] Qns;

  58.     /** Standard gravitational parameter μ for the body in m³/s². */
  59.     private final T gm;

  60.     /** Distance from center of mass of the central body to the 3rd body. */
  61.     private T R3;

  62.     /** A = sqrt(μ * a). */
  63.     private final T A;

  64.     // Direction cosines of the symmetry axis
  65.     /** α. */
  66.     private final T alpha;
  67.     /** β. */
  68.     private final T beta;
  69.     /** γ. */
  70.     private final T gamma;

  71.     /** B². */
  72.     private final T BB;
  73.     /** B³. */
  74.     private final T BBB;

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

  91.     /** mu3 / R3. */
  92.     private final T muoR3;

  93.     /** b = 1 / (1 + sqrt(1 - e²)) = 1 / (1 + B).*/
  94.     private final T b;

  95.     /** h * &Chi;³. */
  96.     private final T hXXX;
  97.     /** k * &Chi;³. */
  98.     private final T kXXX;

  99.     /** Keplerian mean motion. */
  100.     private final T motion;

  101.     /**
  102.      * Simple constructor.
  103.      *
  104.      * @param auxiliaryElements auxiliary elements related to the current orbit
  105.      * @param thirdBody body the 3rd body to consider
  106.      * @param parameters values of the force model parameters
  107.      */
  108.     FieldDSSTThirdBodyContext(final FieldAuxiliaryElements<T> auxiliaryElements,
  109.                                      final CelestialBody thirdBody,
  110.                                      final T[] parameters) {

  111.         super(auxiliaryElements);

  112.         // Field for array building
  113.         final Field<T> field = auxiliaryElements.getDate().getField();
  114.         final T zero = field.getZero();

  115.         final T mu = parameters[1];
  116.         A = FastMath.sqrt(mu.multiply(auxiliaryElements.getSma()));

  117.         this.gm = parameters[0];

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

  121.         // Distance from center of mass of the central body to the 3rd body
  122.         final FieldVector3D<T> bodyPos = thirdBody.getPVCoordinates(auxiliaryElements.getDate(), auxiliaryElements.getFrame()).getPosition();
  123.         R3 = bodyPos.getNorm();

  124.         // Direction cosines
  125.         final FieldVector3D<T> bodyDir = bodyPos.normalize();
  126.         alpha = (T) bodyDir.dotProduct(auxiliaryElements.getVectorF());
  127.         beta  = (T) bodyDir.dotProduct(auxiliaryElements.getVectorG());
  128.         gamma = (T) bodyDir.dotProduct(auxiliaryElements.getVectorW());

  129.         //&Chi;<sup>-2</sup>.
  130.         BB = auxiliaryElements.getB().multiply(auxiliaryElements.getB());
  131.         //&Chi;<sup>-3</sup>.
  132.         BBB = BB.multiply(auxiliaryElements.getB());

  133.         //b = 1 / (1 + B)
  134.         b = auxiliaryElements.getB().add(1.).reciprocal();

  135.         // &Chi;
  136.         X = auxiliaryElements.getB().reciprocal();
  137.         XX = X.multiply(X);
  138.         XXX = X.multiply(XX);

  139.         // -2 * a / A
  140.         m2aoA = auxiliaryElements.getSma().multiply(-2.).divide(A);
  141.         // B / A
  142.         BoA = auxiliaryElements.getB().divide(A);
  143.         // 1 / AB
  144.         ooAB = (A.multiply(auxiliaryElements.getB())).reciprocal();
  145.         // -C / 2AB
  146.         mCo2AB = auxiliaryElements.getC().multiply(ooAB).divide(2.).negate();
  147.         // B / A(1 + B)
  148.         BoABpo = BoA.divide(auxiliaryElements.getB().add(1.));
  149.         // mu3 / R3
  150.         muoR3 = R3.divide(gm).reciprocal();
  151.         //h * &Chi;³
  152.         hXXX = XXX.multiply(auxiliaryElements.getH());
  153.         //k * &Chi;³
  154.         kXXX = XXX.multiply(auxiliaryElements.getK());

  155.         // Truncation tolerance.
  156.         final T aoR3 = auxiliaryElements.getSma().divide(R3);
  157.         final double tol = ( aoR3.getReal() > .3 || (aoR3.getReal() > .15  && auxiliaryElements.getEcc().getReal() > .25) ) ? BIG_TRUNCATION_TOLERANCE : SMALL_TRUNCATION_TOLERANCE;

  158.         // Utilities for truncation
  159.         // Set a lower bound for eccentricity
  160.         final T eo2  = FastMath.max(zero.add(0.0025), auxiliaryElements.getEcc().divide(2.));
  161.         final T x2o2 = XX.divide(2.);
  162.         final T[] eccPwr = MathArrays.buildArray(field, MAX_POWER);
  163.         final T[] chiPwr = MathArrays.buildArray(field, MAX_POWER);
  164.         eccPwr[0] = zero.add(1.);
  165.         chiPwr[0] = X;
  166.         for (int i = 1; i < MAX_POWER; i++) {
  167.             eccPwr[i] = eccPwr[i - 1].multiply(eo2);
  168.             chiPwr[i] = chiPwr[i - 1].multiply(x2o2);
  169.         }

  170.         // Auxiliary quantities.
  171.         final T ao2rxx = aoR3.divide(XX.multiply(2.));
  172.         T xmuarn       = ao2rxx.multiply(ao2rxx).multiply(gm).divide(X.multiply(R3));
  173.         T term         = zero;

  174.         // Compute max power for a/R3 and e.
  175.         maxAR3Pow = 2;
  176.         maxEccPow = 0;
  177.         int n     = 2;
  178.         int m     = 2;
  179.         int nsmd2 = 0;

  180.         do {
  181.             term =  xmuarn.multiply((CombinatoricsUtils.factorialDouble(n + m) / (CombinatoricsUtils.factorialDouble(nsmd2) * CombinatoricsUtils.factorialDouble(nsmd2 + m))) *
  182.                             (CombinatoricsUtils.factorialDouble(n + m + 1) / (CombinatoricsUtils.factorialDouble(m) * CombinatoricsUtils.factorialDouble(n + 1))) *
  183.                             (CombinatoricsUtils.factorialDouble(n - m + 1) / CombinatoricsUtils.factorialDouble(n + 1))).
  184.                             multiply(eccPwr[m]).multiply(UpperBounds.getDnl(XX, chiPwr[m], n + 2, m));

  185.             if (term.getReal() < tol) {
  186.                 if (m == 0) {
  187.                     break;
  188.                 } else if (m < 2) {
  189.                     xmuarn = xmuarn.multiply(ao2rxx);
  190.                     m = 0;
  191.                     n++;
  192.                     nsmd2++;
  193.                 } else {
  194.                     m -= 2;
  195.                     nsmd2++;
  196.                 }
  197.             } else {
  198.                 maxAR3Pow = n;
  199.                 maxEccPow = FastMath.max(m, maxEccPow);
  200.                 xmuarn = xmuarn.multiply(ao2rxx);
  201.                 m++;
  202.                 n++;
  203.             }
  204.         } while (n < MAX_POWER);

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

  206.         // allocate the array aoR3Pow
  207.         aoR3Pow = MathArrays.buildArray(field, maxAR3Pow + 1);

  208.         aoR3Pow[0] = field.getOne();
  209.         for (int i = 1; i <= maxAR3Pow; i++) {
  210.             aoR3Pow[i] = aoR3.multiply(aoR3Pow[i - 1]);
  211.         }

  212.         maxFreqF = maxAR3Pow + 1;
  213.         maxEccPowShort = MAX_ECCPOWER_SP;

  214.         Qns = CoefficientsFactory.computeQns(gamma, maxAR3Pow, FastMath.max(maxEccPow, maxEccPowShort));
  215.     }

  216.     /** Get A = sqrt(μ * a).
  217.      * @return A
  218.      */
  219.     public T getA() {
  220.         return A;
  221.     }

  222.     /** Get direction cosine α for central body.
  223.      * @return α
  224.      */
  225.     public T getAlpha() {
  226.         return alpha;
  227.     }

  228.     /** Get direction cosine β for central body.
  229.      * @return β
  230.      */
  231.     public T getBeta() {
  232.         return beta;
  233.     }

  234.     /** Get direction cosine γ for central body.
  235.      * @return γ
  236.      */
  237.     public T getGamma() {
  238.         return gamma;
  239.     }

  240.     /** Get B².
  241.      * @return B²
  242.      */
  243.     public T getBB() {
  244.         return BB;
  245.     }

  246.     /** Get B³.
  247.      * @return B³
  248.      */
  249.     public T getBBB() {
  250.         return BBB;
  251.     }

  252.     /** Get b = 1 / (1 + sqrt(1 - e²)) = 1 / (1 + B).
  253.      * @return b
  254.      */
  255.     public T getb() {
  256.         return b;
  257.     }

  258.     /** Get &Chi; = 1 / sqrt(1 - e²) = 1 / B.
  259.      * @return &Chi;
  260.      */
  261.     public T getX() {
  262.         return X;
  263.     }

  264.     /** Get m2aoA = -2 * a / A.
  265.      * @return m2aoA
  266.      */
  267.     public T getM2aoA() {
  268.         return m2aoA;
  269.     }

  270.     /** Get B / A.
  271.      * @return BoA
  272.      */
  273.     public T getBoA() {
  274.         return BoA;
  275.     }

  276.     /** Get ooAB = 1 / (A * B).
  277.      * @return ooAB
  278.      */
  279.     public T getOoAB() {
  280.         return ooAB;
  281.     }

  282.     /** Get mCo2AB = -C / 2AB.
  283.      * @return mCo2AB
  284.      */
  285.     public T getMCo2AB() {
  286.         return mCo2AB;
  287.     }

  288.     /** Get BoABpo = B / A(1 + B).
  289.      * @return BoABpo
  290.      */
  291.     public T getBoABpo() {
  292.         return BoABpo;
  293.     }

  294.     /** Get muoR3 = mu3 / R3.
  295.      * @return muoR3
  296.      */
  297.     public T getMuoR3() {
  298.         return muoR3;
  299.     }

  300.     /** Get hXXX = h * &Chi;³.
  301.      * @return hXXX
  302.      */
  303.     public T getHXXX() {
  304.         return hXXX;
  305.     }

  306.     /** Get kXXX = h * &Chi;³.
  307.      * @return kXXX
  308.      */
  309.     public T getKXXX() {
  310.         return kXXX;
  311.     }

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

  318.     /** Get the value of max power for e in the serie expansion.
  319.      * @return maxEccPow
  320.      */
  321.     public int getMaxEccPow() {
  322.         return maxEccPow;
  323.     }

  324.     /** Get the value of a / R3 up to power maxAR3Pow.
  325.      * @return aoR3Pow
  326.      */
  327.     public T[] getAoR3Pow() {
  328.         return aoR3Pow;
  329.     }

  330.    /** Get the value of max frequency of F.
  331.      * @return maxFreqF
  332.      */
  333.     public int getMaxFreqF() {
  334.         return maxFreqF;
  335.     }

  336.     /** Get the Keplerian mean motion.
  337.      * <p>The Keplerian mean motion is computed directly from semi major axis
  338.      * and central acceleration constant.</p>
  339.      * @return Keplerian mean motion in radians per second
  340.      */
  341.     public T getMeanMotion() {
  342.         return motion;
  343.     }

  344.     /** Get the value of Qns coefficients.
  345.      * @return Qns
  346.      */
  347.     public T[][] getQns() {
  348.         return Qns;
  349.     }

  350. }