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