mirror of
https://github.com/acamarata/solar-spa.git
synced 2026-06-30 19:04:28 +00:00
206 lines
11 KiB
C
206 lines
11 KiB
C
|
|
|
|
/////////////////////////////////////////////
|
|
// 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
|