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.lang.reflect.Array;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.SortedMap;
28 import java.util.TreeMap;
29
30 import org.hipparchus.CalculusFieldElement;
31 import org.hipparchus.Field;
32 import org.hipparchus.analysis.differentiation.FieldGradient;
33 import org.hipparchus.exception.LocalizedCoreFormats;
34 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
35 import org.hipparchus.geometry.euclidean.threed.Vector3D;
36 import org.hipparchus.util.FastMath;
37 import org.hipparchus.util.FieldSinCos;
38 import org.hipparchus.util.MathArrays;
39 import org.hipparchus.util.MathUtils;
40 import org.hipparchus.util.SinCos;
41 import org.orekit.attitudes.AttitudeProvider;
42 import org.orekit.errors.OrekitException;
43 import org.orekit.errors.OrekitInternalError;
44 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
45 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider.UnnormalizedSphericalHarmonics;
46 import org.orekit.frames.FieldStaticTransform;
47 import org.orekit.frames.Frame;
48 import org.orekit.frames.StaticTransform;
49 import org.orekit.orbits.FieldOrbit;
50 import org.orekit.orbits.Orbit;
51 import org.orekit.propagation.FieldSpacecraftState;
52 import org.orekit.propagation.PropagationType;
53 import org.orekit.propagation.SpacecraftState;
54 import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
55 import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory;
56 import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
57 import org.orekit.propagation.semianalytical.dsst.utilities.FieldGHmsjPolynomials;
58 import org.orekit.propagation.semianalytical.dsst.utilities.FieldGammaMnsFunction;
59 import org.orekit.propagation.semianalytical.dsst.utilities.FieldShortPeriodicsInterpolatedCoefficient;
60 import org.orekit.propagation.semianalytical.dsst.utilities.GHmsjPolynomials;
61 import org.orekit.propagation.semianalytical.dsst.utilities.GammaMnsFunction;
62 import org.orekit.propagation.semianalytical.dsst.utilities.JacobiPolynomials;
63 import org.orekit.propagation.semianalytical.dsst.utilities.ShortPeriodicsInterpolatedCoefficient;
64 import org.orekit.propagation.semianalytical.dsst.utilities.hansen.FieldHansenTesseralLinear;
65 import org.orekit.propagation.semianalytical.dsst.utilities.hansen.HansenTesseralLinear;
66 import org.orekit.time.AbsoluteDate;
67 import org.orekit.time.FieldAbsoluteDate;
68 import org.orekit.utils.FieldTimeSpanMap;
69 import org.orekit.utils.ParameterDriver;
70 import org.orekit.utils.TimeSpanMap;
71
72
73
74
75
76
77
78
79
80
81 public class DSSTTesseral implements DSSTForceModel {
82
83
84 public static final String SHORT_PERIOD_PREFIX = "DSST-central-body-tesseral-";
85
86
87 public static final String CM_COEFFICIENTS = "cM";
88
89
90 public static final String SM_COEFFICIENTS = "sM";
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 private static final int I = 1;
106
107
108
109
110
111
112
113 private static final double MU_SCALE = FastMath.scalb(1.0, 32);
114
115
116
117
118 private static final double MIN_PERIOD_IN_SECONDS = 864000.;
119
120
121
122
123 private static final double MIN_PERIOD_IN_SAT_REV = 10.;
124
125
126 private static final int INTERPOLATION_POINTS = 3;
127
128
129 private final UnnormalizedSphericalHarmonicsProvider provider;
130
131
132 private final Frame bodyFrame;
133
134
135 private final double centralBodyRotationRate;
136
137
138 private final double bodyPeriod;
139
140
141 private final int maxDegree;
142
143
144 private final int maxDegreeTesseralSP;
145
146
147 private final int maxDegreeMdailyTesseralSP;
148
149
150 private final int maxOrder;
151
152
153 private final int maxOrderTesseralSP;
154
155
156 private final int maxOrderMdailyTesseralSP;
157
158
159
160 private final int maxEccPowTesseralSP;
161
162
163
164 private final int maxEccPowMdailyTesseralSP;
165
166
167 private final int maxFrequencyShortPeriodics;
168
169
170 private int maxEccPow;
171
172
173 private int maxHansen;
174
175
176 private int mMax;
177
178
179 private final SortedMap<Integer, List<Integer> > nonResOrders;
180
181
182 private final List<Integer> resOrders;
183
184
185 private TesseralShortPeriodicCoefficients shortPeriodTerms;
186
187
188 private Map<Field<?>, FieldTesseralShortPeriodicCoefficients<?>> fieldShortPeriodTerms;
189
190
191 private final ParameterDriver gmParameterDriver;
192
193
194 private HansenObjects hansen;
195
196
197 private Map<Field<?>, FieldHansenObjects<?>> fieldHansen;
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220 public DSSTTesseral(final Frame centralBodyFrame,
221 final double centralBodyRotationRate,
222 final UnnormalizedSphericalHarmonicsProvider provider) {
223 this(centralBodyFrame, centralBodyRotationRate, provider, provider.getMaxDegree(),
224 provider.getMaxOrder(), FastMath.min(4, provider.getMaxOrder()), FastMath.min(12, provider.getMaxDegree() + 4),
225 provider.getMaxDegree(), provider.getMaxOrder(), FastMath.min(4, provider.getMaxDegree() - 2));
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252 public DSSTTesseral(final Frame centralBodyFrame,
253 final double centralBodyRotationRate,
254 final UnnormalizedSphericalHarmonicsProvider provider,
255 final int maxDegreeTesseralSP, final int maxOrderTesseralSP,
256 final int maxEccPowTesseralSP, final int maxFrequencyShortPeriodics,
257 final int maxDegreeMdailyTesseralSP, final int maxOrderMdailyTesseralSP,
258 final int maxEccPowMdailyTesseralSP) {
259
260 gmParameterDriver = new ParameterDriver(DSSTNewtonianAttraction.CENTRAL_ATTRACTION_COEFFICIENT,
261 provider.getMu(), MU_SCALE,
262 0.0, Double.POSITIVE_INFINITY);
263
264
265 this.bodyFrame = centralBodyFrame;
266
267
268 this.centralBodyRotationRate = centralBodyRotationRate;
269
270
271 this.bodyPeriod = MathUtils.TWO_PI / centralBodyRotationRate;
272
273
274 this.provider = provider;
275 this.maxDegree = provider.getMaxDegree();
276 this.maxOrder = provider.getMaxOrder();
277
278
279 checkIndexRange(maxDegreeTesseralSP, 2, maxDegree);
280 this.maxDegreeTesseralSP = maxDegreeTesseralSP;
281
282 checkIndexRange(maxDegreeMdailyTesseralSP, 2, maxDegree);
283 this.maxDegreeMdailyTesseralSP = maxDegreeMdailyTesseralSP;
284
285 checkIndexRange(maxOrderTesseralSP, 0, maxOrder);
286 this.maxOrderTesseralSP = maxOrderTesseralSP;
287
288 checkIndexRange(maxOrderMdailyTesseralSP, 0, maxOrder);
289 this.maxOrderMdailyTesseralSP = maxOrderMdailyTesseralSP;
290
291
292 if (maxOrder > 0) {
293
294 checkIndexRange(maxEccPowTesseralSP, 0, maxOrder);
295 }
296 this.maxEccPowTesseralSP = maxEccPowTesseralSP;
297
298 checkIndexRange(maxEccPowMdailyTesseralSP, 0, maxDegreeMdailyTesseralSP - 2);
299 this.maxEccPowMdailyTesseralSP = maxEccPowMdailyTesseralSP;
300
301
302 this.maxFrequencyShortPeriodics = maxFrequencyShortPeriodics;
303
304
305 this.resOrders = new ArrayList<>();
306 this.nonResOrders = new TreeMap<>();
307
308
309 this.fieldShortPeriodTerms = new HashMap<>();
310 this.fieldHansen = new HashMap<>();
311 this.maxEccPow = 0;
312 this.maxHansen = 0;
313
314 }
315
316
317
318
319
320
321 private void checkIndexRange(final int index, final int min, final int max) {
322 if (index < min || index > max) {
323 throw new OrekitException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, index, min, max);
324 }
325 }
326
327
328 @Override
329 public List<ShortPeriodTerms> initializeShortPeriodTerms(final AuxiliaryElements auxiliaryElements,
330 final PropagationType type,
331 final double[] parameters) {
332
333
334
335 final DSSTTesseralContext context = initializeStep(auxiliaryElements, parameters);
336
337
338
339
340 maxEccPow = getMaxEccPow(auxiliaryElements.getEcc());
341
342
343 maxHansen = maxEccPow / 2;
344
345
346 final double ratio = context.getRatio();
347
348
349 getResonantAndNonResonantTerms(type, context.getOrbitPeriod(), ratio);
350
351 hansen = new HansenObjects(ratio, type);
352
353 mMax = FastMath.max(maxOrderTesseralSP, maxOrderMdailyTesseralSP);
354
355 shortPeriodTerms = new TesseralShortPeriodicCoefficients(bodyFrame, maxOrderMdailyTesseralSP,
356 maxDegreeTesseralSP < 0, nonResOrders,
357 mMax, maxFrequencyShortPeriodics, INTERPOLATION_POINTS,
358 new TimeSpanMap<>(new Slot(mMax, maxFrequencyShortPeriodics, INTERPOLATION_POINTS)));
359
360 final List<ShortPeriodTerms> list = new ArrayList<>();
361 list.add(shortPeriodTerms);
362 return list;
363
364 }
365
366
367 @Override
368 public <T extends CalculusFieldElement<T>> List<FieldShortPeriodTerms<T>> initializeShortPeriodTerms(final FieldAuxiliaryElements<T> auxiliaryElements,
369 final PropagationType type,
370 final T[] parameters) {
371
372
373 final Field<T> field = auxiliaryElements.getDate().getField();
374
375
376 final FieldDSSTTesseralContext<T> context = initializeStep(auxiliaryElements, parameters);
377
378
379
380
381 maxEccPow = getMaxEccPow(auxiliaryElements.getEcc().getReal());
382
383
384 maxHansen = maxEccPow / 2;
385
386
387 final T ratio = context.getRatio();
388
389
390
391 getResonantAndNonResonantTerms(type, context.getOrbitPeriod().getReal(), ratio.getReal());
392
393 mMax = FastMath.max(maxOrderTesseralSP, maxOrderMdailyTesseralSP);
394
395 fieldHansen.put(field, new FieldHansenObjects<>(ratio, type));
396
397 final FieldTesseralShortPeriodicCoefficients<T> ftspc =
398 new FieldTesseralShortPeriodicCoefficients<>(bodyFrame, maxOrderMdailyTesseralSP,
399 maxDegreeTesseralSP < 0, nonResOrders,
400 mMax, maxFrequencyShortPeriodics, INTERPOLATION_POINTS,
401 new FieldTimeSpanMap<>(new FieldSlot<>(mMax,
402 maxFrequencyShortPeriodics,
403 INTERPOLATION_POINTS),
404 field));
405
406 fieldShortPeriodTerms.put(field, ftspc);
407 return Collections.singletonList(ftspc);
408
409 }
410
411
412
413
414
415
416 private int getMaxEccPow(final double e) {
417
418 if (e <= 0.005) {
419 return 3;
420 } else if (e <= 0.02) {
421 return 4;
422 } else if (e <= 0.1) {
423 return 7;
424 } else if (e <= 0.2) {
425 return 10;
426 } else if (e <= 0.3) {
427 return 12;
428 } else if (e <= 0.4) {
429 return 15;
430 } else {
431 return 20;
432 }
433 }
434
435
436
437
438
439
440
441
442
443
444
445
446 private DSSTTesseralContext initializeStep(final AuxiliaryElements auxiliaryElements, final double[] parameters) {
447 return new DSSTTesseralContext(auxiliaryElements, bodyFrame, provider, maxFrequencyShortPeriodics, bodyPeriod, parameters);
448 }
449
450
451
452
453
454
455
456
457
458
459
460 private <T extends CalculusFieldElement<T>> FieldDSSTTesseralContext<T> initializeStep(final FieldAuxiliaryElements<T> auxiliaryElements,
461 final T[] parameters) {
462 return new FieldDSSTTesseralContext<>(auxiliaryElements, bodyFrame, provider, maxFrequencyShortPeriodics, bodyPeriod, parameters);
463 }
464
465
466 @Override
467 public double[] getMeanElementRate(final SpacecraftState spacecraftState,
468 final AuxiliaryElements auxiliaryElements, final double[] parameters) {
469
470
471
472 final DSSTTesseralContext context = initializeStep(auxiliaryElements, parameters);
473
474
475 final UAnddU udu = new UAnddU(spacecraftState.getDate(), context, hansen);
476
477
478 final double UAlphaGamma = context.getAlpha() * udu.getdUdGa() - context.getGamma() * udu.getdUdAl();
479 final double UAlphaBeta = context.getAlpha() * udu.getdUdBe() - context.getBeta() * udu.getdUdAl();
480 final double UBetaGamma = context.getBeta() * udu.getdUdGa() - context.getGamma() * udu.getdUdBe();
481 final double Uhk = auxiliaryElements.getH() * udu.getdUdk() - auxiliaryElements.getK() * udu.getdUdh();
482 final double pUagmIqUbgoAB = (auxiliaryElements.getP() * UAlphaGamma - I * auxiliaryElements.getQ() * UBetaGamma) * context.getOoAB();
483 final double UhkmUabmdUdl = Uhk - UAlphaBeta - udu.getdUdl();
484
485 final double da = context.getAx2oA() * udu.getdUdl();
486 final double dh = context.getBoA() * udu.getdUdk() + auxiliaryElements.getK() * pUagmIqUbgoAB - auxiliaryElements.getH() * context.getBoABpo() * udu.getdUdl();
487 final double dk = -(context.getBoA() * udu.getdUdh() + auxiliaryElements.getH() * pUagmIqUbgoAB + auxiliaryElements.getK() * context.getBoABpo() * udu.getdUdl());
488 final double dp = context.getCo2AB() * (auxiliaryElements.getP() * UhkmUabmdUdl - UBetaGamma);
489 final double dq = context.getCo2AB() * (auxiliaryElements.getQ() * UhkmUabmdUdl - I * UAlphaGamma);
490 final double dM = -context.getAx2oA() * udu.getdUda() + context.getBoABpo() * (auxiliaryElements.getH() * udu.getdUdh() + auxiliaryElements.getK() * udu.getdUdk()) + pUagmIqUbgoAB;
491
492 return new double[] {da, dk, dh, dq, dp, dM};
493 }
494
495
496 @Override
497 public <T extends CalculusFieldElement<T>> T[] getMeanElementRate(final FieldSpacecraftState<T> spacecraftState,
498 final FieldAuxiliaryElements<T> auxiliaryElements,
499 final T[] parameters) {
500
501
502 final Field<T> field = auxiliaryElements.getDate().getField();
503
504
505
506 final FieldDSSTTesseralContext<T> context = initializeStep(auxiliaryElements, parameters);
507
508 @SuppressWarnings("unchecked")
509 final FieldHansenObjects<T> fho = (FieldHansenObjects<T>) fieldHansen.get(field);
510
511 final FieldUAnddU<T> udu = new FieldUAnddU<>(spacecraftState.getDate(), context, fho);
512
513
514 final T UAlphaGamma = udu.getdUdGa().multiply(context.getAlpha()).subtract(udu.getdUdAl().multiply(context.getGamma()));
515 final T UAlphaBeta = udu.getdUdBe().multiply(context.getAlpha()).subtract(udu.getdUdAl().multiply(context.getBeta()));
516 final T UBetaGamma = udu.getdUdGa().multiply(context.getBeta()).subtract(udu.getdUdBe().multiply(context.getGamma()));
517 final T Uhk = udu.getdUdk().multiply(auxiliaryElements.getH()).subtract(udu.getdUdh().multiply(auxiliaryElements.getK()));
518 final T pUagmIqUbgoAB = (UAlphaGamma.multiply(auxiliaryElements.getP()).subtract(UBetaGamma.multiply(auxiliaryElements.getQ()).multiply(I))).multiply(context.getOoAB());
519 final T UhkmUabmdUdl = Uhk.subtract(UAlphaBeta).subtract(udu.getdUdl());
520
521 final T da = udu.getdUdl().multiply(context.getAx2oA());
522 final T dh = udu.getdUdk().multiply(context.getBoA()).add(pUagmIqUbgoAB.multiply(auxiliaryElements.getK())).subtract(udu.getdUdl().multiply(auxiliaryElements.getH()).multiply(context.getBoABpo()));
523 final T dk = (udu.getdUdh().multiply(context.getBoA()).add(pUagmIqUbgoAB.multiply(auxiliaryElements.getH())).add(udu.getdUdl().multiply(context.getBoABpo()).multiply(auxiliaryElements.getK()))).negate();
524 final T dp = context.getCo2AB().multiply(auxiliaryElements.getP().multiply(UhkmUabmdUdl).subtract(UBetaGamma));
525 final T dq = context.getCo2AB().multiply(auxiliaryElements.getQ().multiply(UhkmUabmdUdl).subtract(UAlphaGamma.multiply(I)));
526 final T dM = pUagmIqUbgoAB.add(udu.getdUda().multiply(context.getAx2oA()).negate()).add((udu.getdUdh().multiply(auxiliaryElements.getH()).add(udu.getdUdk().multiply(auxiliaryElements.getK()))).multiply(context.getBoABpo()));
527
528 final T[] elements = MathArrays.buildArray(field, 6);
529 elements[0] = da;
530 elements[1] = dk;
531 elements[2] = dh;
532 elements[3] = dq;
533 elements[4] = dp;
534 elements[5] = dM;
535
536 return elements;
537
538 }
539
540
541 @Override
542 public void updateShortPeriodTerms(final double[] parameters, final SpacecraftState... meanStates) {
543
544 final Slot slot = shortPeriodTerms.createSlot(meanStates);
545
546 for (final SpacecraftState meanState : meanStates) {
547
548 final AuxiliaryElements auxiliaryElements = new AuxiliaryElements(meanState.getOrbit(), I);
549
550
551 final double[] extractedParameters = this.extractParameters(parameters, auxiliaryElements.getDate());
552 final DSSTTesseralContext context = initializeStep(auxiliaryElements, extractedParameters);
553
554
555 for (int s = -maxDegree; s <= maxDegree; s++) {
556
557 hansen.computeHansenObjectsInitValues(context, s + maxDegree, 0);
558 if (maxDegreeTesseralSP >= 0) {
559
560 for (int j = 1; j <= maxFrequencyShortPeriodics; j++) {
561 hansen.computeHansenObjectsInitValues(context, s + maxDegree, j);
562 }
563 }
564 }
565
566 final FourierCjSjCoefficients cjsjFourier = new FourierCjSjCoefficients(maxFrequencyShortPeriodics, mMax);
567
568
569
570 if (!nonResOrders.isEmpty() || maxDegreeTesseralSP < 0) {
571
572 cjsjFourier.generateCoefficients(meanState.getDate(), context, hansen);
573
574
575 final double tnota = 1.5 * context.getMeanMotion() / auxiliaryElements.getSma();
576
577
578 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
579
580 buildCoefficients(cjsjFourier, meanState.getDate(), slot, m, 0, tnota, context);
581 }
582
583 if (maxDegreeTesseralSP >= 0) {
584
585 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
586
587 for (int j : entry.getValue()) {
588
589 buildCoefficients(cjsjFourier, meanState.getDate(), slot, entry.getKey(), j, tnota, context);
590 }
591 }
592 }
593 }
594
595 }
596
597 }
598
599
600 @Override
601 @SuppressWarnings("unchecked")
602 public <T extends CalculusFieldElement<T>> void updateShortPeriodTerms(final T[] parameters,
603 final FieldSpacecraftState<T>... meanStates) {
604
605
606 final Field<T> field = meanStates[0].getDate().getField();
607
608 final FieldTesseralShortPeriodicCoefficients<T> ftspc = (FieldTesseralShortPeriodicCoefficients<T>) fieldShortPeriodTerms.get(field);
609 final FieldSlot<T> slot = ftspc.createSlot(meanStates);
610
611 for (final FieldSpacecraftState<T> meanState : meanStates) {
612
613 final FieldAuxiliaryElements<T> auxiliaryElements = new FieldAuxiliaryElements<>(meanState.getOrbit(), I);
614
615
616 final T[] extractedParameters = this.extractParameters(parameters, auxiliaryElements.getDate());
617 final FieldDSSTTesseralContext<T> context = initializeStep(auxiliaryElements, extractedParameters);
618
619 final FieldHansenObjects<T> fho = (FieldHansenObjects<T>) fieldHansen.get(field);
620
621 for (int s = -maxDegree; s <= maxDegree; s++) {
622
623 fho.computeHansenObjectsInitValues(context, s + maxDegree, 0);
624 if (maxDegreeTesseralSP >= 0) {
625
626 for (int j = 1; j <= maxFrequencyShortPeriodics; j++) {
627 fho.computeHansenObjectsInitValues(context, s + maxDegree, j);
628 }
629 }
630 }
631
632 final FieldFourierCjSjCoefficients<T> cjsjFourier = new FieldFourierCjSjCoefficients<>(maxFrequencyShortPeriodics, mMax, field);
633
634
635
636 if (!nonResOrders.isEmpty() || maxDegreeTesseralSP < 0) {
637
638 cjsjFourier.generateCoefficients(meanState.getDate(), context, fho, field);
639
640
641 final T tnota = context.getMeanMotion().multiply(1.5).divide(auxiliaryElements.getSma());
642
643
644 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
645
646 buildCoefficients(cjsjFourier, meanState.getDate(), slot, m, 0, tnota, context, field);
647 }
648
649 if (maxDegreeTesseralSP >= 0) {
650
651 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
652
653 for (int j : entry.getValue()) {
654
655 buildCoefficients(cjsjFourier, meanState.getDate(), slot, entry.getKey(), j, tnota, context, field);
656 }
657 }
658 }
659 }
660
661 }
662
663 }
664
665
666 public List<ParameterDriver> getParametersDrivers() {
667 return Collections.singletonList(gmParameterDriver);
668 }
669
670
671
672
673
674
675
676
677
678
679 private void buildCoefficients(final FourierCjSjCoefficients cjsjFourier,
680 final AbsoluteDate date, final Slot slot,
681 final int m, final int j, final double tnota, final DSSTTesseralContext context) {
682
683
684 final double[] currentCijm = new double[] {0., 0., 0., 0., 0., 0.};
685 final double[] currentSijm = new double[] {0., 0., 0., 0., 0., 0.};
686
687
688 final double oojnmt = 1. / (j * context.getMeanMotion() - m * centralBodyRotationRate);
689
690
691 for (int i = 0; i < 6; i++) {
692 currentCijm[i] = -cjsjFourier.getSijm(i, j, m);
693 currentSijm[i] = cjsjFourier.getCijm(i, j, m);
694 }
695
696 currentCijm[5] += tnota * oojnmt * cjsjFourier.getCijm(0, j, m);
697 currentSijm[5] += tnota * oojnmt * cjsjFourier.getSijm(0, j, m);
698
699
700 for (int i = 0; i < 6; i++) {
701 currentCijm[i] *= oojnmt;
702 currentSijm[i] *= oojnmt;
703 }
704
705
706 slot.cijm[m][j + maxFrequencyShortPeriodics].addGridPoint(date, currentCijm);
707 slot.sijm[m][j + maxFrequencyShortPeriodics].addGridPoint(date, currentSijm);
708
709 }
710
711
712
713
714
715
716
717
718
719
720
721
722 private <T extends CalculusFieldElement<T>> void buildCoefficients(final FieldFourierCjSjCoefficients<T> cjsjFourier,
723 final FieldAbsoluteDate<T> date,
724 final FieldSlot<T> slot,
725 final int m, final int j, final T tnota,
726 final FieldDSSTTesseralContext<T> context,
727 final Field<T> field) {
728
729
730 final T zero = field.getZero();
731
732
733 final T[] currentCijm = MathArrays.buildArray(field, 6);
734 final T[] currentSijm = MathArrays.buildArray(field, 6);
735
736 Arrays.fill(currentCijm, zero);
737 Arrays.fill(currentSijm, zero);
738
739
740 final T oojnmt = (context.getMeanMotion().multiply(j).subtract(m * centralBodyRotationRate)).reciprocal();
741
742
743 for (int i = 0; i < 6; i++) {
744 currentCijm[i] = cjsjFourier.getSijm(i, j, m).negate();
745 currentSijm[i] = cjsjFourier.getCijm(i, j, m);
746 }
747
748 currentCijm[5] = currentCijm[5].add(tnota.multiply(oojnmt).multiply(cjsjFourier.getCijm(0, j, m)));
749 currentSijm[5] = currentSijm[5].add(tnota.multiply(oojnmt).multiply(cjsjFourier.getSijm(0, j, m)));
750
751
752 for (int i = 0; i < 6; i++) {
753 currentCijm[i] = currentCijm[i].multiply(oojnmt);
754 currentSijm[i] = currentSijm[i].multiply(oojnmt);
755 }
756
757
758 slot.cijm[m][j + maxFrequencyShortPeriodics].addGridPoint(date, currentCijm);
759 slot.sijm[m][j + maxFrequencyShortPeriodics].addGridPoint(date, currentSijm);
760
761 }
762
763
764
765
766
767
768
769
770 private void getResonantAndNonResonantTerms(final PropagationType type, final double orbitPeriod,
771 final double ratio) {
772
773
774 final double tolerance = 1. / FastMath.max(MIN_PERIOD_IN_SAT_REV,
775 MIN_PERIOD_IN_SECONDS / orbitPeriod);
776
777
778 resOrders.clear();
779 nonResOrders.clear();
780 for (int m = 1; m <= maxOrder; m++) {
781 final double resonance = ratio * m;
782 int jRes = 0;
783 final int jComputedRes = (int) FastMath.round(resonance);
784 if (jComputedRes > 0 && jComputedRes <= maxFrequencyShortPeriodics && FastMath.abs(resonance - jComputedRes) <= tolerance) {
785
786 resOrders.add(m);
787 jRes = jComputedRes;
788 }
789
790 if (type == PropagationType.OSCULATING && maxDegreeTesseralSP >= 0 && m <= maxOrderTesseralSP) {
791
792 final List<Integer> listJofM = new ArrayList<>();
793
794 for (int j = -maxFrequencyShortPeriodics; j <= maxFrequencyShortPeriodics; j++) {
795 if (j != 0 && j != jRes) {
796 listJofM.add(j);
797 }
798 }
799
800 nonResOrders.put(m, listJofM);
801 }
802 }
803 }
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818 private double[][] computeNSum(final AbsoluteDate date,
819 final int j, final int m, final int s, final int maxN, final double[] roaPow,
820 final GHmsjPolynomials ghMSJ, final GammaMnsFunction gammaMNS, final DSSTTesseralContext context,
821 final HansenObjects hansenObjects) {
822
823
824 final AuxiliaryElements auxiliaryElements = context.getAuxiliaryElements();
825
826
827 final UnnormalizedSphericalHarmonics harmonics = provider.onDate(date);
828
829
830 double dUdaCos = 0.;
831 double dUdaSin = 0.;
832 double dUdhCos = 0.;
833 double dUdhSin = 0.;
834 double dUdkCos = 0.;
835 double dUdkSin = 0.;
836 double dUdlCos = 0.;
837 double dUdlSin = 0.;
838 double dUdAlCos = 0.;
839 double dUdAlSin = 0.;
840 double dUdBeCos = 0.;
841 double dUdBeSin = 0.;
842 double dUdGaCos = 0.;
843 double dUdGaSin = 0.;
844
845
846 @SuppressWarnings("unused")
847 final int Im = I > 0 ? 1 : (m % 2 == 0 ? 1 : -1);
848
849
850 final int v = FastMath.abs(m - s);
851 final int w = FastMath.abs(m + s);
852
853
854 final int nmin = FastMath.max(FastMath.max(2, m), FastMath.abs(s));
855
856
857 final int sIndex = maxDegree + (j < 0 ? -s : s);
858 final int jIndex = FastMath.abs(j);
859 final HansenTesseralLinear hans = hansenObjects.getHansenObjects()[sIndex][jIndex];
860
861
862 for (int n = nmin; n <= maxN; n++) {
863
864 if ((n - s) % 2 == 0) {
865
866
867 final double vMNS = CoefficientsFactory.getVmns(m, n, s);
868
869
870 final double gaMNS = gammaMNS.getValue(m, n, s);
871 final double dGaMNS = gammaMNS.getDerivative(m, n, s);
872
873
874 final double kJNS = hans.getValue(-n - 1, context.getChi());
875 final double dkJNS = hans.getDerivative(-n - 1, context.getChi());
876
877
878 final double gMSJ = ghMSJ.getGmsj(m, s, j);
879 final double hMSJ = ghMSJ.getHmsj(m, s, j);
880 final double dGdh = ghMSJ.getdGmsdh(m, s, j);
881 final double dGdk = ghMSJ.getdGmsdk(m, s, j);
882 final double dGdA = ghMSJ.getdGmsdAlpha(m, s, j);
883 final double dGdB = ghMSJ.getdGmsdBeta(m, s, j);
884 final double dHdh = ghMSJ.getdHmsdh(m, s, j);
885 final double dHdk = ghMSJ.getdHmsdk(m, s, j);
886 final double dHdA = ghMSJ.getdHmsdAlpha(m, s, j);
887 final double dHdB = ghMSJ.getdHmsdBeta(m, s, j);
888
889
890 final int l = FastMath.min(n - m, n - FastMath.abs(s));
891
892 final double[] jacobi = JacobiPolynomials.getValueAndDerivative(l, v, w, context.getGamma());
893
894
895 final double cnm = harmonics.getUnnormalizedCnm(n, m);
896 final double snm = harmonics.getUnnormalizedSnm(n, m);
897
898
899 final double cf_0 = roaPow[n] * Im * vMNS;
900 final double cf_1 = cf_0 * gaMNS * jacobi[0];
901 final double cf_2 = cf_1 * kJNS;
902 final double gcPhs = gMSJ * cnm + hMSJ * snm;
903 final double gsMhc = gMSJ * snm - hMSJ * cnm;
904 final double dKgcPhsx2 = 2. * dkJNS * gcPhs;
905 final double dKgsMhcx2 = 2. * dkJNS * gsMhc;
906 final double dUdaCoef = (n + 1) * cf_2;
907 final double dUdlCoef = j * cf_2;
908
909 final double dUdGaCoef = cf_0 * kJNS * (jacobi[0] * dGaMNS + gaMNS * jacobi[1]);
910
911
912 dUdaCos += dUdaCoef * gcPhs;
913 dUdaSin += dUdaCoef * gsMhc;
914
915
916 dUdhCos += cf_1 * (kJNS * (cnm * dGdh + snm * dHdh) + auxiliaryElements.getH() * dKgcPhsx2);
917 dUdhSin += cf_1 * (kJNS * (snm * dGdh - cnm * dHdh) + auxiliaryElements.getH() * dKgsMhcx2);
918
919
920 dUdkCos += cf_1 * (kJNS * (cnm * dGdk + snm * dHdk) + auxiliaryElements.getK() * dKgcPhsx2);
921 dUdkSin += cf_1 * (kJNS * (snm * dGdk - cnm * dHdk) + auxiliaryElements.getK() * dKgsMhcx2);
922
923
924 dUdlCos += dUdlCoef * gsMhc;
925 dUdlSin += -dUdlCoef * gcPhs;
926
927
928 dUdAlCos += cf_2 * (dGdA * cnm + dHdA * snm);
929 dUdAlSin += cf_2 * (dGdA * snm - dHdA * cnm);
930
931
932 dUdBeCos += cf_2 * (dGdB * cnm + dHdB * snm);
933 dUdBeSin += cf_2 * (dGdB * snm - dHdB * cnm);
934
935
936 dUdGaCos += dUdGaCoef * gcPhs;
937 dUdGaSin += dUdGaCoef * gsMhc;
938 }
939 }
940
941 return new double[][] { { dUdaCos, dUdaSin },
942 { dUdhCos, dUdhSin },
943 { dUdkCos, dUdkSin },
944 { dUdlCos, dUdlSin },
945 { dUdAlCos, dUdAlSin },
946 { dUdBeCos, dUdBeSin },
947 { dUdGaCos, dUdGaSin } };
948 }
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964 private <T extends CalculusFieldElement<T>> T[][] computeNSum(final FieldAbsoluteDate<T> date,
965 final int j, final int m, final int s, final int maxN,
966 final T[] roaPow,
967 final FieldGHmsjPolynomials<T> ghMSJ,
968 final FieldGammaMnsFunction<T> gammaMNS,
969 final FieldDSSTTesseralContext<T> context,
970 final FieldHansenObjects<T> hansenObjects) {
971
972
973 final FieldAuxiliaryElements<T> auxiliaryElements = context.getFieldAuxiliaryElements();
974
975 final Field<T> field = date.getField();
976 final T zero = field.getZero();
977
978
979 final UnnormalizedSphericalHarmonics harmonics = provider.onDate(date.toAbsoluteDate());
980
981
982 T dUdaCos = zero;
983 T dUdaSin = zero;
984 T dUdhCos = zero;
985 T dUdhSin = zero;
986 T dUdkCos = zero;
987 T dUdkSin = zero;
988 T dUdlCos = zero;
989 T dUdlSin = zero;
990 T dUdAlCos = zero;
991 T dUdAlSin = zero;
992 T dUdBeCos = zero;
993 T dUdBeSin = zero;
994 T dUdGaCos = zero;
995 T dUdGaSin = zero;
996
997
998 @SuppressWarnings("unused")
999 final int Im = I > 0 ? 1 : (m % 2 == 0 ? 1 : -1);
1000
1001
1002 final int v = FastMath.abs(m - s);
1003 final int w = FastMath.abs(m + s);
1004
1005
1006 final int nmin = FastMath.max(FastMath.max(2, m), FastMath.abs(s));
1007
1008
1009 final int sIndex = maxDegree + (j < 0 ? -s : s);
1010 final int jIndex = FastMath.abs(j);
1011 final FieldHansenTesseralLinear<T> hans = hansenObjects.getHansenObjects()[sIndex][jIndex];
1012
1013
1014 for (int n = nmin; n <= maxN; n++) {
1015
1016 if ((n - s) % 2 == 0) {
1017
1018
1019 final T vMNS = zero.newInstance(CoefficientsFactory.getVmns(m, n, s));
1020
1021
1022 final T gaMNS = gammaMNS.getValue(m, n, s);
1023 final T dGaMNS = gammaMNS.getDerivative(m, n, s);
1024
1025
1026 final T kJNS = hans.getValue(-n - 1, context.getChi());
1027 final T dkJNS = hans.getDerivative(-n - 1, context.getChi());
1028
1029
1030 final T gMSJ = ghMSJ.getGmsj(m, s, j);
1031 final T hMSJ = ghMSJ.getHmsj(m, s, j);
1032 final T dGdh = ghMSJ.getdGmsdh(m, s, j);
1033 final T dGdk = ghMSJ.getdGmsdk(m, s, j);
1034 final T dGdA = ghMSJ.getdGmsdAlpha(m, s, j);
1035 final T dGdB = ghMSJ.getdGmsdBeta(m, s, j);
1036 final T dHdh = ghMSJ.getdHmsdh(m, s, j);
1037 final T dHdk = ghMSJ.getdHmsdk(m, s, j);
1038 final T dHdA = ghMSJ.getdHmsdAlpha(m, s, j);
1039 final T dHdB = ghMSJ.getdHmsdBeta(m, s, j);
1040
1041
1042 final int l = FastMath.min(n - m, n - FastMath.abs(s));
1043
1044 final FieldGradient<T> jacobi =
1045 JacobiPolynomials.getValue(l, v, w, FieldGradient.variable(1, 0, context.getGamma()));
1046
1047
1048 final T cnm = zero.newInstance(harmonics.getUnnormalizedCnm(n, m));
1049 final T snm = zero.newInstance(harmonics.getUnnormalizedSnm(n, m));
1050
1051
1052 final T cf_0 = roaPow[n].multiply(Im).multiply(vMNS);
1053 final T cf_1 = cf_0.multiply(gaMNS).multiply(jacobi.getValue());
1054 final T cf_2 = cf_1.multiply(kJNS);
1055 final T gcPhs = gMSJ.multiply(cnm).add(hMSJ.multiply(snm));
1056 final T gsMhc = gMSJ.multiply(snm).subtract(hMSJ.multiply(cnm));
1057 final T dKgcPhsx2 = dkJNS.multiply(gcPhs).multiply(2.);
1058 final T dKgsMhcx2 = dkJNS.multiply(gsMhc).multiply(2.);
1059 final T dUdaCoef = cf_2.multiply(n + 1);
1060 final T dUdlCoef = cf_2.multiply(j);
1061 final T dUdGaCoef = cf_0.multiply(kJNS).multiply(dGaMNS.multiply(jacobi.getValue()).add(gaMNS.multiply(jacobi.getGradient()[0])));
1062
1063
1064 dUdaCos = dUdaCos.add(dUdaCoef.multiply(gcPhs));
1065 dUdaSin = dUdaSin.add(dUdaCoef.multiply(gsMhc));
1066
1067
1068 dUdhCos = dUdhCos.add(cf_1.multiply(kJNS.multiply(cnm.multiply(dGdh).add(snm.multiply(dHdh))).add(dKgcPhsx2.multiply(auxiliaryElements.getH()))));
1069 dUdhSin = dUdhSin.add(cf_1.multiply(kJNS.multiply(snm.multiply(dGdh).subtract(cnm.multiply(dHdh))).add(dKgsMhcx2.multiply(auxiliaryElements.getH()))));
1070
1071
1072 dUdkCos = dUdkCos.add(cf_1.multiply(kJNS.multiply(cnm.multiply(dGdk).add(snm.multiply(dHdk))).add(dKgcPhsx2.multiply(auxiliaryElements.getK()))));
1073 dUdkSin = dUdkSin.add(cf_1.multiply(kJNS.multiply(snm.multiply(dGdk).subtract(cnm.multiply(dHdk))).add(dKgsMhcx2.multiply(auxiliaryElements.getK()))));
1074
1075
1076 dUdlCos = dUdlCos.add(dUdlCoef.multiply(gsMhc));
1077 dUdlSin = dUdlSin.add(dUdlCoef.multiply(gcPhs).negate());
1078
1079
1080 dUdAlCos = dUdAlCos.add(cf_2.multiply(dGdA.multiply(cnm).add(dHdA.multiply(snm))));
1081 dUdAlSin = dUdAlSin.add(cf_2.multiply(dGdA.multiply(snm).subtract(dHdA.multiply(cnm))));
1082
1083
1084 dUdBeCos = dUdBeCos.add(cf_2.multiply(dGdB.multiply(cnm).add(dHdB.multiply(snm))));
1085 dUdBeSin = dUdBeSin.add(cf_2.multiply(dGdB.multiply(snm).subtract(dHdB.multiply(cnm))));
1086
1087
1088 dUdGaCos = dUdGaCos.add(dUdGaCoef.multiply(gcPhs));
1089 dUdGaSin = dUdGaSin.add(dUdGaCoef.multiply(gsMhc));
1090 }
1091 }
1092
1093 final T[][] derivatives = MathArrays.buildArray(field, 7, 2);
1094 derivatives[0][0] = dUdaCos;
1095 derivatives[0][1] = dUdaSin;
1096 derivatives[1][0] = dUdhCos;
1097 derivatives[1][1] = dUdhSin;
1098 derivatives[2][0] = dUdkCos;
1099 derivatives[2][1] = dUdkSin;
1100 derivatives[3][0] = dUdlCos;
1101 derivatives[3][1] = dUdlSin;
1102 derivatives[4][0] = dUdAlCos;
1103 derivatives[4][1] = dUdAlSin;
1104 derivatives[5][0] = dUdBeCos;
1105 derivatives[5][1] = dUdBeSin;
1106 derivatives[6][0] = dUdGaCos;
1107 derivatives[6][1] = dUdGaSin;
1108
1109 return derivatives;
1110
1111 }
1112
1113
1114 @Override
1115 public void registerAttitudeProvider(final AttitudeProvider attitudeProvider) {
1116
1117 }
1118
1119
1120
1121
1122
1123
1124
1125 private class FourierCjSjCoefficients {
1126
1127
1128 private final int jMax;
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143 private final double[][][] cCoef;
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158 private final double[][][] sCoef;
1159
1160
1161 private GHmsjPolynomials ghMSJ;
1162
1163
1164 private GammaMnsFunction gammaMNS;
1165
1166
1167 private final double[] roaPow;
1168
1169
1170
1171
1172
1173 FourierCjSjCoefficients(final int jMax, final int mMax) {
1174
1175 final int rows = mMax + 1;
1176 final int columns = 2 * jMax + 1;
1177 this.jMax = jMax;
1178 this.cCoef = new double[rows][columns][6];
1179 this.sCoef = new double[rows][columns][6];
1180 this.roaPow = new double[maxDegree + 1];
1181 roaPow[0] = 1.;
1182 }
1183
1184
1185
1186
1187
1188
1189
1190 public void generateCoefficients(final AbsoluteDate date, final DSSTTesseralContext context,
1191 final HansenObjects hansenObjects) {
1192
1193 final AuxiliaryElements auxiliaryElements = context.getAuxiliaryElements();
1194
1195
1196 if (!nonResOrders.isEmpty() || maxDegreeTesseralSP < 0) {
1197
1198 ghMSJ = new GHmsjPolynomials(auxiliaryElements.getK(), auxiliaryElements.getH(), context.getAlpha(), context.getBeta(), I);
1199
1200
1201 gammaMNS = new GammaMnsFunction(maxDegree, context.getGamma(), I);
1202
1203 final int maxRoaPower = FastMath.max(maxDegreeTesseralSP, maxDegreeMdailyTesseralSP);
1204
1205
1206 for (int i = 1; i <= maxRoaPower; i++) {
1207 roaPow[i] = context.getRoa() * roaPow[i - 1];
1208 }
1209
1210
1211 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1212 buildFourierCoefficients(date, m, 0, maxDegreeMdailyTesseralSP, context, hansenObjects);
1213 }
1214
1215
1216 if (maxDegreeTesseralSP >= 0) {
1217 for (int m: nonResOrders.keySet()) {
1218 final List<Integer> listJ = nonResOrders.get(m);
1219
1220 for (int j: listJ) {
1221 buildFourierCoefficients(date, m, j, maxDegreeTesseralSP, context, hansenObjects);
1222 }
1223 }
1224 }
1225 }
1226 }
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237 private void buildFourierCoefficients(final AbsoluteDate date,
1238 final int m, final int j, final int maxN, final DSSTTesseralContext context,
1239 final HansenObjects hansenObjects) {
1240
1241 final AuxiliaryElements auxiliaryElements = context.getAuxiliaryElements();
1242
1243
1244 double dRdaCos = 0.;
1245 double dRdaSin = 0.;
1246 double dRdhCos = 0.;
1247 double dRdhSin = 0.;
1248 double dRdkCos = 0.;
1249 double dRdkSin = 0.;
1250 double dRdlCos = 0.;
1251 double dRdlSin = 0.;
1252 double dRdAlCos = 0.;
1253 double dRdAlSin = 0.;
1254 double dRdBeCos = 0.;
1255 double dRdBeSin = 0.;
1256 double dRdGaCos = 0.;
1257 double dRdGaSin = 0.;
1258
1259
1260 final int sMin = j == 0 ? maxEccPowMdailyTesseralSP : maxEccPowTesseralSP;
1261 final int sMax = j == 0 ? maxEccPowMdailyTesseralSP : maxEccPowTesseralSP;
1262 for (int s = 0; s <= sMax; s++) {
1263
1264
1265 final double[][] nSumSpos = computeNSum(date, j, m, s, maxN,
1266 roaPow, ghMSJ, gammaMNS, context, hansenObjects);
1267 dRdaCos += nSumSpos[0][0];
1268 dRdaSin += nSumSpos[0][1];
1269 dRdhCos += nSumSpos[1][0];
1270 dRdhSin += nSumSpos[1][1];
1271 dRdkCos += nSumSpos[2][0];
1272 dRdkSin += nSumSpos[2][1];
1273 dRdlCos += nSumSpos[3][0];
1274 dRdlSin += nSumSpos[3][1];
1275 dRdAlCos += nSumSpos[4][0];
1276 dRdAlSin += nSumSpos[4][1];
1277 dRdBeCos += nSumSpos[5][0];
1278 dRdBeSin += nSumSpos[5][1];
1279 dRdGaCos += nSumSpos[6][0];
1280 dRdGaSin += nSumSpos[6][1];
1281
1282
1283 if (s > 0 && s <= sMin) {
1284 final double[][] nSumSneg = computeNSum(date, j, m, -s, maxN,
1285 roaPow, ghMSJ, gammaMNS, context, hansenObjects);
1286 dRdaCos += nSumSneg[0][0];
1287 dRdaSin += nSumSneg[0][1];
1288 dRdhCos += nSumSneg[1][0];
1289 dRdhSin += nSumSneg[1][1];
1290 dRdkCos += nSumSneg[2][0];
1291 dRdkSin += nSumSneg[2][1];
1292 dRdlCos += nSumSneg[3][0];
1293 dRdlSin += nSumSneg[3][1];
1294 dRdAlCos += nSumSneg[4][0];
1295 dRdAlSin += nSumSneg[4][1];
1296 dRdBeCos += nSumSneg[5][0];
1297 dRdBeSin += nSumSneg[5][1];
1298 dRdGaCos += nSumSneg[6][0];
1299 dRdGaSin += nSumSneg[6][1];
1300 }
1301 }
1302 final double muOnA = context.getMuoa();
1303 dRdaCos *= -muOnA / auxiliaryElements.getSma();
1304 dRdaSin *= -muOnA / auxiliaryElements.getSma();
1305 dRdhCos *= muOnA;
1306 dRdhSin *= muOnA;
1307 dRdkCos *= muOnA;
1308 dRdkSin *= muOnA;
1309 dRdlCos *= muOnA;
1310 dRdlSin *= muOnA;
1311 dRdAlCos *= muOnA;
1312 dRdAlSin *= muOnA;
1313 dRdBeCos *= muOnA;
1314 dRdBeSin *= muOnA;
1315 dRdGaCos *= muOnA;
1316 dRdGaSin *= muOnA;
1317
1318
1319 final double RAlphaGammaCos = context.getAlpha() * dRdGaCos - context.getGamma() * dRdAlCos;
1320 final double RAlphaGammaSin = context.getAlpha() * dRdGaSin - context.getGamma() * dRdAlSin;
1321 final double RAlphaBetaCos = context.getAlpha() * dRdBeCos - context.getBeta() * dRdAlCos;
1322 final double RAlphaBetaSin = context.getAlpha() * dRdBeSin - context.getBeta() * dRdAlSin;
1323 final double RBetaGammaCos = context.getBeta() * dRdGaCos - context.getGamma() * dRdBeCos;
1324 final double RBetaGammaSin = context.getBeta() * dRdGaSin - context.getGamma() * dRdBeSin;
1325 final double RhkCos = auxiliaryElements.getH() * dRdkCos - auxiliaryElements.getK() * dRdhCos;
1326 final double RhkSin = auxiliaryElements.getH() * dRdkSin - auxiliaryElements.getK() * dRdhSin;
1327 final double pRagmIqRbgoABCos = (auxiliaryElements.getP() * RAlphaGammaCos - I * auxiliaryElements.getQ() * RBetaGammaCos) * context.getOoAB();
1328 final double pRagmIqRbgoABSin = (auxiliaryElements.getP() * RAlphaGammaSin - I * auxiliaryElements.getQ() * RBetaGammaSin) * context.getOoAB();
1329 final double RhkmRabmdRdlCos = RhkCos - RAlphaBetaCos - dRdlCos;
1330 final double RhkmRabmdRdlSin = RhkSin - RAlphaBetaSin - dRdlSin;
1331
1332
1333 cCoef[m][j + jMax][0] = context.getAx2oA() * dRdlCos;
1334 sCoef[m][j + jMax][0] = context.getAx2oA() * dRdlSin;
1335
1336
1337 cCoef[m][j + jMax][1] = -(context.getBoA() * dRdhCos + auxiliaryElements.getH() * pRagmIqRbgoABCos + auxiliaryElements.getK() * context.getBoABpo() * dRdlCos);
1338 sCoef[m][j + jMax][1] = -(context.getBoA() * dRdhSin + auxiliaryElements.getH() * pRagmIqRbgoABSin + auxiliaryElements.getK() * context.getBoABpo() * dRdlSin);
1339
1340
1341 cCoef[m][j + jMax][2] = context.getBoA() * dRdkCos + auxiliaryElements.getK() * pRagmIqRbgoABCos - auxiliaryElements.getH() * context.getBoABpo() * dRdlCos;
1342 sCoef[m][j + jMax][2] = context.getBoA() * dRdkSin + auxiliaryElements.getK() * pRagmIqRbgoABSin - auxiliaryElements.getH() * context.getBoABpo() * dRdlSin;
1343
1344
1345 cCoef[m][j + jMax][3] = context.getCo2AB() * (auxiliaryElements.getQ() * RhkmRabmdRdlCos - I * RAlphaGammaCos);
1346 sCoef[m][j + jMax][3] = context.getCo2AB() * (auxiliaryElements.getQ() * RhkmRabmdRdlSin - I * RAlphaGammaSin);
1347
1348
1349 cCoef[m][j + jMax][4] = context.getCo2AB() * (auxiliaryElements.getP() * RhkmRabmdRdlCos - RBetaGammaCos);
1350 sCoef[m][j + jMax][4] = context.getCo2AB() * (auxiliaryElements.getP() * RhkmRabmdRdlSin - RBetaGammaSin);
1351
1352
1353 cCoef[m][j + jMax][5] = -context.getAx2oA() * dRdaCos + context.getBoABpo() * (auxiliaryElements.getH() * dRdhCos + auxiliaryElements.getK() * dRdkCos) + pRagmIqRbgoABCos;
1354 sCoef[m][j + jMax][5] = -context.getAx2oA() * dRdaSin + context.getBoABpo() * (auxiliaryElements.getH() * dRdhSin + auxiliaryElements.getK() * dRdkSin) + pRagmIqRbgoABSin;
1355 }
1356
1357
1358
1359
1360
1361
1362
1363 public double getCijm(final int i, final int j, final int m) {
1364 return cCoef[m][j + jMax][i];
1365 }
1366
1367
1368
1369
1370
1371
1372
1373 public double getSijm(final int i, final int j, final int m) {
1374 return sCoef[m][j + jMax][i];
1375 }
1376 }
1377
1378
1379
1380
1381
1382
1383
1384 private class FieldFourierCjSjCoefficients <T extends CalculusFieldElement<T>> {
1385
1386
1387 private final int jMax;
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402 private final T[][][] cCoef;
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417 private final T[][][] sCoef;
1418
1419
1420 private FieldGHmsjPolynomials<T> ghMSJ;
1421
1422
1423 private FieldGammaMnsFunction<T> gammaMNS;
1424
1425
1426 private final T[] roaPow;
1427
1428
1429
1430
1431
1432
1433 FieldFourierCjSjCoefficients(final int jMax, final int mMax, final Field<T> field) {
1434
1435 final T zero = field.getZero();
1436 final int rows = mMax + 1;
1437 final int columns = 2 * jMax + 1;
1438 this.jMax = jMax;
1439 this.cCoef = MathArrays.buildArray(field, rows, columns, 6);
1440 this.sCoef = MathArrays.buildArray(field, rows, columns, 6);
1441 this.roaPow = MathArrays.buildArray(field, maxDegree + 1);
1442 roaPow[0] = zero.newInstance(1.);
1443 }
1444
1445
1446
1447
1448
1449
1450
1451
1452 public void generateCoefficients(final FieldAbsoluteDate<T> date,
1453 final FieldDSSTTesseralContext<T> context,
1454 final FieldHansenObjects<T> hansenObjects,
1455 final Field<T> field) {
1456
1457 final FieldAuxiliaryElements<T> auxiliaryElements = context.getFieldAuxiliaryElements();
1458
1459 if (!nonResOrders.isEmpty() || maxDegreeTesseralSP < 0) {
1460
1461 ghMSJ = new FieldGHmsjPolynomials<>(auxiliaryElements.getK(), auxiliaryElements.getH(), context.getAlpha(), context.getBeta(), I, field);
1462
1463
1464 gammaMNS = new FieldGammaMnsFunction<>(maxDegree, context.getGamma(), I, field);
1465
1466 final int maxRoaPower = FastMath.max(maxDegreeTesseralSP, maxDegreeMdailyTesseralSP);
1467
1468
1469 for (int i = 1; i <= maxRoaPower; i++) {
1470 roaPow[i] = context.getRoa().multiply(roaPow[i - 1]);
1471 }
1472
1473
1474 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1475 buildFourierCoefficients(date, m, 0, maxDegreeMdailyTesseralSP, context, hansenObjects, field);
1476 }
1477
1478
1479 if (maxDegreeTesseralSP >= 0) {
1480 for (int m: nonResOrders.keySet()) {
1481 final List<Integer> listJ = nonResOrders.get(m);
1482
1483 for (int j: listJ) {
1484 buildFourierCoefficients(date, m, j, maxDegreeTesseralSP, context, hansenObjects, field);
1485 }
1486 }
1487 }
1488 }
1489 }
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501 private void buildFourierCoefficients(final FieldAbsoluteDate<T> date,
1502 final int m, final int j, final int maxN,
1503 final FieldDSSTTesseralContext<T> context,
1504 final FieldHansenObjects<T> hansenObjects,
1505 final Field<T> field) {
1506
1507
1508 final T zero = field.getZero();
1509
1510 final FieldAuxiliaryElements<T> auxiliaryElements = context.getFieldAuxiliaryElements();
1511
1512
1513 T dRdaCos = zero;
1514 T dRdaSin = zero;
1515 T dRdhCos = zero;
1516 T dRdhSin = zero;
1517 T dRdkCos = zero;
1518 T dRdkSin = zero;
1519 T dRdlCos = zero;
1520 T dRdlSin = zero;
1521 T dRdAlCos = zero;
1522 T dRdAlSin = zero;
1523 T dRdBeCos = zero;
1524 T dRdBeSin = zero;
1525 T dRdGaCos = zero;
1526 T dRdGaSin = zero;
1527
1528
1529 final int sMin = j == 0 ? maxEccPowMdailyTesseralSP : maxEccPowTesseralSP;
1530 final int sMax = j == 0 ? maxEccPowMdailyTesseralSP : maxEccPowTesseralSP;
1531 for (int s = 0; s <= sMax; s++) {
1532
1533
1534 final T[][] nSumSpos = computeNSum(date, j, m, s, maxN,
1535 roaPow, ghMSJ, gammaMNS, context, hansenObjects);
1536 dRdaCos = dRdaCos.add(nSumSpos[0][0]);
1537 dRdaSin = dRdaSin.add(nSumSpos[0][1]);
1538 dRdhCos = dRdhCos.add(nSumSpos[1][0]);
1539 dRdhSin = dRdhSin.add(nSumSpos[1][1]);
1540 dRdkCos = dRdkCos.add(nSumSpos[2][0]);
1541 dRdkSin = dRdkSin.add(nSumSpos[2][1]);
1542 dRdlCos = dRdlCos.add(nSumSpos[3][0]);
1543 dRdlSin = dRdlSin.add(nSumSpos[3][1]);
1544 dRdAlCos = dRdAlCos.add(nSumSpos[4][0]);
1545 dRdAlSin = dRdAlSin.add(nSumSpos[4][1]);
1546 dRdBeCos = dRdBeCos.add(nSumSpos[5][0]);
1547 dRdBeSin = dRdBeSin.add(nSumSpos[5][1]);
1548 dRdGaCos = dRdGaCos.add(nSumSpos[6][0]);
1549 dRdGaSin = dRdGaSin.add(nSumSpos[6][1]);
1550
1551
1552 if (s > 0 && s <= sMin) {
1553 final T[][] nSumSneg = computeNSum(date, j, m, -s, maxN,
1554 roaPow, ghMSJ, gammaMNS, context, hansenObjects);
1555 dRdaCos = dRdaCos.add(nSumSneg[0][0]);
1556 dRdaSin = dRdaSin.add(nSumSneg[0][1]);
1557 dRdhCos = dRdhCos.add(nSumSneg[1][0]);
1558 dRdhSin = dRdhSin.add(nSumSneg[1][1]);
1559 dRdkCos = dRdkCos.add(nSumSneg[2][0]);
1560 dRdkSin = dRdkSin.add(nSumSneg[2][1]);
1561 dRdlCos = dRdlCos.add(nSumSneg[3][0]);
1562 dRdlSin = dRdlSin.add(nSumSneg[3][1]);
1563 dRdAlCos = dRdAlCos.add(nSumSneg[4][0]);
1564 dRdAlSin = dRdAlSin.add(nSumSneg[4][1]);
1565 dRdBeCos = dRdBeCos.add(nSumSneg[5][0]);
1566 dRdBeSin = dRdBeSin.add(nSumSneg[5][1]);
1567 dRdGaCos = dRdGaCos.add(nSumSneg[6][0]);
1568 dRdGaSin = dRdGaSin.add(nSumSneg[6][1]);
1569 }
1570 }
1571 final T muOnA = context.getMuoa();
1572 dRdaCos = dRdaCos.multiply(muOnA.negate().divide(auxiliaryElements.getSma()));
1573 dRdaSin = dRdaSin.multiply(muOnA.negate().divide(auxiliaryElements.getSma()));
1574 dRdhCos = dRdhCos.multiply(muOnA);
1575 dRdhSin = dRdhSin.multiply(muOnA);
1576 dRdkCos = dRdkCos.multiply(muOnA);
1577 dRdkSin = dRdkSin.multiply(muOnA);
1578 dRdlCos = dRdlCos.multiply(muOnA);
1579 dRdlSin = dRdlSin.multiply(muOnA);
1580 dRdAlCos = dRdAlCos.multiply(muOnA);
1581 dRdAlSin = dRdAlSin.multiply(muOnA);
1582 dRdBeCos = dRdBeCos.multiply(muOnA);
1583 dRdBeSin = dRdBeSin.multiply(muOnA);
1584 dRdGaCos = dRdGaCos.multiply(muOnA);
1585 dRdGaSin = dRdGaSin.multiply(muOnA);
1586
1587
1588 final T RAlphaGammaCos = context.getAlpha().multiply(dRdGaCos).subtract(context.getGamma().multiply(dRdAlCos));
1589 final T RAlphaGammaSin = context.getAlpha().multiply(dRdGaSin).subtract(context.getGamma().multiply(dRdAlSin));
1590 final T RAlphaBetaCos = context.getAlpha().multiply(dRdBeCos).subtract(context.getBeta().multiply(dRdAlCos));
1591 final T RAlphaBetaSin = context.getAlpha().multiply(dRdBeSin).subtract(context.getBeta().multiply(dRdAlSin));
1592 final T RBetaGammaCos = context.getBeta().multiply(dRdGaCos).subtract(context.getGamma().multiply(dRdBeCos));
1593 final T RBetaGammaSin = context.getBeta().multiply(dRdGaSin).subtract(context.getGamma().multiply(dRdBeSin));
1594 final T RhkCos = auxiliaryElements.getH().multiply(dRdkCos).subtract(auxiliaryElements.getK().multiply(dRdhCos));
1595 final T RhkSin = auxiliaryElements.getH().multiply(dRdkSin).subtract(auxiliaryElements.getK().multiply(dRdhSin));
1596 final T pRagmIqRbgoABCos = (auxiliaryElements.getP().multiply(RAlphaGammaCos).subtract(auxiliaryElements.getQ().multiply(RBetaGammaCos).multiply(I))).multiply(context.getOoAB());
1597 final T pRagmIqRbgoABSin = (auxiliaryElements.getP().multiply(RAlphaGammaSin).subtract(auxiliaryElements.getQ().multiply(RBetaGammaSin).multiply(I))).multiply(context.getOoAB());
1598 final T RhkmRabmdRdlCos = RhkCos.subtract(RAlphaBetaCos).subtract(dRdlCos);
1599 final T RhkmRabmdRdlSin = RhkSin.subtract(RAlphaBetaSin).subtract(dRdlSin);
1600
1601
1602 cCoef[m][j + jMax][0] = context.getAx2oA().multiply(dRdlCos);
1603 sCoef[m][j + jMax][0] = context.getAx2oA().multiply(dRdlSin);
1604
1605
1606 cCoef[m][j + jMax][1] = (context.getBoA().multiply(dRdhCos).add(auxiliaryElements.getH().multiply(pRagmIqRbgoABCos)).add(auxiliaryElements.getK().multiply(context.getBoABpo()).multiply(dRdlCos))).negate();
1607 sCoef[m][j + jMax][1] = (context.getBoA().multiply(dRdhSin).add(auxiliaryElements.getH().multiply(pRagmIqRbgoABSin)).add(auxiliaryElements.getK().multiply(context.getBoABpo()).multiply(dRdlSin))).negate();
1608
1609
1610 cCoef[m][j + jMax][2] = context.getBoA().multiply(dRdkCos).add(auxiliaryElements.getK().multiply(pRagmIqRbgoABCos)).subtract(auxiliaryElements.getH().multiply(context.getBoABpo()).multiply(dRdlCos));
1611 sCoef[m][j + jMax][2] = context.getBoA().multiply(dRdkSin).add(auxiliaryElements.getK().multiply(pRagmIqRbgoABSin)).subtract(auxiliaryElements.getH().multiply(context.getBoABpo()).multiply(dRdlSin));
1612
1613
1614 cCoef[m][j + jMax][3] = context.getCo2AB().multiply(auxiliaryElements.getQ().multiply(RhkmRabmdRdlCos).subtract(RAlphaGammaCos.multiply(I)));
1615 sCoef[m][j + jMax][3] = context.getCo2AB().multiply(auxiliaryElements.getQ().multiply(RhkmRabmdRdlSin).subtract(RAlphaGammaSin.multiply(I)));
1616
1617
1618 cCoef[m][j + jMax][4] = context.getCo2AB().multiply(auxiliaryElements.getP().multiply(RhkmRabmdRdlCos).subtract(RBetaGammaCos));
1619 sCoef[m][j + jMax][4] = context.getCo2AB().multiply(auxiliaryElements.getP().multiply(RhkmRabmdRdlSin).subtract(RBetaGammaSin));
1620
1621
1622 cCoef[m][j + jMax][5] = context.getAx2oA().negate().multiply(dRdaCos).add(context.getBoABpo().multiply(auxiliaryElements.getH().multiply(dRdhCos).add(auxiliaryElements.getK().multiply(dRdkCos)))).add(pRagmIqRbgoABCos);
1623 sCoef[m][j + jMax][5] = context.getAx2oA().negate().multiply(dRdaSin).add(context.getBoABpo().multiply(auxiliaryElements.getH().multiply(dRdhSin).add(auxiliaryElements.getK().multiply(dRdkSin)))).add(pRagmIqRbgoABSin);
1624 }
1625
1626
1627
1628
1629
1630
1631
1632 public T getCijm(final int i, final int j, final int m) {
1633 return cCoef[m][j + jMax][i];
1634 }
1635
1636
1637
1638
1639
1640
1641
1642 public T getSijm(final int i, final int j, final int m) {
1643 return sCoef[m][j + jMax][i];
1644 }
1645 }
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656 private static class TesseralShortPeriodicCoefficients implements ShortPeriodTerms {
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671 private static final int I = 1;
1672
1673
1674 private final Frame bodyFrame;
1675
1676
1677 private final int maxOrderMdailyTesseralSP;
1678
1679
1680 private final boolean mDailiesOnly;
1681
1682
1683 private final SortedMap<Integer, List<Integer> > nonResOrders;
1684
1685
1686 private final int mMax;
1687
1688
1689 private final int jMax;
1690
1691
1692 private final int interpolationPoints;
1693
1694
1695 private final transient TimeSpanMap<Slot> slots;
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707 TesseralShortPeriodicCoefficients(final Frame bodyFrame, final int maxOrderMdailyTesseralSP,
1708 final boolean mDailiesOnly, final SortedMap<Integer, List<Integer> > nonResOrders,
1709 final int mMax, final int jMax, final int interpolationPoints,
1710 final TimeSpanMap<Slot> slots) {
1711 this.bodyFrame = bodyFrame;
1712 this.maxOrderMdailyTesseralSP = maxOrderMdailyTesseralSP;
1713 this.mDailiesOnly = mDailiesOnly;
1714 this.nonResOrders = nonResOrders;
1715 this.mMax = mMax;
1716 this.jMax = jMax;
1717 this.interpolationPoints = interpolationPoints;
1718 this.slots = slots;
1719 }
1720
1721
1722
1723
1724
1725 public Slot createSlot(final SpacecraftState... meanStates) {
1726 final Slot slot = new Slot(mMax, jMax, interpolationPoints);
1727 final AbsoluteDate first = meanStates[0].getDate();
1728 final AbsoluteDate last = meanStates[meanStates.length - 1].getDate();
1729 final int compare = first.compareTo(last);
1730 if (compare < 0) {
1731 slots.addValidAfter(slot, first, false);
1732 } else if (compare > 0) {
1733 slots.addValidBefore(slot, first, false);
1734 } else {
1735
1736 slots.addValidAfter(slot, AbsoluteDate.PAST_INFINITY, false);
1737 }
1738 return slot;
1739 }
1740
1741
1742 @Override
1743 public double[] value(final Orbit meanOrbit) {
1744
1745
1746 final Slot slot = slots.get(meanOrbit.getDate());
1747
1748
1749 final double[] shortPeriodicVariation = new double[6];
1750
1751
1752
1753 if (!nonResOrders.isEmpty() || mDailiesOnly) {
1754
1755
1756 final AuxiliaryElements auxiliaryElements = new AuxiliaryElements(meanOrbit, I);
1757
1758
1759 final StaticTransform t = bodyFrame.getStaticTransformTo(
1760 auxiliaryElements.getFrame(),
1761 auxiliaryElements.getDate());
1762 final Vector3D xB = t.transformVector(Vector3D.PLUS_I);
1763 final Vector3D yB = t.transformVector(Vector3D.PLUS_J);
1764 final Vector3D f = auxiliaryElements.getVectorF();
1765 final Vector3D g = auxiliaryElements.getVectorG();
1766 final double currentTheta = FastMath.atan2(-f.dotProduct(yB) + I * g.dotProduct(xB),
1767 f.dotProduct(xB) + I * g.dotProduct(yB));
1768
1769
1770 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1771
1772 final double jlMmt = -m * currentTheta;
1773 final SinCos scPhi = FastMath.sinCos(jlMmt);
1774 final double sinPhi = scPhi.sin();
1775 final double cosPhi = scPhi.cos();
1776
1777
1778 final double[] c = slot.getCijm(0, m, meanOrbit.getDate());
1779 final double[] s = slot.getSijm(0, m, meanOrbit.getDate());
1780 for (int i = 0; i < 6; i++) {
1781 shortPeriodicVariation[i] += c[i] * cosPhi + s[i] * sinPhi;
1782 }
1783 }
1784
1785
1786 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
1787 final int m = entry.getKey();
1788 final List<Integer> listJ = entry.getValue();
1789
1790 for (int j : listJ) {
1791
1792 final double jlMmt = j * meanOrbit.getLM() - m * currentTheta;
1793 final SinCos scPhi = FastMath.sinCos(jlMmt);
1794 final double sinPhi = scPhi.sin();
1795 final double cosPhi = scPhi.cos();
1796
1797
1798 final double[] c = slot.getCijm(j, m, meanOrbit.getDate());
1799 final double[] s = slot.getSijm(j, m, meanOrbit.getDate());
1800 for (int i = 0; i < 6; i++) {
1801 shortPeriodicVariation[i] += c[i] * cosPhi + s[i] * sinPhi;
1802 }
1803
1804 }
1805 }
1806 }
1807
1808 return shortPeriodicVariation;
1809
1810 }
1811
1812
1813 @Override
1814 public String getCoefficientsKeyPrefix() {
1815 return DSSTTesseral.SHORT_PERIOD_PREFIX;
1816 }
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828 @Override
1829 public Map<String, double[]> getCoefficients(final AbsoluteDate date, final Set<String> selected) {
1830
1831
1832 final Slot slot = slots.get(date);
1833
1834 if (!nonResOrders.isEmpty() || mDailiesOnly) {
1835 final Map<String, double[]> coefficients = new HashMap<>(12 * maxOrderMdailyTesseralSP + 12 * nonResOrders.size());
1836
1837 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1838 storeIfSelected(coefficients, selected, slot.getCijm(0, m, date), DSSTTesseral.CM_COEFFICIENTS, m);
1839 storeIfSelected(coefficients, selected, slot.getSijm(0, m, date), DSSTTesseral.SM_COEFFICIENTS, m);
1840 }
1841
1842 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
1843 final int m = entry.getKey();
1844 final List<Integer> listJ = entry.getValue();
1845
1846 for (int j : listJ) {
1847 for (int i = 0; i < 6; ++i) {
1848 storeIfSelected(coefficients, selected, slot.getCijm(j, m, date), "c", j, m);
1849 storeIfSelected(coefficients, selected, slot.getSijm(j, m, date), "s", j, m);
1850 }
1851 }
1852 }
1853
1854 return coefficients;
1855
1856 } else {
1857 return Collections.emptyMap();
1858 }
1859
1860 }
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870 private void storeIfSelected(final Map<String, double[]> map, final Set<String> selected,
1871 final double[] value, final String id, final int... indices) {
1872 final StringBuilder keyBuilder = new StringBuilder(getCoefficientsKeyPrefix());
1873 keyBuilder.append(id);
1874 for (int index : indices) {
1875 keyBuilder.append('[').append(index).append(']');
1876 }
1877 final String key = keyBuilder.toString();
1878 if (selected.isEmpty() || selected.contains(key)) {
1879 map.put(key, value);
1880 }
1881 }
1882
1883 }
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894 private static class FieldTesseralShortPeriodicCoefficients <T extends CalculusFieldElement<T>> implements FieldShortPeriodTerms<T> {
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909 private static final int I = 1;
1910
1911
1912 private final Frame bodyFrame;
1913
1914
1915 private final int maxOrderMdailyTesseralSP;
1916
1917
1918 private final boolean mDailiesOnly;
1919
1920
1921 private final SortedMap<Integer, List<Integer> > nonResOrders;
1922
1923
1924 private final int mMax;
1925
1926
1927 private final int jMax;
1928
1929
1930 private final int interpolationPoints;
1931
1932
1933 private final transient FieldTimeSpanMap<FieldSlot<T>, T> slots;
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945 FieldTesseralShortPeriodicCoefficients(final Frame bodyFrame, final int maxOrderMdailyTesseralSP,
1946 final boolean mDailiesOnly, final SortedMap<Integer, List<Integer> > nonResOrders,
1947 final int mMax, final int jMax, final int interpolationPoints,
1948 final FieldTimeSpanMap<FieldSlot<T>, T> slots) {
1949 this.bodyFrame = bodyFrame;
1950 this.maxOrderMdailyTesseralSP = maxOrderMdailyTesseralSP;
1951 this.mDailiesOnly = mDailiesOnly;
1952 this.nonResOrders = nonResOrders;
1953 this.mMax = mMax;
1954 this.jMax = jMax;
1955 this.interpolationPoints = interpolationPoints;
1956 this.slots = slots;
1957 }
1958
1959
1960
1961
1962
1963 @SuppressWarnings("unchecked")
1964 public FieldSlot<T> createSlot(final FieldSpacecraftState<T>... meanStates) {
1965 final FieldSlot<T> slot = new FieldSlot<>(mMax, jMax, interpolationPoints);
1966 final FieldAbsoluteDate<T> first = meanStates[0].getDate();
1967 final FieldAbsoluteDate<T> last = meanStates[meanStates.length - 1].getDate();
1968 if (first.compareTo(last) <= 0) {
1969 slots.addValidAfter(slot, first);
1970 } else {
1971 slots.addValidBefore(slot, first);
1972 }
1973 return slot;
1974 }
1975
1976
1977 @Override
1978 public T[] value(final FieldOrbit<T> meanOrbit) {
1979
1980
1981 final FieldSlot<T> slot = slots.get(meanOrbit.getDate());
1982
1983
1984 final T[] shortPeriodicVariation = MathArrays.buildArray(meanOrbit.getDate().getField(), 6);
1985
1986
1987
1988 if (!nonResOrders.isEmpty() || mDailiesOnly) {
1989
1990
1991 final FieldAuxiliaryElements<T> auxiliaryElements = new FieldAuxiliaryElements<>(meanOrbit, I);
1992
1993
1994 final FieldStaticTransform<T> t = bodyFrame.getStaticTransformTo(auxiliaryElements.getFrame(), auxiliaryElements.getDate());
1995 final FieldVector3D<T> xB = t.transformVector(Vector3D.PLUS_I);
1996 final FieldVector3D<T> yB = t.transformVector(Vector3D.PLUS_J);
1997 final FieldVector3D<T> f = auxiliaryElements.getVectorF();
1998 final FieldVector3D<T> g = auxiliaryElements.getVectorG();
1999 final T currentTheta = FastMath.atan2(f.dotProduct(yB).negate().add(g.dotProduct(xB).multiply(I)),
2000 f.dotProduct(xB).add(g.dotProduct(yB).multiply(I)));
2001
2002
2003 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
2004
2005 final T jlMmt = currentTheta.multiply(-m);
2006 final FieldSinCos<T> scPhi = FastMath.sinCos(jlMmt);
2007 final T sinPhi = scPhi.sin();
2008 final T cosPhi = scPhi.cos();
2009
2010
2011 final T[] c = slot.getCijm(0, m, meanOrbit.getDate());
2012 final T[] s = slot.getSijm(0, m, meanOrbit.getDate());
2013 for (int i = 0; i < 6; i++) {
2014 shortPeriodicVariation[i] = shortPeriodicVariation[i].add(c[i].multiply(cosPhi).add(s[i].multiply(sinPhi)));
2015 }
2016 }
2017
2018
2019 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
2020 final int m = entry.getKey();
2021 final List<Integer> listJ = entry.getValue();
2022
2023 for (int j : listJ) {
2024
2025 final T jlMmt = meanOrbit.getLM().multiply(j).subtract(currentTheta.multiply(m));
2026 final FieldSinCos<T> scPhi = FastMath.sinCos(jlMmt);
2027 final T sinPhi = scPhi.sin();
2028 final T cosPhi = scPhi.cos();
2029
2030
2031 final T[] c = slot.getCijm(j, m, meanOrbit.getDate());
2032 final T[] s = slot.getSijm(j, m, meanOrbit.getDate());
2033 for (int i = 0; i < 6; i++) {
2034 shortPeriodicVariation[i] = shortPeriodicVariation[i].add(c[i].multiply(cosPhi).add(s[i].multiply(sinPhi)));
2035 }
2036
2037 }
2038 }
2039 }
2040
2041 return shortPeriodicVariation;
2042
2043 }
2044
2045
2046 @Override
2047 public String getCoefficientsKeyPrefix() {
2048 return DSSTTesseral.SHORT_PERIOD_PREFIX;
2049 }
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061 @Override
2062 public Map<String, T[]> getCoefficients(final FieldAbsoluteDate<T> date, final Set<String> selected) {
2063
2064
2065 final FieldSlot<T> slot = slots.get(date);
2066
2067 if (!nonResOrders.isEmpty() || mDailiesOnly) {
2068 final Map<String, T[]> coefficients = new HashMap<>(12 * maxOrderMdailyTesseralSP + 12 * nonResOrders.size());
2069
2070 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
2071 storeIfSelected(coefficients, selected, slot.getCijm(0, m, date), DSSTTesseral.CM_COEFFICIENTS, m);
2072 storeIfSelected(coefficients, selected, slot.getSijm(0, m, date), DSSTTesseral.SM_COEFFICIENTS, m);
2073 }
2074
2075 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
2076 final int m = entry.getKey();
2077 final List<Integer> listJ = entry.getValue();
2078
2079 for (int j : listJ) {
2080 for (int i = 0; i < 6; ++i) {
2081 storeIfSelected(coefficients, selected, slot.getCijm(j, m, date), "c", j, m);
2082 storeIfSelected(coefficients, selected, slot.getSijm(j, m, date), "s", j, m);
2083 }
2084 }
2085 }
2086
2087 return coefficients;
2088
2089 } else {
2090 return Collections.emptyMap();
2091 }
2092
2093 }
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103 private void storeIfSelected(final Map<String, T[]> map, final Set<String> selected,
2104 final T[] value, final String id, final int... indices) {
2105 final StringBuilder keyBuilder = new StringBuilder(getCoefficientsKeyPrefix());
2106 keyBuilder.append(id);
2107 for (int index : indices) {
2108 keyBuilder.append('[').append(index).append(']');
2109 }
2110 final String key = keyBuilder.toString();
2111 if (selected.isEmpty() || selected.contains(key)) {
2112 map.put(key, value);
2113 }
2114 }
2115 }
2116
2117
2118 private static class Slot {
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132 private final ShortPeriodicsInterpolatedCoefficient[][] cijm;
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146 private final ShortPeriodicsInterpolatedCoefficient[][] sijm;
2147
2148
2149
2150
2151
2152
2153 Slot(final int mMax, final int jMax, final int interpolationPoints) {
2154
2155 final int rows = mMax + 1;
2156 final int columns = 2 * jMax + 1;
2157 cijm = new ShortPeriodicsInterpolatedCoefficient[rows][columns];
2158 sijm = new ShortPeriodicsInterpolatedCoefficient[rows][columns];
2159 for (int m = 1; m <= mMax; m++) {
2160 for (int j = -jMax; j <= jMax; j++) {
2161 cijm[m][j + jMax] = new ShortPeriodicsInterpolatedCoefficient(interpolationPoints);
2162 sijm[m][j + jMax] = new ShortPeriodicsInterpolatedCoefficient(interpolationPoints);
2163 }
2164 }
2165
2166 }
2167
2168
2169
2170
2171
2172
2173
2174
2175 double[] getCijm(final int j, final int m, final AbsoluteDate date) {
2176 final int jMax = (cijm[m].length - 1) / 2;
2177 return cijm[m][j + jMax].value(date);
2178 }
2179
2180
2181
2182
2183
2184
2185
2186
2187 double[] getSijm(final int j, final int m, final AbsoluteDate date) {
2188 final int jMax = (cijm[m].length - 1) / 2;
2189 return sijm[m][j + jMax].value(date);
2190 }
2191
2192 }
2193
2194
2195 private static class FieldSlot <T extends CalculusFieldElement<T>> {
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209 private final FieldShortPeriodicsInterpolatedCoefficient<T>[][] cijm;
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223 private final FieldShortPeriodicsInterpolatedCoefficient<T>[][] sijm;
2224
2225
2226
2227
2228
2229
2230 @SuppressWarnings("unchecked")
2231 FieldSlot(final int mMax, final int jMax, final int interpolationPoints) {
2232
2233 final int rows = mMax + 1;
2234 final int columns = 2 * jMax + 1;
2235 cijm = (FieldShortPeriodicsInterpolatedCoefficient<T>[][]) Array.newInstance(FieldShortPeriodicsInterpolatedCoefficient.class, rows, columns);
2236 sijm = (FieldShortPeriodicsInterpolatedCoefficient<T>[][]) Array.newInstance(FieldShortPeriodicsInterpolatedCoefficient.class, rows, columns);
2237 for (int m = 1; m <= mMax; m++) {
2238 for (int j = -jMax; j <= jMax; j++) {
2239 cijm[m][j + jMax] = new FieldShortPeriodicsInterpolatedCoefficient<>(interpolationPoints);
2240 sijm[m][j + jMax] = new FieldShortPeriodicsInterpolatedCoefficient<>(interpolationPoints);
2241 }
2242 }
2243
2244 }
2245
2246
2247
2248
2249
2250
2251
2252
2253 T[] getCijm(final int j, final int m, final FieldAbsoluteDate<T> date) {
2254 final int jMax = (cijm[m].length - 1) / 2;
2255 return cijm[m][j + jMax].value(date);
2256 }
2257
2258
2259
2260
2261
2262
2263
2264
2265 T[] getSijm(final int j, final int m, final FieldAbsoluteDate<T> date) {
2266 final int jMax = (cijm[m].length - 1) / 2;
2267 return sijm[m][j + jMax].value(date);
2268 }
2269
2270 }
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285 private class UAnddU {
2286
2287
2288 private double dUda;
2289
2290
2291 private double dUdk;
2292
2293
2294 private double dUdh;
2295
2296
2297 private double dUdl;
2298
2299
2300 private double dUdAl;
2301
2302
2303 private double dUdBe;
2304
2305
2306 private double dUdGa;
2307
2308
2309
2310
2311
2312
2313 UAnddU(final AbsoluteDate date, final DSSTTesseralContext context, final HansenObjects hansen) {
2314
2315
2316 final AuxiliaryElements auxiliaryElements = context.getAuxiliaryElements();
2317
2318
2319 dUda = 0.;
2320 dUdh = 0.;
2321 dUdk = 0.;
2322 dUdl = 0.;
2323 dUdAl = 0.;
2324 dUdBe = 0.;
2325 dUdGa = 0.;
2326
2327
2328 if (!resOrders.isEmpty()) {
2329
2330 final GHmsjPolynomials ghMSJ = new GHmsjPolynomials(auxiliaryElements.getK(), auxiliaryElements.getH(), context.getAlpha(), context.getBeta(), I);
2331
2332
2333 final GammaMnsFunction gammaMNS = new GammaMnsFunction(maxDegree, context.getGamma(), I);
2334
2335
2336 final double[] roaPow = new double[maxDegree + 1];
2337 roaPow[0] = 1.;
2338 for (int i = 1; i <= maxDegree; i++) {
2339 roaPow[i] = context.getRoa() * roaPow[i - 1];
2340 }
2341
2342
2343 for (int m : resOrders) {
2344
2345
2346 final int j = FastMath.max(1, (int) FastMath.round(context.getRatio() * m));
2347
2348
2349 final double jlMmt = j * auxiliaryElements.getLM() - m * context.getTheta();
2350 final SinCos scPhi = FastMath.sinCos(jlMmt);
2351 final double sinPhi = scPhi.sin();
2352 final double cosPhi = scPhi.cos();
2353
2354
2355 double dUdaCos = 0.;
2356 double dUdaSin = 0.;
2357 double dUdhCos = 0.;
2358 double dUdhSin = 0.;
2359 double dUdkCos = 0.;
2360 double dUdkSin = 0.;
2361 double dUdlCos = 0.;
2362 double dUdlSin = 0.;
2363 double dUdAlCos = 0.;
2364 double dUdAlSin = 0.;
2365 double dUdBeCos = 0.;
2366 double dUdBeSin = 0.;
2367 double dUdGaCos = 0.;
2368 double dUdGaSin = 0.;
2369
2370
2371 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
2372 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
2373 for (int s = 0; s <= sMax; s++) {
2374
2375
2376 hansen.computeHansenObjectsInitValues(context, s + maxDegree, j);
2377
2378
2379 final double[][] nSumSpos = computeNSum(date, j, m, s, maxDegree,
2380 roaPow, ghMSJ, gammaMNS, context, hansen);
2381 dUdaCos += nSumSpos[0][0];
2382 dUdaSin += nSumSpos[0][1];
2383 dUdhCos += nSumSpos[1][0];
2384 dUdhSin += nSumSpos[1][1];
2385 dUdkCos += nSumSpos[2][0];
2386 dUdkSin += nSumSpos[2][1];
2387 dUdlCos += nSumSpos[3][0];
2388 dUdlSin += nSumSpos[3][1];
2389 dUdAlCos += nSumSpos[4][0];
2390 dUdAlSin += nSumSpos[4][1];
2391 dUdBeCos += nSumSpos[5][0];
2392 dUdBeSin += nSumSpos[5][1];
2393 dUdGaCos += nSumSpos[6][0];
2394 dUdGaSin += nSumSpos[6][1];
2395
2396
2397 if (s > 0 && s <= sMin) {
2398
2399 hansen.computeHansenObjectsInitValues(context, maxDegree - s, j);
2400
2401 final double[][] nSumSneg = computeNSum(date, j, m, -s, maxDegree,
2402 roaPow, ghMSJ, gammaMNS, context, hansen);
2403 dUdaCos += nSumSneg[0][0];
2404 dUdaSin += nSumSneg[0][1];
2405 dUdhCos += nSumSneg[1][0];
2406 dUdhSin += nSumSneg[1][1];
2407 dUdkCos += nSumSneg[2][0];
2408 dUdkSin += nSumSneg[2][1];
2409 dUdlCos += nSumSneg[3][0];
2410 dUdlSin += nSumSneg[3][1];
2411 dUdAlCos += nSumSneg[4][0];
2412 dUdAlSin += nSumSneg[4][1];
2413 dUdBeCos += nSumSneg[5][0];
2414 dUdBeSin += nSumSneg[5][1];
2415 dUdGaCos += nSumSneg[6][0];
2416 dUdGaSin += nSumSneg[6][1];
2417 }
2418 }
2419
2420
2421 dUda += cosPhi * dUdaCos + sinPhi * dUdaSin;
2422 dUdh += cosPhi * dUdhCos + sinPhi * dUdhSin;
2423 dUdk += cosPhi * dUdkCos + sinPhi * dUdkSin;
2424 dUdl += cosPhi * dUdlCos + sinPhi * dUdlSin;
2425 dUdAl += cosPhi * dUdAlCos + sinPhi * dUdAlSin;
2426 dUdBe += cosPhi * dUdBeCos + sinPhi * dUdBeSin;
2427 dUdGa += cosPhi * dUdGaCos + sinPhi * dUdGaSin;
2428 }
2429
2430 final double muOnA = context.getMuoa();
2431 this.dUda = dUda * (-muOnA / auxiliaryElements.getSma());
2432 this.dUdh = dUdh * muOnA;
2433 this.dUdk = dUdk * muOnA;
2434 this.dUdl = dUdl * muOnA;
2435 this.dUdAl = dUdAl * muOnA;
2436 this.dUdBe = dUdBe * muOnA;
2437 this.dUdGa = dUdGa * muOnA;
2438 }
2439
2440 }
2441
2442
2443
2444
2445 public double getdUda() {
2446 return dUda;
2447 }
2448
2449
2450
2451
2452 public double getdUdk() {
2453 return dUdk;
2454 }
2455
2456
2457
2458
2459 public double getdUdh() {
2460 return dUdh;
2461 }
2462
2463
2464
2465
2466 public double getdUdl() {
2467 return dUdl;
2468 }
2469
2470
2471
2472
2473 public double getdUdAl() {
2474 return dUdAl;
2475 }
2476
2477
2478
2479
2480 public double getdUdBe() {
2481 return dUdBe;
2482 }
2483
2484
2485
2486
2487 public double getdUdGa() {
2488 return dUdGa;
2489 }
2490
2491 }
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506 private class FieldUAnddU <T extends CalculusFieldElement<T>> {
2507
2508
2509 private T dUda;
2510
2511
2512 private T dUdk;
2513
2514
2515 private T dUdh;
2516
2517
2518 private T dUdl;
2519
2520
2521 private T dUdAl;
2522
2523
2524 private T dUdBe;
2525
2526
2527 private T dUdGa;
2528
2529
2530
2531
2532
2533
2534 FieldUAnddU(final FieldAbsoluteDate<T> date, final FieldDSSTTesseralContext<T> context,
2535 final FieldHansenObjects<T> hansen) {
2536
2537
2538 final FieldAuxiliaryElements<T> auxiliaryElements = context.getFieldAuxiliaryElements();
2539
2540
2541 final Field<T> field = date.getField();
2542 final T zero = field.getZero();
2543
2544
2545 dUda = zero;
2546 dUdh = zero;
2547 dUdk = zero;
2548 dUdl = zero;
2549 dUdAl = zero;
2550 dUdBe = zero;
2551 dUdGa = zero;
2552
2553
2554 if (!resOrders.isEmpty()) {
2555
2556 final FieldGHmsjPolynomials<T> ghMSJ = new FieldGHmsjPolynomials<>(auxiliaryElements.getK(), auxiliaryElements.getH(), context.getAlpha(), context.getBeta(), I, field);
2557
2558
2559 final FieldGammaMnsFunction<T> gammaMNS = new FieldGammaMnsFunction<>(maxDegree, context.getGamma(), I, field);
2560
2561
2562 final T[] roaPow = MathArrays.buildArray(field, maxDegree + 1);
2563 roaPow[0] = zero.newInstance(1.);
2564 for (int i = 1; i <= maxDegree; i++) {
2565 roaPow[i] = roaPow[i - 1].multiply(context.getRoa());
2566 }
2567
2568
2569 for (int m : resOrders) {
2570
2571
2572 final int j = FastMath.max(1, (int) FastMath.round(context.getRatio().multiply(m)));
2573
2574
2575 final T jlMmt = auxiliaryElements.getLM().multiply(j).subtract(context.getTheta().multiply(m));
2576 final FieldSinCos<T> scPhi = FastMath.sinCos(jlMmt);
2577 final T sinPhi = scPhi.sin();
2578 final T cosPhi = scPhi.cos();
2579
2580
2581 T dUdaCos = zero;
2582 T dUdaSin = zero;
2583 T dUdhCos = zero;
2584 T dUdhSin = zero;
2585 T dUdkCos = zero;
2586 T dUdkSin = zero;
2587 T dUdlCos = zero;
2588 T dUdlSin = zero;
2589 T dUdAlCos = zero;
2590 T dUdAlSin = zero;
2591 T dUdBeCos = zero;
2592 T dUdBeSin = zero;
2593 T dUdGaCos = zero;
2594 T dUdGaSin = zero;
2595
2596
2597 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
2598 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
2599 for (int s = 0; s <= sMax; s++) {
2600
2601
2602 hansen.computeHansenObjectsInitValues(context, s + maxDegree, j);
2603
2604
2605 final T[][] nSumSpos = computeNSum(date, j, m, s, maxDegree,
2606 roaPow, ghMSJ, gammaMNS, context, hansen);
2607 dUdaCos = dUdaCos.add(nSumSpos[0][0]);
2608 dUdaSin = dUdaSin.add(nSumSpos[0][1]);
2609 dUdhCos = dUdhCos.add(nSumSpos[1][0]);
2610 dUdhSin = dUdhSin.add(nSumSpos[1][1]);
2611 dUdkCos = dUdkCos.add(nSumSpos[2][0]);
2612 dUdkSin = dUdkSin.add(nSumSpos[2][1]);
2613 dUdlCos = dUdlCos.add(nSumSpos[3][0]);
2614 dUdlSin = dUdlSin.add(nSumSpos[3][1]);
2615 dUdAlCos = dUdAlCos.add(nSumSpos[4][0]);
2616 dUdAlSin = dUdAlSin.add(nSumSpos[4][1]);
2617 dUdBeCos = dUdBeCos.add(nSumSpos[5][0]);
2618 dUdBeSin = dUdBeSin.add(nSumSpos[5][1]);
2619 dUdGaCos = dUdGaCos.add(nSumSpos[6][0]);
2620 dUdGaSin = dUdGaSin.add(nSumSpos[6][1]);
2621
2622
2623 if (s > 0 && s <= sMin) {
2624
2625 hansen.computeHansenObjectsInitValues(context, maxDegree - s, j);
2626
2627 final T[][] nSumSneg = computeNSum(date, j, m, -s, maxDegree,
2628 roaPow, ghMSJ, gammaMNS, context, hansen);
2629 dUdaCos = dUdaCos.add(nSumSneg[0][0]);
2630 dUdaSin = dUdaSin.add(nSumSneg[0][1]);
2631 dUdhCos = dUdhCos.add(nSumSneg[1][0]);
2632 dUdhSin = dUdhSin.add(nSumSneg[1][1]);
2633 dUdkCos = dUdkCos.add(nSumSneg[2][0]);
2634 dUdkSin = dUdkSin.add(nSumSneg[2][1]);
2635 dUdlCos = dUdlCos.add(nSumSneg[3][0]);
2636 dUdlSin = dUdlSin.add(nSumSneg[3][1]);
2637 dUdAlCos = dUdAlCos.add(nSumSneg[4][0]);
2638 dUdAlSin = dUdAlSin.add(nSumSneg[4][1]);
2639 dUdBeCos = dUdBeCos.add(nSumSneg[5][0]);
2640 dUdBeSin = dUdBeSin.add(nSumSneg[5][1]);
2641 dUdGaCos = dUdGaCos.add(nSumSneg[6][0]);
2642 dUdGaSin = dUdGaSin.add(nSumSneg[6][1]);
2643 }
2644 }
2645
2646
2647 dUda = dUda.add(dUdaCos.multiply(cosPhi).add(dUdaSin.multiply(sinPhi)));
2648 dUdh = dUdh.add(dUdhCos.multiply(cosPhi).add(dUdhSin.multiply(sinPhi)));
2649 dUdk = dUdk.add(dUdkCos.multiply(cosPhi).add(dUdkSin.multiply(sinPhi)));
2650 dUdl = dUdl.add(dUdlCos.multiply(cosPhi).add(dUdlSin.multiply(sinPhi)));
2651 dUdAl = dUdAl.add(dUdAlCos.multiply(cosPhi).add(dUdAlSin.multiply(sinPhi)));
2652 dUdBe = dUdBe.add(dUdBeCos.multiply(cosPhi).add(dUdBeSin.multiply(sinPhi)));
2653 dUdGa = dUdGa.add(dUdGaCos.multiply(cosPhi).add(dUdGaSin.multiply(sinPhi)));
2654 }
2655
2656 final T muOnA = context.getMuoa();
2657 dUda = dUda.multiply(muOnA.divide(auxiliaryElements.getSma())).negate();
2658 dUdh = dUdh.multiply(muOnA);
2659 dUdk = dUdk.multiply(muOnA);
2660 dUdl = dUdl.multiply(muOnA);
2661 dUdAl = dUdAl.multiply(muOnA);
2662 dUdBe = dUdBe.multiply(muOnA);
2663 dUdGa = dUdGa.multiply(muOnA);
2664 }
2665 }
2666
2667
2668
2669
2670 public T getdUda() {
2671 return dUda;
2672 }
2673
2674
2675
2676
2677 public T getdUdk() {
2678 return dUdk;
2679 }
2680
2681
2682
2683
2684 public T getdUdh() {
2685 return dUdh;
2686 }
2687
2688
2689
2690
2691 public T getdUdl() {
2692 return dUdl;
2693 }
2694
2695
2696
2697
2698 public T getdUdAl() {
2699 return dUdAl;
2700 }
2701
2702
2703
2704
2705 public T getdUdBe() {
2706 return dUdBe;
2707 }
2708
2709
2710
2711
2712 public T getdUdGa() {
2713 return dUdGa;
2714 }
2715
2716 }
2717
2718
2719 private class HansenObjects {
2720
2721
2722
2723 private HansenTesseralLinear[][] hansenObjects;
2724
2725
2726
2727
2728
2729 HansenObjects(final double ratio,
2730 final PropagationType type) {
2731
2732
2733 final int rows = 2 * maxDegree + 1;
2734 final int columns = maxFrequencyShortPeriodics + 1;
2735 this.hansenObjects = new HansenTesseralLinear[rows][columns];
2736
2737 switch (type) {
2738 case MEAN:
2739
2740 for (int m : resOrders) {
2741
2742 final int j = FastMath.max(1, (int) FastMath.round(ratio * m));
2743
2744
2745 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
2746 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
2747
2748
2749 for (int s = 0; s <= sMax; s++) {
2750
2751 final int n0 = FastMath.max(FastMath.max(2, m), s);
2752
2753
2754 this.hansenObjects[s + maxDegree][j] = new HansenTesseralLinear(maxDegree, s, j, n0, maxHansen);
2755
2756 if (s > 0 && s <= sMin) {
2757
2758 this.hansenObjects[maxDegree - s][j] = new HansenTesseralLinear(maxDegree, -s, j, n0, maxHansen);
2759 }
2760 }
2761 }
2762 break;
2763
2764 case OSCULATING:
2765
2766 for (int j = 0; j <= maxFrequencyShortPeriodics; j++) {
2767 for (int s = -maxDegree; s <= maxDegree; s++) {
2768
2769 final int n0 = FastMath.max(2, FastMath.abs(s));
2770 this.hansenObjects[s + maxDegree][j] = new HansenTesseralLinear(maxDegree, s, j, n0, maxHansen);
2771 }
2772 }
2773 break;
2774
2775 default:
2776 throw new OrekitInternalError(null);
2777 }
2778
2779 }
2780
2781
2782
2783
2784
2785
2786 public void computeHansenObjectsInitValues(final DSSTTesseralContext context, final int rows, final int columns) {
2787 hansenObjects[rows][columns].computeInitValues(context.getE2(), context.getChi(), context.getChi2());
2788 }
2789
2790
2791
2792
2793 public HansenTesseralLinear[][] getHansenObjects() {
2794 return hansenObjects;
2795 }
2796
2797 }
2798
2799
2800 private class FieldHansenObjects<T extends CalculusFieldElement<T>> {
2801
2802
2803
2804 private FieldHansenTesseralLinear<T>[][] hansenObjects;
2805
2806
2807
2808
2809
2810 @SuppressWarnings("unchecked")
2811 FieldHansenObjects(final T ratio,
2812 final PropagationType type) {
2813
2814
2815 maxHansen = maxEccPow / 2;
2816
2817
2818 final int rows = 2 * maxDegree + 1;
2819 final int columns = maxFrequencyShortPeriodics + 1;
2820 this.hansenObjects = (FieldHansenTesseralLinear<T>[][]) Array.newInstance(FieldHansenTesseralLinear.class, rows, columns);
2821
2822 switch (type) {
2823 case MEAN:
2824
2825 for (int m : resOrders) {
2826
2827 final int j = FastMath.max(1, (int) FastMath.round(ratio.multiply(m)));
2828
2829
2830 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
2831 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
2832
2833
2834 for (int s = 0; s <= sMax; s++) {
2835
2836 final int n0 = FastMath.max(FastMath.max(2, m), s);
2837
2838
2839 this.hansenObjects[s + maxDegree][j] = new FieldHansenTesseralLinear<>(maxDegree, s, j, n0, maxHansen, ratio.getField());
2840
2841 if (s > 0 && s <= sMin) {
2842
2843 this.hansenObjects[maxDegree - s][j] = new FieldHansenTesseralLinear<>(maxDegree, -s, j, n0, maxHansen, ratio.getField());
2844 }
2845 }
2846 }
2847 break;
2848
2849 case OSCULATING:
2850
2851 for (int j = 0; j <= maxFrequencyShortPeriodics; j++) {
2852 for (int s = -maxDegree; s <= maxDegree; s++) {
2853
2854 final int n0 = FastMath.max(2, FastMath.abs(s));
2855 this.hansenObjects[s + maxDegree][j] = new FieldHansenTesseralLinear<>(maxDegree, s, j, n0, maxHansen, ratio.getField());
2856 }
2857 }
2858 break;
2859
2860 default:
2861 throw new OrekitInternalError(null);
2862 }
2863
2864 }
2865
2866
2867
2868
2869
2870
2871 public void computeHansenObjectsInitValues(final FieldDSSTTesseralContext<T> context,
2872 final int rows, final int columns) {
2873 hansenObjects[rows][columns].computeInitValues(context.getE2(), context.getChi(), context.getChi2());
2874 }
2875
2876
2877
2878
2879 public FieldHansenTesseralLinear<T>[][] getHansenObjects() {
2880 return hansenObjects;
2881 }
2882
2883 }
2884
2885 }