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