1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.utils;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.io.Serializable;
24 import java.util.List;
25
26 import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
27 import org.apache.commons.math3.analysis.interpolation.HermiteInterpolator;
28 import org.apache.commons.math3.util.FastMath;
29 import org.apache.commons.math3.util.MathUtils;
30 import org.orekit.data.BodiesElements;
31 import org.orekit.data.DelaunayArguments;
32 import org.orekit.data.FieldBodiesElements;
33 import org.orekit.data.FundamentalNutationArguments;
34 import org.orekit.data.PoissonSeries;
35 import org.orekit.data.PoissonSeriesParser;
36 import org.orekit.data.PolynomialNutation;
37 import org.orekit.data.PolynomialParser;
38 import org.orekit.data.PolynomialParser.Unit;
39 import org.orekit.data.SimpleTimeStampedTableParser;
40 import org.orekit.errors.OrekitException;
41 import org.orekit.errors.OrekitInternalError;
42 import org.orekit.errors.OrekitMessages;
43 import org.orekit.errors.TimeStampedCacheException;
44 import org.orekit.frames.EOPHistory;
45 import org.orekit.frames.PoleCorrection;
46 import org.orekit.time.AbsoluteDate;
47 import org.orekit.time.DateComponents;
48 import org.orekit.time.TimeComponents;
49 import org.orekit.time.TimeFunction;
50 import org.orekit.time.TimeScale;
51 import org.orekit.time.TimeScalesFactory;
52 import org.orekit.time.TimeStamped;
53
54
55
56
57
58
59 public enum IERSConventions {
60
61
62 IERS_1996 {
63
64
65 private static final String NUTATION_ARGUMENTS = IERS_BASE + "1996/nutation-arguments.txt";
66
67
68 private static final String X_Y_SERIES = IERS_BASE + "1996/tab5.4.txt";
69
70
71 private static final String PSI_EPSILON_SERIES = IERS_BASE + "1996/tab5.1.txt";
72
73
74 private static final String TIDAL_CORRECTION_XP_YP_SERIES = IERS_BASE + "1996/tab8.4.txt";
75
76
77 private static final String TIDAL_CORRECTION_UT1_SERIES = IERS_BASE + "1996/tab8.3.txt";
78
79
80 private static final String LOVE_NUMBERS = IERS_BASE + "1996/tab6.1.txt";
81
82
83 private static final String K20_FREQUENCY_DEPENDENCE = IERS_BASE + "1996/tab6.2b.txt";
84
85
86 private static final String K21_FREQUENCY_DEPENDENCE = IERS_BASE + "1996/tab6.2a.txt";
87
88
89 private static final String K22_FREQUENCY_DEPENDENCE = IERS_BASE + "1996/tab6.2c.txt";
90
91
92 @Override
93 public FundamentalNutationArguments getNutationArguments(final TimeScale timeScale)
94 throws OrekitException {
95 return new FundamentalNutationArguments(this, timeScale,
96 getStream(NUTATION_ARGUMENTS), NUTATION_ARGUMENTS);
97 }
98
99
100 @Override
101 public TimeFunction<Double> getMeanObliquityFunction() throws OrekitException {
102
103
104 final PolynomialNutation<DerivativeStructure> epsilonA =
105 new PolynomialNutation<DerivativeStructure>(84381.448 * Constants.ARC_SECONDS_TO_RADIANS,
106 -46.8150 * Constants.ARC_SECONDS_TO_RADIANS,
107 -0.00059 * Constants.ARC_SECONDS_TO_RADIANS,
108 0.001813 * Constants.ARC_SECONDS_TO_RADIANS);
109
110 return new TimeFunction<Double>() {
111
112
113 @Override
114 public Double value(final AbsoluteDate date) {
115 return epsilonA.value(evaluateTC(date));
116 }
117
118 };
119
120 }
121
122
123 @Override
124 public TimeFunction<double[]> getXYSpXY2Function()
125 throws OrekitException {
126
127
128 final FundamentalNutationArguments arguments = getNutationArguments(null);
129
130
131
132
133 final PolynomialNutation<DerivativeStructure> xPolynomial =
134 new PolynomialNutation<DerivativeStructure>(0,
135 2004.3109 * Constants.ARC_SECONDS_TO_RADIANS,
136 -0.42665 * Constants.ARC_SECONDS_TO_RADIANS,
137 -0.198656 * Constants.ARC_SECONDS_TO_RADIANS,
138 0.0000140 * Constants.ARC_SECONDS_TO_RADIANS);
139
140 final double fXCosOm = 0.00006 * Constants.ARC_SECONDS_TO_RADIANS;
141 final double fXSinOm = 0.00204 * Constants.ARC_SECONDS_TO_RADIANS;
142 final double fXSin2FDOm = 0.00016 * Constants.ARC_SECONDS_TO_RADIANS;
143 final double sinEps0 = FastMath.sin(getMeanObliquityFunction().value(getNutationReferenceEpoch()));
144
145 final double deciMilliAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-4;
146 final PoissonSeriesParser<DerivativeStructure> baseParser =
147 new PoissonSeriesParser<DerivativeStructure>(12).withFirstDelaunay(1);
148
149 final PoissonSeriesParser<DerivativeStructure> xParser =
150 baseParser.
151 withSinCos(0, 7, deciMilliAS, -1, deciMilliAS).
152 withSinCos(1, 8, deciMilliAS, 9, deciMilliAS);
153 final PoissonSeries<DerivativeStructure> xSum = xParser.parse(getStream(X_Y_SERIES), X_Y_SERIES);
154
155
156
157
158 final PolynomialNutation<DerivativeStructure> yPolynomial =
159 new PolynomialNutation<DerivativeStructure>(-0.00013 * Constants.ARC_SECONDS_TO_RADIANS,
160 0.0,
161 -22.40992 * Constants.ARC_SECONDS_TO_RADIANS,
162 0.001836 * Constants.ARC_SECONDS_TO_RADIANS,
163 0.0011130 * Constants.ARC_SECONDS_TO_RADIANS);
164
165 final double fYCosOm = -0.00231 * Constants.ARC_SECONDS_TO_RADIANS;
166 final double fYCos2FDOm = -0.00014 * Constants.ARC_SECONDS_TO_RADIANS;
167
168 final PoissonSeriesParser<DerivativeStructure> yParser =
169 baseParser.
170 withSinCos(0, -1, deciMilliAS, 10, deciMilliAS).
171 withSinCos(1, 12, deciMilliAS, 11, deciMilliAS);
172 final PoissonSeries<DerivativeStructure> ySum = yParser.parse(getStream(X_Y_SERIES), X_Y_SERIES);
173
174 @SuppressWarnings("unchecked")
175 final PoissonSeries.CompiledSeries<DerivativeStructure> xySum =
176 PoissonSeries.compile(xSum, ySum);
177
178
179
180 final double fST = 0.00385 * Constants.ARC_SECONDS_TO_RADIANS;
181 final double fST3 = -0.07259 * Constants.ARC_SECONDS_TO_RADIANS;
182 final double fSSinOm = -0.00264 * Constants.ARC_SECONDS_TO_RADIANS;
183 final double fSSin2Om = -0.00006 * Constants.ARC_SECONDS_TO_RADIANS;
184 final double fST2SinOm = 0.00074 * Constants.ARC_SECONDS_TO_RADIANS;
185 final double fST2Sin2FDOm = 0.00006 * Constants.ARC_SECONDS_TO_RADIANS;
186
187 return new TimeFunction<double[]>() {
188
189
190 @Override
191 public double[] value(final AbsoluteDate date) {
192
193 final BodiesElements elements = arguments.evaluateAll(date);
194 final double[] xy = xySum.value(elements);
195
196 final double omega = elements.getOmega();
197 final double f = elements.getF();
198 final double d = elements.getD();
199 final double t = elements.getTC();
200
201 final double cosOmega = FastMath.cos(omega);
202 final double sinOmega = FastMath.sin(omega);
203 final double sin2Omega = FastMath.sin(2 * omega);
204 final double cos2FDOm = FastMath.cos(2 * (f - d + omega));
205 final double sin2FDOm = FastMath.sin(2 * (f - d + omega));
206
207 final double x = xPolynomial.value(t) + sinEps0 * xy[0] +
208 t * t * (fXCosOm * cosOmega + fXSinOm * sinOmega + fXSin2FDOm * cos2FDOm);
209 final double y = yPolynomial.value(t) + xy[1] +
210 t * t * (fYCosOm * cosOmega + fYCos2FDOm * cos2FDOm);
211 final double sPxy2 = fSSinOm * sinOmega + fSSin2Om * sin2Omega +
212 t * (fST + t * (fST2SinOm * sinOmega + fST2Sin2FDOm * sin2FDOm + t * fST3));
213
214 return new double[] {
215 x, y, sPxy2
216 };
217
218 }
219
220 };
221
222 }
223
224
225 @Override
226 public TimeFunction<double[]> getPrecessionFunction() throws OrekitException {
227
228
229
230
231
232
233 final PolynomialNutation<DerivativeStructure> psiA =
234 new PolynomialNutation<DerivativeStructure>( 0.0,
235 5038.7784 * Constants.ARC_SECONDS_TO_RADIANS,
236 -1.07259 * Constants.ARC_SECONDS_TO_RADIANS,
237 -0.001147 * Constants.ARC_SECONDS_TO_RADIANS);
238 final PolynomialNutation<DerivativeStructure> omegaA =
239 new PolynomialNutation<DerivativeStructure>(getMeanObliquityFunction().value(getNutationReferenceEpoch()),
240 0.0,
241 0.05127 * Constants.ARC_SECONDS_TO_RADIANS,
242 -0.007726 * Constants.ARC_SECONDS_TO_RADIANS);
243 final PolynomialNutation<DerivativeStructure> chiA =
244 new PolynomialNutation<DerivativeStructure>( 0.0,
245 10.5526 * Constants.ARC_SECONDS_TO_RADIANS,
246 -2.38064 * Constants.ARC_SECONDS_TO_RADIANS,
247 -0.001125 * Constants.ARC_SECONDS_TO_RADIANS);
248
249 return new TimeFunction<double[]>() {
250
251 @Override
252 public double[] value(final AbsoluteDate date) {
253 final double tc = evaluateTC(date);
254 return new double[] {
255 psiA.value(tc), omegaA.value(tc), chiA.value(tc)
256 };
257 }
258 };
259
260 }
261
262
263 @Override
264 public TimeFunction<double[]> getNutationFunction()
265 throws OrekitException {
266
267
268 final FundamentalNutationArguments arguments = getNutationArguments(null);
269
270
271 final double deciMilliAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-4;
272 final PoissonSeriesParser<DerivativeStructure> baseParser =
273 new PoissonSeriesParser<DerivativeStructure>(10).withFirstDelaunay(1);
274
275 final PoissonSeriesParser<DerivativeStructure> psiParser =
276 baseParser.
277 withSinCos(0, 7, deciMilliAS, -1, deciMilliAS).
278 withSinCos(1, 8, deciMilliAS, -1, deciMilliAS);
279 final PoissonSeries<DerivativeStructure> psiSeries = psiParser.parse(getStream(PSI_EPSILON_SERIES), PSI_EPSILON_SERIES);
280
281 final PoissonSeriesParser<DerivativeStructure> epsilonParser =
282 baseParser.
283 withSinCos(0, -1, deciMilliAS, 9, deciMilliAS).
284 withSinCos(1, -1, deciMilliAS, 10, deciMilliAS);
285 final PoissonSeries<DerivativeStructure> epsilonSeries = epsilonParser.parse(getStream(PSI_EPSILON_SERIES), PSI_EPSILON_SERIES);
286
287 @SuppressWarnings("unchecked")
288 final PoissonSeries.CompiledSeries<DerivativeStructure> psiEpsilonSeries =
289 PoissonSeries.compile(psiSeries, epsilonSeries);
290
291 return new TimeFunction<double[]>() {
292
293 @Override
294 public double[] value(final AbsoluteDate date) {
295 final BodiesElements elements = arguments.evaluateAll(date);
296 final double[] psiEpsilon = psiEpsilonSeries.value(elements);
297 return new double[] {
298 psiEpsilon[0], psiEpsilon[1], IAU1994ResolutionC7.value(elements)
299 };
300 }
301 };
302
303 }
304
305
306 @Override
307 public TimeFunction<DerivativeStructure> getGMSTFunction(final TimeScale ut1)
308 throws OrekitException {
309
310
311 final double radiansPerSecond = MathUtils.TWO_PI / Constants.JULIAN_DAY;
312
313
314
315 final AbsoluteDate gmstReference =
316 new AbsoluteDate(DateComponents.J2000_EPOCH, TimeComponents.H12, TimeScalesFactory.getTAI());
317 final double gmst0 = 24110.54841;
318 final double gmst1 = 8640184.812866;
319 final double gmst2 = 0.093104;
320 final double gmst3 = -6.2e-6;
321
322 return new TimeFunction<DerivativeStructure>() {
323
324
325 @Override
326 public DerivativeStructure value(final AbsoluteDate date) {
327
328
329 final double dtai = date.durationFrom(gmstReference);
330 final DerivativeStructure tut1 =
331 new DerivativeStructure(1, 1, dtai + ut1.offsetFromTAI(date), 1.0);
332 final DerivativeStructure tt = tut1.divide(Constants.JULIAN_CENTURY);
333
334
335
336 final DerivativeStructure sd = tut1.add(Constants.JULIAN_DAY / 2).remainder(Constants.JULIAN_DAY);
337
338
339 return tt.multiply(gmst3).add(gmst2).multiply(tt).add(gmst1).multiply(tt).add(gmst0).add(sd).multiply(radiansPerSecond);
340
341 }
342
343 };
344
345 }
346
347
348 @Override
349 public TimeFunction<DerivativeStructure> getGASTFunction(final TimeScale ut1,
350 final EOPHistory eopHistory)
351 throws OrekitException {
352
353
354 final TimeFunction<Double> epsilonA = getMeanObliquityFunction();
355
356
357 final TimeFunction<DerivativeStructure> gmst = getGMSTFunction(ut1);
358
359
360 final TimeFunction<double[]> nutation = getNutationFunction();
361
362 return new TimeFunction<DerivativeStructure>() {
363
364
365 @Override
366 public DerivativeStructure value(final AbsoluteDate date) {
367
368
369 final double[] angles = nutation.value(date);
370 double deltaPsi = angles[0];
371 if (eopHistory != null) {
372 deltaPsi += eopHistory.getEquinoxNutationCorrection(date)[0];
373 }
374 final double eqe = deltaPsi * FastMath.cos(epsilonA.value(date)) + angles[2];
375
376
377 return gmst.value(date).add(eqe);
378
379 }
380
381 };
382
383 }
384
385
386 @Override
387 public TimeFunction<double[]> getEOPTidalCorrection()
388 throws OrekitException {
389
390
391
392
393
394
395 final FundamentalNutationArguments arguments = getNutationArguments(TimeScalesFactory.getTT());
396
397
398 final double milliAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-3;
399 final PoissonSeriesParser<DerivativeStructure> xyParser = new PoissonSeriesParser<DerivativeStructure>(17).
400 withOptionalColumn(1).
401 withGamma(7).
402 withFirstDelaunay(2);
403 final PoissonSeries<DerivativeStructure> xSeries =
404 xyParser.
405 withSinCos(0, 14, milliAS, 15, milliAS).
406 parse(getStream(TIDAL_CORRECTION_XP_YP_SERIES), TIDAL_CORRECTION_XP_YP_SERIES);
407 final PoissonSeries<DerivativeStructure> ySeries =
408 xyParser.
409 withSinCos(0, 16, milliAS, 17, milliAS).
410 parse(getStream(TIDAL_CORRECTION_XP_YP_SERIES),
411 TIDAL_CORRECTION_XP_YP_SERIES);
412
413 final double deciMilliS = 1.0e-4;
414 final PoissonSeriesParser<DerivativeStructure> ut1Parser = new PoissonSeriesParser<DerivativeStructure>(17).
415 withOptionalColumn(1).
416 withGamma(7).
417 withFirstDelaunay(2).
418 withSinCos(0, 16, deciMilliS, 17, deciMilliS);
419 final PoissonSeries<DerivativeStructure> ut1Series =
420 ut1Parser.parse(getStream(TIDAL_CORRECTION_UT1_SERIES), TIDAL_CORRECTION_UT1_SERIES);
421
422 @SuppressWarnings("unchecked")
423 final PoissonSeries.CompiledSeries<DerivativeStructure> correctionSeries =
424 PoissonSeries.compile(xSeries, ySeries, ut1Series);
425
426 return new TimeFunction<double[]>() {
427
428 @Override
429 public double[] value(final AbsoluteDate date) {
430 final FieldBodiesElements<DerivativeStructure> elements =
431 arguments.evaluateDerivative(date);
432 final DerivativeStructure[] correction = correctionSeries.value(elements);
433 return new double[] {
434 correction[0].getValue(),
435 correction[1].getValue(),
436 correction[2].getValue(),
437 -correction[2].getPartialDerivative(1) * Constants.JULIAN_DAY
438 };
439 }
440 };
441
442 }
443
444
445 public LoveNumbers getLoveNumbers() throws OrekitException {
446 return loadLoveNumbers(LOVE_NUMBERS);
447 }
448
449
450 public TimeFunction<double[]> getTideFrequencyDependenceFunction(final TimeScale ut1)
451 throws OrekitException {
452
453
454 final FundamentalNutationArguments arguments = getNutationArguments(ut1);
455
456
457 final PoissonSeriesParser<DerivativeStructure> k20Parser =
458 new PoissonSeriesParser<DerivativeStructure>(18).
459 withOptionalColumn(1).
460 withDoodson(4, 2).
461 withFirstDelaunay(10);
462 final PoissonSeriesParser<DerivativeStructure> k21Parser =
463 new PoissonSeriesParser<DerivativeStructure>(18).
464 withOptionalColumn(1).
465 withDoodson(4, 3).
466 withFirstDelaunay(10);
467 final PoissonSeriesParser<DerivativeStructure> k22Parser =
468 new PoissonSeriesParser<DerivativeStructure>(16).
469 withOptionalColumn(1).
470 withDoodson(4, 2).
471 withFirstDelaunay(10);
472
473 final double pico = 1.0e-12;
474 final PoissonSeries<DerivativeStructure> c20Series =
475 k20Parser.
476 withSinCos(0, 18, -pico, 16, pico).
477 parse(getStream(K20_FREQUENCY_DEPENDENCE), K20_FREQUENCY_DEPENDENCE);
478 final PoissonSeries<DerivativeStructure> c21Series =
479 k21Parser.
480 withSinCos(0, 17, pico, 18, pico).
481 parse(getStream(K21_FREQUENCY_DEPENDENCE), K21_FREQUENCY_DEPENDENCE);
482 final PoissonSeries<DerivativeStructure> s21Series =
483 k21Parser.
484 withSinCos(0, 18, -pico, 17, pico).
485 parse(getStream(K21_FREQUENCY_DEPENDENCE), K21_FREQUENCY_DEPENDENCE);
486 final PoissonSeries<DerivativeStructure> c22Series =
487 k22Parser.
488 withSinCos(0, -1, pico, 16, pico).
489 parse(getStream(K22_FREQUENCY_DEPENDENCE), K22_FREQUENCY_DEPENDENCE);
490 final PoissonSeries<DerivativeStructure> s22Series =
491 k22Parser.
492 withSinCos(0, 16, -pico, -1, pico).
493 parse(getStream(K22_FREQUENCY_DEPENDENCE), K22_FREQUENCY_DEPENDENCE);
494
495 @SuppressWarnings("unchecked")
496 final PoissonSeries.CompiledSeries<DerivativeStructure> kSeries =
497 PoissonSeries.compile(c20Series, c21Series, s21Series, c22Series, s22Series);
498
499 return new TimeFunction<double[]>() {
500
501 @Override
502 public double[] value(final AbsoluteDate date) {
503 return kSeries.value(arguments.evaluateAll(date));
504 }
505 };
506
507 }
508
509
510 @Override
511 public double getPermanentTide() throws OrekitException {
512 return 4.4228e-8 * -0.31460 * getLoveNumbers().getReal(2, 0);
513 }
514
515
516 @Override
517 public TimeFunction<double[]> getSolidPoleTide(final EOPHistory eopHistory) {
518
519
520 final double globalFactor = -1.348e-9 / Constants.ARC_SECONDS_TO_RADIANS;
521 final double coupling = 0.00112;
522
523 return new TimeFunction<double[]>() {
524
525 @Override
526 public double[] value(final AbsoluteDate date) {
527 final PoleCorrection pole = eopHistory.getPoleCorrection(date);
528 return new double[] {
529 globalFactor * (pole.getXp() + coupling * pole.getYp()),
530 globalFactor * (coupling * pole.getXp() - pole.getYp()),
531 };
532 }
533 };
534 }
535
536
537 @Override
538 public TimeFunction<double[]> getOceanPoleTide(final EOPHistory eopHistory)
539 throws OrekitException {
540
541 return new TimeFunction<double[]>() {
542
543 @Override
544 public double[] value(final AbsoluteDate date) {
545
546 return new double[] {
547 0.0, 0.0
548 };
549 }
550 };
551 }
552
553 },
554
555
556 IERS_2003 {
557
558
559 private static final String NUTATION_ARGUMENTS = IERS_BASE + "2003/nutation-arguments.txt";
560
561
562 private static final String X_SERIES = IERS_BASE + "2003/tab5.2a.txt";
563
564
565 private static final String Y_SERIES = IERS_BASE + "2003/tab5.2b.txt";
566
567
568 private static final String S_SERIES = IERS_BASE + "2003/tab5.2c.txt";
569
570
571 private static final String LUNI_SOLAR_SERIES = IERS_BASE + "2003/tab5.3a-first-table.txt";
572
573
574 private static final String PLANETARY_SERIES = IERS_BASE + "2003/tab5.3b.txt";
575
576
577 private static final String GST_SERIES = IERS_BASE + "2003/tab5.4.txt";
578
579
580 private static final String TIDAL_CORRECTION_XP_YP_SERIES = IERS_BASE + "2003/tab8.2ab.txt";
581
582
583 private static final String TIDAL_CORRECTION_UT1_SERIES = IERS_BASE + "2003/tab8.3ab.txt";
584
585
586 private static final String LOVE_NUMBERS = IERS_BASE + "2003/tab6.1.txt";
587
588
589 private static final String K20_FREQUENCY_DEPENDENCE = IERS_BASE + "2003/tab6.3b.txt";
590
591
592 private static final String K21_FREQUENCY_DEPENDENCE = IERS_BASE + "2003/tab6.3a.txt";
593
594
595 private static final String K22_FREQUENCY_DEPENDENCE = IERS_BASE + "2003/tab6.3c.txt";
596
597
598 private static final String ANNUAL_POLE = IERS_BASE + "2003/annual.pole";
599
600
601 public FundamentalNutationArguments getNutationArguments(final TimeScale timeScale)
602 throws OrekitException {
603 return new FundamentalNutationArguments(this, timeScale,
604 getStream(NUTATION_ARGUMENTS), NUTATION_ARGUMENTS);
605 }
606
607
608 @Override
609 public TimeFunction<Double> getMeanObliquityFunction() throws OrekitException {
610
611
612 final PolynomialNutation<DerivativeStructure> epsilonA =
613 new PolynomialNutation<DerivativeStructure>(84381.448 * Constants.ARC_SECONDS_TO_RADIANS,
614 -46.84024 * Constants.ARC_SECONDS_TO_RADIANS,
615 -0.00059 * Constants.ARC_SECONDS_TO_RADIANS,
616 0.001813 * Constants.ARC_SECONDS_TO_RADIANS);
617
618 return new TimeFunction<Double>() {
619
620
621 @Override
622 public Double value(final AbsoluteDate date) {
623 return epsilonA.value(evaluateTC(date));
624 }
625
626 };
627
628 }
629
630
631 @Override
632 public TimeFunction<double[]> getXYSpXY2Function()
633 throws OrekitException {
634
635
636 final FundamentalNutationArguments arguments = getNutationArguments(null);
637
638
639 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
640 final PoissonSeriesParser<DerivativeStructure> parser =
641 new PoissonSeriesParser<DerivativeStructure>(17).
642 withPolynomialPart('t', PolynomialParser.Unit.MICRO_ARC_SECONDS).
643 withFirstDelaunay(4).
644 withFirstPlanetary(9).
645 withSinCos(0, 2, microAS, 3, microAS);
646
647 final PoissonSeries<DerivativeStructure> xSeries = parser.parse(getStream(X_SERIES), X_SERIES);
648 final PoissonSeries<DerivativeStructure> ySeries = parser.parse(getStream(Y_SERIES), Y_SERIES);
649 final PoissonSeries<DerivativeStructure> sSeries = parser.parse(getStream(S_SERIES), S_SERIES);
650 @SuppressWarnings("unchecked")
651 final PoissonSeries.CompiledSeries<DerivativeStructure> xys = PoissonSeries.compile(xSeries, ySeries, sSeries);
652
653
654 return new TimeFunction<double[]>() {
655
656
657 @Override
658 public double[] value(final AbsoluteDate date) {
659 return xys.value(arguments.evaluateAll(date));
660 }
661
662 };
663
664 }
665
666
667
668 @Override
669 public TimeFunction<double[]> getPrecessionFunction() throws OrekitException {
670
671
672
673 final PolynomialNutation<DerivativeStructure> psiA =
674 new PolynomialNutation<DerivativeStructure>( 0.0,
675 5038.47875 * Constants.ARC_SECONDS_TO_RADIANS,
676 -1.07259 * Constants.ARC_SECONDS_TO_RADIANS,
677 -0.001147 * Constants.ARC_SECONDS_TO_RADIANS);
678 final PolynomialNutation<DerivativeStructure> omegaA =
679 new PolynomialNutation<DerivativeStructure>(getMeanObliquityFunction().value(getNutationReferenceEpoch()),
680 -0.02524 * Constants.ARC_SECONDS_TO_RADIANS,
681 0.05127 * Constants.ARC_SECONDS_TO_RADIANS,
682 -0.007726 * Constants.ARC_SECONDS_TO_RADIANS);
683 final PolynomialNutation<DerivativeStructure> chiA =
684 new PolynomialNutation<DerivativeStructure>( 0.0,
685 10.5526 * Constants.ARC_SECONDS_TO_RADIANS,
686 -2.38064 * Constants.ARC_SECONDS_TO_RADIANS,
687 -0.001125 * Constants.ARC_SECONDS_TO_RADIANS);
688
689 return new TimeFunction<double[]>() {
690
691 @Override
692 public double[] value(final AbsoluteDate date) {
693 final double tc = evaluateTC(date);
694 return new double[] {
695 psiA.value(tc), omegaA.value(tc), chiA.value(tc)
696 };
697 }
698 };
699
700 }
701
702
703 @Override
704 public TimeFunction<double[]> getNutationFunction()
705 throws OrekitException {
706
707
708 final FundamentalNutationArguments arguments = getNutationArguments(null);
709
710
711 final double milliAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-3;
712 final PoissonSeriesParser<DerivativeStructure> luniSolarParser =
713 new PoissonSeriesParser<DerivativeStructure>(14).withFirstDelaunay(1);
714 final PoissonSeriesParser<DerivativeStructure> luniSolarPsiParser =
715 luniSolarParser.
716 withSinCos(0, 7, milliAS, 11, milliAS).
717 withSinCos(1, 8, milliAS, 12, milliAS);
718 final PoissonSeries<DerivativeStructure> psiLuniSolarSeries =
719 luniSolarPsiParser.parse(getStream(LUNI_SOLAR_SERIES), LUNI_SOLAR_SERIES);
720 final PoissonSeriesParser<DerivativeStructure> luniSolarEpsilonParser =
721 luniSolarParser.
722 withSinCos(0, 13, milliAS, 9, milliAS).
723 withSinCos(1, 14, milliAS, 10, milliAS);
724 final PoissonSeries<DerivativeStructure> epsilonLuniSolarSeries =
725 luniSolarEpsilonParser.parse(getStream(LUNI_SOLAR_SERIES), LUNI_SOLAR_SERIES);
726
727 final PoissonSeriesParser<DerivativeStructure> planetaryParser =
728 new PoissonSeriesParser<DerivativeStructure>(21).
729 withFirstDelaunay(2).
730 withFirstPlanetary(7);
731 final PoissonSeriesParser<DerivativeStructure> planetaryPsiParser =
732 planetaryParser.withSinCos(0, 17, milliAS, 18, milliAS);
733 final PoissonSeries<DerivativeStructure> psiPlanetarySeries =
734 planetaryPsiParser.parse(getStream(PLANETARY_SERIES), PLANETARY_SERIES);
735 final PoissonSeriesParser<DerivativeStructure> planetaryEpsilonParser =
736 planetaryParser.withSinCos(0, 19, milliAS, 20, milliAS);
737 final PoissonSeries<DerivativeStructure> epsilonPlanetarySeries =
738 planetaryEpsilonParser.parse(getStream(PLANETARY_SERIES), PLANETARY_SERIES);
739
740 @SuppressWarnings("unchecked")
741 final PoissonSeries.CompiledSeries<DerivativeStructure> luniSolarSeries =
742 PoissonSeries.compile(psiLuniSolarSeries, epsilonLuniSolarSeries);
743 @SuppressWarnings("unchecked")
744 final PoissonSeries.CompiledSeries<DerivativeStructure> planetarySeries =
745 PoissonSeries.compile(psiPlanetarySeries, epsilonPlanetarySeries);
746
747 return new TimeFunction<double[]>() {
748
749 @Override
750 public double[] value(final AbsoluteDate date) {
751 final BodiesElements elements = arguments.evaluateAll(date);
752 final double[] luniSolar = luniSolarSeries.value(elements);
753 final double[] planetary = planetarySeries.value(elements);
754 return new double[] {
755 luniSolar[0] + planetary[0], luniSolar[1] + planetary[1],
756 IAU1994ResolutionC7.value(elements)
757 };
758 }
759 };
760
761 }
762
763
764 @Override
765 public TimeFunction<DerivativeStructure> getGMSTFunction(final TimeScale ut1)
766 throws OrekitException {
767
768
769 final StellarAngleCapitaine era = new StellarAngleCapitaine(ut1);
770
771
772
773 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
774 final PoissonSeriesParser<DerivativeStructure> parser =
775 new PoissonSeriesParser<DerivativeStructure>(17).
776 withFirstDelaunay(4).
777 withFirstPlanetary(9).
778 withSinCos(0, 2, microAS, 3, microAS).
779 withPolynomialPart('t', Unit.ARC_SECONDS);
780 final PolynomialNutation<DerivativeStructure> minusEO =
781 parser.parse(getStream(GST_SERIES), GST_SERIES).getPolynomial();
782
783
784 return new TimeFunction<DerivativeStructure>() {
785
786
787 @Override
788 public DerivativeStructure value(final AbsoluteDate date) {
789 return era.value(date).add(minusEO.value(dsEvaluateTC(date)));
790 }
791
792 };
793
794 }
795
796
797 @Override
798 public TimeFunction<DerivativeStructure> getGASTFunction(final TimeScale ut1,
799 final EOPHistory eopHistory)
800 throws OrekitException {
801
802
803 final FundamentalNutationArguments arguments = getNutationArguments(null);
804
805
806 final TimeFunction<Double> epsilon = getMeanObliquityFunction();
807
808
809 final double milliAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-3;
810 final PoissonSeriesParser<DerivativeStructure> luniSolarPsiParser =
811 new PoissonSeriesParser<DerivativeStructure>(14).
812 withFirstDelaunay(1).
813 withSinCos(0, 7, milliAS, 11, milliAS).
814 withSinCos(1, 8, milliAS, 12, milliAS);
815 final PoissonSeries<DerivativeStructure> psiLuniSolarSeries =
816 luniSolarPsiParser.parse(getStream(LUNI_SOLAR_SERIES), LUNI_SOLAR_SERIES);
817
818 final PoissonSeriesParser<DerivativeStructure> planetaryPsiParser =
819 new PoissonSeriesParser<DerivativeStructure>(21).
820 withFirstDelaunay(2).
821 withFirstPlanetary(7).
822 withSinCos(0, 17, milliAS, 18, milliAS);
823 final PoissonSeries<DerivativeStructure> psiPlanetarySeries =
824 planetaryPsiParser.parse(getStream(PLANETARY_SERIES), PLANETARY_SERIES);
825
826 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
827 final PoissonSeriesParser<DerivativeStructure> gstParser =
828 new PoissonSeriesParser<DerivativeStructure>(17).
829 withFirstDelaunay(4).
830 withFirstPlanetary(9).
831 withSinCos(0, 2, microAS, 3, microAS).
832 withPolynomialPart('t', Unit.ARC_SECONDS);
833 final PoissonSeries<DerivativeStructure> gstSeries = gstParser.parse(getStream(GST_SERIES), GST_SERIES);
834 @SuppressWarnings("unchecked")
835 final PoissonSeries.CompiledSeries<DerivativeStructure> psiGstSeries =
836 PoissonSeries.compile(psiLuniSolarSeries, psiPlanetarySeries, gstSeries);
837
838
839 final TimeFunction<DerivativeStructure> era = getEarthOrientationAngleFunction(ut1);
840
841 return new TimeFunction<DerivativeStructure>() {
842
843
844 @Override
845 public DerivativeStructure value(final AbsoluteDate date) {
846
847
848 final BodiesElements elements = arguments.evaluateAll(date);
849 final double[] angles = psiGstSeries.value(elements);
850 final double ddPsi = (eopHistory == null) ? 0 : eopHistory.getEquinoxNutationCorrection(date)[0];
851 final double deltaPsi = angles[0] + angles[1] + ddPsi;
852 final double epsilonA = epsilon.value(date);
853
854
855
856 return era.value(date).add(deltaPsi * FastMath.cos(epsilonA) + angles[2]);
857
858 }
859
860 };
861
862 }
863
864
865 @Override
866 public TimeFunction<double[]> getEOPTidalCorrection()
867 throws OrekitException {
868
869
870
871
872
873
874 final FundamentalNutationArguments arguments = getNutationArguments(TimeScalesFactory.getTT());
875
876
877 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
878 final PoissonSeriesParser<DerivativeStructure> xyParser = new PoissonSeriesParser<DerivativeStructure>(13).
879 withOptionalColumn(1).
880 withGamma(2).
881 withFirstDelaunay(3);
882 final PoissonSeries<DerivativeStructure> xSeries =
883 xyParser.
884 withSinCos(0, 10, microAS, 11, microAS).
885 parse(getStream(TIDAL_CORRECTION_XP_YP_SERIES), TIDAL_CORRECTION_XP_YP_SERIES);
886 final PoissonSeries<DerivativeStructure> ySeries =
887 xyParser.
888 withSinCos(0, 12, microAS, 13, microAS).
889 parse(getStream(TIDAL_CORRECTION_XP_YP_SERIES), TIDAL_CORRECTION_XP_YP_SERIES);
890
891 final double microS = 1.0e-6;
892 final PoissonSeriesParser<DerivativeStructure> ut1Parser = new PoissonSeriesParser<DerivativeStructure>(11).
893 withOptionalColumn(1).
894 withGamma(2).
895 withFirstDelaunay(3).
896 withSinCos(0, 10, microS, 11, microS);
897 final PoissonSeries<DerivativeStructure> ut1Series =
898 ut1Parser.parse(getStream(TIDAL_CORRECTION_UT1_SERIES), TIDAL_CORRECTION_UT1_SERIES);
899
900 @SuppressWarnings("unchecked")
901 final PoissonSeries.CompiledSeries<DerivativeStructure> correctionSeries =
902 PoissonSeries.compile(xSeries, ySeries, ut1Series);
903
904 return new TimeFunction<double[]>() {
905
906 @Override
907 public double[] value(final AbsoluteDate date) {
908 final FieldBodiesElements<DerivativeStructure> elements =
909 arguments.evaluateDerivative(date);
910 final DerivativeStructure[] correction = correctionSeries.value(elements);
911 return new double[] {
912 correction[0].getValue(),
913 correction[1].getValue(),
914 correction[2].getValue(),
915 -correction[2].getPartialDerivative(1) * Constants.JULIAN_DAY
916 };
917 }
918 };
919
920 }
921
922
923 public LoveNumbers getLoveNumbers() throws OrekitException {
924 return loadLoveNumbers(LOVE_NUMBERS);
925 }
926
927
928 public TimeFunction<double[]> getTideFrequencyDependenceFunction(final TimeScale ut1)
929 throws OrekitException {
930
931
932 final FundamentalNutationArguments arguments = getNutationArguments(ut1);
933
934
935 final PoissonSeriesParser<DerivativeStructure> k20Parser =
936 new PoissonSeriesParser<DerivativeStructure>(18).
937 withOptionalColumn(1).
938 withDoodson(4, 2).
939 withFirstDelaunay(10);
940 final PoissonSeriesParser<DerivativeStructure> k21Parser =
941 new PoissonSeriesParser<DerivativeStructure>(18).
942 withOptionalColumn(1).
943 withDoodson(4, 3).
944 withFirstDelaunay(10);
945 final PoissonSeriesParser<DerivativeStructure> k22Parser =
946 new PoissonSeriesParser<DerivativeStructure>(16).
947 withOptionalColumn(1).
948 withDoodson(4, 2).
949 withFirstDelaunay(10);
950
951 final double pico = 1.0e-12;
952 final PoissonSeries<DerivativeStructure> c20Series =
953 k20Parser.
954 withSinCos(0, 18, -pico, 16, pico).
955 parse(getStream(K20_FREQUENCY_DEPENDENCE), K20_FREQUENCY_DEPENDENCE);
956 final PoissonSeries<DerivativeStructure> c21Series =
957 k21Parser.
958 withSinCos(0, 17, pico, 18, pico).
959 parse(getStream(K21_FREQUENCY_DEPENDENCE), K21_FREQUENCY_DEPENDENCE);
960 final PoissonSeries<DerivativeStructure> s21Series =
961 k21Parser.
962 withSinCos(0, 18, -pico, 17, pico).
963 parse(getStream(K21_FREQUENCY_DEPENDENCE), K21_FREQUENCY_DEPENDENCE);
964 final PoissonSeries<DerivativeStructure> c22Series =
965 k22Parser.
966 withSinCos(0, -1, pico, 16, pico).
967 parse(getStream(K22_FREQUENCY_DEPENDENCE), K22_FREQUENCY_DEPENDENCE);
968 final PoissonSeries<DerivativeStructure> s22Series =
969 k22Parser.
970 withSinCos(0, 16, -pico, -1, pico).
971 parse(getStream(K22_FREQUENCY_DEPENDENCE), K22_FREQUENCY_DEPENDENCE);
972
973 @SuppressWarnings("unchecked")
974 final PoissonSeries.CompiledSeries<DerivativeStructure> kSeries =
975 PoissonSeries.compile(c20Series, c21Series, s21Series, c22Series, s22Series);
976
977 return new TimeFunction<double[]>() {
978
979 @Override
980 public double[] value(final AbsoluteDate date) {
981 return kSeries.value(arguments.evaluateAll(date));
982 }
983 };
984
985 }
986
987
988 @Override
989 public double getPermanentTide() throws OrekitException {
990 return 4.4228e-8 * -0.31460 * getLoveNumbers().getReal(2, 0);
991 }
992
993
994 @Override
995 public TimeFunction<double[]> getSolidPoleTide(final EOPHistory eopHistory)
996 throws OrekitException {
997
998
999 final TimeScale utc = TimeScalesFactory.getUTC();
1000 final SimpleTimeStampedTableParser.RowConverter<MeanPole> converter =
1001 new SimpleTimeStampedTableParser.RowConverter<MeanPole>() {
1002
1003 @Override
1004 public MeanPole convert(final double[] rawFields) throws OrekitException {
1005 return new MeanPole(new AbsoluteDate((int) rawFields[0], 1, 1, utc),
1006 rawFields[1] * Constants.ARC_SECONDS_TO_RADIANS,
1007 rawFields[2] * Constants.ARC_SECONDS_TO_RADIANS);
1008 }
1009 };
1010 final SimpleTimeStampedTableParser<MeanPole> parser =
1011 new SimpleTimeStampedTableParser<MeanPole>(3, converter);
1012 final List<MeanPole> annualPoleList = parser.parse(getStream(ANNUAL_POLE), ANNUAL_POLE);
1013 final AbsoluteDate firstAnnualPoleDate = annualPoleList.get(0).getDate();
1014 final AbsoluteDate lastAnnualPoleDate = annualPoleList.get(annualPoleList.size() - 1).getDate();
1015 final ImmutableTimeStampedCache<MeanPole> annualCache =
1016 new ImmutableTimeStampedCache<MeanPole>(2, annualPoleList);
1017
1018
1019 final double xp0 = 0.054 * Constants.ARC_SECONDS_TO_RADIANS;
1020 final double xp0Dot = 0.00083 * Constants.ARC_SECONDS_TO_RADIANS / Constants.JULIAN_YEAR;
1021 final double yp0 = 0.357 * Constants.ARC_SECONDS_TO_RADIANS;
1022 final double yp0Dot = 0.00395 * Constants.ARC_SECONDS_TO_RADIANS / Constants.JULIAN_YEAR;
1023
1024
1025 final double globalFactor = -1.333e-9 / Constants.ARC_SECONDS_TO_RADIANS;
1026 final double ratio = 0.00115;
1027
1028 return new TimeFunction<double[]>() {
1029
1030 @Override
1031 public double[] value(final AbsoluteDate date) {
1032
1033
1034 if (date.compareTo(firstAnnualPoleDate) <= 0) {
1035 return new double[] {
1036 0.0, 0.0
1037 };
1038 }
1039
1040
1041 double meanPoleX = 0;
1042 double meanPoleY = 0;
1043 if (date.compareTo(lastAnnualPoleDate) <= 0) {
1044
1045
1046 try {
1047 final List<MeanPole> neighbors = annualCache.getNeighbors(date);
1048 final HermiteInterpolator interpolator = new HermiteInterpolator();
1049 for (final MeanPole neighbor : neighbors) {
1050 interpolator.addSamplePoint(neighbor.getDate().durationFrom(date),
1051 new double[] {
1052 neighbor.getX(), neighbor.getY()
1053 });
1054 }
1055 final double[] interpolated = interpolator.value(0);
1056 meanPoleX = interpolated[0];
1057 meanPoleY = interpolated[1];
1058 } catch (TimeStampedCacheException tsce) {
1059
1060 throw new OrekitInternalError(tsce);
1061 }
1062 } else {
1063
1064
1065
1066 final double t = date.durationFrom(AbsoluteDate.J2000_EPOCH);
1067 meanPoleX = xp0 + t * xp0Dot;
1068 meanPoleY = yp0 + t * yp0Dot;
1069
1070 }
1071
1072
1073 final PoleCorrection correction = eopHistory.getPoleCorrection(date);
1074 final double m1 = correction.getXp() - meanPoleX;
1075 final double m2 = meanPoleY - correction.getYp();
1076
1077 return new double[] {
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104 globalFactor * (m1 - ratio * m2),
1105 globalFactor * (m2 + ratio * m1),
1106 };
1107
1108 }
1109 };
1110
1111 }
1112
1113
1114 @Override
1115 public TimeFunction<double[]> getOceanPoleTide(final EOPHistory eopHistory)
1116 throws OrekitException {
1117
1118 return new TimeFunction<double[]>() {
1119
1120 @Override
1121 public double[] value(final AbsoluteDate date) {
1122
1123 return new double[] {
1124 0.0, 0.0
1125 };
1126 }
1127 };
1128 }
1129
1130 },
1131
1132
1133 IERS_2010 {
1134
1135
1136 private static final String NUTATION_ARGUMENTS = IERS_BASE + "2010/nutation-arguments.txt";
1137
1138
1139 private static final String X_SERIES = IERS_BASE + "2010/tab5.2a.txt";
1140
1141
1142 private static final String Y_SERIES = IERS_BASE + "2010/tab5.2b.txt";
1143
1144
1145 private static final String S_SERIES = IERS_BASE + "2010/tab5.2d.txt";
1146
1147
1148 private static final String PSI_SERIES = IERS_BASE + "2010/tab5.3a.txt";
1149
1150
1151 private static final String EPSILON_SERIES = IERS_BASE + "2010/tab5.3b.txt";
1152
1153
1154 private static final String GST_SERIES = IERS_BASE + "2010/tab5.2e.txt";
1155
1156
1157 private static final String TIDAL_CORRECTION_XP_YP_SERIES = IERS_BASE + "2010/tab8.2ab.txt";
1158
1159
1160 private static final String TIDAL_CORRECTION_UT1_SERIES = IERS_BASE + "2010/tab8.3ab.txt";
1161
1162
1163 private static final String LOVE_NUMBERS = IERS_BASE + "2010/tab6.3.txt";
1164
1165
1166 private static final String K20_FREQUENCY_DEPENDENCE = IERS_BASE + "2010/tab6.5b.txt";
1167
1168
1169 private static final String K21_FREQUENCY_DEPENDENCE = IERS_BASE + "2010/tab6.5a.txt";
1170
1171
1172 private static final String K22_FREQUENCY_DEPENDENCE = IERS_BASE + "2010/tab6.5c.txt";
1173
1174
1175 public FundamentalNutationArguments getNutationArguments(final TimeScale timeScale)
1176 throws OrekitException {
1177 return new FundamentalNutationArguments(this, timeScale,
1178 getStream(NUTATION_ARGUMENTS), NUTATION_ARGUMENTS);
1179 }
1180
1181
1182 @Override
1183 public TimeFunction<Double> getMeanObliquityFunction() throws OrekitException {
1184
1185
1186 final PolynomialNutation<DerivativeStructure> epsilonA =
1187 new PolynomialNutation<DerivativeStructure>(84381.406 * Constants.ARC_SECONDS_TO_RADIANS,
1188 -46.836769 * Constants.ARC_SECONDS_TO_RADIANS,
1189 -0.0001831 * Constants.ARC_SECONDS_TO_RADIANS,
1190 0.00200340 * Constants.ARC_SECONDS_TO_RADIANS,
1191 -0.000000576 * Constants.ARC_SECONDS_TO_RADIANS,
1192 -0.0000000434 * Constants.ARC_SECONDS_TO_RADIANS);
1193
1194 return new TimeFunction<Double>() {
1195
1196
1197 @Override
1198 public Double value(final AbsoluteDate date) {
1199 return epsilonA.value(evaluateTC(date));
1200 }
1201
1202 };
1203
1204 }
1205
1206
1207 @Override
1208 public TimeFunction<double[]> getXYSpXY2Function() throws OrekitException {
1209
1210
1211 final FundamentalNutationArguments arguments = getNutationArguments(null);
1212
1213
1214 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
1215 final PoissonSeriesParser<DerivativeStructure> parser =
1216 new PoissonSeriesParser<DerivativeStructure>(17).
1217 withPolynomialPart('t', PolynomialParser.Unit.MICRO_ARC_SECONDS).
1218 withFirstDelaunay(4).
1219 withFirstPlanetary(9).
1220 withSinCos(0, 2, microAS, 3, microAS);
1221 final PoissonSeries<DerivativeStructure> xSeries = parser.parse(getStream(X_SERIES), X_SERIES);
1222 final PoissonSeries<DerivativeStructure> ySeries = parser.parse(getStream(Y_SERIES), Y_SERIES);
1223 final PoissonSeries<DerivativeStructure> sSeries = parser.parse(getStream(S_SERIES), S_SERIES);
1224 @SuppressWarnings("unchecked")
1225 final PoissonSeries.CompiledSeries<DerivativeStructure> xys = PoissonSeries.compile(xSeries, ySeries, sSeries);
1226
1227
1228 return new TimeFunction<double[]>() {
1229
1230
1231 @Override
1232 public double[] value(final AbsoluteDate date) {
1233 return xys.value(arguments.evaluateAll(date));
1234 }
1235
1236 };
1237
1238 }
1239
1240
1241 public LoveNumbers getLoveNumbers() throws OrekitException {
1242 return loadLoveNumbers(LOVE_NUMBERS);
1243 }
1244
1245
1246 public TimeFunction<double[]> getTideFrequencyDependenceFunction(final TimeScale ut1)
1247 throws OrekitException {
1248
1249
1250 final FundamentalNutationArguments arguments = getNutationArguments(ut1);
1251
1252
1253 final PoissonSeriesParser<DerivativeStructure> k20Parser =
1254 new PoissonSeriesParser<DerivativeStructure>(18).
1255 withOptionalColumn(1).
1256 withDoodson(4, 2).
1257 withFirstDelaunay(10);
1258 final PoissonSeriesParser<DerivativeStructure> k21Parser =
1259 new PoissonSeriesParser<DerivativeStructure>(18).
1260 withOptionalColumn(1).
1261 withDoodson(4, 3).
1262 withFirstDelaunay(10);
1263 final PoissonSeriesParser<DerivativeStructure> k22Parser =
1264 new PoissonSeriesParser<DerivativeStructure>(16).
1265 withOptionalColumn(1).
1266 withDoodson(4, 2).
1267 withFirstDelaunay(10);
1268
1269 final double pico = 1.0e-12;
1270 final PoissonSeries<DerivativeStructure> c20Series =
1271 k20Parser.
1272 withSinCos(0, 18, -pico, 16, pico).
1273 parse(getStream(K20_FREQUENCY_DEPENDENCE), K20_FREQUENCY_DEPENDENCE);
1274 final PoissonSeries<DerivativeStructure> c21Series =
1275 k21Parser.
1276 withSinCos(0, 17, pico, 18, pico).
1277 parse(getStream(K21_FREQUENCY_DEPENDENCE), K21_FREQUENCY_DEPENDENCE);
1278 final PoissonSeries<DerivativeStructure> s21Series =
1279 k21Parser.
1280 withSinCos(0, 18, -pico, 17, pico).
1281 parse(getStream(K21_FREQUENCY_DEPENDENCE), K21_FREQUENCY_DEPENDENCE);
1282 final PoissonSeries<DerivativeStructure> c22Series =
1283 k22Parser.
1284 withSinCos(0, -1, pico, 16, pico).
1285 parse(getStream(K22_FREQUENCY_DEPENDENCE), K22_FREQUENCY_DEPENDENCE);
1286 final PoissonSeries<DerivativeStructure> s22Series =
1287 k22Parser.
1288 withSinCos(0, 16, -pico, -1, pico).
1289 parse(getStream(K22_FREQUENCY_DEPENDENCE), K22_FREQUENCY_DEPENDENCE);
1290
1291 @SuppressWarnings("unchecked")
1292 final PoissonSeries.CompiledSeries<DerivativeStructure> kSeries =
1293 PoissonSeries.compile(c20Series, c21Series, s21Series, c22Series, s22Series);
1294
1295 return new TimeFunction<double[]>() {
1296
1297 @Override
1298 public double[] value(final AbsoluteDate date) {
1299 return kSeries.value(arguments.evaluateAll(date));
1300 }
1301 };
1302
1303 }
1304
1305
1306 @Override
1307 public double getPermanentTide() throws OrekitException {
1308 return 4.4228e-8 * -0.31460 * getLoveNumbers().getReal(2, 0);
1309 }
1310
1311
1312
1313
1314
1315
1316 private double[] computePoleWobble(final AbsoluteDate date, final EOPHistory eopHistory) {
1317
1318
1319 final double f0 = Constants.ARC_SECONDS_TO_RADIANS / 1000.0;
1320 final double f1 = f0 / Constants.JULIAN_YEAR;
1321 final double f2 = f1 / Constants.JULIAN_YEAR;
1322 final double f3 = f2 / Constants.JULIAN_YEAR;
1323 final AbsoluteDate changeDate = new AbsoluteDate(2010, 1, 1, TimeScalesFactory.getTT());
1324
1325
1326 final double[] xPolynomial;
1327 final double[] yPolynomial;
1328 if (date.compareTo(changeDate) <= 0) {
1329 xPolynomial = new double[] {
1330 55.974 * f0, 1.8243 * f1, 0.18413 * f2, 0.007024 * f3
1331 };
1332 yPolynomial = new double[] {
1333 346.346 * f0, 1.7896 * f1, -0.10729 * f2, -0.000908 * f3
1334 };
1335 } else {
1336 xPolynomial = new double[] {
1337 23.513 * f0, 7.6141 * f1
1338 };
1339 yPolynomial = new double[] {
1340 358.891 * f0, -0.6287 * f1
1341 };
1342 }
1343 double meanPoleX = 0;
1344 double meanPoleY = 0;
1345 final double t = date.durationFrom(AbsoluteDate.J2000_EPOCH);
1346 for (int i = xPolynomial.length - 1; i >= 0; --i) {
1347 meanPoleX = meanPoleX * t + xPolynomial[i];
1348 }
1349 for (int i = yPolynomial.length - 1; i >= 0; --i) {
1350 meanPoleY = meanPoleY * t + yPolynomial[i];
1351 }
1352
1353
1354 final PoleCorrection correction = eopHistory.getPoleCorrection(date);
1355 final double m1 = correction.getXp() - meanPoleX;
1356 final double m2 = meanPoleY - correction.getYp();
1357
1358 return new double[] {
1359 m1, m2
1360 };
1361
1362 }
1363
1364
1365 @Override
1366 public TimeFunction<double[]> getSolidPoleTide(final EOPHistory eopHistory)
1367 throws OrekitException {
1368
1369
1370 final double globalFactor = -1.333e-9 / Constants.ARC_SECONDS_TO_RADIANS;
1371 final double ratio = 0.00115;
1372
1373 return new TimeFunction<double[]>() {
1374
1375 @Override
1376 public double[] value(final AbsoluteDate date) {
1377
1378
1379 final double[] wobbleM = computePoleWobble(date, eopHistory);
1380
1381 return new double[] {
1382
1383
1384
1385
1386
1387
1388
1389
1390 globalFactor * (wobbleM[0] + ratio * wobbleM[1]),
1391 globalFactor * (wobbleM[1] - ratio * wobbleM[0])
1392 };
1393
1394 }
1395 };
1396
1397 }
1398
1399
1400 @Override
1401 public TimeFunction<double[]> getOceanPoleTide(final EOPHistory eopHistory)
1402 throws OrekitException {
1403
1404 return new TimeFunction<double[]>() {
1405
1406 @Override
1407 public double[] value(final AbsoluteDate date) {
1408
1409
1410 final double[] wobbleM = computePoleWobble(date, eopHistory);
1411
1412 return new double[] {
1413
1414
1415
1416
1417 -2.1778e-10 * (wobbleM[0] - 0.01724 * wobbleM[1]) / Constants.ARC_SECONDS_TO_RADIANS,
1418 -1.7232e-10 * (wobbleM[1] - 0.03365 * wobbleM[0]) / Constants.ARC_SECONDS_TO_RADIANS
1419 };
1420
1421 }
1422 };
1423
1424 }
1425
1426
1427 @Override
1428 public TimeFunction<double[]> getPrecessionFunction() throws OrekitException {
1429
1430
1431
1432 final PolynomialNutation<DerivativeStructure> psiA =
1433 new PolynomialNutation<DerivativeStructure>( 0.0,
1434 5038.481507 * Constants.ARC_SECONDS_TO_RADIANS,
1435 -1.0790069 * Constants.ARC_SECONDS_TO_RADIANS,
1436 -0.00114045 * Constants.ARC_SECONDS_TO_RADIANS,
1437 0.000132851 * Constants.ARC_SECONDS_TO_RADIANS,
1438 -0.0000000951 * Constants.ARC_SECONDS_TO_RADIANS);
1439 final PolynomialNutation<DerivativeStructure> omegaA =
1440 new PolynomialNutation<DerivativeStructure>(getMeanObliquityFunction().value(getNutationReferenceEpoch()),
1441 -0.025754 * Constants.ARC_SECONDS_TO_RADIANS,
1442 0.0512623 * Constants.ARC_SECONDS_TO_RADIANS,
1443 -0.00772503 * Constants.ARC_SECONDS_TO_RADIANS,
1444 -0.000000467 * Constants.ARC_SECONDS_TO_RADIANS,
1445 0.0000003337 * Constants.ARC_SECONDS_TO_RADIANS);
1446 final PolynomialNutation<DerivativeStructure> chiA =
1447 new PolynomialNutation<DerivativeStructure>( 0.0,
1448 10.556403 * Constants.ARC_SECONDS_TO_RADIANS,
1449 -2.3814292 * Constants.ARC_SECONDS_TO_RADIANS,
1450 -0.00121197 * Constants.ARC_SECONDS_TO_RADIANS,
1451 0.000170663 * Constants.ARC_SECONDS_TO_RADIANS,
1452 -0.0000000560 * Constants.ARC_SECONDS_TO_RADIANS);
1453
1454 return new TimeFunction<double[]>() {
1455
1456 @Override
1457 public double[] value(final AbsoluteDate date) {
1458 final double tc = evaluateTC(date);
1459 return new double[] {
1460 psiA.value(tc), omegaA.value(tc), chiA.value(tc)
1461 };
1462 }
1463 };
1464
1465 }
1466
1467
1468 @Override
1469 public TimeFunction<double[]> getNutationFunction()
1470 throws OrekitException {
1471
1472
1473 final FundamentalNutationArguments arguments = getNutationArguments(null);
1474
1475
1476 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
1477 final PoissonSeriesParser<DerivativeStructure> parser =
1478 new PoissonSeriesParser<DerivativeStructure>(17).
1479 withFirstDelaunay(4).
1480 withFirstPlanetary(9).
1481 withSinCos(0, 2, microAS, 3, microAS);
1482 final PoissonSeries<DerivativeStructure> psiSeries = parser.parse(getStream(PSI_SERIES), PSI_SERIES);
1483 final PoissonSeries<DerivativeStructure> epsilonSeries = parser.parse(getStream(EPSILON_SERIES), EPSILON_SERIES);
1484 @SuppressWarnings("unchecked")
1485 final PoissonSeries.CompiledSeries<DerivativeStructure> psiEpsilonSeries =
1486 PoissonSeries.compile(psiSeries, epsilonSeries);
1487
1488 return new TimeFunction<double[]>() {
1489
1490 @Override
1491 public double[] value(final AbsoluteDate date) {
1492 final BodiesElements elements = arguments.evaluateAll(date);
1493 final double[] psiEpsilon = psiEpsilonSeries.value(elements);
1494 return new double[] {
1495 psiEpsilon[0], psiEpsilon[1], IAU1994ResolutionC7.value(elements)
1496 };
1497 }
1498 };
1499
1500 }
1501
1502
1503 @Override
1504 public TimeFunction<DerivativeStructure> getGMSTFunction(final TimeScale ut1) throws OrekitException {
1505
1506
1507 final StellarAngleCapitaine era = new StellarAngleCapitaine(ut1);
1508
1509
1510
1511 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
1512 final PoissonSeriesParser<DerivativeStructure> parser =
1513 new PoissonSeriesParser<DerivativeStructure>(17).
1514 withFirstDelaunay(4).
1515 withFirstPlanetary(9).
1516 withSinCos(0, 2, microAS, 3, microAS).
1517 withPolynomialPart('t', Unit.ARC_SECONDS);
1518 final PolynomialNutation<DerivativeStructure> minusEO =
1519 parser.parse(getStream(GST_SERIES), GST_SERIES).getPolynomial();
1520
1521
1522 return new TimeFunction<DerivativeStructure>() {
1523
1524
1525 @Override
1526 public DerivativeStructure value(final AbsoluteDate date) {
1527 return era.value(date).add(minusEO.value(dsEvaluateTC(date)));
1528 }
1529
1530 };
1531
1532 }
1533
1534
1535 @Override
1536 public TimeFunction<DerivativeStructure> getGASTFunction(final TimeScale ut1,
1537 final EOPHistory eopHistory)
1538 throws OrekitException {
1539
1540
1541 final FundamentalNutationArguments arguments = getNutationArguments(null);
1542
1543
1544 final TimeFunction<Double> epsilon = getMeanObliquityFunction();
1545
1546
1547 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
1548 final PoissonSeriesParser<DerivativeStructure> baseParser =
1549 new PoissonSeriesParser<DerivativeStructure>(17).
1550 withFirstDelaunay(4).
1551 withFirstPlanetary(9).
1552 withSinCos(0, 2, microAS, 3, microAS);
1553 final PoissonSeriesParser<DerivativeStructure> gstParser = baseParser.withPolynomialPart('t', Unit.ARC_SECONDS);
1554 final PoissonSeries<DerivativeStructure> psiSeries = baseParser.parse(getStream(PSI_SERIES), PSI_SERIES);
1555 final PoissonSeries<DerivativeStructure> gstSeries = gstParser.parse(getStream(GST_SERIES), GST_SERIES);
1556 @SuppressWarnings("unchecked")
1557 final PoissonSeries.CompiledSeries<DerivativeStructure> psiGstSeries =
1558 PoissonSeries.compile(psiSeries, gstSeries);
1559
1560
1561 final TimeFunction<DerivativeStructure> era = getEarthOrientationAngleFunction(ut1);
1562
1563 return new TimeFunction<DerivativeStructure>() {
1564
1565
1566 @Override
1567 public DerivativeStructure value(final AbsoluteDate date) {
1568
1569
1570 final BodiesElements elements = arguments.evaluateAll(date);
1571 final double[] angles = psiGstSeries.value(elements);
1572 final double ddPsi = (eopHistory == null) ? 0 : eopHistory.getEquinoxNutationCorrection(date)[0];
1573 final double deltaPsi = angles[0] + ddPsi;
1574 final double epsilonA = epsilon.value(date);
1575
1576
1577
1578 return era.value(date).add(deltaPsi * FastMath.cos(epsilonA) + angles[1]);
1579
1580 }
1581
1582 };
1583
1584 }
1585
1586
1587 @Override
1588 public TimeFunction<double[]> getEOPTidalCorrection()
1589 throws OrekitException {
1590
1591
1592
1593
1594
1595
1596 final FundamentalNutationArguments arguments = getNutationArguments(TimeScalesFactory.getTT());
1597
1598
1599 final double microAS = Constants.ARC_SECONDS_TO_RADIANS * 1.0e-6;
1600 final PoissonSeriesParser<DerivativeStructure> xyParser = new PoissonSeriesParser<DerivativeStructure>(13).
1601 withOptionalColumn(1).
1602 withGamma(2).
1603 withFirstDelaunay(3);
1604 final PoissonSeries<DerivativeStructure> xSeries =
1605 xyParser.
1606 withSinCos(0, 10, microAS, 11, microAS).
1607 parse(getStream(TIDAL_CORRECTION_XP_YP_SERIES), TIDAL_CORRECTION_XP_YP_SERIES);
1608 final PoissonSeries<DerivativeStructure> ySeries =
1609 xyParser.
1610 withSinCos(0, 12, microAS, 13, microAS).
1611 parse(getStream(TIDAL_CORRECTION_XP_YP_SERIES), TIDAL_CORRECTION_XP_YP_SERIES);
1612
1613 final double microS = 1.0e-6;
1614 final PoissonSeriesParser<DerivativeStructure> ut1Parser = new PoissonSeriesParser<DerivativeStructure>(11).
1615 withOptionalColumn(1).
1616 withGamma(2).
1617 withFirstDelaunay(3).
1618 withSinCos(0, 10, microS, 11, microS);
1619 final PoissonSeries<DerivativeStructure> ut1Series =
1620 ut1Parser.parse(getStream(TIDAL_CORRECTION_UT1_SERIES), TIDAL_CORRECTION_UT1_SERIES);
1621
1622 @SuppressWarnings("unchecked")
1623 final PoissonSeries.CompiledSeries<DerivativeStructure> correctionSeries =
1624 PoissonSeries.compile(xSeries, ySeries, ut1Series);
1625
1626 return new TimeFunction<double[]>() {
1627
1628 @Override
1629 public double[] value(final AbsoluteDate date) {
1630 final FieldBodiesElements<DerivativeStructure> elements =
1631 arguments.evaluateDerivative(date);
1632 final DerivativeStructure[] correction = correctionSeries.value(elements);
1633 return new double[] {
1634 correction[0].getValue(),
1635 correction[1].getValue(),
1636 correction[2].getValue(),
1637 -correction[2].getPartialDerivative(1) * Constants.JULIAN_DAY
1638 };
1639 }
1640 };
1641
1642 }
1643
1644 };
1645
1646
1647 private static final String IERS_BASE = "/assets/org/orekit/IERS-conventions/";
1648
1649
1650
1651
1652
1653 public AbsoluteDate getNutationReferenceEpoch() {
1654
1655 return AbsoluteDate.J2000_EPOCH;
1656 }
1657
1658
1659
1660
1661
1662
1663 public double evaluateTC(final AbsoluteDate date) {
1664 return date.durationFrom(getNutationReferenceEpoch()) / Constants.JULIAN_CENTURY;
1665 }
1666
1667
1668
1669
1670
1671
1672 public DerivativeStructure dsEvaluateTC(final AbsoluteDate date) {
1673 return new DerivativeStructure(1, 1, evaluateTC(date), 1.0 / Constants.JULIAN_CENTURY);
1674 }
1675
1676
1677
1678
1679
1680
1681
1682
1683 public abstract FundamentalNutationArguments getNutationArguments(final TimeScale timeScale)
1684 throws OrekitException;
1685
1686
1687
1688
1689
1690
1691 public abstract TimeFunction<Double> getMeanObliquityFunction() throws OrekitException;
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701 public abstract TimeFunction<double[]> getXYSpXY2Function()
1702 throws OrekitException;
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716 public TimeFunction<DerivativeStructure> getEarthOrientationAngleFunction(final TimeScale ut1) {
1717 return new StellarAngleCapitaine(ut1);
1718 }
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734 public abstract TimeFunction<double[]> getPrecessionFunction() throws OrekitException;
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747 public abstract TimeFunction<double[]> getNutationFunction()
1748 throws OrekitException;
1749
1750
1751
1752
1753
1754
1755
1756
1757 public abstract TimeFunction<DerivativeStructure> getGMSTFunction(TimeScale ut1)
1758 throws OrekitException;
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768 public abstract TimeFunction<DerivativeStructure> getGASTFunction(TimeScale ut1,
1769 EOPHistory eopHistory)
1770 throws OrekitException;
1771
1772
1773
1774
1775
1776
1777
1778 public abstract TimeFunction<double[]> getEOPTidalCorrection()
1779 throws OrekitException;
1780
1781
1782
1783
1784
1785
1786 public abstract LoveNumbers getLoveNumbers()
1787 throws OrekitException;
1788
1789
1790
1791
1792
1793
1794
1795 public abstract TimeFunction<double[]> getTideFrequencyDependenceFunction(TimeScale ut1)
1796 throws OrekitException;
1797
1798
1799
1800
1801
1802 public abstract double getPermanentTide() throws OrekitException;
1803
1804
1805
1806
1807
1808
1809
1810 public abstract TimeFunction<double[]> getSolidPoleTide(EOPHistory eopHistory)
1811 throws OrekitException;
1812
1813
1814
1815
1816
1817
1818
1819 public abstract TimeFunction<double[]> getOceanPoleTide(EOPHistory eopHistory)
1820 throws OrekitException;
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830 public interface NutationCorrectionConverter {
1831
1832
1833
1834
1835
1836
1837
1838
1839 double[] toNonRotating(AbsoluteDate date, double ddPsi, double ddEpsilon)
1840 throws OrekitException;
1841
1842
1843
1844
1845
1846
1847
1848
1849 double[] toEquinox(AbsoluteDate date, double dX, double dY)
1850 throws OrekitException;
1851
1852 }
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864 public NutationCorrectionConverter getNutationCorrectionConverter()
1865 throws OrekitException {
1866
1867
1868 final TimeFunction<double[]> precessionFunction = getPrecessionFunction();
1869 final TimeFunction<Double> epsilonAFunction = getMeanObliquityFunction();
1870 final AbsoluteDate date0 = getNutationReferenceEpoch();
1871 final double cosE0 = FastMath.cos(epsilonAFunction.value(date0));
1872
1873 return new NutationCorrectionConverter() {
1874
1875
1876 @Override
1877 public double[] toNonRotating(final AbsoluteDate date,
1878 final double ddPsi, final double ddEpsilon)
1879 throws OrekitException {
1880
1881 final double[] angles = precessionFunction.value(date);
1882
1883
1884 final double sinEA = FastMath.sin(epsilonAFunction.value(date));
1885 final double c = angles[0] * cosE0 - angles[2];
1886
1887
1888 return new double[] {
1889 sinEA * ddPsi + c * ddEpsilon,
1890 ddEpsilon - c * sinEA * ddPsi
1891 };
1892
1893 }
1894
1895
1896 @Override
1897 public double[] toEquinox(final AbsoluteDate date,
1898 final double dX, final double dY)
1899 throws OrekitException {
1900
1901 final double[] angles = precessionFunction.value(date);
1902
1903
1904 final double sinEA = FastMath.sin(epsilonAFunction.value(date));
1905 final double c = angles[0] * cosE0 - angles[2];
1906 final double opC2 = 1 + c * c;
1907
1908
1909 return new double[] {
1910 (dX - c * dY) / (sinEA * opC2),
1911 (dY + c * dX) / opC2
1912 };
1913 }
1914
1915 };
1916
1917 }
1918
1919
1920
1921
1922
1923
1924
1925 protected LoveNumbers loadLoveNumbers(final String nameLove) throws OrekitException {
1926 InputStream stream = null;
1927 BufferedReader reader = null;
1928 try {
1929
1930
1931 final double[][] real = new double[4][];
1932 final double[][] imaginary = new double[4][];
1933 final double[][] plus = new double[4][];
1934 for (int i = 0; i < real.length; ++i) {
1935 real[i] = new double[i + 1];
1936 imaginary[i] = new double[i + 1];
1937 plus[i] = new double[i + 1];
1938 }
1939
1940 stream = IERSConventions.class.getResourceAsStream(nameLove);
1941 if (stream == null) {
1942
1943 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, nameLove);
1944 }
1945
1946
1947 reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
1948
1949 String line = reader.readLine();
1950 int lineNumber = 1;
1951
1952
1953 while (line != null) {
1954
1955 line = line.trim();
1956 if (!(line.isEmpty() || line.startsWith("#"))) {
1957 final String[] fields = line.split("\\p{Space}+");
1958 if (fields.length != 5) {
1959
1960 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
1961 lineNumber, nameLove, line);
1962 }
1963 final int n = Integer.parseInt(fields[0]);
1964 final int m = Integer.parseInt(fields[1]);
1965 if ((n < 2) || (n > 3) || (m < 0) || (m > n)) {
1966
1967 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
1968 lineNumber, nameLove, line);
1969
1970 }
1971 real[n][m] = Double.parseDouble(fields[2]);
1972 imaginary[n][m] = Double.parseDouble(fields[3]);
1973 plus[n][m] = Double.parseDouble(fields[4]);
1974 }
1975
1976
1977 lineNumber++;
1978 line = reader.readLine();
1979
1980 }
1981
1982 return new LoveNumbers(real, imaginary, plus);
1983
1984 } catch (IOException ioe) {
1985
1986 throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, nameLove);
1987 } finally {
1988 try {
1989 if (stream != null) {
1990 stream.close();
1991 }
1992 if (reader != null) {
1993 reader.close();
1994 }
1995 } catch (IOException ioe) {
1996
1997 }
1998 }
1999 }
2000
2001
2002
2003
2004
2005 private static InputStream getStream(final String name) {
2006 return IERSConventions.class.getResourceAsStream(name);
2007 }
2008
2009
2010
2011
2012
2013
2014 private static class IAU1994ResolutionC7 {
2015
2016
2017 private static final double EQE1 = 0.00264 * Constants.ARC_SECONDS_TO_RADIANS;
2018
2019
2020 private static final double EQE2 = 0.000063 * Constants.ARC_SECONDS_TO_RADIANS;
2021
2022
2023
2024
2025 private static final AbsoluteDate MODEL_START =
2026 new AbsoluteDate(1997, 2, 27, 0, 0, 30, TimeScalesFactory.getTAI());
2027
2028
2029
2030
2031
2032 public static double value(final DelaunayArguments arguments) {
2033 if (arguments.getDate().compareTo(MODEL_START) >= 0) {
2034
2035
2036
2037
2038
2039 final double om = arguments.getOmega();
2040
2041
2042 return EQE1 * FastMath.sin(om) + EQE2 * FastMath.sin(om + om);
2043
2044 } else {
2045 return 0.0;
2046 }
2047 }
2048
2049 };
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066 private static class StellarAngleCapitaine implements TimeFunction<DerivativeStructure> {
2067
2068
2069 private static final AbsoluteDate REFERENCE_DATE = new AbsoluteDate(DateComponents.J2000_EPOCH,
2070 TimeComponents.H12,
2071 TimeScalesFactory.getTAI());
2072
2073
2074 private static final double ERA_0 = MathUtils.TWO_PI * 0.7790572732640;
2075
2076
2077
2078 private static final double ERA_1A = MathUtils.TWO_PI / Constants.JULIAN_DAY;
2079
2080
2081
2082 private static final double ERA_1B = ERA_1A * 0.00273781191135448;
2083
2084
2085 private static final double ERA_1AB = ERA_1A + ERA_1B;
2086
2087
2088 private final TimeScale ut1;
2089
2090
2091
2092
2093 StellarAngleCapitaine(final TimeScale ut1) {
2094 this.ut1 = ut1;
2095 }
2096
2097
2098 @Override
2099 public DerivativeStructure value(final AbsoluteDate date) {
2100
2101
2102 final int secondsInDay = 86400;
2103 final double dt = date.durationFrom(REFERENCE_DATE);
2104 final long days = ((long) dt) / secondsInDay;
2105 final double dtA = secondsInDay * days;
2106 final double dtB = (dt - dtA) + ut1.offsetFromTAI(date);
2107
2108 return new DerivativeStructure(1, 1,
2109 ERA_0 + ERA_1A * dtB + ERA_1B * (dtA + dtB),
2110 ERA_1AB);
2111
2112 }
2113
2114 }
2115
2116
2117 private static class MeanPole implements TimeStamped, Serializable {
2118
2119
2120 private static final long serialVersionUID = 20131028l;
2121
2122
2123 private final AbsoluteDate date;
2124
2125
2126 private double x;
2127
2128
2129 private double y;
2130
2131
2132
2133
2134
2135
2136 MeanPole(final AbsoluteDate date, final double x, final double y) {
2137 this.date = date;
2138 this.x = x;
2139 this.y = y;
2140 }
2141
2142
2143 @Override
2144 public AbsoluteDate getDate() {
2145 return date;
2146 }
2147
2148
2149
2150
2151 public double getX() {
2152 return x;
2153 }
2154
2155
2156
2157
2158 public double getY() {
2159 return y;
2160 }
2161
2162 }
2163 }