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