def nutation(tee): """Return the longitudinal nutation at moment, tee.""" c = julian_centuries(tee) cap_A = poly(c, [mpf(124.90), mpf(-1934.134), mpf(0.002063)]) cap_B = poly(c, [mpf(201.11), mpf(72001.5377), mpf(0.00057)]) return (mpf(-0.004778) * sin_degrees(cap_A) + mpf(-0.0003667) * sin_degrees(cap_B))
def equation_of_time(tee): """Return the equation of time (as fraction of day) for moment, tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 1991.""" c = julian_centuries(tee) lamb = poly(c, [mpf(280.46645), mpf(36000.76983), mpf(0.0003032)]) anomaly = poly( c, [mpf(357.52910), mpf(35999.05030), mpf(-0.0001559), mpf(-0.00000048)]) eccentricity = poly( c, [mpf(0.016708617), mpf(-0.000042037), mpf(-0.0000001236)]) varepsilon = obliquity(tee) y = pow(tan_degrees(varepsilon / 2), 2) equation = ( (1 / 2 / pi) * (y * sin_degrees(2 * lamb) + -2 * eccentricity * sin_degrees(anomaly) + (4 * eccentricity * y * sin_degrees(anomaly) * cos_degrees(2 * lamb)) + -0.5 * y * y * sin_degrees(4 * lamb) + -1.25 * eccentricity * eccentricity * sin_degrees(2 * anomaly))) return signum(equation) * min(abs(equation), Clock.days_from_hours( mpf(12)))
def ephemeris_correction(tee): """Return Dynamical Time minus Universal Time (in days) for moment, tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 1991.""" year = GregorianDate.to_year(int(math.floor(tee))) c = GregorianDate.date_difference( GregorianDate(1900, MonthOfYear.JANUARY, 1), GregorianDate(year, MonthOfYear.JULY, 1)) / mpf(36525) if 1988 <= year <= 2019: return 1 / 86400 * (year - 1933) elif 1900 <= year <= 1987: return poly(c, [ mpf(-0.00002), mpf(0.000297), mpf(0.025184), mpf(-0.181133), mpf(0.553040), mpf(-0.861938), mpf(0.677066), mpf(-0.212591) ]) elif 1800 <= year <= 1899: return poly(c, [ mpf(-0.000009), mpf(0.003844), mpf(0.083563), mpf(0.865736), mpf(4.867575), mpf(15.845535), mpf(31.332267), mpf(38.291999), mpf(28.316289), mpf(11.636204), mpf(2.043794) ]) elif 1700 <= year <= 1799: return 1 / 86400 * poly( year - 1700, [8.118780842, -0.005092142, 0.003336121, -0.0000266484]) elif 1620 <= year <= 1699: return 1 / 86400 * poly( year - 1600, [mpf(196.58333), mpf(-4.0675), mpf(0.0219167)]) else: x = Clock.days_from_hours(mpf(12)) + GregorianDate.date_difference( GregorianDate(1810, MonthOfYear.JANUARY, 1), GregorianDate(year, MonthOfYear.JANUARY, 1)) return 1 / 86400 * (((x * x) / mpf(41048480)) - 15)
def obliquity(tee): """Return (mean) obliquity of ecliptic at moment tee.""" c = julian_centuries(tee) return (angle(23, 26, mpf(21.448)) + poly(c, [ mpf(0), angle(0, 0, mpf(-46.8150)), angle(0, 0, mpf(-0.00059)), angle(0, 0, mpf(0.001813)) ]))
def sidereal_from_moment(tee): """Return the mean sidereal time of day from moment tee expressed as hour angle. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 1991.""" c = (tee - J2000) / mpf(36525) return poly(c, [ mpf(280.46061837), mpf(36525) * mpf(360.98564736629), mpf(0.000387933), mpf(-1) / mpf(38710000) ]) % 360
def solar_anomaly(c): """Return mean anomaly of sun (in degrees) at moment given in Julian centuries c. Adapted from eq. 47.3 in "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed. with corrections, 2005.""" return normalized_degrees( poly(c, [ mpf(357.5291092), mpf(35999.0502909), mpf(-0.0001536), mpf(1.0 / 24490000.0) ]))
def moon_node(c): """Return Moon's argument of latitude (in degrees) at moment given in Julian centuries 'c'. Adapted from eq. 47.5 in "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed. with corrections, 2005.""" return normalized_degrees( poly(c, [ mpf(93.2720950), mpf(483202.0175233), mpf(-0.0036539), mpf(-1.0 / 3526000.0), mpf(1.0 / 863310000.0) ]))
def lunar_anomaly(c): """Return mean anomaly of moon (in degrees) at moment given in Julian centuries c. Adapted from eq. 47.4 in "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed. with corrections, 2005.""" return normalized_degrees( poly(c, [ mpf(134.9633964), mpf(477198.8675055), mpf(0.0087414), mpf(1.0 / 69699.0), mpf(-1.0 / 14712000.0) ]))
def lunar_elongation(c): """Return elongation of moon (in degrees) at moment given in Julian centuries c. Adapted from eq. 47.2 in "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed. with corrections, 2005.""" return normalized_degrees( poly(c, [ mpf(297.8501921), mpf(445267.1114034), mpf(-0.0018819), mpf(1 / 545868), mpf(-1 / 113065000) ]))
def lunar_longitude(tee): """Return longitude of moon (in degrees) at moment tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998.""" c = julian_centuries(tee) cap_L_prime = mean_lunar_longitude(c) cap_D = lunar_elongation(c) cap_M = solar_anomaly(c) cap_M_prime = lunar_anomaly(c) cap_F = moon_node(c) # see eq. 47.6 in Meeus cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) args_lunar_elongation = \ [0, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 1, 0, 2, 0, 0, 4, 0, 4, 2, 2, 1, 1, 2, 2, 4, 2, 0, 2, 2, 1, 2, 0, 0, 2, 2, 2, 4, 0, 3, 2, 4, 0, 2, 2, 2, 4, 0, 4, 1, 2, 0, 1, 3, 4, 2, 0, 1, 2] args_solar_anomaly = \ [0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, -2, 1, 2, -2, 0, 0, -1, 0, 0, 1, -1, 2, 2, 1, -1, 0, 0, -1, 0, 1, 0, 1, 0, 0, -1, 2, 1, 0] args_lunar_anomaly = \ [1, -1, 0, 2, 0, 0, -2, -1, 1, 0, -1, 0, 1, 0, 1, 1, -1, 3, -2, -1, 0, -1, 0, 1, 2, 0, -3, -2, -1, -2, 1, 0, 2, 0, -1, 1, 0, -1, 2, -1, 1, -2, -1, -1, -2, 0, 1, 4, 0, -2, 0, 2, 1, -2, -3, 2, 1, -1, 3] args_moon_node = \ [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, -2, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -2, 2, 0, 2, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0] sine_coefficients = \ [6288774,1274027,658314,213618,-185116,-114332, 58793,57066,53322,45758,-40923,-34720,-30383, 15327,-12528,10980,10675,10034,8548,-7888, -6766,-5163,4987,4036,3994,3861,3665,-2689, -2602, 2390,-2348,2236,-2120,-2069,2048,-1773, -1595,1215,-1110,-892,-810,759,-713,-700,691, 596,549,537,520,-487,-399,-381,351,-340,330, 327,-323,299,294] correction = ((1.0 / 1000000.0) * sigma([ sine_coefficients, args_lunar_elongation, args_solar_anomaly, args_lunar_anomaly, args_moon_node ], lambda v, w, x, y, z: v * pow(cap_E, abs(x)) * sin_degrees( (w * cap_D) + (x * cap_M) + (y * cap_M_prime) + (z * cap_F)))) A1 = mpf(119.75) + (c * mpf(131.849)) venus = ((3958 / 1000000) * sin_degrees(A1)) A2 = mpf(53.09) + c * mpf(479264.29) jupiter = ((318 / 1000000) * sin_degrees(A2)) flat_earth = ((1962 / 1000000) * sin_degrees(cap_L_prime - cap_F)) return (cap_L_prime + correction + venus + jupiter + flat_earth + nutation(tee)) % 360
def lunar_perigee(tee): """Return Angular distance of the perigee from the equinoctal point at moment, tee. Adapted from eq. 47.7 in "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998 with corrections June 2005.""" return normalized_degrees( poly(julian_centuries(tee), [ mpf(83.3532465), mpf(4069.0137287), mpf(-0.0103200), mpf(-1.0 / 80053.0), mpf(1.0 / 18999000.0) ]))
def lunar_latitude(tee): """Return the latitude of moon (in degrees) at moment, tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 1998.""" c = julian_centuries(tee) cap_L_prime = mean_lunar_longitude(c) cap_D = lunar_elongation(c) cap_M = solar_anomaly(c) cap_M_prime = lunar_anomaly(c) cap_F = moon_node(c) cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) args_lunar_elongation = \ [0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 4, 0, 4, 2, 2, 2, 2, 0, 2, 2, 2, 2, 4, 2, 2, 0, 2, 1, 1, 0, 2, 1, 2, 0, 4, 4, 1, 4, 1, 4, 2] args_solar_anomaly = \ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, -1, -1, -1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 1, 0, -1, -2, 0, 1, 1, 1, 1, 1, 0, -1, 1, 0, -1, 0, 0, 0, -1, -2] args_lunar_anomaly = \ [0, 1, 1, 0, -1, -1, 0, 2, 1, 2, 0, -2, 1, 0, -1, 0, -1, -1, -1, 0, 0, -1, 0, 1, 1, 0, 0, 3, 0, -1, 1, -2, 0, 2, 1, -2, 3, 2, -3, -1, 0, 0, 1, 0, 1, 1, 0, 0, -2, -1, 1, -2, 2, -2, -1, 1, 1, -2, 0, 0] args_moon_node = \ [1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 3, 1, 1, 1, -1, -1, -1, 1, -1, 1, -3, 1, -3, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 3, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1] sine_coefficients = \ [5128122, 280602, 277693, 173237, 55413, 46271, 32573, 17198, 9266, 8822, 8216, 4324, 4200, -3359, 2463, 2211, 2065, -1870, 1828, -1794, -1749, -1565, -1491, -1475, -1410, -1344, -1335, 1107, 1021, 833, 777, 671, 607, 596, 491, -451, 439, 422, 421, -366, -351, 331, 315, 302, -283, -229, 223, 223, -220, -220, -185, 181, -177, 176, 166, -164, 132, -119, 115, 107] beta = ((1.0 / 1000000.0) * sigma([ sine_coefficients, args_lunar_elongation, args_solar_anomaly, args_lunar_anomaly, args_moon_node ], lambda v, w, x, y, z: (v * pow(cap_E, abs(x)) * sin_degrees( (w * cap_D) + (x * cap_M) + (y * cap_M_prime) + (z * cap_F))))) venus = ((175 / 1000000) * (sin_degrees(mpf(119.75) + c * mpf(131.849) + cap_F) + sin_degrees(mpf(119.75) + c * mpf(131.849) - cap_F))) flat_earth = ((-2235 / 1000000) * sin_degrees(cap_L_prime) + (127 / 1000000) * sin_degrees(cap_L_prime - cap_M_prime) + (-115 / 1000000) * sin_degrees(cap_L_prime + cap_M_prime)) extra = ((382 / 1000000) * sin_degrees(mpf(313.45) + c * mpf(481266.484))) return beta + venus + flat_earth + extra
def alt_lunar_node(tee): """Return Angular distance of the node from the equinoctal point at fixed moment, tee. Adapted from eq. 47.7 in "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998 with corrections June 2005.""" return normalized_degrees( poly(julian_centuries(tee), [ mpf(125.0445479), mpf(-1934.1362891), mpf(0.0020754), mpf(1.0 / 467441.0), mpf(-1.0 / 60616000.0) ]))
def precession(tee): """Return the precession at moment tee using 0,0 as J2000 coordinates. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann-Bell, Inc., 1991.""" c = julian_centuries(tee) eta = poly( c, [0, secs(mpf(47.0029)), secs(mpf(-0.03302)), secs(mpf(0.000060))]) % 360 cap_P = poly(c, [mpf(174.876384), secs(mpf(-869.8089)), secs(mpf(0.03536))]) % 360 p = poly( c, [0, secs(mpf(5029.0966)), secs(mpf(1.11113)), secs(mpf(0.000006))]) % 360 cap_A = cos_degrees(eta) * sin_degrees(cap_P) cap_B = cos_degrees(cap_P) arg = arctan_degrees(cap_A, cap_B) return (p + cap_P - arg) % 360
def mean_lunar_longitude(c): """Return mean longitude of moon (in degrees) at moment given in Julian centuries c (including the constant term of the effect of the light-time (-0".70). Adapted from eq. 47.1 in "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed. with corrections, 2005.""" return normalized_degrees( poly(c, [ mpf(218.3164477), mpf(481267.88123421), mpf(-0.0015786), mpf(1 / 538841.0), mpf(-1.0 / 65194000.0) ]))
def precise_obliquity(tee): """Return precise (mean) obliquity of ecliptic at moment tee.""" u = julian_centuries(tee) / 100 #assert(abs(u) < 1, # 'Error! This formula is valid for +/-10000 years around J2000.0') return (poly(u, [ angle(23, 26, mpf(21.448)), angle(0, 0, mpf(-4680.93)), angle(0, 0, mpf(-1.55)), angle(0, 0, mpf(+1999.25)), angle(0, 0, mpf(-51.38)), angle(0, 0, mpf(-249.67)), angle(0, 0, mpf(-39.05)), angle(0, 0, mpf(+7.12)), angle(0, 0, mpf(+27.87)), angle(0, 0, mpf(+5.79)), angle(0, 0, mpf(+2.45)) ]))
def lunar_distance(tee): """Return the distance to moon (in meters) at moment, tee. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed.""" c = julian_centuries(tee) cap_D = lunar_elongation(c) cap_M = solar_anomaly(c) cap_M_prime = lunar_anomaly(c) cap_F = moon_node(c) cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) args_lunar_elongation = \ [0, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 1, 0, 2, 0, 0, 4, 0, 4, 2, 2, 1, 1, 2, 2, 4, 2, 0, 2, 2, 1, 2, 0, 0, 2, 2, 2, 4, 0, 3, 2, 4, 0, 2, 2, 2, 4, 0, 4, 1, 2, 0, 1, 3, 4, 2, 0, 1, 2, 2,] args_solar_anomaly = \ [0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, -2, 1, 2, -2, 0, 0, -1, 0, 0, 1, -1, 2, 2, 1, -1, 0, 0, -1, 0, 1, 0, 1, 0, 0, -1, 2, 1, 0, 0] args_lunar_anomaly = \ [1, -1, 0, 2, 0, 0, -2, -1, 1, 0, -1, 0, 1, 0, 1, 1, -1, 3, -2, -1, 0, -1, 0, 1, 2, 0, -3, -2, -1, -2, 1, 0, 2, 0, -1, 1, 0, -1, 2, -1, 1, -2, -1, -1, -2, 0, 1, 4, 0, -2, 0, 2, 1, -2, -3, 2, 1, -1, 3, -1] args_moon_node = \ [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, -2, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -2, 2, 0, 2, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0, -2] cosine_coefficients = \ [-20905355, -3699111, -2955968, -569925, 48888, -3149, 246158, -152138, -170733, -204586, -129620, 108743, 104755, 10321, 0, 79661, -34782, -23210, -21636, 24208, 30824, -8379, -16675, -12831, -10445, -11650, 14403, -7003, 0, 10056, 6322, -9884, 5751, 0, -4950, 4130, 0, -3958, 0, 3258, 2616, -1897, -2117, 2354, 0, 0, -1423, -1117, -1571, -1739, 0, -4421, 0, 0, 0, 0, 1165, 0, 0, 8752] correction = sigma([ cosine_coefficients, args_lunar_elongation, args_solar_anomaly, args_lunar_anomaly, args_moon_node ], lambda v, w, x, y, z: (v * pow(cap_E, abs(x)) * cos_degrees( (w * cap_D) + (x * cap_M) + (y * cap_M_prime) + (z * cap_F)))) return 385000560 + correction
def geometric_solar_mean_longitude(tee): """Return the geometric mean longitude of the Sun at moment, tee, referred to mean equinox of the date.""" c = julian_centuries(tee) return poly(c, [mpf(280.46646), mpf(36000.76983), mpf(0.0003032)])
def nth_new_moon(n): """Return the moment of n-th new moon after (or before) the new moon of January 11, 1. Adapted from "Astronomical Algorithms" by Jean Meeus, Willmann_Bell, Inc., 2nd ed., 1998.""" n0 = 24724 k = n - n0 c = k / mpf(1236.85) approx = (J2000 + poly(c, [ mpf(5.09766), MEAN_SYNODIC_MONTH * mpf(1236.85), mpf(0.0001437), mpf(-0.000000150), mpf(0.00000000073) ])) cap_E = poly(c, [1, mpf(-0.002516), mpf(-0.0000074)]) solar_anomaly = poly(c, [ mpf(2.5534), (mpf(1236.85) * mpf(29.10535669)), mpf(-0.0000014), mpf(-0.00000011) ]) lunar_anomaly = poly(c, [ mpf(201.5643), (mpf(385.81693528) * mpf(1236.85)), mpf(0.0107582), mpf(0.00001238), mpf(-0.000000058) ]) moon_argument = poly(c, [ mpf(160.7108), (mpf(390.67050284) * mpf(1236.85)), mpf(-0.0016118), mpf(-0.00000227), mpf(0.000000011) ]) cap_omega = poly(c, [ mpf(124.7746), (mpf(-1.56375588) * mpf(1236.85)), mpf(0.0020672), mpf(0.00000215) ]) E_factor = [ 0, 1, 0, 0, 1, 1, 2, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] solar_coeff = [ 0, 1, 0, 0, -1, 1, 2, 0, 0, 1, 0, 1, 1, -1, 2, 0, 3, 1, 0, 1, -1, -1, 1, 0 ] lunar_coeff = [ 1, 0, 2, 0, 1, 1, 0, 1, 1, 2, 3, 0, 0, 2, 1, 2, 0, 1, 2, 1, 1, 1, 3, 4 ] moon_coeff = [ 0, 0, 0, 2, 0, 0, 0, -2, 2, 0, 0, 2, -2, 0, 0, -2, 0, -2, 2, 2, 2, -2, 0, 0 ] sine_coeff = [ mpf(-0.40720), mpf(0.17241), mpf(0.01608), mpf(0.01039), mpf(0.00739), mpf(-0.00514), mpf(0.00208), mpf(-0.00111), mpf(-0.00057), mpf(0.00056), mpf(-0.00042), mpf(0.00042), mpf(0.00038), mpf(-0.00024), mpf(-0.00007), mpf(0.00004), mpf(0.00004), mpf(0.00003), mpf(0.00003), mpf(-0.00003), mpf(0.00003), mpf(-0.00002), mpf(-0.00002), mpf(0.00002) ] correction = ( (mpf(-0.00017) * sin_degrees(cap_omega)) + sigma([sine_coeff, E_factor, solar_coeff, lunar_coeff, moon_coeff], lambda v, w, x, y, z: (v * pow(cap_E, w) * sin_degrees( (x * solar_anomaly) + (y * lunar_anomaly) + (z * moon_argument))))) add_const = [ mpf(251.88), mpf(251.83), mpf(349.42), mpf(84.66), mpf(141.74), mpf(207.14), mpf(154.84), mpf(34.52), mpf(207.19), mpf(291.34), mpf(161.72), mpf(239.56), mpf(331.55) ] add_coeff = [ mpf(0.016321), mpf(26.651886), mpf(36.412478), mpf(18.206239), mpf(53.303771), mpf(2.453732), mpf(7.306860), mpf(27.261239), mpf(0.121824), mpf(1.844379), mpf(24.198154), mpf(25.513099), mpf(3.592518) ] add_factor = [ mpf(0.000165), mpf(0.000164), mpf(0.000126), mpf(0.000110), mpf(0.000062), mpf(0.000060), mpf(0.000056), mpf(0.000047), mpf(0.000042), mpf(0.000040), mpf(0.000037), mpf(0.000035), mpf(0.000023) ] extra = (mpf(0.000325) * sin_degrees( poly(c, [mpf(299.77), mpf(132.8475848), mpf(-0.009173)]))) additional = sigma([add_const, add_coeff, add_factor], lambda i, j, l: l * sin_degrees(i + j * k)) return universal_from_dynamical(approx + correction + extra + additional)