1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.events;
18
19 import org.hipparchus.Field;
20 import org.hipparchus.RealFieldElement;
21 import org.hipparchus.analysis.UnivariateFunction;
22 import org.hipparchus.analysis.solvers.BracketedUnivariateSolver;
23 import org.hipparchus.analysis.solvers.BracketedUnivariateSolver.Interval;
24 import org.hipparchus.analysis.solvers.BracketingNthOrderBrentSolver;
25 import org.hipparchus.exception.MathRuntimeException;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.Precision;
28 import org.orekit.errors.OrekitException;
29 import org.orekit.errors.OrekitExceptionWrapper;
30 import org.orekit.errors.OrekitInternalError;
31 import org.orekit.propagation.FieldSpacecraftState;
32 import org.orekit.propagation.events.handlers.FieldEventHandler;
33 import org.orekit.propagation.events.handlers.FieldEventHandler.Action;
34 import org.orekit.propagation.sampling.FieldOrekitStepInterpolator;
35 import org.orekit.time.FieldAbsoluteDate;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class FieldEventState<D extends FieldEventDetector<T>, T extends RealFieldElement<T>> {
55
56
57 private D detector;
58
59
60 private FieldAbsoluteDate<T> lastT;
61
62
63 private T lastG;
64
65
66 private FieldAbsoluteDate<T> t0;
67
68
69 private T g0;
70
71
72 private boolean g0Positive;
73
74
75 private boolean pendingEvent;
76
77
78 private FieldAbsoluteDate<T> pendingEventTime;
79
80
81
82
83
84 private FieldAbsoluteDate<T> stopTime;
85
86
87 private FieldAbsoluteDate<T> afterEvent;
88
89
90 private T afterG;
91
92
93 private FieldAbsoluteDate<T> earliestTimeConsidered;
94
95
96 private boolean forward;
97
98
99
100
101 private boolean increasing;
102
103
104
105
106 public FieldEventState(final D detector) {
107
108 this.detector = detector;
109
110
111 final Field<T> field = detector.getMaxCheckInterval().getField();
112 final T nan = field.getZero().add(Double.NaN);
113 lastT = FieldAbsoluteDate.getPastInfinity(field);
114 lastG = nan;
115 t0 = null;
116 g0 = nan;
117 g0Positive = true;
118 pendingEvent = false;
119 pendingEventTime = null;
120 stopTime = null;
121 increasing = true;
122 earliestTimeConsidered = null;
123 afterEvent = null;
124 afterG = nan;
125
126 }
127
128
129
130
131 public D getEventDetector() {
132 return detector;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 public void init(final FieldSpacecraftState<T> s0,
147 final FieldAbsoluteDate<T> t) throws OrekitException {
148 detector.init(s0, t);
149 final Field<T> field = detector.getMaxCheckInterval().getField();
150 lastT = FieldAbsoluteDate.getPastInfinity(field);
151 lastG = field.getZero().add(Double.NaN);
152 }
153
154
155
156
157
158
159
160
161 private T g(final FieldSpacecraftState<T> s) throws OrekitException {
162 if (!s.getDate().equals(lastT)) {
163 lastT = s.getDate();
164 lastG = detector.g(s);
165 }
166 return lastG;
167 }
168
169
170
171
172
173
174 public void reinitializeBegin(final FieldOrekitStepInterpolator<T> interpolator)
175 throws OrekitException {
176 forward = interpolator.isForward();
177 final FieldSpacecraftState<T> s0 = interpolator.getPreviousState();
178 this.t0 = s0.getDate();
179 g0 = g(s0);
180 while (g0.getReal() == 0) {
181
182
183
184 final T dt = detector.getThreshold().multiply(forward ? 0.5 : -0.5);
185 FieldAbsoluteDate<T> startDate = t0.shiftedBy(dt);
186
187 if (t0.equals(startDate)) {
188 startDate = nextAfter(startDate);
189 }
190 t0 = startDate;
191 g0 = g(interpolator.getInterpolatedState(t0));
192 }
193 g0Positive = g0.getReal() > 0;
194
195 increasing = g0Positive;
196 }
197
198
199
200
201
202
203
204
205
206
207 public boolean evaluateStep(final FieldOrekitStepInterpolator<T> interpolator)
208 throws OrekitException, MathRuntimeException {
209 forward = interpolator.isForward();
210 final FieldSpacecraftState<T> s1 = interpolator.getCurrentState();
211 final FieldAbsoluteDate<T> t1 = s1.getDate();
212 final T dt = t1.durationFrom(t0);
213 if (FastMath.abs(dt.getReal()) < detector.getThreshold().getReal()) {
214
215 return false;
216 }
217
218 final int n = FastMath.max(1, (int) FastMath.ceil(FastMath.abs(dt.getReal()) / detector.getMaxCheckInterval().getReal()));
219 final T h = dt.divide(n);
220
221
222 FieldAbsoluteDate<T> ta = t0;
223 T ga = g0;
224 for (int i = 0; i < n; ++i) {
225
226
227 final FieldAbsoluteDate<T> tb = (i == n - 1) ? t1 : t0.shiftedBy(h.multiply(i + 1));
228 final T gb = g(interpolator.getInterpolatedState(tb));
229
230
231 if (gb.getReal() == 0.0 || (g0Positive ^ (gb.getReal() > 0))) {
232
233 if (findRoot(interpolator, ta, ga, tb, gb)) {
234 return true;
235 }
236 } else {
237
238 ta = tb;
239 ga = gb;
240 }
241 }
242
243
244 pendingEvent = false;
245 pendingEventTime = null;
246 return false;
247
248 }
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 private boolean findRoot(final FieldOrekitStepInterpolator<T> interpolator,
267 final FieldAbsoluteDate<T> ta, final T ga,
268 final FieldAbsoluteDate<T> tb, final T gb)
269 throws OrekitException {
270
271 final T zero = ga.getField().getZero();
272
273
274 check(ga.getReal() == 0.0 || gb.getReal() == 0.0 || (ga.getReal() > 0.0 && gb.getReal() < 0.0) || (ga.getReal() < 0.0 && gb.getReal() > 0.0));
275 final T convergence = detector.getThreshold();
276 final int maxIterationCount = detector.getMaxIterationCount();
277 final BracketedUnivariateSolver<UnivariateFunction> solver =
278 new BracketingNthOrderBrentSolver(0, convergence.getReal(), 0, 5);
279
280
281 FieldAbsoluteDate<T> beforeRootT = null;
282 T beforeRootG = zero.add(Double.NaN);
283
284
285 FieldAbsoluteDate<T> afterRootT = ta;
286 T afterRootG = zero;
287
288
289
290
291 if (ta.equals(tb)) {
292
293 beforeRootT = ta;
294 beforeRootG = ga;
295 afterRootT = shiftedBy(beforeRootT, convergence);
296 afterRootG = g(interpolator.getInterpolatedState(afterRootT));
297 } else if (ga.getReal() != 0.0 && gb.getReal() == 0.0) {
298
299
300
301 beforeRootT = tb;
302 beforeRootG = gb;
303 afterRootT = shiftedBy(beforeRootT, convergence);
304 afterRootG = g(interpolator.getInterpolatedState(afterRootT));
305 } else if (ga.getReal() != 0.0) {
306 final T newGa = g(interpolator.getInterpolatedState(ta));
307 if (ga.getReal() > 0 != newGa.getReal() > 0) {
308
309 beforeRootT = ta;
310 beforeRootG = newGa;
311 afterRootT = minTime(shiftedBy(beforeRootT, convergence), tb);
312 afterRootG = g(interpolator.getInterpolatedState(afterRootT));
313 }
314 }
315
316
317 FieldAbsoluteDate<T> loopT = ta;
318 T loopG = ga;
319 while ((afterRootG.getReal() == 0.0 || afterRootG.getReal() > 0.0 == g0Positive) &&
320 strictlyAfter(afterRootT, tb)) {
321 if (loopG.getReal() == 0.0) {
322
323
324 beforeRootT = loopT;
325 beforeRootG = loopG;
326 afterRootT = minTime(shiftedBy(beforeRootT, convergence), tb);
327 afterRootG = g(interpolator.getInterpolatedState(afterRootT));
328 } else {
329
330 try {
331
332 final FieldAbsoluteDate<T> fT0 = loopT;
333 final UnivariateFunction f = dt -> {
334 try {
335 return g(interpolator.getInterpolatedState(fT0.shiftedBy(dt))).getReal();
336 } catch (OrekitException oe) {
337 throw new OrekitExceptionWrapper(oe);
338 }
339 };
340
341 final T tbDouble = tb.durationFrom(fT0);
342 if (forward) {
343 final Interval interval =
344 solver.solveInterval(maxIterationCount, f, 0, tbDouble.getReal());
345 beforeRootT = fT0.shiftedBy(interval.getLeftAbscissa());
346 beforeRootG = zero.add(interval.getLeftValue());
347 afterRootT = fT0.shiftedBy(interval.getRightAbscissa());
348 afterRootG = zero.add(interval.getRightValue());
349 } else {
350 final Interval interval =
351 solver.solveInterval(maxIterationCount, f, tbDouble.getReal(), 0);
352 beforeRootT = fT0.shiftedBy(interval.getRightAbscissa());
353 beforeRootG = zero.add(interval.getRightValue());
354 afterRootT = fT0.shiftedBy(interval.getLeftAbscissa());
355 afterRootG = zero.add(interval.getLeftValue());
356 }
357 } catch (OrekitExceptionWrapper oew) {
358 throw oew.getException();
359 }
360 }
361
362
363 if (beforeRootT.equals(afterRootT)) {
364 afterRootT = nextAfter(afterRootT);
365 afterRootG = g(interpolator.getInterpolatedState(afterRootT));
366 }
367
368 check((forward && afterRootT.compareTo(beforeRootT) > 0) ||
369 (!forward && afterRootT.compareTo(beforeRootT) < 0));
370
371 loopT = afterRootT;
372 loopG = afterRootG;
373 }
374
375
376 if (afterRootG.getReal() == 0.0 || afterRootG.getReal() > 0.0 == g0Positive) {
377
378 return false;
379 } else {
380
381 check(beforeRootT != null && !Double.isNaN(beforeRootG.getReal()));
382
383 increasing = !g0Positive;
384 pendingEventTime = beforeRootT;
385 stopTime = beforeRootG.getReal() == 0.0 ? beforeRootT : afterRootT;
386 pendingEvent = true;
387 afterEvent = afterRootT;
388 afterG = afterRootG;
389
390
391 check(afterG.getReal() > 0 == increasing);
392 check(increasing == gb.getReal() >= ga.getReal());
393
394 return true;
395 }
396
397 }
398
399
400
401
402
403
404
405 private FieldAbsoluteDate<T> nextAfter(final FieldAbsoluteDate<T> t) {
406 return t.shiftedBy(forward ? +Precision.EPSILON : -Precision.EPSILON);
407 }
408
409
410
411
412
413
414
415 public FieldAbsoluteDate<T> getEventDate() {
416 return pendingEventTime;
417 }
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434 public boolean tryAdvance(final FieldSpacecraftState<T> state,
435 final FieldOrekitStepInterpolator<T> interpolator)
436 throws OrekitException {
437
438
439 check(!(pendingEvent && strictlyAfter(pendingEventTime, state.getDate())));
440 final FieldAbsoluteDate<T> t = state.getDate();
441
442
443 if (strictlyAfter(t, earliestTimeConsidered)) {
444 return false;
445 }
446
447 final T g = g(state);
448 final boolean positive = g.getReal() > 0;
449
450
451 if ((g.getReal() == 0.0 && t.equals(pendingEventTime)) || positive == g0Positive) {
452
453 t0 = t;
454 g0 = g;
455 return false;
456 } else {
457
458
459 return findRoot(interpolator, t0, g0, t, g);
460 }
461 }
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478 public EventOccurrence<T> doEvent(final FieldSpacecraftState<T> state)
479 throws OrekitException {
480
481 check(pendingEvent);
482 check(state.getDate().equals(this.pendingEventTime));
483
484 final FieldEventHandler.Action action = detector.eventOccurred(state, increasing == forward);
485 final FieldSpacecraftState<T> newState;
486 if (action == FieldEventHandler.Action.RESET_STATE) {
487 newState = detector.resetState(state);
488 } else {
489 newState = state;
490 }
491
492 pendingEvent = false;
493 pendingEventTime = null;
494
495 earliestTimeConsidered = afterEvent;
496 t0 = afterEvent;
497 g0 = afterG;
498 g0Positive = increasing;
499
500 check(g0.getReal() == 0.0 || g0Positive == (g0.getReal() > 0));
501 return new EventOccurrence<T>(action, newState, stopTime);
502 }
503
504
505
506
507
508
509
510
511
512 private FieldAbsoluteDate<T> shiftedBy(final FieldAbsoluteDate<T> t, final T delta) {
513 if (forward) {
514 final FieldAbsoluteDate<T> ret = t.shiftedBy(delta);
515 if (ret.durationFrom(t).getReal() > delta.getReal()) {
516 return ret.shiftedBy(-Precision.EPSILON);
517 } else {
518 return ret;
519 }
520 } else {
521 final FieldAbsoluteDate<T> ret = t.shiftedBy(delta.negate());
522 if (t.durationFrom(ret).getReal() > delta.getReal()) {
523 return ret.shiftedBy(+Precision.EPSILON);
524 } else {
525 return ret;
526 }
527 }
528 }
529
530
531
532
533
534
535
536
537
538 private FieldAbsoluteDate<T> minTime(final FieldAbsoluteDate<T> a, final FieldAbsoluteDate<T> b) {
539 return (forward ^ (a.compareTo(b) > 0)) ? a : b;
540 }
541
542
543
544
545
546
547
548
549
550 private boolean strictlyAfter(final FieldAbsoluteDate<T> t1, final FieldAbsoluteDate<T> t2) {
551 if (t1 == null || t2 == null) {
552 return false;
553 } else {
554 return forward ? t1.compareTo(t2) < 0 : t2.compareTo(t1) < 0;
555 }
556 }
557
558
559
560
561
562
563
564 private void check(final boolean condition) throws MathRuntimeException {
565 if (!condition) {
566 throw new OrekitInternalError(null);
567 }
568 }
569
570
571
572
573
574 public static class EventOccurrence<T extends RealFieldElement<T>> {
575
576
577 private final FieldEventHandler.Action action;
578
579 private final FieldSpacecraftState<T> newState;
580
581 private final FieldAbsoluteDate<T> stopDate;
582
583
584
585
586
587
588
589
590
591
592 EventOccurrence(final FieldEventHandler.Action action,
593 final FieldSpacecraftState<T> newState,
594 final FieldAbsoluteDate<T> stopDate) {
595 this.action = action;
596 this.newState = newState;
597 this.stopDate = stopDate;
598 }
599
600
601
602
603
604
605 public FieldEventHandler.Action getAction() {
606 return action;
607 }
608
609
610
611
612
613
614 public FieldSpacecraftState<T> getNewState() {
615 return newState;
616 }
617
618
619
620
621
622
623 public FieldAbsoluteDate<T> getStopDate() {
624 return stopDate;
625 }
626
627 }
628
629
630
631
632
633 public boolean getPendingEvent() {
634 return pendingEvent;
635 }
636
637 }