1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.analytical;
18
19 import java.util.Arrays;
20 import java.util.List;
21
22 import org.hipparchus.analysis.differentiation.Gradient;
23 import org.hipparchus.linear.MatrixUtils;
24 import org.hipparchus.linear.RealMatrix;
25 import org.orekit.orbits.FieldOrbit;
26 import org.orekit.orbits.OrbitType;
27 import org.orekit.orbits.PositionAngleType;
28 import org.orekit.propagation.AbstractMatricesHarvester;
29 import org.orekit.propagation.AdditionalDataProvider;
30 import org.orekit.propagation.FieldSpacecraftState;
31 import org.orekit.propagation.SpacecraftState;
32 import org.orekit.time.AbsoluteDate;
33 import org.orekit.time.FieldAbsoluteDate;
34 import org.orekit.utils.DoubleArrayDictionary;
35 import org.orekit.utils.FieldPVCoordinates;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.TimeSpanMap;
38 import org.orekit.utils.TimeSpanMap.Span;
39
40
41
42
43
44
45
46
47 public abstract class AbstractAnalyticalMatricesHarvester extends AbstractMatricesHarvester implements AdditionalDataProvider<double[]> {
48
49
50 private List<String> columnsNames;
51
52
53 private AbsoluteDate epoch;
54
55
56 private final double[][] analyticalDerivativesStm;
57
58
59 private final DoubleArrayDictionary analyticalDerivativesJacobianColumns;
60
61
62 private final AbstractAnalyticalPropagator propagator;
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 protected AbstractAnalyticalMatricesHarvester(final AbstractAnalyticalPropagator propagator, final String stmName,
79 final RealMatrix initialStm, final DoubleArrayDictionary initialJacobianColumns) {
80 super(stmName, initialStm, initialJacobianColumns);
81 this.propagator = propagator;
82 this.epoch = propagator.getInitialState().getDate();
83 this.columnsNames = null;
84 this.analyticalDerivativesStm = getInitialStateTransitionMatrix().getData();
85 this.analyticalDerivativesJacobianColumns = new DoubleArrayDictionary();
86 }
87
88
89 @Override
90 public List<String> getJacobiansColumnsNames() {
91 return columnsNames == null ? propagator.getJacobiansColumnsNames() : columnsNames;
92 }
93
94
95 @Override
96 public void freezeColumnsNames() {
97 columnsNames = getJacobiansColumnsNames();
98 }
99
100
101 @Override
102 public String getName() {
103 return getStmName();
104 }
105
106
107 @Override
108 public double[] getAdditionalData(final SpacecraftState state) {
109
110 updateDerivativesIfNeeded(state);
111
112 return toArray(analyticalDerivativesStm);
113 }
114
115
116 @Override
117 public RealMatrix getStateTransitionMatrix(final SpacecraftState state) {
118
119 if (!state.hasAdditionalData(getName())) {
120 return null;
121 }
122
123 return toRealMatrix(state.getAdditionalState(getName()));
124 }
125
126
127 @Override
128 public RealMatrix getParametersJacobian(final SpacecraftState state) {
129
130 updateDerivativesIfNeeded(state);
131
132
133 final List<String> names = getJacobiansColumnsNames();
134 if (names == null || names.isEmpty()) {
135 return null;
136 }
137
138
139 final RealMatrix dYdP = MatrixUtils.createRealMatrix(STATE_DIMENSION, names.size());
140
141
142 for (int j = 0; j < names.size(); ++j) {
143 final double[] column = analyticalDerivativesJacobianColumns.get(names.get(j));
144 if (column != null) {
145 for (int i = 0; i < STATE_DIMENSION; i++) {
146 dYdP.addToEntry(i, j, column[i]);
147 }
148 }
149 }
150
151
152 return dYdP;
153 }
154
155
156 @Override
157 public void setReferenceState(final SpacecraftState reference) {
158
159
160 for (final double[] row : analyticalDerivativesStm) {
161 Arrays.fill(row, 0.0);
162 }
163 analyticalDerivativesJacobianColumns.clear();
164
165 final AbstractAnalyticalGradientConverter converter = getGradientConverter();
166 final FieldAbstractAnalyticalPropagator<Gradient> gPropagator = converter.getPropagator();
167
168
169 final AbsoluteDate target = reference.getDate();
170 final FieldAbsoluteDate<Gradient> start = gPropagator.getInitialState().getDate();
171 final double dt = target.durationFrom(start.toAbsoluteDate());
172 final FieldSpacecraftState<Gradient> state = gPropagator.getInitialState();
173 final Gradient[] parameters = converter.getParameters(state, converter);
174 final FieldOrbit<Gradient> gOrbit = gPropagator.propagateOrbit(start.shiftedBy(dt), parameters);
175 final FieldPVCoordinates<Gradient> gPv = gOrbit.getPVCoordinates();
176
177 final double[] derivativesX = gPv.getPosition().getX().getGradient();
178 final double[] derivativesY = gPv.getPosition().getY().getGradient();
179 final double[] derivativesZ = gPv.getPosition().getZ().getGradient();
180 final double[] derivativesVx = gPv.getVelocity().getX().getGradient();
181 final double[] derivativesVy = gPv.getVelocity().getY().getGradient();
182 final double[] derivativesVz = gPv.getVelocity().getZ().getGradient();
183
184
185 addToRow(derivativesX, 0);
186 addToRow(derivativesY, 1);
187 addToRow(derivativesZ, 2);
188 addToRow(derivativesVx, 3);
189 addToRow(derivativesVy, 4);
190 addToRow(derivativesVz, 5);
191
192
193 int paramsIndex = converter.getFreeStateParameters();
194 for (ParameterDriver driver : converter.getParametersDrivers()) {
195 if (driver.isSelected()) {
196
197 final TimeSpanMap<String> driverNameSpanMap = driver.getNamesSpanMap();
198
199 for (Span<String> span = driverNameSpanMap.getFirstSpan(); span != null; span = span.next()) {
200
201 DoubleArrayDictionary.Entry entry = analyticalDerivativesJacobianColumns.getEntry(span.getData());
202 if (entry == null) {
203
204 analyticalDerivativesJacobianColumns.put(span.getData(), new double[STATE_DIMENSION]);
205 entry = analyticalDerivativesJacobianColumns.getEntry(span.getData());
206 }
207
208
209 entry.increment(new double[] {
210 derivativesX[paramsIndex], derivativesY[paramsIndex], derivativesZ[paramsIndex],
211 derivativesVx[paramsIndex], derivativesVy[paramsIndex], derivativesVz[paramsIndex]
212 });
213 ++paramsIndex;
214 }
215 }
216 }
217
218
219 epoch = target;
220
221 }
222
223
224
225
226 private void updateDerivativesIfNeeded(final SpacecraftState state) {
227 if (!state.getDate().isEqualTo(epoch)) {
228 setReferenceState(state);
229 }
230 }
231
232
233
234
235
236 private void addToRow(final double[] derivatives, final int index) {
237 for (int i = 0; i < 6; i++) {
238 analyticalDerivativesStm[index][i] += derivatives[i];
239 }
240 }
241
242
243
244
245
246 private RealMatrix toRealMatrix(final double[] array) {
247 final RealMatrix matrix = MatrixUtils.createRealMatrix(STATE_DIMENSION, STATE_DIMENSION);
248 int index = 0;
249 for (int i = 0; i < STATE_DIMENSION; ++i) {
250 for (int j = 0; j < STATE_DIMENSION; ++j) {
251 matrix.setEntry(i, j, array[index++]);
252 }
253 }
254 return matrix;
255 }
256
257
258
259
260
261 private double[] toArray(final double[][] matrix) {
262 final double[] array = new double[STATE_DIMENSION * STATE_DIMENSION];
263 int index = 0;
264 for (int i = 0; i < STATE_DIMENSION; ++i) {
265 final double[] row = matrix[i];
266 for (int j = 0; j < STATE_DIMENSION; ++j) {
267 array[index++] = row[j];
268 }
269 }
270 return array;
271 }
272
273
274 @Override
275 public OrbitType getOrbitType() {
276
277 return OrbitType.CARTESIAN;
278 }
279
280
281 @Override
282 public PositionAngleType getPositionAngleType() {
283
284 return PositionAngleType.MEAN;
285 }
286
287
288
289
290
291 public abstract AbstractAnalyticalGradientConverter getGradientConverter();
292
293 }