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 import org.orekit.utils.DoubleArrayDictionary;
58
59 import java.util.ArrayList;
60 import java.util.Arrays;
61 import java.util.Collection;
62 import java.util.Collections;
63 import java.util.HashMap;
64 import java.util.LinkedList;
65 import java.util.List;
66 import java.util.Map;
67 import java.util.Queue;
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 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
645 final String name = provider.getName();
646 final int offset = secondaryOffsets.get(name);
647 final double[] additional = state.getAdditionalState(name);
648 System.arraycopy(additional, 0, secondary[0], offset, additional.length);
649 }
650
651 return secondary;
652
653 }
654
655
656
657
658
659 private ExpandableODE createODE(final ODEIntegrator integ) {
660
661 final ExpandableODE ode =
662 new ExpandableODE(new ConvertedMainStateEquations(getMainStateEquations(integ)));
663
664
665 if (!additionalDerivativesProviders.isEmpty()) {
666 ode.addSecondaryEquations(new ConvertedSecondaryStateEquations());
667 }
668
669 return ode;
670
671 }
672
673
674
675
676
677
678
679
680 protected void beforeIntegration(final SpacecraftState initialState,
681 final AbsoluteDate tEnd) {
682
683 }
684
685
686
687
688
689
690 protected void afterIntegration() {
691
692 }
693
694
695
696
697 public int getBasicDimension() {
698 return 7;
699 }
700
701
702
703
704 protected ODEIntegrator getIntegrator() {
705 return integrator;
706 }
707
708
709
710
711
712 private SpacecraftState convertToOrekitWithAdditional(final ODEStateAndDerivative os) {
713 final SpacecraftState s = convertToOrekitWithoutAdditional(os);
714 return updateAdditionalStatesAndDerivatives(s, os);
715 }
716
717
718
719
720
721
722 private SpacecraftState convertToOrekitWithoutAdditional(final ODEStateAndDerivative os) {
723 return stateMapper.mapArrayToState(os.getTime(), os.getPrimaryState(),
724 os.getPrimaryDerivative(), propagationType);
725 }
726
727
728 public interface MainStateEquations {
729
730
731
732
733
734
735
736
737
738
739
740 default void init(final SpacecraftState initialState, final AbsoluteDate target) {
741 }
742
743
744
745
746
747 double[] computeDerivatives(SpacecraftState state);
748
749 }
750
751
752 private class ConvertedMainStateEquations implements OrdinaryDifferentialEquation {
753
754
755 private final MainStateEquations main;
756
757
758
759
760 ConvertedMainStateEquations(final MainStateEquations main) {
761 this.main = main;
762 calls = 0;
763 }
764
765
766 public int getDimension() {
767 return getBasicDimension();
768 }
769
770 @Override
771 public void init(final double t0, final double[] y0, final double finalTime) {
772
773 SpacecraftState initialState = stateMapper.mapArrayToState(t0, y0, null, PropagationType.MEAN);
774 initialState = updateAdditionalData(initialState);
775 initialState = updateStatesFromAdditionalDerivativesIfKnown(initialState);
776 final AbsoluteDate target = stateMapper.mapDoubleToDate(finalTime);
777 main.init(initialState, target);
778 attitudeProviderForDerivatives = initializeAttitudeProviderForDerivatives();
779 }
780
781
782
783
784
785
786
787
788 private SpacecraftState updateStatesFromAdditionalDerivativesIfKnown(final SpacecraftState originalState) {
789 SpacecraftState updatedState = originalState;
790 final SpacecraftState storedInitialState = getInitialState();
791 final double originalTime = stateMapper.mapDateToDouble(originalState.getDate());
792 if (storedInitialState != null && stateMapper.mapDateToDouble(storedInitialState.getDate()) == originalTime) {
793 for (final AdditionalDerivativesProvider provider: additionalDerivativesProviders) {
794 final String name = provider.getName();
795 final double[] value = storedInitialState.getAdditionalState(name);
796 updatedState = updatedState.addAdditionalData(name, value);
797 }
798 }
799 return updatedState;
800 }
801
802
803 public double[] computeDerivatives(final double t, final double[] y) {
804
805
806 ++calls;
807
808
809 stateMapper.setAttitudeProvider(attitudeProviderForDerivatives);
810 SpacecraftState currentState = stateMapper.mapArrayToState(t, y, null, PropagationType.MEAN);
811 stateMapper.setAttitudeProvider(getAttitudeProvider());
812
813 currentState = updateAdditionalData(currentState);
814
815 return main.computeDerivatives(currentState);
816
817 }
818
819 }
820
821
822 private class ConvertedSecondaryStateEquations implements SecondaryODE {
823
824
825 private final int combinedDimension;
826
827
828
829 ConvertedSecondaryStateEquations() {
830 this.combinedDimension = secondaryOffsets.get(SECONDARY_DIMENSION);
831 }
832
833
834 @Override
835 public int getDimension() {
836 return combinedDimension;
837 }
838
839
840 @Override
841 public void init(final double t0, final double[] primary0,
842 final double[] secondary0, final double finalTime) {
843
844 final SpacecraftState initialState = convert(t0, primary0, null, secondary0);
845
846 final AbsoluteDate target = stateMapper.mapDoubleToDate(finalTime);
847 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
848 provider.init(initialState, target);
849 }
850
851 }
852
853
854 @Override
855 public double[] computeDerivatives(final double t, final double[] primary,
856 final double[] primaryDot, final double[] secondary) {
857
858
859
860
861 SpacecraftState updated = convert(t, primary, primaryDot, secondary);
862
863
864 final Queue<AdditionalDerivativesProvider> pending = new LinkedList<>(additionalDerivativesProviders);
865
866
867 final double[] secondaryDot = new double[combinedDimension];
868 final DoubleArrayDictionary derivativesDictionary = new DoubleArrayDictionary();
869 int yieldCount = 0;
870 while (!pending.isEmpty()) {
871 final AdditionalDerivativesProvider provider = pending.remove();
872 if (provider.yields(updated)) {
873
874
875 pending.add(provider);
876 if (++yieldCount >= pending.size()) {
877
878
879
880 break;
881 }
882 } else {
883
884 final String name = provider.getName();
885 final int offset = secondaryOffsets.get(name);
886 final int dimension = provider.getDimension();
887 final CombinedDerivatives derivatives = provider.combinedDerivatives(updated);
888 final double[] additionalPart = derivatives.getAdditionalDerivatives();
889 final double[] mainPart = derivatives.getMainStateDerivativesIncrements();
890 System.arraycopy(additionalPart, 0, secondaryDot, offset, dimension);
891 derivativesDictionary.put(name, additionalPart);
892 updated = updated.withAdditionalStatesDerivatives(derivativesDictionary);
893 if (mainPart != null) {
894
895 for (int i = 0; i < mainPart.length; ++i) {
896 primaryDot[i] += mainPart[i];
897 }
898 }
899 yieldCount = 0;
900 }
901 }
902
903 return secondaryDot;
904
905 }
906
907
908
909
910
911
912
913
914 private SpacecraftState convert(final double t, final double[] primary,
915 final double[] primaryDot, final double[] secondary) {
916
917 final SpacecraftState initialState = stateMapper.mapArrayToState(t, primary, primaryDot, PropagationType.MEAN);
918
919 final DataDictionary additionalStateDictionary = new DataDictionary();
920 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
921 final String name = provider.getName();
922 final int offset = secondaryOffsets.get(name);
923 final int dimension = provider.getDimension();
924 additionalStateDictionary.put(name, Arrays.copyOfRange(secondary, offset, offset + dimension));
925 }
926
927 return updateAdditionalData(initialState.withAdditionalData(additionalStateDictionary));
928
929 }
930
931 }
932
933
934
935
936
937 private class AdaptedEventDetector implements ODEEventDetector {
938
939
940 private final EventDetector detector;
941
942
943
944
945 private final EventHandler handler;
946
947
948 private double lastT;
949
950
951 private double lastG;
952
953
954
955
956 AdaptedEventDetector(final EventDetector detector) {
957 this.detector = detector;
958 this.handler = detector.getHandler();
959 this.lastT = Double.NaN;
960 this.lastG = Double.NaN;
961 }
962
963
964 @Override
965 public AdaptableInterval getMaxCheckInterval() {
966 return (state, isForward) -> detector.getMaxCheckInterval().currentInterval(convertToOrekitForEventFunction(state), isForward);
967 }
968
969
970 @Override
971 public int getMaxIterationCount() {
972 return detector.getMaxIterationCount();
973 }
974
975
976 @Override
977 public BracketedUnivariateSolver<UnivariateFunction> getSolver() {
978 return new BracketingNthOrderBrentSolver(0, detector.getThreshold(), 0, 5);
979 }
980
981
982 @Override
983 public void init(final ODEStateAndDerivative s0, final double t) {
984 detector.init(convertToOrekitWithAdditional(s0), stateMapper.mapDoubleToDate(t));
985 this.lastT = Double.NaN;
986 this.lastG = Double.NaN;
987 }
988
989
990 @Override
991 public void reset(final ODEStateAndDerivative intermediateState, final double finalTime) {
992 detector.reset(convertToOrekitForEventFunction(intermediateState), stateMapper.mapDoubleToDate(finalTime));
993 this.lastT = Double.NaN;
994 this.lastG = Double.NaN;
995 }
996
997
998 public double g(final ODEStateAndDerivative s) {
999 if (!Precision.equals(lastT, s.getTime(), 0)) {
1000 lastT = s.getTime();
1001 lastG = detector.g(convertToOrekitForEventFunction(s));
1002 }
1003 return lastG;
1004 }
1005
1006
1007
1008
1009
1010
1011 private SpacecraftState convertToOrekitForEventFunction(final ODEStateAndDerivative s) {
1012 if (!this.detector.dependsOnMainVariablesOnly()) {
1013 return convertToOrekitWithAdditional(s);
1014 } else {
1015
1016 stateMapper.setAttitudeProvider(getFrozenAttitudeProvider());
1017 final SpacecraftState converted = convertToOrekitWithoutAdditional(s);
1018 stateMapper.setAttitudeProvider(getAttitudeProvider());
1019 return converted;
1020 }
1021 }
1022
1023
1024 public ODEEventHandler getHandler() {
1025
1026 return new ODEEventHandler() {
1027
1028
1029 public Action eventOccurred(final ODEStateAndDerivative s, final ODEEventDetector d, final boolean increasing) {
1030 return handler.eventOccurred(convertToOrekitWithAdditional(s), detector, increasing);
1031 }
1032
1033
1034 @Override
1035 public ODEState resetState(final ODEEventDetector d, final ODEStateAndDerivative s) {
1036
1037 final SpacecraftState oldState = convertToOrekitWithAdditional(s);
1038 final SpacecraftState newState = handler.resetState(detector, oldState);
1039 stateChanged(newState);
1040
1041
1042 final double[] primary = new double[s.getPrimaryStateDimension()];
1043 stateMapper.mapStateToArray(newState, primary, null);
1044
1045
1046 final double[][] secondary = new double[1][secondaryOffsets.get(SECONDARY_DIMENSION)];
1047 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
1048 final String name = provider.getName();
1049 final int offset = secondaryOffsets.get(name);
1050 final int dimension = provider.getDimension();
1051 System.arraycopy(newState.getAdditionalState(name), 0, secondary[0], offset, dimension);
1052 }
1053
1054 return new ODEState(newState.getDate().durationFrom(getStartDate()),
1055 primary, secondary);
1056
1057 }
1058
1059 };
1060 }
1061
1062 }
1063
1064
1065
1066
1067
1068 private class AdaptedStepHandler implements ODEStepHandler {
1069
1070
1071 private final OrekitStepHandler handler;
1072
1073
1074
1075
1076 AdaptedStepHandler(final OrekitStepHandler handler) {
1077 this.handler = handler;
1078 }
1079
1080
1081 @Override
1082 public void init(final ODEStateAndDerivative s0, final double t) {
1083 handler.init(convertToOrekitWithAdditional(s0), stateMapper.mapDoubleToDate(t));
1084 }
1085
1086
1087 @Override
1088 public void handleStep(final ODEStateInterpolator interpolator) {
1089 handler.handleStep(new AdaptedStepInterpolator(interpolator));
1090 }
1091
1092
1093 @Override
1094 public void finish(final ODEStateAndDerivative finalState) {
1095 handler.finish(convertToOrekitWithAdditional(finalState));
1096 }
1097
1098 }
1099
1100
1101
1102
1103
1104 private class AdaptedStepInterpolator implements OrekitStepInterpolator {
1105
1106
1107 private final ODEStateInterpolator mathInterpolator;
1108
1109
1110
1111
1112 AdaptedStepInterpolator(final ODEStateInterpolator mathInterpolator) {
1113 this.mathInterpolator = mathInterpolator;
1114 }
1115
1116
1117 @Override
1118 public SpacecraftState getPreviousState() {
1119 return convertToOrekitWithAdditional(mathInterpolator.getPreviousState());
1120 }
1121
1122
1123 @Override
1124 public boolean isPreviousStateInterpolated() {
1125 return mathInterpolator.isPreviousStateInterpolated();
1126 }
1127
1128
1129 @Override
1130 public SpacecraftState getCurrentState() {
1131 return convertToOrekitWithAdditional(mathInterpolator.getCurrentState());
1132 }
1133
1134
1135 @Override
1136 public boolean isCurrentStateInterpolated() {
1137 return mathInterpolator.isCurrentStateInterpolated();
1138 }
1139
1140
1141 @Override
1142 public SpacecraftState getInterpolatedState(final AbsoluteDate date) {
1143 return convertToOrekitWithAdditional(mathInterpolator.getInterpolatedState(date.durationFrom(stateMapper.getReferenceDate())));
1144 }
1145
1146
1147 @Override
1148 public boolean isForward() {
1149 return mathInterpolator.isForward();
1150 }
1151
1152
1153 @Override
1154 public AdaptedStepInterpolator restrictStep(final SpacecraftState newPreviousState,
1155 final SpacecraftState newCurrentState) {
1156 try {
1157 final AbstractODEStateInterpolator aosi = (AbstractODEStateInterpolator) mathInterpolator;
1158 return new AdaptedStepInterpolator(aosi.restrictStep(convertFromOrekit(newPreviousState),
1159 convertFromOrekit(newCurrentState)));
1160 } catch (ClassCastException cce) {
1161
1162 throw new OrekitInternalError(cce);
1163 }
1164 }
1165
1166
1167
1168
1169
1170
1171 private ODEStateAndDerivative convertFromOrekit(final SpacecraftState state) {
1172
1173
1174 final double[] primary = new double[getBasicDimension()];
1175 final double[] primaryDot = new double[getBasicDimension()];
1176 stateMapper.mapStateToArray(state, primary, primaryDot);
1177
1178
1179 final double[][] secondary = secondary(state);
1180 final double[][] secondaryDerivative = secondaryDerivative(state);
1181
1182 return new ODEStateAndDerivative(stateMapper.mapDateToDouble(state.getDate()),
1183 primary, primaryDot,
1184 secondary, secondaryDerivative);
1185
1186 }
1187
1188
1189
1190
1191
1192
1193 private double[][] secondaryDerivative(final SpacecraftState state) {
1194
1195 if (secondaryOffsets.isEmpty()) {
1196 return null;
1197 }
1198
1199 final double[][] secondaryDerivative = new double[1][secondaryOffsets.get(SECONDARY_DIMENSION)];
1200 for (final AdditionalDerivativesProvider provider : additionalDerivativesProviders) {
1201 final String name = provider.getName();
1202 final int offset = secondaryOffsets.get(name);
1203 final double[] additionalDerivative = state.getAdditionalStateDerivative(name);
1204 System.arraycopy(additionalDerivative, 0, secondaryDerivative[0], offset, additionalDerivative.length);
1205 }
1206
1207 return secondaryDerivative;
1208
1209 }
1210 }
1211
1212
1213
1214
1215 private class StoringStepHandler implements ODEStepHandler, EphemerisGenerator {
1216
1217
1218 private DenseOutputModel model;
1219
1220
1221 private AbsoluteDate endDate;
1222
1223
1224 private BoundedPropagator ephemeris;
1225
1226
1227 private ODEStateInterpolator lastInterpolator;
1228
1229
1230
1231
1232 public void setEndDate(final AbsoluteDate endDate) {
1233 this.endDate = endDate;
1234 }
1235
1236
1237 @Override
1238 public void init(final ODEStateAndDerivative s0, final double t) {
1239
1240 this.model = new DenseOutputModel();
1241 model.init(s0, t);
1242
1243
1244 this.ephemeris = null;
1245
1246 this.lastInterpolator = null;
1247
1248 }
1249
1250
1251 @Override
1252 public BoundedPropagator getGeneratedEphemeris() {
1253
1254 buildEphemeris();
1255 return ephemeris;
1256 }
1257
1258
1259 @Override
1260 public void handleStep(final ODEStateInterpolator interpolator) {
1261 model.handleStep(interpolator);
1262 lastInterpolator = interpolator;
1263 }
1264
1265
1266 @Override
1267 public void finish(final ODEStateAndDerivative finalState) {
1268 buildEphemeris();
1269 }
1270
1271
1272
1273
1274
1275 private void buildEphemeris() {
1276
1277
1278
1279
1280
1281 model.finish(lastInterpolator.getCurrentState());
1282
1283
1284 final double tI = model.getInitialTime();
1285 final double tF = model.getFinalTime();
1286
1287 final AbsoluteDate startDate =
1288 stateMapper.mapDoubleToDate(tI);
1289 final AbsoluteDate finalDate =
1290 stateMapper.mapDoubleToDate(tF, this.endDate);
1291 final AbsoluteDate minDate;
1292 final AbsoluteDate maxDate;
1293 if (tF < tI) {
1294 minDate = finalDate;
1295 maxDate = startDate;
1296 } else {
1297 minDate = startDate;
1298 maxDate = finalDate;
1299 }
1300
1301
1302 final DataDictionary unmanaged = new DataDictionary();
1303 for (final DataDictionary.Entry initial : getInitialState().getAdditionalDataValues().getData()) {
1304 if (!AbstractIntegratedPropagator.this.isAdditionalDataManaged(initial.getKey())) {
1305
1306
1307 unmanaged.put(initial.getKey(), initial.getValue());
1308 }
1309 }
1310
1311
1312 final String[] names = new String[additionalDerivativesProviders.size()];
1313 final int[] dimensions = new int[additionalDerivativesProviders.size()];
1314 for (int i = 0; i < names.length; ++i) {
1315 names[i] = additionalDerivativesProviders.get(i).getName();
1316 dimensions[i] = additionalDerivativesProviders.get(i).getDimension();
1317 }
1318
1319
1320 ephemeris = new IntegratedEphemeris(startDate, minDate, maxDate,
1321 stateMapper, getAttitudeProvider(), propagationType, model,
1322 unmanaged, getAdditionalDataProviders(),
1323 names, dimensions);
1324
1325 }
1326
1327 }
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339 private static class IntegratorResetter implements AutoCloseable {
1340
1341
1342 private final ODEIntegrator integrator;
1343
1344
1345 private final List<ODEEventDetector> detectors;
1346
1347
1348 private final List<ODEStepHandler> stepHandlers;
1349
1350
1351
1352
1353 IntegratorResetter(final ODEIntegrator integrator) {
1354 this.integrator = integrator;
1355 this.detectors = new ArrayList<>(integrator.getEventDetectors());
1356 this.stepHandlers = new ArrayList<>(integrator.getStepHandlers());
1357 }
1358
1359
1360
1361
1362
1363
1364 @Override
1365 public void close() {
1366
1367
1368 integrator.clearEventDetectors();
1369 detectors.forEach(integrator::addEventDetector);
1370
1371
1372 integrator.clearStepHandlers();
1373 stepHandlers.forEach(integrator::addStepHandler);
1374
1375 }
1376
1377 }
1378
1379 }