1 /* Copyright 2002-2026 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.events;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.orekit.errors.OrekitException;
21 import org.orekit.errors.OrekitMessages;
22 import org.orekit.propagation.FieldSpacecraftState;
23 import org.orekit.propagation.events.functions.EventFunction;
24 import org.orekit.propagation.events.handlers.EventHandler;
25 import org.orekit.propagation.events.handlers.FieldEventHandler;
26 import org.orekit.propagation.events.intervals.FieldAdaptableInterval;
27 import org.orekit.time.FieldAbsoluteDate;
28
29 /** Common parts shared by several events finders.
30 * It should only be implemented by detectors able to accept any handler.
31 * @param <D> type of the detector
32 * @param <T> type of the field element
33 * @see org.orekit.propagation.Propagator#addEventDetector(EventDetector)
34 * @author Luc Maisonobe
35 */
36 public abstract class FieldAbstractDetector<D extends FieldAbstractDetector<D, T>, T extends CalculusFieldElement<T>>
37 implements FieldEventDetector<T> {
38
39 /** Default maximum checking interval (s). */
40 public static final double DEFAULT_MAX_CHECK = FieldEventDetectionSettings.DEFAULT_MAX_CHECK;
41
42 /** Default convergence threshold (s). */
43 public static final double DEFAULT_THRESHOLD = FieldEventDetectionSettings.DEFAULT_THRESHOLD;
44
45 /** Default maximum number of iterations in the event time search. */
46 public static final int DEFAULT_MAX_ITER = FieldEventDetectionSettings.DEFAULT_MAX_ITER;
47
48 /** Detection settings. */
49 private final FieldEventDetectionSettings<T> eventDetectionSettings;
50
51 /** Default handler for event overrides. */
52 private final FieldEventHandler<T> handler;
53
54 /** Propagation direction. */
55 private boolean forward = true;
56
57 /** Event function. */
58 private final EventFunction defaultEventFunction;
59
60 /** Build a new instance with an event function.
61 * @param eventFunction event function
62 * @param detectionSettings event detection settings
63 * @param handler event handler to call at event occurrences
64 * @since 14.0
65 */
66 protected FieldAbstractDetector(final EventFunction eventFunction,
67 final FieldEventDetectionSettings<T> detectionSettings,
68 final FieldEventHandler<T> handler) {
69 checkStrictlyPositive(detectionSettings.getThreshold().getReal());
70 this.eventDetectionSettings = detectionSettings;
71 this.handler = handler;
72 this.defaultEventFunction = eventFunction;
73 }
74
75 /** Build a new instance.
76 * @param detectionSettings event detection settings
77 * @param handler event handler to call at event occurrences
78 * @since 12.2
79 */
80 protected FieldAbstractDetector(final FieldEventDetectionSettings<T> detectionSettings,
81 final FieldEventHandler<T> handler) {
82 checkStrictlyPositive(detectionSettings.getThreshold().getReal());
83 this.eventDetectionSettings = detectionSettings;
84 this.handler = handler;
85 this.defaultEventFunction = EventFunction.of(detectionSettings.getThreshold().getField(), this::g);
86 }
87
88 /**
89 * Check if propagation is forward or not.
90 * @param <W> field type
91 * @param state initial state
92 * @param targetDate target propagation date
93 * @return forward flag
94 * @since 13.0
95 */
96 public static <W extends CalculusFieldElement<W>> boolean checkIfForward(final FieldSpacecraftState<W> state,
97 final FieldAbsoluteDate<W> targetDate) {
98 return targetDate.durationFrom(state.getDate()).getReal() >= 0.0;
99 }
100
101 /** Check value is strictly positive.
102 * @param value value to check
103 * @exception OrekitException if value is not strictly positive
104 * @since 11.2
105 */
106 private void checkStrictlyPositive(final double value) throws OrekitException {
107 if (value <= 0.0) {
108 throw new OrekitException(OrekitMessages.NOT_STRICTLY_POSITIVE, value);
109 }
110 }
111
112 @Override
113 public EventFunction getEventFunction() {
114 return defaultEventFunction;
115 }
116
117 /** {@inheritDoc} */
118 @Override
119 public void init(final FieldSpacecraftState<T> s0, final FieldAbsoluteDate<T> t) {
120 FieldEventDetector.super.init(s0, t);
121 forward = checkIfForward(s0, t);
122 }
123
124 /** {@inheritDoc} */
125 @Override
126 public FieldEventDetectionSettings<T> getDetectionSettings() {
127 return eventDetectionSettings;
128 }
129
130 /**
131 * Set up the maximum checking interval.
132 * <p>
133 * This will override a maximum checking interval if it has been configured previously.
134 * </p>
135 * @param newMaxCheck maximum checking interval (s)
136 * @return a new detector with updated configuration (the instance is not changed)
137 * @since 12.0
138 */
139 public D withMaxCheck(final double newMaxCheck) {
140 return withMaxCheck(FieldAdaptableInterval.of(newMaxCheck));
141 }
142
143 /**
144 * Set up the maximum checking interval.
145 * <p>
146 * This will override a maximum checking interval if it has been configured previously.
147 * </p>
148 * @param newMaxCheck maximum checking interval (s)
149 * @return a new detector with updated configuration (the instance is not changed)
150 * @since 12.0
151 */
152 public D withMaxCheck(final FieldAdaptableInterval<T> newMaxCheck) {
153 return withDetectionSettings(new FieldEventDetectionSettings<>(newMaxCheck, getThreshold(), getMaxIterationCount()));
154 }
155
156 /**
157 * Set up the maximum number of iterations in the event time search.
158 * <p>
159 * This will override a number of iterations if it has been configured previously.
160 * </p>
161 * @param newMaxIter maximum number of iterations in the event time search
162 * @return a new detector with updated configuration (the instance is not changed)
163 * @since 6.1
164 */
165 public D withMaxIter(final int newMaxIter) {
166 return withDetectionSettings(new FieldEventDetectionSettings<>(getMaxCheckInterval(), getThreshold(), newMaxIter));
167 }
168
169 /**
170 * Set up the convergence threshold.
171 * <p>
172 * This will override a convergence threshold if it has been configured previously.
173 * </p>
174 * @param newThreshold convergence threshold (s)
175 * @return a new detector with updated configuration (the instance is not changed)
176 * @since 6.1
177 */
178 public D withThreshold(final T newThreshold) {
179 return withDetectionSettings(new FieldEventDetectionSettings<>(getMaxCheckInterval(), newThreshold, getMaxIterationCount()));
180 }
181
182 /**
183 * Set up the event detection settings.
184 * <p>
185 * This will override settings previously configured.
186 * </p>
187 * @param newSettings new event detection settings
188 * @return a new detector with updated configuration (the instance is not changed)
189 * @since 12.2
190 */
191 public D withDetectionSettings(final FieldEventDetectionSettings<T> newSettings) {
192 return create(newSettings, getHandler());
193 }
194
195 /**
196 * Set up the event handler to call at event occurrences.
197 * <p>
198 * This will override a handler if it has been configured previously.
199 * </p>
200 * @param newHandler event handler to call at event occurrences
201 * @return a new detector with updated configuration (the instance is not changed)
202 * @since 6.1
203 */
204 public D withHandler(final FieldEventHandler<T> newHandler) {
205 return create(getDetectionSettings(), newHandler);
206 }
207
208 /** {@inheritDoc} */
209 public FieldEventHandler<T> getHandler() {
210 return handler;
211 }
212
213 /** Build a new instance.
214 * @param detectionSettings detection settings
215 * @param newHandler event handler to call at event occurrences
216 * @return a new instance of the appropriate sub-type
217 * @since 12.2
218 */
219 protected abstract D create(FieldEventDetectionSettings<T> detectionSettings, FieldEventHandler<T> newHandler);
220
221 /** Check if the current propagation is forward or backward.
222 * @return true if the current propagation is forward
223 * @since 7.2
224 */
225 public boolean isForward() {
226 return forward;
227 }
228
229 /**
230 * Build non-Field instance.
231 * @param eventHandler event handler
232 * @return event detector
233 * @since 14.0
234 */
235 public EventDetector toEventDetector(final EventHandler eventHandler) {
236 return EventDetector.of(getEventFunction(), eventHandler, getDetectionSettings().toEventDetectionSettings());
237 }
238 }