// ICRS to TEME conversion void icrs_to_teme(double mjd,double a[3][3]) { int i,j; double dpsi,deps,eps,z,theta,zeta,h; double p[3][3],n[3][3],q[3][3],b[3][3]; // Precession precess(51544.5,mjd,&zeta,&z,&theta); identity_matrix(p); rotate_z(-zeta,p); rotate_y(theta,p); rotate_z(-z,p); // Nutation nutation(mjd,&dpsi,&deps,&eps); identity_matrix(n); rotate_x(eps,n); rotate_z(-dpsi,n); rotate_x(-eps-deps,n); // Equation of equinoxes identity_matrix(q); rotate_z(dpsi*cos(eps+deps),q); // Multiply matrices (left to right) matrix_multiply(q,n,b); matrix_multiply(b,p,a); return; }
void testnutation(void) { double jd = 2411545.0; char deg[30]; double d; d = nutation(jd) * RAD2DEG; fmtdeg(deg, d); printf("%s\n", deg); }
void vSOPPlanetInfo(char *dataDir, double tJD, int planet, double *rA, double *dec, double *distance) { double L, B, R, L0, B0, R0, x, y, z, lambda, beta, delta, tau, T, Lprime, deltaL, deltaB, deltaPhi, deltaEps, eps, tY, tX; heliocentricEclipticCoordinates(dataDir, tJD, 2, &L0, &B0, &R0); if (planet != SUN) heliocentricEclipticCoordinates(dataDir, tJD, planet, &L, &B, &R); else L = B = R = 0.0; x = R*cos(B)*cos(L) - R0*cos(B0)*cos(L0); y = R*cos(B)*sin(L) - R0*cos(B0)*sin(L0); z = R*sin(B) - R0*sin(B0); delta = sqrt(x*x + y*y + z*z); tau = 0.0057755183*delta; heliocentricEclipticCoordinates(dataDir, tJD-tau, 2, &L0, &B0, &R0); if (planet != SUN) heliocentricEclipticCoordinates(dataDir, tJD-tau, planet, &L, &B, &R); else L = B = R = 0.0; x = R*cos(B)*cos(L) - R0*cos(B0)*cos(L0); y = R*cos(B)*sin(L) - R0*cos(B0)*sin(L0); z = R*sin(B) - R0*sin(B0); lambda = atan2(y, x); doubleNormalize0to2pi(&lambda); beta = atan2(z, sqrt(x*x + y*y)); T = (tJD - 2451545.0) / 36525.0; Lprime = lambda - 1.397*DEGREES_TO_RADIANS*T - 0.00031*DEGREES_TO_RADIANS*T*T; deltaL = -0.09033*ARCSEC_TO_RADIANS + 0.03916*ARCSEC_TO_RADIANS*(cos(Lprime) + sin(Lprime))*tan(beta); deltaB = 0.03916*ARCSEC_TO_RADIANS*(cos(Lprime) - sin(Lprime)); lambda += deltaL; beta += deltaB; nutation(T, &deltaPhi, &deltaEps, &eps); eps *= DEGREES_TO_RADIANS; lambda += deltaPhi*ARCSEC_TO_RADIANS; tY = sin(lambda)*cos(eps) - tan(beta)*sin(eps) + 1.0; tX = cos(lambda) + 1.0; *rA = atan2(sin(lambda)*cos(eps) - tan(beta)*sin(eps), cos(lambda)); doubleNormalize0to2pi(rA); *dec = asin(sin(beta)*cos(eps) + cos(beta)*sin(eps)*sin(lambda)); *distance = sqrt(x*x + y*y + z*z); }
TimeIncrement EquationOfTime( double julianDay ) { shared_ptr< JPLEphemeris > spEphem = JPLEphemeris::GetEphemeris( julianDay ); if ( ! spEphem ) return TimeIncrement( 0 ); Angle meanSolarLong = MeanSolarLongitude( julianDay ); Point3D earthBarycentric; Vector3D earthBarycentricVelocity; #ifdef DEBUG bool earthRslt = #endif GetEarthBarycentric( julianDay, &earthBarycentric, &earthBarycentricVelocity, spEphem ); Assert( earthRslt ); Matrix3D precessionMatrix = Precession( julianDay ).Matrix( ); Nutation nutation( 0., 0. ); if ( spEphem->NutationAvailable() ) { #ifdef DEBUG bool nutRslt = #endif spEphem->GetNutation( julianDay, &nutation ); Assert( nutRslt ); } Angle meanObliquity = MeanObliquity( julianDay ); Angle trueObliquity = TrueObliquity( meanObliquity, nutation ); Matrix3D nutAndPrecMatrix = nutation.Matrix( meanObliquity ) * precessionMatrix; JPLBarycentricEphemeris sunEphem( spEphem, JPLEphemeris::Sun ); Point3D sunPos = GetSunApparentPlace( julianDay, sunEphem, earthBarycentric, earthBarycentricVelocity, nutAndPrecMatrix ); Equatorial sunEquatorial( sunPos ); Angle eotAngle = meanSolarLong - Angle( 0.0057183, Angle::Degree ) - sunEquatorial.RightAscension() + nutation.NutLongitude() * Cos( trueObliquity ); return TimeIncrement( eotAngle.Cycles() ); }
/* given a Now *, find the local apparent sidereal time, in hours. */ void now_lst (Now *np, double *lstp) { static double last_mjd = -23243, last_lng = 121212, last_lst; double eps, lst, deps, dpsi; if (last_mjd == mjd && last_lng == lng) { *lstp = last_lst; return; } utc_gst (mjd_day(mjd), mjd_hr(mjd), &lst); lst += radhr(lng); obliquity(mjd, &eps); nutation(mjd, &deps, &dpsi); lst += radhr(dpsi*cos(eps+deps)); range (&lst, 24.0); last_mjd = mjd; last_lng = lng; *lstp = last_lst = lst; }
void moonPosition(double jDE, double *rA, double *dec, double *eLong, double *eLat, double *distance, float *Fr) { int i; double T, Lprime, D, M, Mprime, F, A1, A2, A3, Sigmal, Sigmar, Sigmab, E, alpha, dD, dM, dMprime, dF, lambda, beta, delta, deltaPhi, deltaEps, eps, pi; T = (jDE - 2451545.0)/36525.0; nutation(T, &deltaPhi, &deltaEps, &eps); Lprime = 218.3164477 + 481267.88123421*T - 0.00157860*T*T + T*T*T/538841.0 - T*T*T*T/65194000.0; doubleNormalize0to360(&Lprime); D = 297.8501921 + 445267.1114034*T - 0.0018819*T*T + T*T*T/545868.0 - T*T*T*T/113065000.0; doubleNormalize0to360(&D); M = 357.5291092 + 35999.0502909*T - 0.0001536*T*T + T*T*T/24490000.0; doubleNormalize0to360(&M); Mprime = 134.9633964 + 477198.8675055*T + 0.0087414*T*T + T*T*T/69699.0 - T*T*T*T/14712000.0; doubleNormalize0to360(&Mprime); F = 93.2720950 + 483202.0175233*T - 0.0036539*T*T - T*T*T/3526000.0 - T*T*T*T/863310000.0; doubleNormalize0to360(&F); A1 = 119.75 + 131.849*T; doubleNormalize0to360(&A1); A2 = 53.09 + 479264.290*T; doubleNormalize0to360(&A2); A3 = 313.45 + 481266.484*T; doubleNormalize0to360(&A3); Sigmal = Sigmar = Sigmab = 0.0; E = 1.0 - 0.002516*T - 0.0000074*T*T; dD = D*DEGREES_TO_RADIANS; dM = M*DEGREES_TO_RADIANS; dMprime = Mprime*DEGREES_TO_RADIANS; dF = F*DEGREES_TO_RADIANS; for (i = 0; i < 60; i++) { if ((argMultlr[i][1] == 1) || (argMultlr[i][1] == -1)) alpha = E; else if ((argMultlr[i][1] == 2) || (argMultlr[i][1] == -2)) alpha = E*E; else alpha = 1; Sigmal += alpha*SigmalCoef[i]*sin(argMultlr[i][0]*dD + argMultlr[i][1]*dM + argMultlr[i][2]*dMprime + argMultlr[i][3]*dF); Sigmar += alpha*SigmarCoef[i]*cos(argMultlr[i][0]*dD + argMultlr[i][1]*dM + argMultlr[i][2]*dMprime + argMultlr[i][3]*dF); if ((argMultb[i][1] == 1) || (argMultb[i][1] == -1)) alpha = E; else if ((argMultb[i][1] == 2) || (argMultb[i][1] == -2)) alpha = E*E; else alpha = 1; Sigmab += alpha*SigmabCoef[i]*sin(argMultb[i][0]*dD + argMultb[i][1]*dM + argMultb[i][2]*dMprime + argMultb[i][3]*dF); } Sigmal += 3958.0*sin(A1*DEGREES_TO_RADIANS) + 1962.0*sin((Lprime-F)*DEGREES_TO_RADIANS) + 318.0*sin(A2*DEGREES_TO_RADIANS); Sigmab += -2235.0*sin(Lprime*DEGREES_TO_RADIANS) + 382.0*sin(A3*DEGREES_TO_RADIANS) + 175.0*sin((A1-F)*DEGREES_TO_RADIANS) + 175.0*sin((A1+F)*DEGREES_TO_RADIANS) + 127.0*sin((Lprime-Mprime)*DEGREES_TO_RADIANS) - 115.0*sin((Lprime+Mprime)*DEGREES_TO_RADIANS); lambda = Lprime + Sigmal*1.0e-6 + deltaPhi/3600.0; doubleNormalize0to360(&lambda); beta = Sigmab*1.0e-6; doubleNormalize0to360(&beta); delta = 385000.56 + Sigmar*1.0e-3; pi = asin(6378.14/delta)/DEGREES_TO_RADIANS; eps *= DEGREES_TO_RADIANS; lambda *= DEGREES_TO_RADIANS; beta *= DEGREES_TO_RADIANS; *eLong = lambda; *eLat = beta; *rA = atan2(sin(lambda)*cos(eps) - tan(beta)*sin(eps), cos(lambda)); doubleNormalize0to2pi(rA); *dec = asin(sin(beta)*cos(eps) + cos(beta)*sin(eps)*sin(lambda)); *distance = delta; }
int lunar_longitude( mpfr_t *result, mpfr_t *moment ) { mpfr_t C, mean_moon, elongation, solar_anomaly, lunar_anomaly, moon_node, E, correction, venus, jupiter, flat_earth, N, fullangle; mpfr_init(C); julian_centuries( &C, moment ); { mpfr_t a, b, c, d, e; mpfr_init(mean_moon); mpfr_init_set_d(a, 218.316591, GMP_RNDN); mpfr_init_set_d(b, 481267.88134236, GMP_RNDN); mpfr_init_set_d(c, -0.0013268, GMP_RNDN); mpfr_init_set_ui(d, 1, GMP_RNDN); mpfr_div_ui(d, d, 538841, GMP_RNDN); mpfr_init_set_si(e, -1, GMP_RNDN); mpfr_div_ui(e, e, 65194000, GMP_RNDN); polynomial( &mean_moon, &C, 5, &a, &b, &c, &d, &e ); mpfr_clear(a); mpfr_clear(b); mpfr_clear(c); mpfr_clear(d); mpfr_clear(e); } { mpfr_t a, b, c, d, e; mpfr_init(elongation); mpfr_init_set_d(a, 297.8502042, GMP_RNDN); mpfr_init_set_d(b, 445267.1115168, GMP_RNDN); mpfr_init_set_d(c, -0.00163, GMP_RNDN); mpfr_init_set_ui(d, 1, GMP_RNDN); mpfr_div_ui(d, d, 545868, GMP_RNDN); mpfr_init_set_si(e, -1, GMP_RNDN); mpfr_div_ui(e, e, 113065000, GMP_RNDN); polynomial( &elongation, &C, 5, &a, &b, &c, &d, &e ); mpfr_clear(a); mpfr_clear(b); mpfr_clear(c); mpfr_clear(d); mpfr_clear(e); } { mpfr_t a, b, c, d; mpfr_init(solar_anomaly); mpfr_init_set_d(a, 357.5291092, GMP_RNDN); mpfr_init_set_d(b, 35999.0502909, GMP_RNDN); mpfr_init_set_d(c, -0.0001536, GMP_RNDN); mpfr_init_set_ui(d, 1, GMP_RNDN); mpfr_div_ui(d, d, 24490000, GMP_RNDN); polynomial( &solar_anomaly, &C, 4, &a, &b, &c, &d ); mpfr_clear(a); mpfr_clear(b); mpfr_clear(c); mpfr_clear(d); } { mpfr_t a, b, c, d, e; mpfr_init(lunar_anomaly); mpfr_init_set_d(a, 134.9634114, GMP_RNDN); mpfr_init_set_d(b, 477198.8676313, GMP_RNDN); mpfr_init_set_d(c, 0.0008997, GMP_RNDN); mpfr_init_set_ui(d, 1, GMP_RNDN); mpfr_div_ui(d, d, 69699, GMP_RNDN); mpfr_init_set_si(e, -1, GMP_RNDN); mpfr_div_ui(e, e, 14712000, GMP_RNDN); polynomial( &lunar_anomaly, &C, 5, &a, &b, &c, &d, &e); mpfr_clear(a); mpfr_clear(b); mpfr_clear(c); mpfr_clear(d); mpfr_clear(e); } { mpfr_t a, b, c, d, e; mpfr_init(moon_node); mpfr_init_set_d(a, 93.2720993, GMP_RNDN); mpfr_init_set_d(b, 483202.0175273, GMP_RNDN); mpfr_init_set_d(c, -0.0034029, GMP_RNDN); mpfr_init_set_si(d, -1, GMP_RNDN); mpfr_div_ui(d, d, 3526000, GMP_RNDN); mpfr_init_set_ui(e, 1, GMP_RNDN); mpfr_div_ui(e, e, 863310000, GMP_RNDN); polynomial(&moon_node, &C, 5, &a, &b, &c, &d, &e); mpfr_clear(a); mpfr_clear(b); mpfr_clear(c); mpfr_clear(d); mpfr_clear(e); } { mpfr_t a, b, c; mpfr_init(E); mpfr_init_set_ui(a, 1, GMP_RNDN); mpfr_init_set_d(b, -0.002516, GMP_RNDN); mpfr_init_set_d(c, -0.0000074, GMP_RNDN); polynomial( &E, &C, 3, &a, &b, &c ); mpfr_clear(a); mpfr_clear(b); mpfr_clear(c); } { int i; mpfr_t fugly; mpfr_init_set_ui(fugly, 0, GMP_RNDN); for(i = 0; i < LUNAR_LONGITUDE_ARGS_SIZE; i++) { mpfr_t a, b, v, w, x, y, z; mpfr_init_set_d( v, LUNAR_LONGITUDE_ARGS[i][0], GMP_RNDN ); mpfr_init_set_d( w, LUNAR_LONGITUDE_ARGS[i][1], GMP_RNDN ); mpfr_init_set_d( x, LUNAR_LONGITUDE_ARGS[i][2], GMP_RNDN ); mpfr_init_set_d( y, LUNAR_LONGITUDE_ARGS[i][3], GMP_RNDN ); mpfr_init_set_d( z, LUNAR_LONGITUDE_ARGS[i][4], GMP_RNDN ); mpfr_init(b); mpfr_pow(b, E, x, GMP_RNDN); mpfr_mul(w, w, elongation, GMP_RNDN); mpfr_mul(x, x, solar_anomaly, GMP_RNDN); mpfr_mul(y, y, lunar_anomaly, GMP_RNDN); mpfr_mul(z, z, moon_node, GMP_RNDN); mpfr_init_set(a, w, GMP_RNDN); mpfr_add(a, a, x, GMP_RNDN); mpfr_add(a, a, y, GMP_RNDN); mpfr_add(a, a, z, GMP_RNDN); dt_astro_sin(&a, &a); mpfr_mul(a, a, v, GMP_RNDN); mpfr_mul(a, a, b, GMP_RNDN); mpfr_add(fugly, fugly, a, GMP_RNDN); mpfr_clear(a); mpfr_clear(b); mpfr_clear(v); mpfr_clear(w); mpfr_clear(x); mpfr_clear(y); mpfr_clear(z); } mpfr_init_set_d( correction, 0.000001, GMP_RNDN ); mpfr_mul( correction, correction, fugly, GMP_RNDN); mpfr_clear(fugly); } { mpfr_t a, b; mpfr_init(venus); mpfr_init_set_d(a, 119.75, GMP_RNDN); mpfr_init_set(b, C, GMP_RNDN); mpfr_mul_d(b, b, 131.849, GMP_RNDN); mpfr_add(a, a, b, GMP_RNDN); dt_astro_sin(&a, &a); mpfr_mul_d(venus, a, 0.003957, GMP_RNDN ); mpfr_clear(a); mpfr_clear(b); } { mpfr_t a, b; mpfr_init(jupiter); mpfr_init_set_d(a, 53.09, GMP_RNDN); mpfr_init_set(b, C, GMP_RNDN); mpfr_mul_d(b, b, 479264.29, GMP_RNDN); mpfr_add(a, a, b, GMP_RNDN); dt_astro_sin(&a, &a); mpfr_mul_d(jupiter, a, 0.000318, GMP_RNDN ); mpfr_clear(a); mpfr_clear(b); } { mpfr_t a; mpfr_init(flat_earth); mpfr_init_set(a, mean_moon, GMP_RNDN); mpfr_sub(a, a, moon_node, GMP_RNDN); dt_astro_sin(&a, &a); mpfr_mul_d(flat_earth, a, 0.001962, GMP_RNDN); mpfr_clear(a); } mpfr_set(*result, mean_moon, GMP_RNDN); mpfr_add(*result, *result, correction, GMP_RNDN); mpfr_add(*result, *result, venus, GMP_RNDN); mpfr_add(*result, *result, jupiter, GMP_RNDN); mpfr_add(*result, *result, flat_earth, GMP_RNDN); #ifdef ANNOYING_DEBUG #if (ANNOYING_DEBUG) mpfr_fprintf(stderr, "mean_moon = %.10RNf\ncorrection = %.10RNf\nvenus = %.10RNf\njupiter = %.10RNf\nflat_earth = %.10RNf\n", mean_moon, correction, venus, jupiter, flat_earth); #endif #endif mpfr_init(N); nutation(&N, moment); mpfr_add(*result, *result, N, GMP_RNDN); mpfr_init_set_ui(fullangle, 360, GMP_RNDN); #ifdef ANNOYING_DEBUG #if (ANNOYING_DEBUG) mpfr_fprintf(stderr, "lunar = mod(%.10RNf) = ", *result ); #endif #endif dt_astro_mod(result, result, &fullangle); #ifdef ANNOYING_DEBUG #if (ANNOYING_DEBUG) mpfr_fprintf(stderr, "%.10RNf\n", *result ); #endif #endif mpfr_clear(C); mpfr_clear(mean_moon); mpfr_clear(elongation); mpfr_clear(solar_anomaly); mpfr_clear(lunar_anomaly); mpfr_clear(moon_node); mpfr_clear(E); mpfr_clear(correction); mpfr_clear(venus); mpfr_clear(jupiter); mpfr_clear(flat_earth); mpfr_clear(N); mpfr_clear(fullangle); return 1; }
/* given the modified JD, mj, correct, IN PLACE, the right ascension *ra * and declination *dec (both in radians) for nutation. */ void nut_eq (double mj, double *ra, double *dec) { static double lastmj = -10000; static double a[3][3]; /* rotation matrix */ double xold, yold, zold, x, y, z; if (mj != lastmj) { double epsilon, dpsi, deps; double se, ce, sp, cp, sede, cede; obliquity(mj, &epsilon); nutation(mj, &deps, &dpsi); /* the rotation matrix a applies the nutation correction to * a vector of equatoreal coordinates Xeq to Xeq' by 3 subsequent * rotations: R1 - from equatoreal to ecliptic system by * rotation of angle epsilon about x, R2 - rotate ecliptic * system by -dpsi about its z, R3 - from ecliptic to equatoreal * by rotation of angle -(epsilon + deps) * * Xeq' = A * Xeq = R3 * R2 * R1 * Xeq * * [ 1 0 0 ] * R1 = [ 0 cos(eps) sin(eps) ] * [ 0 - sin(eps) cos(eps) ] * * [ cos(dpsi) - sin(dpsi) 0 ] * R2 = [ sin(dpsi) cos(dpsi) 0 ] * [ 0 0 1 ] * * [ 1 0 0 ] * R3 = [ 0 cos(eps + deps) - sin(eps + deps) ] * [ 0 sin(eps + deps) cos(eps + deps) ] * * for efficiency, here is a explicitely: */ se = sin(epsilon); ce = cos(epsilon); sp = sin(dpsi); cp = cos(dpsi); sede = sin(epsilon + deps); cede = cos(epsilon + deps); a[0][0] = cp; a[0][1] = -sp*ce; a[0][2] = -sp*se; a[1][0] = cede*sp; a[1][1] = cede*cp*ce+sede*se; a[1][2] = cede*cp*se-sede*ce; a[2][0] = sede*sp; a[2][1] = sede*cp*ce-cede*se; a[2][2] = sede*cp*se+cede*ce; lastmj = mj; } sphcart(*ra, *dec, 1.0, &xold, &yold, &zold); x = a[0][0] * xold + a[0][1] * yold + a[0][2] * zold; y = a[1][0] * xold + a[1][1] * yold + a[1][2] * zold; z = a[2][0] * xold + a[2][1] * yold + a[2][2] * zold; cartsph(x, y, z, ra, dec, &zold); /* radius should be 1.0 */ if (*ra < 0.) *ra += 2.*PI; /* make positive for display */ }