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