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