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.semianalytical.dsst.forces;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.util.MathArrays;
22  import org.orekit.attitudes.AttitudeProvider;
23  import org.orekit.propagation.FieldSpacecraftState;
24  import org.orekit.propagation.PropagationType;
25  import org.orekit.propagation.SpacecraftState;
26  import org.orekit.propagation.events.EventDetector;
27  import org.orekit.propagation.events.EventDetectorsProvider;
28  import org.orekit.propagation.events.FieldEventDetector;
29  import org.orekit.propagation.integration.AbstractGradientConverter;
30  import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
31  import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
32  import org.orekit.time.AbsoluteDate;
33  import org.orekit.time.FieldAbsoluteDate;
34  import org.orekit.utils.ParameterDriver;
35  import org.orekit.utils.ParameterDriversProvider;
36  import org.orekit.utils.TimeSpanMap.Span;
37  
38  import java.util.List;
39  import java.util.stream.Stream;
40  
41  /** This interface represents a force modifying spacecraft motion for a {@link
42   *  org.orekit.propagation.semianalytical.dsst.DSSTPropagator DSSTPropagator}.
43   *  <p>
44   *  Objects implementing this interface are intended to be added to a {@link
45   *  org.orekit.propagation.semianalytical.dsst.DSSTPropagator DSST propagator}
46   *  before the propagation is started.
47   *  </p>
48   *  <p>
49   *  The propagator will call at the very beginning of a propagation the {@link
50   *  #initializeShortPeriodTerms(AuxiliaryElements, PropagationType, double[])} method allowing
51   *  preliminary computation such as truncation if needed.
52   *  </p>
53   *  <p>
54   *  Then the propagator will call at each step:
55   *  <ol>
56   *  <li>the {@link #getMeanElementRate(SpacecraftState, AuxiliaryElements, double[])} method.
57   *  The force model instance will extract all the state data needed to compute
58   *  the mean element rates that contribute to the mean state derivative.</li>
59   *  <li>the {@link #updateShortPeriodTerms(double[], SpacecraftState...)} method,
60   *  if osculating parameters are desired, on a sample of points within the
61   *  last step.</li>
62   *  </ol>
63   *
64   * @author Romain Di Constanzo
65   * @author Pascal Parraud
66   */
67  public interface DSSTForceModel extends ParameterDriversProvider, EventDetectorsProvider {
68  
69      /**
70       * Initialize the force model at the start of propagation.
71       * <p> The default implementation of this method does nothing.</p>
72       *
73       * @param initialState spacecraft state at the start of propagation.
74       * @param target       date of propagation. Not equal to {@code initialState.getDate()}.
75       * @since 11.0
76       */
77      default void init(SpacecraftState initialState, AbsoluteDate target) {
78      }
79  
80      /**
81       * Initialize the force model at the start of propagation.
82       * <p> The default implementation of this method does nothing.</p>
83       *
84       * @param initialState spacecraft state at the start of propagation.
85       * @param target       date of propagation. Not equal to {@code initialState.getDate()}.
86       * @param <T> type of the elements
87       * @since 11.1
88       */
89      default <T extends CalculusFieldElement<T>> void init(FieldSpacecraftState<T> initialState, FieldAbsoluteDate<T> target) {
90          init(initialState.toSpacecraftState(), target.toAbsoluteDate());
91      }
92  
93      /** {@inheritDoc}.*/
94      @Override
95      default Stream<EventDetector> getEventDetectors() {
96          return getEventDetectors(getParametersDrivers());
97      }
98  
99      /** {@inheritDoc}.*/
100     @Override
101     default <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventDetectors(Field<T> field) {
102         return getFieldEventDetectors(field, getParametersDrivers());
103     }
104 
105     /** Performs initialization prior to propagation for the current force model.
106      *  <p>
107      *  This method aims at being called at the very beginning of a propagation.
108      *  </p>
109      *  @param auxiliaryElements auxiliary elements related to the current orbit
110      *  @param type type of the elements used during the propagation
111      *  @param parameters values of the force model parameters for specific date
112      *  (1 value only per parameter driver) obtained for example by calling
113      *  {@link #getParameters(AbsoluteDate)} on force model.
114      *  @return a list of objects that will hold short period terms (the objects
115      *  are also retained by the force model, which will update them during propagation)
116      */
117     List<ShortPeriodTerms> initializeShortPeriodTerms(AuxiliaryElements auxiliaryElements,
118                                                       PropagationType type, double[] parameters);
119 
120     /** Performs initialization prior to propagation for the current force model.
121      *  <p>
122      *  This method aims at being called at the very beginning of a propagation.
123      *  </p>
124      *  @param <T> type of the elements
125      *  @param auxiliaryElements auxiliary elements related to the current orbit
126      *  @param type type of the elements used during the propagation
127      *  @param parameters values of the force model parameters for specific date
128      *  (1 value only per parameter driver) obtained for example by calling
129      *  {@link #getParameters(AbsoluteDate)} on force model or
130      *  {@link AbstractGradientConverter#getParametersAtStateDate(FieldSpacecraftState, ParameterDriversProvider)}
131      *  on gradient converter.
132      *  @return a list of objects that will hold short period terms (the objects
133      *  are also retained by the force model, which will update them during propagation)
134      */
135     <T extends CalculusFieldElement<T>> List<FieldShortPeriodTerms<T>> initializeShortPeriodTerms(FieldAuxiliaryElements<T> auxiliaryElements,
136                                                                                                   PropagationType type, T[] parameters);
137 
138     /** Extract the proper parameter drivers' values from the array in input of the
139      * {@link #updateShortPeriodTerms(double[], SpacecraftState...) updateShortPeriodTerms} method.
140      *  Parameters are filtered given an input date.
141      * @param parameters the input parameters array containing all span values of all drivers
142      * from which the parameter values at date date wants to be extracted
143      * @param date the date
144      * @return the parameters given the date
145      */
146     default double[] extractParameters(final double[] parameters, final AbsoluteDate date) {
147 
148         // Find out the indexes of the parameters in the whole array of parameters
149         final List<ParameterDriver> allParameters = getParametersDrivers();
150         final double[] outParameters = new double[allParameters.size()];
151         int index = 0;
152         int paramIndex = 0;
153         for (final ParameterDriver driver : allParameters) {
154             final String driverNameforDate = driver.getNameSpan(date);
155             // Loop on the spans
156             for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
157                 // Add all the parameter drivers of the span
158                 if (span.getData().equals(driverNameforDate)) {
159                     outParameters[index++] = parameters[paramIndex];
160                 }
161                 paramIndex++;
162             }
163         }
164         return outParameters;
165     }
166 
167     /** Extract the proper parameter drivers' values from the array in input of the
168      * {@link #updateShortPeriodTerms(CalculusFieldElement[], FieldSpacecraftState...)
169      * updateShortPeriodTerms} method. Parameters are filtered given an input date.
170      * @param parameters the input parameters array containing all span values of all drivers
171      * from which the parameter values at date date wants to be extracted
172      * @param date the date
173      * @param <T> extends CalculusFieldElement
174      * @return the parameters given the date
175      */
176     default <T extends CalculusFieldElement<T>> T[] extractParameters(final T[] parameters,
177                                                                       final FieldAbsoluteDate<T> date) {
178 
179         // Find out the indexes of the parameters in the whole array of parameters
180         final List<ParameterDriver> allParameters = getParametersDrivers();
181         final T[] outParameters = MathArrays.buildArray(date.getField(), allParameters.size());
182         int index = 0;
183         int paramIndex = 0;
184         for (final ParameterDriver driver : allParameters) {
185             final String driverNameforDate = driver.getNameSpan(date.toAbsoluteDate());
186             // Loop on the spans
187             for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
188                 // Add all the parameter drivers of the span
189                 if (span.getData().equals(driverNameforDate)) {
190                     outParameters[index++] = parameters[paramIndex];
191                 }
192                 ++paramIndex;
193             }
194         }
195         return outParameters;
196     }
197 
198 
199     /** Computes the mean equinoctial elements rates da<sub>i</sub> / dt.
200      *
201      *  @param state current state information: date, kinematics, attitude
202      *  @param auxiliaryElements auxiliary elements related to the current orbit
203      *  @param parameters values of the force model parameters at state date (only 1 span for
204      *  each parameter driver) obtained for example by calling {@link #getParameters(AbsoluteDate)}
205      *  on force model.
206      *  @return the mean element rates dai/dt
207      */
208     double[] getMeanElementRate(SpacecraftState state,
209                                 AuxiliaryElements auxiliaryElements, double[] parameters);
210 
211     /** Computes the mean equinoctial elements rates da<sub>i</sub> / dt.
212      *
213      *  @param <T> type of the elements
214      *  @param state current state information: date, kinematics, attitude
215      *  @param auxiliaryElements auxiliary elements related to the current orbit
216      *  @param parameters values of the force model parameters at state date (only 1 span for
217      *  each parameter driver) obtained for example by calling {@link #getParameters(Field, FieldAbsoluteDate)}
218      *  on force model  or
219      *  {@link AbstractGradientConverter#getParametersAtStateDate(FieldSpacecraftState, ParameterDriversProvider)}
220      *  on gradient converter.
221      *  @return the mean element rates dai/dt
222      */
223     <T extends CalculusFieldElement<T>> T[] getMeanElementRate(FieldSpacecraftState<T> state,
224                                                                FieldAuxiliaryElements<T> auxiliaryElements, T[] parameters);
225 
226     /** Register an attitude provider.
227      * <p>
228      * Register an attitude provider that can be used by the force model.
229      * </p>
230      * @param provider the {@link AttitudeProvider}
231      */
232     void registerAttitudeProvider(AttitudeProvider provider);
233 
234     /** Update the short period terms.
235      * <p>
236      * The {@link ShortPeriodTerms short period terms} that will be updated
237      * are the ones that were returned during the call to {@link
238      * #initializeShortPeriodTerms(AuxiliaryElements, PropagationType, double[])}.
239      * </p>
240      * @param parameters values of the force model parameters (all span values for each parameters)
241      * obtained for example by calling
242      * {@link #getParametersAllValues()}
243      * on force model. The extract parameter method {@link #extractParameters(double[], AbsoluteDate)} is called in
244      * the method to select the right parameter corresponding to the mean state date.
245      * @param meanStates mean states information: date, kinematics, attitude
246      */
247     void updateShortPeriodTerms(double[] parameters, SpacecraftState... meanStates);
248 
249     /** Update the short period terms.
250      * <p>
251      * The {@link ShortPeriodTerms short period terms} that will be updated
252      * are the ones that were returned during the call to {@link
253      * #initializeShortPeriodTerms(AuxiliaryElements, PropagationType, double[])}.
254      * </p>
255      * @param <T> type of the elements
256      * @param parameters values of the force model parameters (all span values for each parameters)
257      * obtained for example by calling {@link #getParametersAllValues(Field)} on force model or
258      *  {@link AbstractGradientConverter#getParameters(FieldSpacecraftState, ParameterDriversProvider)}
259      *  on gradient converter. The extract parameter method
260      *  {@link #extractParameters(CalculusFieldElement[], FieldAbsoluteDate)} is called in
261      * the method to select the right parameter.
262      * @param meanStates mean states information: date, kinematics, attitude
263      */
264     @SuppressWarnings("unchecked")
265     <T extends CalculusFieldElement<T>> void updateShortPeriodTerms(T[] parameters, FieldSpacecraftState<T>... meanStates);
266 
267 }