DSSTAtmosphericDrag.java

  1. /* Copyright 2002-2023 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.List;
  19. import java.util.stream.Stream;

  20. import org.hipparchus.CalculusFieldElement;
  21. import org.hipparchus.Field;
  22. import org.hipparchus.util.FastMath;
  23. import org.hipparchus.util.MathArrays;
  24. import org.hipparchus.util.MathUtils;
  25. import org.orekit.forces.drag.DragForce;
  26. import org.orekit.forces.drag.DragSensitive;
  27. import org.orekit.forces.drag.IsotropicDrag;
  28. import org.orekit.models.earth.atmosphere.Atmosphere;
  29. import org.orekit.propagation.FieldSpacecraftState;
  30. import org.orekit.propagation.SpacecraftState;
  31. import org.orekit.propagation.events.EventDetector;
  32. import org.orekit.propagation.events.FieldEventDetector;
  33. import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
  34. import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
  35. import org.orekit.utils.Constants;
  36. import org.orekit.utils.ParameterDriver;

  37. /** Atmospheric drag contribution to the
  38.  *  {@link org.orekit.propagation.semianalytical.dsst.DSSTPropagator DSSTPropagator}.
  39.  *  <p>
  40.  *  The drag acceleration is computed through the acceleration model of
  41.  *  {@link org.orekit.forces.drag.DragForce DragForce}.
  42.  *  </p>
  43.  *
  44.  * @author Pascal Parraud
  45.  */
  46. public class DSSTAtmosphericDrag extends AbstractGaussianContribution {

  47.     /** Threshold for the choice of the Gauss quadrature order. */
  48.     private static final double GAUSS_THRESHOLD = 6.0e-10;

  49.     /** Upper limit for atmospheric drag (m) . */
  50.     private static final double ATMOSPHERE_ALTITUDE_MAX = 1000000.;

  51.     /** Atmospheric drag force model. */
  52.     private final DragForce drag;

  53.     /** Critical distance from the center of the central body for entering/leaving the atmosphere. */
  54.     private final double     rbar;

  55.     /** Simple constructor with custom force.
  56.      * @param force atmospheric drag force model
  57.      * @param mu central attraction coefficient
  58.      */
  59.     public DSSTAtmosphericDrag(final DragForce force, final double mu) {
  60.         //Call to the constructor from superclass using the numerical drag model as ForceModel
  61.         super("DSST-drag-", GAUSS_THRESHOLD, force, mu);
  62.         this.drag = force;
  63.         this.rbar = ATMOSPHERE_ALTITUDE_MAX + Constants.WGS84_EARTH_EQUATORIAL_RADIUS;
  64.     }

  65.     /** Simple constructor assuming spherical spacecraft.
  66.      * @param atmosphere atmospheric model
  67.      * @param cd drag coefficient
  68.      * @param area cross sectionnal area of satellite
  69.      * @param mu central attraction coefficient
  70.      */
  71.     public DSSTAtmosphericDrag(final Atmosphere atmosphere, final double cd,
  72.                                final double area, final double mu) {
  73.         this(atmosphere, new IsotropicDrag(area, cd), mu);
  74.     }

  75.     /** Simple constructor with custom spacecraft.
  76.      * @param atmosphere atmospheric model
  77.      * @param spacecraft spacecraft model
  78.      * @param mu central attraction coefficient
  79.      */
  80.     public DSSTAtmosphericDrag(final Atmosphere atmosphere, final DragSensitive spacecraft, final double mu) {

  81.         //Call to the constructor from superclass using the numerical drag model as ForceModel
  82.         this(new DragForce(atmosphere, spacecraft), mu);
  83.     }

  84.     /** Get the atmospheric model.
  85.      * @return atmosphere model
  86.      */
  87.     public Atmosphere getAtmosphere() {
  88.         return drag.getAtmosphere();
  89.     }

  90.     /** Get the critical distance.
  91.      *  <p>
  92.      *  The critical distance from the center of the central body aims at
  93.      *  defining the atmosphere entry/exit.
  94.      *  </p>
  95.      *  @return the critical distance from the center of the central body (m)
  96.      */
  97.     public double getRbar() {
  98.         return rbar;
  99.     }

  100.     /** {@inheritDoc} */
  101.     public Stream<EventDetector> getEventDetectors() {
  102.         return drag.getEventDetectors();
  103.     }

  104.     /** {@inheritDoc} */
  105.     @Override
  106.     public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventDetectors(final Field<T> field) {
  107.         return drag.getFieldEventDetectors(field);
  108.     }

  109.     /** {@inheritDoc} */
  110.     protected double[] getLLimits(final SpacecraftState state, final AuxiliaryElements auxiliaryElements) {

  111.         final double perigee = auxiliaryElements.getSma() * (1. - auxiliaryElements.getEcc());

  112.         // Trajectory entirely out of the atmosphere
  113.         if (perigee > rbar) {
  114.             return new double[2];
  115.         }
  116.         final double apogee  = auxiliaryElements.getSma() * (1. + auxiliaryElements.getEcc());
  117.         // Trajectory entirely within of the atmosphere
  118.         if (apogee < rbar) {
  119.             return new double[] { -FastMath.PI + MathUtils.normalizeAngle(state.getLv(), 0),
  120.                                   FastMath.PI + MathUtils.normalizeAngle(state.getLv(), 0) };
  121.         }
  122.         // Else, trajectory partialy within of the atmosphere
  123.         final double fb = FastMath.acos(((auxiliaryElements.getSma() * (1. - auxiliaryElements.getEcc() * auxiliaryElements.getEcc()) / rbar) - 1.) / auxiliaryElements.getEcc());
  124.         final double wW = FastMath.atan2(auxiliaryElements.getH(), auxiliaryElements.getK());
  125.         return new double[] {wW - fb, wW + fb};
  126.     }

  127.     /** {@inheritDoc} */
  128.     protected <T extends CalculusFieldElement<T>> T[] getLLimits(final FieldSpacecraftState<T> state,
  129.                                                              final FieldAuxiliaryElements<T> auxiliaryElements) {

  130.         final Field<T> field = state.getDate().getField();

  131.         final T[] tab = MathArrays.buildArray(field, 2);

  132.         final T perigee = auxiliaryElements.getSma().multiply(auxiliaryElements.getEcc().negate().add(1.));
  133.         // Trajectory entirely out of the atmosphere
  134.         if (perigee.getReal() > rbar) {
  135.             return tab;
  136.         }
  137.         final T apogee  = auxiliaryElements.getSma().multiply(auxiliaryElements.getEcc().add(1.));
  138.         // Trajectory entirely within of the atmosphere
  139.         if (apogee.getReal() < rbar) {
  140.             final T zero = field.getZero();
  141.             final T pi   = zero.getPi();
  142.             tab[0] = MathUtils.normalizeAngle(state.getLv(), zero).subtract(pi);
  143.             tab[1] = MathUtils.normalizeAngle(state.getLv(), zero).add(pi);
  144.             return tab;
  145.         }
  146.         // Else, trajectory partialy within of the atmosphere
  147.         final T fb = FastMath.acos(((auxiliaryElements.getSma().multiply(auxiliaryElements.getEcc().multiply(auxiliaryElements.getEcc()).negate().add(1.)).divide(rbar)).subtract(1.)).divide(auxiliaryElements.getEcc()));
  148.         final T wW = FastMath.atan2(auxiliaryElements.getH(), auxiliaryElements.getK());

  149.         tab[0] = wW.subtract(fb);
  150.         tab[1] = wW.add(fb);
  151.         return tab;
  152.     }

  153.     /** {@inheritDoc} */
  154.     @Override
  155.     protected List<ParameterDriver> getParametersDriversWithoutMu() {
  156.         return drag.getParametersDrivers();
  157.     }

  158.     /** Get spacecraft shape.
  159.      *
  160.      * @return spacecraft shape
  161.      */
  162.     public DragSensitive getSpacecraft() {
  163.         return drag.getSpacecraft();
  164.     }

  165.     /** Get drag force.
  166.      *
  167.      * @return drag force
  168.      */
  169.     public DragForce getDrag() {
  170.         return drag;
  171.     }
  172. }