1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.drag;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.analysis.differentiation.DSFactory;
21 import org.hipparchus.analysis.differentiation.DerivativeStructure;
22 import org.hipparchus.analysis.differentiation.Gradient;
23 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.orekit.forces.ForceModel;
26 import org.orekit.frames.Frame;
27 import org.orekit.frames.StaticTransform;
28 import org.orekit.models.earth.atmosphere.Atmosphere;
29 import org.orekit.propagation.FieldSpacecraftState;
30 import org.orekit.time.AbsoluteDate;
31 import org.orekit.time.FieldAbsoluteDate;
32 import org.orekit.utils.FieldPVCoordinates;
33
34 import java.util.Arrays;
35
36
37
38
39
40
41
42 public abstract class AbstractDragForceModel implements ForceModel {
43
44
45 private final Atmosphere atmosphere;
46
47
48
49
50 private final boolean useFiniteDifferencesOnDensityWrtPosition;
51
52
53
54
55
56 protected AbstractDragForceModel(final Atmosphere atmosphere) {
57 this(atmosphere, true);
58 }
59
60
61
62
63
64
65
66
67 protected AbstractDragForceModel(final Atmosphere atmosphere, final boolean useFiniteDifferencesOnDensityWrtPosition) {
68 this.atmosphere = atmosphere;
69 this.useFiniteDifferencesOnDensityWrtPosition = useFiniteDifferencesOnDensityWrtPosition;
70 }
71
72
73
74
75
76 public Atmosphere getAtmosphere() {
77 return atmosphere;
78 }
79
80
81 @Override
82 public boolean dependsOnPositionOnly() {
83 return false;
84 }
85
86
87
88
89
90
91 protected <T extends CalculusFieldElement<T>> boolean isDSStateDerivative(final FieldSpacecraftState<T> state) {
92 try {
93 final DerivativeStructure dsMass = (DerivativeStructure) state.getMass();
94 final int o = dsMass.getOrder();
95 final int p = dsMass.getFreeParameters();
96
97
98
99
100 if (o != 1 || p != 6 && p != 7 && p != 8) {
101 return false;
102 }
103
104
105 @SuppressWarnings("unchecked")
106 final FieldPVCoordinates<DerivativeStructure> pv = (FieldPVCoordinates<DerivativeStructure>) state.getPVCoordinates();
107 return isVariable(pv.getPosition().getX(), 0) &&
108 isVariable(pv.getPosition().getY(), 1) &&
109 isVariable(pv.getPosition().getZ(), 2) &&
110 isVariable(pv.getVelocity().getX(), 3) &&
111 isVariable(pv.getVelocity().getY(), 4) &&
112 isVariable(pv.getVelocity().getZ(), 5);
113 } catch (ClassCastException cce) {
114 return false;
115 }
116 }
117
118
119
120
121
122
123 protected <T extends CalculusFieldElement<T>> boolean isGradientStateDerivative(final FieldSpacecraftState<T> state) {
124 try {
125 final Gradient gMass = (Gradient) state.getMass();
126 final int p = gMass.getFreeParameters();
127
128
129
130 if (p != 6 && p != 7 && p != 8) {
131 return false;
132 }
133
134
135 @SuppressWarnings("unchecked")
136 final FieldPVCoordinates<Gradient> pv = (FieldPVCoordinates<Gradient>) state.getPVCoordinates();
137 return isVariable(pv.getPosition().getX(), 0) &&
138 isVariable(pv.getPosition().getY(), 1) &&
139 isVariable(pv.getPosition().getZ(), 2) &&
140 isVariable(pv.getVelocity().getX(), 3) &&
141 isVariable(pv.getVelocity().getY(), 4) &&
142 isVariable(pv.getVelocity().getZ(), 5);
143 } catch (ClassCastException cce) {
144 return false;
145 }
146 }
147
148
149
150
151
152
153
154
155 @SuppressWarnings("unchecked")
156 protected <T extends CalculusFieldElement<T>> T getFieldDensity(final FieldSpacecraftState<T> s) {
157 final FieldAbsoluteDate<T> date = s.getDate();
158 final Frame frame = s.getFrame();
159 final FieldVector3D<T> position = s.getPosition();
160 if (isGradientStateDerivative(s)) {
161 if (useFiniteDifferencesOnDensityWrtPosition) {
162 return (T) this.getGradientDensityWrtStateUsingFiniteDifferences(date.toAbsoluteDate(), frame, (FieldVector3D<Gradient>) position);
163 } else {
164 return (T) this.getGradientDensityWrtState(date.toAbsoluteDate(), frame, (FieldVector3D<Gradient>) position);
165 }
166 } else if (isDSStateDerivative(s)) {
167 if (useFiniteDifferencesOnDensityWrtPosition) {
168 return (T) this.getDSDensityWrtStateUsingFiniteDifferences(date.toAbsoluteDate(), frame, (FieldVector3D<DerivativeStructure>) position);
169 } else {
170 return (T) this.getDSDensityWrtState(date.toAbsoluteDate(), frame, (FieldVector3D<DerivativeStructure>) position);
171 }
172 } else {
173 return atmosphere.getDensity(date, position, frame);
174 }
175 }
176
177
178
179
180
181
182 protected boolean isVariable(final DerivativeStructure ds, final int index) {
183 final double[] derivatives = ds.getAllDerivatives();
184 boolean check = true;
185 for (int i = 1; i < derivatives.length; ++i) {
186 check &= derivatives[i] == ((index + 1 == i) ? 1.0 : 0.0);
187 }
188 return check;
189 }
190
191
192
193
194
195
196 protected boolean isVariable(final Gradient g, final int index) {
197 final double[] derivatives = g.getGradient();
198 boolean check = true;
199 for (int i = 0; i < derivatives.length; ++i) {
200 check &= derivatives[i] == ((index == i) ? 1.0 : 0.0);
201 }
202 return check;
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231 protected DerivativeStructure getDSDensityWrtStateUsingFiniteDifferences(final AbsoluteDate date,
232 final Frame frame,
233 final FieldVector3D<DerivativeStructure> position) {
234
235
236
237
238
239 final DSFactory factory = position.getX().getFactory();
240
241
242 final DSFactory factory3 = new DSFactory(3, 1);
243 final FieldVector3D<DerivativeStructure> position3 =
244 new FieldVector3D<>(factory3.variable(0, position.getX().getReal()),
245 factory3.variable(1, position.getY().getReal()),
246 factory3.variable(2, position.getZ().getReal()));
247
248
249 final Frame atmFrame = atmosphere.getFrame();
250 final StaticTransform toBody = frame.getStaticTransformTo(atmFrame, date);
251 final FieldVector3D<DerivativeStructure> posBodyDS = toBody.transformPosition(position3);
252 final Vector3D posBody = posBodyDS.toVector3D();
253
254
255
256 final double delta = 1.0;
257 final double x = posBody.getX();
258 final double y = posBody.getY();
259 final double z = posBody.getZ();
260 final double rho0 = atmosphere.getDensity(date, posBody, atmFrame);
261 final double dRhodX = (atmosphere.getDensity(date, new Vector3D(x + delta, y, z), atmFrame) - rho0) / delta;
262 final double dRhodY = (atmosphere.getDensity(date, new Vector3D(x, y + delta, z), atmFrame) - rho0) / delta;
263 final double dRhodZ = (atmosphere.getDensity(date, new Vector3D(x, y, z + delta), atmFrame) - rho0) / delta;
264 final double[] dXdQ = posBodyDS.getX().getAllDerivatives();
265 final double[] dYdQ = posBodyDS.getY().getAllDerivatives();
266 final double[] dZdQ = posBodyDS.getZ().getAllDerivatives();
267
268
269
270
271 final int p = factory.getCompiler().getFreeParameters();
272 final double[] rhoAll = new double[p + 1];
273 rhoAll[0] = rho0;
274 for (int i = 1; i < 4; ++i) {
275 rhoAll[i] = dRhodX * dXdQ[i] + dRhodY * dYdQ[i] + dRhodZ * dZdQ[i];
276 }
277
278 return factory.build(rhoAll);
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300 protected DerivativeStructure getDSDensityWrtState(final AbsoluteDate date, final Frame frame,
301 final FieldVector3D<DerivativeStructure> position) {
302
303
304
305
306
307 final DSFactory factory = position.getX().getFactory();
308
309
310 final DSFactory factory3 = new DSFactory(3, 1);
311 final FieldVector3D<DerivativeStructure> position3 =
312 new FieldVector3D<>(factory3.variable(0, position.getX().getReal()),
313 factory3.variable(1, position.getY().getReal()),
314 factory3.variable(2, position.getZ().getReal()));
315
316
317 final Frame atmFrame = atmosphere.getFrame();
318 final StaticTransform toBody = frame.getStaticTransformTo(atmFrame, date);
319 final FieldVector3D<DerivativeStructure> posBodyDS = toBody.transformPosition(position3);
320 final FieldAbsoluteDate<DerivativeStructure> fieldDate = new FieldAbsoluteDate<>(position3.getX().getField(), date);
321 final DerivativeStructure density = atmosphere.getDensity(fieldDate, posBodyDS, atmFrame);
322
323
324
325
326 final double[] derivatives = Arrays.copyOf(density.getAllDerivatives(), factory.getCompiler().getSize());
327 return factory.build(derivatives);
328 }
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356 protected Gradient getGradientDensityWrtStateUsingFiniteDifferences(final AbsoluteDate date,
357 final Frame frame,
358 final FieldVector3D<Gradient> position) {
359
360
361 final FieldVector3D<Gradient> position3 =
362 new FieldVector3D<>(Gradient.variable(3, 0, position.getX().getReal()),
363 Gradient.variable(3, 1, position.getY().getReal()),
364 Gradient.variable(3, 2, position.getZ().getReal()));
365
366
367 final Frame atmFrame = atmosphere.getFrame();
368 final StaticTransform toBody = frame.getStaticTransformTo(atmFrame, date);
369 final FieldVector3D<Gradient> posBodyDS = toBody.transformPosition(position3);
370 final Vector3D posBody = posBodyDS.toVector3D();
371
372
373
374 final double delta = 1.0;
375 final double x = posBody.getX();
376 final double y = posBody.getY();
377 final double z = posBody.getZ();
378 final double rho0 = atmosphere.getDensity(date, posBody, atmFrame);
379 final double dRhodX = (atmosphere.getDensity(date, new Vector3D(x + delta, y, z), atmFrame) - rho0) / delta;
380 final double dRhodY = (atmosphere.getDensity(date, new Vector3D(x, y + delta, z), atmFrame) - rho0) / delta;
381 final double dRhodZ = (atmosphere.getDensity(date, new Vector3D(x, y, z + delta), atmFrame) - rho0) / delta;
382 final double[] dXdQ = posBodyDS.getX().getGradient();
383 final double[] dYdQ = posBodyDS.getY().getGradient();
384 final double[] dZdQ = posBodyDS.getZ().getGradient();
385
386
387
388
389 final int p = position.getX().getFreeParameters();
390 final double[] rhoAll = new double[p];
391 for (int i = 0; i < 3; ++i) {
392 rhoAll[i] = dRhodX * dXdQ[i] + dRhodY * dYdQ[i] + dRhodZ * dZdQ[i];
393 }
394
395 return new Gradient(rho0, rhoAll);
396 }
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 protected Gradient getGradientDensityWrtState(final AbsoluteDate date, final Frame frame,
418 final FieldVector3D<Gradient> position) {
419
420
421 final int positionDimension = 3;
422 final FieldVector3D<Gradient> position3 =
423 new FieldVector3D<>(Gradient.variable(positionDimension, 0, position.getX().getReal()),
424 Gradient.variable(positionDimension, 1, position.getY().getReal()),
425 Gradient.variable(positionDimension, 2, position.getZ().getReal()));
426
427
428 final Frame atmFrame = atmosphere.getFrame();
429 final StaticTransform toBody = frame.getStaticTransformTo(atmFrame, date);
430 final FieldVector3D<Gradient> posBodyGradient = toBody.transformPosition(position3);
431 final FieldAbsoluteDate<Gradient> fieldDate = new FieldAbsoluteDate<>(position3.getX().getField(), date);
432 final Gradient density = atmosphere.getDensity(fieldDate, posBodyGradient, atmFrame);
433
434
435
436
437 final double[] derivatives = Arrays.copyOf(density.getGradient(), position.getX().getFreeParameters());
438 return new Gradient(density.getValue(), derivatives);
439 }
440 }