/* * Sun clock - astronomical routines. */ #include "sunclock.h" long jdate(struct tm *); double jtime(struct tm *); double kepler(double m, double ecc); void sunpos(double jd, int apparent, double *ra, double *dec, double *rv, double *slong); double gmst(double jd); /* JDATE -- Convert internal GMT date and time to Julian day and fraction. */ long jdate(t) struct tm *t; { long c, m, y; y = t->tm_year + 1900; m = t->tm_mon + 1; if (m > 2) m = m - 3; else { m = m + 9; y--; } c = y / 100L; /* Compute century */ y -= 100L * c; return t->tm_mday + (c * 146097L) / 4 + (y * 1461L) / 4 + (m * 153L + 2) / 5 + 1721119L; } /* JTIME -- Convert internal GMT date and time to astronomical Julian time (i.e. Julian date plus day fraction, expressed as a double). */ double jtime(t) struct tm *t; { return (jdate(t) - 0.5) + (((long) t->tm_sec) + 60L * (t->tm_min + 60L * t->tm_hour)) / 86400.0; } /* KEPLER -- Solve the equation of Kepler. */ double kepler(m, ecc) double m, ecc; { double e, delta; #define EPSILON 1E-6 e = m = dtr(m); do { delta = e - ecc * sin(e) - m; e -= delta / (1 - ecc * cos(e)); } while (abs(delta) > EPSILON); return e; } /* SUNPOS -- Calculate position of the Sun. JD is the Julian date of the instant for which the position is desired and APPARENT should be nonzero if the apparent position (corrected for nutation and aberration) is desired. The Sun's co-ordinates are returned in RA and DEC, both specified in degrees (divide RA by 15 to obtain hours). The radius vector to the Sun in astronomical units is returned in RV and the Sun's longitude (true or apparent, as desired) is returned as degrees in SLONG. */ void sunpos(jd, apparent, ra, dec, rv, slong) double jd; int apparent; double *ra, *dec, *rv, *slong; { double t, t2, t3, l, m, e, ea, v, theta, omega, eps; /* Time, in Julian centuries of 36525 ephemeris days, measured from the epoch 1900 January 0.5 ET. */ t = (jd - 2415020.0) / 36525.0; t2 = t * t; t3 = t2 * t; /* Geometric mean longitude of the Sun, referred to the mean equinox of the date. */ l = fixangle(279.69668 + 36000.76892 * t + 0.0003025 * t2); /* Sun's mean anomaly. */ m = fixangle(358.47583 + 35999.04975*t - 0.000150*t2 - 0.0000033*t3); /* Eccentricity of the Earth's orbit. */ e = 0.01675104 - 0.0000418 * t - 0.000000126 * t2; /* Eccentric anomaly. */ ea = kepler(m, e); /* True anomaly */ v = fixangle(2 * rtd(atan(sqrt((1 + e) / (1 - e)) * tan(ea / 2)))); /* Sun's true longitude. */ theta = l + v - m; /* Obliquity of the ecliptic. */ eps = 23.452294 - 0.0130125 * t - 0.00000164 * t2 + 0.000000503 * t3; /* Corrections for Sun's apparent longitude, if desired. */ if (apparent) { omega = fixangle(259.18 - 1934.142 * t); theta = theta - 0.00569 - 0.00479 * sin(dtr(omega)); eps += 0.00256 * cos(dtr(omega)); } /* Return Sun's longitude and radius vector */ *slong = theta; *rv = (1.0000002 * (1 - e * e)) / (1 + e * cos(dtr(v))); /* Determine solar co-ordinates. */ *ra = fixangle(rtd(atan2(cos(dtr(eps)) * sin(dtr(theta)), cos(dtr(theta))))); *dec = rtd(asin(sin(dtr(eps)) * sin(dtr(theta)))); } /* GMST -- Calculate Greenwich Mean Siderial Time for a given instant expressed as a Julian date and fraction. */ double gmst(jd) double jd; { double t, theta0; /* Time, in Julian centuries of 36525 ephemeris days, measured from the epoch 1900 January 0.5 ET. */ t = ((floor(jd + 0.5) - 0.5) - 2415020.0) / 36525.0; theta0 = 6.6460656 + 2400.051262 * t + 0.00002581 * t * t; t = (jd + 0.5) - (floor(jd + 0.5)); theta0 += (t * 24.0) * 1.002737908; theta0 = (theta0 - 24.0 * (floor(theta0 / 24.0))); return theta0; }