PredefinedIAUPoles.java

  1. /* Copyright 2002-2025 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.bodies;

  18. import java.util.ArrayList;
  19. import java.util.List;

  20. import org.hipparchus.CalculusFieldElement;
  21. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  22. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  23. import org.hipparchus.util.FastMath;
  24. import org.hipparchus.util.FieldSinCos;
  25. import org.hipparchus.util.SinCos;
  26. import org.orekit.bodies.JPLEphemeridesLoader.EphemerisType;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.time.FieldAbsoluteDate;
  29. import org.orekit.time.TimeScales;
  30. import org.orekit.utils.Constants;

  31. /** Enumerate for predefined IAU poles.
  32.  * <p>The pole models provided here come from the <a
  33.  * href="http://astropedia.astrogeology.usgs.gov/alfresco/d/d/workspace/SpacesStore/28fd9e81-1964-44d6-a58b-fbbf61e64e15/WGCCRE2009reprint.pdf">
  34.  * 2009 report</a> and the <a href="http://astropedia.astrogeology.usgs.gov/alfresco/d/d/workspace/SpacesStore/04d348b0-eb2b-46a2-abe9-6effacb37763/WGCCRE-Erratum-2011reprint.pdf">
  35.  * 2011 erratum</a> of the IAU/IAG Working Group on Cartographic Coordinates
  36.  * and Rotational Elements of the Planets and Satellites (WGCCRE). Note that these value
  37.  * differ from earliest reports (before 2005).
  38.  *</p>
  39.  * @author Luc Maisonobe
  40.  * @since 9.0
  41.  */
  42. abstract class PredefinedIAUPoles implements IAUPole {

  43.     /** Serializable UID. */
  44.     private static final long serialVersionUID = 20200130L;

  45.     /** Time scales. */
  46.     private final TimeScales timeScales;

  47.     /**
  48.      * Simple constructor.
  49.      *
  50.      * @param timeScales to use when computing the pole, including TDB and J2000.0.
  51.      */
  52.     PredefinedIAUPoles(final TimeScales timeScales) {
  53.         this.timeScales = timeScales;
  54.     }

  55.     /** IAU pole and prime meridian model for Sun. */
  56.     private static class Sun extends PredefinedIAUPoles {

  57.         /** Serializable UID. */
  58.         private static final long serialVersionUID = 20200130L;

  59.         /** Constant term of the prime meridian. */
  60.         private static final double W0 = 84.176;

  61.         /** Rate term of the prime meridian. */
  62.         private static final double W_DOT = 14.1844000;

  63.         /** Fixed pole. */
  64.         private final Vector3D pole = new Vector3D(FastMath.toRadians(286.13),
  65.                                                    FastMath.toRadians(63.87));

  66.         /**
  67.          * Simple constructor.
  68.          *
  69.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  70.          */
  71.         Sun(final TimeScales timeScales) {
  72.             super(timeScales);
  73.         }

  74.         /** {@inheritDoc} */
  75.         public Vector3D getPole(final AbsoluteDate date) {
  76.             return pole;
  77.         }

  78.         /** {@inheritDoc} */
  79.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  80.             return new FieldVector3D<>(date.getField(), pole);
  81.         }

  82.         /** {@inheritDoc} */
  83.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  84.             return FastMath.toRadians(d(date) * W_DOT + W0);
  85.         }

  86.         /** {@inheritDoc} */
  87.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  88.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W0));
  89.         }

  90.     }

  91.     /** IAU pole and prime meridian model for Mercury. */
  92.     private static class Mercury extends PredefinedIAUPoles {

  93.         /** Serializable UID. */
  94.         private static final long serialVersionUID = 20200130L;

  95.         /** Constant term of the right ascension of the pole. */
  96.         private static final double ALPHA_0 = 281.0097;

  97.         /** Rate term of the right ascension of the pole. */
  98.         private static final double ALPHA_DOT = -0.0328;

  99.         /** Constant term of the declination of the pole. */
  100.         private static final double DELTA_0 = 61.4143;

  101.         /** Rate term of the declination of the pole. */
  102.         private static final double DELTA_DOT = -0.0049;

  103.         /** Constant term of the prime meridian. */
  104.         private static final double W_0 = 329.5469;

  105.         /** Rate term of the prime meridian. */
  106.         private static final double W_DOT = 6.1385025;

  107.         /** M1 coefficient of the prime meridian. */
  108.         private static final double M1_COEFF = 0.00993822;

  109.         /** M2 coefficient of the prime meridian. */
  110.         private static final double M2_COEFF = -0.00104581;

  111.         /** M3 coefficient of the prime meridian. */
  112.         private static final double M3_COEFF = -0.00010280;

  113.         /** M4 coefficient of the prime meridian. */
  114.         private static final double M4_COEFF = -0.00002364;

  115.         /** M5 coefficient of the prime meridian. */
  116.         private static final double M5_COEFF = -0.00000532;

  117.         /** Constant term of the M1 angle. */
  118.         private static final double M1_0   = 174.791086;

  119.         /** Rate term of the M1 angle. */
  120.         private static final double M1_DOT = 4.092335;

  121.         /** Constant term of the M2 angle. */
  122.         private static final double M2_0   = 349.582171;

  123.         /** Rate term of the M1 angle. */
  124.         private static final double M2_DOT = 8.184670;

  125.         /** Constant term of the M3 angle. */
  126.         private static final double M3_0   = 164.373257;

  127.         /** Rate term of the M1 angle. */
  128.         private static final double M3_DOT = 12.277005;

  129.         /** Constant term of the M4 angle. */
  130.         private static final double M4_0   = 339.164343;

  131.         /** Rate term of the M1 angle. */
  132.         private static final double M4_DOT = 16.369340;

  133.         /** Constant term of the M5 angle. */
  134.         private static final double M5_0   = 153.955429;

  135.         /** Rate term of the M1 angle. */
  136.         private static final double M5_DOT = 20.461675;

  137.         /**
  138.          * Simple constructor.
  139.          *
  140.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  141.          */
  142.         Mercury(final TimeScales timeScales) {
  143.             super(timeScales);
  144.         }

  145.         /** {@inheritDoc} */
  146.         public Vector3D getPole(final AbsoluteDate date) {
  147.             final double t = t(date);
  148.             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
  149.                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
  150.         }

  151.         /** {@inheritDoc} */
  152.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  153.             final T t = t(date);
  154.             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
  155.                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
  156.         }

  157.         /** {@inheritDoc} */
  158.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  159.             final double d = d(date);
  160.             return FastMath.toRadians(d(date) * W_DOT + W_0 +
  161.                                       FastMath.sin(FastMath.toRadians(d * M1_DOT + M1_0)) * M1_COEFF +
  162.                                       FastMath.sin(FastMath.toRadians(d * M2_DOT + M2_0)) * M2_COEFF +
  163.                                       FastMath.sin(FastMath.toRadians(d * M3_DOT + M3_0)) * M3_COEFF +
  164.                                       FastMath.sin(FastMath.toRadians(d * M4_DOT + M4_0)) * M4_COEFF +
  165.                                       FastMath.sin(FastMath.toRadians(d * M5_DOT + M5_0)) * M5_COEFF);
  166.         }

  167.         /** {@inheritDoc} */
  168.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  169.             final T d = d(date);
  170.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0).
  171.                              add(FastMath.toRadians(d.multiply(M1_DOT).add(M1_0)).sin().multiply(M1_COEFF)).
  172.                              add(FastMath.toRadians(d.multiply(M2_DOT).add(M2_0)).sin().multiply(M2_COEFF)).
  173.                              add(FastMath.toRadians(d.multiply(M3_DOT).add(M3_0)).sin().multiply(M3_COEFF)).
  174.                              add(FastMath.toRadians(d.multiply(M4_DOT).add(M4_0)).sin().multiply(M4_COEFF)).
  175.                              add(FastMath.toRadians(d.multiply(M5_DOT).add(M5_0)).sin().multiply(M5_COEFF)));
  176.         }

  177.     }

  178.     /** IAU pole and prime meridian model for Venus. */
  179.     private static class Venus extends PredefinedIAUPoles {

  180.         /** Serializable UID. */
  181.         private static final long serialVersionUID = 20200130L;

  182.         /** Constant term of the prime meridian. */
  183.         private static final double W_0 = 160.20;

  184.         /** Rate term of the prime meridian. */
  185.         private static final double W_DOT = -1.4813688;

  186.         /** Fixed pole. */
  187.         private final Vector3D pole = new Vector3D(FastMath.toRadians(272.76),
  188.                                                    FastMath.toRadians(67.16));

  189.         /**
  190.          * Simple constructor.
  191.          *
  192.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  193.          */
  194.         Venus(final TimeScales timeScales) {
  195.             super(timeScales);
  196.         }

  197.         /** {@inheritDoc} */
  198.         public Vector3D getPole(final AbsoluteDate date) {
  199.             return pole;
  200.         }

  201.         /** {@inheritDoc} */
  202.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  203.             return new FieldVector3D<>(date.getField(), pole);
  204.         }

  205.         /** {@inheritDoc} */
  206.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  207.             return FastMath.toRadians(d(date) * W_DOT + W_0);
  208.         }

  209.         /** {@inheritDoc} */
  210.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  211.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
  212.         }

  213.     }

  214.     /** IAU pole and prime meridian model for Earth. */
  215.     private static class Earth extends PredefinedIAUPoles {

  216.         /** Serializable UID. */
  217.         private static final long serialVersionUID = 20200130L;

  218.         /** Constant term of the right ascension of the pole. */
  219.         private static final double ALPHA_0 =  0.00;

  220.         /** Rate term of the right ascension of the pole. */
  221.         private static final double ALPHA_DOT = -0.641;

  222.         /** Constant term of the declination of the pole. */
  223.         private static final double DELTA_0 = 90.00;

  224.         /** Rate term of the declination of the pole. */
  225.         private static final double DELTA_DOT = -0.557;

  226.         /** Constant term of the prime meridian. */
  227.         private static final double W_0 = 190.147;

  228.         /** Rate term of the prime meridian. */
  229.         private static final double W_DOT = 360.9856235;

  230.         /**
  231.          * Simple constructor.
  232.          *
  233.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  234.          */
  235.         Earth(final TimeScales timeScales) {
  236.             super(timeScales);
  237.         }

  238.         /** {@inheritDoc} */
  239.         public Vector3D getPole(final AbsoluteDate date) {
  240.             final double t = t(date);
  241.             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
  242.                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
  243.         }

  244.         /** {@inheritDoc} */
  245.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  246.             final T t = t(date);
  247.             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
  248.                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
  249.         }

  250.         /** {@inheritDoc} */
  251.         @Override
  252.         public Vector3D getNode(final AbsoluteDate date) {
  253.             final double t = t(date);
  254.             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 + 90.0),
  255.                                 0.0);
  256.         }

  257.         /** {@inheritDoc} */
  258.         @Override
  259.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getNode(final FieldAbsoluteDate<T> date) {
  260.             final T t = t(date);
  261.             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0 + 90.0)),
  262.                                        date.getField().getZero());
  263.         }

  264.         /** {@inheritDoc} */
  265.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  266.             return FastMath.toRadians(d(date) * W_DOT + W_0);
  267.         }

  268.         /** {@inheritDoc} */
  269.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  270.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
  271.         }

  272.     }

  273.     /** IAU pole and prime meridian model for the Moon. */
  274.     private static class Moon extends PredefinedIAUPoles {

  275.         /** Serializable UID. */
  276.         private static final long serialVersionUID = 20200130L;

  277.         /** Constant term of the right ascension of the pole. */
  278.         private static final double ALPHA_0 = 269.9949;

  279.         /** Rate term of the right ascension of the pole. */
  280.         private static final double ALPHA_DOT = 0.0031;

  281.         /** Constant term of the declination of the pole. */
  282.         private static final double DELTA_0 = 66.5392;

  283.         /** Rate term of the declination of the pole. */
  284.         private static final double DELTA_DOT =  0.0130;

  285.         /** Constant term of the prime meridian. */
  286.         private static final double W_0 = 38.3213;

  287.         /** Rate term of the prime meridian. */
  288.         private static final double W_DOT = 13.17635815;

  289.         /** Rate term of the prime meridian. */
  290.         private static final double W_DOT_DOT = -1.4e-12;

  291.         /** Constant term of the E1 angle. */
  292.         private static final double E01_0    = 125.045;

  293.         /** Rate term of the E1 angle. */
  294.         private static final double E01_DOT  =  -0.0529921;

  295.         /** Sine coefficient of the E1 angle. */
  296.         private static final double E01_SIN  = -3.8787;

  297.         /** Cosine coefficient of the E1 angle. */
  298.         private static final double E01_COS  =  1.5419;

  299.         /** Sine coefficient of the E1 angle, for the prime meridian. */
  300.         private static final double E01_W_SIN =  3.5610;

  301.         /** Constant term of the E2 angle. */
  302.         private static final double E02_0    = 250.089;

  303.         /** Rate term of the E2 angle. */
  304.         private static final double E02_DOT  =  -0.1059842;

  305.         /** Sine coefficient of the E2 angle. */
  306.         private static final double E02_SIN  = -0.1204;

  307.         /** Cosine coefficient of the E2 angle. */
  308.         private static final double E02_COS  =  0.0239;

  309.         /** Sine coefficient of the E2 angle, for the prime meridian. */
  310.         private static final double E02_W_SIN =  0.1208;

  311.         /** Constant term of the E3 angle. */
  312.         private static final double E03_0    = 260.008;

  313.         /** Rate term of the E3 angle. */
  314.         private static final double E03_DOT  =  13.0120009;

  315.         /** Sine coefficient of the E3 angle. */
  316.         private static final double E03_SIN  =  0.0700;

  317.         /** Cosine coefficient of the E3 angle. */
  318.         private static final double E03_COS  = -0.0278;

  319.         /** Sine coefficient of the E3 angle, for the prime meridian. */
  320.         private static final double E03_W_SIN = -0.0642;

  321.         /** Constant term of the E4 angle. */
  322.         private static final double E04_0    = 176.625;

  323.         /** Rate term of the E4 angle. */
  324.         private static final double E04_DOT  =  13.3407154;

  325.         /** Sine coefficient of the E4 angle. */
  326.         private static final double E04_SIN  = -0.0172;

  327.         /** Cosine coefficient of the E4 angle. */
  328.         private static final double E04_COS  =  0.0068;

  329.         /** Sine coefficient of the E4 angle, for the prime meridian. */
  330.         private static final double E04_W_SIN =  0.0158;

  331.         /** Constant term of the E5 angle. */
  332.         private static final double E05_0    = 357.529;

  333.         /** Rate term of the E5 angle. */
  334.         private static final double E05_DOT  =   0.9856003;

  335.         /** Sine coefficient of the E5 angle, for the prime meridian. */
  336.         private static final double E05_W_SIN =  0.0252;

  337.         /** Constant term of the E6 angle. */
  338.         private static final double E06_0    = 311.589;

  339.         /** Rate term of the E6 angle. */
  340.         private static final double E06_DOT  =  26.4057084;

  341.         /** Sine coefficient of the E6 angle. */
  342.         private static final double E06_SIN  = 0.0072;

  343.         /** Cosine coefficient of the E6 angle. */
  344.         private static final double E06_COS  = -0.0029;

  345.         /** Sine coefficient of the E6 angle, for the prime meridian. */
  346.         private static final double E06_W_SIN = -0.0066;

  347.         /** Constant term of the E7 angle. */
  348.         private static final double E07_0    = 134.963;

  349.         /** Rate term of the E7 angle. */
  350.         private static final double E07_DOT  =  13.0649930;

  351.         /** Cosine coefficient of the E7 angle. */
  352.         private static final double E07_COS  =  0.0009;

  353.         /** Sine coefficient of the E7 angle, for the prime meridian. */
  354.         private static final double E07_W_SIN = -0.0047;

  355.         /** Constant term of the E8 angle. */
  356.         private static final double E08_0    = 276.617;

  357.         /** Rate term of the E8 angle. */
  358.         private static final double E08_DOT  =   0.3287146;

  359.         /** Sine coefficient of the E8 angle, for the prime meridian. */
  360.         private static final double E08_W_SIN = -0.0046;

  361.         /** Constant term of the E9 angle. */
  362.         private static final double E09_0    =  34.226;

  363.         /** Rate term of the E9 angle. */
  364.         private static final double E09_DOT  =   1.7484877;

  365.         /** Sine coefficient of the E9 angle, for the prime meridian. */
  366.         private static final double E09_W_SIN =  0.0028;

  367.         /** Constant term of the E10 angle. */
  368.         private static final double E10_0    =  15.134;

  369.         /** Rate term of the E10 angle. */
  370.         private static final double E10_DOT  =  -0.1589763;

  371.         /** Sine coefficient of the E10 angle. */
  372.         private static final double E10_SIN  = -0.0052;

  373.         /** Cosine coefficient of the E10 angle. */
  374.         private static final double E10_COS  = 0.0008;

  375.         /** Sine coefficient of the E10 angle, for the prime meridian. */
  376.         private static final double E10_W_SIN =  0.0052;

  377.         /** Constant term of the E11 angle. */
  378.         private static final double E11_0    = 119.743;

  379.         /** Rate term of the E11 angle. */
  380.         private static final double E11_DOT  =   0.0036096;

  381.         /** Sine coefficient of the E11 angle, for the prime meridian. */
  382.         private static final double E11_W_SIN =  0.0040;

  383.         /** Constant term of the E12 angle. */
  384.         private static final double E12_0    = 239.961;

  385.         /** Rate term of the E12 angle. */
  386.         private static final double E12_DOT  =   0.1643573;

  387.         /** Sine coefficient of the E12 angle, for the prime meridian. */
  388.         private static final double E12_W_SIN =  0.0019;

  389.         /** Constant term of the E13 angle. */
  390.         private static final double E13_0    =  25.053;

  391.         /** Rate term of the E13 angle. */
  392.         private static final double E13_DOT  =  12.9590088;

  393.         /** Sine coefficient of the E13 angle. */
  394.         private static final double E13_SIN  = 0.0043;

  395.         /** Cosine coefficient of the E13 angle. */
  396.         private static final double E13_COS  = -0.0009;

  397.         /** Sine coefficient of the E13 angle, for the prime meridian. */
  398.         private static final double E13_W_SIN = -0.0044;

  399.         /**
  400.          * Simple constructor.
  401.          *
  402.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  403.          */
  404.         Moon(final TimeScales timeScales) {
  405.             super(timeScales);
  406.         }

  407.         /** {@inheritDoc} */
  408.         public Vector3D getPole(final AbsoluteDate date) {
  409.             final double d = d(date);
  410.             final double t = t(date);

  411.             final SinCos scE01 = FastMath.sinCos(FastMath.toRadians(d * E01_DOT + E01_0));
  412.             final SinCos scE02 = FastMath.sinCos(FastMath.toRadians(d * E02_DOT + E02_0));
  413.             final SinCos scE03 = FastMath.sinCos(FastMath.toRadians(d * E03_DOT + E03_0));
  414.             final SinCos scE04 = FastMath.sinCos(FastMath.toRadians(d * E04_DOT + E04_0));
  415.             final SinCos scE06 = FastMath.sinCos(FastMath.toRadians(d * E06_DOT + E06_0));
  416.             final SinCos scE10 = FastMath.sinCos(FastMath.toRadians(d * E10_DOT + E10_0));
  417.             final SinCos scE13 = FastMath.sinCos(FastMath.toRadians(d * E13_DOT + E13_0));

  418.             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 +
  419.                                                    scE01.sin() * E01_SIN +
  420.                                                    scE02.sin() * E02_SIN +
  421.                                                    scE03.sin() * E03_SIN +
  422.                                                    scE04.sin() * E04_SIN +
  423.                                                    scE06.sin() * E06_SIN +
  424.                                                    scE10.sin() * E10_SIN +
  425.                                                    scE13.sin() * E13_SIN),
  426.                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0 +
  427.                                                    scE01.cos() * E01_COS +
  428.                                                    scE02.cos() * E02_COS +
  429.                                                    scE03.cos() * E03_COS +
  430.                                                    scE04.cos() * E04_COS +
  431.                                                    scE06.cos() * E06_COS +
  432.                                                    FastMath.cos(FastMath.toRadians(d * E07_DOT + E07_0)) * E07_COS +  // only the cosine is needed
  433.                                                    scE10.cos() * E10_COS +
  434.                                                    scE13.cos() * E13_COS));
  435.         }

  436.         /** {@inheritDoc} */
  437.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  438.             final T d = d(date);
  439.             final T t = t(date);

  440.             final FieldSinCos<T> scE01 = FastMath.sinCos(FastMath.toRadians(d.multiply(E01_DOT).add(E01_0)));
  441.             final FieldSinCos<T> scE02 = FastMath.sinCos(FastMath.toRadians(d.multiply(E02_DOT).add(E02_0)));
  442.             final FieldSinCos<T> scE03 = FastMath.sinCos(FastMath.toRadians(d.multiply(E03_DOT).add(E03_0)));
  443.             final FieldSinCos<T> scE04 = FastMath.sinCos(FastMath.toRadians(d.multiply(E04_DOT).add(E04_0)));
  444.             final FieldSinCos<T> scE06 = FastMath.sinCos(FastMath.toRadians(d.multiply(E06_DOT).add(E06_0)));
  445.             final FieldSinCos<T> scE10 = FastMath.sinCos(FastMath.toRadians(d.multiply(E10_DOT).add(E10_0)));
  446.             final FieldSinCos<T> scE13 = FastMath.sinCos(FastMath.toRadians(d.multiply(E13_DOT).add(E13_0)));

  447.             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0).
  448.                                                  add(scE01.sin().multiply(E01_SIN)).
  449.                                                  add(scE02.sin().multiply(E02_SIN)).
  450.                                                  add(scE03.sin().multiply(E03_SIN)).
  451.                                                  add(scE04.sin().multiply(E04_SIN)).
  452.                                                  add(scE06.sin().multiply(E06_SIN)).
  453.                                                  add(scE10.sin().multiply(E10_SIN)).
  454.                                                  add(scE13.sin().multiply(E13_SIN))),
  455.                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0).
  456.                                                  add(scE01.cos().multiply(E01_COS)).
  457.                                                  add(scE02.cos().multiply(E02_COS)).
  458.                                                  add(scE03.cos().multiply(E03_COS)).
  459.                                                  add(scE04.cos().multiply(E04_COS)).
  460.                                                  add(scE06.cos().multiply(E06_COS)).
  461.                                                  add(FastMath.toRadians(d.multiply(E07_DOT).add(E07_0)).cos().multiply(E07_COS)).// only the cosine is needed
  462.                                                  add(scE10.cos().multiply(E10_COS)).
  463.                                                  add(scE13.cos().multiply(E13_COS))));
  464.         }

  465.         /** {@inheritDoc} */
  466.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  467.             final double d = d(date);

  468.             return FastMath.toRadians(d * (d * W_DOT_DOT + W_DOT) + W_0 +
  469.                                       FastMath.sin(FastMath.toRadians(d * E01_DOT + E01_0)) * E01_W_SIN +
  470.                                       FastMath.sin(FastMath.toRadians(d * E02_DOT + E02_0)) * E02_W_SIN +
  471.                                       FastMath.sin(FastMath.toRadians(d * E03_DOT + E03_0)) * E03_W_SIN +
  472.                                       FastMath.sin(FastMath.toRadians(d * E04_DOT + E04_0)) * E04_W_SIN +
  473.                                       FastMath.sin(FastMath.toRadians(d * E05_DOT + E05_0)) * E05_W_SIN +
  474.                                       FastMath.sin(FastMath.toRadians(d * E06_DOT + E06_0)) * E06_W_SIN +
  475.                                       FastMath.sin(FastMath.toRadians(d * E07_DOT + E07_0)) * E07_W_SIN +
  476.                                       FastMath.sin(FastMath.toRadians(d * E08_DOT + E08_0)) * E08_W_SIN +
  477.                                       FastMath.sin(FastMath.toRadians(d * E09_DOT + E09_0)) * E09_W_SIN +
  478.                                       FastMath.sin(FastMath.toRadians(d * E10_DOT + E10_0)) * E10_W_SIN +
  479.                                       FastMath.sin(FastMath.toRadians(d * E11_DOT + E11_0)) * E11_W_SIN +
  480.                                       FastMath.sin(FastMath.toRadians(d * E12_DOT + E12_0)) * E12_W_SIN +
  481.                                       FastMath.sin(FastMath.toRadians(d * E13_DOT + E13_0)) * E13_W_SIN);
  482.         }

  483.         /** {@inheritDoc} */
  484.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  485.             final T d = d(date);
  486.             return FastMath.toRadians(d.multiply(d.multiply(W_DOT_DOT).add(W_DOT)).add(W_0).
  487.                                       add(FastMath.toRadians(d.multiply(E01_DOT).add(E01_0)).sin().multiply(E01_W_SIN)).
  488.                                       add(FastMath.toRadians(d.multiply(E02_DOT).add(E02_0)).sin().multiply(E02_W_SIN)).
  489.                                       add(FastMath.toRadians(d.multiply(E03_DOT).add(E03_0)).sin().multiply(E03_W_SIN)).
  490.                                       add(FastMath.toRadians(d.multiply(E04_DOT).add(E04_0)).sin().multiply(E04_W_SIN)).
  491.                                       add(FastMath.toRadians(d.multiply(E05_DOT).add(E05_0)).sin().multiply(E05_W_SIN)).
  492.                                       add(FastMath.toRadians(d.multiply(E06_DOT).add(E06_0)).sin().multiply(E06_W_SIN)).
  493.                                       add(FastMath.toRadians(d.multiply(E07_DOT).add(E07_0)).sin().multiply(E07_W_SIN)).
  494.                                       add(FastMath.toRadians(d.multiply(E08_DOT).add(E08_0)).sin().multiply(E08_W_SIN)).
  495.                                       add(FastMath.toRadians(d.multiply(E09_DOT).add(E09_0)).sin().multiply(E09_W_SIN)).
  496.                                       add(FastMath.toRadians(d.multiply(E10_DOT).add(E10_0)).sin().multiply(E10_W_SIN)).
  497.                                       add(FastMath.toRadians(d.multiply(E11_DOT).add(E11_0)).sin().multiply(E11_W_SIN)).
  498.                                       add(FastMath.toRadians(d.multiply(E12_DOT).add(E12_0)).sin().multiply(E12_W_SIN)).
  499.                                       add(FastMath.toRadians(d.multiply(E13_DOT).add(E13_0)).sin().multiply(E13_W_SIN)));
  500.         }

  501.     }

  502.     /** IAU pole and prime meridian model for Mars. */
  503.     private static class Mars extends PredefinedIAUPoles {

  504.         /** Serializable UID. */
  505.         private static final long serialVersionUID = 20200130L;

  506.         /** Constant term of the right ascension of the pole. */
  507.         private static final double ALPHA_0 = 317.68143;

  508.         /** Rate term of the right ascension of the pole. */
  509.         private static final double ALPHA_DOT = -0.1061;

  510.         /** Constant term of the declination of the pole. */
  511.         private static final double DELTA_0 =  52.88650;

  512.         /** Rate term of the declination of the pole. */
  513.         private static final double DELTA_DOT = -0.0609;

  514.         /** Constant term of the prime meridian. */
  515.         private static final double W_0 = 176.630;

  516.         /** Rate term of the prime meridian. */
  517.         private static final double W_DOT = 350.89198226;

  518.         /**
  519.          * Simple constructor.
  520.          *
  521.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  522.          */
  523.         Mars(final TimeScales timeScales) {
  524.             super(timeScales);
  525.         }

  526.         /** {@inheritDoc} */
  527.         public Vector3D getPole(final AbsoluteDate date) {
  528.             final double t = t(date);
  529.             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
  530.                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
  531.         }

  532.         /** {@inheritDoc} */
  533.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  534.             final T t = t(date);
  535.             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
  536.                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
  537.         }

  538.         /** {@inheritDoc} */
  539.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  540.             return FastMath.toRadians(d(date) * W_DOT + W_0);
  541.         }

  542.         /** {@inheritDoc} */
  543.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  544.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
  545.         }

  546.     }

  547.     /** IAU pole and prime meridian model for Jupiter. */
  548.     private static class Jupiter extends PredefinedIAUPoles {

  549.         /** Serializable UID. */
  550.         private static final long serialVersionUID = 20200130L;

  551.         /** Constant term of the right ascension of the pole. */
  552.         private static final double ALPHA_0 = 268.056595;

  553.         /** Rate term of the right ascension of the pole. */
  554.         private static final double ALPHA_DOT = -0.006499;

  555.         /** Constant term of the declination of the pole. */
  556.         private static final double DELTA_0 = 64.495303;

  557.         /** Rate term of the declination of the pole. */
  558.         private static final double DELTA_DOT = 0.002413;

  559.         /** Constant term of the ja angle. */
  560.         private static final double JA_0 =  99.360714;

  561.         /** Rate term of the ja angle. */
  562.         private static final double JA_DOT = 4850.4046;

  563.         /** Sine coefficient of the ja angle. */
  564.         private static final double JA_SIN = 0.000117;

  565.         /** Cosine coefficient of the ja angle. */
  566.         private static final double JA_COS = 0.000050;

  567.         /** Constant term of the jb angle. */
  568.         private static final double JB_0 = 175.895369;

  569.         /** Rate term of the jb angle. */
  570.         private static final double JB_DOT = 1191.9605;

  571.         /** Sine coefficient of the jb angle. */
  572.         private static final double JB_SIN = 0.000938;

  573.         /** Cosine coefficient of the jb angle. */
  574.         private static final double JB_COS = 0.000404;

  575.         /** Constant term of the jc angle. */
  576.         private static final double JC_0 = 300.323162;

  577.         /** Rate term of the jc angle. */
  578.         private static final double JC_DOT = 262.5475;

  579.         /** Sine coefficient of the jc angle. */
  580.         private static final double JC_SIN = 0.001432;

  581.         /** Cosine coefficient of the jc angle. */
  582.         private static final double JC_COS = 0.000617;

  583.         /** Constant term of the jd angle. */
  584.         private static final double JD_0 = 114.012305;

  585.         /** Rate term of the jd angle. */
  586.         private static final double JD_DOT = 6070.2476;

  587.         /** Sine coefficient of the jd angle. */
  588.         private static final double JD_SIN = 0.000030;

  589.         /** Cosine coefficient of the jd angle. */
  590.         private static final double JD_COS = -0.000013;

  591.         /** Constant term of the je angle. */
  592.         private static final double JE_0 = 49.511251;

  593.         /** Rate term of the je angle. */
  594.         private static final double JE_DOT = 64.3000;

  595.         /** Sine coefficient of the je angle. */
  596.         private static final double JE_SIN = 0.002150;

  597.         /** Cosine coefficient of the je angle. */
  598.         private static final double JE_COS = 0.000926;

  599.         /** Constant term of the prime meridian. */
  600.         private static final double W_0 = 284.95;

  601.         /** Rate term of the prime meridian. */
  602.         private static final double W_DOT = 870.5360000;

  603.         /**
  604.          * Simple constructor.
  605.          *
  606.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  607.          */
  608.         Jupiter(final TimeScales timeScales) {
  609.             super(timeScales);
  610.         }

  611.         /** {@inheritDoc} */
  612.         public Vector3D getPole(final AbsoluteDate date) {

  613.             final double t = t(date);
  614.             final double ja = FastMath.toRadians(t * JA_DOT + JA_0);
  615.             final double jb = FastMath.toRadians(t * JB_DOT + JB_0);
  616.             final double jc = FastMath.toRadians(t * JC_DOT + JC_0);
  617.             final double jd = FastMath.toRadians(t * JD_DOT + JD_0);
  618.             final double je = FastMath.toRadians(t * JE_DOT + JE_0);

  619.             final SinCos scJa = FastMath.sinCos(ja);
  620.             final SinCos scJb = FastMath.sinCos(jb);
  621.             final SinCos scJc = FastMath.sinCos(jc);
  622.             final SinCos scJd = FastMath.sinCos(jd);
  623.             final SinCos scJe = FastMath.sinCos(je);

  624.             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 +
  625.                                                    scJa.sin() * JA_SIN +
  626.                                                    scJb.sin() * JB_SIN +
  627.                                                    scJc.sin() * JC_SIN +
  628.                                                    scJd.sin() * JD_SIN +
  629.                                                    scJe.sin() * JE_SIN),
  630.                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0 +
  631.                                                    scJa.cos() * JA_COS +
  632.                                                    scJb.cos() * JB_COS +
  633.                                                    scJc.cos() * JC_COS +
  634.                                                    scJd.cos() * JD_COS +
  635.                                                    scJe.cos() * JE_COS));
  636.         }

  637.         /** {@inheritDoc} */
  638.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {

  639.             final T t = t(date);
  640.             final T ja = FastMath.toRadians(t.multiply(JA_DOT).add(JA_0));
  641.             final T jb = FastMath.toRadians(t.multiply(JB_DOT).add(JB_0));
  642.             final T jc = FastMath.toRadians(t.multiply(JC_DOT).add(JC_0));
  643.             final T jd = FastMath.toRadians(t.multiply(JD_DOT).add(JD_0));
  644.             final T je = FastMath.toRadians(t.multiply(JE_DOT).add(JE_0));

  645.             final FieldSinCos<T> scJa = FastMath.sinCos(ja);
  646.             final FieldSinCos<T> scJb = FastMath.sinCos(jb);
  647.             final FieldSinCos<T> scJc = FastMath.sinCos(jc);
  648.             final FieldSinCos<T> scJd = FastMath.sinCos(jd);
  649.             final FieldSinCos<T> scJe = FastMath.sinCos(je);

  650.             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0).
  651.                                                  add(scJa.sin().multiply(JA_SIN)).
  652.                                                  add(scJb.sin().multiply(JB_SIN)).
  653.                                                  add(scJc.sin().multiply(JC_SIN)).
  654.                                                  add(scJd.sin().multiply(JD_SIN)).
  655.                                                  add(scJe.sin().multiply(JE_SIN))),
  656.                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0).
  657.                                                  add(scJa.cos().multiply(JA_COS)).
  658.                                                  add(scJb.cos().multiply(JB_COS)).
  659.                                                  add(scJc.cos().multiply(JC_COS)).
  660.                                                  add(scJd.cos().multiply(JD_COS)).
  661.                                                  add(scJe.cos().multiply(JE_COS))));

  662.         }

  663.         /** {@inheritDoc} */
  664.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  665.             return FastMath.toRadians(d(date) * W_DOT + W_0);
  666.         }

  667.         /** {@inheritDoc} */
  668.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  669.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
  670.         }

  671.     }

  672.     /** IAU pole and prime meridian model for Saturn. */
  673.     private static class Saturn extends PredefinedIAUPoles {

  674.         /** Serializable UID. */
  675.         private static final long serialVersionUID = 20200130L;

  676.         /** Constant term of the right ascension of the pole. */
  677.         private static final double ALPHA_0 = 40.589;

  678.         /** Rate term of the right ascension of the pole. */
  679.         private static final double ALPHA_DOT = -0.036;

  680.         /** Constant term of the declination of the pole. */
  681.         private static final double DELTA_0 = 83.537;

  682.         /** Rate term of the declination of the pole. */
  683.         private static final double DELTA_DOT = -0.004;

  684.         /** Constant term of the prime meridian. */
  685.         private static final double W_0 = 38.90;

  686.         /** Rate term of the prime meridian. */
  687.         private static final double W_DOT = 810.7939024;

  688.         /**
  689.          * Simple constructor.
  690.          *
  691.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  692.          */
  693.         Saturn(final TimeScales timeScales) {
  694.             super(timeScales);
  695.         }

  696.         /** {@inheritDoc} */
  697.         public Vector3D getPole(final AbsoluteDate date) {
  698.             final double t = t(date);
  699.             return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
  700.                                 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
  701.         }

  702.         /** {@inheritDoc} */
  703.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  704.             final T t = t(date);
  705.             return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
  706.                                        FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
  707.         }

  708.         /** {@inheritDoc} */
  709.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  710.             return FastMath.toRadians(d(date) * W_DOT + W_0);
  711.         }

  712.         /** {@inheritDoc} */
  713.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  714.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
  715.         }

  716.     }

  717.     /** IAU pole and prime meridian model for Uranus. */
  718.     private static class Uranus extends PredefinedIAUPoles {

  719.         /** Serializable UID. */
  720.         private static final long serialVersionUID = 20200130L;

  721.         /** Constant term of the prime meridian. */
  722.         private static final double W_0 = 203.81;

  723.         /** Rate term of the prime meridian. */
  724.         private static final double W_DOT = -501.1600928;

  725.         /** Fixed pole. */
  726.         private final Vector3D pole = new Vector3D(FastMath.toRadians(257.311),
  727.                                                    FastMath.toRadians(-15.175));

  728.         /**
  729.          * Simple constructor.
  730.          *
  731.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  732.          */
  733.         Uranus(final TimeScales timeScales) {
  734.             super(timeScales);
  735.         }

  736.         /** {@inheritDoc} */
  737.         public Vector3D getPole(final AbsoluteDate date) {
  738.             return pole;
  739.         }

  740.         /** {@inheritDoc} */
  741.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  742.             return new FieldVector3D<>(date.getField(), pole);
  743.         }

  744.         /** {@inheritDoc} */
  745.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  746.             return FastMath.toRadians(d(date) * W_DOT + W_0);
  747.         }

  748.         /** {@inheritDoc} */
  749.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  750.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
  751.         }

  752.     }

  753.     /** IAU pole and prime meridian model for Neptune. */
  754.     private static class Neptune extends PredefinedIAUPoles {

  755.         /** Serializable UID. */
  756.         private static final long serialVersionUID = 20200130L;

  757.         /** Constant term of the right ascension of the pole. */
  758.         private static final double ALPHA_0 = 299.36;

  759.         /** Sine term of the right ascension of the pole. */
  760.         private static final double ALPHA_SIN = 0.70;

  761.         /** Constant term of the declination of the pole. */
  762.         private static final double DELTA_0 = 43.46;

  763.         /** Cosine term of the declination of the pole. */
  764.         private static final double DELTA_COS = -0.51;

  765.         /** Constant term of the prime meridian. */
  766.         private static final double W_0 = 253.18;

  767.         /** Rate term of the prime meridian. */
  768.         private static final double W_DOT = 536.3128492;

  769.         /** Sine term of the prime meridian. */
  770.         private static final double W_SIN = -0.48;

  771.         /** Constant term of the N angle. */
  772.         private static final double N_0   = 357.85;

  773.         /** Rate term of the M1 angle. */
  774.         private static final double N_DOT = 52.316;

  775.         /**
  776.          * Simple constructor.
  777.          *
  778.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  779.          */
  780.         Neptune(final TimeScales timeScales) {
  781.             super(timeScales);
  782.         }

  783.         /** {@inheritDoc} */
  784.         public Vector3D getPole(final AbsoluteDate date) {
  785.             final double n  = FastMath.toRadians(t(date) * N_DOT + N_0);
  786.             final SinCos sc = FastMath.sinCos(n);
  787.             return new Vector3D(FastMath.toRadians(sc.sin() * ALPHA_SIN + ALPHA_0),
  788.                                 FastMath.toRadians(sc.cos() * DELTA_COS + DELTA_0));
  789.         }

  790.         /** {@inheritDoc} */
  791.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  792.             final T n = FastMath.toRadians(t(date).multiply(N_DOT).add(N_0));
  793.             final FieldSinCos<T> sc = FastMath.sinCos(n);
  794.             return new FieldVector3D<>(FastMath.toRadians(sc.sin().multiply(ALPHA_SIN).add(ALPHA_0)),
  795.                                        FastMath.toRadians(sc.cos().multiply(DELTA_COS).add(DELTA_0)));
  796.         }

  797.         /** {@inheritDoc} */
  798.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  799.             final double n = FastMath.toRadians(t(date) * N_DOT + N_0);
  800.             return FastMath.toRadians(d(date) * W_DOT + FastMath.sin(n) * W_SIN + W_0);
  801.         }

  802.         /** {@inheritDoc} */
  803.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  804.             final T n = FastMath.toRadians(t(date).multiply(N_DOT).add(N_0));
  805.             return FastMath.toRadians(d(date).multiply(W_DOT).add(n.sin().multiply(W_SIN)).add(W_0));
  806.         }

  807.     }

  808.     /** IAU pole and prime meridian model for Pluto. */
  809.     private static class Pluto extends PredefinedIAUPoles {

  810.         /** Serializable UID. */
  811.         private static final long serialVersionUID = 20200130L;

  812.         /** Constant term of the prime meridian. */
  813.         private static final double W_0 = 302.695;

  814.         /** Rate term of the prime meridian. */
  815.         private static final double W_DOT = 56.3625225;

  816.         /** Fixed pole. */
  817.         private final Vector3D pole = new Vector3D(FastMath.toRadians(132.993),
  818.                                                    FastMath.toRadians(-6.163));

  819.         /**
  820.          * Simple constructor.
  821.          *
  822.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  823.          */
  824.         Pluto(final TimeScales timeScales) {
  825.             super(timeScales);
  826.         }

  827.         /** {@inheritDoc} */
  828.         public Vector3D getPole(final AbsoluteDate date) {
  829.             return pole;
  830.         }

  831.         /** {@inheritDoc} */
  832.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  833.             return new FieldVector3D<>(date.getField(), pole);
  834.         }

  835.         /** {@inheritDoc} */
  836.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  837.             return FastMath.toRadians(d(date) * W_DOT + W_0);
  838.         }

  839.         /** {@inheritDoc} */
  840.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  841.             return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
  842.         }

  843.     }

  844.     /** Default IAUPole implementation for barycenters.
  845.      * <p>
  846.      * This implementation defines directions such that the inertially oriented and body
  847.      * oriented frames are identical and aligned with GCRF. It is used for example
  848.      * to define the ICRF.
  849.      * </p>
  850.      */
  851.     private static class GcrfAligned extends PredefinedIAUPoles {

  852.         /** Serializable UID. */
  853.         private static final long serialVersionUID = 20200130L;

  854.         /**
  855.          * Simple constructor.
  856.          *
  857.          * @param timeScales to use when computing the pole, including TDB and J2000.0.
  858.          */
  859.         GcrfAligned(final TimeScales timeScales) {
  860.             super(timeScales);
  861.         }

  862.         /** {@inheritDoc} */
  863.         public Vector3D getPole(final AbsoluteDate date) {
  864.             return Vector3D.PLUS_K;
  865.         }

  866.         /** {@inheritDoc} */
  867.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
  868.             return FieldVector3D.getPlusK(date.getField());
  869.         }

  870.         /** {@inheritDoc} */
  871.         @Override
  872.         public Vector3D getNode(final AbsoluteDate date) {
  873.             return Vector3D.PLUS_I;
  874.         }

  875.         /** {@inheritDoc} */
  876.         @Override
  877.         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getNode(final FieldAbsoluteDate<T> date) {
  878.             return FieldVector3D.getPlusI(date.getField());
  879.         }

  880.         /** {@inheritDoc} */
  881.         public double getPrimeMeridianAngle(final AbsoluteDate date) {
  882.             return 0;
  883.         }

  884.         /** {@inheritDoc} */
  885.         public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
  886.             return date.getField().getZero();
  887.         }

  888.     }


  889.     /** Get a predefined IAU pole.
  890.      * @param body body identifier
  891.      * @param timeScales to use when computing the pole, including TDB and J2000.0.
  892.      * @return predefined IAU pole
  893.      */
  894.     public static PredefinedIAUPoles getIAUPole(final EphemerisType body,
  895.                                                 final TimeScales timeScales) {

  896.         switch (body) {
  897.             case SUN :
  898.                 return new Sun(timeScales);
  899.             case MERCURY :
  900.                 return new Mercury(timeScales);
  901.             case VENUS :
  902.                 return new Venus(timeScales);
  903.             case EARTH :
  904.                 return new Earth(timeScales);
  905.             case MOON :
  906.                 return new Moon(timeScales);
  907.             case MARS :
  908.                 return new Mars(timeScales);
  909.             case JUPITER :
  910.                 return new Jupiter(timeScales);
  911.             case SATURN :
  912.                 return new Saturn(timeScales);
  913.             case URANUS :
  914.                 return new Uranus(timeScales);
  915.             case NEPTUNE :
  916.                 return new Neptune(timeScales);
  917.             case PLUTO :
  918.                 return new Pluto(timeScales);
  919.             default :
  920.                 return new GcrfAligned(timeScales);
  921.         }
  922.     }

  923.     /**
  924.      * List of predefined IAU poles.
  925.      *
  926.      * @param timeScales to use when computing the pole, including TDB and J2000.0.
  927.      * @return the poles.
  928.      */
  929.     static List<PredefinedIAUPoles> values(final TimeScales timeScales) {
  930.         final List<PredefinedIAUPoles> values = new ArrayList<>(12);
  931.         values.add(new Sun(timeScales));
  932.         values.add(new Mercury(timeScales));
  933.         values.add(new Venus(timeScales));
  934.         values.add(new Earth(timeScales));
  935.         values.add(new Moon(timeScales));
  936.         values.add(new Mars(timeScales));
  937.         values.add(new Jupiter(timeScales));
  938.         values.add(new Saturn(timeScales));
  939.         values.add(new Uranus(timeScales));
  940.         values.add(new Neptune(timeScales));
  941.         values.add(new Pluto(timeScales));
  942.         values.add(new GcrfAligned(timeScales));
  943.         return values;
  944.     }

  945.     /** Compute the interval in julian centuries from standard epoch.
  946.      * @param date date
  947.      * @return interval between date and standard epoch in julian centuries
  948.      */
  949.     protected double t(final AbsoluteDate date) {
  950.         return date.offsetFrom(timeScales.getJ2000Epoch(), timeScales.getTDB()) /
  951.                 Constants.JULIAN_CENTURY;
  952.     }

  953.     /** Compute the interval in julian centuries from standard epoch.
  954.      * @param date date
  955.      * @param <T> type of the filed elements
  956.      * @return interval between date and standard epoch in julian centuries
  957.      */
  958.     protected <T extends CalculusFieldElement<T>> T t(final FieldAbsoluteDate<T> date) {
  959.         final FieldAbsoluteDate<T> j2000Epoch =
  960.                 new FieldAbsoluteDate<>(date.getField(), timeScales.getJ2000Epoch());
  961.         return date.offsetFrom(j2000Epoch, timeScales.getTDB()).divide(Constants.JULIAN_CENTURY);
  962.     }

  963.     /** Compute the interval in julian days from standard epoch.
  964.      * @param date date
  965.      * @return interval between date and standard epoch in julian days
  966.      */
  967.     protected double d(final AbsoluteDate date) {
  968.         return date.offsetFrom(timeScales.getJ2000Epoch(), timeScales.getTDB()) /
  969.                 Constants.JULIAN_DAY;
  970.     }

  971.     /** Compute the interval in julian days from standard epoch.
  972.      * @param date date
  973.      * @param <T> type of the filed elements
  974.      * @return interval between date and standard epoch in julian days
  975.      */
  976.     protected <T extends CalculusFieldElement<T>> T d(final FieldAbsoluteDate<T> date) {
  977.         final FieldAbsoluteDate<T> j2000Epoch =
  978.                 new FieldAbsoluteDate<>(date.getField(), timeScales.getJ2000Epoch());
  979.         return date.offsetFrom(j2000Epoch, timeScales.getTDB()).divide(Constants.JULIAN_DAY);
  980.     }

  981. }