1   /* Copyright 2002-2019 CS Systèmes d'Information
2    * Licensed to CS Systèmes d'Information (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.forces;
18  
19  import java.util.stream.Stream;
20  
21  import org.hipparchus.Field;
22  import org.hipparchus.RealFieldElement;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.hipparchus.geometry.euclidean.threed.Vector3D;
25  import org.hipparchus.util.MathArrays;
26  import org.orekit.propagation.FieldSpacecraftState;
27  import org.orekit.propagation.SpacecraftState;
28  import org.orekit.propagation.events.EventDetector;
29  import org.orekit.propagation.events.FieldEventDetector;
30  import org.orekit.propagation.numerical.FieldTimeDerivativesEquations;
31  import org.orekit.propagation.numerical.TimeDerivativesEquations;
32  import org.orekit.time.AbsoluteDate;
33  import org.orekit.utils.ParameterDriver;
34  
35  /** This interface represents a force modifying spacecraft motion.
36   *
37   * <p>
38   * Objects implementing this interface are intended to be added to a
39   * {@link org.orekit.propagation.numerical.NumericalPropagator numerical propagator}
40   * before the propagation is started.
41   *
42   * <p>
43   * The propagator will call at each step the {@link #addContribution(SpacecraftState,
44   * TimeDerivativesEquations)} method. The force model instance will extract all the
45   * state data it needs (date, position, velocity, frame, attitude, mass) from the first
46   * parameter. From these state data, it will compute the perturbing acceleration. It
47   * will then add this acceleration to the second parameter which will take thins
48   * contribution into account and will use the Gauss equations to evaluate its impact
49   * on the global state derivative.
50   * </p>
51   * <p>
52   * Force models which create discontinuous acceleration patterns (typically for maneuvers
53   * start/stop or solar eclipses entry/exit) must provide one or more {@link
54   * org.orekit.propagation.events.EventDetector events detectors} to the
55   * propagator thanks to their {@link #getEventsDetectors()} method. This method
56   * is called once just before propagation starts. The events states will be checked by
57   * the propagator to ensure accurate propagation and proper events handling.
58   * </p>
59   *
60   * @author Mathieu Rom&eacute;ro
61   * @author Luc Maisonobe
62   * @author V&eacute;ronique Pommier-Maurussane
63   */
64  public interface ForceModel {
65  
66      /**
67       * Initialize the force model at the start of propagation. This method will be called
68       * before any calls to {@link #addContribution(SpacecraftState, TimeDerivativesEquations)},
69       * {@link #addContribution(FieldSpacecraftState, FieldTimeDerivativesEquations)},
70       * {@link #acceleration(SpacecraftState, double[])} or {@link #acceleration(FieldSpacecraftState, RealFieldElement[])}
71       *
72       * <p> The default implementation of this method does nothing.</p>
73       *
74       * @param initialState spacecraft state at the start of propagation.
75       * @param target       date of propagation. Not equal to {@code initialState.getDate()}.
76       */
77      default void init(SpacecraftState initialState, AbsoluteDate target) {
78      }
79  
80      /** Compute the contribution of the force model to the perturbing
81       * acceleration.
82       * <p>
83       * The default implementation simply adds the {@link #acceleration(SpacecraftState, double[]) acceleration}
84       * as a non-Keplerian acceleration.
85       * </p>
86       * @param s current state information: date, kinematics, attitude
87       * @param adder object where the contribution should be added
88       */
89      default void addContribution(SpacecraftState s, TimeDerivativesEquations adder) {
90          adder.addNonKeplerianAcceleration(acceleration(s, getParameters()));
91      }
92  
93      /** Compute the contribution of the force model to the perturbing
94       * acceleration.
95       * @param s current state information: date, kinematics, attitude
96       * @param adder object where the contribution should be added
97       * @param <T> type of the elements
98       */
99      default <T extends RealFieldElement<T>> void addContribution(FieldSpacecraftState<T> s, FieldTimeDerivativesEquations<T> adder) {
100         adder.addNonKeplerianAcceleration(acceleration(s, getParameters(s.getDate().getField())));
101     }
102 
103     /** Get force model parameters.
104      * @return force model parameters
105      * @since 9.0
106      */
107     default double[] getParameters() {
108         final ParameterDriver[] drivers = getParametersDrivers();
109         final double[] parameters = new double[drivers.length];
110         for (int i = 0; i < drivers.length; ++i) {
111             parameters[i] = drivers[i].getValue();
112         }
113         return parameters;
114     }
115 
116     /** Get force model parameters.
117      * @param field field to which the elements belong
118      * @param <T> type of the elements
119      * @return force model parameters
120      * @since 9.0
121      */
122     default <T extends RealFieldElement<T>> T[] getParameters(final Field<T> field) {
123         final ParameterDriver[] drivers = getParametersDrivers();
124         final T[] parameters = MathArrays.buildArray(field, drivers.length);
125         for (int i = 0; i < drivers.length; ++i) {
126             parameters[i] = field.getZero().add(drivers[i].getValue());
127         }
128         return parameters;
129     }
130 
131     /** Check if force models depends on position only.
132      * @return true if force model depends on position only, false
133      * if it depends on velocity, either directly or due to a dependency
134      * on attitude
135      * @since 9.0
136      */
137     boolean dependsOnPositionOnly();
138 
139     /** Compute acceleration.
140      * @param s current state information: date, kinematics, attitude
141      * @param parameters values of the force model parameters
142      * @return acceleration in same frame as state
143           * @since 9.0
144      */
145     Vector3D acceleration(SpacecraftState s, double[] parameters);
146 
147     /** Compute acceleration.
148      * @param s current state information: date, kinematics, attitude
149      * @param parameters values of the force model parameters
150      * @return acceleration in same frame as state
151      * @param <T> type of the elements
152           * @since 9.0
153      */
154     <T extends RealFieldElement<T>> FieldVector3D<T> acceleration(FieldSpacecraftState<T> s, T[] parameters);
155 
156     /** Get the discrete events related to the model.
157      * @return stream of events detectors
158      */
159     Stream<EventDetector> getEventsDetectors();
160 
161     /** Get the discrete events related to the model.
162      * @param field field to which the state belongs
163      * @param <T> extends RealFieldElement<T>
164      * @return stream of events detectors
165      */
166     <T extends RealFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(Field<T> field);
167 
168     /** Get the drivers for force model parameters.
169      * @return drivers for force model parameters
170      * @since 8.0
171      */
172     ParameterDriver[] getParametersDrivers();
173 
174     /** Get parameter value from its name.
175      * @param name parameter name
176      * @return parameter value
177           * @since 8.0
178      */
179     ParameterDriver getParameterDriver(String name);
180 
181     /** Check if a parameter is supported.
182      * <p>Supported parameters are those listed by {@link #getParametersDrivers()}.</p>
183      * @param name parameter name to check
184      * @return true if the parameter is supported
185      * @see #getParametersDrivers()
186      */
187     boolean isSupported(String name);
188 
189 }