1   /* Copyright 2002-2025 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  
19  import java.util.Collection;
20  import java.util.List;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.orekit.attitudes.AttitudeProvider;
25  import org.orekit.frames.Frame;
26  import org.orekit.propagation.events.FieldEventDetector;
27  import org.orekit.propagation.sampling.FieldOrekitFixedStepHandler;
28  import org.orekit.propagation.sampling.FieldOrekitStepHandler;
29  import org.orekit.propagation.sampling.FieldStepHandlerMultiplexer;
30  import org.orekit.time.FieldAbsoluteDate;
31  import org.orekit.utils.FieldPVCoordinatesProvider;
32  import org.orekit.utils.TimeStampedFieldPVCoordinates;
33  
34  /** This interface provides a way to propagate an orbit at any time.
35   *
36   * <p>This interface is the top-level abstraction for orbit propagation.
37   * It only allows propagation to a predefined date.
38   * It is implemented by analytical models which have no time limit,
39   * by orbit readers based on external data files, by numerical integrators
40   * using rich force models and by continuous models built after numerical
41   * integration has been completed and dense output data as been
42   * gathered.</p>
43   * @param <T> the type of the field elements
44  
45   * @author Luc Maisonobe
46   * @author V&eacute;ronique Pommier-Maurussane
47   *
48   */
49  
50  public interface FieldPropagator<T extends CalculusFieldElement<T>> extends FieldPVCoordinatesProvider<T> {
51  
52      /** Default mass. */
53      double DEFAULT_MASS = 1000.0;
54  
55      /** Get the multiplexer holding all step handlers.
56       * @return multiplexer holding all step handlers
57       * @since 11.0
58       */
59      FieldStepHandlerMultiplexer<T> getMultiplexer();
60  
61      /** Remove all step handlers.
62       * <p>This convenience method is equivalent to call {@code getMultiplexer().clear()}</p>
63       * @see #getMultiplexer()
64       * @see FieldStepHandlerMultiplexer#clear()
65       * @since 11.0
66       */
67      default void clearStepHandlers() {
68          getMultiplexer().clear();
69      }
70  
71      /** Set a single handler for fixed stepsizes.
72       * <p>This convenience method is equivalent to call {@code getMultiplexer().clear()}
73       * followed by {@code getMultiplexer().add(h, handler)}</p>
74       * @param h fixed stepsize (s)
75       * @param handler handler called at the end of each finalized step
76       * @see #getMultiplexer()
77       * @see FieldStepHandlerMultiplexer#add(CalculusFieldElement, FieldOrekitFixedStepHandler)
78       * @since 11.0
79       */
80      default void setStepHandler(final T h, final FieldOrekitFixedStepHandler<T> handler) {
81          getMultiplexer().clear();
82          getMultiplexer().add(h, handler);
83      }
84  
85      /** Set a single handler for variable stepsizes.
86       * <p>This convenience method is equivalent to call {@code getMultiplexer().clear()}
87       * followed by {@code getMultiplexer().add(handler)}</p>
88       * @param handler handler called at the end of each finalized step
89       * @see #getMultiplexer()
90       * @see FieldStepHandlerMultiplexer#add(FieldOrekitStepHandler)
91       * @since 11.0
92       */
93      default void setStepHandler(final FieldOrekitStepHandler<T> handler) {
94          getMultiplexer().clear();
95          getMultiplexer().add(handler);
96      }
97  
98      /**
99       * Set up an ephemeris generator that will monitor the propagation for building
100      * an ephemeris from it once completed.
101      *
102      * <p>
103      * This generator can be used when the user needs fast random access to the orbit
104      * state at any time between the initial and target times. A typical example is the
105      * implementation of search and iterative algorithms that may navigate forward and
106      * backward inside the propagation range before finding their result even if the
107      * propagator used is integration-based and only goes from one initial time to one
108      * target time.
109      * </p>
110      * <p>
111      * Beware that when used with integration-based propagators, the generator will
112      * store <strong>all</strong> intermediate results. It is therefore memory intensive
113      * for long integration-based ranges and high precision/short time steps. When
114      * used with analytical propagators, the generator only stores start/stop time
115      * and a reference to the analytical propagator itself to call it back as needed,
116      * so it is less memory intensive.
117      * </p>
118      * <p>
119      * The returned ephemeris generator will be initially empty, it will be filled
120      * with propagation data when a subsequent call to either {@link #propagate(FieldAbsoluteDate)
121      * propagate(target)} or {@link #propagate(FieldAbsoluteDate, FieldAbsoluteDate)
122      * propagate(start, target)} is called. The proper way to use this method is
123      * therefore to do:
124      * </p>
125      * <pre>
126      *   FieldEphemerisGenerator&lt;T&gt; generator = propagator.getEphemerisGenerator();
127      *   propagator.propagate(target);
128      *   FieldBoundedPropagator&lt;T&gt; ephemeris = generator.getGeneratedEphemeris();
129      * </pre>
130      * @return ephemeris generator
131      */
132     FieldEphemerisGenerator<T> getEphemerisGenerator();
133 
134     /** Get the propagator initial state.
135      * @return initial state
136      */
137     FieldSpacecraftState<T> getInitialState();
138 
139     /** Reset the propagator initial state.
140      * @param state new initial state to consider
141      */
142     void resetInitialState(FieldSpacecraftState<T> state);
143 
144     /** Add a set of user-specified data to be computed along with the orbit propagation.
145      * @param additionalDataProvider provider for additional data
146      */
147     void addAdditionalDataProvider(FieldAdditionalDataProvider<?, T> additionalDataProvider);
148 
149     /** Get an unmodifiable list of providers for additional data.
150      * @return providers for the additional states
151      */
152     List<FieldAdditionalDataProvider<?, T>> getAdditionalDataProviders();
153 
154     /** Check if an additional data is managed.
155      * <p>
156      * Managed data are the ones for which the propagators know how to compute
157      * its evolution. They correspond to additional data for which an
158      * {@link FieldAdditionalDataProvider additional data provider} has been registered
159      * by calling the {@link #addAdditionalDataProvider(FieldAdditionalDataProvider)
160      * addAdditionalDataProvider} method. If the propagator is an {@link
161      * org.orekit.propagation.integration.FieldAbstractIntegratedPropagator integrator-based
162      * propagator}, the states for which a set of {@link
163      * org.orekit.propagation.integration.FieldAdditionalDerivativesProvider additional derivatives
164      * provider} has been registered by calling the {@link
165      * org.orekit.propagation.integration.FieldAbstractIntegratedPropagator#addAdditionalDerivativesProvider(
166      * org.orekit.propagation.integration.FieldAdditionalDerivativesProvider) addAdditionalDerivativesProvider}
167      * method are also counted as managed additional states.
168      * </p>
169      * <p>
170      * Additional data that are present in the {@link #getInitialState() initial state}
171      * but have no evolution method registered are <em>not</em> considered as managed data.
172      * These unmanaged additional data are not lost during propagation, though. Their
173      * value are piecewise constant between state resets that may change them if some
174      * event handler {@link
175      * org.orekit.propagation.events.handlers.FieldEventHandler#resetState(FieldEventDetector,
176      * FieldSpacecraftState) resetState} method is called at an event occurrence and happens
177      * to change the unmanaged additional data.
178      * </p>
179      * @param name name of the additional data
180      * @return true if the additional data is managed
181      */
182     boolean isAdditionalDataManaged(String name);
183 
184     /** Get all the names of all managed data.
185      * @return names of all managed data
186      */
187     String[] getManagedAdditionalData();
188 
189     /** Add an event detector.
190      * @param detector event detector to add
191      * @see #clearEventsDetectors()
192      * @see #getEventDetectors()
193      * @param <D> class type for the generic version
194      */
195     <D extends FieldEventDetector<T>> void addEventDetector(D detector);
196 
197     /** Get all the events detectors that have been added.
198      * @return an unmodifiable collection of the added detectors
199      * @see #addEventDetector(FieldEventDetector)
200      * @see #clearEventsDetectors()
201      */
202     Collection<FieldEventDetector<T>> getEventDetectors();
203 
204     /** Remove all events detectors.
205      * @see #addEventDetector(FieldEventDetector)
206      * @see #getEventDetectors()
207      */
208     void clearEventsDetectors();
209 
210     /** Get attitude provider.
211      * @return attitude provider
212      */
213     AttitudeProvider getAttitudeProvider();
214 
215     /** Set attitude provider.
216      * @param attitudeProvider attitude provider
217      */
218     void setAttitudeProvider(AttitudeProvider attitudeProvider);
219 
220     /** Get the frame in which the orbit is propagated.
221      * <p>
222      * The propagation frame is the definition frame of the initial
223      * state, so this method should be called after this state has
224      * been set, otherwise it may return null.
225      * </p>
226      * @return frame in which the orbit is propagated
227      * @see #resetInitialState(FieldSpacecraftState)
228      */
229     Frame getFrame();
230 
231     /** Propagate towards a target date.
232      * <p>Simple propagators use only the target date as the specification for
233      * computing the propagated state. More feature rich propagators can consider
234      * other information and provide different operating modes or G-stop
235      * facilities to stop at pinpointed events occurrences. In these cases, the
236      * target date is only a hint, not a mandatory objective.</p>
237      * @param target target date towards which orbit state should be propagated
238      * @return propagated state
239      */
240     FieldSpacecraftState<T> propagate(FieldAbsoluteDate<T> target);
241 
242     /** Propagate from a start date towards a target date.
243      * <p>Those propagators use a start date and a target date to
244      * compute the propagated state. For propagators using event detection mechanism,
245      * if the provided start date is different from the initial state date, a first,
246      * simple propagation is performed, without processing any event computation.
247      * Then complete propagation is performed from start date to target date.</p>
248      * @param start start date from which orbit state should be propagated
249      * @param target target date to which orbit state should be propagated
250      * @return propagated state
251      */
252     FieldSpacecraftState<T> propagate(FieldAbsoluteDate<T> start, FieldAbsoluteDate<T> target);
253 
254     /** {@inheritDoc} */
255     @Override
256     default TimeStampedFieldPVCoordinates<T> getPVCoordinates(FieldAbsoluteDate<T> date, Frame frame) {
257         return propagate(date).getPVCoordinates(frame);
258     }
259 
260     /** {@inheritDoc} */
261     @Override
262     default FieldVector3D<T> getPosition(final FieldAbsoluteDate<T> date, final Frame frame) {
263         return propagate(date).getPosition(frame);
264     }
265 
266 }