1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.time.clocks;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.function.DoubleFunction;
24
25 import org.hipparchus.CalculusFieldElement;
26 import org.hipparchus.Field;
27 import org.hipparchus.analysis.differentiation.Gradient;
28 import org.orekit.errors.OrekitException;
29 import org.orekit.errors.OrekitMessages;
30 import org.orekit.time.AbsoluteDate;
31 import org.orekit.utils.drivers.ParameterDriver;
32 import org.orekit.utils.TimeSpanMap;
33
34
35
36
37
38
39
40 public class AggregatedClockModel implements ClockModel {
41
42
43 private final TimeSpanMap<ClockModel> models;
44
45
46
47
48 private final Map<Field<? extends CalculusFieldElement<?>>, AggregatedFieldClockModel<?>> fieldModels;
49
50
51
52
53 public AggregatedClockModel(final TimeSpanMap<ClockModel> models) {
54
55 try {
56
57 models.getFirstNonNullSpan();
58 } catch (OrekitException oe) {
59 throw new OrekitException(oe, OrekitMessages.NOT_ENOUGH_DATA, 0);
60 }
61
62 this.models = models;
63 this.fieldModels = new HashMap<>();
64 }
65
66
67
68
69 public TimeSpanMap<ClockModel> getModels() {
70 return models;
71 }
72
73
74 @Override
75 public AbsoluteDate getValidityStart() {
76 return models.getFirstNonNullSpan().getStart();
77 }
78
79
80 @Override
81 public AbsoluteDate getValidityEnd() {
82 return models.getLastNonNullSpan().getEnd();
83 }
84
85
86 @Override
87 public List<ParameterDriver> getParametersDrivers() {
88 final List<ParameterDriver> drivers = new ArrayList<>();
89 models.forEach(model -> drivers.addAll(model.getParametersDrivers()));
90 return drivers;
91 }
92
93
94 @Override
95 public ClockOffset getOffset(final AbsoluteDate date) {
96 return getModel(date).getOffset(date);
97 }
98
99
100 @Override
101 @SuppressWarnings("unchecked")
102 public <T extends CalculusFieldElement<T>> AggregatedFieldClockModel<T> toField(final DoubleFunction<T> converter) {
103
104 return (AggregatedFieldClockModel<T>) fieldModels.computeIfAbsent(converter.apply(0.0).getField(),
105 f -> buildFieldModel(converter));
106 }
107
108
109
110
111
112
113
114
115 private <T extends CalculusFieldElement<T>> AggregatedFieldClockModel<T> buildFieldModel(final DoubleFunction<T> converter) {
116 final TimeSpanMap<FieldClockModel<T>> fieldMap = new TimeSpanMap<>(null);
117 for (TimeSpanMap.Span<ClockModel> span = models.getFirstSpan(); span != null; span = span.next()) {
118 fieldMap.addValidBetween(span.getData() == null ? null : span.getData().toField(converter),
119 span.getStart(), span.getEnd());
120 }
121 return new AggregatedFieldClockModel<>(fieldMap);
122 }
123
124
125 @Override
126 public AggregatedFieldClockModel<Gradient> toGradient(final int freeParameters, final Map<String, Integer> indices) {
127 final TimeSpanMap<FieldClockModel<Gradient>> fieldMap = new TimeSpanMap<>(null);
128 for (TimeSpanMap.Span<ClockModel> span = models.getFirstSpan(); span != null; span = span.next()) {
129 fieldMap.addValidBetween(span.getData() == null ?
130 null :
131 span.getData().toGradient(freeParameters, indices),
132 span.getStart(), span.getEnd());
133 }
134 return new AggregatedFieldClockModel<>(fieldMap);
135 }
136
137
138
139
140
141
142
143 private ClockModel getModel(final AbsoluteDate date) {
144 final ClockModel clockModel = models.get(date);
145 if (clockModel == null) {
146
147
148 throw new OrekitException(OrekitMessages.NO_DATA_GENERATED, date);
149 }
150 return clockModel;
151 }
152
153 }