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.ArrayList;
20 import java.util.List;
21 import java.util.SortedMap;
22 import java.util.TreeMap;
23
24 import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
25 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
26 import org.apache.commons.math3.util.FastMath;
27 import org.apache.commons.math3.util.MathUtils;
28 import org.orekit.attitudes.AttitudeProvider;
29 import org.orekit.errors.OrekitException;
30 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
31 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider.UnnormalizedSphericalHarmonics;
32 import org.orekit.frames.Frame;
33 import org.orekit.frames.Transform;
34 import org.orekit.orbits.Orbit;
35 import org.orekit.orbits.OrbitType;
36 import org.orekit.orbits.PositionAngle;
37 import org.orekit.propagation.SpacecraftState;
38 import org.orekit.propagation.events.EventDetector;
39 import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
40 import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory;
41 import org.orekit.propagation.semianalytical.dsst.utilities.GHmsjPolynomials;
42 import org.orekit.propagation.semianalytical.dsst.utilities.GammaMnsFunction;
43 import org.orekit.propagation.semianalytical.dsst.utilities.JacobiPolynomials;
44 import org.orekit.propagation.semianalytical.dsst.utilities.ShortPeriodicsInterpolatedCoefficient;
45 import org.orekit.propagation.semianalytical.dsst.utilities.hansen.HansenTesseralLinear;
46 import org.orekit.time.AbsoluteDate;
47
48
49
50
51
52
53
54
55
56
57 class TesseralContribution implements DSSTForceModel {
58
59
60
61
62 private static final double MIN_PERIOD_IN_SECONDS = 864000.;
63
64
65
66
67 private static final double MIN_PERIOD_IN_SAT_REV = 10.;
68
69
70 private static final int INTERPOLATION_POINTS = 3;
71
72
73 private static final int MAXJ = 12;
74
75
76 private static final int MAX_DEGREE_TESSERAL_SP = 8;
77
78
79 private static final int MAX_DEGREE_MDAILY_TESSERAL_SP = 12;
80
81
82 private static final int MAX_ORDER_TESSERAL_SP = 8;
83
84
85 private static final int MAX_ORDER_MDAILY_TESSERAL_SP = 12;
86
87
88 private static final int MAX_ECCPOWER_SP = 4;
89
90
91 private final UnnormalizedSphericalHarmonicsProvider provider;
92
93
94 private final Frame bodyFrame;
95
96
97 private final double centralBodyRotationRate;
98
99
100 private final double bodyPeriod;
101
102
103 private final int maxDegree;
104
105
106 private final int maxDegreeTesseralSP;
107
108
109 private final int maxDegreeMdailyTesseralSP;
110
111
112 private final int maxOrder;
113
114
115 private final int maxOrderTesseralSP;
116
117
118 private final int maxOrderMdailyTesseralSP;
119
120
121 private final List<Integer> resOrders;
122
123
124 private final double[] fact;
125
126
127 private int maxEccPow;
128
129
130
131 private int maxEccPowTesseralSP;
132
133
134
135 private int maxEccPowMdailyTesseralSP;
136
137
138 private int maxHansen;
139
140
141 private double orbitPeriod;
142
143
144 private double ratio;
145
146
147 private int I;
148
149
150
151 private double a;
152
153
154 private double k;
155
156
157 private double h;
158
159
160 private double q;
161
162
163 private double p;
164
165
166 private double lm;
167
168
169 private double ecc;
170
171
172
173 private double chi;
174
175
176 private double chi2;
177
178
179
180 private Vector3D f;
181
182
183 private Vector3D g;
184
185
186 private double theta;
187
188
189 private double alpha;
190
191
192 private double beta;
193
194
195 private double gamma;
196
197
198
199 private double ax2oA;
200
201
202 private double ooAB;
203
204
205 private double BoA;
206
207
208 private double BoABpo;
209
210
211 private double Co2AB;
212
213
214 private double moa;
215
216
217 private double roa;
218
219
220 private double e2;
221
222
223 private double meanMotion;
224
225
226 private final boolean mDailiesOnly;
227
228
229
230
231
232
233 private int jMax;
234
235
236 private final SortedMap<Integer, List<Integer> > nonResOrders;
237
238
239
240 private HansenTesseralLinear[][] hansenObjects;
241
242
243
244 private TesseralShortPeriodicCoefficients tesseralSPCoefs;
245
246
247 private Frame frame;
248
249
250
251
252
253
254
255 public TesseralContribution(final Frame centralBodyFrame,
256 final double centralBodyRotationRate,
257 final UnnormalizedSphericalHarmonicsProvider provider,
258 final boolean mDailiesOnly) {
259
260
261 this.bodyFrame = centralBodyFrame;
262
263
264 this.centralBodyRotationRate = centralBodyRotationRate;
265
266
267 this.bodyPeriod = MathUtils.TWO_PI / centralBodyRotationRate;
268
269
270 this.provider = provider;
271 this.maxDegree = provider.getMaxDegree();
272 this.maxOrder = provider.getMaxOrder();
273
274
275 this.maxDegreeTesseralSP = FastMath.min(maxDegree, MAX_DEGREE_TESSERAL_SP);
276 this.maxDegreeMdailyTesseralSP = FastMath.min(maxDegree, MAX_DEGREE_MDAILY_TESSERAL_SP);
277 this.maxOrderTesseralSP = FastMath.min(maxOrder, MAX_ORDER_TESSERAL_SP);
278 this.maxOrderMdailyTesseralSP = FastMath.min(maxOrder, MAX_ORDER_MDAILY_TESSERAL_SP);
279
280
281 this.maxEccPowTesseralSP = MAX_ECCPOWER_SP;
282 this.maxEccPowMdailyTesseralSP = FastMath.min(maxDegreeMdailyTesseralSP - 2, MAX_ECCPOWER_SP);
283 this.jMax = FastMath.min(MAXJ, maxDegreeTesseralSP + maxEccPowTesseralSP);
284
285
286 this.mDailiesOnly = mDailiesOnly;
287
288
289 this.resOrders = new ArrayList<Integer>();
290 this.nonResOrders = new TreeMap<Integer, List <Integer> >();
291 this.maxEccPow = 0;
292 this.maxHansen = 0;
293
294
295 final int maxFact = 2 * maxDegree + 1;
296 this.fact = new double[maxFact];
297 fact[0] = 1;
298 for (int i = 1; i < maxFact; i++) {
299 fact[i] = i * fact[i - 1];
300 }
301 }
302
303
304 @Override
305 public void initialize(final AuxiliaryElements aux, final boolean meanOnly)
306 throws OrekitException {
307
308
309 orbitPeriod = aux.getKeplerianPeriod();
310
311
312 frame = aux.getFrame();
313
314
315
316
317 final double e = aux.getEcc();
318 if (e <= 0.005) {
319 maxEccPow = 3;
320 } else if (e <= 0.02) {
321 maxEccPow = 4;
322 } else if (e <= 0.1) {
323 maxEccPow = 7;
324 } else if (e <= 0.2) {
325 maxEccPow = 10;
326 } else if (e <= 0.3) {
327 maxEccPow = 12;
328 } else if (e <= 0.4) {
329 maxEccPow = 15;
330 } else {
331 maxEccPow = 20;
332 }
333
334
335 maxHansen = maxEccPow / 2;
336 jMax = FastMath.min(MAXJ, maxDegree + maxEccPow);
337
338
339 ratio = orbitPeriod / bodyPeriod;
340
341
342 getResonantAndNonResonantTerms(meanOnly);
343
344
345 createHansenObjects(meanOnly);
346
347 if (!meanOnly) {
348
349 tesseralSPCoefs = new TesseralShortPeriodicCoefficients(jMax,
350 FastMath.max(maxOrderTesseralSP, maxOrderMdailyTesseralSP), INTERPOLATION_POINTS);
351 }
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366 private void createHansenObjects(final boolean meanOnly) {
367
368 this.hansenObjects = new HansenTesseralLinear[2 * maxDegree + 1][jMax + 1];
369
370 if (meanOnly) {
371
372 for (int m : resOrders) {
373
374 final int j = FastMath.max(1, (int) FastMath.round(ratio * m));
375
376
377 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
378 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
379
380
381 for (int s = 0; s <= sMax; s++) {
382
383 final int n0 = FastMath.max(FastMath.max(2, m), s);
384
385
386 this.hansenObjects[s + maxDegree][j] = new HansenTesseralLinear(maxDegree, s, j, n0, maxHansen);
387
388 if (s > 0 && s <= sMin) {
389
390 this.hansenObjects[maxDegree - s][j] = new HansenTesseralLinear(maxDegree, -s, j, n0, maxHansen);
391 }
392 }
393 }
394 } else {
395
396 for (int j = 0; j <= jMax; j++) {
397 for (int s = -maxDegree; s <= maxDegree; s++) {
398
399 final int n0 = FastMath.max(2, FastMath.abs(s));
400
401 this.hansenObjects[s + maxDegree][j] = new HansenTesseralLinear(maxDegree, s, j, n0, maxHansen);
402 }
403 }
404 }
405 }
406
407
408 @Override
409 public void initializeStep(final AuxiliaryElements aux) throws OrekitException {
410
411
412 a = aux.getSma();
413 k = aux.getK();
414 h = aux.getH();
415 q = aux.getQ();
416 p = aux.getP();
417 lm = aux.getLM();
418
419
420 ecc = aux.getEcc();
421 e2 = ecc * ecc;
422
423
424 I = aux.getRetrogradeFactor();
425
426
427 f = aux.getVectorF();
428 g = aux.getVectorG();
429
430
431 final Transform t = bodyFrame.getTransformTo(aux.getFrame(), aux.getDate());
432 final Vector3D xB = t.transformVector(Vector3D.PLUS_I);
433 final Vector3D yB = t.transformVector(Vector3D.PLUS_J);
434 theta = FastMath.atan2(-f.dotProduct(yB) + I * g.dotProduct(xB),
435 f.dotProduct(xB) + I * g.dotProduct(yB));
436
437
438 alpha = aux.getAlpha();
439 beta = aux.getBeta();
440 gamma = aux.getGamma();
441
442
443
444 final double A = aux.getA();
445
446 final double B = aux.getB();
447
448 final double C = aux.getC();
449
450
451 ax2oA = 2. * a / A;
452
453 BoA = B / A;
454
455 ooAB = 1. / (A * B);
456
457 Co2AB = C * ooAB / 2.;
458
459 BoABpo = BoA / (1. + B);
460
461 moa = provider.getMu() / a;
462
463 roa = provider.getAe() / a;
464
465
466 chi = 1. / B;
467 chi2 = chi * chi;
468
469
470 meanMotion = aux.getMeanMotion();
471 }
472
473
474 @Override
475 public double[] getMeanElementRate(final SpacecraftState spacecraftState) throws OrekitException {
476
477
478 final double[] dU = computeUDerivatives(spacecraftState.getDate());
479 final double dUda = dU[0];
480 final double dUdh = dU[1];
481 final double dUdk = dU[2];
482 final double dUdl = dU[3];
483 final double dUdAl = dU[4];
484 final double dUdBe = dU[5];
485 final double dUdGa = dU[6];
486
487
488 final double UAlphaGamma = alpha * dUdGa - gamma * dUdAl;
489 final double UAlphaBeta = alpha * dUdBe - beta * dUdAl;
490 final double UBetaGamma = beta * dUdGa - gamma * dUdBe;
491 final double Uhk = h * dUdk - k * dUdh;
492 final double pUagmIqUbgoAB = (p * UAlphaGamma - I * q * UBetaGamma) * ooAB;
493 final double UhkmUabmdUdl = Uhk - UAlphaBeta - dUdl;
494
495 final double da = ax2oA * dUdl;
496 final double dh = BoA * dUdk + k * pUagmIqUbgoAB - h * BoABpo * dUdl;
497 final double dk = -(BoA * dUdh + h * pUagmIqUbgoAB + k * BoABpo * dUdl);
498 final double dp = Co2AB * (p * UhkmUabmdUdl - UBetaGamma);
499 final double dq = Co2AB * (q * UhkmUabmdUdl - I * UAlphaGamma);
500 final double dM = -ax2oA * dUda + BoABpo * (h * dUdh + k * dUdk) + pUagmIqUbgoAB;
501
502 return new double[] {da, dk, dh, dq, dp, dM};
503 }
504
505
506 @Override
507 public double[] getShortPeriodicVariations(final AbsoluteDate date,
508 final double[] meanElements)
509 throws OrekitException {
510
511
512 final double[] shortPeriodicVariation = new double[] {0., 0., 0., 0., 0., 0.};
513
514
515
516 if (!nonResOrders.isEmpty() || mDailiesOnly) {
517
518
519 final Orbit meanOrbit = OrbitType.EQUINOCTIAL.mapArrayToOrbit(
520 meanElements, PositionAngle.MEAN, date, provider.getMu(), this.frame);
521
522
523 final AuxiliaryElements aux = new AuxiliaryElements(meanOrbit, I);
524
525
526 final Transform t = bodyFrame.getTransformTo(aux.getFrame(), aux.getDate());
527 final Vector3D xB = t.transformVector(Vector3D.PLUS_I);
528 final Vector3D yB = t.transformVector(Vector3D.PLUS_J);
529 final double currentTheta = FastMath.atan2(-f.dotProduct(yB) + I * g.dotProduct(xB),
530 f.dotProduct(xB) + I * g.dotProduct(yB));
531
532
533 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
534
535 final double jlMmt = -m * currentTheta;
536 final double sinPhi = FastMath.sin(jlMmt);
537 final double cosPhi = FastMath.cos(jlMmt);
538
539
540 for (int i = 0; i < 6; i++) {
541 shortPeriodicVariation[i] += tesseralSPCoefs.getCijm(i, 0, m, date) * cosPhi +
542 tesseralSPCoefs.getSijm(i, 0, m, date) * sinPhi;
543 }
544 }
545
546
547 for (int m : nonResOrders.keySet()) {
548 final List<Integer> listJ = nonResOrders.get(m);
549
550 for (int j : listJ) {
551
552 final double jlMmt = j * meanElements[5] - m * currentTheta;
553 final double sinPhi = FastMath.sin(jlMmt);
554 final double cosPhi = FastMath.cos(jlMmt);
555
556
557 for (int i = 0; i < 6; i++) {
558 shortPeriodicVariation[i] += tesseralSPCoefs.getCijm(i, j, m, date) * cosPhi +
559 tesseralSPCoefs.getSijm(i, j, m, date) * sinPhi;
560 }
561
562 }
563 }
564 }
565
566 return shortPeriodicVariation;
567 }
568
569
570 @Override
571 public EventDetector[] getEventsDetectors() {
572 return null;
573 }
574
575
576 public void computeShortPeriodicsCoefficients(final SpacecraftState state) throws OrekitException {
577
578 for (int s = -maxDegree; s <= maxDegree; s++) {
579
580 this.hansenObjects[s + maxDegree][0].computeInitValues(e2, chi, chi2);
581 if (!mDailiesOnly) {
582
583 for (int j = 1; j <= jMax; j++) {
584 this.hansenObjects[s + maxDegree][j].computeInitValues(e2, chi, chi2);
585 }
586 }
587 }
588
589
590 tesseralSPCoefs.computeCoefficients(state.getDate());
591 }
592
593
594
595
596
597
598 private void getResonantAndNonResonantTerms(final boolean resonantOnly) {
599
600
601 final double tolerance = 1. / FastMath.max(MIN_PERIOD_IN_SAT_REV,
602 MIN_PERIOD_IN_SECONDS / orbitPeriod);
603
604
605 resOrders.clear();
606 nonResOrders.clear();
607 for (int m = 1; m <= maxOrder; m++) {
608 final double resonance = ratio * m;
609 int jRes = 0;
610 final int jComputedRes = (int) FastMath.round(resonance);
611 if (jComputedRes > 0 && jComputedRes <= jMax && FastMath.abs(resonance - jComputedRes) <= tolerance) {
612
613 resOrders.add(m);
614 jRes = jComputedRes;
615 }
616
617 if (!resonantOnly && !mDailiesOnly && m <= maxOrderTesseralSP) {
618
619 final List<Integer> listJofM = new ArrayList<Integer>();
620
621 for (int j = -jMax; j <= jMax; j++) {
622 if (j != 0 && j != jRes) {
623 listJofM.add(j);
624 }
625 }
626
627 nonResOrders.put(m, listJofM);
628 }
629 }
630 }
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649 private double[] computeUDerivatives(final AbsoluteDate date) throws OrekitException {
650
651
652 double dUda = 0.;
653 double dUdh = 0.;
654 double dUdk = 0.;
655 double dUdl = 0.;
656 double dUdAl = 0.;
657 double dUdBe = 0.;
658 double dUdGa = 0.;
659
660
661 if (!resOrders.isEmpty()) {
662
663 final GHmsjPolynomials ghMSJ = new GHmsjPolynomials(k, h, alpha, beta, I);
664
665
666 final GammaMnsFunction gammaMNS = new GammaMnsFunction(fact, gamma, I);
667
668
669 final double[] roaPow = new double[maxDegree + 1];
670 roaPow[0] = 1.;
671 for (int i = 1; i <= maxDegree; i++) {
672 roaPow[i] = roa * roaPow[i - 1];
673 }
674
675
676 for (int m : resOrders) {
677
678
679 final int j = FastMath.max(1, (int) FastMath.round(ratio * m));
680
681
682 final double jlMmt = j * lm - m * theta;
683 final double sinPhi = FastMath.sin(jlMmt);
684 final double cosPhi = FastMath.cos(jlMmt);
685
686
687 double dUdaCos = 0.;
688 double dUdaSin = 0.;
689 double dUdhCos = 0.;
690 double dUdhSin = 0.;
691 double dUdkCos = 0.;
692 double dUdkSin = 0.;
693 double dUdlCos = 0.;
694 double dUdlSin = 0.;
695 double dUdAlCos = 0.;
696 double dUdAlSin = 0.;
697 double dUdBeCos = 0.;
698 double dUdBeSin = 0.;
699 double dUdGaCos = 0.;
700 double dUdGaSin = 0.;
701
702
703 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
704 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
705 for (int s = 0; s <= sMax; s++) {
706
707
708 this.hansenObjects[s + maxDegree][j].computeInitValues(e2, chi, chi2);
709
710
711 final double[][] nSumSpos = computeNSum(date, j, m, s, maxDegree,
712 roaPow, ghMSJ, gammaMNS);
713 dUdaCos += nSumSpos[0][0];
714 dUdaSin += nSumSpos[0][1];
715 dUdhCos += nSumSpos[1][0];
716 dUdhSin += nSumSpos[1][1];
717 dUdkCos += nSumSpos[2][0];
718 dUdkSin += nSumSpos[2][1];
719 dUdlCos += nSumSpos[3][0];
720 dUdlSin += nSumSpos[3][1];
721 dUdAlCos += nSumSpos[4][0];
722 dUdAlSin += nSumSpos[4][1];
723 dUdBeCos += nSumSpos[5][0];
724 dUdBeSin += nSumSpos[5][1];
725 dUdGaCos += nSumSpos[6][0];
726 dUdGaSin += nSumSpos[6][1];
727
728
729 if (s > 0 && s <= sMin) {
730
731 this.hansenObjects[maxDegree - s][j].computeInitValues(e2, chi, chi2);
732
733 final double[][] nSumSneg = computeNSum(date, j, m, -s, maxDegree,
734 roaPow, ghMSJ, gammaMNS);
735 dUdaCos += nSumSneg[0][0];
736 dUdaSin += nSumSneg[0][1];
737 dUdhCos += nSumSneg[1][0];
738 dUdhSin += nSumSneg[1][1];
739 dUdkCos += nSumSneg[2][0];
740 dUdkSin += nSumSneg[2][1];
741 dUdlCos += nSumSneg[3][0];
742 dUdlSin += nSumSneg[3][1];
743 dUdAlCos += nSumSneg[4][0];
744 dUdAlSin += nSumSneg[4][1];
745 dUdBeCos += nSumSneg[5][0];
746 dUdBeSin += nSumSneg[5][1];
747 dUdGaCos += nSumSneg[6][0];
748 dUdGaSin += nSumSneg[6][1];
749 }
750 }
751
752
753 dUda += cosPhi * dUdaCos + sinPhi * dUdaSin;
754 dUdh += cosPhi * dUdhCos + sinPhi * dUdhSin;
755 dUdk += cosPhi * dUdkCos + sinPhi * dUdkSin;
756 dUdl += cosPhi * dUdlCos + sinPhi * dUdlSin;
757 dUdAl += cosPhi * dUdAlCos + sinPhi * dUdAlSin;
758 dUdBe += cosPhi * dUdBeCos + sinPhi * dUdBeSin;
759 dUdGa += cosPhi * dUdGaCos + sinPhi * dUdGaSin;
760 }
761
762 dUda *= -moa / a;
763 dUdh *= moa;
764 dUdk *= moa;
765 dUdl *= moa;
766 dUdAl *= moa;
767 dUdBe *= moa;
768 dUdGa *= moa;
769 }
770
771 return new double[] {dUda, dUdh, dUdk, dUdl, dUdAl, dUdBe, dUdGa};
772 }
773
774
775
776
777
778
779
780
781
782
783
784
785
786 private double[][] computeNSum(final AbsoluteDate date,
787 final int j, final int m, final int s, final int maxN, final double[] roaPow,
788 final GHmsjPolynomials ghMSJ, final GammaMnsFunction gammaMNS)
789 throws OrekitException {
790
791
792 final UnnormalizedSphericalHarmonics harmonics = provider.onDate(date);
793
794
795 double dUdaCos = 0.;
796 double dUdaSin = 0.;
797 double dUdhCos = 0.;
798 double dUdhSin = 0.;
799 double dUdkCos = 0.;
800 double dUdkSin = 0.;
801 double dUdlCos = 0.;
802 double dUdlSin = 0.;
803 double dUdAlCos = 0.;
804 double dUdAlSin = 0.;
805 double dUdBeCos = 0.;
806 double dUdBeSin = 0.;
807 double dUdGaCos = 0.;
808 double dUdGaSin = 0.;
809
810
811 final int Im = I > 0 ? 1 : (m % 2 == 0 ? 1 : -1);
812
813
814 final int v = FastMath.abs(m - s);
815 final int w = FastMath.abs(m + s);
816
817
818 final int nmin = FastMath.max(FastMath.max(2, m), FastMath.abs(s));
819
820
821 final int sIndex = maxDegree + (j < 0 ? -s : s);
822 final int jIndex = FastMath.abs(j);
823 final HansenTesseralLinear hans = this.hansenObjects[sIndex][jIndex];
824
825
826 for (int n = nmin; n <= maxN; n++) {
827
828 if ((n - s) % 2 == 0) {
829
830
831 final double fns = fact[n + FastMath.abs(s)];
832 final double vMNS = CoefficientsFactory.getVmns(m, n, s, fns, fact[n - m]);
833
834
835 final double gaMNS = gammaMNS.getValue(m, n, s);
836 final double dGaMNS = gammaMNS.getDerivative(m, n, s);
837
838
839 final double kJNS = hans.getValue(-n - 1, chi);
840 final double dkJNS = hans.getDerivative(-n - 1, chi);
841
842
843 final double gMSJ = ghMSJ.getGmsj(m, s, j);
844 final double hMSJ = ghMSJ.getHmsj(m, s, j);
845 final double dGdh = ghMSJ.getdGmsdh(m, s, j);
846 final double dGdk = ghMSJ.getdGmsdk(m, s, j);
847 final double dGdA = ghMSJ.getdGmsdAlpha(m, s, j);
848 final double dGdB = ghMSJ.getdGmsdBeta(m, s, j);
849 final double dHdh = ghMSJ.getdHmsdh(m, s, j);
850 final double dHdk = ghMSJ.getdHmsdk(m, s, j);
851 final double dHdA = ghMSJ.getdHmsdAlpha(m, s, j);
852 final double dHdB = ghMSJ.getdHmsdBeta(m, s, j);
853
854
855 final int l = FastMath.min(n - m, n - FastMath.abs(s));
856
857 final DerivativeStructure jacobi =
858 JacobiPolynomials.getValue(l, v , w, new DerivativeStructure(1, 1, 0, gamma));
859
860
861 final double cnm = harmonics.getUnnormalizedCnm(n, m);
862 final double snm = harmonics.getUnnormalizedSnm(n, m);
863
864
865 final double cf_0 = roaPow[n] * Im * vMNS;
866 final double cf_1 = cf_0 * gaMNS * jacobi.getValue();
867 final double cf_2 = cf_1 * kJNS;
868 final double gcPhs = gMSJ * cnm + hMSJ * snm;
869 final double gsMhc = gMSJ * snm - hMSJ * cnm;
870 final double dKgcPhsx2 = 2. * dkJNS * gcPhs;
871 final double dKgsMhcx2 = 2. * dkJNS * gsMhc;
872 final double dUdaCoef = (n + 1) * cf_2;
873 final double dUdlCoef = j * cf_2;
874 final double dUdGaCoef = cf_0 * kJNS * (jacobi.getValue() * dGaMNS + gaMNS * jacobi.getPartialDerivative(1));
875
876
877 dUdaCos += dUdaCoef * gcPhs;
878 dUdaSin += dUdaCoef * gsMhc;
879
880
881 dUdhCos += cf_1 * (kJNS * (cnm * dGdh + snm * dHdh) + h * dKgcPhsx2);
882 dUdhSin += cf_1 * (kJNS * (snm * dGdh - cnm * dHdh) + h * dKgsMhcx2);
883
884
885 dUdkCos += cf_1 * (kJNS * (cnm * dGdk + snm * dHdk) + k * dKgcPhsx2);
886 dUdkSin += cf_1 * (kJNS * (snm * dGdk - cnm * dHdk) + k * dKgsMhcx2);
887
888
889 dUdlCos += dUdlCoef * gsMhc;
890 dUdlSin += -dUdlCoef * gcPhs;
891
892
893 dUdAlCos += cf_2 * (dGdA * cnm + dHdA * snm);
894 dUdAlSin += cf_2 * (dGdA * snm - dHdA * cnm);
895
896
897 dUdBeCos += cf_2 * (dGdB * cnm + dHdB * snm);
898 dUdBeSin += cf_2 * (dGdB * snm - dHdB * cnm);
899
900
901 dUdGaCos += dUdGaCoef * gcPhs;
902 dUdGaSin += dUdGaCoef * gsMhc;
903 }
904 }
905
906 return new double[][] {{dUdaCos, dUdaSin},
907 {dUdhCos, dUdhSin},
908 {dUdkCos, dUdkSin},
909 {dUdlCos, dUdlSin},
910 {dUdAlCos, dUdAlSin},
911 {dUdBeCos, dUdBeSin},
912 {dUdGaCos, dUdGaSin}};
913 }
914
915
916 @Override
917 public void registerAttitudeProvider(final AttitudeProvider attitudeProvider) {
918
919 }
920
921
922 @Override
923 public void resetShortPeriodicsCoefficients() {
924 if (tesseralSPCoefs != null) {
925 tesseralSPCoefs.resetCoefficients();
926 }
927 }
928
929
930
931
932
933
934
935 private class FourierCjSjCoefficients {
936
937
938 private final int jMax;
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953 private final double[][][] cCoef;
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968 private final double[][][] sCoef;
969
970
971 private GHmsjPolynomials ghMSJ;
972
973
974 private GammaMnsFunction gammaMNS;
975
976
977 private final double[] roaPow;
978
979
980
981
982
983 public FourierCjSjCoefficients(final int jMax, final int mMax) {
984
985 this.jMax = jMax;
986 this.cCoef = new double[mMax + 1][2 * jMax + 1][6];
987 this.sCoef = new double[mMax + 1][2 * jMax + 1][6];
988 this.roaPow = new double[maxDegree + 1];
989 roaPow[0] = 1.;
990 }
991
992
993
994
995
996
997 public void generateCoefficients(final AbsoluteDate date) throws OrekitException {
998
999 if (!nonResOrders.isEmpty() || mDailiesOnly) {
1000
1001 ghMSJ = new GHmsjPolynomials(k, h, alpha, beta, I);
1002
1003
1004 gammaMNS = new GammaMnsFunction(fact, gamma, I);
1005
1006 final int maxRoaPower = FastMath.max(maxDegreeTesseralSP, maxDegreeMdailyTesseralSP);
1007
1008
1009 for (int i = 1; i <= maxRoaPower; i++) {
1010 roaPow[i] = roa * roaPow[i - 1];
1011 }
1012
1013
1014 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1015 buildFourierCoefficients(date, m, 0, maxDegreeMdailyTesseralSP);
1016 }
1017
1018
1019 if (!mDailiesOnly) {
1020 for (int m: nonResOrders.keySet()) {
1021 final List<Integer> listJ = nonResOrders.get(m);
1022
1023 for (int j: listJ) {
1024
1025 buildFourierCoefficients(date, m, j, maxDegreeTesseralSP);
1026 }
1027 }
1028 }
1029 }
1030 }
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040 private void buildFourierCoefficients(final AbsoluteDate date,
1041 final int m, final int j, final int maxN) throws OrekitException {
1042
1043 double dRdaCos = 0.;
1044 double dRdaSin = 0.;
1045 double dRdhCos = 0.;
1046 double dRdhSin = 0.;
1047 double dRdkCos = 0.;
1048 double dRdkSin = 0.;
1049 double dRdlCos = 0.;
1050 double dRdlSin = 0.;
1051 double dRdAlCos = 0.;
1052 double dRdAlSin = 0.;
1053 double dRdBeCos = 0.;
1054 double dRdBeSin = 0.;
1055 double dRdGaCos = 0.;
1056 double dRdGaSin = 0.;
1057
1058
1059 final int sMin = j == 0 ? maxEccPowMdailyTesseralSP : maxEccPowTesseralSP;
1060 final int sMax = j == 0 ? maxEccPowMdailyTesseralSP : maxEccPowTesseralSP;
1061 for (int s = 0; s <= sMax; s++) {
1062
1063
1064 final double[][] nSumSpos = computeNSum(date, j, m, s, maxN,
1065 roaPow, ghMSJ, gammaMNS);
1066 dRdaCos += nSumSpos[0][0];
1067 dRdaSin += nSumSpos[0][1];
1068 dRdhCos += nSumSpos[1][0];
1069 dRdhSin += nSumSpos[1][1];
1070 dRdkCos += nSumSpos[2][0];
1071 dRdkSin += nSumSpos[2][1];
1072 dRdlCos += nSumSpos[3][0];
1073 dRdlSin += nSumSpos[3][1];
1074 dRdAlCos += nSumSpos[4][0];
1075 dRdAlSin += nSumSpos[4][1];
1076 dRdBeCos += nSumSpos[5][0];
1077 dRdBeSin += nSumSpos[5][1];
1078 dRdGaCos += nSumSpos[6][0];
1079 dRdGaSin += nSumSpos[6][1];
1080
1081
1082 if (s > 0 && s <= sMin) {
1083 final double[][] nSumSneg = computeNSum(date, j, m, -s, maxN,
1084 roaPow, ghMSJ, gammaMNS);
1085 dRdaCos += nSumSneg[0][0];
1086 dRdaSin += nSumSneg[0][1];
1087 dRdhCos += nSumSneg[1][0];
1088 dRdhSin += nSumSneg[1][1];
1089 dRdkCos += nSumSneg[2][0];
1090 dRdkSin += nSumSneg[2][1];
1091 dRdlCos += nSumSneg[3][0];
1092 dRdlSin += nSumSneg[3][1];
1093 dRdAlCos += nSumSneg[4][0];
1094 dRdAlSin += nSumSneg[4][1];
1095 dRdBeCos += nSumSneg[5][0];
1096 dRdBeSin += nSumSneg[5][1];
1097 dRdGaCos += nSumSneg[6][0];
1098 dRdGaSin += nSumSneg[6][1];
1099 }
1100 }
1101 dRdaCos *= -moa / a;
1102 dRdaSin *= -moa / a;
1103 dRdhCos *= moa;
1104 dRdhSin *= moa;
1105 dRdkCos *= moa;
1106 dRdkSin *= moa;
1107 dRdlCos *= moa;
1108 dRdlSin *= moa;
1109 dRdAlCos *= moa;
1110 dRdAlSin *= moa;
1111 dRdBeCos *= moa;
1112 dRdBeSin *= moa;
1113 dRdGaCos *= moa;
1114 dRdGaSin *= moa;
1115
1116
1117 final double RAlphaGammaCos = alpha * dRdGaCos - gamma * dRdAlCos;
1118 final double RAlphaGammaSin = alpha * dRdGaSin - gamma * dRdAlSin;
1119 final double RAlphaBetaCos = alpha * dRdBeCos - beta * dRdAlCos;
1120 final double RAlphaBetaSin = alpha * dRdBeSin - beta * dRdAlSin;
1121 final double RBetaGammaCos = beta * dRdGaCos - gamma * dRdBeCos;
1122 final double RBetaGammaSin = beta * dRdGaSin - gamma * dRdBeSin;
1123 final double RhkCos = h * dRdkCos - k * dRdhCos;
1124 final double RhkSin = h * dRdkSin - k * dRdhSin;
1125 final double pRagmIqRbgoABCos = (p * RAlphaGammaCos - I * q * RBetaGammaCos) * ooAB;
1126 final double pRagmIqRbgoABSin = (p * RAlphaGammaSin - I * q * RBetaGammaSin) * ooAB;
1127 final double RhkmRabmdRdlCos = RhkCos - RAlphaBetaCos - dRdlCos;
1128 final double RhkmRabmdRdlSin = RhkSin - RAlphaBetaSin - dRdlSin;
1129
1130
1131 cCoef[m][j + jMax][0] = ax2oA * dRdlCos;
1132 sCoef[m][j + jMax][0] = ax2oA * dRdlSin;
1133
1134
1135 cCoef[m][j + jMax][1] = -(BoA * dRdhCos + h * pRagmIqRbgoABCos + k * BoABpo * dRdlCos);
1136 sCoef[m][j + jMax][1] = -(BoA * dRdhSin + h * pRagmIqRbgoABSin + k * BoABpo * dRdlSin);
1137
1138
1139 cCoef[m][j + jMax][2] = BoA * dRdkCos + k * pRagmIqRbgoABCos - h * BoABpo * dRdlCos;
1140 sCoef[m][j + jMax][2] = BoA * dRdkSin + k * pRagmIqRbgoABSin - h * BoABpo * dRdlSin;
1141
1142
1143 cCoef[m][j + jMax][3] = Co2AB * (q * RhkmRabmdRdlCos - I * RAlphaGammaCos);
1144 sCoef[m][j + jMax][3] = Co2AB * (q * RhkmRabmdRdlSin - I * RAlphaGammaSin);
1145
1146
1147 cCoef[m][j + jMax][4] = Co2AB * (p * RhkmRabmdRdlCos - RBetaGammaCos);
1148 sCoef[m][j + jMax][4] = Co2AB * (p * RhkmRabmdRdlSin - RBetaGammaSin);
1149
1150
1151 cCoef[m][j + jMax][5] = -ax2oA * dRdaCos + BoABpo * (h * dRdhCos + k * dRdkCos) + pRagmIqRbgoABCos;
1152 sCoef[m][j + jMax][5] = -ax2oA * dRdaSin + BoABpo * (h * dRdhSin + k * dRdkSin) + pRagmIqRbgoABSin;
1153 }
1154
1155
1156
1157
1158
1159
1160
1161 public double getCijm(final int i, final int j, final int m) {
1162 return cCoef[m][j + jMax][i];
1163 }
1164
1165
1166
1167
1168
1169
1170
1171 public double getSijm(final int i, final int j, final int m) {
1172 return sCoef[m][j + jMax][i];
1173 }
1174 }
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185 private class TesseralShortPeriodicCoefficients {
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199 private final ShortPeriodicsInterpolatedCoefficient[][][] cijm;
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213 private final ShortPeriodicsInterpolatedCoefficient[][][] sijm;
1214
1215
1216 private final int jMax;
1217
1218
1219 private final int mMax;
1220
1221
1222 private final FourierCjSjCoefficients cjsjFourier;
1223
1224
1225 private double tnota;
1226
1227
1228
1229
1230
1231
1232 public TesseralShortPeriodicCoefficients(final int jMax, final int mMax, final int interpolationPoints) {
1233
1234
1235 this.jMax = jMax;
1236 this.mMax = mMax;
1237 this.cijm = new ShortPeriodicsInterpolatedCoefficient[mMax + 1][2 * jMax + 1][6];
1238 this.sijm = new ShortPeriodicsInterpolatedCoefficient[mMax + 1][2 * jMax + 1][6];
1239 this.cjsjFourier = new FourierCjSjCoefficients(jMax, mMax);
1240
1241 for (int m = 1; m <= mMax; m++) {
1242 for (int j = -jMax; j <= jMax; j++) {
1243 for (int i = 0; i < 6; i++) {
1244 this.cijm[m][j + jMax][i] = new ShortPeriodicsInterpolatedCoefficient(interpolationPoints);
1245 this.sijm[m][j + jMax][i] = new ShortPeriodicsInterpolatedCoefficient(interpolationPoints);
1246 }
1247 }
1248 }
1249 }
1250
1251
1252
1253
1254
1255
1256 public void computeCoefficients(final AbsoluteDate date)
1257 throws OrekitException {
1258
1259 if (!nonResOrders.isEmpty() || mDailiesOnly) {
1260
1261 cjsjFourier.generateCoefficients(date);
1262
1263
1264 tnota = 1.5 * meanMotion / a;
1265
1266
1267 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1268
1269 buildCoefficients(date, m, 0);
1270 }
1271
1272 if (!mDailiesOnly) {
1273
1274 for (int m: nonResOrders.keySet()) {
1275 final List<Integer> listJ = nonResOrders.get(m);
1276
1277 for (int j: listJ) {
1278
1279 buildCoefficients(date, m, j);
1280 }
1281 }
1282 }
1283 }
1284
1285 }
1286
1287
1288
1289
1290
1291
1292
1293 private void buildCoefficients(final AbsoluteDate date, final int m, final int j) {
1294
1295 final double[] currentCijm = new double[] {0., 0., 0., 0., 0., 0.};
1296 final double[] currentSijm = new double[] {0., 0., 0., 0., 0., 0.};
1297
1298
1299 final double oojnmt = 1. / (j * meanMotion - m * centralBodyRotationRate);
1300
1301
1302 for (int i = 0; i < 6; i++) {
1303 currentCijm[i] = -cjsjFourier.getSijm(i, j, m);
1304 currentSijm[i] = cjsjFourier.getCijm(i, j, m);
1305 }
1306
1307 currentCijm[5] += tnota * oojnmt * cjsjFourier.getCijm(0, j, m);
1308 currentSijm[5] += tnota * oojnmt * cjsjFourier.getSijm(0, j, m);
1309
1310
1311 for (int i = 0; i < 6; i++) {
1312 currentCijm[i] *= oojnmt;
1313 currentSijm[i] *= oojnmt;
1314 }
1315
1316
1317 for (int i = 0; i < 6; i++) {
1318 cijm[m][j + jMax][i].addGridPoint(date, currentCijm[i]);
1319 sijm[m][j + jMax][i].addGridPoint(date, currentSijm[i]);
1320 }
1321 }
1322
1323
1324
1325
1326
1327
1328 public void resetCoefficients() {
1329 for (int m = 1; m <= mMax; m++) {
1330 for (int j = -jMax; j <= jMax; j++) {
1331 for (int i = 0; i < 6; i++) {
1332 this.cijm[m][j + jMax][i].clearHistory();
1333 this.sijm[m][j + jMax][i].clearHistory();
1334 }
1335 }
1336 }
1337 }
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347 public double getCijm(final int i, final int j, final int m, final AbsoluteDate date) {
1348 return cijm[m][j + jMax][i].value(date);
1349 }
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359 public double getSijm(final int i, final int j, final int m, final AbsoluteDate date) {
1360 return sijm[m][j + jMax][i].value(date);
1361 }
1362 }
1363 }