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); }
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); }
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; } }
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); }
/* 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], }); }
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; } } }
/// <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)); }
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); }
/* * 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, }); }
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); }
/* 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 }); }
/// <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); }
/// <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); }
/// <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);
/// <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); }
/// <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); }
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)); }
/// <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); }