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