1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.LinkedList;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Queue;
26
27 import org.hipparchus.CalculusFieldElement;
28 import org.hipparchus.Field;
29 import org.orekit.attitudes.AttitudeProvider;
30 import org.orekit.errors.OrekitException;
31 import org.orekit.errors.OrekitMessages;
32 import org.orekit.frames.Frame;
33 import org.orekit.propagation.sampling.FieldStepHandlerMultiplexer;
34 import org.orekit.time.FieldAbsoluteDate;
35 import org.orekit.utils.FieldDataDictionary;
36 import org.orekit.utils.FieldTimeSpanMap;
37
38
39
40
41
42
43
44
45
46
47 public abstract class FieldAbstractPropagator<T extends CalculusFieldElement<T>> implements FieldPropagator<T> {
48
49
50 private final FieldStepHandlerMultiplexer<T> multiplexer;
51
52
53 private FieldAbsoluteDate<T> startDate;
54
55
56 private AttitudeProvider attitudeProvider;
57
58
59 private final List<FieldAdditionalDataProvider<?, T>> additionalDataProviders;
60
61
62 private final Map<String, FieldTimeSpanMap<Object, T>> unmanagedStates;
63
64
65 private final Field<T> field;
66
67
68 private FieldSpacecraftState<T> initialState;
69
70
71
72
73 protected FieldAbstractPropagator(final Field<T> field) {
74 this.field = field;
75 multiplexer = new FieldStepHandlerMultiplexer<>();
76 additionalDataProviders = new ArrayList<>();
77 unmanagedStates = new HashMap<>();
78 }
79
80
81
82
83 protected void setStartDate(final FieldAbsoluteDate<T> startDate) {
84 this.startDate = startDate;
85 }
86
87
88
89
90 protected FieldAbsoluteDate<T> getStartDate() {
91 return startDate;
92 }
93
94
95 public AttitudeProvider getAttitudeProvider() {
96 return attitudeProvider;
97 }
98
99
100 public void setAttitudeProvider(final AttitudeProvider attitudeProvider) {
101 this.attitudeProvider = attitudeProvider;
102 }
103
104
105
106 public Field<T> getField() {
107 return field;
108 }
109
110
111 public FieldSpacecraftState<T> getInitialState() {
112 return initialState;
113 }
114
115
116 public Frame getFrame() {
117 return initialState.getFrame();
118 }
119
120
121 public void resetInitialState(final FieldSpacecraftState<T> state) {
122 initialState = state;
123 setStartDate(state.getDate());
124 }
125
126
127 public FieldStepHandlerMultiplexer<T> getMultiplexer() {
128 return multiplexer;
129 }
130
131
132 public void addAdditionalDataProvider(final FieldAdditionalDataProvider<?, T> additionalDataProvider) {
133
134
135 if (isAdditionalDataManaged(additionalDataProvider.getName())) {
136
137 throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
138 additionalDataProvider.getName());
139 }
140
141
142 additionalDataProviders.add(additionalDataProvider);
143
144 }
145
146
147 public List<FieldAdditionalDataProvider<?, T>> getAdditionalDataProviders() {
148 return Collections.unmodifiableList(additionalDataProviders);
149 }
150
151
152
153
154
155
156 public void removeAdditionalDataProvider(final String name) {
157 additionalDataProviders.removeIf(provider -> provider.getName().equals(name));
158 }
159
160
161
162
163
164
165 protected FieldSpacecraftState<T> updateUnmanagedData(final FieldSpacecraftState<T> original) {
166
167
168
169 FieldSpacecraftState<T> updated = original;
170
171
172 for (final Map.Entry<String, FieldTimeSpanMap<Object, T>> entry : unmanagedStates.entrySet()) {
173 updated = updated.addAdditionalData(entry.getKey(),
174 entry.getValue().get(original.getDate()));
175 }
176
177 return updated;
178
179 }
180
181
182
183
184
185
186 public FieldSpacecraftState<T> updateAdditionalData(final FieldSpacecraftState<T> original) {
187
188
189 FieldSpacecraftState<T> updated = updateUnmanagedData(original);
190
191
192 final Queue<FieldAdditionalDataProvider<?, T>> pending = new LinkedList<>(getAdditionalDataProviders());
193
194
195 int yieldCount = 0;
196 while (!pending.isEmpty()) {
197 final FieldAdditionalDataProvider<?, T> provider = pending.remove();
198 if (provider.yields(updated)) {
199
200
201 pending.add(provider);
202 if (++yieldCount >= pending.size()) {
203
204
205
206 break;
207 }
208 } else {
209
210 updated = provider.update(updated);
211 yieldCount = 0;
212 }
213 }
214
215 return updated;
216
217 }
218
219
220
221
222
223
224 protected void initializeAdditionalData(final FieldAbsoluteDate<T> target) {
225 for (final FieldAdditionalDataProvider<?, T> provider : additionalDataProviders) {
226 provider.init(initialState, target);
227 }
228 }
229
230
231 public boolean isAdditionalDataManaged(final String name) {
232 for (final FieldAdditionalDataProvider<?, T> provider : additionalDataProviders) {
233 if (provider.getName().equals(name)) {
234 return true;
235 }
236 }
237 return false;
238 }
239
240
241 public String[] getManagedAdditionalData() {
242 final String[] managed = new String[additionalDataProviders.size()];
243 for (int i = 0; i < managed.length; ++i) {
244 managed[i] = additionalDataProviders.get(i).getName();
245 }
246 return managed;
247 }
248
249
250 public FieldSpacecraftState<T> propagate(final FieldAbsoluteDate<T> target) {
251 if (startDate == null) {
252 startDate = getInitialState().getDate();
253 }
254 return propagate(startDate, target);
255 }
256
257
258
259
260 protected void initializePropagation() {
261
262 unmanagedStates.clear();
263
264 if (initialState != null) {
265
266
267
268 for (final FieldDataDictionary<T>.Entry initial : initialState.getAdditionalDataValues().getData()) {
269 if (!isAdditionalDataManaged(initial.getKey())) {
270
271
272 unmanagedStates.put(initial.getKey(),
273 new FieldTimeSpanMap<>(initial.getValue(),
274 initialState.getDate().getField()));
275 }
276 }
277 }
278 }
279
280
281
282
283 protected void stateChanged(final FieldSpacecraftState<T> state) {
284 final FieldAbsoluteDate<T> date = state.getDate();
285 final boolean forward = date.durationFrom(getStartDate()).getReal() >= 0.0;
286 for (final FieldDataDictionary<T>.Entry changed : state.getAdditionalDataValues().getData()) {
287 final FieldTimeSpanMap<Object, T> tsm = unmanagedStates.get(changed.getKey());
288 if (tsm != null) {
289
290 if (forward) {
291 tsm.addValidAfter(changed.getValue(), date, false);
292 } else {
293 tsm.addValidBefore(changed.getValue(), date, false);
294 }
295 }
296 }
297 }
298
299 }