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éro
61 * @author Luc Maisonobe
62 * @author Vé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 }