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