FieldIntegratedEphemeris.java

  1. /* Copyright 2002-2022 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.integration;

  18. import java.util.Arrays;
  19. import java.util.Collections;
  20. import java.util.List;
  21. import java.util.Map;

  22. import org.hipparchus.CalculusFieldElement;
  23. import org.hipparchus.ode.FieldDenseOutputModel;
  24. import org.hipparchus.ode.FieldODEStateAndDerivative;
  25. import org.orekit.errors.OrekitException;
  26. import org.orekit.errors.OrekitInternalError;
  27. import org.orekit.errors.OrekitMessages;
  28. import org.orekit.frames.Frame;
  29. import org.orekit.orbits.FieldOrbit;
  30. import org.orekit.propagation.FieldAdditionalStateProvider;
  31. import org.orekit.propagation.FieldBoundedPropagator;
  32. import org.orekit.propagation.FieldSpacecraftState;
  33. import org.orekit.propagation.PropagationType;
  34. import org.orekit.propagation.analytical.FieldAbstractAnalyticalPropagator;
  35. import org.orekit.time.FieldAbsoluteDate;
  36. import org.orekit.utils.FieldArrayDictionary;
  37. import org.orekit.utils.ParameterDriver;
  38. import org.orekit.utils.TimeStampedFieldPVCoordinates;

  39. /** This class stores sequentially generated orbital parameters for
  40.  * later retrieval.
  41.  *
  42.  * <p>
  43.  * Instances of this class are built automatically when the {@link
  44.  * org.orekit.propagation.FieldPropagator#getEphemerisGenerator()
  45.  * getEphemerisGenerator} method has been called. They are created when propagation is over.
  46.  * Random access to any intermediate state of the orbit throughout the propagation range is
  47.  * possible afterwards through this object.
  48.  * </p>
  49.  * <p>
  50.  * A typical use case is for numerically integrated orbits, which can be used by
  51.  * algorithms that need to wander around according to their own algorithm without
  52.  * cumbersome tight links with the integrator.
  53.  * </p>
  54.  * <p>
  55.  * As this class implements the {@link org.orekit.propagation.Propagator Propagator}
  56.  * interface, it can itself be used in batch mode to build another instance of the
  57.  * same type. This is however not recommended since it would be a waste of resources.
  58.  * </p>
  59.  * <p>
  60.  * Note that this class stores all intermediate states along with interpolation
  61.  * models, so it may be memory intensive.
  62.  * </p>
  63.  *
  64.  * @see org.orekit.propagation.numerical.NumericalPropagator
  65.  * @author Mathieu Rom&eacute;ro
  66.  * @author Luc Maisonobe
  67.  * @author V&eacute;ronique Pommier-Maurussane
  68.  */
  69. public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
  70.     extends FieldAbstractAnalyticalPropagator<T> implements FieldBoundedPropagator<T> {

  71.     /** Event detection requires evaluating the state slightly before / past an event. */
  72.     private static final double EXTRAPOLATION_TOLERANCE = 1.0;

  73.     /** Mapper between raw double components and spacecraft state. */
  74.     private final FieldStateMapper<T> mapper;

  75.     /** Type of orbit to output (mean or osculating).
  76.      * <p>
  77.      * This is used only in the case of semianalitical propagators where there is a clear separation between
  78.      * mean and short periodic elements. It is ignored by the Numerical propagator.
  79.      * </p>
  80.      */
  81.     private PropagationType type;

  82.     /** Start date of the integration (can be min or max). */
  83.     private final FieldAbsoluteDate<T> startDate;

  84.     /** First date of the range. */
  85.     private final FieldAbsoluteDate<T> minDate;

  86.     /** Last date of the range. */
  87.     private final FieldAbsoluteDate<T> maxDate;

  88.     /** Underlying raw mathematical model. */
  89.     private FieldDenseOutputModel<T> model;

  90.     /** Unmanaged additional states that must be simply copied. */
  91.     private final FieldArrayDictionary<T> unmanaged;

  92.     /** Names of additional equations.
  93.      * @since 11.2
  94.      */
  95.     private final String[] equations;

  96.     /** Dimensions of additional equations.
  97.      * @since 11.2
  98.      */
  99.     private final int[] dimensions;

  100.     /** Creates a new instance of IntegratedEphemeris.
  101.      * @param startDate Start date of the integration (can be minDate or maxDate)
  102.      * @param minDate first date of the range
  103.      * @param maxDate last date of the range
  104.      * @param mapper mapper between raw double components and spacecraft state
  105.      * @param type type of orbit to output (mean or osculating)
  106.      * @param model underlying raw mathematical model
  107.      * @param unmanaged unmanaged additional states that must be simply copied
  108.      * @param providers providers for pre-integrated states
  109.      * @param equations names of additional equations
  110.      * @deprecated as of 11.2, replaced by {@link #FieldIntegratedEphemeris(FieldAbsoluteDate,
  111.      * FieldAbsoluteDate, FieldAbsoluteDate, FieldStateMapper, PropagationType,
  112.      * FieldDenseOutputModel, FieldArrayDictionary, List, String[], int[])}
  113.      */
  114.     @Deprecated
  115.     public FieldIntegratedEphemeris(final FieldAbsoluteDate<T> startDate,
  116.                                final FieldAbsoluteDate<T> minDate, final FieldAbsoluteDate<T> maxDate,
  117.                                final FieldStateMapper<T> mapper, final PropagationType type,
  118.                                final FieldDenseOutputModel<T> model,
  119.                                final Map<String, T[]> unmanaged,
  120.                                final List<org.orekit.propagation.FieldAdditionalStateProvider<T>> providers,
  121.                                final String[] equations) {
  122.         this(startDate, minDate, maxDate, mapper, type, model,
  123.              new FieldArrayDictionary<>(startDate.getField(), unmanaged),
  124.              providers, equations);
  125.     }

  126.     /** Creates a new instance of IntegratedEphemeris.
  127.      * @param startDate Start date of the integration (can be minDate or maxDate)
  128.      * @param minDate first date of the range
  129.      * @param maxDate last date of the range
  130.      * @param mapper mapper between raw double components and spacecraft state
  131.      * @param type type of orbit to output (mean or osculating)
  132.      * @param model underlying raw mathematical model
  133.      * @param unmanaged unmanaged additional states that must be simply copied
  134.      * @param providers generators for pre-integrated states
  135.      * @param equations names of additional equations
  136.      * @since 11.1
  137.      * @deprecated as of 11.2, replaced by {@link #FieldIntegratedEphemeris(FieldAbsoluteDate,
  138.      * FieldAbsoluteDate, FieldAbsoluteDate, FieldStateMapper, PropagationType,
  139.      * FieldDenseOutputModel, FieldArrayDictionary, List, String[], int[])}
  140.      */
  141.     @Deprecated
  142.     public FieldIntegratedEphemeris(final FieldAbsoluteDate<T> startDate,
  143.                                     final FieldAbsoluteDate<T> minDate, final FieldAbsoluteDate<T> maxDate,
  144.                                     final FieldStateMapper<T> mapper, final PropagationType type,
  145.                                     final FieldDenseOutputModel<T> model,
  146.                                     final FieldArrayDictionary<T> unmanaged,
  147.                                     final List<FieldAdditionalStateProvider<T>> providers,
  148.                                     final String[] equations) {
  149.         this(startDate, minDate, maxDate, mapper, type, model,
  150.              unmanaged, providers, equations,
  151.              remainingDimensions(model, unmanaged, providers, equations));
  152.     }

  153.     /** Creates a new instance of IntegratedEphemeris.
  154.      * @param startDate Start date of the integration (can be minDate or maxDate)
  155.      * @param minDate first date of the range
  156.      * @param maxDate last date of the range
  157.      * @param mapper mapper between raw double components and spacecraft state
  158.      * @param type type of orbit to output (mean or osculating)
  159.      * @param model underlying raw mathematical model
  160.      * @param unmanaged unmanaged additional states that must be simply copied
  161.      * @param providers generators for pre-integrated states
  162.      * @param equations names of additional equations
  163.      * @param dimensions dimensions of additional equations
  164.      * @since 11.2
  165.      */
  166.     public FieldIntegratedEphemeris(final FieldAbsoluteDate<T> startDate,
  167.                                     final FieldAbsoluteDate<T> minDate, final FieldAbsoluteDate<T> maxDate,
  168.                                     final FieldStateMapper<T> mapper, final PropagationType type,
  169.                                     final FieldDenseOutputModel<T> model,
  170.                                     final FieldArrayDictionary<T> unmanaged,
  171.                                     final List<FieldAdditionalStateProvider<T>> providers,
  172.                                     final String[] equations, final int[] dimensions) {

  173.         super(startDate.getField(), mapper.getAttitudeProvider());

  174.         this.startDate = startDate;
  175.         this.minDate   = minDate;
  176.         this.maxDate   = maxDate;
  177.         this.mapper    = mapper;
  178.         this.type      = type;
  179.         this.model     = model;
  180.         this.unmanaged = unmanaged;

  181.         // set up the pre-integrated providers
  182.         for (final FieldAdditionalStateProvider<T> provider : providers) {
  183.             addAdditionalStateProvider(provider);
  184.         }

  185.         this.equations  = equations.clone();
  186.         this.dimensions = dimensions.clone();

  187.     }

  188.     /** Compute remaining dimensions for additional equations.
  189.      * @param <T> tupe of the field elements
  190.      * @param model underlying raw mathematical model
  191.      * @param unmanaged unmanaged additional states that must be simply copied
  192.      * @param providers providers for pre-integrated states
  193.      * @param equations names of additional equations
  194.      * @return dimensions of additional equations
  195.      * @deprecated as of 11.2 this method is temporary and should be removed
  196.      * when the calling constructors are removed
  197.      * @since 11.2
  198.      */
  199.     @Deprecated
  200.     private static <T extends CalculusFieldElement<T>> int[] remainingDimensions(final FieldDenseOutputModel<T> model,
  201.                                                                                  final FieldArrayDictionary<T> unmanaged,
  202.                                                                                  final List<FieldAdditionalStateProvider<T>> providers,
  203.                                                                                  final String[] equations) {
  204.         final FieldODEStateAndDerivative<T> osd = model.getInterpolatedState(model.getInitialTime());
  205.         if (equations.length != osd.getNumberOfSecondaryStates()) {
  206.             throw new OrekitInternalError(null);
  207.         }
  208.         final int[] dimensions = new int[equations.length];
  209.         for (int i = 0; i < dimensions.length; ++i) {
  210.             dimensions[i] = osd.getSecondaryStateDimension(i + 1);
  211.         }
  212.         return dimensions;
  213.     }

  214.     /** Interpolate the model at some date.
  215.      * @param date desired interpolation date
  216.      * @return state interpolated at date
  217.           * of supported range
  218.      */
  219.     private FieldODEStateAndDerivative<T> getInterpolatedState(final FieldAbsoluteDate<T> date) {

  220.         // compare using double precision instead of FieldAbsoluteDate<T>.compareTo(...)
  221.         // because time is expressed as a double when searching for events
  222.         if (date.compareTo(minDate.shiftedBy(-EXTRAPOLATION_TOLERANCE)) < 0) {
  223.             // date is outside of supported range
  224.             throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE,
  225.                     date, minDate, maxDate, minDate.durationFrom(date).getReal());
  226.         }
  227.         if (date.compareTo(maxDate.shiftedBy(EXTRAPOLATION_TOLERANCE)) > 0) {
  228.             // date is outside of supported range
  229.             throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER,
  230.                     date, minDate, maxDate, date.durationFrom(maxDate).getReal());
  231.         }

  232.         return model.getInterpolatedState(date.durationFrom(startDate));

  233.     }

  234.     /** {@inheritDoc} */
  235.     @Override
  236.     protected FieldSpacecraftState<T> basicPropagate(final FieldAbsoluteDate<T> date) {
  237.         final FieldODEStateAndDerivative<T> os = getInterpolatedState(date);
  238.         FieldSpacecraftState<T> state = mapper.mapArrayToState(mapper.mapDoubleToDate(os.getTime(), date),
  239.                                                                os.getPrimaryState(), os.getPrimaryDerivative(),
  240.                                                                type);
  241.         for (FieldArrayDictionary<T>.Entry initial : unmanaged.getData()) {
  242.             state = state.addAdditionalState(initial.getKey(), initial.getValue());
  243.         }
  244.         return state;
  245.     }

  246.     /** {@inheritDoc} */
  247.     @Override
  248.     protected FieldOrbit<T> propagateOrbit(final FieldAbsoluteDate<T> date, final T[] parameters) {
  249.         return basicPropagate(date).getOrbit();
  250.     }

  251.     /** {@inheritDoc} */
  252.     @Override
  253.     protected T getMass(final FieldAbsoluteDate<T> date) {
  254.         return basicPropagate(date).getMass();
  255.     }

  256.     /** {@inheritDoc} */
  257.     @Override
  258.     public TimeStampedFieldPVCoordinates<T> getPVCoordinates(final FieldAbsoluteDate<T> date, final Frame frame) {
  259.         return propagate(date).getPVCoordinates(frame);
  260.     }

  261.     /** Get the first date of the range.
  262.      * @return the first date of the range
  263.      */
  264.     @Override
  265.     public FieldAbsoluteDate<T> getMinDate() {
  266.         return minDate;
  267.     }

  268.     /** Get the last date of the range.
  269.      * @return the last date of the range
  270.      */
  271.     @Override
  272.     public FieldAbsoluteDate<T> getMaxDate() {
  273.         return maxDate;
  274.     }

  275.     @Override
  276.     public Frame getFrame() {
  277.         return this.mapper.getFrame();
  278.     }

  279.     /** {@inheritDoc} */
  280.     @Override
  281.     public void resetInitialState(final FieldSpacecraftState<T> state) {
  282.         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
  283.     }

  284.     /** {@inheritDoc} */
  285.     @Override
  286.     protected void resetIntermediateState(final FieldSpacecraftState<T> state, final boolean forward) {
  287.         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
  288.     }

  289.     /** {@inheritDoc} */
  290.     @Override
  291.     public FieldSpacecraftState<T> getInitialState() {
  292.         return updateAdditionalStates(basicPropagate(getMinDate()));
  293.     }

  294.     /** {@inheritDoc} */
  295.     @Override
  296.     protected FieldSpacecraftState<T> updateAdditionalStates(final FieldSpacecraftState<T> original) {

  297.         FieldSpacecraftState<T> updated = super.updateAdditionalStates(original);

  298.         if (equations.length > 0) {
  299.             final FieldODEStateAndDerivative<T> osd                = getInterpolatedState(updated.getDate());
  300.             final T[]                           combinedState      = osd.getSecondaryState(1);
  301.             final T[]                           combinedDerivative = osd.getSecondaryDerivative(1);
  302.             int index = 0;
  303.             for (int i = 0; i < equations.length; ++i) {
  304.                 final T[] state      = Arrays.copyOfRange(combinedState,      index, index + dimensions[i]);
  305.                 final T[] derivative = Arrays.copyOfRange(combinedDerivative, index, index + dimensions[i]);
  306.                 updated = updated.
  307.                           addAdditionalState(equations[i], state).
  308.                           addAdditionalStateDerivative(equations[i], derivative);
  309.                 index += dimensions[i];
  310.             }
  311.         }

  312.         return updated;

  313.     }

  314.     /** {@inheritDoc} */
  315.     @Override
  316.     protected List<ParameterDriver> getParametersDrivers() {
  317.         // Integrated Ephemeris propagation model does not have parameter drivers.
  318.         return Collections.emptyList();
  319.     }

  320. }