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.Collections;
  19. import java.util.List;
  20. import java.util.Map;

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

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

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

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

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

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

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

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

  86.     /** Underlying raw mathematical model. */
  87.     private FieldDenseOutputModel<T> model;

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

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

  116.     /** Creates a new instance of IntegratedEphemeris.
  117.      * @param startDate Start date of the integration (can be minDate or maxDate)
  118.      * @param minDate first date of the range
  119.      * @param maxDate last date of the range
  120.      * @param mapper mapper between raw double components and spacecraft state
  121.      * @param type type of orbit to output (mean or osculating)
  122.      * @param model underlying raw mathematical model
  123.      * @param unmanaged unmanaged additional states that must be simply copied
  124.      * @param providers generators for pre-integrated states
  125.      * @param equations names of additional equations
  126.      * @since 11.1
  127.      */
  128.     public FieldIntegratedEphemeris(final FieldAbsoluteDate<T> startDate,
  129.                                     final FieldAbsoluteDate<T> minDate, final FieldAbsoluteDate<T> maxDate,
  130.                                     final FieldStateMapper<T> mapper, final PropagationType type,
  131.                                     final FieldDenseOutputModel<T> model,
  132.                                     final FieldArrayDictionary<T> unmanaged,
  133.                                     final List<FieldAdditionalStateProvider<T>> providers,
  134.                                     final String[] equations) {

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

  136.         this.startDate = startDate;
  137.         this.minDate   = minDate;
  138.         this.maxDate   = maxDate;
  139.         this.mapper    = mapper;
  140.         this.type      = type;
  141.         this.model     = model;
  142.         this.unmanaged = unmanaged;

  143.         // set up the pre-integrated providers
  144.         for (final FieldAdditionalStateProvider<T> provider : providers) {
  145.             addAdditionalStateProvider(provider);
  146.         }

  147.         // set up providers to map the final elements of the model array to additional states
  148.         for (int i = 0; i < equations.length; ++i) {
  149.             addAdditionalStateProvider(new LocalGenerator(equations[i], i));
  150.         }

  151.     }

  152.     /** Interpolate the model at some date.
  153.      * @param date desired interpolation date
  154.      * @return state interpolated at date
  155.           * of supported range
  156.      */
  157.     private FieldODEStateAndDerivative<T> getInterpolatedState(final FieldAbsoluteDate<T> date) {

  158.         // compare using double precision instead of FieldAbsoluteDate<T>.compareTo(...)
  159.         // because time is expressed as a double when searching for events
  160.         if (date.compareTo(minDate.shiftedBy(-EXTRAPOLATION_TOLERANCE)) < 0) {
  161.             // date is outside of supported range
  162.             throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE,
  163.                     date, minDate, maxDate, minDate.durationFrom(date).getReal());
  164.         }
  165.         if (date.compareTo(maxDate.shiftedBy(EXTRAPOLATION_TOLERANCE)) > 0) {
  166.             // date is outside of supported range
  167.             throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER,
  168.                     date, minDate, maxDate, date.durationFrom(maxDate).getReal());
  169.         }

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

  171.     }

  172.     /** {@inheritDoc} */
  173.     @Override
  174.     protected FieldSpacecraftState<T> basicPropagate(final FieldAbsoluteDate<T> date) {
  175.         final FieldODEStateAndDerivative<T> os = getInterpolatedState(date);
  176.         FieldSpacecraftState<T> state = mapper.mapArrayToState(mapper.mapDoubleToDate(os.getTime(), date),
  177.                                                                os.getPrimaryState(), os.getPrimaryDerivative(),
  178.                                                                type);
  179.         for (FieldArrayDictionary<T>.Entry initial : unmanaged.getData()) {
  180.             state = state.addAdditionalState(initial.getKey(), initial.getValue());
  181.         }
  182.         return state;
  183.     }

  184.     /** {@inheritDoc} */
  185.     @Override
  186.     protected FieldOrbit<T> propagateOrbit(final FieldAbsoluteDate<T> date, final T[] parameters) {
  187.         return basicPropagate(date).getOrbit();
  188.     }

  189.     /** {@inheritDoc} */
  190.     @Override
  191.     protected T getMass(final FieldAbsoluteDate<T> date) {
  192.         return basicPropagate(date).getMass();
  193.     }

  194.     /** {@inheritDoc} */
  195.     @Override
  196.     public TimeStampedFieldPVCoordinates<T> getPVCoordinates(final FieldAbsoluteDate<T> date, final Frame frame) {
  197.         return propagate(date).getPVCoordinates(frame);
  198.     }

  199.     /** Get the first date of the range.
  200.      * @return the first date of the range
  201.      */
  202.     @Override
  203.     public FieldAbsoluteDate<T> getMinDate() {
  204.         return minDate;
  205.     }

  206.     /** Get the last date of the range.
  207.      * @return the last date of the range
  208.      */
  209.     @Override
  210.     public FieldAbsoluteDate<T> getMaxDate() {
  211.         return maxDate;
  212.     }

  213.     @Override
  214.     public Frame getFrame() {
  215.         return this.mapper.getFrame();
  216.     }

  217.     /** {@inheritDoc} */
  218.     @Override
  219.     public void resetInitialState(final FieldSpacecraftState<T> state) {
  220.         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
  221.     }

  222.     /** {@inheritDoc} */
  223.     @Override
  224.     protected void resetIntermediateState(final FieldSpacecraftState<T> state, final boolean forward) {
  225.         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
  226.     }

  227.     /** {@inheritDoc} */
  228.     @Override
  229.     public FieldSpacecraftState<T> getInitialState() {
  230.         return updateAdditionalStates(basicPropagate(getMinDate()));
  231.     }

  232.     /** Local generator for additional state data. */
  233.     private class LocalGenerator implements FieldAdditionalStateProvider<T> {

  234.         /** Name of the additional state. */
  235.         private final String name;

  236.         /** Index of the additional state. */
  237.         private final int index;

  238.         /** Simple constructor.
  239.          * @param name name of the additional state
  240.          * @param index index of the additional state
  241.          */
  242.         LocalGenerator(final String name, final int index) {
  243.             this.name  = name;
  244.             this.index = index;
  245.         }

  246.         /** {@inheritDoc} */
  247.         @Override
  248.         public String getName() {
  249.             return name;
  250.         }

  251.         /** {@inheritDoc} */
  252.         @Override
  253.         public T[] getAdditionalState(final FieldSpacecraftState<T> state) {

  254.             // extract the part of the interpolated array corresponding to the additional state
  255.             return getInterpolatedState(state.getDate()).getSecondaryState(index + 1);

  256.         }

  257.     }

  258.     /** {@inheritDoc} */
  259.     @Override
  260.     protected List<ParameterDriver> getParametersDrivers() {
  261.         // Integrated Ephemeris propagation model does not have parameter drivers.
  262.         return Collections.emptyList();
  263.     }

  264. }