1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.semianalytical.dsst;
18
19 import org.hipparchus.analysis.differentiation.Gradient;
20 import org.hipparchus.exception.LocalizedCoreFormats;
21 import org.hipparchus.linear.MatrixUtils;
22 import org.hipparchus.linear.RealMatrix;
23 import org.orekit.attitudes.AttitudeProvider;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.propagation.FieldSpacecraftState;
26 import org.orekit.propagation.PropagationType;
27 import org.orekit.propagation.SpacecraftState;
28 import org.orekit.propagation.integration.AdditionalDerivativesProvider;
29 import org.orekit.propagation.integration.CombinedDerivatives;
30 import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
31 import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
32 import org.orekit.time.AbsoluteDate;
33 import org.orekit.utils.DoubleArrayDictionary;
34 import org.orekit.utils.drivers.ParameterDriver;
35
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39
40
41
42
43
44 class DSSTStateTransitionMatrixGenerator implements AdditionalDerivativesProvider {
45
46
47 private static final int SPACE_DIMENSION = 3;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 private static final int I = 1;
63
64
65 public static final int STATE_DIMENSION = 2 * SPACE_DIMENSION;
66
67
68 private final String stmName;
69
70
71 private final List<DSSTForceModel> forceModels;
72
73
74 private final AttitudeProvider attitudeProvider;
75
76
77 private final Map<String, DSSTPartialsObserver> partialsObservers;
78
79
80 private final PropagationType propagationType;
81
82
83
84
85
86
87
88 DSSTStateTransitionMatrixGenerator(final String stmName,
89 final List<DSSTForceModel> forceModels,
90 final AttitudeProvider attitudeProvider,
91 final PropagationType propagationType) {
92 this.stmName = stmName;
93 this.forceModels = forceModels;
94 this.attitudeProvider = attitudeProvider;
95 this.propagationType = propagationType;
96 this.partialsObservers = new HashMap<>();
97 }
98
99
100
101
102
103
104
105
106
107
108 void addObserver(final String name, final DSSTPartialsObserver observer) {
109 partialsObservers.put(name, observer);
110 }
111
112
113 @Override
114 public String getName() {
115 return stmName;
116 }
117
118
119 @Override
120 public int getDimension() {
121 return STATE_DIMENSION * STATE_DIMENSION;
122 }
123
124 @Override
125 @SuppressWarnings("unchecked")
126 public void init(final SpacecraftState initialState, final AbsoluteDate target) {
127
128
129
130
131
132
133
134 final DSSTGradientConverter converter =
135 new DSSTGradientConverter(initialState, attitudeProvider);
136
137
138 final PropagationType type = propagationType;
139
140
141 for (final DSSTForceModel forceModel : forceModels) {
142 final FieldSpacecraftState<Gradient> dsState = converter.getState(forceModel);
143 final Gradient[] parameters = converter.getParametersAtStateDate(dsState, forceModel);
144 final FieldAuxiliaryElements<Gradient> auxiliaryElements = new FieldAuxiliaryElements<>(dsState.getOrbit(), I);
145 forceModel.initializeShortPeriodTerms(auxiliaryElements, type, parameters);
146 }
147
148
149 if (type == PropagationType.OSCULATING) {
150
151 for (DSSTForceModel forceModel : forceModels) {
152 final FieldSpacecraftState<Gradient> dsState = converter.getState(forceModel);
153 final Gradient[] parameters = converter.getParametersAtStateDate(dsState, forceModel);
154 forceModel.updateShortPeriodTerms(parameters, dsState);
155 }
156 }
157
158 }
159
160
161 @Override
162 public boolean yields(final SpacecraftState state) {
163 return !state.hasAdditionalData(getName());
164 }
165
166
167
168
169
170
171
172
173
174
175 SpacecraftState setInitialStateTransitionMatrix(final SpacecraftState state, final RealMatrix dYdY0) {
176
177 if (dYdY0 != null) {
178 if (dYdY0.getRowDimension() != STATE_DIMENSION ||
179 dYdY0.getColumnDimension() != STATE_DIMENSION) {
180 throw new OrekitException(LocalizedCoreFormats.DIMENSIONS_MISMATCH_2x2,
181 dYdY0.getRowDimension(), dYdY0.getColumnDimension(),
182 STATE_DIMENSION, STATE_DIMENSION);
183 }
184 }
185
186
187 final double[] flat = new double[STATE_DIMENSION * STATE_DIMENSION];
188 int k = 0;
189 for (int i = 0; i < STATE_DIMENSION; ++i) {
190 for (int j = 0; j < STATE_DIMENSION; ++j) {
191 flat[k++] = dYdY0.getEntry(i, j);
192 }
193 }
194
195
196 return state.addAdditionalData(stmName, flat);
197
198 }
199
200
201 public CombinedDerivatives combinedDerivatives(final SpacecraftState state) {
202
203 final double[] p = state.getAdditionalState(getName());
204 final double[] res = new double[p.length];
205
206
207 final RealMatrix factor = computePartials(state);
208 int index = 0;
209 for (int i = 0; i < STATE_DIMENSION; ++i) {
210 for (int j = 0; j < STATE_DIMENSION; ++j) {
211 double sum = 0;
212 for (int k = 0; k < STATE_DIMENSION; ++k) {
213 sum += factor.getEntry(i, k) * p[j + k * STATE_DIMENSION];
214 }
215 res[index++] = sum;
216 }
217 }
218
219 return new CombinedDerivatives(res, null);
220
221 }
222
223
224
225
226
227 private RealMatrix computePartials(final SpacecraftState state) {
228
229
230 final RealMatrix factor = MatrixUtils.createRealMatrix(STATE_DIMENSION, STATE_DIMENSION);
231 final DoubleArrayDictionary meanElementsPartials = new DoubleArrayDictionary();
232 final DSSTGradientConverter converter = new DSSTGradientConverter(state, attitudeProvider);
233
234
235 for (final DSSTForceModel forceModel : forceModels) {
236
237 final FieldSpacecraftState<Gradient> dsState = converter.getState(forceModel);
238 final Gradient[] parameters = converter.getParametersAtStateDate(dsState, forceModel);
239 final FieldAuxiliaryElements<Gradient> auxiliaryElements = new FieldAuxiliaryElements<>(dsState.getOrbit(), I);
240
241 final Gradient[] meanElementRate = forceModel.getMeanElementRate(dsState, auxiliaryElements, parameters);
242 final double[] derivativesA = meanElementRate[0].getGradient();
243 final double[] derivativesEx = meanElementRate[1].getGradient();
244 final double[] derivativesEy = meanElementRate[2].getGradient();
245 final double[] derivativesHx = meanElementRate[3].getGradient();
246 final double[] derivativesHy = meanElementRate[4].getGradient();
247 final double[] derivativesL = meanElementRate[5].getGradient();
248
249
250 addToRow(derivativesA, 0, factor);
251 addToRow(derivativesEx, 1, factor);
252 addToRow(derivativesEy, 2, factor);
253 addToRow(derivativesHx, 3, factor);
254 addToRow(derivativesHy, 4, factor);
255 addToRow(derivativesL, 5, factor);
256
257
258 int paramsIndex = converter.getFreeStateParameters();
259 for (ParameterDriver driver : forceModel.getParametersDrivers()) {
260 if (driver.isSelected()) {
261
262
263 DoubleArrayDictionary.Entry entry = meanElementsPartials.getEntry(driver.getName());
264 if (entry == null) {
265
266 meanElementsPartials.put(driver.getName(), new double[STATE_DIMENSION]);
267 entry = meanElementsPartials.getEntry(driver.getName());
268 }
269
270
271 entry.increment(new double[] {
272 derivativesA[paramsIndex], derivativesEx[paramsIndex], derivativesEy[paramsIndex],
273 derivativesHx[paramsIndex], derivativesHy[paramsIndex], derivativesL[paramsIndex]
274 });
275 ++paramsIndex;
276
277 }
278 }
279
280 }
281
282
283 for (Map.Entry<String, DSSTPartialsObserver> observersEntry : partialsObservers.entrySet()) {
284 final DoubleArrayDictionary.Entry entry = meanElementsPartials.getEntry(observersEntry.getKey());
285 observersEntry.getValue().partialsComputed(state, factor, entry == null ? new double[STATE_DIMENSION] : entry.getValue());
286 }
287
288 return factor;
289
290 }
291
292
293
294
295
296
297 private void addToRow(final double[] derivatives, final int index, final RealMatrix factor) {
298 for (int i = 0; i < 6; i++) {
299 factor.addToEntry(index, i, derivatives[i]);
300 }
301 }
302
303
304 @FunctionalInterface
305 public interface DSSTPartialsObserver {
306
307
308
309
310
311
312
313 void partialsComputed(SpacecraftState state, RealMatrix factor, double[] meanElementsPartials);
314
315 }
316
317 }
318