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