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