1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.integration;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Queue;
28
29 import org.hipparchus.analysis.UnivariateFunction;
30 import org.hipparchus.analysis.solvers.BracketedUnivariateSolver;
31 import org.hipparchus.analysis.solvers.BracketingNthOrderBrentSolver;
32 import org.hipparchus.exception.MathRuntimeException;
33 import org.hipparchus.ode.DenseOutputModel;
34 import org.hipparchus.ode.ExpandableODE;
35 import org.hipparchus.ode.ODEIntegrator;
36 import org.hipparchus.ode.ODEState;
37 import org.hipparchus.ode.ODEStateAndDerivative;
38 import org.hipparchus.ode.OrdinaryDifferentialEquation;
39 import org.hipparchus.ode.SecondaryODE;
40 import org.hipparchus.ode.events.Action;
41 import org.hipparchus.ode.events.AdaptableInterval;
42 import org.hipparchus.ode.events.ODEEventDetector;
43 import org.hipparchus.ode.events.ODEEventHandler;
44 import org.hipparchus.ode.sampling.AbstractODEStateInterpolator;
45 import org.hipparchus.ode.sampling.ODEStateInterpolator;
46 import org.hipparchus.ode.sampling.ODEStepHandler;
47 import org.hipparchus.util.Precision;
48 import org.orekit.attitudes.AttitudeProvider;
49 import org.orekit.attitudes.AttitudeProviderModifier;
50 import org.orekit.errors.OrekitException;
51 import org.orekit.errors.OrekitInternalError;
52 import org.orekit.errors.OrekitMessages;
53 import org.orekit.frames.Frame;
54 import org.orekit.orbits.OrbitType;
55 import org.orekit.orbits.PositionAngleType;
56 import org.orekit.propagation.AbstractPropagator;
57 import org.orekit.propagation.BoundedPropagator;
58 import org.orekit.propagation.EphemerisGenerator;
59 import org.orekit.propagation.PropagationType;
60 import org.orekit.propagation.SpacecraftState;
61 import org.orekit.propagation.events.EventDetector;
62 import org.orekit.propagation.events.handlers.EventHandler;
63 import org.orekit.propagation.sampling.OrekitStepHandler;
64 import org.orekit.propagation.sampling.OrekitStepInterpolator;
65 import org.orekit.time.AbsoluteDate;
66 import org.orekit.utils.DataDictionary;
67 import org.orekit.utils.DoubleArrayDictionary;
68
69
70
71
72
73
74 public abstract class AbstractIntegratedPropagator extends AbstractPropagator {
75
76
77
78
79 private static final String SECONDARY_DIMENSION = "Orekit-secondary-dimension";
80
81
82 private final List<EventDetector> detectors;
83
84
85 private final List<StoringStepHandler> ephemerisGenerators;
86
87
88 private final ODEIntegrator integrator;
89
90
91
92
93 private final Map<String, Integer> secondaryOffsets;
94
95
96
97
98 private final List<AdditionalDerivativesProvider> additionalDerivativesProviders;
99
100
101
102 private int calls;
103
104
105 private StateMapper stateMapper;
106
107
108
109
110
111 private AttitudeProvider attitudeProviderForDerivatives;
112
113
114
115
116
117 private AttitudeProvider frozenAttitudeProvider;
118
119
120 private boolean resetAtEnd;
121
122
123
124
125
126
127
128 private final PropagationType propagationType;
129
130
131
132
133
134 protected AbstractIntegratedPropagator(final ODEIntegrator integrator, final PropagationType propagationType) {
135 detectors = new ArrayList<>();
136 ephemerisGenerators = new ArrayList<>();
137 additionalDerivativesProviders = new ArrayList<>();
138 this.secondaryOffsets = new HashMap<>();
139 this.integrator = integrator;
140 this.propagationType = propagationType;
141 this.resetAtEnd = true;
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155
156 public void setResetAtEnd(final boolean resetAtEnd) {
157 this.resetAtEnd = resetAtEnd;
158 }
159
160
161
162
163
164 public boolean getResetAtEnd() {
165 return this.resetAtEnd;
166 }
167
168
169
170
171
172
173 protected AttitudeProvider getFrozenAttitudeProvider() {
174 return frozenAttitudeProvider;
175 }
176
177
178
179
180
181 protected AttitudeProvider initializeAttitudeProviderForDerivatives() {
182 return getAttitudeProvider();
183 }
184
185
186 protected void initMapper() {
187 stateMapper = createMapper(null, Double.NaN, null, null, null, null);
188 }
189
190
191
192
193
194 public String getIntegratorName() {
195 return integrator.getName();
196 }
197
198
199 @Override
200 public void setAttitudeProvider(final AttitudeProvider attitudeProvider) {
201 super.setAttitudeProvider(attitudeProvider);
202 frozenAttitudeProvider = AttitudeProviderModifier.getFrozenAttitudeProvider(attitudeProvider);
203 stateMapper = createMapper(stateMapper.getReferenceDate(), stateMapper.getMu(),
204 stateMapper.getOrbitType(), stateMapper.getPositionAngleType(),
205 attitudeProvider, stateMapper.getFrame());
206 }
207
208
209
210
211
212
213 protected void setOrbitType(final OrbitType orbitType) {
214 stateMapper = createMapper(stateMapper.getReferenceDate(), stateMapper.getMu(),
215 orbitType, stateMapper.getPositionAngleType(),
216 stateMapper.getAttitudeProvider(), stateMapper.getFrame());
217 }
218
219
220
221
222
223
224 protected OrbitType getOrbitType() {
225 return stateMapper.getOrbitType();
226 }
227
228
229
230
231
232 public PropagationType getPropagationType() {
233 return propagationType;
234 }
235
236
237
238
239
240
241
242
243
244
245 protected void setPositionAngleType(final PositionAngleType positionAngleType) {
246 stateMapper = createMapper(stateMapper.getReferenceDate(), stateMapper.getMu(),
247 stateMapper.getOrbitType(), positionAngleType,
248 stateMapper.getAttitudeProvider(), stateMapper.getFrame());
249 }
250
251
252
253
254 protected PositionAngleType getPositionAngleType() {
255 return stateMapper.getPositionAngleType();
256 }
257
258
259
260
261 public void setMu(final double mu) {
262 stateMapper = createMapper(stateMapper.getReferenceDate(), mu,
263 stateMapper.getOrbitType(), stateMapper.getPositionAngleType(),
264 stateMapper.getAttitudeProvider(), stateMapper.getFrame());
265 }
266
267
268
269
270
271 public double getMu() {
272 return stateMapper.getMu();
273 }
274
275
276
277
278
279
280 public int getCalls() {
281 return calls;
282 }
283
284
285 @Override
286 public boolean isAdditionalDataManaged(final String name) {
287
288
289 if (super.isAdditionalDataManaged(name)) {
290 return true;
291 }
292
293
294 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
295 if (provider.getName().equals(name)) {
296 return true;
297 }
298 }
299
300 return false;
301 }
302
303
304 @Override
305 public String[] getManagedAdditionalData() {
306 final String[] alreadyIntegrated = super.getManagedAdditionalData();
307 final String[] managed = new String[alreadyIntegrated.length + additionalDerivativesProviders.size()];
308 System.arraycopy(alreadyIntegrated, 0, managed, 0, alreadyIntegrated.length);
309 for (int i = 0; i < additionalDerivativesProviders.size(); ++i) {
310 managed[i + alreadyIntegrated.length] = additionalDerivativesProviders.get(i).getName();
311 }
312 return managed;
313 }
314
315
316
317
318
319
320 public void addAdditionalDerivativesProvider(final AdditionalDerivativesProvider provider) {
321
322
323 if (this.isAdditionalDataManaged(provider.getName())) {
324
325 throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
326 provider.getName());
327 }
328
329
330 additionalDerivativesProviders.add(provider);
331
332 secondaryOffsets.clear();
333
334 }
335
336
337
338
339
340 public List<AdditionalDerivativesProvider> getAdditionalDerivativesProviders() {
341 return Collections.unmodifiableList(additionalDerivativesProviders);
342 }
343
344
345
346
347
348
349 protected void removeAdditionalDerivativesProvider(final String name) {
350 additionalDerivativesProviders.removeIf(provider -> provider.getName().equals(name));
351 }
352
353
354 public void addEventDetector(final EventDetector detector) {
355 detectors.add(detector);
356 }
357
358
359 public Collection<EventDetector> getEventDetectors() {
360 return Collections.unmodifiableCollection(detectors);
361 }
362
363
364 public void clearEventsDetectors() {
365 detectors.clear();
366 }
367
368
369
370 protected void setUpUserEventDetectors() {
371 for (final EventDetector detector : detectors) {
372 setUpEventDetector(integrator, detector);
373 }
374 }
375
376
377
378
379
380 protected void setUpEventDetector(final ODEIntegrator integ, final EventDetector detector) {
381 integ.addEventDetector(new AdaptedEventDetector(detector));
382 }
383
384
385
386
387
388 public void clearEphemerisGenerators() {
389 ephemerisGenerators.clear();
390 }
391
392
393 @Override
394 public EphemerisGenerator getEphemerisGenerator() {
395 final StoringStepHandler storingHandler = new StoringStepHandler();
396 ephemerisGenerators.add(storingHandler);
397 return storingHandler;
398 }
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 protected abstract StateMapper createMapper(AbsoluteDate referenceDate, double mu,
417 OrbitType orbitType, PositionAngleType positionAngleType,
418 AttitudeProvider attitudeProvider, Frame frame);
419
420
421
422
423
424 protected abstract MainStateEquations getMainStateEquations(ODEIntegrator integ);
425
426
427 @Override
428 public SpacecraftState propagate(final AbsoluteDate target) {
429 if (getStartDate() == null) {
430 if (getInitialState() == null) {
431 throw new OrekitException(OrekitMessages.INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION);
432 }
433 setStartDate(getInitialState().getDate());
434 }
435 return propagate(getStartDate(), target);
436 }
437
438
439 public SpacecraftState propagate(final AbsoluteDate tStart, final AbsoluteDate tEnd) {
440
441 if (getInitialState() == null) {
442 throw new OrekitException(OrekitMessages.INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION);
443 }
444
445
446 try (IntegratorResetter resetter = new IntegratorResetter(integrator)) {
447
448
449 setUpStmAndJacobianGenerators();
450
451
452 initializeAdditionalData(tEnd);
453
454 if (!tStart.equals(getInitialState().getDate())) {
455
456
457 try (IntegratorResetter startResetter = new IntegratorResetter(integrator)) {
458 integrateDynamics(tStart, true);
459 }
460 }
461
462
463 setUpUserEventDetectors();
464
465
466 for (final OrekitStepHandler handler : getMultiplexer().getHandlers()) {
467 integrator.addStepHandler(new AdaptedStepHandler(handler));
468 }
469 for (final StoringStepHandler generator : ephemerisGenerators) {
470 generator.setEndDate(tEnd);
471 integrator.addStepHandler(generator);
472 }
473
474
475 final SpacecraftState finalState = integrateDynamics(tEnd, false);
476
477
478 getEventDetectors().forEach(detector -> detector.finish(finalState));
479
480 return finalState;
481 }
482
483 }
484
485
486
487
488
489
490
491
492
493
494 public void resetInitialState(final SpacecraftState state, final PropagationType stateType) {
495
496 resetInitialState(state);
497 }
498
499
500
501
502 protected void setUpStmAndJacobianGenerators() {
503
504 }
505
506 @Override
507 public void clearMatricesComputation() {
508 secondaryOffsets.clear();
509 super.clearMatricesComputation();
510 }
511
512
513
514
515
516
517 private SpacecraftState integrateDynamics(final AbsoluteDate tEnd, final boolean forceResetAtEnd) {
518 try {
519
520 initializePropagation();
521
522 if (getInitialState().getDate().equals(tEnd)) {
523
524 return getInitialState();
525 }
526
527
528 stateMapper = createMapper(getInitialState().getDate(), stateMapper.getMu(),
529 stateMapper.getOrbitType(), stateMapper.getPositionAngleType(),
530 stateMapper.getAttitudeProvider(), getInitialState().getFrame());
531 attitudeProviderForDerivatives = initializeAttitudeProviderForDerivatives();
532
533 if (Double.isNaN(getMu())) {
534 setMu(getInitialState().isOrbitDefined() ? getInitialState().getOrbit().getMu() : Double.NaN);
535 }
536
537 if (getInitialState().getMass() <= 0.0) {
538 throw new OrekitException(OrekitMessages.NOT_POSITIVE_SPACECRAFT_MASS,
539 getInitialState().getMass());
540 }
541
542
543 final SpacecraftState initialIntegrationState = getInitialIntegrationState();
544 final ODEState mathInitialState = createInitialState(initialIntegrationState);
545 final ExpandableODE mathODE = createODE(integrator);
546
547
548 final ODEStateAndDerivative mathFinalState;
549 beforeIntegration(initialIntegrationState, tEnd);
550 mathFinalState = integrator.integrate(mathODE, mathInitialState,
551 tEnd.durationFrom(getInitialState().getDate()));
552 afterIntegration();
553
554
555 SpacecraftState finalState =
556 stateMapper.mapArrayToState(stateMapper.mapDoubleToDate(mathFinalState.getTime(),
557 tEnd),
558 mathFinalState.getPrimaryState(),
559 mathFinalState.getPrimaryDerivative(),
560 propagationType);
561
562 finalState = updateAdditionalStatesAndDerivatives(finalState, mathFinalState);
563
564 if (resetAtEnd || forceResetAtEnd) {
565 resetInitialState(finalState, propagationType);
566 setStartDate(finalState.getDate());
567 }
568
569 return finalState;
570
571 } catch (MathRuntimeException mre) {
572 throw OrekitException.unwrap(mre);
573 }
574 }
575
576
577
578
579
580
581
582
583
584 private SpacecraftState updateAdditionalStatesAndDerivatives(final SpacecraftState originalState,
585 final ODEStateAndDerivative os) {
586 SpacecraftState updatedState = originalState;
587 if (os.getNumberOfSecondaryStates() > 0) {
588 final double[] secondary = os.getSecondaryState(1);
589 final double[] secondaryDerivative = os.getSecondaryDerivative(1);
590 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
591 final String name = provider.getName();
592 final int offset = secondaryOffsets.get(name);
593 final int dimension = provider.getDimension();
594 updatedState = updatedState.addAdditionalData(name, Arrays.copyOfRange(secondary, offset, offset + dimension));
595 updatedState = updatedState.addAdditionalStateDerivative(name, Arrays.copyOfRange(secondaryDerivative, offset, offset + dimension));
596 }
597 }
598 return updateAdditionalData(updatedState);
599 }
600
601
602
603
604 protected SpacecraftState getInitialIntegrationState() {
605 return getInitialState();
606 }
607
608
609
610
611
612 private ODEState createInitialState(final SpacecraftState initialState) {
613
614
615 final double[] primary = new double[getBasicDimension()];
616 stateMapper.mapStateToArray(initialState, primary, null);
617
618 if (secondaryOffsets.isEmpty()) {
619
620 int offset = 0;
621 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
622 secondaryOffsets.put(provider.getName(), offset);
623 offset += provider.getDimension();
624 }
625 secondaryOffsets.put(SECONDARY_DIMENSION, offset);
626 }
627
628 return new ODEState(0.0, primary, secondary(initialState));
629
630 }
631
632
633
634
635
636
637 private double[][] secondary(final SpacecraftState state) {
638
639 if (secondaryOffsets.isEmpty()) {
640 return null;
641 }
642
643 final double[][] secondary = new double[1][secondaryOffsets.get(SECONDARY_DIMENSION)];
644 copyAdditionalStateOrDerivative(state, false, secondary);
645
646 return secondary;
647
648 }
649
650 private void copyAdditionalStateOrDerivative(final SpacecraftState state, final boolean copyDerivative,
651 final double[][] secondary) {
652 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
653 final String name = provider.getName();
654 final int offset = secondaryOffsets.get(name);
655 final int dimension = provider.getDimension();
656 final double[] secondaryArray = copyDerivative ? state.getAdditionalStateDerivative(name) :
657 state.getAdditionalState(name);
658 System.arraycopy(secondaryArray, 0, secondary[0], offset, dimension);
659 }
660 }
661
662
663
664
665
666 private ExpandableODE createODE(final ODEIntegrator integ) {
667
668 final ExpandableODE ode =
669 new ExpandableODE(new ConvertedMainStateEquations(getMainStateEquations(integ)));
670
671
672 if (!additionalDerivativesProviders.isEmpty()) {
673 ode.addSecondaryEquations(new ConvertedSecondaryStateEquations());
674 }
675
676 return ode;
677
678 }
679
680
681
682
683
684
685
686
687 protected void beforeIntegration(final SpacecraftState initialState,
688 final AbsoluteDate tEnd) {
689
690 }
691
692
693
694
695
696
697 protected void afterIntegration() {
698
699 }
700
701
702
703
704 public int getBasicDimension() {
705 return 7;
706 }
707
708
709
710
711 protected ODEIntegrator getIntegrator() {
712 return integrator;
713 }
714
715
716
717
718
719 private SpacecraftState convertToOrekitWithAdditional(final ODEStateAndDerivative os) {
720 final SpacecraftState s = convertToOrekitWithoutAdditional(os);
721 return updateAdditionalStatesAndDerivatives(s, os);
722 }
723
724
725
726
727
728
729 private SpacecraftState convertToOrekitWithoutAdditional(final ODEStateAndDerivative os) {
730 return stateMapper.mapArrayToState(os.getTime(), os.getPrimaryState(),
731 os.getPrimaryDerivative(), propagationType);
732 }
733
734
735 public interface MainStateEquations {
736
737
738
739
740
741
742
743
744
745
746
747 default void init(final SpacecraftState initialState, final AbsoluteDate target) {
748 }
749
750
751
752
753
754 double[] computeDerivatives(SpacecraftState state);
755
756 }
757
758
759 private class ConvertedMainStateEquations implements OrdinaryDifferentialEquation {
760
761
762 private final MainStateEquations main;
763
764
765
766
767 ConvertedMainStateEquations(final MainStateEquations main) {
768 this.main = main;
769 calls = 0;
770 }
771
772
773 public int getDimension() {
774 return getBasicDimension();
775 }
776
777 @Override
778 public void init(final double t0, final double[] y0, final double finalTime) {
779
780 SpacecraftState initialState = stateMapper.mapArrayToState(t0, y0, null, PropagationType.MEAN);
781 initialState = updateAdditionalData(initialState);
782 initialState = updateStatesFromAdditionalDerivativesIfKnown(initialState);
783 final AbsoluteDate target = stateMapper.mapDoubleToDate(finalTime);
784 main.init(initialState, target);
785 attitudeProviderForDerivatives = initializeAttitudeProviderForDerivatives();
786 }
787
788
789
790
791
792
793
794
795 private SpacecraftState updateStatesFromAdditionalDerivativesIfKnown(final SpacecraftState originalState) {
796 SpacecraftState updatedState = originalState;
797 final SpacecraftState storedInitialState = getInitialState();
798 final double originalTime = stateMapper.mapDateToDouble(originalState.getDate());
799 if (storedInitialState != null && stateMapper.mapDateToDouble(storedInitialState.getDate()) == originalTime) {
800 for (final AdditionalDerivativesProvider provider: additionalDerivativesProviders) {
801 final String name = provider.getName();
802 final double[] value = storedInitialState.getAdditionalState(name);
803 updatedState = updatedState.addAdditionalData(name, value);
804 }
805 }
806 return updatedState;
807 }
808
809
810 public double[] computeDerivatives(final double t, final double[] y) {
811
812
813 ++calls;
814
815
816 stateMapper.setAttitudeProvider(attitudeProviderForDerivatives);
817 SpacecraftState currentState = stateMapper.mapArrayToState(t, y, null, PropagationType.MEAN);
818 stateMapper.setAttitudeProvider(getAttitudeProvider());
819
820 currentState = updateAdditionalData(currentState);
821
822 return main.computeDerivatives(currentState);
823
824 }
825
826 }
827
828
829 private class ConvertedSecondaryStateEquations implements SecondaryODE {
830
831
832 private final int combinedDimension;
833
834
835
836 ConvertedSecondaryStateEquations() {
837 this.combinedDimension = secondaryOffsets.get(SECONDARY_DIMENSION);
838 }
839
840
841 @Override
842 public int getDimension() {
843 return combinedDimension;
844 }
845
846
847 @Override
848 public void init(final double t0, final double[] primary0,
849 final double[] secondary0, final double finalTime) {
850
851 final SpacecraftState initialState = convert(t0, primary0, null, secondary0);
852
853 final AbsoluteDate target = stateMapper.mapDoubleToDate(finalTime);
854 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
855 provider.init(initialState, target);
856 }
857
858 }
859
860
861 @Override
862 public double[] computeDerivatives(final double t, final double[] primary,
863 final double[] primaryDot, final double[] secondary) {
864
865
866
867
868 SpacecraftState updated = convert(t, primary, primaryDot, secondary);
869
870
871 final Queue<AdditionalDerivativesProvider> pending = new LinkedList<>(additionalDerivativesProviders);
872
873
874 final double[] secondaryDot = new double[combinedDimension];
875 final DoubleArrayDictionary derivativesDictionary = new DoubleArrayDictionary();
876 int yieldCount = 0;
877 while (!pending.isEmpty()) {
878 final AdditionalDerivativesProvider provider = pending.remove();
879 if (provider.yields(updated)) {
880
881
882 pending.add(provider);
883 if (++yieldCount >= pending.size()) {
884
885
886
887 break;
888 }
889 } else {
890
891 final String name = provider.getName();
892 final int offset = secondaryOffsets.get(name);
893 final int dimension = provider.getDimension();
894 final CombinedDerivatives derivatives = provider.combinedDerivatives(updated);
895 final double[] additionalPart = derivatives.getAdditionalDerivatives();
896 final double[] mainPart = derivatives.getMainStateDerivativesIncrements();
897 System.arraycopy(additionalPart, 0, secondaryDot, offset, dimension);
898 derivativesDictionary.put(name, additionalPart);
899 updated = updated.withAdditionalStatesDerivatives(derivativesDictionary);
900 if (mainPart != null) {
901
902 for (int i = 0; i < mainPart.length; ++i) {
903 primaryDot[i] += mainPart[i];
904 }
905 }
906 yieldCount = 0;
907 }
908 }
909
910 return secondaryDot;
911
912 }
913
914
915
916
917
918
919
920
921 private SpacecraftState convert(final double t, final double[] primary,
922 final double[] primaryDot, final double[] secondary) {
923
924 final SpacecraftState initialState = stateMapper.mapArrayToState(t, primary, primaryDot, PropagationType.MEAN);
925
926 final DataDictionary additionalStateDictionary = new DataDictionary();
927 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
928 final String name = provider.getName();
929 final int offset = secondaryOffsets.get(name);
930 final int dimension = provider.getDimension();
931 additionalStateDictionary.put(name, Arrays.copyOfRange(secondary, offset, offset + dimension));
932 }
933
934 return updateAdditionalData(initialState.withAdditionalData(additionalStateDictionary));
935
936 }
937
938 }
939
940
941
942
943
944 private class AdaptedEventDetector implements ODEEventDetector {
945
946
947 private final EventDetector detector;
948
949
950
951
952 private final EventHandler handler;
953
954
955 private double lastT;
956
957
958 private double lastG;
959
960
961
962
963 AdaptedEventDetector(final EventDetector detector) {
964 this.detector = detector;
965 this.handler = detector.getHandler();
966 this.lastT = Double.NaN;
967 this.lastG = Double.NaN;
968 }
969
970
971 @Override
972 public AdaptableInterval getMaxCheckInterval() {
973 return (state, isForward) -> detector.getMaxCheckInterval().currentInterval(convertToOrekitForEventFunction(state), isForward);
974 }
975
976
977 @Override
978 public int getMaxIterationCount() {
979 return detector.getMaxIterationCount();
980 }
981
982
983 @Override
984 public BracketedUnivariateSolver<UnivariateFunction> getSolver() {
985 return new BracketingNthOrderBrentSolver(0, detector.getThreshold(), 0, 5);
986 }
987
988
989 @Override
990 public void init(final ODEStateAndDerivative s0, final double t) {
991 detector.init(convertToOrekitWithAdditional(s0), stateMapper.mapDoubleToDate(t));
992 this.lastT = Double.NaN;
993 this.lastG = Double.NaN;
994 }
995
996
997 @Override
998 public void reset(final ODEStateAndDerivative intermediateState, final double finalTime) {
999 detector.reset(convertToOrekitForEventFunction(intermediateState), stateMapper.mapDoubleToDate(finalTime));
1000 this.lastT = Double.NaN;
1001 this.lastG = Double.NaN;
1002 }
1003
1004
1005 public double g(final ODEStateAndDerivative s) {
1006 if (!Precision.equals(lastT, s.getTime(), 0)) {
1007 lastT = s.getTime();
1008 lastG = detector.g(convertToOrekitForEventFunction(s));
1009 }
1010 return lastG;
1011 }
1012
1013
1014
1015
1016
1017
1018 private SpacecraftState convertToOrekitForEventFunction(final ODEStateAndDerivative s) {
1019 if (!this.detector.getEventFunction().dependsOnMainVariablesOnly()) {
1020 return convertToOrekitWithAdditional(s);
1021 } else {
1022
1023 stateMapper.setAttitudeProvider(getFrozenAttitudeProvider());
1024 final SpacecraftState converted = convertToOrekitWithoutAdditional(s);
1025 stateMapper.setAttitudeProvider(getAttitudeProvider());
1026 return converted;
1027 }
1028 }
1029
1030
1031 public ODEEventHandler getHandler() {
1032
1033 return new ODEEventHandler() {
1034
1035
1036 public Action eventOccurred(final ODEStateAndDerivative s, final ODEEventDetector d, final boolean increasing) {
1037 return handler.eventOccurred(convertToOrekitWithAdditional(s), detector, increasing);
1038 }
1039
1040
1041 @Override
1042 public ODEState resetState(final ODEEventDetector d, final ODEStateAndDerivative s) {
1043
1044 final SpacecraftState oldState = convertToOrekitWithAdditional(s);
1045 final SpacecraftState newState = handler.resetState(detector, oldState);
1046 stateChanged(newState);
1047
1048
1049 final double[] primary = new double[s.getPrimaryStateDimension()];
1050 stateMapper.mapStateToArray(newState, primary, null);
1051
1052
1053 final double[][] secondary = new double[1][secondaryOffsets.get(SECONDARY_DIMENSION)];
1054 copyAdditionalStateOrDerivative(newState, false, secondary);
1055
1056 return new ODEState(newState.getDate().durationFrom(getStartDate()),
1057 primary, secondary);
1058
1059 }
1060
1061 };
1062 }
1063
1064 }
1065
1066
1067
1068
1069
1070 private class AdaptedStepHandler implements ODEStepHandler {
1071
1072
1073 private final OrekitStepHandler handler;
1074
1075
1076
1077
1078 AdaptedStepHandler(final OrekitStepHandler handler) {
1079 this.handler = handler;
1080 }
1081
1082
1083 @Override
1084 public void init(final ODEStateAndDerivative s0, final double t) {
1085 handler.init(convertToOrekitWithAdditional(s0), stateMapper.mapDoubleToDate(t));
1086 }
1087
1088
1089 @Override
1090 public void handleStep(final ODEStateInterpolator interpolator) {
1091 handler.handleStep(new AdaptedStepInterpolator(interpolator));
1092 }
1093
1094
1095 @Override
1096 public void finish(final ODEStateAndDerivative finalState) {
1097 handler.finish(convertToOrekitWithAdditional(finalState));
1098 }
1099
1100 }
1101
1102
1103
1104
1105
1106 private class AdaptedStepInterpolator implements OrekitStepInterpolator {
1107
1108
1109 private final ODEStateInterpolator mathInterpolator;
1110
1111
1112
1113
1114 AdaptedStepInterpolator(final ODEStateInterpolator mathInterpolator) {
1115 this.mathInterpolator = mathInterpolator;
1116 }
1117
1118
1119 @Override
1120 public SpacecraftState getPreviousState() {
1121 return convertToOrekitWithAdditional(mathInterpolator.getPreviousState());
1122 }
1123
1124
1125 @Override
1126 public boolean isPreviousStateInterpolated() {
1127 return mathInterpolator.isPreviousStateInterpolated();
1128 }
1129
1130
1131 @Override
1132 public SpacecraftState getCurrentState() {
1133 return convertToOrekitWithAdditional(mathInterpolator.getCurrentState());
1134 }
1135
1136
1137 @Override
1138 public boolean isCurrentStateInterpolated() {
1139 return mathInterpolator.isCurrentStateInterpolated();
1140 }
1141
1142
1143 @Override
1144 public SpacecraftState getInterpolatedState(final AbsoluteDate date) {
1145 return convertToOrekitWithAdditional(mathInterpolator.getInterpolatedState(date.durationFrom(stateMapper.getReferenceDate())));
1146 }
1147
1148
1149 @Override
1150 public boolean isForward() {
1151 return mathInterpolator.isForward();
1152 }
1153
1154
1155 @Override
1156 public AdaptedStepInterpolator restrictStep(final SpacecraftState newPreviousState,
1157 final SpacecraftState newCurrentState) {
1158 try {
1159 final AbstractODEStateInterpolator aosi = (AbstractODEStateInterpolator) mathInterpolator;
1160 return new AdaptedStepInterpolator(aosi.restrictStep(convertFromOrekit(newPreviousState),
1161 convertFromOrekit(newCurrentState)));
1162 } catch (ClassCastException cce) {
1163
1164 throw new OrekitInternalError(cce);
1165 }
1166 }
1167
1168
1169
1170
1171
1172
1173 private ODEStateAndDerivative convertFromOrekit(final SpacecraftState state) {
1174
1175
1176 final double[] primary = new double[getBasicDimension()];
1177 final double[] primaryDot = new double[getBasicDimension()];
1178 stateMapper.mapStateToArray(state, primary, primaryDot);
1179
1180
1181 final double[][] secondary = secondary(state);
1182 final double[][] secondaryDerivative = secondaryDerivative(state);
1183
1184 return new ODEStateAndDerivative(stateMapper.mapDateToDouble(state.getDate()),
1185 primary, primaryDot,
1186 secondary, secondaryDerivative);
1187
1188 }
1189
1190
1191
1192
1193
1194
1195 private double[][] secondaryDerivative(final SpacecraftState state) {
1196
1197 if (secondaryOffsets.isEmpty()) {
1198 return null;
1199 }
1200
1201 final double[][] secondaryDerivative = new double[1][secondaryOffsets.get(SECONDARY_DIMENSION)];
1202 copyAdditionalStateOrDerivative(state, true, secondaryDerivative);
1203
1204 return secondaryDerivative;
1205
1206 }
1207 }
1208
1209
1210
1211
1212 private class StoringStepHandler implements ODEStepHandler, EphemerisGenerator {
1213
1214
1215 private DenseOutputModel model;
1216
1217
1218 private AbsoluteDate endDate;
1219
1220
1221 private BoundedPropagator ephemeris;
1222
1223
1224 private ODEStateInterpolator lastInterpolator;
1225
1226
1227
1228
1229 public void setEndDate(final AbsoluteDate endDate) {
1230 this.endDate = endDate;
1231 }
1232
1233
1234 @Override
1235 public void init(final ODEStateAndDerivative s0, final double t) {
1236
1237 this.model = new DenseOutputModel();
1238 model.init(s0, t);
1239
1240
1241 this.ephemeris = null;
1242
1243 this.lastInterpolator = null;
1244
1245 }
1246
1247
1248 @Override
1249 public BoundedPropagator getGeneratedEphemeris() {
1250
1251 buildEphemeris();
1252 return ephemeris;
1253 }
1254
1255
1256 @Override
1257 public void handleStep(final ODEStateInterpolator interpolator) {
1258 model.handleStep(interpolator);
1259 lastInterpolator = interpolator;
1260 }
1261
1262
1263 @Override
1264 public void finish(final ODEStateAndDerivative finalState) {
1265 buildEphemeris();
1266 }
1267
1268
1269
1270
1271
1272 private void buildEphemeris() {
1273
1274
1275
1276
1277
1278 model.finish(lastInterpolator.getCurrentState());
1279
1280
1281 final double tI = model.getInitialTime();
1282 final double tF = model.getFinalTime();
1283
1284 final AbsoluteDate startDate =
1285 stateMapper.mapDoubleToDate(tI);
1286 final AbsoluteDate finalDate =
1287 stateMapper.mapDoubleToDate(tF, this.endDate);
1288 final AbsoluteDate minDate;
1289 final AbsoluteDate maxDate;
1290 if (tF < tI) {
1291 minDate = finalDate;
1292 maxDate = startDate;
1293 } else {
1294 minDate = startDate;
1295 maxDate = finalDate;
1296 }
1297
1298
1299 final DataDictionary unmanaged = new DataDictionary();
1300 for (final DataDictionary.Entry initial : getInitialState().getAdditionalDataValues().getData()) {
1301 if (!AbstractIntegratedPropagator.this.isAdditionalDataManaged(initial.getKey())) {
1302
1303
1304 unmanaged.put(initial.getKey(), initial.getValue());
1305 }
1306 }
1307
1308
1309 final String[] names = new String[additionalDerivativesProviders.size()];
1310 final int[] dimensions = new int[additionalDerivativesProviders.size()];
1311 for (int i = 0; i < names.length; ++i) {
1312 names[i] = additionalDerivativesProviders.get(i).getName();
1313 dimensions[i] = additionalDerivativesProviders.get(i).getDimension();
1314 }
1315
1316
1317 ephemeris = new IntegratedEphemeris(startDate, minDate, maxDate,
1318 stateMapper, getAttitudeProvider(), propagationType, model,
1319 unmanaged, getAdditionalDataProviders(),
1320 names, dimensions);
1321
1322 }
1323
1324 }
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336 private static class IntegratorResetter implements AutoCloseable {
1337
1338
1339 private final ODEIntegrator integrator;
1340
1341
1342 private final List<ODEEventDetector> detectors;
1343
1344
1345 private final List<ODEStepHandler> stepHandlers;
1346
1347
1348
1349
1350 IntegratorResetter(final ODEIntegrator integrator) {
1351 this.integrator = integrator;
1352 this.detectors = new ArrayList<>(integrator.getEventDetectors());
1353 this.stepHandlers = new ArrayList<>(integrator.getStepHandlers());
1354 }
1355
1356
1357
1358
1359
1360
1361 @Override
1362 public void close() {
1363
1364
1365 integrator.clearEventDetectors();
1366 detectors.forEach(integrator::addEventDetector);
1367
1368
1369 integrator.clearStepHandlers();
1370 stepHandlers.forEach(integrator::addStepHandler);
1371
1372 }
1373
1374 }
1375
1376 }