FieldAbstractPropagator.java

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

  18. import java.util.ArrayList;
  19. import java.util.Collections;
  20. import java.util.HashMap;
  21. import java.util.LinkedList;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Queue;

  25. import org.hipparchus.CalculusFieldElement;
  26. import org.hipparchus.Field;
  27. import org.orekit.attitudes.AttitudeProvider;
  28. import org.orekit.errors.OrekitException;
  29. import org.orekit.errors.OrekitMessages;
  30. import org.orekit.frames.Frame;
  31. import org.orekit.propagation.sampling.FieldStepHandlerMultiplexer;
  32. import org.orekit.time.FieldAbsoluteDate;
  33. import org.orekit.utils.FieldArrayDictionary;
  34. import org.orekit.utils.FieldTimeSpanMap;

  35. /** Common handling of {@link Propagator} methods for analytical propagators.
  36.  * <p>
  37.  * This abstract class allows to provide easily the full set of {@link Propagator}
  38.  * methods, including all propagation modes support and discrete events support for
  39.  * any simple propagation method.
  40.  * </p>
  41.  * @param <T> the type of the field elements
  42.  * @author Luc Maisonobe
  43.  */
  44. public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>> implements FieldPropagator<T> {

  45.     /** Multiplexer for step handlers. */
  46.     private final FieldStepHandlerMultiplexer<T> multiplexer;

  47.     /** Start date. */
  48.     private FieldAbsoluteDate<T> startDate;

  49.     /** Attitude provider. */
  50.     private AttitudeProvider attitudeProvider;

  51.     /** Additional state providers. */
  52.     private final List<FieldAdditionalStateProvider<T>> additionalStateProviders;

  53.     /** States managed by neither additional equations nor state providers. */
  54.     private final Map<String, FieldTimeSpanMap<T[], T>> unmanagedStates;

  55.     /** Field used.*/
  56.     private final Field<T> field;

  57.     /** Initial state. */
  58.     private FieldSpacecraftState<T> initialState;

  59.     /** Build a new instance.
  60.      * @param field setting the field
  61.      */
  62.     protected FieldAbstractPropagator(final Field<T> field) {
  63.         this.field               = field;
  64.         multiplexer              = new FieldStepHandlerMultiplexer<>();
  65.         additionalStateProviders = new ArrayList<>();
  66.         unmanagedStates          = new HashMap<>();
  67.     }

  68.     /** Set a start date.
  69.      * @param startDate start date
  70.      */
  71.     protected void setStartDate(final FieldAbsoluteDate<T> startDate) {
  72.         this.startDate = startDate;
  73.     }

  74.     /** Get the start date.
  75.      * @return start date
  76.      */
  77.     protected FieldAbsoluteDate<T> getStartDate() {
  78.         return startDate;
  79.     }

  80.     /**  {@inheritDoc} */
  81.     public AttitudeProvider getAttitudeProvider() {
  82.         return attitudeProvider;
  83.     }

  84.     /**  {@inheritDoc} */
  85.     public void setAttitudeProvider(final AttitudeProvider attitudeProvider) {
  86.         this.attitudeProvider = attitudeProvider;
  87.     }

  88.     /** Field getter.
  89.      * @return field used*/
  90.     public Field<T> getField() {
  91.         return field;
  92.     }

  93.     /** {@inheritDoc} */
  94.     public FieldSpacecraftState<T> getInitialState() {
  95.         return initialState;
  96.     }

  97.     /** {@inheritDoc} */
  98.     public Frame getFrame() {
  99.         return initialState.getFrame();
  100.     }

  101.     /** {@inheritDoc} */
  102.     public void resetInitialState(final FieldSpacecraftState<T> state) {
  103.         initialState = state;
  104.         setStartDate(state.getDate());
  105.     }

  106.     /** {@inheritDoc} */
  107.     public FieldStepHandlerMultiplexer<T> getMultiplexer() {
  108.         return multiplexer;
  109.     }

  110.     /** {@inheritDoc} */
  111.     public void addAdditionalStateProvider(final FieldAdditionalStateProvider<T> additionalStateProvider) {

  112.         // check if the name is already used
  113.         if (isAdditionalStateManaged(additionalStateProvider.getName())) {
  114.             // this additional state is already registered, complain
  115.             throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
  116.                                       additionalStateProvider.getName());
  117.         }

  118.         // this is really a new name, add it
  119.         additionalStateProviders.add(additionalStateProvider);

  120.     }

  121.     /** {@inheritDoc} */
  122.     public List<FieldAdditionalStateProvider<T>> getAdditionalStateProviders() {
  123.         return Collections.unmodifiableList(additionalStateProviders);
  124.     }

  125.     /** Update state by adding unmanaged states.
  126.      * @param original original state
  127.      * @return updated state, with unmanaged states included
  128.      * @see #updateAdditionalStates(FieldSpacecraftState)
  129.      */
  130.     protected FieldSpacecraftState<T> updateUnmanagedStates(final FieldSpacecraftState<T> original) {

  131.         // start with original state,
  132.         // which may already contain additional states, for example in interpolated ephemerides
  133.         FieldSpacecraftState<T> updated = original;

  134.         // update the states not managed by providers
  135.         for (final Map.Entry<String, FieldTimeSpanMap<T[], T>> entry : unmanagedStates.entrySet()) {
  136.             updated = updated.addAdditionalState(entry.getKey(),
  137.                                                  entry.getValue().get(original.getDate()));
  138.         }

  139.         return updated;

  140.     }

  141.     /** Update state by adding all additional states.
  142.      * @param original original state
  143.      * @return updated state, with all additional states included
  144.      * @see #addAdditionalStateProvider(FieldAdditionalStateProvider)
  145.      */
  146.     protected FieldSpacecraftState<T> updateAdditionalStates(final FieldSpacecraftState<T> original) {

  147.         // start with original state and unmanaged states
  148.         FieldSpacecraftState<T> updated = updateUnmanagedStates(original);

  149.         // set up queue for providers
  150.         final Queue<FieldAdditionalStateProvider<T>> pending = new LinkedList<>(getAdditionalStateProviders());

  151.         // update the additional states managed by providers, taking care of dependencies
  152.         int yieldCount = 0;
  153.         while (!pending.isEmpty()) {
  154.             final FieldAdditionalStateProvider<T> provider = pending.remove();
  155.             if (provider.yields(updated)) {
  156.                 // this generator has to wait for another one,
  157.                 // we put it again in the pending queue
  158.                 pending.add(provider);
  159.                 if (++yieldCount >= pending.size()) {
  160.                     // all pending providers yielded!, they probably need data not yet initialized
  161.                     // we let the propagation proceed, if these data are really needed right now
  162.                     // an appropriate exception will be triggered when caller tries to access them
  163.                     break;
  164.                 }
  165.             } else {
  166.                 // we can use this provider right now
  167.                 updated    = provider.update(updated);
  168.                 yieldCount = 0;
  169.             }
  170.         }

  171.         return updated;

  172.     }

  173.     /**
  174.      * Initialize the additional state providers at the start of propagation.
  175.      * @param target date of propagation. Not equal to {@code initialState.getDate()}.
  176.      * @since 11.2
  177.      */
  178.     protected void initializeAdditionalStates(final FieldAbsoluteDate<T> target) {
  179.         for (final FieldAdditionalStateProvider<T> provider : additionalStateProviders) {
  180.             provider.init(initialState, target);
  181.         }
  182.     }

  183.     /** {@inheritDoc} */
  184.     public boolean isAdditionalStateManaged(final String name) {
  185.         for (final FieldAdditionalStateProvider<T> provider : additionalStateProviders) {
  186.             if (provider.getName().equals(name)) {
  187.                 return true;
  188.             }
  189.         }
  190.         return false;
  191.     }

  192.     /** {@inheritDoc} */
  193.     public String[] getManagedAdditionalStates() {
  194.         final String[] managed = new String[additionalStateProviders.size()];
  195.         for (int i = 0; i < managed.length; ++i) {
  196.             managed[i] = additionalStateProviders.get(i).getName();
  197.         }
  198.         return managed;
  199.     }

  200.     /** {@inheritDoc} */
  201.     public FieldSpacecraftState<T> propagate(final FieldAbsoluteDate<T> target) {
  202.         if (startDate == null) {
  203.             startDate = getInitialState().getDate();
  204.         }
  205.         return propagate(startDate, target);
  206.     }

  207.     /** Initialize propagation.
  208.      * @since 10.1
  209.      */
  210.     protected void initializePropagation() {

  211.         unmanagedStates.clear();

  212.         if (initialState != null) {
  213.             // there is an initial state
  214.             // (null initial states occur for example in interpolated ephemerides)
  215.             // copy the additional states present in initialState but otherwise not managed
  216.             for (final FieldArrayDictionary<T>.Entry initial : initialState.getAdditionalStatesValues().getData()) {
  217.                 if (!isAdditionalStateManaged(initial.getKey())) {
  218.                     // this additional state is in the initial state, but is unknown to the propagator
  219.                     // we store it in a way event handlers may change it
  220.                     unmanagedStates.put(initial.getKey(),
  221.                                         new FieldTimeSpanMap<>(initial.getValue(),
  222.                                                                initialState.getDate().getField()));
  223.                 }
  224.             }
  225.         }
  226.     }

  227.     /** Notify about a state change.
  228.      * @param state new state
  229.      */
  230.     protected void stateChanged(final FieldSpacecraftState<T> state) {
  231.         final FieldAbsoluteDate<T> date    = state.getDate();
  232.         final boolean              forward = date.durationFrom(getStartDate()).getReal() >= 0.0;
  233.         for (final  FieldArrayDictionary<T>.Entry changed : state.getAdditionalStatesValues().getData()) {
  234.             final FieldTimeSpanMap<T[], T> tsm = unmanagedStates.get(changed.getKey());
  235.             if (tsm != null) {
  236.                 // this is an unmanaged state
  237.                 if (forward) {
  238.                     tsm.addValidAfter(changed.getValue(), date);
  239.                 } else {
  240.                     tsm.addValidBefore(changed.getValue(), date);
  241.                 }
  242.             }
  243.         }
  244.     }

  245. }