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 org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.analysis.differentiation.FieldGradient;
22 import org.hipparchus.exception.LocalizedCoreFormats;
23 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.hipparchus.util.FastMath;
26 import org.hipparchus.util.FieldSinCos;
27 import org.hipparchus.util.MathArrays;
28 import org.hipparchus.util.MathUtils;
29 import org.hipparchus.util.SinCos;
30 import org.orekit.attitudes.AttitudeProvider;
31 import org.orekit.errors.OrekitException;
32 import org.orekit.errors.OrekitInternalError;
33 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
34 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider.UnnormalizedSphericalHarmonics;
35 import org.orekit.frames.FieldStaticTransform;
36 import org.orekit.frames.Frame;
37 import org.orekit.frames.StaticTransform;
38 import org.orekit.orbits.FieldOrbit;
39 import org.orekit.orbits.Orbit;
40 import org.orekit.propagation.FieldSpacecraftState;
41 import org.orekit.propagation.PropagationType;
42 import org.orekit.propagation.SpacecraftState;
43 import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
44 import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory;
45 import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
46 import org.orekit.propagation.semianalytical.dsst.utilities.FieldGHmsjPolynomials;
47 import org.orekit.propagation.semianalytical.dsst.utilities.FieldGammaMnsFunction;
48 import org.orekit.propagation.semianalytical.dsst.utilities.FieldShortPeriodicsInterpolatedCoefficient;
49 import org.orekit.propagation.semianalytical.dsst.utilities.GHmsjPolynomials;
50 import org.orekit.propagation.semianalytical.dsst.utilities.GammaMnsFunction;
51 import org.orekit.propagation.semianalytical.dsst.utilities.JacobiPolynomials;
52 import org.orekit.propagation.semianalytical.dsst.utilities.ShortPeriodicsInterpolatedCoefficient;
53 import org.orekit.propagation.semianalytical.dsst.utilities.hansen.FieldHansenTesseralLinear;
54 import org.orekit.propagation.semianalytical.dsst.utilities.hansen.HansenTesseralLinear;
55 import org.orekit.time.AbsoluteDate;
56 import org.orekit.time.FieldAbsoluteDate;
57 import org.orekit.utils.FieldTimeSpanMap;
58 import org.orekit.utils.ParameterDriver;
59 import org.orekit.utils.TimeSpanMap;
60
61 import java.lang.reflect.Array;
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.Collections;
65 import java.util.HashMap;
66 import java.util.List;
67 import java.util.Map;
68 import java.util.Set;
69 import java.util.SortedMap;
70 import java.util.TreeMap;
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 = auxiliaryElements.getAlpha() * udu.getdUdGa() - auxiliaryElements.getGamma() * udu.getdUdAl();
479 final double UAlphaBeta = auxiliaryElements.getAlpha() * udu.getdUdBe() - auxiliaryElements.getBeta() * udu.getdUdAl();
480 final double UBetaGamma = auxiliaryElements.getBeta() * udu.getdUdGa() - auxiliaryElements.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(auxiliaryElements.getAlpha()).subtract(udu.getdUdAl().multiply(auxiliaryElements.getGamma()));
515 final T UAlphaBeta = udu.getdUdBe().multiply(auxiliaryElements.getAlpha()).subtract(udu.getdUdAl().multiply(auxiliaryElements.getBeta()));
516 final T UBetaGamma = udu.getdUdGa().multiply(auxiliaryElements.getBeta()).subtract(udu.getdUdBe().multiply(auxiliaryElements.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, auxiliaryElements.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, auxiliaryElements.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(), auxiliaryElements.getAlpha(), auxiliaryElements.getBeta(), I);
1199
1200
1201 gammaMNS = new GammaMnsFunction(maxDegree, auxiliaryElements.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 dRdaCos *= -context.getMoa() / auxiliaryElements.getSma();
1303 dRdaSin *= -context.getMoa() / auxiliaryElements.getSma();
1304 dRdhCos *= context.getMoa();
1305 dRdhSin *= context.getMoa();
1306 dRdkCos *= context.getMoa();
1307 dRdkSin *= context.getMoa();
1308 dRdlCos *= context.getMoa();
1309 dRdlSin *= context.getMoa();
1310 dRdAlCos *= context.getMoa();
1311 dRdAlSin *= context.getMoa();
1312 dRdBeCos *= context.getMoa();
1313 dRdBeSin *= context.getMoa();
1314 dRdGaCos *= context.getMoa();
1315 dRdGaSin *= context.getMoa();
1316
1317
1318 final double RAlphaGammaCos = auxiliaryElements.getAlpha() * dRdGaCos - auxiliaryElements.getGamma() * dRdAlCos;
1319 final double RAlphaGammaSin = auxiliaryElements.getAlpha() * dRdGaSin - auxiliaryElements.getGamma() * dRdAlSin;
1320 final double RAlphaBetaCos = auxiliaryElements.getAlpha() * dRdBeCos - auxiliaryElements.getBeta() * dRdAlCos;
1321 final double RAlphaBetaSin = auxiliaryElements.getAlpha() * dRdBeSin - auxiliaryElements.getBeta() * dRdAlSin;
1322 final double RBetaGammaCos = auxiliaryElements.getBeta() * dRdGaCos - auxiliaryElements.getGamma() * dRdBeCos;
1323 final double RBetaGammaSin = auxiliaryElements.getBeta() * dRdGaSin - auxiliaryElements.getGamma() * dRdBeSin;
1324 final double RhkCos = auxiliaryElements.getH() * dRdkCos - auxiliaryElements.getK() * dRdhCos;
1325 final double RhkSin = auxiliaryElements.getH() * dRdkSin - auxiliaryElements.getK() * dRdhSin;
1326 final double pRagmIqRbgoABCos = (auxiliaryElements.getP() * RAlphaGammaCos - I * auxiliaryElements.getQ() * RBetaGammaCos) * context.getOoAB();
1327 final double pRagmIqRbgoABSin = (auxiliaryElements.getP() * RAlphaGammaSin - I * auxiliaryElements.getQ() * RBetaGammaSin) * context.getOoAB();
1328 final double RhkmRabmdRdlCos = RhkCos - RAlphaBetaCos - dRdlCos;
1329 final double RhkmRabmdRdlSin = RhkSin - RAlphaBetaSin - dRdlSin;
1330
1331
1332 cCoef[m][j + jMax][0] = context.getAx2oA() * dRdlCos;
1333 sCoef[m][j + jMax][0] = context.getAx2oA() * dRdlSin;
1334
1335
1336 cCoef[m][j + jMax][1] = -(context.getBoA() * dRdhCos + auxiliaryElements.getH() * pRagmIqRbgoABCos + auxiliaryElements.getK() * context.getBoABpo() * dRdlCos);
1337 sCoef[m][j + jMax][1] = -(context.getBoA() * dRdhSin + auxiliaryElements.getH() * pRagmIqRbgoABSin + auxiliaryElements.getK() * context.getBoABpo() * dRdlSin);
1338
1339
1340 cCoef[m][j + jMax][2] = context.getBoA() * dRdkCos + auxiliaryElements.getK() * pRagmIqRbgoABCos - auxiliaryElements.getH() * context.getBoABpo() * dRdlCos;
1341 sCoef[m][j + jMax][2] = context.getBoA() * dRdkSin + auxiliaryElements.getK() * pRagmIqRbgoABSin - auxiliaryElements.getH() * context.getBoABpo() * dRdlSin;
1342
1343
1344 cCoef[m][j + jMax][3] = context.getCo2AB() * (auxiliaryElements.getQ() * RhkmRabmdRdlCos - I * RAlphaGammaCos);
1345 sCoef[m][j + jMax][3] = context.getCo2AB() * (auxiliaryElements.getQ() * RhkmRabmdRdlSin - I * RAlphaGammaSin);
1346
1347
1348 cCoef[m][j + jMax][4] = context.getCo2AB() * (auxiliaryElements.getP() * RhkmRabmdRdlCos - RBetaGammaCos);
1349 sCoef[m][j + jMax][4] = context.getCo2AB() * (auxiliaryElements.getP() * RhkmRabmdRdlSin - RBetaGammaSin);
1350
1351
1352 cCoef[m][j + jMax][5] = -context.getAx2oA() * dRdaCos + context.getBoABpo() * (auxiliaryElements.getH() * dRdhCos + auxiliaryElements.getK() * dRdkCos) + pRagmIqRbgoABCos;
1353 sCoef[m][j + jMax][5] = -context.getAx2oA() * dRdaSin + context.getBoABpo() * (auxiliaryElements.getH() * dRdhSin + auxiliaryElements.getK() * dRdkSin) + pRagmIqRbgoABSin;
1354 }
1355
1356
1357
1358
1359
1360
1361
1362 public double getCijm(final int i, final int j, final int m) {
1363 return cCoef[m][j + jMax][i];
1364 }
1365
1366
1367
1368
1369
1370
1371
1372 public double getSijm(final int i, final int j, final int m) {
1373 return sCoef[m][j + jMax][i];
1374 }
1375 }
1376
1377
1378
1379
1380
1381
1382
1383 private class FieldFourierCjSjCoefficients <T extends CalculusFieldElement<T>> {
1384
1385
1386 private final int jMax;
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401 private final T[][][] cCoef;
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416 private final T[][][] sCoef;
1417
1418
1419 private FieldGHmsjPolynomials<T> ghMSJ;
1420
1421
1422 private FieldGammaMnsFunction<T> gammaMNS;
1423
1424
1425 private final T[] roaPow;
1426
1427
1428
1429
1430
1431
1432 FieldFourierCjSjCoefficients(final int jMax, final int mMax, final Field<T> field) {
1433
1434 final T zero = field.getZero();
1435 final int rows = mMax + 1;
1436 final int columns = 2 * jMax + 1;
1437 this.jMax = jMax;
1438 this.cCoef = MathArrays.buildArray(field, rows, columns, 6);
1439 this.sCoef = MathArrays.buildArray(field, rows, columns, 6);
1440 this.roaPow = MathArrays.buildArray(field, maxDegree + 1);
1441 roaPow[0] = zero.newInstance(1.);
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451 public void generateCoefficients(final FieldAbsoluteDate<T> date,
1452 final FieldDSSTTesseralContext<T> context,
1453 final FieldHansenObjects<T> hansenObjects,
1454 final Field<T> field) {
1455
1456 final FieldAuxiliaryElements<T> auxiliaryElements = context.getFieldAuxiliaryElements();
1457
1458 if (!nonResOrders.isEmpty() || maxDegreeTesseralSP < 0) {
1459
1460 ghMSJ = new FieldGHmsjPolynomials<>(auxiliaryElements.getK(), auxiliaryElements.getH(), auxiliaryElements.getAlpha(), auxiliaryElements.getBeta(), I, field);
1461
1462
1463 gammaMNS = new FieldGammaMnsFunction<>(maxDegree, auxiliaryElements.getGamma(), I, field);
1464
1465 final int maxRoaPower = FastMath.max(maxDegreeTesseralSP, maxDegreeMdailyTesseralSP);
1466
1467
1468 for (int i = 1; i <= maxRoaPower; i++) {
1469 roaPow[i] = context.getRoa().multiply(roaPow[i - 1]);
1470 }
1471
1472
1473 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1474 buildFourierCoefficients(date, m, 0, maxDegreeMdailyTesseralSP, context, hansenObjects, field);
1475 }
1476
1477
1478 if (maxDegreeTesseralSP >= 0) {
1479 for (int m: nonResOrders.keySet()) {
1480 final List<Integer> listJ = nonResOrders.get(m);
1481
1482 for (int j: listJ) {
1483 buildFourierCoefficients(date, m, j, maxDegreeTesseralSP, context, hansenObjects, field);
1484 }
1485 }
1486 }
1487 }
1488 }
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500 private void buildFourierCoefficients(final FieldAbsoluteDate<T> date,
1501 final int m, final int j, final int maxN,
1502 final FieldDSSTTesseralContext<T> context,
1503 final FieldHansenObjects<T> hansenObjects,
1504 final Field<T> field) {
1505
1506
1507 final T zero = field.getZero();
1508
1509 final FieldAuxiliaryElements<T> auxiliaryElements = context.getFieldAuxiliaryElements();
1510
1511
1512 T dRdaCos = zero;
1513 T dRdaSin = zero;
1514 T dRdhCos = zero;
1515 T dRdhSin = zero;
1516 T dRdkCos = zero;
1517 T dRdkSin = zero;
1518 T dRdlCos = zero;
1519 T dRdlSin = zero;
1520 T dRdAlCos = zero;
1521 T dRdAlSin = zero;
1522 T dRdBeCos = zero;
1523 T dRdBeSin = zero;
1524 T dRdGaCos = zero;
1525 T dRdGaSin = zero;
1526
1527
1528 final int sMin = j == 0 ? maxEccPowMdailyTesseralSP : maxEccPowTesseralSP;
1529 final int sMax = j == 0 ? maxEccPowMdailyTesseralSP : maxEccPowTesseralSP;
1530 for (int s = 0; s <= sMax; s++) {
1531
1532
1533 final T[][] nSumSpos = computeNSum(date, j, m, s, maxN,
1534 roaPow, ghMSJ, gammaMNS, context, hansenObjects);
1535 dRdaCos = dRdaCos.add(nSumSpos[0][0]);
1536 dRdaSin = dRdaSin.add(nSumSpos[0][1]);
1537 dRdhCos = dRdhCos.add(nSumSpos[1][0]);
1538 dRdhSin = dRdhSin.add(nSumSpos[1][1]);
1539 dRdkCos = dRdkCos.add(nSumSpos[2][0]);
1540 dRdkSin = dRdkSin.add(nSumSpos[2][1]);
1541 dRdlCos = dRdlCos.add(nSumSpos[3][0]);
1542 dRdlSin = dRdlSin.add(nSumSpos[3][1]);
1543 dRdAlCos = dRdAlCos.add(nSumSpos[4][0]);
1544 dRdAlSin = dRdAlSin.add(nSumSpos[4][1]);
1545 dRdBeCos = dRdBeCos.add(nSumSpos[5][0]);
1546 dRdBeSin = dRdBeSin.add(nSumSpos[5][1]);
1547 dRdGaCos = dRdGaCos.add(nSumSpos[6][0]);
1548 dRdGaSin = dRdGaSin.add(nSumSpos[6][1]);
1549
1550
1551 if (s > 0 && s <= sMin) {
1552 final T[][] nSumSneg = computeNSum(date, j, m, -s, maxN,
1553 roaPow, ghMSJ, gammaMNS, context, hansenObjects);
1554 dRdaCos = dRdaCos.add(nSumSneg[0][0]);
1555 dRdaSin = dRdaSin.add(nSumSneg[0][1]);
1556 dRdhCos = dRdhCos.add(nSumSneg[1][0]);
1557 dRdhSin = dRdhSin.add(nSumSneg[1][1]);
1558 dRdkCos = dRdkCos.add(nSumSneg[2][0]);
1559 dRdkSin = dRdkSin.add(nSumSneg[2][1]);
1560 dRdlCos = dRdlCos.add(nSumSneg[3][0]);
1561 dRdlSin = dRdlSin.add(nSumSneg[3][1]);
1562 dRdAlCos = dRdAlCos.add(nSumSneg[4][0]);
1563 dRdAlSin = dRdAlSin.add(nSumSneg[4][1]);
1564 dRdBeCos = dRdBeCos.add(nSumSneg[5][0]);
1565 dRdBeSin = dRdBeSin.add(nSumSneg[5][1]);
1566 dRdGaCos = dRdGaCos.add(nSumSneg[6][0]);
1567 dRdGaSin = dRdGaSin.add(nSumSneg[6][1]);
1568 }
1569 }
1570 dRdaCos = dRdaCos.multiply(context.getMoa().negate().divide(auxiliaryElements.getSma()));
1571 dRdaSin = dRdaSin.multiply(context.getMoa().negate().divide(auxiliaryElements.getSma()));
1572 dRdhCos = dRdhCos.multiply(context.getMoa());
1573 dRdhSin = dRdhSin.multiply(context.getMoa());
1574 dRdkCos = dRdkCos.multiply(context.getMoa());
1575 dRdkSin = dRdkSin.multiply(context.getMoa());
1576 dRdlCos = dRdlCos.multiply(context.getMoa());
1577 dRdlSin = dRdlSin.multiply(context.getMoa());
1578 dRdAlCos = dRdAlCos.multiply(context.getMoa());
1579 dRdAlSin = dRdAlSin.multiply(context.getMoa());
1580 dRdBeCos = dRdBeCos.multiply(context.getMoa());
1581 dRdBeSin = dRdBeSin.multiply(context.getMoa());
1582 dRdGaCos = dRdGaCos.multiply(context.getMoa());
1583 dRdGaSin = dRdGaSin.multiply(context.getMoa());
1584
1585
1586 final T RAlphaGammaCos = auxiliaryElements.getAlpha().multiply(dRdGaCos).subtract(auxiliaryElements.getGamma().multiply(dRdAlCos));
1587 final T RAlphaGammaSin = auxiliaryElements.getAlpha().multiply(dRdGaSin).subtract(auxiliaryElements.getGamma().multiply(dRdAlSin));
1588 final T RAlphaBetaCos = auxiliaryElements.getAlpha().multiply(dRdBeCos).subtract(auxiliaryElements.getBeta().multiply(dRdAlCos));
1589 final T RAlphaBetaSin = auxiliaryElements.getAlpha().multiply(dRdBeSin).subtract(auxiliaryElements.getBeta().multiply(dRdAlSin));
1590 final T RBetaGammaCos = auxiliaryElements.getBeta().multiply(dRdGaCos).subtract(auxiliaryElements.getGamma().multiply(dRdBeCos));
1591 final T RBetaGammaSin = auxiliaryElements.getBeta().multiply(dRdGaSin).subtract(auxiliaryElements.getGamma().multiply(dRdBeSin));
1592 final T RhkCos = auxiliaryElements.getH().multiply(dRdkCos).subtract(auxiliaryElements.getK().multiply(dRdhCos));
1593 final T RhkSin = auxiliaryElements.getH().multiply(dRdkSin).subtract(auxiliaryElements.getK().multiply(dRdhSin));
1594 final T pRagmIqRbgoABCos = (auxiliaryElements.getP().multiply(RAlphaGammaCos).subtract(auxiliaryElements.getQ().multiply(RBetaGammaCos).multiply(I))).multiply(context.getOoAB());
1595 final T pRagmIqRbgoABSin = (auxiliaryElements.getP().multiply(RAlphaGammaSin).subtract(auxiliaryElements.getQ().multiply(RBetaGammaSin).multiply(I))).multiply(context.getOoAB());
1596 final T RhkmRabmdRdlCos = RhkCos.subtract(RAlphaBetaCos).subtract(dRdlCos);
1597 final T RhkmRabmdRdlSin = RhkSin.subtract(RAlphaBetaSin).subtract(dRdlSin);
1598
1599
1600 cCoef[m][j + jMax][0] = context.getAx2oA().multiply(dRdlCos);
1601 sCoef[m][j + jMax][0] = context.getAx2oA().multiply(dRdlSin);
1602
1603
1604 cCoef[m][j + jMax][1] = (context.getBoA().multiply(dRdhCos).add(auxiliaryElements.getH().multiply(pRagmIqRbgoABCos)).add(auxiliaryElements.getK().multiply(context.getBoABpo()).multiply(dRdlCos))).negate();
1605 sCoef[m][j + jMax][1] = (context.getBoA().multiply(dRdhSin).add(auxiliaryElements.getH().multiply(pRagmIqRbgoABSin)).add(auxiliaryElements.getK().multiply(context.getBoABpo()).multiply(dRdlSin))).negate();
1606
1607
1608 cCoef[m][j + jMax][2] = context.getBoA().multiply(dRdkCos).add(auxiliaryElements.getK().multiply(pRagmIqRbgoABCos)).subtract(auxiliaryElements.getH().multiply(context.getBoABpo()).multiply(dRdlCos));
1609 sCoef[m][j + jMax][2] = context.getBoA().multiply(dRdkSin).add(auxiliaryElements.getK().multiply(pRagmIqRbgoABSin)).subtract(auxiliaryElements.getH().multiply(context.getBoABpo()).multiply(dRdlSin));
1610
1611
1612 cCoef[m][j + jMax][3] = context.getCo2AB().multiply(auxiliaryElements.getQ().multiply(RhkmRabmdRdlCos).subtract(RAlphaGammaCos.multiply(I)));
1613 sCoef[m][j + jMax][3] = context.getCo2AB().multiply(auxiliaryElements.getQ().multiply(RhkmRabmdRdlSin).subtract(RAlphaGammaSin.multiply(I)));
1614
1615
1616 cCoef[m][j + jMax][4] = context.getCo2AB().multiply(auxiliaryElements.getP().multiply(RhkmRabmdRdlCos).subtract(RBetaGammaCos));
1617 sCoef[m][j + jMax][4] = context.getCo2AB().multiply(auxiliaryElements.getP().multiply(RhkmRabmdRdlSin).subtract(RBetaGammaSin));
1618
1619
1620 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);
1621 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);
1622 }
1623
1624
1625
1626
1627
1628
1629
1630 public T getCijm(final int i, final int j, final int m) {
1631 return cCoef[m][j + jMax][i];
1632 }
1633
1634
1635
1636
1637
1638
1639
1640 public T getSijm(final int i, final int j, final int m) {
1641 return sCoef[m][j + jMax][i];
1642 }
1643 }
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654 private static class TesseralShortPeriodicCoefficients implements ShortPeriodTerms {
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669 private static final int I = 1;
1670
1671
1672 private final Frame bodyFrame;
1673
1674
1675 private final int maxOrderMdailyTesseralSP;
1676
1677
1678 private final boolean mDailiesOnly;
1679
1680
1681 private final SortedMap<Integer, List<Integer> > nonResOrders;
1682
1683
1684 private final int mMax;
1685
1686
1687 private final int jMax;
1688
1689
1690 private final int interpolationPoints;
1691
1692
1693 private final transient TimeSpanMap<Slot> slots;
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705 TesseralShortPeriodicCoefficients(final Frame bodyFrame, final int maxOrderMdailyTesseralSP,
1706 final boolean mDailiesOnly, final SortedMap<Integer, List<Integer> > nonResOrders,
1707 final int mMax, final int jMax, final int interpolationPoints,
1708 final TimeSpanMap<Slot> slots) {
1709 this.bodyFrame = bodyFrame;
1710 this.maxOrderMdailyTesseralSP = maxOrderMdailyTesseralSP;
1711 this.mDailiesOnly = mDailiesOnly;
1712 this.nonResOrders = nonResOrders;
1713 this.mMax = mMax;
1714 this.jMax = jMax;
1715 this.interpolationPoints = interpolationPoints;
1716 this.slots = slots;
1717 }
1718
1719
1720
1721
1722
1723 public Slot createSlot(final SpacecraftState... meanStates) {
1724 final Slot slot = new Slot(mMax, jMax, interpolationPoints);
1725 final AbsoluteDate first = meanStates[0].getDate();
1726 final AbsoluteDate last = meanStates[meanStates.length - 1].getDate();
1727 final int compare = first.compareTo(last);
1728 if (compare < 0) {
1729 slots.addValidAfter(slot, first, false);
1730 } else if (compare > 0) {
1731 slots.addValidBefore(slot, first, false);
1732 } else {
1733
1734 slots.addValidAfter(slot, AbsoluteDate.PAST_INFINITY, false);
1735 }
1736 return slot;
1737 }
1738
1739
1740 @Override
1741 public double[] value(final Orbit meanOrbit) {
1742
1743
1744 final Slot slot = slots.get(meanOrbit.getDate());
1745
1746
1747 final double[] shortPeriodicVariation = new double[6];
1748
1749
1750
1751 if (!nonResOrders.isEmpty() || mDailiesOnly) {
1752
1753
1754 final AuxiliaryElements auxiliaryElements = new AuxiliaryElements(meanOrbit, I);
1755
1756
1757 final StaticTransform t = bodyFrame.getStaticTransformTo(
1758 auxiliaryElements.getFrame(),
1759 auxiliaryElements.getDate());
1760 final Vector3D xB = t.transformVector(Vector3D.PLUS_I);
1761 final Vector3D yB = t.transformVector(Vector3D.PLUS_J);
1762 final Vector3D f = auxiliaryElements.getVectorF();
1763 final Vector3D g = auxiliaryElements.getVectorG();
1764 final double currentTheta = FastMath.atan2(-f.dotProduct(yB) + I * g.dotProduct(xB),
1765 f.dotProduct(xB) + I * g.dotProduct(yB));
1766
1767
1768 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1769
1770 final double jlMmt = -m * currentTheta;
1771 final SinCos scPhi = FastMath.sinCos(jlMmt);
1772 final double sinPhi = scPhi.sin();
1773 final double cosPhi = scPhi.cos();
1774
1775
1776 final double[] c = slot.getCijm(0, m, meanOrbit.getDate());
1777 final double[] s = slot.getSijm(0, m, meanOrbit.getDate());
1778 for (int i = 0; i < 6; i++) {
1779 shortPeriodicVariation[i] += c[i] * cosPhi + s[i] * sinPhi;
1780 }
1781 }
1782
1783
1784 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
1785 final int m = entry.getKey();
1786 final List<Integer> listJ = entry.getValue();
1787
1788 for (int j : listJ) {
1789
1790 final double jlMmt = j * meanOrbit.getLM() - m * currentTheta;
1791 final SinCos scPhi = FastMath.sinCos(jlMmt);
1792 final double sinPhi = scPhi.sin();
1793 final double cosPhi = scPhi.cos();
1794
1795
1796 final double[] c = slot.getCijm(j, m, meanOrbit.getDate());
1797 final double[] s = slot.getSijm(j, m, meanOrbit.getDate());
1798 for (int i = 0; i < 6; i++) {
1799 shortPeriodicVariation[i] += c[i] * cosPhi + s[i] * sinPhi;
1800 }
1801
1802 }
1803 }
1804 }
1805
1806 return shortPeriodicVariation;
1807
1808 }
1809
1810
1811 @Override
1812 public String getCoefficientsKeyPrefix() {
1813 return DSSTTesseral.SHORT_PERIOD_PREFIX;
1814 }
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826 @Override
1827 public Map<String, double[]> getCoefficients(final AbsoluteDate date, final Set<String> selected) {
1828
1829
1830 final Slot slot = slots.get(date);
1831
1832 if (!nonResOrders.isEmpty() || mDailiesOnly) {
1833 final Map<String, double[]> coefficients = new HashMap<>(12 * maxOrderMdailyTesseralSP + 12 * nonResOrders.size());
1834
1835 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
1836 storeIfSelected(coefficients, selected, slot.getCijm(0, m, date), DSSTTesseral.CM_COEFFICIENTS, m);
1837 storeIfSelected(coefficients, selected, slot.getSijm(0, m, date), DSSTTesseral.SM_COEFFICIENTS, m);
1838 }
1839
1840 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
1841 final int m = entry.getKey();
1842 final List<Integer> listJ = entry.getValue();
1843
1844 for (int j : listJ) {
1845 for (int i = 0; i < 6; ++i) {
1846 storeIfSelected(coefficients, selected, slot.getCijm(j, m, date), "c", j, m);
1847 storeIfSelected(coefficients, selected, slot.getSijm(j, m, date), "s", j, m);
1848 }
1849 }
1850 }
1851
1852 return coefficients;
1853
1854 } else {
1855 return Collections.emptyMap();
1856 }
1857
1858 }
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868 private void storeIfSelected(final Map<String, double[]> map, final Set<String> selected,
1869 final double[] value, final String id, final int... indices) {
1870 final StringBuilder keyBuilder = new StringBuilder(getCoefficientsKeyPrefix());
1871 keyBuilder.append(id);
1872 for (int index : indices) {
1873 keyBuilder.append('[').append(index).append(']');
1874 }
1875 final String key = keyBuilder.toString();
1876 if (selected.isEmpty() || selected.contains(key)) {
1877 map.put(key, value);
1878 }
1879 }
1880
1881 }
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892 private static class FieldTesseralShortPeriodicCoefficients <T extends CalculusFieldElement<T>> implements FieldShortPeriodTerms<T> {
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907 private static final int I = 1;
1908
1909
1910 private final Frame bodyFrame;
1911
1912
1913 private final int maxOrderMdailyTesseralSP;
1914
1915
1916 private final boolean mDailiesOnly;
1917
1918
1919 private final SortedMap<Integer, List<Integer> > nonResOrders;
1920
1921
1922 private final int mMax;
1923
1924
1925 private final int jMax;
1926
1927
1928 private final int interpolationPoints;
1929
1930
1931 private final transient FieldTimeSpanMap<FieldSlot<T>, T> slots;
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943 FieldTesseralShortPeriodicCoefficients(final Frame bodyFrame, final int maxOrderMdailyTesseralSP,
1944 final boolean mDailiesOnly, final SortedMap<Integer, List<Integer> > nonResOrders,
1945 final int mMax, final int jMax, final int interpolationPoints,
1946 final FieldTimeSpanMap<FieldSlot<T>, T> slots) {
1947 this.bodyFrame = bodyFrame;
1948 this.maxOrderMdailyTesseralSP = maxOrderMdailyTesseralSP;
1949 this.mDailiesOnly = mDailiesOnly;
1950 this.nonResOrders = nonResOrders;
1951 this.mMax = mMax;
1952 this.jMax = jMax;
1953 this.interpolationPoints = interpolationPoints;
1954 this.slots = slots;
1955 }
1956
1957
1958
1959
1960
1961 @SuppressWarnings("unchecked")
1962 public FieldSlot<T> createSlot(final FieldSpacecraftState<T>... meanStates) {
1963 final FieldSlot<T> slot = new FieldSlot<>(mMax, jMax, interpolationPoints);
1964 final FieldAbsoluteDate<T> first = meanStates[0].getDate();
1965 final FieldAbsoluteDate<T> last = meanStates[meanStates.length - 1].getDate();
1966 if (first.compareTo(last) <= 0) {
1967 slots.addValidAfter(slot, first);
1968 } else {
1969 slots.addValidBefore(slot, first);
1970 }
1971 return slot;
1972 }
1973
1974
1975 @Override
1976 public T[] value(final FieldOrbit<T> meanOrbit) {
1977
1978
1979 final FieldSlot<T> slot = slots.get(meanOrbit.getDate());
1980
1981
1982 final T[] shortPeriodicVariation = MathArrays.buildArray(meanOrbit.getDate().getField(), 6);
1983
1984
1985
1986 if (!nonResOrders.isEmpty() || mDailiesOnly) {
1987
1988
1989 final FieldAuxiliaryElements<T> auxiliaryElements = new FieldAuxiliaryElements<>(meanOrbit, I);
1990
1991
1992 final FieldStaticTransform<T> t = bodyFrame.getStaticTransformTo(auxiliaryElements.getFrame(), auxiliaryElements.getDate());
1993 final FieldVector3D<T> xB = t.transformVector(Vector3D.PLUS_I);
1994 final FieldVector3D<T> yB = t.transformVector(Vector3D.PLUS_J);
1995 final FieldVector3D<T> f = auxiliaryElements.getVectorF();
1996 final FieldVector3D<T> g = auxiliaryElements.getVectorG();
1997 final T currentTheta = FastMath.atan2(f.dotProduct(yB).negate().add(g.dotProduct(xB).multiply(I)),
1998 f.dotProduct(xB).add(g.dotProduct(yB).multiply(I)));
1999
2000
2001 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
2002
2003 final T jlMmt = currentTheta.multiply(-m);
2004 final FieldSinCos<T> scPhi = FastMath.sinCos(jlMmt);
2005 final T sinPhi = scPhi.sin();
2006 final T cosPhi = scPhi.cos();
2007
2008
2009 final T[] c = slot.getCijm(0, m, meanOrbit.getDate());
2010 final T[] s = slot.getSijm(0, m, meanOrbit.getDate());
2011 for (int i = 0; i < 6; i++) {
2012 shortPeriodicVariation[i] = shortPeriodicVariation[i].add(c[i].multiply(cosPhi).add(s[i].multiply(sinPhi)));
2013 }
2014 }
2015
2016
2017 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
2018 final int m = entry.getKey();
2019 final List<Integer> listJ = entry.getValue();
2020
2021 for (int j : listJ) {
2022
2023 final T jlMmt = meanOrbit.getLM().multiply(j).subtract(currentTheta.multiply(m));
2024 final FieldSinCos<T> scPhi = FastMath.sinCos(jlMmt);
2025 final T sinPhi = scPhi.sin();
2026 final T cosPhi = scPhi.cos();
2027
2028
2029 final T[] c = slot.getCijm(j, m, meanOrbit.getDate());
2030 final T[] s = slot.getSijm(j, m, meanOrbit.getDate());
2031 for (int i = 0; i < 6; i++) {
2032 shortPeriodicVariation[i] = shortPeriodicVariation[i].add(c[i].multiply(cosPhi).add(s[i].multiply(sinPhi)));
2033 }
2034
2035 }
2036 }
2037 }
2038
2039 return shortPeriodicVariation;
2040
2041 }
2042
2043
2044 @Override
2045 public String getCoefficientsKeyPrefix() {
2046 return DSSTTesseral.SHORT_PERIOD_PREFIX;
2047 }
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059 @Override
2060 public Map<String, T[]> getCoefficients(final FieldAbsoluteDate<T> date, final Set<String> selected) {
2061
2062
2063 final FieldSlot<T> slot = slots.get(date);
2064
2065 if (!nonResOrders.isEmpty() || mDailiesOnly) {
2066 final Map<String, T[]> coefficients = new HashMap<>(12 * maxOrderMdailyTesseralSP + 12 * nonResOrders.size());
2067
2068 for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
2069 storeIfSelected(coefficients, selected, slot.getCijm(0, m, date), DSSTTesseral.CM_COEFFICIENTS, m);
2070 storeIfSelected(coefficients, selected, slot.getSijm(0, m, date), DSSTTesseral.SM_COEFFICIENTS, m);
2071 }
2072
2073 for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
2074 final int m = entry.getKey();
2075 final List<Integer> listJ = entry.getValue();
2076
2077 for (int j : listJ) {
2078 for (int i = 0; i < 6; ++i) {
2079 storeIfSelected(coefficients, selected, slot.getCijm(j, m, date), "c", j, m);
2080 storeIfSelected(coefficients, selected, slot.getSijm(j, m, date), "s", j, m);
2081 }
2082 }
2083 }
2084
2085 return coefficients;
2086
2087 } else {
2088 return Collections.emptyMap();
2089 }
2090
2091 }
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101 private void storeIfSelected(final Map<String, T[]> map, final Set<String> selected,
2102 final T[] value, final String id, final int... indices) {
2103 final StringBuilder keyBuilder = new StringBuilder(getCoefficientsKeyPrefix());
2104 keyBuilder.append(id);
2105 for (int index : indices) {
2106 keyBuilder.append('[').append(index).append(']');
2107 }
2108 final String key = keyBuilder.toString();
2109 if (selected.isEmpty() || selected.contains(key)) {
2110 map.put(key, value);
2111 }
2112 }
2113 }
2114
2115
2116 private static class Slot {
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130 private final ShortPeriodicsInterpolatedCoefficient[][] cijm;
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144 private final ShortPeriodicsInterpolatedCoefficient[][] sijm;
2145
2146
2147
2148
2149
2150
2151 Slot(final int mMax, final int jMax, final int interpolationPoints) {
2152
2153 final int rows = mMax + 1;
2154 final int columns = 2 * jMax + 1;
2155 cijm = new ShortPeriodicsInterpolatedCoefficient[rows][columns];
2156 sijm = new ShortPeriodicsInterpolatedCoefficient[rows][columns];
2157 for (int m = 1; m <= mMax; m++) {
2158 for (int j = -jMax; j <= jMax; j++) {
2159 cijm[m][j + jMax] = new ShortPeriodicsInterpolatedCoefficient(interpolationPoints);
2160 sijm[m][j + jMax] = new ShortPeriodicsInterpolatedCoefficient(interpolationPoints);
2161 }
2162 }
2163
2164 }
2165
2166
2167
2168
2169
2170
2171
2172
2173 double[] getCijm(final int j, final int m, final AbsoluteDate date) {
2174 final int jMax = (cijm[m].length - 1) / 2;
2175 return cijm[m][j + jMax].value(date);
2176 }
2177
2178
2179
2180
2181
2182
2183
2184
2185 double[] getSijm(final int j, final int m, final AbsoluteDate date) {
2186 final int jMax = (cijm[m].length - 1) / 2;
2187 return sijm[m][j + jMax].value(date);
2188 }
2189
2190 }
2191
2192
2193 private static class FieldSlot <T extends CalculusFieldElement<T>> {
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207 private final FieldShortPeriodicsInterpolatedCoefficient<T>[][] cijm;
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221 private final FieldShortPeriodicsInterpolatedCoefficient<T>[][] sijm;
2222
2223
2224
2225
2226
2227
2228 @SuppressWarnings("unchecked")
2229 FieldSlot(final int mMax, final int jMax, final int interpolationPoints) {
2230
2231 final int rows = mMax + 1;
2232 final int columns = 2 * jMax + 1;
2233 cijm = (FieldShortPeriodicsInterpolatedCoefficient<T>[][]) Array.newInstance(FieldShortPeriodicsInterpolatedCoefficient.class, rows, columns);
2234 sijm = (FieldShortPeriodicsInterpolatedCoefficient<T>[][]) Array.newInstance(FieldShortPeriodicsInterpolatedCoefficient.class, rows, columns);
2235 for (int m = 1; m <= mMax; m++) {
2236 for (int j = -jMax; j <= jMax; j++) {
2237 cijm[m][j + jMax] = new FieldShortPeriodicsInterpolatedCoefficient<>(interpolationPoints);
2238 sijm[m][j + jMax] = new FieldShortPeriodicsInterpolatedCoefficient<>(interpolationPoints);
2239 }
2240 }
2241
2242 }
2243
2244
2245
2246
2247
2248
2249
2250
2251 T[] getCijm(final int j, final int m, final FieldAbsoluteDate<T> date) {
2252 final int jMax = (cijm[m].length - 1) / 2;
2253 return cijm[m][j + jMax].value(date);
2254 }
2255
2256
2257
2258
2259
2260
2261
2262
2263 T[] getSijm(final int j, final int m, final FieldAbsoluteDate<T> date) {
2264 final int jMax = (cijm[m].length - 1) / 2;
2265 return sijm[m][j + jMax].value(date);
2266 }
2267
2268 }
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283 private class UAnddU {
2284
2285
2286 private double dUda;
2287
2288
2289 private double dUdk;
2290
2291
2292 private double dUdh;
2293
2294
2295 private double dUdl;
2296
2297
2298 private double dUdAl;
2299
2300
2301 private double dUdBe;
2302
2303
2304 private double dUdGa;
2305
2306
2307
2308
2309
2310
2311 UAnddU(final AbsoluteDate date, final DSSTTesseralContext context, final HansenObjects hansen) {
2312
2313
2314 final AuxiliaryElements auxiliaryElements = context.getAuxiliaryElements();
2315
2316
2317 dUda = 0.;
2318 dUdh = 0.;
2319 dUdk = 0.;
2320 dUdl = 0.;
2321 dUdAl = 0.;
2322 dUdBe = 0.;
2323 dUdGa = 0.;
2324
2325
2326 if (!resOrders.isEmpty()) {
2327
2328 final GHmsjPolynomials ghMSJ = new GHmsjPolynomials(auxiliaryElements.getK(), auxiliaryElements.getH(), auxiliaryElements.getAlpha(), auxiliaryElements.getBeta(), I);
2329
2330
2331 final GammaMnsFunction gammaMNS = new GammaMnsFunction(maxDegree, auxiliaryElements.getGamma(), I);
2332
2333
2334 final double[] roaPow = new double[maxDegree + 1];
2335 roaPow[0] = 1.;
2336 for (int i = 1; i <= maxDegree; i++) {
2337 roaPow[i] = context.getRoa() * roaPow[i - 1];
2338 }
2339
2340
2341 for (int m : resOrders) {
2342
2343
2344 final int j = FastMath.max(1, (int) FastMath.round(context.getRatio() * m));
2345
2346
2347 final double jlMmt = j * auxiliaryElements.getLM() - m * context.getTheta();
2348 final SinCos scPhi = FastMath.sinCos(jlMmt);
2349 final double sinPhi = scPhi.sin();
2350 final double cosPhi = scPhi.cos();
2351
2352
2353 double dUdaCos = 0.;
2354 double dUdaSin = 0.;
2355 double dUdhCos = 0.;
2356 double dUdhSin = 0.;
2357 double dUdkCos = 0.;
2358 double dUdkSin = 0.;
2359 double dUdlCos = 0.;
2360 double dUdlSin = 0.;
2361 double dUdAlCos = 0.;
2362 double dUdAlSin = 0.;
2363 double dUdBeCos = 0.;
2364 double dUdBeSin = 0.;
2365 double dUdGaCos = 0.;
2366 double dUdGaSin = 0.;
2367
2368
2369 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
2370 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
2371 for (int s = 0; s <= sMax; s++) {
2372
2373
2374 hansen.computeHansenObjectsInitValues(context, s + maxDegree, j);
2375
2376
2377 final double[][] nSumSpos = computeNSum(date, j, m, s, maxDegree,
2378 roaPow, ghMSJ, gammaMNS, context, hansen);
2379 dUdaCos += nSumSpos[0][0];
2380 dUdaSin += nSumSpos[0][1];
2381 dUdhCos += nSumSpos[1][0];
2382 dUdhSin += nSumSpos[1][1];
2383 dUdkCos += nSumSpos[2][0];
2384 dUdkSin += nSumSpos[2][1];
2385 dUdlCos += nSumSpos[3][0];
2386 dUdlSin += nSumSpos[3][1];
2387 dUdAlCos += nSumSpos[4][0];
2388 dUdAlSin += nSumSpos[4][1];
2389 dUdBeCos += nSumSpos[5][0];
2390 dUdBeSin += nSumSpos[5][1];
2391 dUdGaCos += nSumSpos[6][0];
2392 dUdGaSin += nSumSpos[6][1];
2393
2394
2395 if (s > 0 && s <= sMin) {
2396
2397 hansen.computeHansenObjectsInitValues(context, maxDegree - s, j);
2398
2399 final double[][] nSumSneg = computeNSum(date, j, m, -s, maxDegree,
2400 roaPow, ghMSJ, gammaMNS, context, hansen);
2401 dUdaCos += nSumSneg[0][0];
2402 dUdaSin += nSumSneg[0][1];
2403 dUdhCos += nSumSneg[1][0];
2404 dUdhSin += nSumSneg[1][1];
2405 dUdkCos += nSumSneg[2][0];
2406 dUdkSin += nSumSneg[2][1];
2407 dUdlCos += nSumSneg[3][0];
2408 dUdlSin += nSumSneg[3][1];
2409 dUdAlCos += nSumSneg[4][0];
2410 dUdAlSin += nSumSneg[4][1];
2411 dUdBeCos += nSumSneg[5][0];
2412 dUdBeSin += nSumSneg[5][1];
2413 dUdGaCos += nSumSneg[6][0];
2414 dUdGaSin += nSumSneg[6][1];
2415 }
2416 }
2417
2418
2419 dUda += cosPhi * dUdaCos + sinPhi * dUdaSin;
2420 dUdh += cosPhi * dUdhCos + sinPhi * dUdhSin;
2421 dUdk += cosPhi * dUdkCos + sinPhi * dUdkSin;
2422 dUdl += cosPhi * dUdlCos + sinPhi * dUdlSin;
2423 dUdAl += cosPhi * dUdAlCos + sinPhi * dUdAlSin;
2424 dUdBe += cosPhi * dUdBeCos + sinPhi * dUdBeSin;
2425 dUdGa += cosPhi * dUdGaCos + sinPhi * dUdGaSin;
2426 }
2427
2428 this.dUda = dUda * (-context.getMoa() / auxiliaryElements.getSma());
2429 this.dUdh = dUdh * context.getMoa();
2430 this.dUdk = dUdk * context.getMoa();
2431 this.dUdl = dUdl * context.getMoa();
2432 this.dUdAl = dUdAl * context.getMoa();
2433 this.dUdBe = dUdBe * context.getMoa();
2434 this.dUdGa = dUdGa * context.getMoa();
2435 }
2436
2437 }
2438
2439
2440
2441
2442 public double getdUda() {
2443 return dUda;
2444 }
2445
2446
2447
2448
2449 public double getdUdk() {
2450 return dUdk;
2451 }
2452
2453
2454
2455
2456 public double getdUdh() {
2457 return dUdh;
2458 }
2459
2460
2461
2462
2463 public double getdUdl() {
2464 return dUdl;
2465 }
2466
2467
2468
2469
2470 public double getdUdAl() {
2471 return dUdAl;
2472 }
2473
2474
2475
2476
2477 public double getdUdBe() {
2478 return dUdBe;
2479 }
2480
2481
2482
2483
2484 public double getdUdGa() {
2485 return dUdGa;
2486 }
2487
2488 }
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503 private class FieldUAnddU <T extends CalculusFieldElement<T>> {
2504
2505
2506 private T dUda;
2507
2508
2509 private T dUdk;
2510
2511
2512 private T dUdh;
2513
2514
2515 private T dUdl;
2516
2517
2518 private T dUdAl;
2519
2520
2521 private T dUdBe;
2522
2523
2524 private T dUdGa;
2525
2526
2527
2528
2529
2530
2531 FieldUAnddU(final FieldAbsoluteDate<T> date, final FieldDSSTTesseralContext<T> context,
2532 final FieldHansenObjects<T> hansen) {
2533
2534
2535 final FieldAuxiliaryElements<T> auxiliaryElements = context.getFieldAuxiliaryElements();
2536
2537
2538 final Field<T> field = date.getField();
2539 final T zero = field.getZero();
2540
2541
2542 dUda = zero;
2543 dUdh = zero;
2544 dUdk = zero;
2545 dUdl = zero;
2546 dUdAl = zero;
2547 dUdBe = zero;
2548 dUdGa = zero;
2549
2550
2551 if (!resOrders.isEmpty()) {
2552
2553 final FieldGHmsjPolynomials<T> ghMSJ = new FieldGHmsjPolynomials<>(auxiliaryElements.getK(), auxiliaryElements.getH(), auxiliaryElements.getAlpha(), auxiliaryElements.getBeta(), I, field);
2554
2555
2556 final FieldGammaMnsFunction<T> gammaMNS = new FieldGammaMnsFunction<>(maxDegree, auxiliaryElements.getGamma(), I, field);
2557
2558
2559 final T[] roaPow = MathArrays.buildArray(field, maxDegree + 1);
2560 roaPow[0] = zero.newInstance(1.);
2561 for (int i = 1; i <= maxDegree; i++) {
2562 roaPow[i] = roaPow[i - 1].multiply(context.getRoa());
2563 }
2564
2565
2566 for (int m : resOrders) {
2567
2568
2569 final int j = FastMath.max(1, (int) FastMath.round(context.getRatio().multiply(m)));
2570
2571
2572 final T jlMmt = auxiliaryElements.getLM().multiply(j).subtract(context.getTheta().multiply(m));
2573 final FieldSinCos<T> scPhi = FastMath.sinCos(jlMmt);
2574 final T sinPhi = scPhi.sin();
2575 final T cosPhi = scPhi.cos();
2576
2577
2578 T dUdaCos = zero;
2579 T dUdaSin = zero;
2580 T dUdhCos = zero;
2581 T dUdhSin = zero;
2582 T dUdkCos = zero;
2583 T dUdkSin = zero;
2584 T dUdlCos = zero;
2585 T dUdlSin = zero;
2586 T dUdAlCos = zero;
2587 T dUdAlSin = zero;
2588 T dUdBeCos = zero;
2589 T dUdBeSin = zero;
2590 T dUdGaCos = zero;
2591 T dUdGaSin = zero;
2592
2593
2594 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
2595 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
2596 for (int s = 0; s <= sMax; s++) {
2597
2598
2599 hansen.computeHansenObjectsInitValues(context, s + maxDegree, j);
2600
2601
2602 final T[][] nSumSpos = computeNSum(date, j, m, s, maxDegree,
2603 roaPow, ghMSJ, gammaMNS, context, hansen);
2604 dUdaCos = dUdaCos.add(nSumSpos[0][0]);
2605 dUdaSin = dUdaSin.add(nSumSpos[0][1]);
2606 dUdhCos = dUdhCos.add(nSumSpos[1][0]);
2607 dUdhSin = dUdhSin.add(nSumSpos[1][1]);
2608 dUdkCos = dUdkCos.add(nSumSpos[2][0]);
2609 dUdkSin = dUdkSin.add(nSumSpos[2][1]);
2610 dUdlCos = dUdlCos.add(nSumSpos[3][0]);
2611 dUdlSin = dUdlSin.add(nSumSpos[3][1]);
2612 dUdAlCos = dUdAlCos.add(nSumSpos[4][0]);
2613 dUdAlSin = dUdAlSin.add(nSumSpos[4][1]);
2614 dUdBeCos = dUdBeCos.add(nSumSpos[5][0]);
2615 dUdBeSin = dUdBeSin.add(nSumSpos[5][1]);
2616 dUdGaCos = dUdGaCos.add(nSumSpos[6][0]);
2617 dUdGaSin = dUdGaSin.add(nSumSpos[6][1]);
2618
2619
2620 if (s > 0 && s <= sMin) {
2621
2622 hansen.computeHansenObjectsInitValues(context, maxDegree - s, j);
2623
2624 final T[][] nSumSneg = computeNSum(date, j, m, -s, maxDegree,
2625 roaPow, ghMSJ, gammaMNS, context, hansen);
2626 dUdaCos = dUdaCos.add(nSumSneg[0][0]);
2627 dUdaSin = dUdaSin.add(nSumSneg[0][1]);
2628 dUdhCos = dUdhCos.add(nSumSneg[1][0]);
2629 dUdhSin = dUdhSin.add(nSumSneg[1][1]);
2630 dUdkCos = dUdkCos.add(nSumSneg[2][0]);
2631 dUdkSin = dUdkSin.add(nSumSneg[2][1]);
2632 dUdlCos = dUdlCos.add(nSumSneg[3][0]);
2633 dUdlSin = dUdlSin.add(nSumSneg[3][1]);
2634 dUdAlCos = dUdAlCos.add(nSumSneg[4][0]);
2635 dUdAlSin = dUdAlSin.add(nSumSneg[4][1]);
2636 dUdBeCos = dUdBeCos.add(nSumSneg[5][0]);
2637 dUdBeSin = dUdBeSin.add(nSumSneg[5][1]);
2638 dUdGaCos = dUdGaCos.add(nSumSneg[6][0]);
2639 dUdGaSin = dUdGaSin.add(nSumSneg[6][1]);
2640 }
2641 }
2642
2643
2644 dUda = dUda.add(dUdaCos.multiply(cosPhi).add(dUdaSin.multiply(sinPhi)));
2645 dUdh = dUdh.add(dUdhCos.multiply(cosPhi).add(dUdhSin.multiply(sinPhi)));
2646 dUdk = dUdk.add(dUdkCos.multiply(cosPhi).add(dUdkSin.multiply(sinPhi)));
2647 dUdl = dUdl.add(dUdlCos.multiply(cosPhi).add(dUdlSin.multiply(sinPhi)));
2648 dUdAl = dUdAl.add(dUdAlCos.multiply(cosPhi).add(dUdAlSin.multiply(sinPhi)));
2649 dUdBe = dUdBe.add(dUdBeCos.multiply(cosPhi).add(dUdBeSin.multiply(sinPhi)));
2650 dUdGa = dUdGa.add(dUdGaCos.multiply(cosPhi).add(dUdGaSin.multiply(sinPhi)));
2651 }
2652
2653 dUda = dUda.multiply(context.getMoa().divide(auxiliaryElements.getSma())).negate();
2654 dUdh = dUdh.multiply(context.getMoa());
2655 dUdk = dUdk.multiply(context.getMoa());
2656 dUdl = dUdl.multiply(context.getMoa());
2657 dUdAl = dUdAl.multiply(context.getMoa());
2658 dUdBe = dUdBe.multiply(context.getMoa());
2659 dUdGa = dUdGa.multiply(context.getMoa());
2660
2661 }
2662
2663 }
2664
2665
2666
2667
2668 public T getdUda() {
2669 return dUda;
2670 }
2671
2672
2673
2674
2675 public T getdUdk() {
2676 return dUdk;
2677 }
2678
2679
2680
2681
2682 public T getdUdh() {
2683 return dUdh;
2684 }
2685
2686
2687
2688
2689 public T getdUdl() {
2690 return dUdl;
2691 }
2692
2693
2694
2695
2696 public T getdUdAl() {
2697 return dUdAl;
2698 }
2699
2700
2701
2702
2703 public T getdUdBe() {
2704 return dUdBe;
2705 }
2706
2707
2708
2709
2710 public T getdUdGa() {
2711 return dUdGa;
2712 }
2713
2714 }
2715
2716
2717 private class HansenObjects {
2718
2719
2720
2721 private HansenTesseralLinear[][] hansenObjects;
2722
2723
2724
2725
2726
2727 HansenObjects(final double ratio,
2728 final PropagationType type) {
2729
2730
2731 final int rows = 2 * maxDegree + 1;
2732 final int columns = maxFrequencyShortPeriodics + 1;
2733 this.hansenObjects = new HansenTesseralLinear[rows][columns];
2734
2735 switch (type) {
2736 case MEAN:
2737
2738 for (int m : resOrders) {
2739
2740 final int j = FastMath.max(1, (int) FastMath.round(ratio * m));
2741
2742
2743 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
2744 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
2745
2746
2747 for (int s = 0; s <= sMax; s++) {
2748
2749 final int n0 = FastMath.max(FastMath.max(2, m), s);
2750
2751
2752 this.hansenObjects[s + maxDegree][j] = new HansenTesseralLinear(maxDegree, s, j, n0, maxHansen);
2753
2754 if (s > 0 && s <= sMin) {
2755
2756 this.hansenObjects[maxDegree - s][j] = new HansenTesseralLinear(maxDegree, -s, j, n0, maxHansen);
2757 }
2758 }
2759 }
2760 break;
2761
2762 case OSCULATING:
2763
2764 for (int j = 0; j <= maxFrequencyShortPeriodics; j++) {
2765 for (int s = -maxDegree; s <= maxDegree; s++) {
2766
2767 final int n0 = FastMath.max(2, FastMath.abs(s));
2768 this.hansenObjects[s + maxDegree][j] = new HansenTesseralLinear(maxDegree, s, j, n0, maxHansen);
2769 }
2770 }
2771 break;
2772
2773 default:
2774 throw new OrekitInternalError(null);
2775 }
2776
2777 }
2778
2779
2780
2781
2782
2783
2784 public void computeHansenObjectsInitValues(final DSSTTesseralContext context, final int rows, final int columns) {
2785 hansenObjects[rows][columns].computeInitValues(context.getE2(), context.getChi(), context.getChi2());
2786 }
2787
2788
2789
2790
2791 public HansenTesseralLinear[][] getHansenObjects() {
2792 return hansenObjects;
2793 }
2794
2795 }
2796
2797
2798 private class FieldHansenObjects<T extends CalculusFieldElement<T>> {
2799
2800
2801
2802 private FieldHansenTesseralLinear<T>[][] hansenObjects;
2803
2804
2805
2806
2807
2808 @SuppressWarnings("unchecked")
2809 FieldHansenObjects(final T ratio,
2810 final PropagationType type) {
2811
2812
2813 maxHansen = maxEccPow / 2;
2814
2815
2816 final int rows = 2 * maxDegree + 1;
2817 final int columns = maxFrequencyShortPeriodics + 1;
2818 this.hansenObjects = (FieldHansenTesseralLinear<T>[][]) Array.newInstance(FieldHansenTesseralLinear.class, rows, columns);
2819
2820 switch (type) {
2821 case MEAN:
2822
2823 for (int m : resOrders) {
2824
2825 final int j = FastMath.max(1, (int) FastMath.round(ratio.multiply(m)));
2826
2827
2828 final int sMin = FastMath.min(maxEccPow - j, maxDegree);
2829 final int sMax = FastMath.min(maxEccPow + j, maxDegree);
2830
2831
2832 for (int s = 0; s <= sMax; s++) {
2833
2834 final int n0 = FastMath.max(FastMath.max(2, m), s);
2835
2836
2837 this.hansenObjects[s + maxDegree][j] = new FieldHansenTesseralLinear<>(maxDegree, s, j, n0, maxHansen, ratio.getField());
2838
2839 if (s > 0 && s <= sMin) {
2840
2841 this.hansenObjects[maxDegree - s][j] = new FieldHansenTesseralLinear<>(maxDegree, -s, j, n0, maxHansen, ratio.getField());
2842 }
2843 }
2844 }
2845 break;
2846
2847 case OSCULATING:
2848
2849 for (int j = 0; j <= maxFrequencyShortPeriodics; j++) {
2850 for (int s = -maxDegree; s <= maxDegree; s++) {
2851
2852 final int n0 = FastMath.max(2, FastMath.abs(s));
2853 this.hansenObjects[s + maxDegree][j] = new FieldHansenTesseralLinear<>(maxDegree, s, j, n0, maxHansen, ratio.getField());
2854 }
2855 }
2856 break;
2857
2858 default:
2859 throw new OrekitInternalError(null);
2860 }
2861
2862 }
2863
2864
2865
2866
2867
2868
2869 public void computeHansenObjectsInitValues(final FieldDSSTTesseralContext<T> context,
2870 final int rows, final int columns) {
2871 hansenObjects[rows][columns].computeInitValues(context.getE2(), context.getChi(), context.getChi2());
2872 }
2873
2874
2875
2876
2877 public FieldHansenTesseralLinear<T>[][] getHansenObjects() {
2878 return hansenObjects;
2879 }
2880
2881 }
2882
2883 }