1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.semianalytical.dsst.forces;
18
19 import java.util.TreeMap;
20
21 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
22 import org.apache.commons.math3.util.FastMath;
23 import org.orekit.bodies.CelestialBody;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.propagation.SpacecraftState;
26 import org.orekit.propagation.events.EventDetector;
27 import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
28 import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory;
29 import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory.NSKey;
30 import org.orekit.propagation.semianalytical.dsst.utilities.UpperBounds;
31 import org.orekit.time.AbsoluteDate;
32
33
34
35
36
37
38
39 public class DSSTThirdBody implements DSSTForceModel {
40
41
42 private static final int MAX_POWER = 22;
43
44
45 private static final double BIG_TRUNCATION_TOLERANCE = 1.e-1;
46
47
48 private static final double SMALL_TRUNCATION_TOLERANCE = 1.e-4;
49
50
51 private final CelestialBody body;
52
53
54 private final double gm;
55
56
57 private final double[] fact;
58
59
60 private TreeMap<NSKey, Double> Vns;
61
62
63 private double R3;
64
65
66
67 private double a;
68
69 private double k;
70
71 private double h;
72
73 private double q;
74
75 private double p;
76
77
78 private double ecc;
79
80
81
82 private double alpha;
83
84 private double beta;
85
86 private double gamma;
87
88
89
90 private double X;
91
92 private double XX;
93
94 private double XXX;
95
96 private double m2aoA;
97
98 private double BoA;
99
100 private double ooAB;
101
102 private double mCo2AB;
103
104 private double BoABpo;
105
106
107 private int I;
108
109
110 private int maxAR3Pow;
111
112
113 private int maxEccPow;
114
115
116
117
118
119 public DSSTThirdBody(final CelestialBody body) {
120 this.body = body;
121 this.gm = body.getGM();
122
123 this.maxAR3Pow = Integer.MIN_VALUE;
124 this.maxEccPow = Integer.MIN_VALUE;
125
126 this.Vns = CoefficientsFactory.computeVns(MAX_POWER);
127
128
129 final int dim = 2 * MAX_POWER;
130 this.fact = new double[dim];
131 fact[0] = 1.;
132 for (int i = 1; i < dim; i++) {
133 fact[i] = i * fact[i - 1];
134 }
135 }
136
137
138
139
140 public CelestialBody getBody() {
141 return body;
142 }
143
144
145
146
147
148
149
150
151
152
153
154 public void initialize(final AuxiliaryElements aux)
155 throws OrekitException {
156
157
158 initializeStep(aux);
159
160
161 final double aor = a / R3;
162 final double tol = ( aor > .3 || (aor > .15 && ecc > .25) ) ? BIG_TRUNCATION_TOLERANCE : SMALL_TRUNCATION_TOLERANCE;
163
164
165
166 final double eo2 = FastMath.max(0.0025, ecc / 2.);
167 final double x2o2 = XX / 2.;
168 final double[] eccPwr = new double[MAX_POWER];
169 final double[] chiPwr = new double[MAX_POWER];
170 eccPwr[0] = 1.;
171 chiPwr[0] = X;
172 for (int i = 1; i < MAX_POWER; i++) {
173 eccPwr[i] = eccPwr[i - 1] * eo2;
174 chiPwr[i] = chiPwr[i - 1] * x2o2;
175 }
176
177
178 final double ao2rxx = aor / (2. * XX);
179 double xmuarn = ao2rxx * ao2rxx * gm / (X * R3);
180 double term = 0.;
181
182
183 maxAR3Pow = 2;
184 maxEccPow = 0;
185 int n = 2;
186 int m = 2;
187 int nsmd2 = 0;
188
189 do {
190
191 term = xmuarn *
192 (fact[n + m] / (fact[nsmd2] * fact[nsmd2 + m])) *
193 (fact[n + m + 1] / (fact[m] * fact[n + 1])) *
194 (fact[n - m + 1] / fact[n + 1]) *
195 eccPwr[m] * UpperBounds.getDnl(XX, chiPwr[m], n + 2, m);
196
197 if (term < tol) {
198 if (m == 0) {
199 break;
200 } else if (m < 2) {
201 xmuarn *= ao2rxx;
202 m = 0;
203 n++;
204 nsmd2++;
205 } else {
206 m -= 2;
207 nsmd2++;
208 }
209 } else {
210 maxAR3Pow = n;
211 maxEccPow = FastMath.max(m, maxEccPow);
212 xmuarn *= ao2rxx;
213 m++;
214 n++;
215 }
216 } while (n < MAX_POWER);
217
218 maxEccPow = FastMath.min(maxAR3Pow, maxEccPow);
219
220 }
221
222
223 public void initializeStep(final AuxiliaryElements aux) throws OrekitException {
224
225
226 a = aux.getSma();
227 k = aux.getK();
228 h = aux.getH();
229 q = aux.getQ();
230 p = aux.getP();
231
232
233 I = aux.getRetrogradeFactor();
234
235
236 ecc = aux.getEcc();
237
238
239 final Vector3D bodyPos = body.getPVCoordinates(aux.getDate(), aux.getFrame()).getPosition();
240 R3 = bodyPos.getNorm();
241
242
243 final Vector3D bodyDir = bodyPos.normalize();
244 alpha = bodyDir.dotProduct(aux.getVectorF());
245 beta = bodyDir.dotProduct(aux.getVectorG());
246 gamma = bodyDir.dotProduct(aux.getVectorW());
247
248
249 final double A = aux.getA();
250 final double B = aux.getB();
251 final double C = aux.getC();
252
253
254 X = 1. / B;
255 XX = X * X;
256 XXX = X * XX;
257
258 m2aoA = -2. * a / A;
259
260 BoA = B / A;
261
262 ooAB = 1. / (A * B);
263
264 mCo2AB = -C * ooAB / 2.;
265
266 BoABpo = BoA / (1. + B);
267
268 }
269
270
271 public double[] getMeanElementRate(final SpacecraftState currentState) throws OrekitException {
272
273
274 final double[] dU = computeUDerivatives();
275 final double dUda = dU[0];
276 final double dUdk = dU[1];
277 final double dUdh = dU[2];
278 final double dUdAl = dU[3];
279 final double dUdBe = dU[4];
280 final double dUdGa = dU[5];
281
282
283
284 final double UAlphaGamma = alpha * dUdGa - gamma * dUdAl;
285
286 final double UBetaGamma = beta * dUdGa - gamma * dUdBe;
287
288 final double pUAGmIqUBGoAB = (p * UAlphaGamma - I * q * UBetaGamma) * ooAB;
289
290
291 final double da = 0.;
292 final double dh = BoA * dUdk + k * pUAGmIqUBGoAB;
293 final double dk = -BoA * dUdh - h * pUAGmIqUBGoAB;
294 final double dp = mCo2AB * UBetaGamma;
295 final double dq = mCo2AB * UAlphaGamma * I;
296 final double dM = m2aoA * dUda + BoABpo * (h * dUdh + k * dUdk) + pUAGmIqUBGoAB;
297
298 return new double[] {da, dk, dh, dq, dp, dM};
299
300 }
301
302
303 public double[] getShortPeriodicVariations(final AbsoluteDate date,
304 final double[] meanElements) throws OrekitException {
305
306 return new double[] {0., 0., 0., 0., 0., 0.};
307 }
308
309
310 public EventDetector[] getEventsDetectors() {
311 return null;
312 }
313
314
315
316
317
318 private double[] computeUDerivatives() throws OrekitException {
319
320
321 final HansenThirdBody hansen = new HansenThirdBody();
322
323 final double[][] GsHs = CoefficientsFactory.computeGsHs(k, h, alpha, beta, maxEccPow);
324
325 final double[][] Qns = CoefficientsFactory.computeQns(gamma, maxAR3Pow, maxEccPow);
326
327 final double aoR3 = a / R3;
328 final double[] aoR3Pow = new double[maxAR3Pow + 1];
329 aoR3Pow[0] = 1.;
330 for (int i = 1; i <= maxAR3Pow; i++) {
331 aoR3Pow[i] = aoR3 * aoR3Pow[i - 1];
332 }
333
334
335 double dUda = 0.;
336 double dUdk = 0.;
337 double dUdh = 0.;
338 double dUdAl = 0.;
339 double dUdBe = 0.;
340 double dUdGa = 0.;
341
342 for (int s = 0; s <= maxEccPow; s++) {
343
344 final double gs = GsHs[0][s];
345
346
347 double dGsdh = 0.;
348 double dGsdk = 0.;
349 double dGsdAl = 0.;
350 double dGsdBe = 0.;
351 if (s > 0) {
352
353 final double sxGsm1 = s * GsHs[0][s - 1];
354 final double sxHsm1 = s * GsHs[1][s - 1];
355
356 dGsdh = beta * sxGsm1 - alpha * sxHsm1;
357 dGsdk = alpha * sxGsm1 + beta * sxHsm1;
358 dGsdAl = k * sxGsm1 - h * sxHsm1;
359 dGsdBe = h * sxGsm1 + k * sxHsm1;
360 }
361
362
363 final double delta0s = (s == 0) ? 1. : 2.;
364
365 for (int n = FastMath.max(2, s); n <= maxAR3Pow; n++) {
366
367 if ((n - s) % 2 == 0) {
368
369 final double kns = hansen.getValue(n, s);
370 final double dkns = hansen.getDerivative(n, s);
371 final double vns = Vns.get(new NSKey(n, s));
372 final double coef0 = delta0s * aoR3Pow[n] * vns;
373 final double coef1 = coef0 * Qns[n][s];
374 final double coef2 = coef1 * kns;
375
376
377 final double dqns = (n == s) ? 0. : Qns[n][s + 1];
378
379
380 dUda += coef2 * n * gs;
381
382 dUdh += coef1 * (kns * dGsdh + h * XXX * gs * dkns);
383
384 dUdk += coef1 * (kns * dGsdk + k * XXX * gs * dkns);
385
386 dUdAl += coef2 * dGsdAl;
387
388 dUdBe += coef2 * dGsdBe;
389
390 dUdGa += coef0 * kns * dqns * gs;
391 }
392 }
393 }
394
395
396 final double muoR3 = gm / R3;
397
398 return new double[] {
399 dUda * muoR3 / a,
400 dUdk * muoR3,
401 dUdh * muoR3,
402 dUdAl * muoR3,
403 dUdBe * muoR3,
404 dUdGa * muoR3
405 };
406
407 }
408
409
410
411
412
413
414
415 private class HansenThirdBody {
416
417
418 private TreeMap<NSKey, Double> coefficients;
419
420
421 private TreeMap<NSKey, Double> derivatives;
422
423
424 public HansenThirdBody() {
425 coefficients = new TreeMap<CoefficientsFactory.NSKey, Double>();
426 derivatives = new TreeMap<CoefficientsFactory.NSKey, Double>();
427 initialize();
428 }
429
430
431
432
433
434
435 public double getValue(final int n, final int s) {
436 if (coefficients.containsKey(new NSKey(n, s))) {
437 return coefficients.get(new NSKey(n, s));
438 } else {
439
440 return computeValue(n, s);
441 }
442 }
443
444
445
446
447
448
449 public double getDerivative(final int n, final int s) {
450 if (derivatives.containsKey(new NSKey(n, s))) {
451 return derivatives.get(new NSKey(n, s));
452 } else {
453
454 return computeDerivative(n, s);
455 }
456 }
457
458
459 private void initialize() {
460 final double ec2 = ecc * ecc;
461 final double oX3 = 1. / XXX;
462 coefficients.put(new NSKey(0, 0), 1.);
463 coefficients.put(new NSKey(0, 1), -1.);
464 coefficients.put(new NSKey(1, 0), 1. + 0.5 * ec2);
465 coefficients.put(new NSKey(1, 1), -1.5);
466 coefficients.put(new NSKey(2, 0), 1. + 1.5 * ec2);
467 coefficients.put(new NSKey(2, 1), -2. - 0.5 * ec2);
468 derivatives.put(new NSKey(0, 0), 0.);
469 derivatives.put(new NSKey(1, 0), oX3);
470 derivatives.put(new NSKey(2, 0), 3. * oX3);
471 derivatives.put(new NSKey(2, 1), -oX3);
472 }
473
474
475
476
477
478
479 private double computeValue(final int n, final int s) {
480
481 double kns = 0.;
482
483 if (n == (s - 1)) {
484
485 final NSKey key = new NSKey(s - 2, s - 1);
486 if (coefficients.containsKey(key)) {
487 kns = coefficients.get(key);
488 } else {
489 kns = computeValue(s - 2, s - 1);
490 }
491
492 kns *= -(2. * s - 1.) / s;
493
494 } else if (n == s) {
495
496 final NSKey key = new NSKey(s - 1, s);
497 if (coefficients.containsKey(key)) {
498 kns = coefficients.get(key);
499 } else {
500 kns = computeValue(s - 1, s);
501 }
502
503 kns *= (2. * s + 1.) / (s + 1.);
504
505 } else if (n > s) {
506
507 final NSKey key1 = new NSKey(n - 1, s);
508 double knM1 = 0.;
509 if (coefficients.containsKey(key1)) {
510 knM1 = coefficients.get(key1);
511 } else {
512 knM1 = computeValue(n - 1, s);
513 }
514
515 final NSKey key2 = new NSKey(n - 2, s);
516 double knM2 = 0.;
517 if (coefficients.containsKey(key2)) {
518 knM2 = coefficients.get(key2);
519 } else {
520 knM2 = computeValue(n - 2, s);
521 }
522
523 final double val1 = (2. * n + 1.) / (n + 1.);
524 final double val2 = (n + s) * (n - s) / (n * (n + 1.) * XX);
525
526 kns = val1 * knM1 - val2 * knM2;
527 }
528
529 coefficients.put(new NSKey(n, s), kns);
530 return kns;
531 }
532
533
534
535
536
537
538 private double computeDerivative(final int n, final int s) {
539
540 double dknsdx = 0.;
541
542 if (n > s) {
543
544 final NSKey keyNm1 = new NSKey(n - 1, s);
545 double dKnM1 = 0.;
546 if (derivatives.containsKey(keyNm1)) {
547 dKnM1 = derivatives.get(keyNm1);
548 } else {
549 dKnM1 = computeDerivative(n - 1, s);
550 }
551
552 final NSKey keyNm2 = new NSKey(n - 2, s);
553 double dKnM2 = 0.;
554 if (derivatives.containsKey(keyNm2)) {
555 dKnM2 = derivatives.get(keyNm2);
556 } else {
557 dKnM2 = computeDerivative(n - 2, s);
558 }
559
560 final double knM2 = getValue(n - 2, s);
561
562 final double val1 = (2. * n + 1.) / (n + 1.);
563 final double coef = (n + s) * (n - s) / (n * (n + 1.));
564 final double val2 = coef / XX;
565 final double val3 = 2. * coef / XXX;
566
567 dknsdx = val1 * dKnM1 - val2 * dKnM2 + val3 * knM2;
568 }
569
570 derivatives.put(new NSKey(n, s), dknsdx);
571 return dknsdx;
572 }
573
574 }
575
576 }