6 |
|
* |
7 |
|
* 3/31/87 |
8 |
|
* |
9 |
+ |
* Michalsky algorithm added October 2019: |
10 |
+ |
* "The Astronomical Almanac's Algorithm for Approximate |
11 |
+ |
* Solar Position (1950-2050)" by Joseph J. Michalsky, |
12 |
+ |
* published in 1988 in Solar Energy, Vol. 40, No. 3. |
13 |
+ |
* Also added correction to sdec() (365 was 368 originally) |
14 |
+ |
* |
15 |
|
*/ |
16 |
|
|
17 |
|
#include <math.h> |
20 |
|
#ifdef M_PI |
21 |
|
#define PI M_PI |
22 |
|
#else |
23 |
< |
#define PI 3.141592653589793 |
23 |
> |
#define PI 3.14159265358979323846 |
24 |
|
#endif |
25 |
+ |
#undef DEG |
26 |
+ |
#define DEG (PI/180.) |
27 |
|
|
20 |
– |
double s_latitude = 0.66; /* site latitude (radians) */ |
21 |
– |
double s_longitude = 2.13; /* site longitude (radians) */ |
22 |
– |
double s_meridian = 2.0944; /* standard meridian (radians) */ |
28 |
|
|
29 |
+ |
double s_latitude = 0.66; /* site latitude (radians north of equator) */ |
30 |
+ |
double s_longitude = 2.13; /* site longitude (radians west of Greenwich) */ |
31 |
+ |
double s_meridian = 120.*DEG; /* standard meridian (radians west) */ |
32 |
|
|
33 |
+ |
|
34 |
|
int |
35 |
|
jdate( /* Julian date (days into year) */ |
36 |
|
int month, |
48 |
|
int jd |
49 |
|
) |
50 |
|
{ |
51 |
< |
return( 0.170 * sin( (4*PI/373) * (jd - 80) ) - |
52 |
< |
0.129 * sin( (2*PI/355) * (jd - 8) ) + |
53 |
< |
12 * (s_meridian - s_longitude) / PI ); |
51 |
> |
return( 0.170 * sin( (4.*PI/373.) * (jd - 80) ) - |
52 |
> |
0.129 * sin( (2.*PI/355.) * (jd - 8) ) + |
53 |
> |
(12./PI) * (s_meridian - s_longitude) ); |
54 |
|
} |
55 |
|
|
56 |
|
|
59 |
|
int jd |
60 |
|
) |
61 |
|
{ |
62 |
< |
return( 0.4093 * sin( (2*PI/368) * (jd - 81) ) ); |
62 |
> |
return( 0.4093 * sin( (2.*PI/365.) * (jd - 81) ) ); |
63 |
|
} |
64 |
|
|
65 |
|
|
70 |
|
) |
71 |
|
{ |
72 |
|
return( asin( sin(s_latitude) * sin(sd) - |
73 |
< |
cos(s_latitude) * cos(sd) * cos(st*(PI/12)) ) ); |
73 |
> |
cos(s_latitude) * cos(sd) * cos(st*(PI/12.)) ) ); |
74 |
|
} |
75 |
|
|
76 |
|
|
80 |
|
double st |
81 |
|
) |
82 |
|
{ |
83 |
< |
return( -atan2( cos(sd)*sin(st*(PI/12)), |
83 |
> |
return( -atan2( cos(sd)*sin(st*(PI/12.)), |
84 |
|
-cos(s_latitude)*sin(sd) - |
85 |
< |
sin(s_latitude)*cos(sd)*cos(st*(PI/12)) ) ); |
85 |
> |
sin(s_latitude)*cos(sd)*cos(st*(PI/12.)) ) ); |
86 |
> |
} |
87 |
> |
|
88 |
> |
|
89 |
> |
/****************** More accurate Michalsky algorithm ****************/ |
90 |
> |
|
91 |
> |
|
92 |
> |
/* circle normalization */ |
93 |
> |
static double |
94 |
> |
norm_cir(double r, const double p) |
95 |
> |
{ |
96 |
> |
while (r < 0) r += p; |
97 |
> |
while (r >= p) r -= p; |
98 |
> |
return(r); |
99 |
> |
} |
100 |
> |
|
101 |
> |
|
102 |
> |
/* Almanac Julian date relative to noon UT on Jan 1, 2000 (fractional days) */ |
103 |
> |
double |
104 |
> |
mjdate(int year, int month, int day, double hour) |
105 |
> |
{ |
106 |
> |
int jd = jdate(month, day); |
107 |
> |
jd += (month > 2) & !(year&3); |
108 |
> |
jd += (year - 1949)*365 + (year - 1949)/4; |
109 |
> |
hour += s_meridian*(12./PI); |
110 |
> |
return(jd + hour*(1./24.) + (2432916.5-2451545.)); |
111 |
> |
} |
112 |
> |
|
113 |
> |
|
114 |
> |
/* Solar declination (and solar time) from Almanac Julian date (fractional) */ |
115 |
> |
double |
116 |
> |
msdec(double mjd, double *stp) |
117 |
> |
{ /* Ecliptic coordinates (radians) */ |
118 |
> |
double L = norm_cir(280.460*DEG + 0.9856474*DEG*mjd, 2.*PI); |
119 |
> |
double g = norm_cir(357.528*DEG + 0.9856003*DEG*mjd, 2.*PI); |
120 |
> |
double l = L + 1.915*DEG*sin(g) + 0.020*DEG*sin(2.*g); |
121 |
> |
double ep = 23.439*DEG - 4e-7*DEG*mjd; |
122 |
> |
double sin_l = sin(l); |
123 |
> |
|
124 |
> |
if (stp) { /* solar time requested, also? */ |
125 |
> |
double ra = atan2(sin_l*cos(ep), cos(l)); |
126 |
> |
double utime = 24.*(mjd - floor(mjd)) + 12.; |
127 |
> |
double gmst = 6.697375 + 0.0657098242*mjd + utime; |
128 |
> |
double lmst = gmst - s_longitude*(12./PI); |
129 |
> |
|
130 |
> |
*stp = norm_cir(lmst - ra*(12./PI) + 12., 24.); |
131 |
> |
} |
132 |
> |
return(asin(sin(ep)*sin_l)); /* return solar declination angle */ |
133 |
|
} |