1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.models.earth.troposphere;
18
19 import org.hipparchus.Field;
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.util.FastMath;
22 import org.hipparchus.util.FieldSinCos;
23 import org.hipparchus.util.MathArrays;
24 import org.hipparchus.util.SinCos;
25 import org.orekit.annotation.DefaultDataContext;
26 import org.orekit.bodies.FieldGeodeticPoint;
27 import org.orekit.bodies.GeodeticPoint;
28 import org.orekit.data.DataContext;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.time.DateTimeComponents;
31 import org.orekit.time.FieldAbsoluteDate;
32 import org.orekit.time.TimeScale;
33 import org.orekit.utils.FieldLegendrePolynomials;
34 import org.orekit.utils.LegendrePolynomials;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 public class GlobalMappingFunctionModel implements MappingFunction {
58
59
60 private static final double FACTOR = 1.0e-5;
61
62
63 private final TimeScale utc;
64
65
66
67
68
69
70
71 @DefaultDataContext
72 public GlobalMappingFunctionModel() {
73 this(DataContext.getDefault().getTimeScales().getUTC());
74 }
75
76
77
78
79
80 public GlobalMappingFunctionModel(final TimeScale utc) {
81 this.utc = utc;
82 }
83
84
85 @Override
86 public double[] mappingFactors(final double elevation, final GeodeticPoint point,
87 final AbsoluteDate date) {
88
89 final DateTimeComponents dtc = date.getComponents(utc);
90 final int dofyear = dtc.getDate().getDayOfYear();
91
92
93 final double bh = 0.0029;
94 final double c0h = 0.062;
95 final double c10h;
96 final double c11h;
97 final double psi;
98
99
100 final double latitude = point.getLatitude();
101 final double longitude = point.getLongitude();
102
103 if (FastMath.sin(latitude) > 0) {
104
105 c10h = 0.001;
106 c11h = 0.005;
107 psi = 0.0;
108 } else {
109
110 c10h = 0.002;
111 c11h = 0.007;
112 psi = FastMath.PI;
113 }
114
115 double t0 = 28;
116 if (latitude < 0) {
117
118 t0 += 183;
119 }
120 final double coef = ((dofyear + 1 - t0) / 365.25) * 2 * FastMath.PI + psi;
121 final double ch = c0h + ((FastMath.cos(coef) + 1) * (c11h / 2.0) + c10h) * (1.0 - FastMath.cos(latitude));
122
123
124 final double bw = 0.00146;
125 final double cw = 0.04391;
126
127
128
129
130 final int degree = 9;
131 final int order = 9;
132 final LegendrePolynomials p = new LegendrePolynomials(degree, order, FastMath.sin(latitude));
133
134 double a0Hydro = 0.;
135 double amplHydro = 0.;
136 double a0Wet = 0.;
137 double amplWet = 0.;
138 final ABCoefficients abCoef = new ABCoefficients();
139 int j = 0;
140 for (int n = 0; n <= 9; n++) {
141 for (int m = 0; m <= n; m++) {
142
143 final SinCos sc = FastMath.sinCos(m * longitude);
144
145 a0Hydro = a0Hydro + (abCoef.getAHMean(j) * p.getPnm(n, m) * sc.cos() +
146 abCoef.getBHMean(j) * p.getPnm(n, m) * sc.sin()) * FACTOR;
147
148 a0Wet = a0Wet + (abCoef.getAWMean(j) * p.getPnm(n, m) * sc.cos() +
149 abCoef.getBWMean(j) * p.getPnm(n, m) * sc.sin()) * FACTOR;
150
151 amplHydro = amplHydro + (abCoef.getAHAmplitude(j) * p.getPnm(n, m) * sc.cos() +
152 abCoef.getBHAmplitude(j) * p.getPnm(n, m) * sc.sin()) * FACTOR;
153
154 amplWet = amplWet + (abCoef.getAWAmplitude(j) * p.getPnm(n, m) * sc.cos() +
155 abCoef.getBWAmplitude(j) * p.getPnm(n, m) * sc.sin()) * FACTOR;
156
157 j = j + 1;
158 }
159 }
160
161
162 final double ah = a0Hydro + amplHydro * FastMath.cos(coef - psi);
163 final double aw = a0Wet + amplWet * FastMath.cos(coef - psi);
164
165 final double[] function = new double[2];
166 function[0] = TroposphericModelUtils.mappingFunction(ah, bh, ch, elevation);
167 function[1] = TroposphericModelUtils.mappingFunction(aw, bw, cw, elevation);
168
169
170 final double correction = TroposphericModelUtils.computeHeightCorrection(elevation, point.getAltitude());
171 function[0] = function[0] + correction;
172
173 return function;
174 }
175
176
177 @Override
178 public <T extends CalculusFieldElement<T>> T[] mappingFactors(final T elevation, final FieldGeodeticPoint<T> point,
179 final FieldAbsoluteDate<T> date) {
180
181 final DateTimeComponents dtc = date.getComponents(utc);
182 final int dofyear = dtc.getDate().getDayOfYear();
183
184 final Field<T> field = date.getField();
185 final T zero = field.getZero();
186
187
188 final T bh = zero.add(0.0029);
189 final T c0h = zero.add(0.062);
190 final T c10h;
191 final T c11h;
192 final T psi;
193
194
195 final T latitude = point.getLatitude();
196 final T longitude = point.getLongitude();
197
198
199 if (FastMath.sin(latitude.getReal()) > 0) {
200 c10h = zero.add(0.001);
201 c11h = zero.add(0.005);
202 psi = zero;
203 } else {
204 c10h = zero.add(0.002);
205 c11h = zero.add(0.007);
206 psi = zero.getPi();
207 }
208
209 double t0 = 28;
210 if (latitude.getReal() < 0) {
211
212 t0 += 183;
213 }
214 final T coef = psi.add(zero.getPi().multiply(2.0).multiply((dofyear + 1 - t0) / 365.25));
215 final T ch = c11h.divide(2.0).multiply(FastMath.cos(coef).add(1.0)).add(c10h).multiply(FastMath.cos(latitude).negate().add(1.0)).add(c0h);
216
217
218 final T bw = zero.add(0.00146);
219 final T cw = zero.add(0.04391);
220
221
222
223
224 final int degree = 9;
225 final int order = 9;
226 final FieldLegendrePolynomials<T> p = new FieldLegendrePolynomials<>(degree, order, FastMath.sin(latitude));
227
228 T a0Hydro = zero;
229 T amplHydro = zero;
230 T a0Wet = zero;
231 T amplWet = zero;
232 final ABCoefficients abCoef = new ABCoefficients();
233 int j = 0;
234 for (int n = 0; n <= 9; n++) {
235 for (int m = 0; m <= n; m++) {
236
237 final FieldSinCos<T> sc = FastMath.sinCos(longitude.multiply(m));
238
239
240 a0Hydro = a0Hydro.add(p.getPnm(n, m).multiply(abCoef.getAHMean(j)).multiply(sc.cos()).
241 add(p.getPnm(n, m).multiply(abCoef.getBHMean(j)).multiply(sc.sin())).
242 multiply(FACTOR));
243
244 a0Wet = a0Wet.add(p.getPnm(n, m).multiply(abCoef.getAWMean(j)).multiply(sc.cos()).
245 add(p.getPnm(n, m).multiply(abCoef.getBWMean(j)).multiply(sc.sin())).
246 multiply(FACTOR));
247
248 amplHydro = amplHydro.add(p.getPnm(n, m).multiply(abCoef.getAHAmplitude(j)).multiply(sc.cos()).
249 add(p.getPnm(n, m).multiply(abCoef.getBHAmplitude(j)).multiply(sc.sin())).
250 multiply(FACTOR));
251
252 amplWet = amplWet.add(p.getPnm(n, m).multiply(abCoef.getAWAmplitude(j)).multiply(sc.cos()).
253 add(p.getPnm(n, m).multiply(abCoef.getBWAmplitude(j)).multiply(sc.sin())).
254 multiply(FACTOR));
255
256 j = j + 1;
257 }
258 }
259
260
261 final T ah = a0Hydro.add(amplHydro.multiply(FastMath.cos(coef.subtract(psi))));
262 final T aw = a0Wet.add(amplWet.multiply(FastMath.cos(coef.subtract(psi))));
263
264 final T[] function = MathArrays.buildArray(field, 2);
265 function[0] = TroposphericModelUtils.mappingFunction(ah, bh, ch, elevation);
266 function[1] = TroposphericModelUtils.mappingFunction(aw, bw, cw, elevation);
267
268
269 final T correction = TroposphericModelUtils.computeHeightCorrection(elevation, point.getAltitude(), field);
270 function[0] = function[0].add(correction);
271
272 return function;
273 }
274
275 private static class ABCoefficients {
276
277
278 private static final double[] AH_MEAN = {
279 1.2517e02,
280 8.503e-01,
281 6.936e-02,
282 -6.760e+00,
283 1.771e-01,
284 1.130e-02,
285 5.963e-01,
286 1.808e-02,
287 2.801e-03,
288 -1.414e-03,
289 -1.212e+00,
290 9.300e-02,
291 3.683e-03,
292 1.095e-03,
293 4.671e-05,
294 3.959e-01,
295 -3.867e-02,
296 5.413e-03,
297 -5.289e-04,
298 3.229e-04,
299 2.067e-05,
300 3.000e-01,
301 2.031e-02,
302 5.900e-03,
303 4.573e-04,
304 -7.619e-05,
305 2.327e-06,
306 3.845e-06,
307 1.182e-01,
308 1.158e-02,
309 5.445e-03,
310 6.219e-05,
311 4.204e-06,
312 -2.093e-06,
313 1.540e-07,
314 -4.280e-08,
315 -4.751e-01,
316 -3.490e-02,
317 1.758e-03,
318 4.019e-04,
319 -2.799e-06,
320 -1.287e-06,
321 5.468e-07,
322 7.580e-08,
323 -6.300e-09,
324 -1.160e-01,
325 8.301e-03,
326 8.771e-04,
327 9.955e-05,
328 -1.718e-06,
329 -2.012e-06,
330 1.170e-08,
331 1.790e-08,
332 -1.300e-09,
333 1.000e-10
334 };
335
336
337 private static final double[] BH_MEAN = {
338 0.000e+00,
339 0.000e+00,
340 3.249e-02,
341 0.000e+00,
342 3.324e-02,
343 1.850e-02,
344 0.000e+00,
345 -1.115e-01,
346 2.519e-02,
347 4.923e-03,
348 0.000e+00,
349 2.737e-02,
350 1.595e-02,
351 -7.332e-04,
352 1.933e-04,
353 0.000e+00,
354 -4.796e-02,
355 6.381e-03,
356 -1.599e-04,
357 -3.685e-04,
358 1.815e-05,
359 0.000e+00,
360 7.033e-02,
361 2.426e-03,
362 -1.111e-03,
363 -1.357e-04,
364 -7.828e-06,
365 2.547e-06,
366 0.000e+00,
367 5.779e-03,
368 3.133e-03,
369 -5.312e-04,
370 -2.028e-05,
371 2.323e-07,
372 -9.100e-08,
373 -1.650e-08,
374 0.000e+00,
375 3.688e-02,
376 -8.638e-04,
377 -8.514e-05,
378 -2.828e-05,
379 5.403e-07,
380 4.390e-07,
381 1.350e-08,
382 1.800e-09,
383 0.000e+00,
384 -2.736e-02,
385 -2.977e-04,
386 8.113e-05,
387 2.329e-07,
388 8.451e-07,
389 4.490e-08,
390 -8.100e-09,
391 -1.500e-09,
392 2.000e-10
393 };
394
395
396 private static final double[] AH_AMPL = {
397 -2.738e-01,
398 -2.837e+00,
399 1.298e-02,
400 -3.588e-01,
401 2.413e-02,
402 3.427e-02,
403 -7.624e-01,
404 7.272e-02,
405 2.160e-02,
406 -3.385e-03,
407 4.424e-01,
408 3.722e-02,
409 2.195e-02,
410 -1.503e-03,
411 2.426e-04,
412 3.013e-01,
413 5.762e-02,
414 1.019e-02,
415 -4.476e-04,
416 6.790e-05,
417 3.227e-05,
418 3.123e-01,
419 -3.535e-02,
420 4.840e-03,
421 3.025e-06,
422 -4.363e-05,
423 2.854e-07,
424 -1.286e-06,
425 -6.725e-01,
426 -3.730e-02,
427 8.964e-04,
428 1.399e-04,
429 -3.990e-06,
430 7.431e-06,
431 -2.796e-07,
432 -1.601e-07,
433 4.068e-02,
434 -1.352e-02,
435 7.282e-04,
436 9.594e-05,
437 2.070e-06,
438 -9.620e-08,
439 -2.742e-07,
440 -6.370e-08,
441 -6.300e-09,
442 8.625e-02,
443 -5.971e-03,
444 4.705e-04,
445 2.335e-05,
446 4.226e-06,
447 2.475e-07,
448 -8.850e-08,
449 -3.600e-08,
450 -2.900e-09,
451 0.000e+00
452 };
453
454
455 private static final double[] BH_AMPL = {
456 0.000e+00,
457 0.000e+00,
458 -1.136e-01,
459 0.000e+00,
460 -1.868e-01,
461 -1.399e-02,
462 0.000e+00,
463 -1.043e-01,
464 1.175e-02,
465 -2.240e-03,
466 0.000e+00,
467 -3.222e-02,
468 1.333e-02,
469 -2.647e-03,
470 -2.316e-05,
471 0.000e+00,
472 5.339e-02,
473 1.107e-02,
474 -3.116e-03,
475 -1.079e-04,
476 -1.299e-05,
477 0.000e+00,
478 4.861e-03,
479 8.891e-03,
480 -6.448e-04,
481 -1.279e-05,
482 6.358e-06,
483 -1.417e-07,
484 0.000e+00,
485 3.041e-02,
486 1.150e-03,
487 -8.743e-04,
488 -2.781e-05,
489 6.367e-07,
490 -1.140e-08,
491 -4.200e-08,
492 0.000e+00,
493 -2.982e-02,
494 -3.000e-03,
495 1.394e-05,
496 -3.290e-05,
497 -1.705e-07,
498 7.440e-08,
499 2.720e-08,
500 -6.600e-09,
501 0.000e+00,
502 1.236e-02,
503 -9.981e-04,
504 -3.792e-05,
505 -1.355e-05,
506 1.162e-06,
507 -1.789e-07,
508 1.470e-08,
509 -2.400e-09,
510 -4.000e-10
511 };
512
513
514 private static final double[] AW_MEAN = {
515 5.640e+01,
516 1.555e+00,
517 -1.011e+00,
518 -3.975e+00,
519 3.171e-02,
520 1.065e-01,
521 6.175e-01,
522 1.376e-01,
523 4.229e-02,
524 3.028e-03,
525 1.688e+00,
526 -1.692e-01,
527 5.478e-02,
528 2.473e-02,
529 6.059e-04,
530 2.278e+00,
531 6.614e-03,
532 -3.505e-04,
533 -6.697e-03,
534 8.402e-04,
535 7.033e-04,
536 -3.236e+00,
537 2.184e-01,
538 -4.611e-02,
539 -1.613e-02,
540 -1.604e-03,
541 5.420e-05,
542 7.922e-05,
543 -2.711e-01,
544 -4.406e-01,
545 -3.376e-02,
546 -2.801e-03,
547 -4.090e-04,
548 -2.056e-05,
549 6.894e-06,
550 2.317e-06,
551 1.941e+00,
552 -2.562e-01,
553 1.598e-02,
554 5.449e-03,
555 3.544e-04,
556 1.148e-05,
557 7.503e-06,
558 -5.667e-07,
559 -3.660e-08,
560 8.683e-01,
561 -5.931e-02,
562 -1.864e-03,
563 -1.277e-04,
564 2.029e-04,
565 1.269e-05,
566 1.629e-06,
567 9.660e-08,
568 -1.015e-07,
569 -5.000e-10
570 };
571
572
573 private static final double[] BW_MEAN = {
574 0.000e+00,
575 0.000e+00,
576 2.592e-01,
577 0.000e+00,
578 2.974e-02,
579 -5.471e-01,
580 0.000e+00,
581 -5.926e-01,
582 -1.030e-01,
583 -1.567e-02,
584 0.000e+00,
585 1.710e-01,
586 9.025e-02,
587 2.689e-02,
588 2.243e-03,
589 0.000e+00,
590 3.439e-01,
591 2.402e-02,
592 5.410e-03,
593 1.601e-03,
594 9.669e-05,
595 0.000e+00,
596 9.502e-02,
597 -3.063e-02,
598 -1.055e-03,
599 -1.067e-04,
600 -1.130e-04,
601 2.124e-05,
602 0.000e+00,
603 -3.129e-01,
604 8.463e-03,
605 2.253e-04,
606 7.413e-05,
607 -9.376e-05,
608 -1.606e-06,
609 2.060e-06,
610 0.000e+00,
611 2.739e-01,
612 1.167e-03,
613 -2.246e-05,
614 -1.287e-04,
615 -2.438e-05,
616 -7.561e-07,
617 1.158e-06,
618 4.950e-08,
619 0.000e+00,
620 -1.344e-01,
621 5.342e-03,
622 3.775e-04,
623 -6.756e-05,
624 -1.686e-06,
625 -1.184e-06,
626 2.768e-07,
627 2.730e-08,
628 5.700e-09
629 };
630
631
632 private static final double[] AW_AMPL = {
633 1.023e-01,
634 -2.695e+00,
635 3.417e-01,
636 -1.405e-01,
637 3.175e-01,
638 2.116e-01,
639 3.536e+00,
640 -1.505e-01,
641 -1.660e-02,
642 2.967e-02,
643 3.819e-01,
644 -1.695e-01,
645 -7.444e-02,
646 7.409e-03,
647 -6.262e-03,
648 -1.836e+00,
649 -1.759e-02,
650 -6.256e-02,
651 -2.371e-03,
652 7.947e-04,
653 1.501e-04,
654 -8.603e-01,
655 -1.360e-01,
656 -3.629e-02,
657 -3.706e-03,
658 -2.976e-04,
659 1.857e-05,
660 3.021e-05,
661 2.248e+00,
662 -1.178e-01,
663 1.255e-02,
664 1.134e-03,
665 -2.161e-04,
666 -5.817e-06,
667 8.836e-07,
668 -1.769e-07,
669 7.313e-01,
670 -1.188e-01,
671 1.145e-02,
672 1.011e-03,
673 1.083e-04,
674 2.570e-06,
675 -2.140e-06,
676 -5.710e-08,
677 2.000e-08,
678 -1.632e+00,
679 -6.948e-03,
680 -3.893e-03,
681 8.592e-04,
682 7.577e-05,
683 4.539e-06,
684 -3.852e-07,
685 -2.213e-07,
686 -1.370e-08,
687 5.800e-09
688 };
689
690
691 private static final double[] BW_AMPL = {
692 0.000e+00,
693 0.000e+00,
694 -8.865e-02,
695 0.000e+00,
696 -4.309e-01,
697 6.340e-02,
698 0.000e+00,
699 1.162e-01,
700 6.176e-02,
701 -4.234e-03,
702 0.000e+00,
703 2.530e-01,
704 4.017e-02,
705 -6.204e-03,
706 4.977e-03,
707 0.000e+00,
708 -1.737e-01,
709 -5.638e-03,
710 1.488e-04,
711 4.857e-04,
712 -1.809e-04,
713 0.000e+00,
714 -1.514e-01,
715 -1.685e-02,
716 5.333e-03,
717 -7.611e-05,
718 2.394e-05,
719 8.195e-06,
720 0.000e+00,
721 9.326e-02,
722 -1.275e-02,
723 -3.071e-04,
724 5.374e-05,
725 -3.391e-05,
726 -7.436e-06,
727 6.747e-07,
728 0.000e+00,
729 -8.637e-02,
730 -3.807e-03,
731 -6.833e-04,
732 -3.861e-05,
733 -2.268e-05,
734 1.454e-06,
735 3.860e-07,
736 -1.068e-07,
737 0.000e+00,
738 -2.658e-02,
739 -1.947e-03,
740 7.131e-04,
741 -3.506e-05,
742 1.885e-07,
743 5.792e-07,
744 3.990e-08,
745 2.000e-08,
746 -5.700e-09
747 };
748
749
750 ABCoefficients() {
751
752 }
753
754
755
756
757
758 public double getAHMean(final int index) {
759 return AH_MEAN[index];
760 }
761
762
763
764
765
766 public double getBHMean(final int index) {
767 return BH_MEAN[index];
768 }
769
770
771
772
773
774 public double getAWMean(final int index) {
775 return AW_MEAN[index];
776 }
777
778
779
780
781
782 public double getBWMean(final int index) {
783 return BW_MEAN[index];
784 }
785
786
787
788
789
790 public double getAHAmplitude(final int index) {
791 return AH_AMPL[index];
792 }
793
794
795
796
797
798 public double getBHAmplitude(final int index) {
799 return BH_AMPL[index];
800 }
801
802
803
804
805
806 public double getAWAmplitude(final int index) {
807 return AW_AMPL[index];
808 }
809
810
811
812
813
814 public double getBWAmplitude(final int index) {
815 return BW_AMPL[index];
816 }
817 }
818 }