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 protected FieldSpacecraftState<T> updateUnmanagedData(final FieldSpacecraftState<T> original) {
157
158
159
160 FieldSpacecraftState<T> updated = original;
161
162
163 for (final Map.Entry<String, FieldTimeSpanMap<Object, T>> entry : unmanagedStates.entrySet()) {
164 updated = updated.addAdditionalData(entry.getKey(),
165 entry.getValue().get(original.getDate()));
166 }
167
168 return updated;
169
170 }
171
172
173
174
175
176
177 public FieldSpacecraftState<T> updateAdditionalData(final FieldSpacecraftState<T> original) {
178
179
180 FieldSpacecraftState<T> updated = updateUnmanagedData(original);
181
182
183 final Queue<FieldAdditionalDataProvider<?, T>> pending = new LinkedList<>(getAdditionalDataProviders());
184
185
186 int yieldCount = 0;
187 while (!pending.isEmpty()) {
188 final FieldAdditionalDataProvider<?, T> provider = pending.remove();
189 if (provider.yields(updated)) {
190
191
192 pending.add(provider);
193 if (++yieldCount >= pending.size()) {
194
195
196
197 break;
198 }
199 } else {
200
201 updated = provider.update(updated);
202 yieldCount = 0;
203 }
204 }
205
206 return updated;
207
208 }
209
210
211
212
213
214
215 protected void initializeAdditionalData(final FieldAbsoluteDate<T> target) {
216 for (final FieldAdditionalDataProvider<?, T> provider : additionalDataProviders) {
217 provider.init(initialState, target);
218 }
219 }
220
221
222 public boolean isAdditionalDataManaged(final String name) {
223 for (final FieldAdditionalDataProvider<?, T> provider : additionalDataProviders) {
224 if (provider.getName().equals(name)) {
225 return true;
226 }
227 }
228 return false;
229 }
230
231
232 public String[] getManagedAdditionalData() {
233 final String[] managed = new String[additionalDataProviders.size()];
234 for (int i = 0; i < managed.length; ++i) {
235 managed[i] = additionalDataProviders.get(i).getName();
236 }
237 return managed;
238 }
239
240
241 public FieldSpacecraftState<T> propagate(final FieldAbsoluteDate<T> target) {
242 if (startDate == null) {
243 startDate = getInitialState().getDate();
244 }
245 return propagate(startDate, target);
246 }
247
248
249
250
251 protected void initializePropagation() {
252
253 unmanagedStates.clear();
254
255 if (initialState != null) {
256
257
258
259 for (final FieldDataDictionary<T>.Entry initial : initialState.getAdditionalDataValues().getData()) {
260 if (!isAdditionalDataManaged(initial.getKey())) {
261
262
263 unmanagedStates.put(initial.getKey(),
264 new FieldTimeSpanMap<>(initial.getValue(),
265 initialState.getDate().getField()));
266 }
267 }
268 }
269 }
270
271
272
273
274 protected void stateChanged(final FieldSpacecraftState<T> state) {
275 final FieldAbsoluteDate<T> date = state.getDate();
276 final boolean forward = date.durationFrom(getStartDate()).getReal() >= 0.0;
277 for (final FieldDataDictionary<T>.Entry changed : state.getAdditionalDataValues().getData()) {
278 final FieldTimeSpanMap<Object, T> tsm = unmanagedStates.get(changed.getKey());
279 if (tsm != null) {
280
281 if (forward) {
282 tsm.addValidAfter(changed.getValue(), date);
283 } else {
284 tsm.addValidBefore(changed.getValue(), date);
285 }
286 }
287 }
288 }
289
290 }