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  
18  package org.orekit.forces.maneuvers.propulsion;
19  
20  import org.hipparchus.CalculusFieldElement;
21  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.orekit.forces.maneuvers.Control3DVectorCostType;
24  import org.orekit.propagation.FieldSpacecraftState;
25  import org.orekit.propagation.SpacecraftState;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.utils.Constants;
28  
29  /** This abstract class simply serve as a container for a constant thrust maneuver.
30   * It re-writes all spacecraft dependent methods from {@link ThrustPropulsionModel}
31   * and removes their dependencies to current spacecraft state.
32   * Indeed since the thrust is constant (i.e. not variable during the maneuver), most of the
33   * calculated parameters (thrust vector, flow rate etc.) do not depend on current spacecraft state.
34   * @author Maxime Journot
35   * @since 10.2
36   */
37  public abstract class AbstractConstantThrustPropulsionModel implements ThrustPropulsionModel {
38  
39      /** Default control vector cost type. */
40      static final Control3DVectorCostType DEFAULT_CONTROL_3D_VECTOR_COST_TYPE = Control3DVectorCostType.TWO_NORM;
41  
42      /** Initial thrust vector (N) in S/C frame, when building the object. */
43      private final Vector3D initialThrustVector;
44  
45      /** Initial flow rate (kg/s), when building the object. */
46      private final double initialFlowRate;
47  
48      /** Type of norm linking thrust vector to mass flow rate. */
49      private final Control3DVectorCostType control3DVectorCostType;
50  
51      /** User-defined name of the maneuver.
52       * This String attribute is empty by default.
53       * It is added as a prefix to the parameter drivers of the maneuver.
54       * The purpose is to differentiate between drivers in the case where several maneuvers
55       * were added to a propagator force model.
56       * Additionally, the user can retrieve the whole maneuver by looping on the force models of a propagator,
57       * scanning for its name.
58       * @since 9.2
59       */
60      private final String name;
61  
62      /** Generic constructor.
63       * @param thrust initial thrust value (N)
64       * @param isp initial isp value (s)
65       * @param direction initial thrust direction in S/C frame
66       * @param control3DVectorCostType control cost type
67       * @param name name of the maneuver
68       * @since 12.0
69       */
70      protected AbstractConstantThrustPropulsionModel(final double thrust, final double isp, final Vector3D direction,
71                                                      final Control3DVectorCostType control3DVectorCostType,
72                                                      final String name) {
73          this.name = name;
74          this.initialThrustVector = direction.normalize().scalarMultiply(thrust);
75          this.control3DVectorCostType = control3DVectorCostType;
76          this.initialFlowRate = -control3DVectorCostType.evaluate(initialThrustVector) / ThrustPropulsionModel.getExhaustVelocity(isp);
77      }
78  
79      /** Constructor with default control cost type.
80       * @param thrust initial thrust value (N)
81       * @param isp initial isp value (s)
82       * @param direction initial thrust direction in S/C frame
83       * @param name name of the maneuver
84       */
85      protected AbstractConstantThrustPropulsionModel(final double thrust, final double isp, final Vector3D direction,
86                                                      final String name) {
87          this(thrust, isp, direction, DEFAULT_CONTROL_3D_VECTOR_COST_TYPE, name);
88      }
89  
90      /** Get the initial thrust vector.
91       * @return the initial thrust vector
92       */
93      protected Vector3D getInitialThrustVector() {
94          return initialThrustVector;
95      }
96  
97      /** Get the initial flow rate.
98       * @return the initial flow rate
99       */
100     protected double getInitialFlowRate() {
101         return initialFlowRate;
102     }
103 
104     /** {@inheritDoc} */
105     @Override
106     public String getName() {
107         return name;
108     }
109 
110     /** {@inheritDoc} */
111     @Override
112     public Control3DVectorCostType getControl3DVectorCostType() {
113         return control3DVectorCostType;
114     }
115 
116     /** Get the specific impulse.
117      * @return specific impulse (s), will throw exception if
118      * used on PDriver having several driven values, because
119      * in this case a date is needed.
120      */
121     public double getIsp() {
122         final double flowRate = getFlowRate();
123         return -control3DVectorCostType.evaluate(getThrustVector()) / (Constants.G0_STANDARD_GRAVITY * flowRate);
124     }
125 
126     /** Get the specific impulse at given date.
127      * @param date date at which the Isp wants to be known
128      * @return specific impulse (s).
129      */
130     public double getIsp(final AbsoluteDate date) {
131         final double flowRate = getFlowRate(date);
132         return -control3DVectorCostType.evaluate(getThrustVector(date)) / (Constants.G0_STANDARD_GRAVITY * flowRate);
133     }
134 
135     /** Get the thrust direction in S/C frame.
136      * @param date date at which the direction wants to be known
137      * @return the thrust direction in S/C frame
138      */
139     public Vector3D getDirection(final AbsoluteDate date) {
140         return getThrustVector(date).normalize();
141     }
142 
143     /** Get the thrust direction in S/C frame.
144      * @return the thrust direction in S/C frame,  will throw exception if
145      * used on PDriver having several driven values, because
146      * in this case a date is needed.
147      */
148     public Vector3D getDirection() {
149         return getThrustVector().normalize();
150     }
151 
152     /** Get the thrust magnitude (N).
153      * @return the thrust value (N), will throw
154      * an exception if called of a driver having several
155      * values driven
156      */
157     public double getThrustMagnitude() {
158         return getThrustVector().getNorm();
159     }
160 
161     /** Get the thrust magnitude (N) at given date.
162      * @param date date at which the thrust vector wants to be known,
163      * often the date parameter will not be important and can be whatever
164      * if the thrust parameter driver as only value estimated over the all
165      * orbit determination interval
166      * @return the thrust value (N)
167      */
168     public double getThrustMagnitude(final AbsoluteDate date) {
169         return getThrustVector(date).getNorm();
170     }
171 
172     /** {@inheritDoc}
173      * Here the thrust vector do not depend on current S/C state.
174      */
175     @Override
176     public Vector3D getThrustVector(final SpacecraftState s) {
177         // Call the abstract function that do not depend on current S/C state
178         return getThrustVector(s.getDate());
179     }
180 
181     /** {@inheritDoc}
182      * Here the flow rate do not depend on current S/C state
183      */
184     @Override
185     public double getFlowRate(final SpacecraftState s) {
186         // Call the abstract function that do not depend on current S/C state
187         return getFlowRate(s.getDate());
188     }
189 
190     /** {@inheritDoc}
191      * Here the thrust vector do not depend on current S/C state.
192      */
193     @Override
194     public Vector3D getThrustVector(final SpacecraftState s, final double[] parameters) {
195         // Call the abstract function that do not depend on current S/C state
196         return getThrustVector(parameters);
197     }
198 
199     /** {@inheritDoc}
200      * Here the flow rate do not depend on current S/C state
201      */
202     public double getFlowRate(final SpacecraftState s, final double[] parameters) {
203         // Call the abstract function that do not depend on current S/C state
204         return getFlowRate(parameters);
205     }
206 
207     /** {@inheritDoc}
208      * Here the thrust vector do not depend on current S/C state.
209      */
210     public <T extends CalculusFieldElement<T>> FieldVector3D<T> getThrustVector(final FieldSpacecraftState<T> s,
211                                                                             final T[] parameters) {
212         // Call the abstract function that do not depend on current S/C state
213         return getThrustVector(parameters);
214     }
215 
216     /** {@inheritDoc}
217      * Here the flow rate do not depend on current S/C state
218      */
219     public <T extends CalculusFieldElement<T>> T getFlowRate(final FieldSpacecraftState<T> s, final T[] parameters) {
220         // Call the abstract function that do not depend on current S/C state
221         return getFlowRate(parameters);
222     }
223 
224     /** Get the thrust vector in spacecraft frame (N).
225      * Here it does not depend on current S/C state.
226      * @return thrust vector in spacecraft frame (N),
227      * will throw an exception if used on driver
228      * containing several value spans
229      */
230     public abstract Vector3D getThrustVector();
231 
232     /** Get the thrust vector in spacecraft frame (N).
233      * Here it does not depend on current S/C state.
234      * @param date date at which the thrust vector wants to be known,
235      * often the date parameter will not be important and can be whatever
236      * if the thrust parameter driver as only value estimated over the all
237      * orbit determination interval
238      * @return thrust vector in spacecraft frame (N)
239      */
240     public abstract Vector3D getThrustVector(AbsoluteDate date);
241 
242     /** Get the flow rate (kg/s).
243      * Here it does not depend on current S/C.
244      * @return flow rate (kg/s)
245      * will throw an exception if used on driver
246      * containing several value spans
247      */
248     public abstract double getFlowRate();
249 
250     /** Get the flow rate (kg/s).
251      * Here it does not depend on current S/C.
252      * @param date date at which the thrust vector wants to be known,
253      * often the date parameter will not be important and can be whatever
254      * if the thrust parameter driver as only value estimated over the all
255      * orbit determination interval
256      * @return flow rate (kg/s)
257      */
258     public abstract double getFlowRate(AbsoluteDate date);
259 
260     /** Get the thrust vector in spacecraft frame (N).
261      * Here it does not depend on current S/C state.
262      * @param parameters propulsion model parameters
263      * @return thrust vector in spacecraft frame (N)
264      */
265     public abstract Vector3D getThrustVector(double[] parameters);
266 
267     /** Get the flow rate (kg/s).
268      * Here it does not depend on current S/C state.
269      * @param parameters propulsion model parameters
270      * @return flow rate (kg/s)
271      */
272     public abstract double getFlowRate(double[] parameters);
273 
274     /** Get the thrust vector in spacecraft frame (N).
275      * Here it does not depend on current S/C state.
276      * @param parameters propulsion model parameters
277      * @param <T> extends CalculusFieldElement&lt;T&gt;
278      * @return thrust vector in spacecraft frame (N)
279      */
280     public abstract <T extends CalculusFieldElement<T>> FieldVector3D<T> getThrustVector(T[] parameters);
281 
282     /** Get the flow rate (kg/s).
283      * Here it does not depend on current S/C state.
284      * @param parameters propulsion model parameters
285      * @param <T> extends CalculusFieldElement&lt;T&gt;
286      * @return flow rate (kg/s)
287      */
288     public abstract <T extends CalculusFieldElement<T>> T getFlowRate(T[] parameters);
289 }