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