allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (06/04/89)
Posting-number: Volume 7, Issue 11 Submitted-by: ecd@ncs-med.UUCP (Elwood C. Downey) Archive-name: ephem/part03 [BTW, not putting "guard characters" at the beginnings of lines in a shar'ed file is asking for trouble on some systems. Especially with idiot UUCP mail systems -- some, perhaps all, of this group *does* get sent over mail links. One "From" will produce a mangled transmission. And Bitnet seems to know of other ways to destroy such files. ++bsa] #!/bin/sh echo mkdir lib mkdir lib echo cd lib cd lib echo extracting Makefile cat > Makefile << 'xXx' CLNFLAGS=$(CLNF) LNFLAGS=$(CLNFLAGS) $(LNF) CFLAGS=$(CLNFLAGS) $(CF) LINTFLAGS=$(CFLAGS) $(LINTF) LINTLIBS= .c.a: -$(CC) -c $(CFLAGS) $< .PRECIOUS: lib.a lib.a: lib.a(aa_hadec.o) \ lib.a(anomaly.o) \ lib.a(cal_mjd.o) \ lib.a(eq_ecl.o) \ lib.a(moon.o) \ lib.a(moonnf.o) \ lib.a(moonrs.o) \ lib.a(nutation.o) \ lib.a(obliq.o) \ lib.a(parallax.o) \ lib.a(pelement.o) \ lib.a(plans.o) \ lib.a(precess.o) \ lib.a(refract.o) \ lib.a(riset.o) \ lib.a(sex_dec.o) \ lib.a(sun.o) \ lib.a(sunrs.o) \ lib.a(utc_gst.o) ar rv $@ $? ranlib $@ rm -f $? xXx echo extracting aa_hadec.c cat > aa_hadec.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* given latitude (n+, radians), lat, altitude (up+, radians), alt, and * azimuth (angle round to the east from north+, radians), * return hour angle (radians), ha, and declination (radians), dec. */ aa_hadec (lat, alt, az, ha, dec) float lat; float alt, az; float *ha, *dec; { aaha_aux (lat, az, alt, ha, dec); } /* given latitude (n+, radians), lat, hour angle (radians), ha, and declination * (radians), dec, * return altitude (up+, radians), alt, and * azimuth (angle round to the east from north+, radians), */ hadec_aa (lat, ha, dec, alt, az) float lat; float ha, dec; float *alt, *az; { aaha_aux (lat, ha, dec, az, alt); } /* the actual formula is the same for both transformation directions so * do it here once for each way. * N.B. all arguments are in radians. */ static aaha_aux (lat, x, y, p, q) float lat; float x, y; float *p, *q; { static float lastlat = -1000.; static float sinlastlat, coslastlat; float sy, cy; float sx, cx; float sq, cq; float a; float cp; /* latitude doesn't change much, so try to reuse the sin and cos evals. */ if (lat != lastlat) { sinlastlat = sin (lat); coslastlat = cos (lat); lastlat = lat; } sy = sin (y); cy = cos (y); sx = sin (x); cx = cos (x); /* define GOODATAN2 if atan2 returns full range -PI through +PI. */ #ifdef GOODATAN2 *q = asin ((sy*sinlastlat) + (cy*coslastlat*cx)); *p = atan2 (-cy*sx, -cy*cx*sinlastlat + sy*coslastlat); #else #define EPS (1e-20) sq = (sy*sinlastlat) + (cy*coslastlat*cx); *q = asin (sq); cq = cos (*q); a = coslastlat*cq; if (a > -EPS && a < EPS) a = a < 0 ? -EPS : EPS; /* avoid / 0 */ cp = (sy - (sinlastlat*sq))/a; if (cp >= 1.0) /* the /a can be slightly > 1 */ *p = 0.0; else if (cp <= -1.0) *p = PI; else *p = acos ((sy - (sinlastlat*sq))/a); if (sx>0) *p = 2.0*PI - *p; #endif } xXx echo extracting anomaly.c cat > anomaly.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" #define TWOPI (2*PI) /* given the mean anomaly, ma, and the eccentricity, s, of elliptical motion, * find the true anomaly, *nu, and the eccentric anomaly, *ea. * all angles in radians. */ anomaly (ma, s, nu, ea) float ma, s; float *nu, *ea; { float m, dla, fea; m = ma-TWOPI*(int)(ma/TWOPI); fea = m; while (1) { dla = fea-(s*sin(fea))-m; if (fabs(dla)<1e-6) break; dla /= 1-(s*cos(fea)); fea -= dla; } *nu = 2*atan(sqrt((1+s)/(1-s))*tan(fea/2)); *ea = fea; } xXx echo extracting astro.h cat > astro.h << 'xXx' #ifndef PI #define PI 3.141592653589793 #endif /* conversions among hours (of ra), degrees and radians. */ #define degrad(x) ((x)*PI/180.) #define raddeg(x) ((x)*180./PI) #define hrdeg(x) ((x)*15.) #define deghr(x) ((x)/15.) #define hrrad(x) degrad(hrdeg(x)) #define radhr(x) deghr(raddeg(x)) /* manifest names for planets. * N.B. must cooincide with usage in pelement.c and plans.c. */ #define MERCURY 0 #define VENUS 1 #define MARS 2 #define JUPITER 3 #define SATURN 4 #define URANUS 5 #define NEPTUNE 6 #define PLUTO 7 xXx echo extracting cal_mjd.c cat > cal_mjd.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* given a date in months, mn, days, dy, years, yr, * return the modified Julian date (number of days elapsed since 1900 jan 0.5), * *mjd. */ cal_mjd (mn, dy, yr, mjd) int mn, yr; float dy; float *mjd; { int b, d, m, y; long c; m = mn; y = (yr < 0) ? yr + 1 : yr; if (mn < 3) { m += 12; y -= 1; } if (yr < 1582 || yr == 1582 && (mn < 10 || mn == 10 && dy < 15)) b = 0; else { int a; a = y/100; b = 2 - a + a/4; } if (y < 0) c = (long)((365.25*y) - 0.75) - 694025L; else c = (long)(365.25*y) - 694025L; d = 30.6001*(m+1); *mjd = b + c + d + dy - 0.5; } /* given the modified Julian date (number of days elapsed since 1900 jan 0.5,), * mjd, return the calendar date in months, *mn, days, *dy, and years, *yr. */ mjd_cal (mjd, mn, dy, yr) float mjd; int *mn, *yr; float *dy; { float d, f; float i, a, b, ce, g; d = mjd + 0.5; i = floor(d); f = d-i; if (f == 1) { f = 0; i += 1; } if (i > -115860.0) { a = floor((i/36524.25)+.9983573)+14; i += 1 + a - floor(a/4.0); } b = floor((i/365.25)+.802601); ce = i - floor((365.25*b)+.750001)+416; g = floor(ce/30.6001); *mn = g - 1; *dy = ce - floor(30.6001*g)+f; *yr = b + 1899; if (g > 13.5) *mn = g - 13; if (*mn < 2.5) *yr = b + 1900; if (*yr < 1) *yr -= 1; } /* given an mjd, set *dow to 0..6 according to which dayof the week it falls * on (0=sunday) or set it to -1 if can't figure it out. */ mjd_dow (mjd, dow) float mjd; int *dow; { /* cal_mjd() uses Gregorian dates on or after Oct 15, 1582. * (Pope Gregory XIII dropped 10 days, Oct 5..14, and improved the leap- * year algorithm). however, Great Britian and the colonies did not * adopt it until Sept 14, 1752 (they dropped 11 days, Sept 3-13, * due to additional accumulated error). leap years before 1752 thus * can not easily be accounted for from the cal_mjd() number... */ if (mjd < -53798.5) { /* pre sept 14, 1752 too hard to correct */ *dow = -1; return; } *dow = ((int)floor(mjd-.5) + 1) % 7; /* 1/1/1900 (mjd 0.5) is a Monday*/ if (*dow < 0) *dow += 7; } /* given a mjd, return the the number of days in the month. */ mjd_dpm (mjd, ndays) float mjd; int *ndays; { static short dpm[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int m, y; float d; mjd_cal (mjd, &m, &d, &y); *ndays = (m==2 && ((y%4==0 && y%100!=0)||y%400==0)) ? 29 : dpm[m-1]; } xXx echo extracting eq_ecl.c cat > eq_ecl.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" #define EQtoECL 1 #define ECLtoEQ (-1) /* given the modified Julian date, mjd, and an equitorial ra and dec, each in * radians, find the corresponding geocentric ecliptic latitude, *lat, and * longititude, *lng, also each in radians. * the effects of nutation and the angle of the obliquity are included. */ eq_ecl (mjd, ra, dec, lat, lng) float mjd, ra, dec; float *lat, *lng; { ecleq_aux (EQtoECL, mjd, ra, dec, lng, lat); } /* given the modified Julian date, mjd, and a geocentric ecliptic latitude, * *lat, and longititude, *lng, each in radians, find the corresponding * equitorial ra and dec, also each in radians. * the effects of nutation and the angle of the obliquity are included. */ ecl_eq (mjd, lat, lng, ra, dec) float mjd, lat, lng; float *ra, *dec; { ecleq_aux (ECLtoEQ, mjd, lng, lat, ra, dec); } static ecleq_aux (sw, mjd, x, y, p, q) int sw; /* +1 for eq to ecliptic, -1 for vv. */ float mjd, x, y; /* sw==1: x==ra, y==dec. sw==-1: x==lng, y==lat. */ float *p, *q; /* sw==1: p==lng, q==lat. sw==-1: p==ra, q==dec. */ { static float lastmjd; /* last mjd calculated */ static float seps, ceps; /* sin and cos of mean obliquity */ float sx, cx, sy, cy, ty; if (mjd != lastmjd) { float deps, dpsi, eps; obliquity (mjd, &eps); /* mean obliquity for date */ #ifdef NONUTATION #define NONUTATION deps = 0; /* checkout handler did not * include nutation correction. */ #else nutation (mjd, &deps, &dpsi); /* correctin due to nutation */ #endif eps += deps; /* true obliquity for date */ seps = sin(eps); ceps = cos(eps); lastmjd = mjd; } sy = sin(y); cy = cos(y); /* always non-negative */ if (fabs(cy)<1e-20) cy = 1e-20; /* insure > 0 */ ty = sy/cy; cx = cos(x); sx = sin(x); *q = asin((sy*ceps)-(cy*seps*sx*sw)); *p = atan(((sx*ceps)+(ty*seps*sw))/cx); if (cx<0) *p += PI; /* account for atan quad ambiguity */ range (p, 2*PI); } xXx echo extracting moon.c cat > moon.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* given the mjd, find the geocentric ecliptic longitude, lam, and latitude, * bet, and horizontal parallax, hp for the moon. * N.B. series for long and lat are good to about 10 and 3 arcseconds. however, * math errors cause up to 100 and 30 arcseconds error, even if use double. * why?? suspect highly sensitive nature of difference used to get m1..6. * N.B. still need to correct for nutation. then for topocentric location * further correct for parallax and refraction. */ moon (mjd, lam, bet, hp) float mjd; float *lam, *bet, *hp; { float t, t2; float ld; float ms; float md; float de; float f; float n; float a, sa, sn, b, sb, c, sc, e, e2, l, g, w1, w2; float m1, m2, m3, m4, m5, m6; t = mjd/36525.; t2 = t*t; m1 = mjd/27.32158213; m1 = 360.0*(m1-(int)m1); m2 = mjd/365.2596407; m2 = 360.0*(m2-(int)m2); m3 = mjd/27.55455094; m3 = 360.0*(m3-(int)m3); m4 = mjd/29.53058868; m4 = 360.0*(m4-(int)m4); m5 = mjd/27.21222039; m5 = 360.0*(m5-(int)m5); m6 = mjd/6798.363307; m6 = 360.0*(m6-(int)m6); ld = 270.434164+m1-(.001133-.0000019*t)*t2; ms = 358.475833+m2-(.00015+.0000033*t)*t2; md = 296.104608+m3+(.009192+.0000144*t)*t2; de = 350.737486+m4-(.001436-.0000019*t)*t2; f = 11.250889+m5-(.003211+.0000003*t)*t2; n = 259.183275-m6+(.002078+.000022*t)*t2; a = degrad(51.2+20.2*t); sa = sin(a); sn = sin(degrad(n)); b = 346.56+(132.87-.0091731*t)*t; sb = .003964*sin(degrad(b)); c = degrad(n+275.05-2.3*t); sc = sin(c); ld = ld+.000233*sa+sb+.001964*sn; ms = ms-.001778*sa; md = md+.000817*sa+sb+.002541*sn; f = f+sb-.024691*sn-.004328*sc; de = de+.002011*sa+sb+.001964*sn; e = 1-(.002495+7.52e-06*t)*t; e2 = e*e; ld = degrad(ld); ms = degrad(ms); n = degrad(n); de = degrad(de); f = degrad(f); md = degrad(md); l = 6.28875*sin(md)+1.27402*sin(2*de-md)+.658309*sin(2*de)+ .213616*sin(2*md)-e*.185596*sin(ms)-.114336*sin(2*f)+ .058793*sin(2*(de-md))+.057212*e*sin(2*de-ms-md)+ .05332*sin(2*de+md)+.045874*e*sin(2*de-ms)+.041024*e*sin(md-ms); l = l-.034718*sin(de)-e*.030465*sin(ms+md)+.015326*sin(2*(de-f))- .012528*sin(2*f+md)-.01098*sin(2*f-md)+.010674*sin(4*de-md)+ .010034*sin(3*md)+.008548*sin(4*de-2*md)-e*.00791*sin(ms-md+2*de)- e*.006783*sin(2*de+ms); l = l+.005162*sin(md-de)+e*.005*sin(ms+de)+.003862*sin(4*de)+ e*.004049*sin(md-ms+2*de)+.003996*sin(2*(md+de))+ .003665*sin(2*de-3*md)+e*.002695*sin(2*md-ms)+ .002602*sin(md-2*(f+de))+e*.002396*sin(2*(de-md)-ms)- .002349*sin(md+de); l = l+e2*.002249*sin(2*(de-ms))-e*.002125*sin(2*md+ms)- e2*.002079*sin(2*ms)+e2*.002059*sin(2*(de-ms)-md)- .001773*sin(md+2*(de-f))-.001595*sin(2*(f+de))+ e*.00122*sin(4*de-ms-md)-.00111*sin(2*(md+f))+.000892*sin(md-3*de); l = l-e*.000811*sin(ms+md+2*de)+e*.000761*sin(4*de-ms-2*md)+ e2*.000704*sin(md-2*(ms+de))+e*.000693*sin(ms-2*(md-de))+ e*.000598*sin(2*(de-f)-ms)+.00055*sin(md+4*de)+.000538*sin(4*md)+ e*.000521*sin(4*de-ms)+.000486*sin(2*md-de); l = l+e2*.000717*sin(md-2*ms); *lam = ld+degrad(l); range (lam, 2*PI); g = 5.12819*sin(f)+.280606*sin(md+f)+.277693*sin(md-f)+ .173238*sin(2*de-f)+.055413*sin(2*de+f-md)+.046272*sin(2*de-f-md)+ .032573*sin(2*de+f)+.017198*sin(2*md+f)+.009267*sin(2*de+md-f)+ .008823*sin(2*md-f)+e*.008247*sin(2*de-ms-f); g = g+.004323*sin(2*(de-md)-f)+.0042*sin(2*de+f+md)+ e*.003372*sin(f-ms-2*de)+e*.002472*sin(2*de+f-ms-md)+ e*.002222*sin(2*de+f-ms)+e*.002072*sin(2*de-f-ms-md)+ e*.001877*sin(f-ms+md)+.001828*sin(4*de-f-md)-e*.001803*sin(f+ms)- .00175*sin(3*f); g = g+e*.00157*sin(md-ms-f)-.001487*sin(f+de)-e*.001481*sin(f+ms+md)+ e*.001417*sin(f-ms-md)+e*.00135*sin(f-ms)+.00133*sin(f-de)+ .001106*sin(f+3*md)+.00102*sin(4*de-f)+.000833*sin(f+4*de-md)+ .000781*sin(md-3*f)+.00067*sin(f+4*de-2*md); g = g+.000606*sin(2*de-3*f)+.000597*sin(2*(de+md)-f)+ e*.000492*sin(2*de+md-ms-f)+.00045*sin(2*(md-de)-f)+ .000439*sin(3*md-f)+.000423*sin(f+2*(de+md))+ .000422*sin(2*de-f-3*md)-e*.000367*sin(ms+f+2*de-md)- e*.000353*sin(ms+f+2*de)+.000331*sin(f+4*de); g = g+e*.000317*sin(2*de+f-ms+md)+e2*.000306*sin(2*(de-ms)-f)- .000283*sin(md+3*f); w1 = .0004664*cos(n); w2 = .0000754*cos(c); *bet = degrad(g)*(1-w1-w2); *hp = .950724+.051818*cos(md)+.009531*cos(2*de-md)+.007843*cos(2*de)+ .002824*cos(2*md)+.000857*cos(2*de+md)+e*.000533*cos(2*de-ms)+ e*.000401*cos(2*de-md-ms)+e*.00032*cos(md-ms)-.000271*cos(de)- e*.000264*cos(ms+md)-.000198*cos(2*f-md); *hp = *hp+.000173*cos(3*md)+.000167*cos(4*de-md)-e*.000111*cos(ms)+ .000103*cos(4*de-2*md)-.000084*cos(2*md-2*de)- e*.000083*cos(2*de+ms)+.000079*cos(2*de+2*md)+.000072*cos(4*de)+ e*.000064*cos(2*de-ms+md)-e*.000063*cos(2*de+ms-md)+ e*.000041*cos(ms+de); *hp = *hp+e*.000035*cos(2*md-ms)-.000033*cos(3*md-2*de)- .00003*cos(md+de)-.000029*cos(2*(f-de))-e*.000029*cos(2*md+ms)+ e2*.000026*cos(2*(de-ms))-.000023*cos(2*(f-de)+md)+ e*.000019*cos(4*de-ms-md); *hp = degrad(*hp); } xXx echo extracting moonnf.c cat > moonnf.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" #define unw(w,z) ((w)-floor((w)/(z))*(z)) /* given a modified Julian date, mjd, return the mjd of the new * and full moons about then, mjdn and mjdf. * TODO: exactly which ones does it find? eg: * 5/28/1988 yields 5/15 and 5/31 * 5/29 6/14 6/29 */ moonnf (mjd, mjdn, mjdf) float mjd; float *mjdn, *mjdf; { int mo, yr; float dy; float mjd0; float k, tn, tf, t; mjd_cal (mjd, &mo, &dy, &yr); cal_mjd (1, 0., yr, &mjd0); k = (yr-1900+((mjd-mjd0)/365))*12.3685; k = floor(k+0.5); tn = k/1236.85; tf = (k+0.5)/1236.85; t = tn; m (t, k, mjdn); t = tf; k += 0.5; m (t, k, mjdf); } static m (t, k, mjd) float t, k; float *mjd; { float t2, a, a1, b, b1, c, ms, mm, f, ddjd; t2 = t*t; a = 29.53*k; c = degrad(166.56+(132.87-9.173e-3*t)*t); b = 5.8868e-4*k+(1.178e-4-1.55e-7*t)*t2+3.3e-4*sin(c)+7.5933E-1; ms = 359.2242+360*unw(k/1.236886e1,1)-(3.33e-5+3.47e-6*t)*t2; mm = 306.0253+360*unw(k/9.330851e-1,1)+(1.07306e-2+1.236e-5*t)*t2; f = 21.2964+360*unw(k/9.214926e-1,1)-(1.6528e-3+2.39e-6*t)*t2; ms = unw(ms,360); mm = unw(mm,360); f = unw(f,360); ms = degrad(ms); mm = degrad(mm); f = degrad(f); ddjd = (1.734e-1-3.93e-4*t)*sin(ms)+2.1e-3*sin(2*ms) -4.068e-1*sin(mm)+1.61e-2*sin(2*mm)-4e-4*sin(3*mm) +1.04e-2*sin(2*f)-5.1e-3*sin(ms+mm)-7.4e-3*sin(ms-mm) +4e-4*sin(2*f+ms)-4e-4*sin(2*f-ms)-6e-4*sin(2*f+mm) +1e-3*sin(2*f-mm)+5e-4*sin(ms+2*mm); a1 = (int)a; b = b+ddjd+(a-a1); b1 = (int)b; a = a1+b1; b = b-b1; *mjd = a + b; } xXx echo extracting moonrs.c cat > moonrs.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" #define PASSES 2 /* given the mjd and geographical latitude and longitude, lat and lng, * find the ut and azimuth of moonrise, utcr and azr, and moonset, utcs and * azs for the day of mjd. all angles are in radians. * times are for the upper limb, including effects of refraction (a constant 34 * arcminutes), parallax, and nutation. accuracy is to nearest minute. * the calculated times can be in error if they occur within about a half hour * of utc midnight due to the algorithm's confusion about the date. the best * way to verify it is to calculate the times for several days either side of * the date to see whether the problem values conform to a smooth trend set * by the others. * possible values of status: * 2: can't cope (such as geographical latitude very near +-90). * 1: moon never rises/sets on date. * 0: all ok. * -1: moon is circumpolar. * -2: possible error in near-midnight moonrise time; see above. * -3: possible error in near-midnight moonset time; see above. */ moonrs (mjd, lat, lng, utcr, utcs, azr, azs, status) float mjd, lat, lng; float *utcr, *utcs; float *azr, *azs; int *status; { float lstr, lsts; /* local sidereal times of rising/setting */ float al = radhr(lng); /* time correction for longitude */ int midnight = 0; /* midnight caution */ float mjd0; /* start of mjd day */ float x; /* discarded tmp value */ float ut; int pass; mjd0 = floor(mjd+0.5)-0.5; /* first approximation is to find rise/set times of a fixed object * in the position of the moon at local midday. */ fixedmoonriset (mjd0+(12.0-al)/24.0, lat, &lstr, &lsts, &x, &x, status); if (*status != 0) return; /* find a better approximation to the rising circumstances based on two * more passes, each using a "fixed" object at the moons location at * previous approximation of the rise time. */ pass = 0; while (1) { gst_utc (mjd0, lstr, &ut); if (++pass > PASSES) break; fixedmoonriset (mjd0+(ut-al)/24., lat, &lstr, &x, azr, &x, status); if (*status != 0) return; } if (ut > 23.5 || ut < 0.5) midnight = -2; /* moonrise caution near midnight */ *utcr = ut - (al * .9972696); /* allow for sidereal shift */ /* find a better approximation to the setting circumstances based on two * more passes, each using a "fixed" object at the moons location at * previous approximation of the setting time. */ pass = 0; while (1) { gst_utc (mjd0, lsts, &ut); if (++pass > PASSES) break; fixedmoonriset (mjd0+(ut-al)/24., lat, &x, &lsts, &x, azs, status); if (*status != 0) return; } if (ut > 23.5 || ut < 0.5) midnight = -3; /* moonset caution near midnight */ *utcs = ut - (al * .9972696); /* allow for sidereal shift */ if (midnight) *status = midnight; /* report caution if near midnight */ } /* find the local rise/set sidereal times and azimuths of an object fixed * at the ra/dec of the moon on the given mjd time as seen from lat. */ static fixedmoonriset (mjd, lat, lstr, lsts, azr, azs, status) float mjd, lat; float *lstr, *lsts; float *azr, *azs; int *status; { float lam, bet, hp; float deps, dpsi; float dis; float ra, dec; /* find geocentric ecliptic location and equatorial horizontal parallax * of moon at mjd. */ moon (mjd, &lam, &bet, &hp); /* allow for nutation */ nutation (mjd, &deps, &dpsi); lam += dpsi; /* convert ecliptic to equatorial coords */ ecl_eq (mjd, bet, lam, &ra, &dec); /* find local sidereal times of rise/set times/azimuths for given * equatorial coords, allowing for * .27249*sin(hp) parallax (hp is radius of earth from moon; * .27249 is radius of moon from earth where * the ratio is the dia_moon/dia_earth). * 34' (9.8902e-3) nominal refraction * hp nominal angular earth radius. subtract because * tangential line-of-sight makes moon appear lower * as move out from center of earth. * TODO: do better at refraction; see fixedsunriset() in sunrs.c. */ dis = .27249*sin(hp) + 9.8902e-3 - hp; riset (ra, dec, lat, dis, lstr, lsts, azr, azs, status); } xXx echo extracting nutation.c cat > nutation.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* given the modified JD, mjd, find the nutation in obliquity, *deps, and * the nutation in longitude, *dpsi, each in radians. */ nutation (mjd, deps, dpsi) float mjd; float *deps, *dpsi; { static float lastmjd, lastdeps, lastdpsi; float ls, ld; /* sun's mean longitude, moon's mean longitude */ float ms, md; /* sun's mean anomaly, moon's mean anomaly */ float nm; /* longitude of moon's ascending node */ float t, t2; /* number of Julian centuries of 36525 days since * Jan 0.5 1900. */ float tls, tnm, tld; /* twice above */ double a, b; /* temps */ if (mjd == lastmjd) { *deps = lastdeps; *dpsi = lastdpsi; return; } t = mjd/36525.; t2 = t*t; a = 100.0021358*t; b = 360.*(a-(int)a); ls = 279.697+.000303*t2+b; a = 1336.855231*t; b = 360.*(a-(int)a); ld = 270.434-.001133*t2+b; a = 99.99736056000026*t; b = 360.*(a-(int)a); ms = 358.476-.00015*t2+b; a = 13255523.59*t; b = 360.*(a-(int)a); md = 296.105+.009192*t2+b; a = 5.372616667*t; b = 360.*(a-(int)a); nm = 259.183+.002078*t2-b; /* convert to radian forms for use with trig functions. */ tls = 2*degrad(ls); nm = degrad(nm); tnm = 2*degrad(nm); ms = degrad(ms); tld = 2*degrad(ld); md = degrad(md); /* find delta psi and eps, in arcseconds. */ lastdpsi = (-17.2327-.01737*t)*sin(nm)+(-1.2729-.00013*t)*sin(tls) +.2088*sin(tnm)-.2037*sin(tld)+(.1261-.00031*t)*sin(ms) +.0675*sin(md)-(.0497-.00012*t)*sin(tls+ms) -.0342*sin(tld-nm)-.0261*sin(tld+md)+.0214*sin(tls-ms) -.0149*sin(tls-tld+md)+.0124*sin(tls-nm)+.0114*sin(tld-md); lastdeps = (9.21+.00091*t)*cos(nm)+(.5522-.00029*t)*cos(tls) -.0904*cos(tnm)+.0884*cos(tld)+.0216*cos(tls+ms) +.0183*cos(tld-nm)+.0113*cos(tld+md)-.0093*cos(tls-ms) -.0066*cos(tls-nm); /* convert to radians. */ lastdpsi = degrad(lastdpsi/3600); lastdeps = degrad(lastdeps/3600); lastmjd = mjd; *deps = lastdeps; *dpsi = lastdpsi; } xXx echo extracting obliq.c cat > obliq.c << 'xXx' #include <stdio.h> #include "astro.h" /* given the modified Julian date, mjd, find the obliquity of the * ecliptic, *eps, in radians. */ obliquity (mjd, eps) float mjd; float *eps; { static float lastmjd, lasteps; if (mjd != lastmjd) { float t; t = mjd/36525.; lasteps = degrad(2.345229444E1 - ((((-1.81E-3*t)+5.9E-3)*t+4.6845E1)*t)/3600.0); lastmjd = mjd; } *eps = lasteps; } xXx echo extracting parallax.c cat > parallax.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* given true ha and dec, tha and tdec, the geographical latitude, phi, the * height above sea-level (as a fraction of the earths radius, 6378.16km), * ht, and the equatorial horizontal parallax, ehp, find the apparent * ha and dec, aha and adec allowing for parallax. * all angles in radians. ehp is the angle subtended at the body by the * earth's equator. */ ta_par (tha, tdec, phi, ht, ehp, aha, adec) float tha, tdec, phi, ht, ehp; float *aha, *adec; { static float last_phi, last_ht, rsp, rcp; float rp; /* distance to object in Earth radii */ float ctha; float stdec, ctdec; float tdtha, dtha; float caha; /* avoid calcs involving the same phi and ht */ if (phi != last_phi || ht != last_ht) { float cphi, sphi, u; cphi = cos(phi); sphi = sin(phi); u = atan(9.96647e-1*sphi/cphi); rsp = (9.96647e-1*sin(u))+(ht*sphi); rcp = cos(u)+(ht*cphi); last_phi = phi; last_ht = ht; } rp = 1/sin(ehp); ctha = cos(tha); stdec = sin(tdec); ctdec = cos(tdec); tdtha = (rcp*sin(tha))/((rp*ctdec)-(rcp*ctha)); dtha = atan(tdtha); *aha = tha+dtha; caha = cos(*aha); range (aha, 2*PI); *adec = atan(caha*(rp*stdec-rsp)/(rp*ctdec*ctha-rcp)); } /* given the apparent ha and dec, aha and adec, the geographical latitude, phi, * the height above sea-level (as a fraction of the earths radius, 6378.16km), * ht, and the equatorial horizontal parallax, ehp, find the true ha and dec, * tha and tdec allowing for parallax. * all angles in radians. ehp is the angle subtended at the body by the * earth's equator. * uses ta_par() iteratively: find a set of true ha/dec that converts back * to the given apparent ha/dec. */ at_par (aha, adec, phi, ht, ehp, tha, tdec) float aha, adec, phi, ht, ehp; float *tha, *tdec; { float nha, ndec; /* ha/dec corres. to current true guesses */ float eha, edec; /* error in ha/dec */ /* first guess for true is just the apparent */ *tha = aha; *tdec = adec; while (1) { ta_par (*tha, *tdec, phi, ht, ehp, &nha, &ndec); eha = aha - nha; edec = adec - ndec; if (fabs(eha)<1e-6 && fabs(edec)<1e-6) break; *tha += eha; *tdec += edec; } } xXx echo extracting pelement.c cat > pelement.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* this array contains polynomial coefficients to find the various orbital * elements for the mean orbit at any instant in time for each major planet. * the first five elements are in the form a0 + a1*t + a2*t**2 + a3*t**3, * where t is the number of Julian centuries of 36525 Julian days since 1900 * Jan 0.5. the last three elements are constants. * * the orbital element (column) indeces are: * [ 0- 3]: coefficients for mean longitude, in degrees; * [ 4- 7]: coefficients for longitude of the perihelion, in degrees; * [ 8-11]: coefficients for eccentricity; * [12-15]: coefficients for inclination, in degrees; * [16-19]: coefficients for longitude of the ascending node, in degrees; * [20]: semi-major axis, in AU; * [21]: angular diameter at 1 AU, in arcsec; * [22]: standard visual magnitude, ie, the visual magnitude of the planet * when at a distance of 1 AU from both the Sun and the Earth and * with zero phase angle. * * the planent (row) indeces are: * [0]: Mercury; [1]: Venus; [2]: Mars; [3]: Jupiter; [4]: Saturn; * [5]: Uranus; [6]: Neptune; [7]: Pluto. */ #define NPELE (5*4 + 3) /* 4 coeffs for ea of 5 elems, + 3 constants */ static float elements[8][NPELE] = { { /* mercury... */ 178.179078, 415.2057519, 3.011e-4, 0.0, 75.899697, 1.5554889, 2.947e-4, 0.0, .20561421, 2.046e-5, 3e-8, 0.0, 7.002881, 1.8608e-3, -1.83e-5, 0.0, 47.145944, 1.1852083, 1.739e-4, 0.0, .3870986, 6.74, -0.42 }, { /* venus... */ 342.767053, 162.5533664, 3.097e-4, 0.0, 130.163833, 1.4080361, -9.764e-4, 0.0, 6.82069e-3, -4.774e-5, 9.1e-8, 0.0, 3.393631, 1.0058e-3, -1e-6, 0.0, 75.779647, .89985, 4.1e-4, 0.0, .7233316, 16.92, -4.4 }, { /* mars... */ 293.737334, 53.17137642, 3.107e-4, 0.0, 3.34218203e2, 1.8407584, 1.299e-4, -1.19e-6, 9.33129e-2, 9.2064e-5, 7.7e-8, 0.0, 1.850333, -6.75e-4, 1.26e-5, 0.0, 48.786442, .7709917, -1.4e-6, -5.33e-6, 1.5236883, 9.36, -1.52 }, { /* jupiter... */ 238.049257, 8.434172183, 3.347e-4, -1.65e-6, 1.2720972e1, 1.6099617, 1.05627e-3, -3.43e-6, 4.833475e-2, 1.6418e-4, -4.676e-7, -1.7e-9, 1.308736, -5.6961e-3, 3.9e-6, 0.0, 99.443414, 1.01053, 3.5222e-4, -8.51e-6, 5.202561, 196.74, -9.4 }, { /* saturn... */ 266.564377, 3.398638567, 3.245e-4, -5.8e-6, 9.1098214e1, 1.9584158, 8.2636e-4, 4.61e-6, 5.589232e-2, -3.455e-4, -7.28e-7, 7.4e-10, 2.492519, -3.9189e-3, -1.549e-5, 4e-8, 112.790414, .8731951, -1.5218e-4, -5.31e-6, 9.554747, 165.6, -8.88 }, { /* uranus... */ 244.19747, 1.194065406, 3.16e-4, -6e-7, 1.71548692e2, 1.4844328, 2.372e-4, -6.1e-7, 4.63444e-2, -2.658e-5, 7.7e-8, 0.0, .772464, 6.253e-4, 3.95e-5, 0.0, 73.477111, .4986678, 1.3117e-3, 0.0, 19.21814, 65.8, -7.19 }, { /* neptune... */ 84.457994, .6107942056, 3.205e-4, -6e-7, 4.6727364e1, 1.4245744, 3.9082e-4, -6.05e-7, 8.99704e-3, 6.33e-6, -2e-9, 0.0, 1.779242, -9.5436e-3, -9.1e-6, 0.0, 130.681389, 1.098935, 2.4987e-4, -4.718e-6, 30.10957, 62.2, -6.87 }, { /* pluto...(osculating 1984 jan 21) */ 95.3113544, .3980332167, 0.0, 0.0, 224.017, 0.0, 0.0, 0.0, .25515, 0.0, 0.0, 0.0, 17.1329, 0.0, 0.0, 0.0, 110.191, 0.0, 0.0, 0.0, 39.8151, 8.2, -1.0 } }; /* given a modified Julian date, mjd, return the elements for the mean orbit * at that instant of all the major planets, together with their * mean daily motions in longitude, angular diameter and standard visual * magnitude. * plan[i][j] contains all the values for all the planets at mjd, such that * i = 0..7: mercury, venus, mars, jupiter, saturn, unranus, neptune, pluto; * j = 0..8: mean longitude, mean daily motion in longitude, longitude of * the perihelion, eccentricity, inclination, longitude of the ascending * node, length of the semi-major axis, angular diameter from 1 AU, and * the standard visual magnitude (see elements[][] comment, above). */ pelement (mjd, plan) float mjd; float plan[8][9]; { register float *ep, *pp; register float t = mjd/36525.; float aa; int planet, i; for (planet = 0; planet < 8; planet++) { ep = elements[planet]; pp = plan[planet]; aa = ep[1]*t; pp[0] = ep[0] + 360.*(aa-(int)aa) + (ep[3]*t + ep[2])*t*t; range (pp, 360.); pp[1] = (ep[1]*9.856263e-3) + (ep[2] + ep[3])/36525; for (i = 4; i < 20; i += 4) pp[i/4+1] = ((ep[i+3]*t + ep[i+2])*t + ep[i+1])*t + ep[i+0]; pp[6] = ep[20]; pp[7] = ep[21]; pp[8] = ep[22]; } } xXx echo extracting plans.c cat > plans.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" #define TWOPI (2*PI) #define mod2PI(x) ((x) - (int)((x)/TWOPI)*TWOPI) /* given a modified Julian date, mjd, and a planet, p, find: * lpd0: heliocentric longitude, * psi0: heliocentric latitude, * rp0: distance from the sun to the planet, * rho0: distance from the Earth to the planet, * none corrected for light time, ie, they are the true values for the * given instant. * lam: geocentric ecliptic longitude, * bet: geocentric ecliptic latitude, * each corrected for light time, ie, they are the apparent values as * seen from the center of the Earth for the given instant. * dia: angular diameter in arcsec at 1 AU, * mag: visual magnitude when 1 AU from sun and earth at 0 phase angle. * * all angles are in radians, all distances in AU. * the mean orbital elements are found by calling pelement(), then mutual * perturbation corrections are applied as necessary. * * corrections for nutation and abberation must be made by the caller. The RA * and DEC calculated from the fully-corrected ecliptic coordinates are then * the apparent geocentric coordinates. Further corrections can be made, if * required, for atmospheric refraction and geocentric parallax although the * intrinsic error herein of about 10 arcseconds is usually the dominant * error at this stage. * TODO: combine the several intermediate expressions when get a good compiler. */ plans (mjd, p, lpd0, psi0, rp0, rho0, lam, bet, dia, mag) float mjd; int p; float *lpd0, *psi0, *rp0, *rho0, *lam, *bet, *dia, *mag; { static float plan[8][9]; static lastmjd = -10000; float dl; /* perturbation correction for longitude */ float dr; /* " orbital radius */ float dml; /* " mean longitude */ float ds; /* " eccentricity */ float dm; /* " mean anomaly */ float da; /* " semi-major axis */ float dhl; /* " heliocentric longitude */ float lsn, rsn; /* true geocentric longitude of sun and sun-earth rad */ float mas; /* mean anomaly of the sun */ float re; /* radius of earth's orbit */ float lg; /* longitude of earth */ float map[8]; /* array of mean anomalies for each planet */ float lpd, psi, rp, rho; float ll, sll, cll; float t; float dt; int pass; int j; float s, ma; float nu, ea; float lp, om; float lo, slo, clo; float inc, y; float spsi, cpsi; float rpd; /* only need to fill in plan[] once for a given mjd */ if (mjd != lastmjd) { pelement (mjd, plan); lastmjd = mjd; } dt = 0; t = mjd/36525.; sun (mjd, &lsn, &rsn); masun (mjd, &mas); re = rsn; lg = lsn+PI; /* first find the true position of the planet at mjd. * then repeat a second time for a slightly different time based * on the position found in the first pass to account for light-travel * time. */ for (pass = 0; pass < 2; pass++) { for (j = 0; j < 8; j++) map[j] = degrad(plan[j][0]-plan[j][2]-dt*plan[j][1]); /* set initial corrections to 0. * then modify as necessary for the planet of interest. */ dl = 0; dr = 0; dml = 0; ds = 0; dm = 0; da = 0; dhl = 0; switch (p) { case MERCURY: p_mercury (map, &dl, &dr); break; case VENUS: p_venus (t, mas, map, &dl, &dr, &dml, &dm); break; case MARS: p_mars (mas, map, &dl, &dr, &dml, &dm); break; case JUPITER: p_jupiter (t, plan[p][3], &dml, &ds, &dm, &da); break; case SATURN: p_saturn (t, plan[p][3], &dml, &ds, &dm, &da, &dhl); break; case URANUS: p_uranus (t, plan[p][3], &dl, &dr, &dml, &ds, &dm, &da, &dhl); break; case NEPTUNE: p_neptune (t, plan[p][3], &dl, &dr, &dml, &ds, &dm, &da, &dhl); break; case PLUTO: /* no perturbation theory for pluto */ break; } s = plan[p][3]+ds; ma = map[p]+dm; anomaly (ma, s, &nu, &ea); rp = (plan[p][6]+da)*(1-s*s)/(1+s*cos(nu)); lp = raddeg(nu)+plan[p][2]+raddeg(dml-dm); lp = degrad(lp); om = degrad(plan[p][5]); lo = lp-om; slo = sin(lo); clo = cos(lo); inc = degrad(plan[p][4]); rp = rp+dr; spsi = slo*sin(inc); y = slo*cos(inc); psi = asin(spsi)+dhl; spsi = sin(psi); lpd = atan(y/clo)+om+degrad(dl); if (clo<0) lpd += PI; if (lpd>TWOPI) lpd -= TWOPI; cpsi = cos(psi); rpd = rp*cpsi; ll = lpd-lg; rho = sqrt(re*re+rp*rp-2*re*rp*cpsi*cos(ll)); /* when we view a planet we see it in the position it occupied * dt hours ago, where rho is the distance between it and earth, * in AU. use this as the new time for the next pass. */ dt = rho*5.775518e-3; if (pass == 0) { /* save heliocentric coordinates after first pass since, being * true, they are NOT to be corrected for light-travel time. */ *lpd0 = lpd; *psi0 = psi; *rp0 = rp; *rho0 = rho; } } sll = sin(ll); cll = cos(ll); if (p < MARS) *lam = atan(-1*rpd*sll/(re-rpd*cll))+lg+PI; else *lam = atan(re*sll/(rpd-re*cll))+lpd; range (lam, TWOPI); *bet = atan(rpd*spsi*sin(*lam-lpd)/(cpsi*re*sll)); *dia = plan[p][7]; *mag = plan[p][8]; } /* set auxilliary variables used for jupiter, saturn, uranus, and neptune */ static aux_jsun (t, j1, j2, j3, j4, j5, j6) float t; float *j1, *j2, *j3, *j4, *j5, *j6; { *j1 = t/5+0.1; *j2 = mod2PI(4.14473+5.29691e1*t); *j3 = mod2PI(4.641118+2.132991e1*t); *j4 = mod2PI(4.250177+7.478172*t); *j5 = 5 * *j3 - 2 * *j2; *j6 = 2 * *j2 - 6 * *j3 + 3 * *j4; } /* find the mean anomaly of the sun at mjd. * this is the same as that used in sun() but when it was converted to C it * was not known it would be required outside that routine. * TODO: add an argument to sun() to return mas and eliminate this routine. */ static masun (mjd, mas) float mjd; float *mas; { float t, t2; float a, b; t = mjd/36525; t2 = t*t; a = 9.999736042e1*t; b = 360.*(a-(int)a); *mas = degrad (3.5847583e2-(1.5e-4+3.3e-6*t)*t2+b); } /* perturbations for mercury */ static p_mercury (map, dl, dr) float map[]; float *dl, *dr; { *dl = 2.04e-3*cos(5*map[2-1]-2*map[1-1]+2.1328e-1)+ 1.03e-3*cos(2*map[2-1]-map[1-1]-2.8046)+ 9.1e-4*cos(2*map[3]-map[1-1]-6.4582e-1)+ 7.8e-4*cos(5*map[2-1]-3*map[1-1]+1.7692e-1); *dr = 7.525e-6*cos(2*map[3]-map[1-1]+9.25251e-1)+ 6.802e-6*cos(5*map[2-1]-3*map[1-1]-4.53642)+ 5.457e-6*cos(2*map[2-1]-2*map[1-1]-1.24246)+ 3.569e-6*cos(5*map[2-1]-map[1-1]-1.35699); } /* ....venus */ static p_venus (t, mas, map, dl, dr, dml, dm) float t, mas, map[]; float *dl, *dr, *dml, *dm; { *dml = degrad (7.7e-4*sin(4.1406+t*2.6227)); *dm = *dml; *dl = 3.13e-3*cos(2*mas-2*map[2-1]-2.587)+ 1.98e-3*cos(3*mas-3*map[2-1]+4.4768e-2)+ 1.36e-3*cos(mas-map[2-1]-2.0788)+ 9.6e-4*cos(3*mas-2*map[2-1]-2.3721)+ 8.2e-4*cos(map[3]-map[2-1]-3.6318); *dr = 2.2501e-5*cos(2*mas-2*map[2-1]-1.01592)+ 1.9045e-5*cos(3*mas-3*map[2-1]+1.61577)+ 6.887e-6*cos(map[3]-map[2-1]-2.06106)+ 5.172e-6*cos(mas-map[2-1]-5.08065e-1)+ 3.62e-6*cos(5*mas-4*map[2-1]-1.81877)+ 3.283e-6*cos(4*mas-4*map[2-1]+1.10851)+ 3.074e-6*cos(2*map[3]-2*map[2-1]-9.62846e-1); } /* ....mars */ static p_mars (mas, map, dl, dr, dml, dm) float mas, map[]; float *dl, *dr, *dml, *dm; { float a; a = 3*map[3]-8*map[2]+4*mas; *dml = degrad (-1*(1.133e-2*sin(a)+9.33e-3*cos(a))); *dm = *dml; *dl = 7.05e-3*cos(map[3]-map[2]-8.5448e-1)+ 6.07e-3*cos(2*map[3]-map[2]-3.2873)+ 4.45e-3*cos(2*map[3]-2*map[2]-3.3492)+ 3.88e-3*cos(mas-2*map[2]+3.5771e-1)+ 2.38e-3*cos(mas-map[2]+6.1256e-1)+ 2.04e-3*cos(2*mas-3*map[2]+2.7688)+ 1.77e-3*cos(3*map[2]-map[2-1]-1.0053)+ 1.36e-3*cos(2*mas-4*map[2]+2.6894)+ 1.04e-3*cos(map[3]+3.0749e-1); *dr = 5.3227e-5*cos(map[3]-map[2]+7.17864e-1)+ 5.0989e-5*cos(2*map[3]-2*map[2]-1.77997)+ 3.8278e-5*cos(2*map[3]-map[2]-1.71617)+ 1.5996e-5*cos(mas-map[2]-9.69618e-1)+ 1.4764e-5*cos(2*mas-3*map[2]+1.19768)+ 8.966e-6*cos(map[3]-2*map[2]+7.61225e-1)+ 7.914e-6*cos(3*map[3]-2*map[2]-2.43887)+ 7.004e-6*cos(2*map[3]-3*map[2]-1.79573)+ 6.62e-6*cos(mas-2*map[2]+1.97575)+ 4.93e-6*cos(3*map[3]-3*map[2]-1.33069)+ 4.693e-6*cos(3*mas-5*map[2]+3.32665)+ 4.571e-6*cos(2*mas-4*map[2]+4.27086)+ 4.409e-6*cos(3*map[3]-map[2]-2.02158); } /* ....jupiter */ static p_jupiter (t, s, dml, ds, dm, da) float t, s; float *dml, *ds, *dm, *da; { float dp; float j1, j2, j3, j4, j5, j6, j7; float sj3, cj3, s2j3, c2j3; float sj5, cj5, s2j5; float sj6; float sj7, cj7, s2j7, c2j7, s3j7, c3j7, s4j7, c4j7, c5j7; aux_jsun (t, &j1, &j2, &j3, &j4, &j5, &j6); j7 = j3-j2; sj3 = sin(j3); cj3 = cos(j3); s2j3 = sin(2*j3); c2j3 = cos(2*j3); sj5 = sin(j5); cj5 = cos(j5); s2j5 = sin(2*j5); sj6 = sin(j6); sj7 = sin(j7); cj7 = cos(j7); s2j7 = sin(2*j7); c2j7 = cos(2*j7); s3j7 = sin(3*j7); c3j7 = cos(3*j7); s4j7 = sin(4*j7); c4j7 = cos(4*j7); c5j7 = cos(5*j7); *dml = (3.31364e-1-(1.0281e-2+4.692e-3*j1)*j1)*sj5+ (3.228e-3-(6.4436e-2-2.075e-3*j1)*j1)*cj5- (3.083e-3+(2.75e-4-4.89e-4*j1)*j1)*s2j5+ 2.472e-3*sj6+1.3619e-2*sj7+1.8472e-2*s2j7+6.717e-3*s3j7+ 2.775e-3*s4j7+6.417e-3*s2j7*sj3+ (7.275e-3-1.253e-3*j1)*sj7*sj3+ 2.439e-3*s3j7*sj3-(3.5681e-2+1.208e-3*j1)*sj7*cj3- 3.767e-3*c2j7*sj3-(3.3839e-2+1.125e-3*j1)*cj7*sj3- 4.261e-3*s2j7*cj3+ (1.161e-3*j1-6.333e-3)*cj7*cj3+ 2.178e-3*cj3-6.675e-3*c2j7*cj3-2.664e-3*c3j7*cj3- 2.572e-3*sj7*s2j3-3.567e-3*s2j7*s2j3+2.094e-3*cj7*c2j3+ 3.342e-3*c2j7*c2j3; *dml = degrad(*dml); *ds = (3606+(130-43*j1)*j1)*sj5+(1289-580*j1)*cj5-6764*sj7*sj3- 1110*s2j7*sj3-224*s3j7*sj3-204*sj3+(1284+116*j1)*cj7*sj3+ 188*c2j7*sj3+(1460+130*j1)*sj7*cj3+224*s2j7*cj3-817*cj3+ 6074*cj3*cj7+992*c2j7*cj3+ 508*c3j7*cj3+230*c4j7*cj3+108*c5j7*cj3- (956+73*j1)*sj7*s2j3+448*s2j7*s2j3+137*s3j7*s2j3+ (108*j1-997)*cj7*s2j3+480*c2j7*s2j3+148*c3j7*s2j3+ (99*j1-956)*sj7*c2j3+490*s2j7*c2j3+ 158*s3j7*c2j3+179*c2j3+(1024+75*j1)*cj7*c2j3- 437*c2j7*c2j3-132*c3j7*c2j3; *ds *= 1e-7; dp = (7.192e-3-3.147e-3*j1)*sj5-4.344e-3*sj3+ (j1*(1.97e-4*j1-6.75e-4)-2.0428e-2)*cj5+ 3.4036e-2*cj7*sj3+(7.269e-3+6.72e-4*j1)*sj7*sj3+ 5.614e-3*c2j7*sj3+2.964e-3*c3j7*sj3+3.7761e-2*sj7*cj3+ 6.158e-3*s2j7*cj3- 6.603e-3*cj7*cj3-5.356e-3*sj7*s2j3+2.722e-3*s2j7*s2j3+ 4.483e-3*cj7*s2j3-2.642e-3*c2j7*s2j3+4.403e-3*sj7*c2j3- 2.536e-3*s2j7*c2j3+5.547e-3*cj7*c2j3-2.689e-3*c2j7*c2j3; *dm = *dml-(degrad(dp)/s); *da = 205*cj7-263*cj5+693*c2j7+312*c3j7+147*c4j7+299*sj7*sj3+ 181*c2j7*sj3+204*s2j7*cj3+111*s3j7*cj3-337*cj7*cj3- 111*c2j7*cj3; *da *= 1e-6; } /* ....saturn */ static p_saturn (t, s, dml, ds, dm, da, dhl) float t, s; float *dml, *ds, *dm, *da, *dhl; { float dp; float j1, j2, j3, j4, j5, j6, j7, j8; float sj3, cj3, s2j3, c2j3, s3j3, c3j3, s4j3, c4j3; float sj5, cj5, s2j5, c2j5; float sj6; float sj7, cj7, s2j7, c2j7, s3j7, c3j7, s4j7, c4j7, c5j7, s5j7; float s2j8, c2j8, s3j8, c3j8; aux_jsun (t, &j1, &j2, &j3, &j4, &j5, &j6); j7 = j3-j2; sj3 = sin(j3); cj3 = cos(j3); s2j3 = sin(2*j3); c2j3 = cos(2*j3); sj5 = sin(j5); cj5 = cos(j5); s2j5 = sin(2*j5); sj6 = sin(j6); sj7 = sin(j7); cj7 = cos(j7); s2j7 = sin(2*j7); c2j7 = cos(2*j7); s3j7 = sin(3*j7); c3j7 = cos(3*j7); s4j7 = sin(4*j7); c4j7 = cos(4*j7); c5j7 = cos(5*j7); s3j3 = sin(3*j3); c3j3 = cos(3*j3); s4j3 = sin(4*j3); c4j3 = cos(4*j3); c2j5 = cos(2*j5); s5j7 = sin(5*j7); j8 = j4-j3; s2j8 = sin(2*j8); c2j8 = cos(2*j8); s3j8 = sin(3*j8); c3j8 = cos(3*j8); *dml = 7.581e-3*s2j5-7.986e-3*sj6-1.48811e-1*sj7-4.0786e-2*s2j7- (8.14181e-1-(1.815e-2-1.6714e-2*j1)*j1)*sj5- (1.0497e-2-(1.60906e-1-4.1e-3*j1)*j1)*cj5-1.5208e-2*s3j7- 6.339e-3*s4j7-6.244e-3*sj3-1.65e-2*s2j7*sj3+ (8.931e-3+2.728e-3*j1)*sj7*sj3-5.775e-3*s3j7*sj3+ (8.1344e-2+3.206e-3*j1)*cj7*sj3+1.5019e-2*c2j7*sj3+ (8.5581e-2+2.494e-3*j1)*sj7*cj3+1.4394e-2*c2j7*cj3+ (2.5328e-2-3.117e-3*j1)*cj7*cj3+ 6.319e-3*c3j7*cj3+6.369e-3*sj7*s2j3+9.156e-3*s2j7*s2j3+ 7.525e-3*s3j8*s2j3-5.236e-3*cj7*c2j3-7.736e-3*c2j7*c2j3- 7.528e-3*c3j8*c2j3; *dml = degrad(*dml); *ds = (-7927+(2548+91*j1)*j1)*sj5+(13381+(1226-253*j1)*j1)*cj5+ (248-121*j1)*s2j5-(305+91*j1)*c2j5+412*s2j7+12415*sj3+ (390-617*j1)*sj7*sj3+(165-204*j1)*s2j7*sj3+26599*cj7*sj3- 4687*c2j7*sj3-1870*c3j7*sj3-821*c4j7*sj3- 377*c5j7*sj3+497*c2j8*sj3+(163-611*j1)*cj3- 12696*sj7*cj3-4200*s2j7*cj3-1503*s3j7*cj3-619*s4j7*cj3- 268*s5j7*cj3-(282+1306*j1)*cj7*cj3+(-86+230*j1)*c2j7*cj3+ 461*s2j8*cj3-350*s2j3+(2211-286*j1)*sj7*s2j3- 2208*s2j7*s2j3-568*s3j7*s2j3-346*s4j7*s2j3- (2780+222*j1)*cj7*s2j3+(2022+263*j1)*c2j7*s2j3+248*c3j7*s2j3+ 242*s3j8*s2j3+467*c3j8*s2j3-490*c2j3-(2842+279*j1)*sj7*c2j3+ (128+226*j1)*s2j7*c2j3+224*s3j7*c2j3+ (-1594+282*j1)*cj7*c2j3+(2162-207*j1)*c2j7*c2j3+ 561*c3j7*c2j3+343*c4j7*c2j3+469*s3j8*c2j3-242*c3j8*c2j3- 205*sj7*s3j3+262*s3j7*s3j3+208*cj7*c3j3-271*c3j7*c3j3- 382*c3j7*s4j3-376*s3j7*c4j3; *ds *= 1e-7; dp = (7.7108e-2+(7.186e-3-1.533e-3*j1)*j1)*sj5-7.075e-3*sj7+ (4.5803e-2-(1.4766e-2+5.36e-4*j1)*j1)*cj5-7.2586e-2*cj3- 7.5825e-2*sj7*sj3-2.4839e-2*s2j7*sj3-8.631e-3*s3j7*sj3- 1.50383e-1*cj7*cj3+2.6897e-2*c2j7*cj3+1.0053e-2*c3j7*cj3- (1.3597e-2+1.719e-3*j1)*sj7*s2j3+1.1981e-2*s2j7*c2j3- (7.742e-3-1.517e-3*j1)*cj7*s2j3+ (1.3586e-2-1.375e-3*j1)*c2j7*c2j3- (1.3667e-2-1.239e-3*j1)*sj7*c2j3+ (1.4861e-2+1.136e-3*j1)*cj7*c2j3- (1.3064e-2+1.628e-3*j1)*c2j7*c2j3; *dm = *dml-(degrad(dp)/s); *da = 572*sj5-1590*s2j7*cj3+2933*cj5-647*s3j7*cj3+33629*cj7- 344*s4j7*cj3-3081*c2j7+2885*cj7*cj3-1423*c3j7+ (2172+102*j1)*c2j7*cj3-671*c4j7+296*c3j7*cj3-320*c5j7- 267*s2j7*s2j3+1098*sj3-778*cj7*s2j3-2812*sj7*sj3+ 495*c2j7*s2j3+688*s2j7*sj3+250*c3j7*s2j3-393*s3j7*sj3- 856*sj7*c2j3-228*s4j7*sj3+441*s2j7*c2j3+2138*cj7*sj3+ 296*c2j7*c2j3-999*c2j7*sj3+211*c3j7*c2j3-642*c3j7*sj3- 427*sj7*s3j3-325*c4j7*sj3+398*s3j7*s3j3-890*cj3+ 344*cj7*c3j3+2206*sj7*cj3-427*c3j7*c3j3; *da *= 1e-6; *dhl = 7.47e-4*cj7*sj3+1.069e-3*cj7*cj3+2.108e-3*s2j7*s2j3+ 1.261e-3*c2j7*s2j3+1.236e-3*s2j7*c2j3-2.075e-3*c2j7*c2j3; *dhl = degrad(*dhl); } /* ....uranus */ static p_uranus (t, s, dl, dr, dml, ds, dm, da, dhl) float t, s; float *dl, *dr, *dml, *ds, *dm, *da, *dhl; { float dp; float j1, j2, j3, j4, j5, j6; float j8, j9, j10, j11, j12; float sj4, cj4, s2j4, c2j4; float sj9, cj9, s2j9, c2j9; float sj11, cj11; aux_jsun (t, &j1, &j2, &j3, &j4, &j5, &j6); j8 = mod2PI(1.46205+3.81337*t); j9 = 2*j8-j4; sj9 = sin(j9); cj9 = cos(j9); s2j9 = sin(2*j9); c2j9 = cos(2*j9); j10 = j4-j2; j11 = j4-j3; j12 = j8-j4; *dml = (8.64319e-1-1.583e-3*j1)*sj9+(8.2222e-2-6.833e-3*j1)*cj9+ 3.6017e-2*s2j9-3.019e-3*c2j9+8.122e-3*sin(j6); *dml = degrad(*dml); dp = 1.20303e-1*sj9+6.197e-3*s2j9+(1.9472e-2-9.47e-4*j1)*cj9; *dm = *dml-(degrad(dp)/s); *ds = (163*j1-3349)*sj9+20981*cj9+1311*c2j9; *ds *= 1e-7; *da = -3.825e-3*cj9; *dl = (1.0122e-2-9.88e-4*j1)*sin(j4+j11)+ (-3.8581e-2+(2.031e-3-1.91e-3*j1)*j1)*cos(j4+j11)+ (3.4964e-2-(1.038e-3-8.68e-4*j1)*j1)*cos(2*j4+j11)+ 5.594e-3*sin(j4+3*j12)-1.4808e-2*sin(j10)- 5.794e-3*sin(j11)+2.347e-3*cos(j11)+9.872e-3*sin(j12)+ 8.803e-3*sin(2*j12)-4.308e-3*sin(3*j12); sj11 = sin(j11); cj11 = cos(j11); sj4 = sin(j4); cj4 = cos(j4); s2j4 = sin(2*j4); c2j4 = cos(2*j4); *dhl = (4.58e-4*sj11-6.42e-4*cj11-5.17e-4*cos(4*j12))*sj4- (3.47e-4*sj11+8.53e-4*cj11+5.17e-4*sin(4*j11))*cj4+ 4.03e-4*(cos(2*j12)*s2j4+sin(2*j12)*c2j4); *dhl = degrad(*dhl); *dr = -25948+4985*cos(j10)-1230*cj4+3354*cos(j11)+904*cos(2*j12)+ 894*(cos(j12)-cos(3*j12))+(5795*cj4-1165*sj4+1388*c2j4)*sj11+ (1351*cj4+5702*sj4+1388*s2j4)*cos(j11); *dr *= 1e-6; } /* ....neptune */ static p_neptune (t, s, dl, dr, dml, ds, dm, da, dhl) float t, s; float *dl, *dr, *dml, *ds, *dm, *da, *dhl; { float dp; float j1, j2, j3, j4, j5, j6; float j8, j9, j10, j11, j12; float sj8, cj8; float sj9, cj9, s2j9, c2j9; float s2j12, c2j12; aux_jsun (t, &j1, &j2, &j3, &j4, &j5, &j6); j8 = mod2PI(1.46205+3.81337*t); j9 = 2*j8-j4; sj9 = sin(j9); cj9 = cos(j9); s2j9 = sin(2*j9); c2j9 = cos(2*j9); j10 = j8-j2; j11 = j8-j3; j12 = j8-j4; *dml = (1.089e-3*j1-5.89833e-1)*sj9+(4.658e-3*j1-5.6094e-2)*cj9- 2.4286e-2*s2j9; *dml = degrad(*dml); dp = 2.4039e-2*sj9-2.5303e-2*cj9+6.206e-3*s2j9-5.992e-3*c2j9; *dm = *dml-(degrad(dp)/s); *ds = 4389*sj9+1129*s2j9+4262*cj9+1089*c2j9; *ds *= 1e-7; *da = 8189*cj9-817*sj9+781*c2j9; *da *= 1e-6; s2j12 = sin(2*j12); c2j12 = cos(2*j12); sj8 = sin(j8); cj8 = cos(j8); *dl = -9.556e-3*sin(j10)-5.178e-3*sin(j11)+2.572e-3*s2j12- 2.972e-3*c2j12*sj8-2.833e-3*s2j12*cj8; *dhl = 3.36e-4*c2j12*sj8+3.64e-4*s2j12*cj8; *dhl = degrad(*dhl); *dr = -40596+4992*cos(j10)+2744*cos(j11)+2044*cos(j12)+1051*c2j12; *dr *= 1e-6; } xXx echo extracting precess.c cat > precess.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* corrects ra and dec, both in radians, for precession from epoch 1 to epoch 2. * the epochs are given by their modified JDs, mjd1 and mjd2, respectively. * N.B. ra and dec are modifed IN PLACE. */ precess (mjd1, mjd2, ra, dec) float mjd1, mjd2; /* initial and final epoch modified JDs */ float *ra, *dec; /* ra/dec for mjd1 in, for mjd2 out */ { static float lastmjd1, lastmjd2; static float m, n, nyrs; float dra, ddec; /* ra and dec corrections */ if (mjd1 != lastmjd1 || mjd2 != lastmjd2) { float t1, t2; /* Julian centuries of 36525 days since Jan .5 1900 */ float m1, n1; /* "constants" for t1 */ float m2, n2; /* "constants" for t2 */ t1 = mjd1/36525.; t2 = mjd2/36525.; m1 = 3.07234+(1.86e-3*t1); n1 = 20.0468-(8.5e-3*t1); m2 = 3.07234+(1.86e-3*t2); n2 = 20.0468-(8.5e-3*t2); m = (m1+m2)/2; /* average m for the two epochs */ n = (n1+n2)/2; /* average n for the two epochs */ nyrs = (mjd2-mjd1)/365.2425; lastmjd1 = mjd1; lastmjd2 = mjd2; } dra = (m+(n*sin(*ra)*tan(*dec)/15))*7.272205e-5*nyrs; ddec = n*cos(*ra)*4.848137e-6*nyrs; *ra += dra; *dec += ddec; range (ra, 2*PI); } xXx echo extracting refract.c cat > refract.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* correct the true altitude, ta, for refraction to the apparent altitude, aa, * each in radians, given the local atmospheric pressure, pr, in mbars, and * the temperature, tr, in degrees C. */ refract (pr, tr, ta, aa) float pr, tr; float ta; float *aa; { float r; /* refraction correction*/ if (ta >= degrad(15.)) { /* model for altitudes at least 15 degrees above horizon */ r = 7.888888e-5*pr/((273+tr)*tan(ta)); } else if (ta > degrad(-5.)) { /* hairier model for altitudes at least -5 and below 15 degrees */ float a, b, tadeg = raddeg(ta); a = ((2e-5*tadeg+1.96e-2)*tadeg+1.594e-1)*pr; b = (273+tr)*((8.45e-2*tadeg+5.05e-1)*tadeg+1); r = degrad(a/b); } else { /* do nothing if more than 5 degrees below horizon. */ r = 0; } *aa = ta + r; } /* correct the apparent altitude, aa, for refraction to the true altitude, ta, * each in radians, given the local atmospheric pressure, pr, in mbars, and * the temperature, tr, in degrees C. */ unrefract (pr, tr, aa, ta) float pr, tr; float aa; float *ta; { float err; float appar; float true; /* iterative solution: search for the true that refracts to the * given apparent. * since refract() is discontinuous at -5 degrees, there is a range * of apparent altitudes between about -4.5 and -5 degrees that are * not invertable (the graph of ap vs. true has a vertical step at * true = -5). thus, the iteration just oscillates if it gets into * this region. if this happens the iteration is forced to abort. * of course, this makes unrefract() discontinuous too. */ true = aa; do { refract (pr, tr, true, &appar); err = appar - aa; true -= err; } while (fabs(err) >= 1e-6 && true > degrad(-5)); *ta = true; } xXx echo extracting riset.c cat > riset.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* given the true geocentric ra and dec of an object, in radians, the observer's * latitude in radians, and a horizon displacement correction, dis, in radians * find the local sidereal times and azimuths of rising and setting, lstr/s * and azr/s, in radians, respectively. * dis is the vertical displacement from the true position of the horizon. it * is positive if the apparent position is higher than the true position. * said another way, it is positive if the shift causes the object to spend * longer above the horizon. for example, atmospheric refraction is typically * assumed to produce a vertical shift of 34 arc minutes at the horizon; dis * would then take on the value +9.89e-3 (radians). On the other hand, if * your horizon has hills such that your apparent horizon is, say, 1 degree * above sea level, you would allow for this by setting dis to -1.75e-2 * (radians). * status: 0: normal; 1: never rises; -1: circumpolar; 2: trouble. */ riset (ra, dec, lat, dis, lstr, lsts, azr, azs, status) float ra, dec; float lat, dis; float *lstr, *lsts; float *azr, *azs; int *status; { static float lastlat = 0, slat = 0, clat = 1.0; float dec1, sdec, cdec, tdec; float psi, spsi, cpsi; float h, dh, ch; /* hr angle, delta and cos */ /* avoid needless sin/cos since latitude doesn't change often */ if (lat != lastlat) { clat = cos(lat); slat = sin(lat); lastlat = lat; } /* can't cope with objects very near the celestial pole nor if we * are located very near the earth's poles. */ cdec = cos(dec); if (fabs(cdec*clat) < 1e-10) { /* trouble */ *status = 2; return; } cpsi = slat/cdec; if (cpsi>1.0) cpsi = 1.0; else if (cpsi<-1.0) cpsi = -1.0; psi = acos(cpsi); spsi = sin(psi); dh = dis*spsi; dec1 = dec + (dis*cpsi); sdec = sin(dec1); tdec = tan(dec1); ch = (-1*slat*tdec)/clat; if (ch < -1) { /* circumpolar */ *status = -1; return; } if (ch > 1) { /* never rises */ *status = 1; return; } *status = 0; h = acos(ch)+dh; *lstr = 24+radhr(ra-h); *lsts = radhr(ra+h); range (lstr, 24.0); range (lsts, 24.0); *azr = acos(sdec/clat); range (azr, 2*PI); *azs = 2*PI - *azr; } xXx echo extracting sex_dec.c cat > sex_dec.c << 'xXx' /* given hours (or degrees), hd, minutes, m, and seconds, s, * return decimal hours (or degrees), *d. * in the case of hours (angles) < 0, only the first non-zero element should * be negative. */ sex_dec (hd, m, s, d) int hd, m, s; float *d; { int sign = 1; if (hd < 0) { sign = -1; hd = -hd; } else if (m < 0) { sign = -1; m = -m; } else if (s < 0) { sign = -1; s = -s; } *d = ((s/60.0 + m)/60.0 + hd) * sign; } /* given decimal hours (or degrees), d. * return nearest hours (or degrees), *hd, minutes, *m, and seconds, *s, * each always non-negative; *isneg is set to 1 if d is < 0, else to 0. */ dec_sex (d, hd, m, s, isneg) float d; int *hd, *m, *s, *isneg; { float min; if (d < 0) { *isneg = 1; d = -d; } else *isneg = 0; *hd = (int)d; min = (d - *hd)*60.; *m = (int)min; *s = (int)((min - *m)*60. + 0.5); if (*s == 60) { if ((*m += 1) == 60) { *hd += 1; *m = 0; } *s = 0; } /* no negative 0's */ if (*hd == 0 && *m == 0 && *s == 0) *isneg = 0; } /* insure 0 <= *v < r. */ range (v, r) float *v, r; { while (*v < 0) *v += r; while (*v >= r) *v -= r; } xXx echo extracting sun.c cat > sun.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* given the modified JD, mjd, return the true geocentric ecliptic longitude * of the sun for the mean equinox of the date, *lsn, in radians, and the * sun-earth distance, *rsn, in AU. (the true ecliptic latitude is never more * than 1.2 arc seconds and so may be taken to be a constant 0.) * if the APPARENT ecliptic longitude is required, correct the longitude for * nutation to the true equinox of date and for aberration (light travel time, * approximately -9.27e7/186000/(3600*24*365)*2*pi = -9.93e-5 radians). */ sun (mjd, lsn, rsn) float mjd; float *lsn, *rsn; { float t, t2; float ls, ms; /* mean longitude and mean anomoay */ float s, nu, ea; /* eccentricity, true anomaly, eccentric anomaly */ double a, b, a1, b1, c1, d1, e1, h1, dl, dr; t = mjd/36525.; t2 = t*t; a = 100.0021359*t; b = 360.*(a-(int)a); ls = 279.69668+.0003025*t2+b; a = 99.99736042000039*t; b = 360*(a-(int)a); ms = 358.47583-(.00015+.0000033*t)*t2+b; s = .016751-.0000418*t-1.26e-07*t2; anomaly (degrad(ms), s, &nu, &ea); a = 62.55209472000015*t; b = 360*(a-(int)a); a1 = degrad(153.23+b); a = 125.1041894*t; b = 360*(a-(int)a); b1 = degrad(216.57+b); a = 91.56766028*t; b = 360*(a = (int)a); c1 = degrad(312.69+b); a = 1236.853095*t; b = 360*(a-(int)a); d1 = degrad(350.74-.00144*t2+b); e1 = degrad(231.19+20.2*t); a = 183.1353208*t; b = 360*(a-(int)a); h1 = degrad(353.4+b); dl = .00134*cos(a1)+.00154*cos(b1)+.002*cos(c1)+.00179*sin(d1)+ .00178*sin(e1); dr = 5.43e-06*sin(a1)+1.575e-05*sin(b1)+1.627e-05*sin(c1)+ 3.076e-05*cos(d1)+9.27e-06*sin(h1); *lsn = nu+degrad(ls-ms+dl); *rsn = 1.0000002*(1-s*cos(ea))+dr; range (lsn, 2*PI); } xXx echo extracting sunrs.c cat > sunrs.c << 'xXx' #include <stdio.h> #include <math.h> #include "astro.h" /* given the modified julian date, mjd, geographical latitude, lat, and * longitude, lng, each in radians with west lng < 0, and a horizon * displacement, dis, find the utc times of sunrise, utcr, and sunset, utcs, * and the azimuths of sunrise, azr, and sunset, azs. all angles in radians; * azimuths are E of N. * times are for the upper limb, including effects of nutation and aberration. * displacement is additional amount added to suns altitude compared to its * true location; see riset.c for more discussion. it can be used to * account for irregular horizons, various refraction models, even times * of twilight. eg, refraction to a level horizon is often taken to be about * 32/2(sun's semi-diameter) + 34(nominal refraction) = 50 arc minutes. * better is: * unrefract (pre, temp, 0.0, &a); /* true alt of upper limb * a -= SUN_DIAM; /* true alt of sun center * also used to find astro twilight by calling with dis of 18 degrees. * status: * 2: error * 1: never rises * 0: normal * -1: circumpolar */ sunrs (mjd, lat, lng, dis, utcr, utcs, azr, azs, status) float mjd, lat, lng, dis; float *utcr, *utcs; float *azr, *azs; int *status; { float lstr, lsts; /* local sidereal times of rising/setting */ float al = radhr(lng); /* time correction for longitude */ float tmp1, tmp2; /* tmp */ float mjd0, t; mjd0 = floor(mjd+0.5)-0.5; /* insure mjd0 is greenwich start of day */ /* first approximation is to find rise/set times of a fixed object * in the position of the sun at local midday. the sun is not * fixed but moves about a degree per day so these are then refined. */ fixedsunriset(mjd0+(12.-al)/24.,lat,dis,&lstr,&lsts,&tmp1,&tmp2,status); if (*status != 0) return; /* find a better approximation to the rising circumstances based on a * fixed object at the suns location at the first approximation of the * rise time. * N.B. more iterations are less than sp float precision. */ gst_utc (mjd0, lstr, &t); fixedsunriset(mjd0+(t-al)/24.,lat,dis,&lstr,&tmp1,azr,&tmp2,status); if (*status != 0) return; gst_utc (mjd0, lstr, utcr); *utcr -= al*.9972696; /* allow for sideral shift */ /* find a better approximation to the setting circumstances based on a * fixed object at the suns location at the first approximation of the * setting time. */ gst_utc (mjd0, lsts, &t); fixedsunriset (mjd0+(t-al)/24.,lat,dis,&tmp1,&lsts,&tmp2,azs,status); if (*status != 0) return; gst_utc (mjd0, lsts, utcs); *utcs -= al*.9972696; /* allow for sideral shift */ } /* find the local rise/set sidereal times and azimuths of an object fixed * at the ra/dec of the sun on the given mjd time as seen from lat. */ static fixedsunriset (mjd, lat, dis, lstr, lsts, azr, azs, status) float mjd, lat, dis; float *lstr, *lsts; float *azr, *azs; int *status; { float lsn, rsn; float deps, dpsi; float ra, dec; /* find ecliptic position of sun at mjd */ sun (mjd, &lsn, &rsn); /* allow for 20.4" aberation and nutation */ nutation (mjd, &deps, &dpsi); lsn += dpsi - degrad(20.4/3600.0); /* convert ecliptic to equatorial coords */ ecl_eq (mjd, 0.0, lsn, &ra, &dec); /* find circumstances for given horizon displacement */ riset (ra, dec, lat, dis, lstr, lsts, azr, azs, status); } xXx echo extracting utc_gst.c cat > utc_gst.c << 'xXx' /* given a modified julian date, mjd, and a universally coordinated time, utc, * return greenwich mean siderial time, *gst. */ utc_gst (mjd, utc, gst) float mjd; float utc; float *gst; { float tnaught(); static float lastmjd; static float t0; if (mjd != lastmjd) { t0 = tnaught (mjd); lastmjd = mjd; } *gst = 1.002737908*utc + t0; range (gst, 24.0); } /* given a modified julian date, mjd, and a greenwich mean siderial time, gst, * return universally coordinated time, *utc. */ gst_utc (mjd, gst, utc) float mjd; float gst; float *utc; { float tnaught(); static float lastmjd; static float t0; if (mjd != lastmjd) { t0 = tnaught (mjd); range (&t0, 24.0); lastmjd = mjd; } *utc = gst - t0; range (utc, 24.0); *utc *= .9972695677; } static float tnaught (mjd) float mjd; /* julian days since 1900 jan 0.5 */ { float dmjd; int m, y; float d; float t, t0; mjd_cal (mjd, &m, &d, &y); cal_mjd (1, 0., y, &dmjd); t = dmjd/36525; t0 = 6.57098e-2 * (mjd - dmjd) - (24 - (6.6460656 + (5.1262e-2 + (t * 2.581e-5))*t) - (2400 * (t - (((float)y - 1900)/100)))); return (t0); } xXx