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.propagation.sampling;
19  
20  import org.hipparchus.Field;
21  import org.hipparchus.ode.events.Action;
22  import org.hipparchus.util.Binary64;
23  import org.hipparchus.util.Binary64Field;
24  import org.junit.jupiter.api.AfterEach;
25  import org.junit.jupiter.api.Assertions;
26  import org.junit.jupiter.api.BeforeEach;
27  import org.junit.jupiter.api.Test;
28  import org.orekit.Utils;
29  import org.orekit.frames.FramesFactory;
30  import org.orekit.orbits.FieldKeplerianOrbit;
31  import org.orekit.orbits.FieldOrbit;
32  import org.orekit.orbits.PositionAngleType;
33  import org.orekit.propagation.FieldPropagator;
34  import org.orekit.propagation.FieldSpacecraftState;
35  import org.orekit.propagation.analytical.FieldKeplerianPropagator;
36  import org.orekit.propagation.events.FieldDateDetector;
37  import org.orekit.time.FieldAbsoluteDate;
38  import org.orekit.time.TimeScalesFactory;
39  import org.orekit.utils.Constants;
40  
41  public class FieldStepHandlerMultiplexerTest {
42  
43      FieldAbsoluteDate<Binary64> initDate;
44      FieldPropagator<Binary64> propagator;
45  
46      @BeforeEach
47      public void setUp() {
48          Utils.setDataRoot("regular-data");
49          Field<Binary64> field = Binary64Field.getInstance();
50          Binary64        zero  = field.getZero();
51          initDate = new FieldAbsoluteDate<>(field, 2020, 2, 28, 16, 15, 0.0, TimeScalesFactory.getUTC());
52          FieldOrbit<Binary64> ic = new FieldKeplerianOrbit<>(zero.add(6378137 + 500e3), zero.add(1e-3), zero, zero, zero, zero,
53                                                               PositionAngleType.TRUE, FramesFactory.getGCRF(), initDate,
54                                                               zero.add(Constants.WGS84_EARTH_MU));
55          propagator = new FieldKeplerianPropagator<>(ic);
56      }
57  
58      @AfterEach
59      public void tearDown() {
60          initDate   = null;
61          propagator = null;
62      }
63  
64      @Test
65      public void testMixedSteps() {
66  
67          Field<Binary64> field = Binary64Field.getInstance();
68          Binary64        zero  = field.getZero();
69  
70          FieldStepHandlerMultiplexer<Binary64> multiplexer = propagator.getMultiplexer();
71  
72          FieldInitCheckerHandler initHandler = new FieldInitCheckerHandler(1.0);
73          FieldFixedCounter    counter60  = new FieldFixedCounter();
74          FieldVariableCounter counterVar = new FieldVariableCounter();
75          FieldFixedCounter    counter10  = new FieldFixedCounter();
76  
77          multiplexer.add(zero.newInstance(60.0), initHandler);
78          multiplexer.add(zero.newInstance(60.0), counter60);
79          multiplexer.add(counterVar);
80          multiplexer.add(zero.newInstance(10.0), counter10);
81          Assertions.assertEquals(4, multiplexer.getHandlers().size());
82  
83          Assertions.assertFalse(initHandler.isInitialized());
84          Assertions.assertEquals(1.0, initHandler.getExpected(), Double.MIN_VALUE);
85  
86          propagator.propagate(initDate.shiftedBy(90.0));
87  
88          // verify
89          Assertions.assertTrue(initHandler.isInitialized());
90          Assertions.assertEquals(2.0, initHandler.getExpected(), Double.MIN_VALUE);
91  
92          Assertions.assertEquals( 1,  counter60.initCount);
93          Assertions.assertEquals( 2,  counter60.handleCount);
94          Assertions.assertEquals( 1,  counter60.finishCount);
95  
96          Assertions.assertEquals( 1,  counterVar.initCount);
97          Assertions.assertEquals( 1,  counterVar.handleCount);
98          Assertions.assertEquals( 1,  counterVar.finishCount);
99  
100         Assertions.assertEquals( 1,  counter10.initCount);
101         Assertions.assertEquals(10,  counter10.handleCount);
102         Assertions.assertEquals( 1,  counter10.finishCount);
103 
104     }
105 
106     @Test
107     public void testRemove() {
108 
109         FieldStepHandlerMultiplexer<Binary64> multiplexer = propagator.getMultiplexer();
110 
111         Field<Binary64> field = Binary64Field.getInstance();
112         Binary64        zero  = field.getZero();
113 
114         FieldFixedCounter    counter60  = new FieldFixedCounter();
115         FieldVariableCounter counterVar = new FieldVariableCounter();
116         FieldFixedCounter    counter10  = new FieldFixedCounter();
117 
118         multiplexer.add(zero.newInstance(60.0), counter60);
119         multiplexer.add(counterVar);
120         multiplexer.add(zero.newInstance(10.0), counter10);
121         Assertions.assertEquals(3, multiplexer.getHandlers().size());
122         Assertions.assertInstanceOf(FieldFixedCounter.class, ((FieldOrekitStepNormalizer<Binary64>) multiplexer.getHandlers().get(0)).getFixedStepHandler());
123         Assertions.assertEquals(60.0, ((FieldOrekitStepNormalizer<Binary64>) multiplexer.getHandlers().get(0)).getFixedTimeStep().getReal(), 1.0e-15);
124         Assertions.assertInstanceOf(FieldFixedCounter.class, ((FieldOrekitStepNormalizer<Binary64>) multiplexer.getHandlers().get(2)).getFixedStepHandler());
125         Assertions.assertEquals(10.0, ((FieldOrekitStepNormalizer<Binary64>) multiplexer.getHandlers().get(2)).getFixedTimeStep().getReal(), 1.0e-15);
126 
127         // first run with all handlers
128         propagator.propagate(initDate.shiftedBy(90.0));
129         Assertions.assertEquals( 1,    counter60.initCount);
130         Assertions.assertEquals( 2,    counter60.handleCount);
131         Assertions.assertEquals( 1,    counter60.finishCount);
132         Assertions.assertEquals(  0.0, counter60.start, 1.0e-15);
133         Assertions.assertEquals( 90.0, counter60.stop, 1.0e-15);
134         Assertions.assertEquals( 1,    counterVar.initCount);
135         Assertions.assertEquals( 1,    counterVar.handleCount);
136         Assertions.assertEquals( 1,    counterVar.finishCount);
137         Assertions.assertEquals(  0.0, counterVar.start, 1.0e-15);
138         Assertions.assertEquals( 90.0, counterVar.stop, 1.0e-15);
139         Assertions.assertEquals( 1,    counter10.initCount);
140         Assertions.assertEquals(10,    counter10.handleCount);
141         Assertions.assertEquals( 1,    counter10.finishCount);
142         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
143         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
144 
145         // removing the handler at 10 seconds
146         multiplexer.remove(counter10);
147         Assertions.assertEquals(2, multiplexer.getHandlers().size());
148         propagator.propagate(initDate.shiftedBy(100.0), initDate.shiftedBy(190.0));
149         Assertions.assertEquals( 2,    counter60.initCount);
150         Assertions.assertEquals( 4,    counter60.handleCount);
151         Assertions.assertEquals( 2,    counter60.initCount);
152         Assertions.assertEquals(100.0, counter60.start, 1.0e-15);
153         Assertions.assertEquals(190.0, counter60.stop, 1.0e-15);
154         Assertions.assertEquals( 2,    counterVar.initCount);
155         Assertions.assertEquals( 2,    counterVar.handleCount);
156         Assertions.assertEquals( 2,    counterVar.finishCount);
157         Assertions.assertEquals(100.0, counterVar.start, 1.0e-15);
158         Assertions.assertEquals(190.0, counterVar.stop, 1.0e-15);
159         Assertions.assertEquals( 1,    counter10.initCount);
160         Assertions.assertEquals(10,    counter10.handleCount);
161         Assertions.assertEquals( 1,    counter10.initCount);
162         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
163         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
164 
165         // attempting to remove a handler already removed
166         multiplexer.remove(counter10);
167         Assertions.assertEquals(2, multiplexer.getHandlers().size());
168         propagator.propagate(initDate.shiftedBy(200.0), initDate.shiftedBy(290.0));
169         Assertions.assertEquals( 3,    counter60.initCount);
170         Assertions.assertEquals( 6,    counter60.handleCount);
171         Assertions.assertEquals( 3,    counter60.finishCount);
172         Assertions.assertEquals(200.0, counter60.start, 1.0e-15);
173         Assertions.assertEquals(290.0, counter60.stop, 1.0e-15);
174         Assertions.assertEquals( 3,    counterVar.initCount);
175         Assertions.assertEquals( 3,    counterVar.handleCount);
176         Assertions.assertEquals( 3,    counterVar.finishCount);
177         Assertions.assertEquals(200.0, counterVar.start, 1.0e-15);
178         Assertions.assertEquals(290.0, counterVar.stop, 1.0e-15);
179         Assertions.assertEquals( 1,    counter10.initCount);
180         Assertions.assertEquals(10,    counter10.handleCount);
181         Assertions.assertEquals( 1,    counter10.finishCount);
182         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
183         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
184 
185         // removing the handler with variable stepsize
186         multiplexer.remove(counterVar);
187         Assertions.assertEquals(1, multiplexer.getHandlers().size());
188         propagator.propagate(initDate.shiftedBy(300.0), initDate.shiftedBy(390.0));
189         Assertions.assertEquals( 4,    counter60.initCount);
190         Assertions.assertEquals( 8,    counter60.handleCount);
191         Assertions.assertEquals( 4,    counter60.initCount);
192         Assertions.assertEquals(300.0, counter60.start, 1.0e-15);
193         Assertions.assertEquals(390.0, counter60.stop, 1.0e-15);
194         Assertions.assertEquals( 3,    counterVar.initCount);
195         Assertions.assertEquals( 3,    counterVar.handleCount);
196         Assertions.assertEquals( 3,    counterVar.finishCount);
197         Assertions.assertEquals(200.0, counterVar.start, 1.0e-15);
198         Assertions.assertEquals(290.0, counterVar.stop, 1.0e-15);
199         Assertions.assertEquals( 1,    counter10.initCount);
200         Assertions.assertEquals(10,    counter10.handleCount);
201         Assertions.assertEquals( 1,    counter10.initCount);
202         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
203         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
204 
205         // attempting to remove a handler already removed
206         multiplexer.remove(counterVar);
207         Assertions.assertEquals(1, multiplexer.getHandlers().size());
208         propagator.propagate(initDate.shiftedBy(400.0), initDate.shiftedBy(490.0));
209         Assertions.assertEquals( 5,    counter60.initCount);
210         Assertions.assertEquals(10,    counter60.handleCount);
211         Assertions.assertEquals( 5,    counter60.finishCount);
212         Assertions.assertEquals(400.0, counter60.start, 1.0e-15);
213         Assertions.assertEquals(490.0, counter60.stop, 1.0e-15);
214         Assertions.assertEquals( 3,    counterVar.initCount);
215         Assertions.assertEquals( 3,    counterVar.handleCount);
216         Assertions.assertEquals( 3,    counterVar.finishCount);
217         Assertions.assertEquals(200.0, counterVar.start, 1.0e-15);
218         Assertions.assertEquals(290.0, counterVar.stop, 1.0e-15);
219         Assertions.assertEquals( 1,    counter10.initCount);
220         Assertions.assertEquals(10,    counter10.handleCount);
221         Assertions.assertEquals( 1,    counter10.finishCount);
222         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
223         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
224 
225         // removing everything
226         multiplexer.clear();
227         Assertions.assertEquals(0, multiplexer.getHandlers().size());
228         propagator.propagate(initDate.shiftedBy(500.0), initDate.shiftedBy(590.0));
229         Assertions.assertEquals( 5,    counter60.initCount);
230         Assertions.assertEquals(10,    counter60.handleCount);
231         Assertions.assertEquals( 5,    counter60.finishCount);
232         Assertions.assertEquals(400.0, counter60.start, 1.0e-15);
233         Assertions.assertEquals(490.0, counter60.stop, 1.0e-15);
234         Assertions.assertEquals( 3,    counterVar.initCount);
235         Assertions.assertEquals( 3,    counterVar.handleCount);
236         Assertions.assertEquals( 3,    counterVar.finishCount);
237         Assertions.assertEquals(200.0, counterVar.start, 1.0e-15);
238         Assertions.assertEquals(290.0, counterVar.stop, 1.0e-15);
239         Assertions.assertEquals( 1,    counter10.initCount);
240         Assertions.assertEquals(10,    counter10.handleCount);
241         Assertions.assertEquals( 1,    counter10.finishCount);
242         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
243         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
244 
245     }
246 
247     @Test
248     public void testOnTheFlyChanges() {
249 
250         final FieldStepHandlerMultiplexer<Binary64> multiplexer = propagator.getMultiplexer();
251 
252         Field<Binary64> field = Binary64Field.getInstance();
253         Binary64        zero  = field.getZero();
254 
255         double               add60      =  3.0;
256         double               rem60      = 78.0;
257         FieldFixedCounter    counter60  = new FieldFixedCounter();
258         FieldDateDetector<Binary64> d1 = new FieldDateDetector<>(field, initDate.shiftedBy(add60)).
259                                          withHandler((s, d, i) -> {
260                                              multiplexer.add(zero.newInstance(60.0), counter60);
261                                             return Action.CONTINUE;
262                                          });
263         propagator.addEventDetector(d1);
264         FieldDateDetector<Binary64> d2 = new FieldDateDetector<>(field, initDate.shiftedBy(rem60)).
265                                          withHandler((s, d, i) -> {
266                                              multiplexer.remove(counter60);
267                                              return Action.CONTINUE;
268                                          });
269         propagator.addEventDetector(d2);
270 
271         double               addVar     =  5.0;
272         double               remVar     =  7.0;
273         FieldVariableCounter counterVar = new FieldVariableCounter();
274         FieldDateDetector<Binary64> d3 = new FieldDateDetector<>(field, initDate.shiftedBy(addVar)).
275                                          withHandler((s, d, i) -> {
276                                              multiplexer.add(counterVar);
277                                              return Action.CONTINUE;
278                                          });
279         propagator.addEventDetector(d3);
280         FieldDateDetector<Binary64> d4 = new FieldDateDetector<>(field, initDate.shiftedBy(remVar)).
281                                          withHandler((s, d, i) -> {
282                                              multiplexer.remove(counterVar);
283                                              return Action.CONTINUE;
284                                          });
285         propagator.addEventDetector(d4);
286 
287         double               add10      =  6.0;
288         double               rem10      = 82.0;
289         FieldFixedCounter    counter10  = new FieldFixedCounter();
290         FieldDateDetector<Binary64> d5 = new FieldDateDetector<>(field, initDate.shiftedBy(add10)).
291                                          withHandler((s, d, i) -> {
292                                              multiplexer.add(zero.newInstance(10.0), counter10);
293                                              return Action.CONTINUE;
294                                          });
295         propagator.addEventDetector(d5);
296         FieldDateDetector<Binary64> d6 = new FieldDateDetector<>(field, initDate.shiftedBy(rem10)).
297                                          withHandler((s, d, i) -> {
298                                              multiplexer.clear();
299                                              return Action.CONTINUE;
300                                          });
301         propagator.addEventDetector(d6);
302 
303         // full run, which will add and remove step handlers on the fly
304         propagator.propagate(initDate.shiftedBy(90.0));
305         Assertions.assertEquals( 1,     counter60.initCount);
306         Assertions.assertEquals( 2,     counter60.handleCount);
307         Assertions.assertEquals( 1,     counter60.finishCount);
308         Assertions.assertEquals(add60,  counter60.start, 1.0e-15);
309         Assertions.assertEquals(rem60,  counter60.stop, 1.0e-15);
310         Assertions.assertEquals( 1,     counterVar.initCount);
311         Assertions.assertEquals( 2,     counterVar.handleCount); // event at add10 splits the variable step in two parts
312         Assertions.assertEquals( 1,     counterVar.finishCount);
313         Assertions.assertEquals(addVar, counterVar.start, 1.0e-15);
314         Assertions.assertEquals(remVar, counterVar.stop, 1.0e-15);
315         Assertions.assertEquals( 1,     counter10.initCount);
316         Assertions.assertEquals( 8,     counter10.handleCount);
317         Assertions.assertEquals( 1,     counter10.finishCount);
318         Assertions.assertEquals(add10,  counter10.start, 1.0e-15);
319         Assertions.assertEquals(rem10,  counter10.stop, 1.0e-15);
320 
321     }
322 
323     private class FieldInitCheckerHandler implements FieldOrekitFixedStepHandler<Binary64> {
324 
325         private double expected;
326         private boolean initialized;
327 
328         public FieldInitCheckerHandler(final double expected) {
329             this.expected    = expected;
330             this.initialized = false;
331         }
332 
333         @Override
334         public void init(FieldSpacecraftState<Binary64> s0, FieldAbsoluteDate<Binary64> t, Binary64 step) {
335             initialized = true;
336         }
337 
338         @Override
339         public void handleStep(FieldSpacecraftState<Binary64> currentState) {
340             this.expected = 2.0;
341         }
342 
343         boolean isInitialized() {
344             return initialized;
345         }
346 
347         double getExpected() {
348             return expected;
349         }
350 
351     }
352 
353     private class FieldFixedCounter implements FieldOrekitFixedStepHandler<Binary64> {
354 
355         private int    initCount;
356         private int    handleCount;
357         private int    finishCount;
358         private double start;
359         private double stop;
360 
361         @Override
362         public void init(FieldSpacecraftState<Binary64> s0, FieldAbsoluteDate<Binary64> t, Binary64 step) {
363             ++initCount;
364             start = s0.getDate().durationFrom(initDate).getReal();
365         }
366 
367         @Override
368         public void handleStep(FieldSpacecraftState<Binary64> currentState) {
369             ++handleCount;
370         }
371 
372         @Override
373         public void finish(FieldSpacecraftState<Binary64> finalState) {
374             ++finishCount;
375             stop = finalState.getDate().durationFrom(initDate).getReal();
376         }
377 
378     }
379 
380     private class FieldVariableCounter implements FieldOrekitStepHandler<Binary64> {
381 
382         private int    initCount;
383         private int    handleCount;
384         private int    finishCount;
385         private double start;
386         private double stop;
387 
388         @Override
389         public void init(FieldSpacecraftState<Binary64> s0, FieldAbsoluteDate<Binary64> t) {
390             ++initCount;
391             start = s0.getDate().durationFrom(initDate).getReal();
392         }
393 
394         @Override
395         public void handleStep(FieldOrekitStepInterpolator<Binary64> interpolator) {
396             Assertions.assertNotNull(interpolator.getPosition(interpolator.getCurrentState().getDate(),
397                                                               interpolator.getCurrentState().getFrame()));
398             ++handleCount;
399         }
400 
401         @Override
402         public void finish(FieldSpacecraftState<Binary64> finalState) {
403             ++finishCount;
404             stop = finalState.getDate().durationFrom(initDate).getReal();
405         }
406 
407     }
408 
409 }