|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 12378 (0x305a)
Types: TextFile
Names: »sun.c«
└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
└─⟦this⟧ »cph85dist/astro/sun/sun.c«
/***** hpfcla:net.sources / nsc-pdc!rgb / 10:24 am May 16, 1985
*
* Changed constants to Fort Collins, Colorado. (ajs, 850520)
* Made other minor output format improvements also.
*
* sun <options>
*
* options: -t hh:mm:ss time (default is current system time)
* -d mm/dd/yy date (default is current system date)
* -a lat decimal latitude (default = 45.5333)
* -o lon decimal longitude (default = 122.8333)
* -z tz timezone (default = 8, pst)
* -p show position of sun (azimuth)
* -v turn on debugging
*
* All output is to standard io.
*
* Compile with cc -O -o sun sun.c -lm
* Non 4.2 systems may have to change <sys/time.h> to <time.h> below.
* (yes, done)
*
* Note that the latitude, longitude, time zone correction and
* time zone string are all defaulted in the global variable section.
*
* Most of the code in this program is adapted from algorithms
* presented in "Practical Astronomy With Your Calculator" by
* Peter Duffet-Smith.
*
* The GST and ALT-AZIMUTH algorithms are from Sky and Telescope,
* June, 1984 by Roger W. Sinnott
*
* Author Robert Bond - Beaverton Oregon.
*
*/
#include <stdio.h>
#include <math.h>
#include <sys/types.h>
#include <time.h>
#define PI 3.141592654
#define EPOCH 1980
#define JDE 2444238.5 /* Julian date of EPOCH */
double dtor();
double adj360();
double adj24();
double julian_date();
double hms_to_dh();
double solar_lon();
double acos_deg();
double asin_deg();
double atan_q_deg();
double atan_deg();
double sin_deg();
double cos_deg();
double tan_deg();
double gmst();
int th;
int tm;
int ts;
int mo;
int day;
int yr;
int tz=7; /* Default time zone */
char *tzs = "(MST)"; /* Default time zone string */
char *dtzs = "(MDT)"; /* Default daylight savings time string */
int debug = 0;
int popt = 0;
double lat = 40.5253; /* Default latitude (Fort Collins, Colorado) */
double lon = 105.0119; /* Default Longitude (Degrees west) */
main(argc,argv)
int argc;
char *argv[];
{
double ed, jd;
double alpha1, delta1, alpha2, delta2, st1r, st1s, st2r, st2s;
double a1r, a1s, a2r, a2s, dt, dh, x, y;
double trise, tset, ar, as, alpha, delta, tri, da;
double lambda1, lambda2;
double alt, az, gst, m1;
double hsm, ratio;
time_t sec_1970;
int h, m;
struct tm *pt;
sec_1970 = time((time_t *)0);
pt = localtime(&sec_1970);
th = pt->tm_hour;
tm = pt->tm_min;
ts = pt->tm_sec;
yr = pt->tm_year + 1900;
mo = pt->tm_mon + 1;
day = pt->tm_mday;
if (pt->tm_isdst) { /* convert tz to daylight savings time */
tz--;
tzs = dtzs;
}
initopts(argc,argv);
if (debug)
printf("Date: %d/%d/%d, Time: %d:%d:%d, Tz: %d, Lat: %lf, Lon: %lf \n",
mo,day,yr,th,tm,ts,tz,lat,lon);
jd = julian_date(mo,day,yr);
ed = jd - JDE;
lambda1 = solar_lon(ed);
lambda2 = solar_lon(ed + 1.0);
lon_to_eq(lambda1, &alpha1, &delta1);
lon_to_eq(lambda2, &alpha2, &delta2);
rise_set(alpha1, delta1, &st1r, &st1s, &a1r, &a1s);
rise_set(alpha2, delta2, &st2r, &st2s, &a2r, &a2s);
m1 = adj24(gmst(jd - 0.5, 0.5 + tz / 24.0) - lon / 15); /* lst midnight */
if (debug)
printf ("local sidereal time of midnight is %lf \n", m1);
hsm = adj24(st1r - m1);
if (debug)
printf ("about %lf hours from midnight to dawn \n", hsm);
ratio = hsm / 24.07;
if (debug)
printf("%lf is how far dawn is into the day \n", ratio);
if (fabs(st2r - st1r) > 1.0) {
st2r += 24.0;
if (debug)
printf("st2r corrected from %lf to %lf \n", st2r-24.0, st2r);
}
trise = adj24((1.0 - ratio) * st1r + ratio * st2r);
hsm = adj24(st1s - m1);
if (debug)
printf ("about %lf hours from midnight to sunset \n", hsm);
ratio = hsm / 24.07;
if (debug)
printf("%lf is how far sunset is into the day \n", ratio);
if (fabs(st2s - st1s) > 1.0) {
st2s += 24.0;
if (debug)
printf("st2s corrected from %lf to %lf \n", st2s-24.0, st2s);
}
tset = adj24((1.0 - ratio) * st1s + ratio * st2s);
if (debug)
printf("Uncorrected rise = %lf, set = %lf \n", trise, tset);
ar = a1r * 360.0 / (360.0 + a1r - a2r);
as = a1s * 360.0 / (360.0 + a1s - a2s);
delta = (delta1 + delta2) / 2.0;
tri = acos_deg(sin_deg(lat)/cos_deg(delta));
x = 0.835608; /* correction for refraction, parallax, ? */
y = asin_deg(sin_deg(x)/sin_deg(tri));
da = asin_deg(tan_deg(x)/tan_deg(tri));
dt = 240.0 * y / cos_deg(delta) / 3600;
if (debug)
printf("Corrections: dt = %lf, da = %lf \n", dt, da);
lst_to_hm(trise - dt, jd, &h, &m);
printf("Sunrise: %2d:%02d\t\t", h, m);
if (popt) {
dh_to_hm(ar - da, &h, &m);
printf("Azimuth: %3d %02d'\n", h, m);
}
lst_to_hm(tset + dt, jd, &h, &m);
printf("Sunset: %2d:%02d ", h, m);
if (popt) {
dh_to_hm(as + da, &h, &m);
printf("Azimuth: %3d %02d'\n", h, m);
} else
printf("%s\n",tzs);
if (popt) {
if (alpha1 < alpha2)
alpha = (alpha1 + alpha2) / 2.0;
else
alpha = (alpha1 + 24.0 + alpha2) / 2.0;
if (alpha > 24.0)
alpha -= 24.0;
dh = (hms_to_dh(th, tm, ts) + tz) / 24.0;
if (dh > 0.5) {
dh -= 0.5;
jd += 0.5;
} else {
dh += 0.5;
jd -= 0.5;
}
gst = gmst(jd, dh);
eq_to_altaz(alpha, delta, gst, &alt, &az);
printf ("The sun is at: ");
dh_to_hm (az, &h, &m);
printf ("Azimuth: %3d %02d' ", h, m);
dh_to_hm (alt, &h, &m);
printf ("Altitude: %3d %02d'\n", h, m);
}
}
double
dtor(deg)
double deg;
{
return (deg * PI / 180.0);
}
double
rtod(deg)
double deg;
{
return (deg * 180.0 / PI);
}
double
adj360(deg)
double deg;
{
while (deg < 0.0)
deg += 360.0;
while (deg > 360.0)
deg -= 360.0;
return(deg);
}
double
adj24(hrs)
double hrs;
{
while (hrs < 0.0)
hrs += 24.0;
while (hrs > 24.0)
hrs -= 24.0;
return(hrs);
}
initopts(argc,argv)
int argc;
char *argv[];
{
int ai;
char *ca;
char *str;
while (--argc) {
if ((*++argv)[0] == '-') {
ca = *argv;
for(ai = 1; ca[ai] != '\0'; ai++)
switch (ca[ai]) {
case 'v':
debug++;
break;
case 'p':
popt++;
break;
case 'a':
str = *++argv;
if (sscanf(str, "%lf", &lat) != 1)
usage();
argc--;
break;
case 'o':
str = *++argv;
if (sscanf(str, "%lf", &lon) != 1)
usage();
argc--;
break;
case 'z':
str = *++argv;
if (sscanf(str, "%d", &tz) != 1)
usage();
tzs = " ";
argc--;
break;
case 't':
str = *++argv;
if (sscanf(str, "%d:%d:%d", &th, &tm, &ts) != 3)
usage();
argc--;
break;
case 'd':
str = *++argv;
if (sscanf(str, "%d/%d/%d", &mo, &day, &yr) != 3)
usage();
argc--;
break;
default: usage();
}
} else usage();
}
}
usage()
{
printf("Usage: sun [-p] [-t h:m:s] [-d m/d/y] [-a lat] [-o lon] [-z tz]\n");
exit(1);
}
double
julian_date(m, d, y)
{
long a, b;
double jd;
if (m == 1 || m == 2) {
--y;
m += 12;
}
if (y < 1583) {
printf("Can't handle dates before 1583\n");
exit(1);
}
a = y/100;
b = 2 - a + a/4;
b += (int)((double)y * 365.25);
b += (int)(30.6001 * ((double)m + 1.0));
jd = (double)d + (double)b + 1720994.5;
if (debug)
printf("Julian date for %d/%d/%d is %lf \n", m, d, y, jd);
return(jd);
}
double
hms_to_dh(h, m, s)
{
double rv;
rv = h + m / 60.0 + s / 3600.0;
if (debug)
printf("For time %d:%d:%d frac hours are: %lf \n", h, m, s, rv);
return rv;
}
double
solar_lon(ed)
double ed;
{
double n, m, e, ect, errt, v;
n = 360.0 * ed / 365.2422;
n = adj360(n);
m = n + 278.83354 - 282.596403;
m = adj360(m);
m = dtor(m);
e = m; ect = 0.016718;
while ((errt = e - ect * sin(e) - m) > 0.0000001)
e = e - errt / (1 - ect * cos(e));
v = 2 * atan(1.0168601 * tan(e/2));
v = adj360(v * 180.0 / PI + 282.596403);
if (debug)
printf("Solar Longitude for %lf days is %lf \n", ed, v);
return(v);
}
double
acos_deg(x)
double x;
{
return rtod(acos(x));
}
double
asin_deg(x)
double x;
{
return rtod(asin(x));
}
double
atan_q_deg(y,x)
double y,x;
{
double rv;
if (y == 0)
rv = 0;
else if (x == 0)
rv = y>0 ? 90.0 : -90.0;
else rv = atan_deg(y/x);
if (x<0) return rv+180.0;
if (y<0) return rv+360.0;
return(rv);
}
double
atan_deg(x)
double x;
{
return rtod(atan(x));
}
double
sin_deg(x)
double x;
{
return sin(dtor(x));
}
double
cos_deg(x)
double x;
{
return cos(dtor(x));
}
double
tan_deg(x)
double x;
{
return tan(dtor(x));
}
lon_to_eq(lambda, alpha, delta)
double lambda;
double *alpha;
double *delta;
{
double tlam,epsilon;
tlam = dtor(lambda);
epsilon = dtor((double)23.441884);
*alpha = atan_q_deg((sin(tlam))*cos(epsilon),cos(tlam)) / 15.0;
*delta = asin_deg(sin(epsilon)*sin(tlam));
if (debug)
printf("Right ascension, declination for lon %lf is %lf, %lf \n",
lambda, *alpha, *delta);
}
rise_set(alpha, delta, lstr, lsts, ar, as)
double alpha, delta, *lstr, *lsts, *ar, *as;
{
double tar;
double h;
tar = sin_deg(delta)/cos_deg(lat);
if (tar < -1.0 || tar > 1.0) {
printf("The object is circumpolar\n");
exit (1);
}
*ar = acos_deg(tar);
*as = 360.0 - *ar;
h = acos_deg(-tan_deg(lat) * tan_deg(delta)) / 15.0;
*lstr = 24.0 + alpha - h;
if (*lstr > 24.0)
*lstr -= 24.0;
*lsts = alpha + h;
if (*lsts > 24.0)
*lsts -= 24.0;
if (debug) {
printf("For ra, decl. of %lf, %lf: \n", alpha, delta);
printf("lstr = %lf, lsts = %lf, \n", *lstr, *lsts);
printf("ar = %lf, as = %lf \n", *ar, *as);
}
}
lst_to_hm(lst, jd, h, m)
double lst, jd;
int *h, *m;
{
double ed, gst, jzjd, t, r, b, t0, gmt;
gst = lst + lon / 15.0;
if (gst > 24.0)
gst -= 24.0;
jzjd = julian_date(1,0,yr);
ed = jd-jzjd;
t = (jzjd -2415020.0)/36525.0;
r = 6.6460656+2400.05126*t+2.58E-05*t*t;
b = 24-(r-24*(yr-1900));
t0 = ed * 0.0657098 - b;
if (t0 < 0.0)
t0 += 24;
gmt = gst-t0;
if (gmt<0)
gmt += 24.0;
gmt = gmt * 0.99727 - tz;;
if (gmt < 0)
gmt +=24.0;
dh_to_hm(gmt, h, m);
}
dh_to_hm(dh, h, m)
double dh;
int *h, *m;
{
double tempsec;
*h = dh;
*m = (dh - *h) * 60;
tempsec = (dh - *h) * 60 - *m;
tempsec = tempsec * 60 + 0.5;
if (tempsec > 30)
(*m)++;
if (*m == 60) {
*m = 0;
(*h)++;
}
}
eq_to_altaz(r, d, t, alt, az)
double r, d, t;
double *alt, *az;
{
double p = 3.14159265;
double r1 = p / 180.0;
double b = lat * r1;
double l = (360 - lon) * r1;
double t5, s1, c1, c2, s2, a, h;
if (debug)
printf("Given R. A. = %lf, DECL. = %lf, gmt = %lf \n", r, d, t);
r = r * 15.0 * r1;
d = d * r1;
t = t * 15.0 * r1;
t5 = t - r + l;
s1 = sin(b) * sin(d) + cos(b) * cos(d) * cos(t5);
c1 = 1 - s1 * s1;
if (c1 > 0) {
c1 = sqrt(c1);
h = atan(s1 / c1);
} else {
h = (s1 / fabs(s1)) * (p / 2.0);
}
c2 = cos(b) * sin(d) - sin(b) * cos(d) * cos(t5);
s2 = -cos(d) * sin(t5);
if (c2 == 0)
a = (s2/fabs(s2)) * (p/2);
else {
a = atan(s2/c2);
if (c2 < 0)
a=a+p;
}
if (a<0)
a=a+2*p;
*alt = h / r1;
*az = a / r1;
if (debug)
printf("alt = %lf, az = %lf \n",*alt,*az);
}
double
gmst(j, f)
double j,f;
{
double d, j0, t, t1, t2, s;
d = j - 2451545.0;
t = d / 36525.0;
t1 = floor(t);
j0 = t1 * 36525.0 + 2451545.0;
t2 = (j - j0 + 0.5)/36525.0;
s = 24110.54841 + 184.812866 * t1;
s += 8640184.812866 * t2;
s += 0.093104 * t * t;
s -= 0.0000062 * t * t * t;
s /= 86400.0;
s -= floor(s);
s = 24 * (s + (f - 0.5) * 1.002737909);
if (s < 0)
s += 24.0;
if (s > 24.0)
s -= 24.0;
if (debug)
printf("For jd = %lf, f = %lf, gst = %lf \n", j, f, s);
return(s);
}