-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathspa.h
206 lines (166 loc) · 10.7 KB
/
spa.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/////////////////////////////////////////////
// HEADER FILE for SPA.C //
// //
// Solar Position Algorithm (SPA) //
// for //
// Solar Radiation Application //
// //
// May 12, 2003 //
// //
// Filename: SPA.H //
// //
// Afshin Michael Andreas //
// afshin_andreas@nrel.gov (303)384-6383 //
// //
// Measurement & Instrumentation Team //
// Solar Radiation Research Laboratory //
// National Renewable Energy Laboratory //
// 1617 Cole Blvd, Golden, CO 80401 //
/////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// //
// Usage: //
// //
// 1) In calling program, include this header file, //
// by adding this line to the top of file: //
// #include "spa.h" //
// //
// 2) In calling program, declare the SPA structure: //
// spa_data spa; //
// //
// 3) Enter the required input values into SPA structure //
// (input values listed in comments below) //
// //
// 4) Call the SPA calculate function and pass the SPA structure //
// (prototype is declared at the end of this header file): //
// spa_calculate(&spa); //
// //
// Selected output values (listed in comments below) will be //
// computed and returned in the passed SPA structure. Output //
// will based on function code selected from enumeration below. //
// //
// Note: A non-zero return code from spa_calculate() indicates that //
// one of the input values did not pass simple bounds tests. //
// The valid input ranges and return error codes are also //
// listed below. //
// //
////////////////////////////////////////////////////////////////////////
#ifndef __solar_position_algorithm_header
#define __solar_position_algorithm_header
//enumeration for function codes to select desired final outputs from SPA
enum {
SPA_ZA, //calculate zenith and azimuth
SPA_ZA_INC, //calculate zenith, azimuth, and incidence
SPA_ZA_RTS, //calculate zenith, azimuth, and sun rise/transit/set values
SPA_ALL, //calculate all SPA output values
};
typedef struct
{
//----------------------INPUT VALUES------------------------
int year; // 4-digit year, valid range: -2000 to 6000, error code: 1
int month; // 2-digit month, valid range: 1 to 12, error code: 2
int day; // 2-digit day, valid range: 1 to 31, error code: 3
int hour; // Observer local hour, valid range: 0 to 24, error code: 4
int minute; // Observer local minute, valid range: 0 to 59, error code: 5
double second; // Observer local second, valid range: 0 to <60, error code: 6
double delta_ut1; // Fractional second difference between UTC and UT which is used
// to adjust UTC for earth's irregular rotation rate and is derived
// from observation only and is reported in this bulletin:
// http://maia.usno.navy.mil/ser7/ser7.dat,
// where delta_ut1 = DUT1
// valid range: -1 to 1 second (exclusive), error code 17
double delta_t; // Difference between earth rotation time and terrestrial time
// It is derived from observation only and is reported in this
// bulletin: http://maia.usno.navy.mil/ser7/ser7.dat,
// where delta_t = 32.184 + (TAI-UTC) - DUT1
// valid range: -8000 to 8000 seconds, error code: 7
double timezone; // Observer time zone (negative west of Greenwich)
// valid range: -18 to 18 hours, error code: 8
double longitude; // Observer longitude (negative west of Greenwich)
// valid range: -180 to 180 degrees, error code: 9
double latitude; // Observer latitude (negative south of equator)
// valid range: -90 to 90 degrees, error code: 10
double elevation; // Observer elevation [meters]
// valid range: -6500000 or higher meters, error code: 11
double pressure; // Annual average local pressure [millibars]
// valid range: 0 to 5000 millibars, error code: 12
double temperature; // Annual average local temperature [degrees Celsius]
// valid range: -273 to 6000 degrees Celsius, error code; 13
double slope; // Surface slope (measured from the horizontal plane)
// valid range: -360 to 360 degrees, error code: 14
double azm_rotation; // Surface azimuth rotation (measured from south to projection of
// surface normal on horizontal plane, negative east)
// valid range: -360 to 360 degrees, error code: 15
double atmos_refract;// Atmospheric refraction at sunrise and sunset (0.5667 deg is typical)
// valid range: -5 to 5 degrees, error code: 16
int function; // Switch to choose functions for desired output (from enumeration)
//-----------------Intermediate OUTPUT VALUES--------------------
double jd; //Julian day
double jc; //Julian century
double jde; //Julian ephemeris day
double jce; //Julian ephemeris century
double jme; //Julian ephemeris millennium
double l; //earth heliocentric longitude [degrees]
double b; //earth heliocentric latitude [degrees]
double r; //earth radius vector [Astronomical Units, AU]
double theta; //geocentric longitude [degrees]
double beta; //geocentric latitude [degrees]
double x0; //mean elongation (moon-sun) [degrees]
double x1; //mean anomaly (sun) [degrees]
double x2; //mean anomaly (moon) [degrees]
double x3; //argument latitude (moon) [degrees]
double x4; //ascending longitude (moon) [degrees]
double del_psi; //nutation longitude [degrees]
double del_epsilon; //nutation obliquity [degrees]
double epsilon0; //ecliptic mean obliquity [arc seconds]
double epsilon; //ecliptic true obliquity [degrees]
double del_tau; //aberration correction [degrees]
double lamda; //apparent sun longitude [degrees]
double nu0; //Greenwich mean sidereal time [degrees]
double nu; //Greenwich sidereal time [degrees]
double alpha; //geocentric sun right ascension [degrees]
double delta; //geocentric sun declination [degrees]
double h; //observer hour angle [degrees]
double xi; //sun equatorial horizontal parallax [degrees]
double del_alpha; //sun right ascension parallax [degrees]
double delta_prime; //topocentric sun declination [degrees]
double alpha_prime; //topocentric sun right ascension [degrees]
double h_prime; //topocentric local hour angle [degrees]
double e0; //topocentric elevation angle (uncorrected) [degrees]
double del_e; //atmospheric refraction correction [degrees]
double e; //topocentric elevation angle (corrected) [degrees]
double eot; //equation of time [minutes]
double srha; //sunrise hour angle [degrees]
double ssha; //sunset hour angle [degrees]
double sta; //sun transit altitude [degrees]
//---------------------Final OUTPUT VALUES------------------------
double zenith; //topocentric zenith angle [degrees]
double azimuth_astro;//topocentric azimuth angle (westward from south) [for astronomers]
double azimuth; //topocentric azimuth angle (eastward from north) [for navigators and solar radiation]
double incidence; //surface incidence angle [degrees]
double suntransit; //local sun transit time (or solar noon) [fractional hour]
double sunrise; //local sunrise time (+/- 30 seconds) [fractional hour]
double sunset; //local sunset time (+/- 30 seconds) [fractional hour]
} spa_data;
//-------------- Utility functions for other applications (such as NREL's SAMPA) --------------
double deg2rad(double degrees);
double rad2deg(double radians);
double limit_degrees(double degrees);
double third_order_polynomial(double a, double b, double c, double d, double x);
double geocentric_right_ascension(double lamda, double epsilon, double beta);
double geocentric_declination(double beta, double epsilon, double lamda);
double observer_hour_angle(double nu, double longitude, double alpha_deg);
void right_ascension_parallax_and_topocentric_dec(double latitude, double elevation,
double xi, double h, double delta, double *delta_alpha, double *delta_prime);
double topocentric_right_ascension(double alpha_deg, double delta_alpha);
double topocentric_local_hour_angle(double h, double delta_alpha);
double topocentric_elevation_angle(double latitude, double delta_prime, double h_prime);
double atmospheric_refraction_correction(double pressure, double temperature,
double atmos_refract, double e0);
double topocentric_elevation_angle_corrected(double e0, double delta_e);
double topocentric_zenith_angle(double e);
double topocentric_azimuth_angle_astro(double h_prime, double latitude, double delta_prime);
double topocentric_azimuth_angle(double azimuth_astro);
//Calculate SPA output values (in structure) based on input values passed in structure
int spa_calculate(spa_data *spa);
#endif