Esempio n. 1
0
        public static double epsiln_owen_1986(JulianDayNumber tjd)
        {
            int i;

            double[] k = new double[10], tau = new double[10];
            var(t0, icof) = get_owen_t0_icof(tjd);
            double eps = 0;

            tau[0] = 0;
            tau[1] = (tjd - t0).Raw / 36525.0 / 40.0;
            for (i = 2; i <= 9; i++)
            {
                tau[i] = tau[1] * tau[i - 1];
            }
            k[0] = 1;
            k[1] = tau[1];
            k[2] = 2 * tau[2] - 1;
            k[3] = 4 * tau[3] - 3 * tau[1];
            k[4] = 8 * tau[4] - 8 * tau[2] + 1;
            k[5] = 16 * tau[5] - 20 * tau[3] + 5 * tau[1];
            k[6] = 32 * tau[6] - 48 * tau[4] + 18 * tau[2] - 1;
            k[7] = 64 * tau[7] - 112 * tau[5] + 56 * tau[3] - 7 * tau[1];
            k[8] = 128 * tau[8] - 256 * tau[6] + 160 * tau[4] - 32 * tau[2] + 1;
            k[9] = 256 * tau[9] - 576 * tau[7] + 432 * tau[5] - 120 * tau[3] + 9 * tau[1];
            for (i = 0; i < 10; i++)
            {
                eps += (k[i] * owen_eps0_coef[icof][i]);
            }
            return(eps);
        }
Esempio n. 2
0
 private Epsilon(JulianDayNumber date, double eps)
 {
     Date   = date;
     Eps    = eps;
     SinEps = Math.Sin(eps);
     CosEps = Math.Cos(eps);
 }
        /// <see cref="deltat_longterm_morrison_stephenson"/>
        public static double Calc(JulianDayNumber tjd)
        {
            var    gregorianYear = tjd.GetGregorianYear();
            double u             = (gregorianYear - 1820) / 100.0;

            return(-20 + 32 * u * u);
        }
Esempio n. 4
0
        private void ReadPlanetConstants(SEFileData data)
        {
            foreach (var ipli in data.PlanetNumbers)
            {
                var pdp = new PlanetData();

                pdp.InternalBodyNumber = ipli;
                pdp.FileIndexStart     = ReadInt32();
                pdp.Flags = (PlanetFlags)_stream.ReadByte();
                pdp.CoefficientsNumber  = _stream.ReadByte();
                pdp.NormalizationFactor = ReadInt32() / 1000.0;
                var doubles = ReadDoubles(10);
                pdp.StartDate         = JulianDayNumber.FromRaw(doubles[0]);
                pdp.EndDate           = JulianDayNumber.FromRaw(doubles[1]);
                pdp.SegmentSize       = doubles[2];
                pdp.IndexEntriesCount = (int)((doubles[1] - doubles[0] + 0.1) / doubles[2]);
                pdp.ElementsEpoch     = doubles[3];
                pdp.Prot     = doubles[4];
                pdp.Dprot    = doubles[5];
                pdp.Qrot     = doubles[6];
                pdp.Dqrot    = doubles[7];
                pdp.Perigee  = doubles[8];
                pdp.DPerigee = doubles[9];
                if (pdp.Flags.HasFlag(PlanetFlags.Ellipse))
                {
                    pdp.ReferenceEllipseCoefficients = ReadDoubles(2 * pdp.CoefficientsNumber);
                }

                var index = ipli >= SEConsts.AseroidOffset
                                        ? InternalPlanets.AnyBody
                                        : (InternalPlanets)ipli;
                data.PlanetsData[index] = pdp;
            }
        }
Esempio n. 5
0
        public static (double dpre, double deps) swi_ldp_peps(JulianDayNumber tjd)
        {
            int    i;
            int    npol = NPOL_PEPS;
            int    nper = NPER_PEPS;
            double t, p, q, w, a, s, c;

            t = (tjd - JulianDayNumber.J2000).Raw / 36525.0;
            p = 0;
            q = 0;
            /* periodic terms */
            for (i = 0; i < nper; i++)
            {
                w  = Consts.TwoPi * t;
                a  = w / peper[0][i];
                s  = Math.Sin(a);
                c  = Math.Cos(a);
                p += c * peper[1][i] + s * peper[3][i];
                q += c * peper[2][i] + s * peper[4][i];
            }
            /* polynomial terms */
            w = 1;
            for (i = 0; i < npol; i++)
            {
                p += pepol[i][0] * w;
                q += pepol[i][1] * w;
                w *= t;
            }
            /* both to radians */
            p *= AS2R;
            q *= AS2R;
            return(p, q);
        }
Esempio n. 6
0
        /* precession matrix */
        public static double[] pre_pmat(JulianDayNumber tjd)
        {
            //tjd = 1219339.078000;
            /*equator pole */
            var peqr = pre_pequ(tjd);
            /* ecliptic pole */
            var pecl = pre_pecl(tjd);
            /* equinox */
            var v = Calculus.CrossProduct(peqr, pecl);
            var w = Math.Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);

            double[] eqx = new[]
            {
                v[0] / w,
                v[1] / w,
                v[2] / w,
            };
            v = Calculus.CrossProduct(peqr, eqx);
            return(new[]
            {
                eqx[0],
                eqx[1],
                eqx[2],
                v[0],
                v[1],
                v[2],
                peqr[0],
                peqr[1],
                peqr[2],
            });
        }
Esempio n. 7
0
        public static double Calc(JulianDayNumber julianDay, double tidalAcceleration)
        {
            var    gregorianYear = julianDay.GetGregorianYear();
            double dt            = 0.0;

            if (julianDay >= J2016 || julianDay < JMinus720)
            {
                var t = (gregorianYear - 1825) / 100.0;
                dt = -320 + 32.5 * t * t;
                if (julianDay >= J2016)
                {
                    dt += 269.4790417;                     // to make curve continous on 1 Jan 2016 (D. Koch)
                }
                else
                {
                    dt -= 179.7337208;                     // to make curve continous on 1 Jan -720 (D. Koch)
                }
            }
            else
            {
                for (int i = 0; i < _coefficients.Length; i++)
                {
                    ref var data = ref _coefficients[i];
                    if (julianDay < data.End)
                    {
                        var t = (double)(julianDay - data.Begin) / (double)(data.End - data.Begin);
                        dt = data.Coef1 + data.Coef2 * t + data.Coef3 * t * t + data.Coef4 * t * t * t;
                    }
                }
            }
Esempio n. 8
0
        /// <summary>
        /// start and end epoch of file
        /// </summary>
        private (JulianDayNumber, JulianDayNumber) ReadFilePeriod()
        {
            var    buff  = ReadDoubles(2);
            double start = buff[0];
            double end   = buff[1];

            return(JulianDayNumber.FromRaw(start), JulianDayNumber.FromRaw(end));
        }
Esempio n. 9
0
        public SEFileSegment(JulianDayNumber start, JulianDayNumber size, double[] coefficients, int evaluateCoefficientsCount)
        {
            Start         = start;
            Size          = size;
            _coefficients = coefficients;

            var partSize = coefficients.Length / 3;

            LongitudeCoefficients = new ArraySegment <double>(_coefficients, 0, evaluateCoefficientsCount);
            LatitudeCoefficients  = new ArraySegment <double>(_coefficients, partSize, evaluateCoefficientsCount);
            DistanceCoefficients  = new ArraySegment <double>(_coefficients, partSize * 2, evaluateCoefficientsCount);
        }
        /// <summary>
        /// Stephenson & Morrison (2004)
        /// </summary>
        public static double Calc(JulianDayNumber tjd, double tid_acc)
        {
            double ans = 0, ans2, ans3;
            double p, B, dd;
            double tjd0;
            int    iy;
            double Y = tjd.GetGregorianYear();

            /* before -1000:
             * formula by Stephenson & Morrison (2004; p. 335) but adjusted to fit the
             * starting point of table dt2. */
            if (Y < DeltaTTabulated.Tab2Start)
            {
                // before -1000
                ans = DeltaTLongtermMorrisonStephenson.Calc(tjd);
                ans = TidalAcceleration.AdjustForTidalAcceleration(ans, Y, tid_acc, TidalAccelerationMode.Const26, false);
                /* transition from formula to table over 100 years */
                if (Y >= DeltaTTabulated.Tab2Start - 100)
                {
                    /* starting value of table dt2: */
                    ans2 = TidalAcceleration.AdjustForTidalAcceleration(DeltaTTabulated.dt2[0], DeltaTTabulated.Tab2Start, tid_acc, TidalAccelerationMode.Const26, false);
                    /* value of formula at epoch TAB2_START */

                    /* B = (TAB2_START - LTERM_EQUATION_YSTART) * 0.01;
                     * ans3 = -20 + LTERM_EQUATION_COEFF * B * B;*/
                    tjd0 = (DeltaTTabulated.Tab2Start - 2000) * 365.2425 + (double)JulianDayNumber.J2000;
                    ans3 = DeltaTLongtermMorrisonStephenson.Calc(JulianDayNumber.FromRaw(tjd0));
                    ans3 = TidalAcceleration.AdjustForTidalAcceleration(ans3, Y, tid_acc, TidalAccelerationMode.Const26, false);
                    dd   = ans3 - ans2;
                    B    = (Y - (DeltaTTabulated.Tab2Start - 100)) * 0.01;
                    /* fit to starting point of table dt2. */
                    ans -= dd * B;
                }
            }

            /* between -1000 and 1600:
             * linear interpolation between values of table dt2 (Stephenson & Morrison 2004) */
            if (Y >= DeltaTTabulated.Tab2Start && Y < DeltaTTabulated.Tab2End)
            {
                double Yjul = tjd.GetJulianYear();
                p   = Math.Floor(Yjul);
                iy  = (int)((p - DeltaTTabulated.Tab2Start) / DeltaTTabulated.Tab2Step);
                dd  = (Yjul - (DeltaTTabulated.Tab2Start + DeltaTTabulated.Tab2Step * iy)) / DeltaTTabulated.Tab2Step;
                ans = DeltaTTabulated.dt2[iy] + (DeltaTTabulated.dt2[iy + 1] - DeltaTTabulated.dt2[iy]) * dd;
                /* correction for tidal acceleration used by our ephemeris */
                ans = TidalAcceleration.AdjustForTidalAcceleration(ans, Y, tid_acc, TidalAccelerationMode.Const26, false);
            }
            ans /= 86400.0;
            return(ans);
        }
Esempio n. 11
0
        /*
         * Long term high precision precession,
         * according to Vondrak/Capitaine/Wallace, "New precession expressions, valid
         * for long time intervals", in A&A 534, A22(2011).
         */
        /* precession of the ecliptic */
        public static double[] pre_pecl(JulianDayNumber tjd)
        {
            int    i;
            int    npol = NPOL_PECL;
            int    nper = NPER_PECL;
            double t, p, q, w, a, s, c, z;

            t = (tjd - JulianDayNumber.J2000).Raw / 36525.0;
            p = 0;
            q = 0;
            /* periodic terms */
            for (i = 0; i < nper; i++)
            {
                w  = Consts.TwoPi * t;
                a  = w / pqper[0][i];
                s  = Math.Sin(a);
                c  = Math.Cos(a);
                p += c * pqper[1][i] + s * pqper[3][i];
                q += c * pqper[2][i] + s * pqper[4][i];
            }
            /* polynomial terms */
            w = 1;
            for (i = 0; i < npol; i++)
            {
                p += pqpol[i][0] * w;
                q += pqpol[i][1] * w;
                w *= t;
            }
            /* both to radians */
            p *= AS2R;
            q *= AS2R;
            /* ecliptic pole vector */
            z = 1 - p * p - q * q;
            if (z < 0)
            {
                z = 0;
            }
            else
            {
                z = Math.Sqrt(z);
            }
            s = Math.Sin(EPS0);
            c = Math.Cos(EPS0);
            return(new[]
            {
                p,
                -q * c - z * s,
                -q * s + z * c,
            });
        }
Esempio n. 12
0
        private static (JulianDayNumber, int) get_owen_t0_icof(JulianDayNumber tjd)
        {
            int j  = 0;
            var t0 = t0s[0];

            for (int i = 1; i < 5; i++)
            {
                if (tjd.Raw < (t0s[i - 1] + t0s[i]).Raw / 2)
                {
                    ;
                }
                else
                {
                    t0 = t0s[i];
                    j++;
                }
            }
            return(t0, j);
        }
Esempio n. 13
0
        /* precession of the equator */
        public static double[] pre_pequ(JulianDayNumber tjd)
        {
            int    i;
            int    npol = NPOL_PEQU;
            int    nper = NPER_PEQU;
            double t, x, y, w, a, s, c;

            t = (tjd - JulianDayNumber.J2000).Raw / 36525.0;
            x = 0;
            y = 0;
            for (i = 0; i < nper; i++)
            {
                w  = Consts.TwoPi * t;
                a  = w / xyper[0][i];
                s  = Math.Sin(a);
                c  = Math.Cos(a);
                x += c * xyper[1][i] + s * xyper[3][i];
                y += c * xyper[2][i] + s * xyper[4][i];
            }
            /* polynomial terms */
            w = 1;
            for (i = 0; i < npol; i++)
            {
                x += xypol[i][0] * w;
                y += xypol[i][1] * w;
                w *= t;
            }
            x *= AS2R;
            y *= AS2R;
            /* equator pole vector */
            w = x * x + y * y;
            return(new[]
            {
                x,
                y,
                w < 1 ? Math.Sqrt(1 - w) : 0
            });
        }
Esempio n. 14
0
        /// <summary>
        /// Calculate DeltaT
        /// </summary>
        /// <remarks>
        /// delta t is adjusted to the tidal acceleration that is compatible
        /// with the ephemeris mode contained in ephemerisMode and with the ephemeris
        /// files made accessible through swe_set_ephe_path() or swe_set_jplfile().
        /// If ephemerisMode is null, then the default tidal acceleration is ussed(i.e. that of DE431).
        /// </remarks>
        /// <see cref="calc_deltat"/>
        /// <returns>DeltaT (ET - UT) in days</returns>
        public static double Calc(JulianDayNumber julianDay, DeltaTMode deltaTMode, EphemerisMode?ephemerisMode)
        {
            var tidalAcceleration = ephemerisMode is null
                                ? TidalAcceleration.Get(JPLDENumber.Default)
                                : TidalAcceleration.Calculate(ephemerisMode.Value, julianDay, JPLDENumber.Auto);

            if (deltaTMode == DeltaTMode.Stephenson_Etc_2016 && julianDay < JulianDayNumber.J1955)
            {
                double deltaT = DeltaTStephensonEtc2016.Calc(julianDay, tidalAcceleration);
                if (julianDay >= JulianDayNumber.J1952_05_04)
                {
                    deltaT += (1.0 - (double)(JulianDayNumber.J1955 - julianDay) / 1000.0) * 0.6610218 / 86400.0;
                }
                return(deltaT);
            }

            if (deltaTMode == DeltaTMode.Espenak_Meeus_2006 && julianDay < J1633)
            {
                return(DeltaTEspenakMeeus1620.Calc(julianDay, tidalAcceleration));
            }

            var year = julianDay.GetYear();

            // delta t model used in SE 1.72 - 1.76: Stephenson & Morrison 2004; before 1620
            if (deltaTMode == DeltaTMode.Stephenson_Morrison_2004 && year < DeltaTTabulated.TabStart)
            {
                // before 1600:
                if (year < DeltaTTabulated.Tab2End)
                {
                    return(DeltaTStephensonMorrison2004_1600.Calc(julianDay, tidalAcceleration));
                }
                else
                {
                    // between 1600 and 1620:
                    // linear interpolation between end of table dt2 and start of table dt
                    return(DeltaTTabulated.CalcInterpolated(year, julianDay.GetGregorianYear(), tidalAcceleration));
                }
            }

            /* delta t model used before SE 1.64:
             * Stephenson/Morrison 1984 with Borkowski 1988;
             * before 1620 */
            if (deltaTMode == DeltaTMode.Stephenson_Morrison_1984 && year < DeltaTTabulated.TabStart)
            {
                double B;
                double ans;
                if (year >= 948.0)
                {
                    /* Stephenson and Morrison, stated domain is 948 to 1600:
                     * 25.5(centuries from 1800)^2 - 1.9159(centuries from 1955)^2 */
                    B   = 0.01 * (year - 2000.0);
                    ans = (23.58 * B + 100.3) * B + 101.6;
                }
                else
                {
                    /* Borkowski, before 948 and between 1600 and 1620 */
                    B   = 0.01 * (year - 2000.0) + 3.75;
                    ans = 35.0 * B * B + 40.0;
                }
                return(ans / 86400.0);
            }

            /* 1620 - today + a few years (tabend):
             * Tabulated values of deltaT from Astronomical Almanac
             * (AA 1997etc., pp. K8-K9) and from IERS
             * (http://maia.usno.navy.mil/ser7/deltat.data).
             */
            if (year >= DeltaTTabulated.TabStart)
            {
                return(DeltaTTabulated.Calc(julianDay, tidalAcceleration, deltaTMode));
            }

            return(0);
        }
Esempio n. 15
0
        /// <summary>
        /// The tabulated values of deltaT, in hundredths of a second,
        /// were taken from The Astronomical Almanac 1997etc., pp.K8-K9.
        /// Some more recent values are taken from IERS
        /// http://maia.usno.navy.mil/ser7/deltat.data .
        /// </summary>
        /// <remarks>
        /// Bessel's interpolation formula is implemented to obtain fourth
        /// order interpolated values at intermediate times.
        /// The values are adjusted depending on the ephemeris used
        /// and its inherent value of secular tidal acceleration ndot.
        /// Note by Dieter Jan. 2017:
        /// Bessel interpolation assumes equidistant sampling points. However the
        /// sampling points are not equidistant, because they are for first January of
        /// every year and years can have either 365 or 366 days.The interpolation uses
        /// a step width of 365.25 days.As a consequence, in three out of four years
        /// the interpolation does not reproduce the exact values of the sampling points
        /// on the days they refer to.
        /// </remarks>
        /// <see cref="deltat_aa"/>
        public static double Calc(JulianDayNumber tjd, double tid_acc, DeltaTMode mode)
        {
            double ans, ans2 = 0, ans3;
            double p, B, B2, Y, dd;

            double[] d = new double[6];
            int      i, iy, k;

            Y = tjd.GetYear();
            if (Y <= TabEnd)
            {
                // Index into the table.
                p  = Math.Floor(Y);
                iy = (int)(p - TabStart);
                /* Zeroth order estimate is value at start of year */
                ans = dt[iy];
                k   = iy + 1;
                if (k >= TabSize)
                {
                    goto done;                     /* No data, can't go on. */
                }
                /* The fraction of tabulation interval */
                p = Y - p;
                /* First order interpolated value */
                ans += p * (dt[k] - dt[iy]);
                if ((iy - 1 < 0) || (iy + 2 >= TabSize))
                {
                    goto done;                     /* can't do second differences */
                }
                /* Make table of first differences */
                k = iy - 2;
                for (i = 0; i < 5; i++)
                {
                    if ((k < 0) || (k + 1 >= TabSize))
                    {
                        d[i] = 0;
                    }
                    else
                    {
                        d[i] = dt[k + 1] - dt[k];
                    }
                    k += 1;
                }
                /* Compute second differences */
                for (i = 0; i < 4; i++)
                {
                    d[i] = d[i + 1] - d[i];
                }
                B    = 0.25 * p * (p - 1.0);
                ans += B * (d[1] + d[2]);
                if (iy + 2 >= TabSize)
                {
                    goto done;
                }
                /* Compute third differences */
                for (i = 0; i < 3; i++)
                {
                    d[i] = d[i + 1] - d[i];
                }
                B    = 2.0 * B / 3.0;
                ans += (p - 0.5) * B * d[1];
                if ((iy - 2 < 0) || (iy + 3 > TabSize))
                {
                    goto done;
                }
                /* Compute fourth differences */
                for (i = 0; i < 2; i++)
                {
                    d[i] = d[i + 1] - d[i];
                }
                B    = 0.125 * B * (p + 1.0) * (p - 2.0);
                ans += B * (d[0] + d[1]);
done:
                ans = TidalAcceleration.AdjustForTidalAcceleration(ans, Y, tid_acc, TidalAccelerationMode.Const26, false);
                return(ans / 86400.0);
            }

            /* today - future:
             * 3rd degree polynomial based on data given by
             * Stephenson/Morrison/Hohenkerk 2016 here:
             * http://astro.ukho.gov.uk/nao/lvm/
             */
            if (mode == DeltaTMode.Stephenson_Etc_2016)
            {
                B = Y - 2000;
                if (Y < 2500)
                {
                    ans = B * B * B * 121.0 / 30000000.0 + B * B / 1250.0 + B * 521.0 / 3000.0 + 64.0;
                    /* for slow transition from tablulated data */
                    B2   = TabEnd - 2000;
                    ans2 = B2 * B2 * B2 * 121.0 / 30000000.0 + B2 * B2 / 1250.0 + B2 * 521.0 / 3000.0 + 64.0;
                    /* we use a parable after 2500 */
                }
                else
                {
                    B   = 0.01 * (Y - 2000);
                    ans = B * B * 32.5 + 42.5;
                }

                /*
                 * Formula Stephenson (1997; p. 507),
                 * with modification to avoid jump at end of AA table,
                 * similar to what Meeus 1998 had suggested.
                 * Slow transition within 100 years.
                 */
            }
            else
            {
                B   = 0.01 * (Y - 1820);
                ans = -20 + 31 * B * B;
                /* for slow transition from tablulated data */
                B2   = 0.01 * (TabEnd - 1820);
                ans2 = -20 + 31 * B2 * B2;
            }
            /* slow transition from tabulated values to Stephenson formula: */
            if (Y <= TabEnd + 100)
            {
                ans3 = dt[TabSize - 1];
                dd   = (ans2 - ans3);
                ans += dd * (Y - (TabEnd + 100)) * 0.01;
            }
            return(ans / 86400.0);
        }
Esempio n. 16
0
 /// <summary>
 /// Fetch chebyshew coefficients from sweph file
 /// </summary>
 /// <param name="pdp">Planet</param>
 /// <param name="jd">Time</param>
 /// <param name="epsilonJ2000">Epsilon for J2000</param>
 /// <see cref="get_new_segment"/>
 internal SEFileSegment ReadSegment(PlanetData pdp, JulianDayNumber jd, Epsilon epsilonJ2000) =>
 _reader.ReadSegment(pdp, jd, epsilonJ2000);
Esempio n. 17
0
        /// <summary>
        /// Model used SE 1.77 - 2.05.01, for epochs before 1633:
        /// Polynomials by Espenak & Meeus 2006, derived from Stephenson & Morrison 2004.
        /// deltat_model == SEMOD_DELTAT_ESPENAK_MEEUS_2006:
        /// This method is used only for epochs before 1633.
        /// (For more recent epochs, we use the data provided by Astronomical Almanac K8-K9.)
        /// </summary>
        /// <see cref="deltat_espenak_meeus_1620"/>
        public static double Calc(JulianDayNumber tjd, double tidalAcceleration)
        {
            double ans = 0;
            double u;
            double Ygreg = tjd.GetGregorianYear();

            if (Ygreg < -500)
            {
                ans = DeltaTLongtermMorrisonStephenson.Calc(tjd);
            }
            else if (Ygreg < 500)
            {
                u   = Ygreg / 100.0;
                ans = (((((0.0090316521 * u + 0.022174192) * u - 0.1798452) * u - 5.952053) * u + 33.78311) * u - 1014.41) * u + 10583.6;
            }
            else if (Ygreg < 1600)
            {
                u   = (Ygreg - 1000) / 100.0;
                ans = (((((0.0083572073 * u - 0.005050998) * u - 0.8503463) * u + 0.319781) * u + 71.23472) * u - 556.01) * u + 1574.2;
            }
            else if (Ygreg < 1700)
            {
                u   = Ygreg - 1600;
                ans = 120 - 0.9808 * u - 0.01532 * u * u + u * u * u / 7129.0;
            }
            else if (Ygreg < 1800)
            {
                u   = Ygreg - 1700;
                ans = (((-u / 1174000.0 + 0.00013336) * u - 0.0059285) * u + 0.1603) * u + 8.83;
            }
            else if (Ygreg < 1860)
            {
                u   = Ygreg - 1800;
                ans = ((((((0.000000000875 * u - 0.0000001699) * u + 0.0000121272) * u - 0.00037436) * u + 0.0041116) * u + 0.0068612) * u - 0.332447) * u + 13.72;
            }
            else if (Ygreg < 1900)
            {
                u   = Ygreg - 1860;
                ans = ((((u / 233174.0 - 0.0004473624) * u + 0.01680668) * u - 0.251754) * u + 0.5737) * u + 7.62;
            }
            else if (Ygreg < 1920)
            {
                u   = Ygreg - 1900;
                ans = (((-0.000197 * u + 0.0061966) * u - 0.0598939) * u + 1.494119) * u - 2.79;
            }
            else if (Ygreg < 1941)
            {
                u   = Ygreg - 1920;
                ans = 21.20 + 0.84493 * u - 0.076100 * u * u + 0.0020936 * u * u * u;
            }
            else if (Ygreg < 1961)
            {
                u   = Ygreg - 1950;
                ans = 29.07 + 0.407 * u - u * u / 233.0 + u * u * u / 2547.0;
            }
            else if (Ygreg < 1986)
            {
                u   = Ygreg - 1975;
                ans = 45.45 + 1.067 * u - u * u / 260.0 - u * u * u / 718.0;
            }
            else if (Ygreg < 2005)
            {
                u   = Ygreg - 2000;
                ans = ((((0.00002373599 * u + 0.000651814) * u + 0.0017275) * u - 0.060374) * u + 0.3345) * u + 63.86;
            }
            ans  = TidalAcceleration.AdjustForTidalAcceleration(ans, Ygreg, tidalAcceleration, TidalAccelerationMode.Const26, false);
            ans /= 86400.0;
            return(ans);
        }
Esempio n. 18
0
        /// <summary>
        /// Fetch chebyshew coefficients from sweph file
        /// </summary>
        /// <param name="pdp">Planet</param>
        /// <param name="jd">Time</param>
        /// <param name="epsilonJ2000">Epsilon for J2000</param>
        /// <see cref="get_new_segment"/>
        internal SEFileSegment ReadSegment(PlanetData pdp, JulianDayNumber jd, Epsilon epsilonJ2000)
        {
            int segmentNumber = (int)((jd - pdp.StartDate).Raw / pdp.SegmentSize);
            var segmentStart  = pdp.StartDate + JulianDayNumber.FromRaw(pdp.SegmentSize * segmentNumber);

            var fpos = pdp.FileIndexStart + segmentNumber * 3;

            fpos = ReadInt32From3Bytes(fpos);
            _stream.Seek(fpos, SeekOrigin.Begin);

            var rmax = pdp.NormalizationFactor;

            double[] segp = new double[pdp.CoefficientsNumber * 3];
            // read coefficients for 3 coordinates
            for (var icoord = 0; icoord < 3; icoord++)
            {
                var idbl = icoord * pdp.CoefficientsNumber;
                // first read header
                // first bit indicates number of sizes of packed coefficients
                int   nco;
                int   nsizes;
                int[] nsize = new int[6];
                var   c     = ReadData(1, 2);
                if ((c[0] & 128) > 0)
                {
                    var c2 = ReadData(1, 2);
                    nsizes   = 6;
                    nsize[0] = c[1] / 16;
                    nsize[1] = c[1] % 16;
                    nsize[2] = c2[0] / 16;
                    nsize[3] = c2[0] % 16;
                    nsize[4] = c2[1] / 16;
                    nsize[5] = c2[1] % 16;
                    nco      = nsize[0] + nsize[1] + nsize[2] + nsize[3] + nsize[4] + nsize[5];
                }
                else
                {
                    nsizes   = 4;
                    nsize[0] = c[0] / 16;
                    nsize[1] = c[0] % 16;
                    nsize[2] = c[1] / 16;
                    nsize[3] = c[1] % 16;
                    nco      = nsize[0] + nsize[1] + nsize[2] + nsize[3];
                }
                // there may not be more coefficients than interpolation order + 1
                if (nco > pdp.CoefficientsNumber)
                {
                    throw new FormatException($"Error in ephemeris file: {nco} coefficients instead of {pdp.CoefficientsNumber}");
                }

                // now unpack
                for (var i = 0; i < nsizes; i++)
                {
                    if (nsize[i] == 0)
                    {
                        continue;
                    }

                    if (i < 4)
                    {
                        int j     = 4 - i;
                        int k     = nsize[i];
                        var longs = ReadUints(j, k);
                        for (int m = 0; m < k; m++)
                        {
                            if ((longs[m] & 1) > 0)                             // will be negative
                            {
                                segp[idbl] = -(((longs[m] + 1) / 2) / 1e+9 * rmax / 2);
                            }
                            else
                            {
                                segp[idbl] = (longs[m] / 2) / 1e+9 * rmax / 2;
                            }
                            idbl++;
                        }
                    }
                    else if (i == 4)                     // half byte packing
                    {
                        int k     = (nsize[i] + 1) / 2;
                        var longs = ReadUints(1, k);
                        for (int m = 0, j = 0;
                             m < k && j < nsize[i];
                             m++)
                        {
                            for (int n = 0, o = 16;
                                 n < 2 && j < nsize[i];
                                 n++, j++, idbl++, longs[m] %= (uint)o, o /= 16)
                            {
                                if ((longs[m] & o) > 0)
                                {
                                    segp[idbl] = -(((longs[m] + o) / o / 2) * rmax / 2 / 1e+9);
                                }
                                else
                                {
                                    segp[idbl] = (longs[m] / o / 2) * rmax / 2 / 1e+9;
                                }
                            }
                        }
                    }
                    else if (i == 5)                     // quarter byte packing
                    {
                        int k     = (nsize[i] + 3) / 4;
                        var longs = ReadUints(1, k);
                        for (int m = 0, j = 0;
                             m < k && j < nsize[i];
                             m++)
                        {
                            for (int n = 0, o = 64;
                                 n < 4 && j < nsize[i];
                                 n++, j++, idbl++, longs[m] %= (uint)o, o /= 4)
                            {
                                if ((longs[m] & o) > 0)
                                {
                                    segp[idbl] = -(((longs[m] + o) / o / 2) * rmax / 2 / 1e+9);
                                }
                                else
                                {
                                    segp[idbl] = (longs[m] / o / 2) * rmax / 2 / 1e+9;
                                }
                            }
                        }
                    }
                }
            }

            int evaluateCoefficientsCount = pdp.Flags.HasFlag(PlanetFlags.Rotate)
                                ? RotateBack(pdp, segmentStart, segp, epsilonJ2000)
                                : pdp.CoefficientsNumber;
            var segment = new SEFileSegment(segmentStart, JulianDayNumber.FromRaw(pdp.SegmentSize), segp, evaluateCoefficientsCount);

            return(segment);
        }
Esempio n. 19
0
        public static Epsilon Calc(JulianDayNumber J, SEFLG iflag, SweData swed)
        {
            var prec_model       = swed.LongtermPrecessionMode;
            var prec_model_short = swed.ShorttermPrecessionMode;
            var jplhora_model    = swed.JplHorizonsMode;

            bool is_jplhor = false;

            if (iflag.HasFlag(SEFLG.JPLHOR))
            {
                is_jplhor = true;
            }

            if (iflag.HasFlag(SEFLG.JPLHOR_APPROX) &&
                jplhora_model == JplHorizonsMode.Three &&
                J <= HORIZONS_TJD0_DPSI_DEPS_IAU1980)
            {
                is_jplhor = true;
            }

            double T = (J - JulianDayNumber.J2000).Raw / 36525.0;

            double eps;

            if (is_jplhor)
            {
                if (J > JulianDayNumber.J1799_01_01 && J < JulianDayNumber.J2202_01_01)
                {                 // between 1.1.1799 and 1.1.2202
                    eps = (((1.813e-3 * T - 5.9e-4) * T - 46.8150) * T + 84381.448) * DEGTORAD / 3600;
                }
                else
                {
                    eps  = OwenPrecession.epsiln_owen_1986(J);
                    eps *= DEGTORAD;
                }
            }
            else if (iflag.HasFlag(SEFLG.JPLHOR_APPROX) && jplhora_model == JplHorizonsMode.Two)
            {
                eps = (((1.813e-3 * T - 5.9e-4) * T - 46.8150) * T + 84381.448) * DEGTORAD / 3600;
            }
            else if (prec_model_short == PrecessionModel.IAU_1976 && Math.Abs(T) <= PREC_IAU_1976_CTIES)
            {
                eps = (((1.813e-3 * T - 5.9e-4) * T - 46.8150) * T + 84381.448) * DEGTORAD / 3600;
            }
            else if (prec_model == PrecessionModel.IAU_1976)
            {
                eps = (((1.813e-3 * T - 5.9e-4) * T - 46.8150) * T + 84381.448) * DEGTORAD / 3600;
            }
            else if (prec_model_short == PrecessionModel.IAU_2000 && Math.Abs(T) <= PREC_IAU_2000_CTIES)
            {
                eps = (((1.813e-3 * T - 5.9e-4) * T - 46.84024) * T + 84381.406) * DEGTORAD / 3600;
            }
            else if (prec_model == PrecessionModel.IAU_2000)
            {
                eps = (((1.813e-3 * T - 5.9e-4) * T - 46.84024) * T + 84381.406) * DEGTORAD / 3600;
            }
            else if (prec_model_short == PrecessionModel.IAU_2006 && Math.Abs(T) <= PREC_IAU_2006_CTIES)
            {
                eps = (((((-4.34e-8 * T - 5.76e-7) * T + 2.0034e-3) * T - 1.831e-4) * T - 46.836769) * T + 84381.406) * DEGTORAD / 3600.0;
            }
            else if (prec_model == PrecessionModel.IAU_2006)
            {
                eps = (((((-4.34e-8 * T - 5.76e-7) * T + 2.0034e-3) * T - 1.831e-4) * T - 46.836769) * T + 84381.406) * DEGTORAD / 3600.0;
            }
            else if (prec_model == PrecessionModel.BRETAGNON_2003)
            {
                eps = ((((((-3e-11 * T - 2.48e-8) * T - 5.23e-7) * T + 1.99911e-3) * T - 1.667e-4) * T - 46.836051) * T + 84381.40880) * DEGTORAD / 3600.0;
            }
            else if (prec_model == PrecessionModel.SIMON_1994)
            {
                eps = (((((2.5e-8 * T - 5.1e-7) * T + 1.9989e-3) * T - 1.52e-4) * T - 46.80927) * T + 84381.412) * DEGTORAD / 3600.0;                /* */
            }
            else if (prec_model == PrecessionModel.WILLIAMS_1994)
            {
                eps = ((((-1.0e-6 * T + 2.0e-3) * T - 1.74e-4) * T - 46.833960) * T + 84381.409) * DEGTORAD / 3600.0;                /* */
            }
            else if (prec_model == PrecessionModel.LASKAR_1986 || prec_model == PrecessionModel.WILL_EPS_LASK)
            {
                T  /= 10.0;
                eps = (((((((((2.45e-10 * T + 5.79e-9) * T + 2.787e-7) * T
                             + 7.12e-7) * T - 3.905e-5) * T - 2.4967e-3) * T
                          - 5.138e-3) * T + 1.99925) * T - 0.0155) * T - 468.093) * T
                      + 84381.448;
                eps *= DEGTORAD / 3600.0;
            }
            else if (prec_model == PrecessionModel.OWEN_1990)
            {
                eps  = OwenPrecession.epsiln_owen_1986(J);
                eps *= DEGTORAD;
            }
            else
            {             /* SEMOD_PREC_VONDRAK_2011 */
                (_, eps) = Vondrak.swi_ldp_peps(J);
                if (iflag.HasFlag(SEFLG.JPLHOR_APPROX) && jplhora_model != JplHorizonsMode.Two)
                {
                    double tofs = (J - DCOR_EPS_JPL_TJD0).Raw / 365.25;
                    double dofs;
                    if (tofs < 0)
                    {
                        dofs = dcor_eps_jpl[0];
                    }
                    else if (tofs >= dcor_eps_jpl.Length)
                    {
                        dofs = dcor_eps_jpl.Last();
                    }
                    else
                    {
                        int t0 = (int)tofs;
                        int t1 = t0 + 1;
                        dofs = (tofs - t0) * (dcor_eps_jpl[t0] - dcor_eps_jpl[t1]) + dcor_eps_jpl[t0];
                    }
                    dofs /= (1000.0 * 3600.0);
                    eps  += dofs * DEGTORAD;
                }
            }
            return(new Epsilon(J, eps));
        }
Esempio n. 20
0
        /// <summary>
        /// <c>rot_back</c>
        /// Adds reference orbit to chebyshew series (if SEI_FLG_ELLIPSE),
        /// rotates series to mean equinox of J2000
        /// </summary>
        private int RotateBack(PlanetData pdp, JulianDayNumber segmentStart, double[] coefficients, Epsilon epsilon)
        {
            int nco = pdp.CoefficientsNumber;
            var t   = segmentStart.Raw + pdp.SegmentSize / 2;
            // data align: chcfx double[nco] + chcfy double[nco] + chcfz double[nco]
            // allsize: nco * 3
            var    segp = coefficients;
            var    chcfx = new Span <double>(segp, 0, nco);
            var    chcfy = new Span <double>(segp, nco, nco);
            var    chcfz = new Span <double>(segp, nco * 2, nco);
            var    tdiff = (t - pdp.ElementsEpoch) / 365250.0;
            double qav, pav;

            if (pdp.InternalBodyNumber == (int)InternalPlanets.Moon)
            {
                var dn = pdp.Prot + tdiff * pdp.Dprot;
                var i  = (int)(dn / Consts.TwoPi);
                dn -= i * Consts.TwoPi;
                qav = (pdp.Qrot + tdiff * pdp.Dqrot) * Math.Cos(dn);
                pav = (pdp.Qrot + tdiff * pdp.Dqrot) * Math.Sin(dn);
            }
            else
            {
                qav = pdp.Qrot + tdiff * pdp.Dqrot;
                pav = pdp.Prot + tdiff * pdp.Dprot;
            }
            // calculate cosine and sine of average perihelion longitude.
            var x = new double[nco, 3];

            for (int i = 0; i < nco; i++)
            {
                x[i, 0] = chcfx[i];
                x[i, 1] = chcfy[i];
                x[i, 2] = chcfz[i];
            }
            if (pdp.Flags.HasFlag(PlanetFlags.Ellipse))
            {
                var refepx = new Span <double>(pdp.ReferenceEllipseCoefficients, 0, nco);
                var refepy = new Span <double>(pdp.ReferenceEllipseCoefficients, nco, nco);
                var omtild = pdp.Perigee + tdiff + pdp.DPerigee;
                int i      = (int)(omtild / Consts.TwoPi);
                omtild -= i * Consts.TwoPi;
                var com = Math.Cos(omtild);
                var som = Math.Sin(omtild);
                // add reference orbit.
                for (i = 0; i < nco; i++)
                {
                    x[i, 0] = chcfx[i] + com * refepx[i] - som * refepy[i];
                    x[i, 1] = chcfy[i] + com * refepy[i] + som * refepx[i];
                }
            }

            /* construct right handed orthonormal system with first axis along
             * origin of longitudes and third axis along angular momentum
             * this uses the standard formulas for equinoctal variables
             * (see papers by broucke and by cefola).      */
            var cosih2 = 1.0 / (1.0 + qav * qav + pav * pav);
            //     calculate orbit pole.
            Span <double> uiz = stackalloc double[3];

            uiz[0] = 2.0 * pav * cosih2;
            uiz[1] = -2.0 * qav * cosih2;
            uiz[2] = (1.0 - qav * qav - pav * pav) * cosih2;
            //     calculate origin of longitudes vector.
            Span <double> uix = stackalloc double[3];

            uix[0] = (1.0 + qav * qav - pav * pav) * cosih2;
            uix[1] = 2.0 * qav * pav * cosih2;
            uix[2] = -2.0 * pav * cosih2;
            //     calculate vector in orbital plane orthogonal to origin of longitudes.
            Span <double> uiy = stackalloc double[3];

            uiy[0] = 2.0 * qav * pav * cosih2;
            uiy[1] = (1.0 - qav * qav + pav * pav) * cosih2;
            uiy[2] = 2.0 * qav * cosih2;
            int evaluateCoefficientsCount = 0;

            //     rotate to actual orientation in space.
            for (var i = 0; i < nco; i++)
            {
                var xrot = x[i, 0] * uix[0] + x[i, 1] * uiy[0] + x[i, 2] * uiz[0];
                var yrot = x[i, 0] * uix[1] + x[i, 1] * uiy[1] + x[i, 2] * uiz[1];
                var zrot = x[i, 0] * uix[2] + x[i, 1] * uiy[2] + x[i, 2] * uiz[2];
                if (Math.Abs(xrot) + Math.Abs(yrot) + Math.Abs(zrot) >= 1e-14)
                {
                    evaluateCoefficientsCount = i;
                }
                x[i, 0] = xrot;
                x[i, 1] = yrot;
                x[i, 2] = zrot;
                if (pdp.InternalBodyNumber == (int)InternalPlanets.Moon)
                {
                    /* rotate to j2000 equator */
                    x[i, 1] = epsilon.CosEps * yrot - epsilon.SinEps * zrot;
                    x[i, 2] = epsilon.SinEps * yrot + epsilon.CosEps * zrot;
                }
            }

            for (var i = 0; i < nco; i++)
            {
                chcfx[i] = x[i, 0];
                chcfy[i] = x[i, 1];
                chcfz[i] = x[i, 2];
            }
            return(evaluateCoefficientsCount);
        }