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 @Override
112 public FieldSpacecraftState<T> getBaseInitialState() {
113 return initialState;
114 }
115
116
117 @Override
118 public FieldSpacecraftState<T> getInitialState() {
119 return updateAdditionalData(getBaseInitialState());
120 }
121
122
123 public Frame getFrame() {
124 return initialState.getFrame();
125 }
126
127
128 public void resetInitialState(final FieldSpacecraftState<T> state) {
129 initialState = state;
130 setStartDate(state.getDate());
131 }
132
133
134 public FieldStepHandlerMultiplexer<T> getMultiplexer() {
135 return multiplexer;
136 }
137
138
139 public void addAdditionalDataProvider(final FieldAdditionalDataProvider<?, T> additionalDataProvider) {
140
141
142 if (isAdditionalDataManaged(additionalDataProvider.getName())) {
143
144 throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
145 additionalDataProvider.getName());
146 }
147
148
149 additionalDataProviders.add(additionalDataProvider);
150
151 }
152
153
154 public List<FieldAdditionalDataProvider<?, T>> getAdditionalDataProviders() {
155 return Collections.unmodifiableList(additionalDataProviders);
156 }
157
158
159
160
161
162
163 public void removeAdditionalDataProvider(final String name) {
164 additionalDataProviders.removeIf(provider -> provider.getName().equals(name));
165 }
166
167
168
169
170
171
172 protected FieldSpacecraftState<T> updateUnmanagedData(final FieldSpacecraftState<T> original) {
173
174
175
176 FieldSpacecraftState<T> updated = original;
177
178
179 for (final Map.Entry<String, FieldTimeSpanMap<Object, T>> entry : unmanagedStates.entrySet()) {
180 updated = updated.addAdditionalData(entry.getKey(),
181 entry.getValue().get(original.getDate()));
182 }
183
184 return updated;
185
186 }
187
188
189
190
191
192
193 public FieldSpacecraftState<T> updateAdditionalData(final FieldSpacecraftState<T> original) {
194
195
196 FieldSpacecraftState<T> updated = updateUnmanagedData(original);
197
198
199 final Queue<FieldAdditionalDataProvider<?, T>> pending = new LinkedList<>(getAdditionalDataProviders());
200
201
202 int yieldCount = 0;
203 while (!pending.isEmpty()) {
204 final FieldAdditionalDataProvider<?, T> provider = pending.remove();
205 if (provider.yields(updated)) {
206
207
208 pending.add(provider);
209 if (++yieldCount >= pending.size()) {
210
211
212
213 break;
214 }
215 } else {
216
217 updated = provider.update(updated);
218 yieldCount = 0;
219 }
220 }
221
222 return updated;
223
224 }
225
226
227
228
229
230
231 protected void initializeAdditionalData(final FieldAbsoluteDate<T> target) {
232 for (final FieldAdditionalDataProvider<?, T> provider : additionalDataProviders) {
233 provider.init(initialState, target);
234 }
235 }
236
237
238 public boolean isAdditionalDataManaged(final String name) {
239 for (final FieldAdditionalDataProvider<?, T> provider : additionalDataProviders) {
240 if (provider.getName().equals(name)) {
241 return true;
242 }
243 }
244 return false;
245 }
246
247
248 public String[] getManagedAdditionalData() {
249 final String[] managed = new String[additionalDataProviders.size()];
250 for (int i = 0; i < managed.length; ++i) {
251 managed[i] = additionalDataProviders.get(i).getName();
252 }
253 return managed;
254 }
255
256
257 public FieldSpacecraftState<T> propagate(final FieldAbsoluteDate<T> target) {
258 if (startDate == null) {
259 startDate = getInitialState().getDate();
260 }
261 return propagate(startDate, target);
262 }
263
264
265
266
267 protected void initializePropagation() {
268
269 unmanagedStates.clear();
270
271 if (initialState != null) {
272
273
274
275 for (final FieldDataDictionary<T>.Entry initial : initialState.getAdditionalDataValues().getData()) {
276 if (!isAdditionalDataManaged(initial.getKey())) {
277
278
279 unmanagedStates.put(initial.getKey(),
280 new FieldTimeSpanMap<>(initial.getValue(),
281 initialState.getDate().getField()));
282 }
283 }
284 }
285 }
286
287
288
289
290 protected void stateChanged(final FieldSpacecraftState<T> state) {
291 final FieldAbsoluteDate<T> date = state.getDate();
292 final boolean forward = date.durationFrom(getStartDate()).getReal() >= 0.0;
293 for (final FieldDataDictionary<T>.Entry changed : state.getAdditionalDataValues().getData()) {
294 final FieldTimeSpanMap<Object, T> tsm = unmanagedStates.get(changed.getKey());
295 if (tsm != null) {
296
297 if (forward) {
298 tsm.addValidAfter(changed.getValue(), date, false);
299 } else {
300 tsm.addValidBefore(changed.getValue(), date, false);
301 }
302 }
303 }
304 }
305
306 }