This code is imported direct from http://rredc.nrel.gov/solar/codesandalgorithms/solpos/ Copyrights are retained in the code for each algorithm used. The library calculates the apparent solar position and intensity (theoretical maximum solar energy) based on the date, time, and location on Earth. The calculated data can be used to predict solar radiation, to be used in meteorological, solar energy and irrigation applications.

Committer:
jcobb
Date:
Tue Jul 20 22:45:48 2010 +0000
Revision:
0:fba19b344b6d

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jcobb 0:fba19b344b6d 1 /*============================================================================
jcobb 0:fba19b344b6d 2 * Contains:
jcobb 0:fba19b344b6d 3 * S_solpos (computes solar position and intensity
jcobb 0:fba19b344b6d 4 * from time and place)
jcobb 0:fba19b344b6d 5 *
jcobb 0:fba19b344b6d 6 * INPUTS: (via posdata struct) year, daynum, hour,
jcobb 0:fba19b344b6d 7 * minute, second, latitude, longitude, timezone,
jcobb 0:fba19b344b6d 8 * intervl
jcobb 0:fba19b344b6d 9 * OPTIONAL: (via posdata struct) month, day, press, temp, tilt,
jcobb 0:fba19b344b6d 10 * aspect, function
jcobb 0:fba19b344b6d 11 * OUTPUTS: EVERY variable in the struct posdata
jcobb 0:fba19b344b6d 12 * (defined in solpos.h)
jcobb 0:fba19b344b6d 13 *
jcobb 0:fba19b344b6d 14 * NOTE: Certain conditions exist during which some of
jcobb 0:fba19b344b6d 15 * the output variables are undefined or cannot be
jcobb 0:fba19b344b6d 16 * calculated. In these cases, the variables are
jcobb 0:fba19b344b6d 17 * returned with flag values indicating such. In other
jcobb 0:fba19b344b6d 18 * cases, the variables may return a realistic, though
jcobb 0:fba19b344b6d 19 * invalid, value. These variables and the flag values
jcobb 0:fba19b344b6d 20 * or invalid conditions are listed below:
jcobb 0:fba19b344b6d 21 *
jcobb 0:fba19b344b6d 22 * amass -1.0 at zenetr angles greater than 93.0
jcobb 0:fba19b344b6d 23 * degrees
jcobb 0:fba19b344b6d 24 * ampress -1.0 at zenetr angles greater than 93.0
jcobb 0:fba19b344b6d 25 * degrees
jcobb 0:fba19b344b6d 26 * azim invalid at zenetr angle 0.0 or latitude
jcobb 0:fba19b344b6d 27 * +/-90.0 or at night
jcobb 0:fba19b344b6d 28 * elevetr limited to -9 degrees at night
jcobb 0:fba19b344b6d 29 * etr 0.0 at night
jcobb 0:fba19b344b6d 30 * etrn 0.0 at night
jcobb 0:fba19b344b6d 31 * etrtilt 0.0 when cosinc is less than 0
jcobb 0:fba19b344b6d 32 * prime invalid at zenetr angles greater than 93.0
jcobb 0:fba19b344b6d 33 * degrees
jcobb 0:fba19b344b6d 34 * sretr +/- 2999.0 during periods of 24 hour sunup or
jcobb 0:fba19b344b6d 35 * sundown
jcobb 0:fba19b344b6d 36 * ssetr +/- 2999.0 during periods of 24 hour sunup or
jcobb 0:fba19b344b6d 37 * sundown
jcobb 0:fba19b344b6d 38 * ssha invalid at the North and South Poles
jcobb 0:fba19b344b6d 39 * unprime invalid at zenetr angles greater than 93.0
jcobb 0:fba19b344b6d 40 * degrees
jcobb 0:fba19b344b6d 41 * zenetr limited to 99.0 degrees at night
jcobb 0:fba19b344b6d 42 *
jcobb 0:fba19b344b6d 43 * S_init (optional initialization for all input parameters in
jcobb 0:fba19b344b6d 44 * the posdata struct)
jcobb 0:fba19b344b6d 45 * INPUTS: struct posdata*
jcobb 0:fba19b344b6d 46 * OUTPUTS: struct posdata*
jcobb 0:fba19b344b6d 47 *
jcobb 0:fba19b344b6d 48 * (Note: initializes the required S_solpos INPUTS above
jcobb 0:fba19b344b6d 49 * to out-of-bounds conditions, forcing the user to
jcobb 0:fba19b344b6d 50 * supply the parameters; initializes the OPTIONAL
jcobb 0:fba19b344b6d 51 * S_solpos inputs above to nominal values.)
jcobb 0:fba19b344b6d 52 *
jcobb 0:fba19b344b6d 53 * S_decode (optional utility for decoding the S_solpos return code)
jcobb 0:fba19b344b6d 54 * INPUTS: long integer S_solpos return value, struct posdata*
jcobb 0:fba19b344b6d 55 * OUTPUTS: text to stderr
jcobb 0:fba19b344b6d 56 *
jcobb 0:fba19b344b6d 57 * Usage:
jcobb 0:fba19b344b6d 58 * In calling program, just after other 'includes', insert:
jcobb 0:fba19b344b6d 59 *
jcobb 0:fba19b344b6d 60 * #include "solpos00.h"
jcobb 0:fba19b344b6d 61 *
jcobb 0:fba19b344b6d 62 * Function calls:
jcobb 0:fba19b344b6d 63 * S_init(struct posdata*) [optional]
jcobb 0:fba19b344b6d 64 * .
jcobb 0:fba19b344b6d 65 * .
jcobb 0:fba19b344b6d 66 * [set time and location parameters before S_solpos call]
jcobb 0:fba19b344b6d 67 * .
jcobb 0:fba19b344b6d 68 * .
jcobb 0:fba19b344b6d 69 * int retval = S_solpos(struct posdata*)
jcobb 0:fba19b344b6d 70 * S_decode(int retval, struct posdata*) [optional]
jcobb 0:fba19b344b6d 71 * (Note: you should always look at the S_solpos return
jcobb 0:fba19b344b6d 72 * value, which contains error codes. S_decode is one option
jcobb 0:fba19b344b6d 73 * for examining these codes. It can also serve as a
jcobb 0:fba19b344b6d 74 * template for building your own application-specific
jcobb 0:fba19b344b6d 75 * decoder.)
jcobb 0:fba19b344b6d 76 *
jcobb 0:fba19b344b6d 77 * Martin Rymes
jcobb 0:fba19b344b6d 78 * National Renewable Energy Laboratory
jcobb 0:fba19b344b6d 79 * 25 March 1998
jcobb 0:fba19b344b6d 80 *
jcobb 0:fba19b344b6d 81 * 27 April 1999 REVISION: Corrected leap year in S_date.
jcobb 0:fba19b344b6d 82 * 13 January 2000 REVISION: SMW converted to structure posdata parameter
jcobb 0:fba19b344b6d 83 * and subdivided into functions.
jcobb 0:fba19b344b6d 84 * 01 February 2001 REVISION: SMW corrected ecobli calculation
jcobb 0:fba19b344b6d 85 * (changed sign). Error is small (max 0.015 deg
jcobb 0:fba19b344b6d 86 * in calculation of declination angle)
jcobb 0:fba19b344b6d 87 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 88 #include <math.h>
jcobb 0:fba19b344b6d 89 #include <string.h>
jcobb 0:fba19b344b6d 90 #include <stdio.h>
jcobb 0:fba19b344b6d 91 #include "solpos00.h"
jcobb 0:fba19b344b6d 92
jcobb 0:fba19b344b6d 93 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
jcobb 0:fba19b344b6d 94 *
jcobb 0:fba19b344b6d 95 * Structures defined for this module
jcobb 0:fba19b344b6d 96 *
jcobb 0:fba19b344b6d 97 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
jcobb 0:fba19b344b6d 98 struct trigdata /* used to pass calculated values locally */
jcobb 0:fba19b344b6d 99 {
jcobb 0:fba19b344b6d 100 float cd; /* cosine of the declination */
jcobb 0:fba19b344b6d 101 float ch; /* cosine of the hour angle */
jcobb 0:fba19b344b6d 102 float cl; /* cosine of the latitude */
jcobb 0:fba19b344b6d 103 float sd; /* sine of the declination */
jcobb 0:fba19b344b6d 104 float sl; /* sine of the latitude */
jcobb 0:fba19b344b6d 105 };
jcobb 0:fba19b344b6d 106
jcobb 0:fba19b344b6d 107
jcobb 0:fba19b344b6d 108 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
jcobb 0:fba19b344b6d 109 *
jcobb 0:fba19b344b6d 110 * Temporary global variables used only in this file:
jcobb 0:fba19b344b6d 111 *
jcobb 0:fba19b344b6d 112 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
jcobb 0:fba19b344b6d 113 static int month_days[2][13] = { { 0, 0, 31, 59, 90, 120, 151,
jcobb 0:fba19b344b6d 114 181, 212, 243, 273, 304, 334 },
jcobb 0:fba19b344b6d 115 { 0, 0, 31, 60, 91, 121, 152,
jcobb 0:fba19b344b6d 116 182, 213, 244, 274, 305, 335 } };
jcobb 0:fba19b344b6d 117 /* cumulative number of days prior to beginning of month */
jcobb 0:fba19b344b6d 118
jcobb 0:fba19b344b6d 119 static float degrad = 57.295779513; /* converts from radians to degrees */
jcobb 0:fba19b344b6d 120 static float raddeg = 0.0174532925; /* converts from degrees to radians */
jcobb 0:fba19b344b6d 121
jcobb 0:fba19b344b6d 122 /*============================================================================
jcobb 0:fba19b344b6d 123 * Local function prototypes
jcobb 0:fba19b344b6d 124 ============================================================================*/
jcobb 0:fba19b344b6d 125 static long int validate ( struct posdata *pdat);
jcobb 0:fba19b344b6d 126 static void dom2doy( struct posdata *pdat );
jcobb 0:fba19b344b6d 127 static void doy2dom( struct posdata *pdat );
jcobb 0:fba19b344b6d 128 static void geometry ( struct posdata *pdat );
jcobb 0:fba19b344b6d 129 static void zen_no_ref ( struct posdata *pdat, struct trigdata *tdat );
jcobb 0:fba19b344b6d 130 static void ssha( struct posdata *pdat, struct trigdata *tdat );
jcobb 0:fba19b344b6d 131 static void sbcf( struct posdata *pdat, struct trigdata *tdat );
jcobb 0:fba19b344b6d 132 static void tst( struct posdata *pdat );
jcobb 0:fba19b344b6d 133 static void srss( struct posdata *pdat );
jcobb 0:fba19b344b6d 134 static void sazm( struct posdata *pdat, struct trigdata *tdat );
jcobb 0:fba19b344b6d 135 static void refrac( struct posdata *pdat );
jcobb 0:fba19b344b6d 136 static void amass( struct posdata *pdat );
jcobb 0:fba19b344b6d 137 static void prime( struct posdata *pdat );
jcobb 0:fba19b344b6d 138 static void etr( struct posdata *pdat );
jcobb 0:fba19b344b6d 139 static void tilt( struct posdata *pdat );
jcobb 0:fba19b344b6d 140 static void localtrig( struct posdata *pdat, struct trigdata *tdat );
jcobb 0:fba19b344b6d 141
jcobb 0:fba19b344b6d 142 /*============================================================================
jcobb 0:fba19b344b6d 143 * Long integer function S_solpos, adapted from the VAX solar libraries
jcobb 0:fba19b344b6d 144 *
jcobb 0:fba19b344b6d 145 * This function calculates the apparent solar position and the
jcobb 0:fba19b344b6d 146 * intensity of the sun (theoretical maximum solar energy) from
jcobb 0:fba19b344b6d 147 * time and place on Earth.
jcobb 0:fba19b344b6d 148 *
jcobb 0:fba19b344b6d 149 * Requires (from the struct posdata parameter):
jcobb 0:fba19b344b6d 150 * Date and time:
jcobb 0:fba19b344b6d 151 * year
jcobb 0:fba19b344b6d 152 * daynum (requirement depends on the S_DOY switch)
jcobb 0:fba19b344b6d 153 * month (requirement depends on the S_DOY switch)
jcobb 0:fba19b344b6d 154 * day (requirement depends on the S_DOY switch)
jcobb 0:fba19b344b6d 155 * hour
jcobb 0:fba19b344b6d 156 * minute
jcobb 0:fba19b344b6d 157 * second
jcobb 0:fba19b344b6d 158 * interval DEFAULT 0
jcobb 0:fba19b344b6d 159 * Location:
jcobb 0:fba19b344b6d 160 * latitude
jcobb 0:fba19b344b6d 161 * longitude
jcobb 0:fba19b344b6d 162 * Location/time adjuster:
jcobb 0:fba19b344b6d 163 * timezone
jcobb 0:fba19b344b6d 164 * Atmospheric pressure and temperature:
jcobb 0:fba19b344b6d 165 * press DEFAULT 1013.0 mb
jcobb 0:fba19b344b6d 166 * temp DEFAULT 10.0 degrees C
jcobb 0:fba19b344b6d 167 * Tilt of flat surface that receives solar energy:
jcobb 0:fba19b344b6d 168 * aspect DEFAULT 180 (South)
jcobb 0:fba19b344b6d 169 * tilt DEFAULT 0 (Horizontal)
jcobb 0:fba19b344b6d 170 * Function Switch (codes defined in solpos.h)
jcobb 0:fba19b344b6d 171 * function DEFAULT S_ALL
jcobb 0:fba19b344b6d 172 *
jcobb 0:fba19b344b6d 173 * Returns (via the struct posdata parameter):
jcobb 0:fba19b344b6d 174 * everything defined in the struct posdata in solpos.h.
jcobb 0:fba19b344b6d 175 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 176 long S_solpos (struct posdata *pdat)
jcobb 0:fba19b344b6d 177 {
jcobb 0:fba19b344b6d 178 long int retval;
jcobb 0:fba19b344b6d 179
jcobb 0:fba19b344b6d 180 struct trigdata trigdat, *tdat;
jcobb 0:fba19b344b6d 181
jcobb 0:fba19b344b6d 182 tdat = &trigdat; /* point to the structure */
jcobb 0:fba19b344b6d 183
jcobb 0:fba19b344b6d 184 /* initialize the trig structure */
jcobb 0:fba19b344b6d 185 tdat->sd = -999.0; /* flag to force calculation of trig data */
jcobb 0:fba19b344b6d 186 tdat->cd = 1.0;
jcobb 0:fba19b344b6d 187 tdat->ch = 1.0; /* set the rest of these to something safe */
jcobb 0:fba19b344b6d 188 tdat->cl = 1.0;
jcobb 0:fba19b344b6d 189 tdat->sl = 1.0;
jcobb 0:fba19b344b6d 190
jcobb 0:fba19b344b6d 191 if ((retval = validate ( pdat )) != 0) /* validate the inputs */
jcobb 0:fba19b344b6d 192 return retval;
jcobb 0:fba19b344b6d 193
jcobb 0:fba19b344b6d 194
jcobb 0:fba19b344b6d 195 if ( pdat->function & L_DOY )
jcobb 0:fba19b344b6d 196 doy2dom( pdat ); /* convert input doy to month-day */
jcobb 0:fba19b344b6d 197 else
jcobb 0:fba19b344b6d 198 dom2doy( pdat ); /* convert input month-day to doy */
jcobb 0:fba19b344b6d 199
jcobb 0:fba19b344b6d 200 if ( pdat->function & L_GEOM )
jcobb 0:fba19b344b6d 201 geometry( pdat ); /* do basic geometry calculations */
jcobb 0:fba19b344b6d 202
jcobb 0:fba19b344b6d 203 if ( pdat->function & L_ZENETR ) /* etr at non-refracted zenith angle */
jcobb 0:fba19b344b6d 204 zen_no_ref( pdat, tdat );
jcobb 0:fba19b344b6d 205
jcobb 0:fba19b344b6d 206 if ( pdat->function & L_SSHA ) /* Sunset hour calculation */
jcobb 0:fba19b344b6d 207 ssha( pdat, tdat );
jcobb 0:fba19b344b6d 208
jcobb 0:fba19b344b6d 209 if ( pdat->function & L_SBCF ) /* Shadowband correction factor */
jcobb 0:fba19b344b6d 210 sbcf( pdat, tdat );
jcobb 0:fba19b344b6d 211
jcobb 0:fba19b344b6d 212 if ( pdat->function & L_TST ) /* true solar time */
jcobb 0:fba19b344b6d 213 tst( pdat );
jcobb 0:fba19b344b6d 214
jcobb 0:fba19b344b6d 215 if ( pdat->function & L_SRSS ) /* sunrise/sunset calculations */
jcobb 0:fba19b344b6d 216 srss( pdat );
jcobb 0:fba19b344b6d 217
jcobb 0:fba19b344b6d 218 if ( pdat->function & L_SOLAZM ) /* solar azimuth calculations */
jcobb 0:fba19b344b6d 219 sazm( pdat, tdat );
jcobb 0:fba19b344b6d 220
jcobb 0:fba19b344b6d 221 if ( pdat->function & L_REFRAC ) /* atmospheric refraction calculations */
jcobb 0:fba19b344b6d 222 refrac( pdat );
jcobb 0:fba19b344b6d 223
jcobb 0:fba19b344b6d 224 if ( pdat->function & L_AMASS ) /* airmass calculations */
jcobb 0:fba19b344b6d 225 amass( pdat );
jcobb 0:fba19b344b6d 226
jcobb 0:fba19b344b6d 227 if ( pdat->function & L_PRIME ) /* kt-prime/unprime calculations */
jcobb 0:fba19b344b6d 228 prime( pdat );
jcobb 0:fba19b344b6d 229
jcobb 0:fba19b344b6d 230 if ( pdat->function & L_ETR ) /* ETR and ETRN (refracted) */
jcobb 0:fba19b344b6d 231 etr( pdat );
jcobb 0:fba19b344b6d 232
jcobb 0:fba19b344b6d 233 if ( pdat->function & L_TILT ) /* tilt calculations */
jcobb 0:fba19b344b6d 234 tilt( pdat );
jcobb 0:fba19b344b6d 235
jcobb 0:fba19b344b6d 236 return 0;
jcobb 0:fba19b344b6d 237 }
jcobb 0:fba19b344b6d 238
jcobb 0:fba19b344b6d 239
jcobb 0:fba19b344b6d 240 /*============================================================================
jcobb 0:fba19b344b6d 241 * Void function S_init
jcobb 0:fba19b344b6d 242 *
jcobb 0:fba19b344b6d 243 * This function initiates all of the input parameters in the struct
jcobb 0:fba19b344b6d 244 * posdata passed to S_solpos(). Initialization is either to nominal
jcobb 0:fba19b344b6d 245 * values or to out of range values, which forces the calling program to
jcobb 0:fba19b344b6d 246 * specify parameters.
jcobb 0:fba19b344b6d 247 *
jcobb 0:fba19b344b6d 248 * NOTE: This function is optional if you initialize ALL input parameters
jcobb 0:fba19b344b6d 249 * in your calling code. Note that the required parameters of date
jcobb 0:fba19b344b6d 250 * and location are deliberately initialized out of bounds to force
jcobb 0:fba19b344b6d 251 * the user to enter real-world values.
jcobb 0:fba19b344b6d 252 *
jcobb 0:fba19b344b6d 253 * Requires: Pointer to a posdata structure, members of which are
jcobb 0:fba19b344b6d 254 * initialized.
jcobb 0:fba19b344b6d 255 *
jcobb 0:fba19b344b6d 256 * Returns: Void
jcobb 0:fba19b344b6d 257 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 258 void S_init(struct posdata *pdat)
jcobb 0:fba19b344b6d 259 {
jcobb 0:fba19b344b6d 260 pdat->day = -99; /* Day of month (May 27 = 27, etc.) */
jcobb 0:fba19b344b6d 261 pdat->daynum = -999; /* Day number (day of year; Feb 1 = 32 ) */
jcobb 0:fba19b344b6d 262 pdat->hour = -99; /* Hour of day, 0 - 23 */
jcobb 0:fba19b344b6d 263 pdat->minute = -99; /* Minute of hour, 0 - 59 */
jcobb 0:fba19b344b6d 264 pdat->month = -99; /* Month number (Jan = 1, Feb = 2, etc.) */
jcobb 0:fba19b344b6d 265 pdat->second = -99; /* Second of minute, 0 - 59 */
jcobb 0:fba19b344b6d 266 pdat->year = -99; /* 4-digit year */
jcobb 0:fba19b344b6d 267 pdat->interval = 0; /* instantaneous measurement interval */
jcobb 0:fba19b344b6d 268 pdat->aspect = 180.0; /* Azimuth of panel surface (direction it
jcobb 0:fba19b344b6d 269 faces) N=0, E=90, S=180, W=270 */
jcobb 0:fba19b344b6d 270 pdat->latitude = -99.0; /* Latitude, degrees north (south negative) */
jcobb 0:fba19b344b6d 271 pdat->longitude = -999.0; /* Longitude, degrees east (west negative) */
jcobb 0:fba19b344b6d 272 pdat->press = 1013.0; /* Surface pressure, millibars */
jcobb 0:fba19b344b6d 273 pdat->solcon = 1367.0; /* Solar constant, 1367 W/sq m */
jcobb 0:fba19b344b6d 274 pdat->temp = 15.0; /* Ambient dry-bulb temperature, degrees C */
jcobb 0:fba19b344b6d 275 pdat->tilt = 0.0; /* Degrees tilt from horizontal of panel */
jcobb 0:fba19b344b6d 276 pdat->timezone = -99.0; /* Time zone, east (west negative). */
jcobb 0:fba19b344b6d 277 pdat->sbwid = 7.6; /* Eppley shadow band width */
jcobb 0:fba19b344b6d 278 pdat->sbrad = 31.7; /* Eppley shadow band radius */
jcobb 0:fba19b344b6d 279 pdat->sbsky = 0.04; /* Drummond factor for partly cloudy skies */
jcobb 0:fba19b344b6d 280 pdat->function = S_ALL; /* compute all parameters */
jcobb 0:fba19b344b6d 281 }
jcobb 0:fba19b344b6d 282
jcobb 0:fba19b344b6d 283
jcobb 0:fba19b344b6d 284 /*============================================================================
jcobb 0:fba19b344b6d 285 * Local long int function validate
jcobb 0:fba19b344b6d 286 *
jcobb 0:fba19b344b6d 287 * Validates the input parameters
jcobb 0:fba19b344b6d 288 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 289 static long int validate ( struct posdata *pdat)
jcobb 0:fba19b344b6d 290 {
jcobb 0:fba19b344b6d 291
jcobb 0:fba19b344b6d 292 long int retval = 0; /* start with no errors */
jcobb 0:fba19b344b6d 293
jcobb 0:fba19b344b6d 294 /* No absurd dates, please. */
jcobb 0:fba19b344b6d 295 if ( pdat->function & L_GEOM )
jcobb 0:fba19b344b6d 296 {
jcobb 0:fba19b344b6d 297 if ( (pdat->year < 1950) || (pdat->year > 2050) ) /* limits of algoritm */
jcobb 0:fba19b344b6d 298 retval |= (1L << S_YEAR_ERROR);
jcobb 0:fba19b344b6d 299 if ( !(pdat->function & S_DOY) && ((pdat->month < 1) || (pdat->month > 12)))
jcobb 0:fba19b344b6d 300 retval |= (1L << S_MONTH_ERROR);
jcobb 0:fba19b344b6d 301 if ( !(pdat->function & S_DOY) && ((pdat->day < 1) || (pdat->day > 31)) )
jcobb 0:fba19b344b6d 302 retval |= (1L << S_DAY_ERROR);
jcobb 0:fba19b344b6d 303 if ( (pdat->function & S_DOY) && ((pdat->daynum < 1) || (pdat->daynum > 366)) )
jcobb 0:fba19b344b6d 304 retval |= (1L << S_DOY_ERROR);
jcobb 0:fba19b344b6d 305
jcobb 0:fba19b344b6d 306 /* No absurd times, please. */
jcobb 0:fba19b344b6d 307 if ( (pdat->hour < 0) || (pdat->hour > 24) )
jcobb 0:fba19b344b6d 308 retval |= (1L << S_HOUR_ERROR);
jcobb 0:fba19b344b6d 309 if ( (pdat->minute < 0) || (pdat->minute > 59) )
jcobb 0:fba19b344b6d 310 retval |= (1L << S_MINUTE_ERROR);
jcobb 0:fba19b344b6d 311 if ( (pdat->second < 0) || (pdat->second > 59) )
jcobb 0:fba19b344b6d 312 retval |= (1L << S_SECOND_ERROR);
jcobb 0:fba19b344b6d 313 if ( (pdat->hour == 24) && (pdat->minute > 0) ) /* no more than 24 hrs */
jcobb 0:fba19b344b6d 314 retval |= ( (1L << S_HOUR_ERROR) | (1L << S_MINUTE_ERROR) );
jcobb 0:fba19b344b6d 315 if ( (pdat->hour == 24) && (pdat->second > 0) ) /* no more than 24 hrs */
jcobb 0:fba19b344b6d 316 retval |= ( (1L << S_HOUR_ERROR) | (1L << S_SECOND_ERROR) );
jcobb 0:fba19b344b6d 317 if ( fabs (pdat->timezone) > 12.0 )
jcobb 0:fba19b344b6d 318 retval |= (1L << S_TZONE_ERROR);
jcobb 0:fba19b344b6d 319 if ( (pdat->interval < 0) || (pdat->interval > 28800) )
jcobb 0:fba19b344b6d 320 retval |= (1L << S_INTRVL_ERROR);
jcobb 0:fba19b344b6d 321
jcobb 0:fba19b344b6d 322 /* No absurd locations, please. */
jcobb 0:fba19b344b6d 323 if ( fabs (pdat->longitude) > 180.0 )
jcobb 0:fba19b344b6d 324 retval |= (1L << S_LON_ERROR);
jcobb 0:fba19b344b6d 325 if ( fabs (pdat->latitude) > 90.0 )
jcobb 0:fba19b344b6d 326 retval |= (1L << S_LAT_ERROR);
jcobb 0:fba19b344b6d 327 }
jcobb 0:fba19b344b6d 328
jcobb 0:fba19b344b6d 329 /* No silly temperatures or pressures, please. */
jcobb 0:fba19b344b6d 330 if ( (pdat->function & L_REFRAC) && (fabs (pdat->temp) > 100.0) )
jcobb 0:fba19b344b6d 331 retval |= (1L << S_TEMP_ERROR);
jcobb 0:fba19b344b6d 332 if ( (pdat->function & L_REFRAC) &&
jcobb 0:fba19b344b6d 333 (pdat->press < 0.0) || (pdat->press > 2000.0) )
jcobb 0:fba19b344b6d 334 retval |= (1L << S_PRESS_ERROR);
jcobb 0:fba19b344b6d 335
jcobb 0:fba19b344b6d 336 /* No out of bounds tilts, please */
jcobb 0:fba19b344b6d 337 if ( (pdat->function & L_TILT) && (fabs (pdat->tilt) > 180.0) )
jcobb 0:fba19b344b6d 338 retval |= (1L << S_TILT_ERROR);
jcobb 0:fba19b344b6d 339 if ( (pdat->function & L_TILT) && (fabs (pdat->aspect) > 360.0) )
jcobb 0:fba19b344b6d 340 retval |= (1L << S_ASPECT_ERROR);
jcobb 0:fba19b344b6d 341
jcobb 0:fba19b344b6d 342 /* No oddball shadowbands, please */
jcobb 0:fba19b344b6d 343 if ( (pdat->function & L_SBCF) &&
jcobb 0:fba19b344b6d 344 (pdat->sbwid < 1.0) || (pdat->sbwid > 100.0) )
jcobb 0:fba19b344b6d 345 retval |= (1L << S_SBWID_ERROR);
jcobb 0:fba19b344b6d 346 if ( (pdat->function & L_SBCF) &&
jcobb 0:fba19b344b6d 347 (pdat->sbrad < 1.0) || (pdat->sbrad > 100.0) )
jcobb 0:fba19b344b6d 348 retval |= (1L << S_SBRAD_ERROR);
jcobb 0:fba19b344b6d 349 if ( (pdat->function & L_SBCF) && ( fabs (pdat->sbsky) > 1.0) )
jcobb 0:fba19b344b6d 350 retval |= (1L << S_SBSKY_ERROR);
jcobb 0:fba19b344b6d 351
jcobb 0:fba19b344b6d 352 return retval;
jcobb 0:fba19b344b6d 353 }
jcobb 0:fba19b344b6d 354
jcobb 0:fba19b344b6d 355
jcobb 0:fba19b344b6d 356 /*============================================================================
jcobb 0:fba19b344b6d 357 * Local Void function dom2doy
jcobb 0:fba19b344b6d 358 *
jcobb 0:fba19b344b6d 359 * Converts day-of-month to day-of-year
jcobb 0:fba19b344b6d 360 *
jcobb 0:fba19b344b6d 361 * Requires (from struct posdata parameter):
jcobb 0:fba19b344b6d 362 * year
jcobb 0:fba19b344b6d 363 * month
jcobb 0:fba19b344b6d 364 * day
jcobb 0:fba19b344b6d 365 *
jcobb 0:fba19b344b6d 366 * Returns (via the struct posdata parameter):
jcobb 0:fba19b344b6d 367 * year
jcobb 0:fba19b344b6d 368 * daynum
jcobb 0:fba19b344b6d 369 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 370 static void dom2doy( struct posdata *pdat )
jcobb 0:fba19b344b6d 371 {
jcobb 0:fba19b344b6d 372 pdat->daynum = pdat->day + month_days[0][pdat->month];
jcobb 0:fba19b344b6d 373
jcobb 0:fba19b344b6d 374 /* (adjust for leap year) */
jcobb 0:fba19b344b6d 375 if ( ((pdat->year % 4) == 0) &&
jcobb 0:fba19b344b6d 376 ( ((pdat->year % 100) != 0) || ((pdat->year % 400) == 0) ) &&
jcobb 0:fba19b344b6d 377 (pdat->month > 2) )
jcobb 0:fba19b344b6d 378 pdat->daynum += 1;
jcobb 0:fba19b344b6d 379 }
jcobb 0:fba19b344b6d 380
jcobb 0:fba19b344b6d 381
jcobb 0:fba19b344b6d 382 /*============================================================================
jcobb 0:fba19b344b6d 383 * Local void function doy2dom
jcobb 0:fba19b344b6d 384 *
jcobb 0:fba19b344b6d 385 * This function computes the month/day from the day number.
jcobb 0:fba19b344b6d 386 *
jcobb 0:fba19b344b6d 387 * Requires (from struct posdata parameter):
jcobb 0:fba19b344b6d 388 * Year and day number:
jcobb 0:fba19b344b6d 389 * year
jcobb 0:fba19b344b6d 390 * daynum
jcobb 0:fba19b344b6d 391 *
jcobb 0:fba19b344b6d 392 * Returns (via the struct posdata parameter):
jcobb 0:fba19b344b6d 393 * year
jcobb 0:fba19b344b6d 394 * month
jcobb 0:fba19b344b6d 395 * day
jcobb 0:fba19b344b6d 396 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 397 static void doy2dom(struct posdata *pdat)
jcobb 0:fba19b344b6d 398 {
jcobb 0:fba19b344b6d 399 int imon; /* Month (month_days) array counter */
jcobb 0:fba19b344b6d 400 int leap; /* leap year switch */
jcobb 0:fba19b344b6d 401
jcobb 0:fba19b344b6d 402 /* Set the leap year switch */
jcobb 0:fba19b344b6d 403 if ( ((pdat->year % 4) == 0) &&
jcobb 0:fba19b344b6d 404 ( ((pdat->year % 100) != 0) || ((pdat->year % 400) == 0) ) )
jcobb 0:fba19b344b6d 405 leap = 1;
jcobb 0:fba19b344b6d 406 else
jcobb 0:fba19b344b6d 407 leap = 0;
jcobb 0:fba19b344b6d 408
jcobb 0:fba19b344b6d 409 /* Find the month */
jcobb 0:fba19b344b6d 410 imon = 12;
jcobb 0:fba19b344b6d 411 while ( pdat->daynum <= month_days [leap][imon] )
jcobb 0:fba19b344b6d 412 --imon;
jcobb 0:fba19b344b6d 413
jcobb 0:fba19b344b6d 414 /* Set the month and day of month */
jcobb 0:fba19b344b6d 415 pdat->month = imon;
jcobb 0:fba19b344b6d 416 pdat->day = pdat->daynum - month_days[leap][imon];
jcobb 0:fba19b344b6d 417 }
jcobb 0:fba19b344b6d 418
jcobb 0:fba19b344b6d 419
jcobb 0:fba19b344b6d 420 /*============================================================================
jcobb 0:fba19b344b6d 421 * Local Void function geometry
jcobb 0:fba19b344b6d 422 *
jcobb 0:fba19b344b6d 423 * Does the underlying geometry for a given time and location
jcobb 0:fba19b344b6d 424 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 425 static void geometry ( struct posdata *pdat )
jcobb 0:fba19b344b6d 426 {
jcobb 0:fba19b344b6d 427 float bottom; /* denominator (bottom) of the fraction */
jcobb 0:fba19b344b6d 428 float c2; /* cosine of d2 */
jcobb 0:fba19b344b6d 429 float cd; /* cosine of the day angle or delination */
jcobb 0:fba19b344b6d 430 float d2; /* pdat->dayang times two */
jcobb 0:fba19b344b6d 431 float delta; /* difference between current year and 1949 */
jcobb 0:fba19b344b6d 432 float s2; /* sine of d2 */
jcobb 0:fba19b344b6d 433 float sd; /* sine of the day angle */
jcobb 0:fba19b344b6d 434 float top; /* numerator (top) of the fraction */
jcobb 0:fba19b344b6d 435 int leap; /* leap year counter */
jcobb 0:fba19b344b6d 436
jcobb 0:fba19b344b6d 437 /* Day angle */
jcobb 0:fba19b344b6d 438 /* Iqbal, M. 1983. An Introduction to Solar Radiation.
jcobb 0:fba19b344b6d 439 Academic Press, NY., page 3 */
jcobb 0:fba19b344b6d 440 pdat->dayang = 360.0 * ( pdat->daynum - 1 ) / 365.0;
jcobb 0:fba19b344b6d 441
jcobb 0:fba19b344b6d 442 /* Earth radius vector * solar constant = solar energy */
jcobb 0:fba19b344b6d 443 /* Spencer, J. W. 1971. Fourier series representation of the
jcobb 0:fba19b344b6d 444 position of the sun. Search 2 (5), page 172 */
jcobb 0:fba19b344b6d 445 sd = sin (raddeg * pdat->dayang);
jcobb 0:fba19b344b6d 446 cd = cos (raddeg * pdat->dayang);
jcobb 0:fba19b344b6d 447 d2 = 2.0 * pdat->dayang;
jcobb 0:fba19b344b6d 448 c2 = cos (raddeg * d2);
jcobb 0:fba19b344b6d 449 s2 = sin (raddeg * d2);
jcobb 0:fba19b344b6d 450
jcobb 0:fba19b344b6d 451 pdat->erv = 1.000110 + 0.034221 * cd + 0.001280 * sd;
jcobb 0:fba19b344b6d 452 pdat->erv += 0.000719 * c2 + 0.000077 * s2;
jcobb 0:fba19b344b6d 453
jcobb 0:fba19b344b6d 454 /* Universal Coordinated (Greenwich standard) time */
jcobb 0:fba19b344b6d 455 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 456 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 457 pp. 227-235. */
jcobb 0:fba19b344b6d 458 pdat->utime =
jcobb 0:fba19b344b6d 459 pdat->hour * 3600.0 +
jcobb 0:fba19b344b6d 460 pdat->minute * 60.0 +
jcobb 0:fba19b344b6d 461 pdat->second -
jcobb 0:fba19b344b6d 462 (float)pdat->interval / 2.0;
jcobb 0:fba19b344b6d 463 pdat->utime = pdat->utime / 3600.0 - pdat->timezone;
jcobb 0:fba19b344b6d 464
jcobb 0:fba19b344b6d 465 /* Julian Day minus 2,400,000 days (to eliminate roundoff errors) */
jcobb 0:fba19b344b6d 466 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 467 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 468 pp. 227-235. */
jcobb 0:fba19b344b6d 469
jcobb 0:fba19b344b6d 470 /* No adjustment for century non-leap years since this function is
jcobb 0:fba19b344b6d 471 bounded by 1950 - 2050 */
jcobb 0:fba19b344b6d 472 delta = pdat->year - 1949;
jcobb 0:fba19b344b6d 473 leap = (int) ( delta / 4.0 );
jcobb 0:fba19b344b6d 474 pdat->julday =
jcobb 0:fba19b344b6d 475 32916.5 + delta * 365.0 + leap + pdat->daynum + pdat->utime / 24.0;
jcobb 0:fba19b344b6d 476
jcobb 0:fba19b344b6d 477 /* Time used in the calculation of ecliptic coordinates */
jcobb 0:fba19b344b6d 478 /* Noon 1 JAN 2000 = 2,400,000 + 51,545 days Julian Date */
jcobb 0:fba19b344b6d 479 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 480 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 481 pp. 227-235. */
jcobb 0:fba19b344b6d 482 pdat->ectime = pdat->julday - 51545.0;
jcobb 0:fba19b344b6d 483
jcobb 0:fba19b344b6d 484 /* Mean longitude */
jcobb 0:fba19b344b6d 485 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 486 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 487 pp. 227-235. */
jcobb 0:fba19b344b6d 488 pdat->mnlong = 280.460 + 0.9856474 * pdat->ectime;
jcobb 0:fba19b344b6d 489
jcobb 0:fba19b344b6d 490 /* (dump the multiples of 360, so the answer is between 0 and 360) */
jcobb 0:fba19b344b6d 491 pdat->mnlong -= 360.0 * (int) ( pdat->mnlong / 360.0 );
jcobb 0:fba19b344b6d 492 if ( pdat->mnlong < 0.0 )
jcobb 0:fba19b344b6d 493 pdat->mnlong += 360.0;
jcobb 0:fba19b344b6d 494
jcobb 0:fba19b344b6d 495 /* Mean anomaly */
jcobb 0:fba19b344b6d 496 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 497 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 498 pp. 227-235. */
jcobb 0:fba19b344b6d 499 pdat->mnanom = 357.528 + 0.9856003 * pdat->ectime;
jcobb 0:fba19b344b6d 500
jcobb 0:fba19b344b6d 501 /* (dump the multiples of 360, so the answer is between 0 and 360) */
jcobb 0:fba19b344b6d 502 pdat->mnanom -= 360.0 * (int) ( pdat->mnanom / 360.0 );
jcobb 0:fba19b344b6d 503 if ( pdat->mnanom < 0.0 )
jcobb 0:fba19b344b6d 504 pdat->mnanom += 360.0;
jcobb 0:fba19b344b6d 505
jcobb 0:fba19b344b6d 506 /* Ecliptic longitude */
jcobb 0:fba19b344b6d 507 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 508 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 509 pp. 227-235. */
jcobb 0:fba19b344b6d 510 pdat->eclong = pdat->mnlong + 1.915 * sin ( pdat->mnanom * raddeg ) +
jcobb 0:fba19b344b6d 511 0.020 * sin ( 2.0 * pdat->mnanom * raddeg );
jcobb 0:fba19b344b6d 512
jcobb 0:fba19b344b6d 513 /* (dump the multiples of 360, so the answer is between 0 and 360) */
jcobb 0:fba19b344b6d 514 pdat->eclong -= 360.0 * (int) ( pdat->eclong / 360.0 );
jcobb 0:fba19b344b6d 515 if ( pdat->eclong < 0.0 )
jcobb 0:fba19b344b6d 516 pdat->eclong += 360.0;
jcobb 0:fba19b344b6d 517
jcobb 0:fba19b344b6d 518 /* Obliquity of the ecliptic */
jcobb 0:fba19b344b6d 519 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 520 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 521 pp. 227-235. */
jcobb 0:fba19b344b6d 522
jcobb 0:fba19b344b6d 523 /* 02 Feb 2001 SMW corrected sign in the following line */
jcobb 0:fba19b344b6d 524 /* pdat->ecobli = 23.439 + 4.0e-07 * pdat->ectime; */
jcobb 0:fba19b344b6d 525 pdat->ecobli = 23.439 - 4.0e-07 * pdat->ectime;
jcobb 0:fba19b344b6d 526
jcobb 0:fba19b344b6d 527 /* Declination */
jcobb 0:fba19b344b6d 528 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 529 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 530 pp. 227-235. */
jcobb 0:fba19b344b6d 531 pdat->declin = degrad * asin ( sin (pdat->ecobli * raddeg) *
jcobb 0:fba19b344b6d 532 sin (pdat->eclong * raddeg) );
jcobb 0:fba19b344b6d 533
jcobb 0:fba19b344b6d 534 /* Right ascension */
jcobb 0:fba19b344b6d 535 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 536 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 537 pp. 227-235. */
jcobb 0:fba19b344b6d 538 top = cos ( raddeg * pdat->ecobli ) * sin ( raddeg * pdat->eclong );
jcobb 0:fba19b344b6d 539 bottom = cos ( raddeg * pdat->eclong );
jcobb 0:fba19b344b6d 540
jcobb 0:fba19b344b6d 541 pdat->rascen = degrad * atan2 ( top, bottom );
jcobb 0:fba19b344b6d 542
jcobb 0:fba19b344b6d 543 /* (make it a positive angle) */
jcobb 0:fba19b344b6d 544 if ( pdat->rascen < 0.0 )
jcobb 0:fba19b344b6d 545 pdat->rascen += 360.0;
jcobb 0:fba19b344b6d 546
jcobb 0:fba19b344b6d 547 /* Greenwich mean sidereal time */
jcobb 0:fba19b344b6d 548 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 549 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 550 pp. 227-235. */
jcobb 0:fba19b344b6d 551 pdat->gmst = 6.697375 + 0.0657098242 * pdat->ectime + pdat->utime;
jcobb 0:fba19b344b6d 552
jcobb 0:fba19b344b6d 553 /* (dump the multiples of 24, so the answer is between 0 and 24) */
jcobb 0:fba19b344b6d 554 pdat->gmst -= 24.0 * (int) ( pdat->gmst / 24.0 );
jcobb 0:fba19b344b6d 555 if ( pdat->gmst < 0.0 )
jcobb 0:fba19b344b6d 556 pdat->gmst += 24.0;
jcobb 0:fba19b344b6d 557
jcobb 0:fba19b344b6d 558 /* Local mean sidereal time */
jcobb 0:fba19b344b6d 559 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 560 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 561 pp. 227-235. */
jcobb 0:fba19b344b6d 562 pdat->lmst = pdat->gmst * 15.0 + pdat->longitude;
jcobb 0:fba19b344b6d 563
jcobb 0:fba19b344b6d 564 /* (dump the multiples of 360, so the answer is between 0 and 360) */
jcobb 0:fba19b344b6d 565 pdat->lmst -= 360.0 * (int) ( pdat->lmst / 360.0 );
jcobb 0:fba19b344b6d 566 if ( pdat->lmst < 0.)
jcobb 0:fba19b344b6d 567 pdat->lmst += 360.0;
jcobb 0:fba19b344b6d 568
jcobb 0:fba19b344b6d 569 /* Hour angle */
jcobb 0:fba19b344b6d 570 /* Michalsky, J. 1988. The Astronomical Almanac's algorithm for
jcobb 0:fba19b344b6d 571 approximate solar position (1950-2050). Solar Energy 40 (3),
jcobb 0:fba19b344b6d 572 pp. 227-235. */
jcobb 0:fba19b344b6d 573 pdat->hrang = pdat->lmst - pdat->rascen;
jcobb 0:fba19b344b6d 574
jcobb 0:fba19b344b6d 575 /* (force it between -180 and 180 degrees) */
jcobb 0:fba19b344b6d 576 if ( pdat->hrang < -180.0 )
jcobb 0:fba19b344b6d 577 pdat->hrang += 360.0;
jcobb 0:fba19b344b6d 578 else if ( pdat->hrang > 180.0 )
jcobb 0:fba19b344b6d 579 pdat->hrang -= 360.0;
jcobb 0:fba19b344b6d 580 }
jcobb 0:fba19b344b6d 581
jcobb 0:fba19b344b6d 582
jcobb 0:fba19b344b6d 583 /*============================================================================
jcobb 0:fba19b344b6d 584 * Local Void function zen_no_ref
jcobb 0:fba19b344b6d 585 *
jcobb 0:fba19b344b6d 586 * ETR solar zenith angle
jcobb 0:fba19b344b6d 587 * Iqbal, M. 1983. An Introduction to Solar Radiation.
jcobb 0:fba19b344b6d 588 * Academic Press, NY., page 15
jcobb 0:fba19b344b6d 589 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 590 static void zen_no_ref ( struct posdata *pdat, struct trigdata *tdat )
jcobb 0:fba19b344b6d 591 {
jcobb 0:fba19b344b6d 592 float cz; /* cosine of the solar zenith angle */
jcobb 0:fba19b344b6d 593
jcobb 0:fba19b344b6d 594 localtrig( pdat, tdat );
jcobb 0:fba19b344b6d 595 cz = tdat->sd * tdat->sl + tdat->cd * tdat->cl * tdat->ch;
jcobb 0:fba19b344b6d 596
jcobb 0:fba19b344b6d 597 /* (watch out for the roundoff errors) */
jcobb 0:fba19b344b6d 598 if ( fabs (cz) > 1.0 ) {
jcobb 0:fba19b344b6d 599 if ( cz >= 0.0 )
jcobb 0:fba19b344b6d 600 cz = 1.0;
jcobb 0:fba19b344b6d 601 else
jcobb 0:fba19b344b6d 602 cz = -1.0;
jcobb 0:fba19b344b6d 603 }
jcobb 0:fba19b344b6d 604
jcobb 0:fba19b344b6d 605 pdat->zenetr = acos ( cz ) * degrad;
jcobb 0:fba19b344b6d 606
jcobb 0:fba19b344b6d 607 /* (limit the degrees below the horizon to 9 [+90 -> 99]) */
jcobb 0:fba19b344b6d 608 if ( pdat->zenetr > 99.0 )
jcobb 0:fba19b344b6d 609 pdat->zenetr = 99.0;
jcobb 0:fba19b344b6d 610
jcobb 0:fba19b344b6d 611 pdat->elevetr = 90.0 - pdat->zenetr;
jcobb 0:fba19b344b6d 612 }
jcobb 0:fba19b344b6d 613
jcobb 0:fba19b344b6d 614
jcobb 0:fba19b344b6d 615 /*============================================================================
jcobb 0:fba19b344b6d 616 * Local Void function ssha
jcobb 0:fba19b344b6d 617 *
jcobb 0:fba19b344b6d 618 * Sunset hour angle, degrees
jcobb 0:fba19b344b6d 619 * Iqbal, M. 1983. An Introduction to Solar Radiation.
jcobb 0:fba19b344b6d 620 * Academic Press, NY., page 16
jcobb 0:fba19b344b6d 621 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 622 static void ssha( struct posdata *pdat, struct trigdata *tdat )
jcobb 0:fba19b344b6d 623 {
jcobb 0:fba19b344b6d 624 float cssha; /* cosine of the sunset hour angle */
jcobb 0:fba19b344b6d 625 float cdcl; /* ( cd * cl ) */
jcobb 0:fba19b344b6d 626
jcobb 0:fba19b344b6d 627 localtrig( pdat, tdat );
jcobb 0:fba19b344b6d 628 cdcl = tdat->cd * tdat->cl;
jcobb 0:fba19b344b6d 629
jcobb 0:fba19b344b6d 630 if ( fabs ( cdcl ) >= 0.001 ) {
jcobb 0:fba19b344b6d 631 cssha = -tdat->sl * tdat->sd / cdcl;
jcobb 0:fba19b344b6d 632
jcobb 0:fba19b344b6d 633 /* This keeps the cosine from blowing on roundoff */
jcobb 0:fba19b344b6d 634 if ( cssha < -1.0 )
jcobb 0:fba19b344b6d 635 pdat->ssha = 180.0;
jcobb 0:fba19b344b6d 636 else if ( cssha > 1.0 )
jcobb 0:fba19b344b6d 637 pdat->ssha = 0.0;
jcobb 0:fba19b344b6d 638 else
jcobb 0:fba19b344b6d 639 pdat->ssha = degrad * acos ( cssha );
jcobb 0:fba19b344b6d 640 }
jcobb 0:fba19b344b6d 641 else if ( ((pdat->declin >= 0.0) && (pdat->latitude > 0.0 )) ||
jcobb 0:fba19b344b6d 642 ((pdat->declin < 0.0) && (pdat->latitude < 0.0 )) )
jcobb 0:fba19b344b6d 643 pdat->ssha = 180.0;
jcobb 0:fba19b344b6d 644 else
jcobb 0:fba19b344b6d 645 pdat->ssha = 0.0;
jcobb 0:fba19b344b6d 646 }
jcobb 0:fba19b344b6d 647
jcobb 0:fba19b344b6d 648
jcobb 0:fba19b344b6d 649 /*============================================================================
jcobb 0:fba19b344b6d 650 * Local Void function sbcf
jcobb 0:fba19b344b6d 651 *
jcobb 0:fba19b344b6d 652 * Shadowband correction factor
jcobb 0:fba19b344b6d 653 * Drummond, A. J. 1956. A contribution to absolute pyrheliometry.
jcobb 0:fba19b344b6d 654 * Q. J. R. Meteorol. Soc. 82, pp. 481-493
jcobb 0:fba19b344b6d 655 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 656 static void sbcf( struct posdata *pdat, struct trigdata *tdat )
jcobb 0:fba19b344b6d 657 {
jcobb 0:fba19b344b6d 658 float p, t1, t2; /* used to compute sbcf */
jcobb 0:fba19b344b6d 659
jcobb 0:fba19b344b6d 660 localtrig( pdat, tdat );
jcobb 0:fba19b344b6d 661 p = 0.6366198 * pdat->sbwid / pdat->sbrad * pow (tdat->cd,3);
jcobb 0:fba19b344b6d 662 t1 = tdat->sl * tdat->sd * pdat->ssha * raddeg;
jcobb 0:fba19b344b6d 663 t2 = tdat->cl * tdat->cd * sin ( pdat->ssha * raddeg );
jcobb 0:fba19b344b6d 664 pdat->sbcf = pdat->sbsky + 1.0 / ( 1.0 - p * ( t1 + t2 ) );
jcobb 0:fba19b344b6d 665
jcobb 0:fba19b344b6d 666 }
jcobb 0:fba19b344b6d 667
jcobb 0:fba19b344b6d 668
jcobb 0:fba19b344b6d 669 /*============================================================================
jcobb 0:fba19b344b6d 670 * Local Void function tst
jcobb 0:fba19b344b6d 671 *
jcobb 0:fba19b344b6d 672 * TST -> True Solar Time = local standard time + TSTfix, time
jcobb 0:fba19b344b6d 673 * in minutes from midnight.
jcobb 0:fba19b344b6d 674 * Iqbal, M. 1983. An Introduction to Solar Radiation.
jcobb 0:fba19b344b6d 675 * Academic Press, NY., page 13
jcobb 0:fba19b344b6d 676 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 677 static void tst( struct posdata *pdat )
jcobb 0:fba19b344b6d 678 {
jcobb 0:fba19b344b6d 679 pdat->tst = ( 180.0 + pdat->hrang ) * 4.0;
jcobb 0:fba19b344b6d 680 pdat->tstfix =
jcobb 0:fba19b344b6d 681 pdat->tst -
jcobb 0:fba19b344b6d 682 (float)pdat->hour * 60.0 -
jcobb 0:fba19b344b6d 683 pdat->minute -
jcobb 0:fba19b344b6d 684 (float)pdat->second / 60.0 +
jcobb 0:fba19b344b6d 685 (float)pdat->interval / 120.0; /* add back half of the interval */
jcobb 0:fba19b344b6d 686
jcobb 0:fba19b344b6d 687 /* bound tstfix to this day */
jcobb 0:fba19b344b6d 688 while ( pdat->tstfix > 720.0 )
jcobb 0:fba19b344b6d 689 pdat->tstfix -= 1440.0;
jcobb 0:fba19b344b6d 690 while ( pdat->tstfix < -720.0 )
jcobb 0:fba19b344b6d 691 pdat->tstfix += 1440.0;
jcobb 0:fba19b344b6d 692
jcobb 0:fba19b344b6d 693 pdat->eqntim =
jcobb 0:fba19b344b6d 694 pdat->tstfix + 60.0 * pdat->timezone - 4.0 * pdat->longitude;
jcobb 0:fba19b344b6d 695
jcobb 0:fba19b344b6d 696 }
jcobb 0:fba19b344b6d 697
jcobb 0:fba19b344b6d 698
jcobb 0:fba19b344b6d 699 /*============================================================================
jcobb 0:fba19b344b6d 700 * Local Void function srss
jcobb 0:fba19b344b6d 701 *
jcobb 0:fba19b344b6d 702 * Sunrise and sunset times (minutes from midnight)
jcobb 0:fba19b344b6d 703 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 704 static void srss( struct posdata *pdat )
jcobb 0:fba19b344b6d 705 {
jcobb 0:fba19b344b6d 706 if ( pdat->ssha <= 1.0 ) {
jcobb 0:fba19b344b6d 707 pdat->sretr = 2999.0;
jcobb 0:fba19b344b6d 708 pdat->ssetr = -2999.0;
jcobb 0:fba19b344b6d 709 }
jcobb 0:fba19b344b6d 710 else if ( pdat->ssha >= 179.0 ) {
jcobb 0:fba19b344b6d 711 pdat->sretr = -2999.0;
jcobb 0:fba19b344b6d 712 pdat->ssetr = 2999.0;
jcobb 0:fba19b344b6d 713 }
jcobb 0:fba19b344b6d 714 else {
jcobb 0:fba19b344b6d 715 pdat->sretr = 720.0 - 4.0 * pdat->ssha - pdat->tstfix;
jcobb 0:fba19b344b6d 716 pdat->ssetr = 720.0 + 4.0 * pdat->ssha - pdat->tstfix;
jcobb 0:fba19b344b6d 717 }
jcobb 0:fba19b344b6d 718 }
jcobb 0:fba19b344b6d 719
jcobb 0:fba19b344b6d 720
jcobb 0:fba19b344b6d 721 /*============================================================================
jcobb 0:fba19b344b6d 722 * Local Void function sazm
jcobb 0:fba19b344b6d 723 *
jcobb 0:fba19b344b6d 724 * Solar azimuth angle
jcobb 0:fba19b344b6d 725 * Iqbal, M. 1983. An Introduction to Solar Radiation.
jcobb 0:fba19b344b6d 726 * Academic Press, NY., page 15
jcobb 0:fba19b344b6d 727 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 728 static void sazm( struct posdata *pdat, struct trigdata *tdat )
jcobb 0:fba19b344b6d 729 {
jcobb 0:fba19b344b6d 730 float ca; /* cosine of the solar azimuth angle */
jcobb 0:fba19b344b6d 731 float ce; /* cosine of the solar elevation */
jcobb 0:fba19b344b6d 732 float cecl; /* ( ce * cl ) */
jcobb 0:fba19b344b6d 733 float se; /* sine of the solar elevation */
jcobb 0:fba19b344b6d 734
jcobb 0:fba19b344b6d 735 localtrig( pdat, tdat );
jcobb 0:fba19b344b6d 736 ce = cos ( raddeg * pdat->elevetr );
jcobb 0:fba19b344b6d 737 se = sin ( raddeg * pdat->elevetr );
jcobb 0:fba19b344b6d 738
jcobb 0:fba19b344b6d 739 pdat->azim = 180.0;
jcobb 0:fba19b344b6d 740 cecl = ce * tdat->cl;
jcobb 0:fba19b344b6d 741 if ( fabs ( cecl ) >= 0.001 ) {
jcobb 0:fba19b344b6d 742 ca = ( se * tdat->sl - tdat->sd ) / cecl;
jcobb 0:fba19b344b6d 743 if ( ca > 1.0 )
jcobb 0:fba19b344b6d 744 ca = 1.0;
jcobb 0:fba19b344b6d 745 else if ( ca < -1.0 )
jcobb 0:fba19b344b6d 746 ca = -1.0;
jcobb 0:fba19b344b6d 747
jcobb 0:fba19b344b6d 748 pdat->azim = 180.0 - acos ( ca ) * degrad;
jcobb 0:fba19b344b6d 749 if ( pdat->hrang > 0 )
jcobb 0:fba19b344b6d 750 pdat->azim = 360.0 - pdat->azim;
jcobb 0:fba19b344b6d 751 }
jcobb 0:fba19b344b6d 752 }
jcobb 0:fba19b344b6d 753
jcobb 0:fba19b344b6d 754
jcobb 0:fba19b344b6d 755 /*============================================================================
jcobb 0:fba19b344b6d 756 * Local Int function refrac
jcobb 0:fba19b344b6d 757 *
jcobb 0:fba19b344b6d 758 * Refraction correction, degrees
jcobb 0:fba19b344b6d 759 * Zimmerman, John C. 1981. Sun-pointing programs and their
jcobb 0:fba19b344b6d 760 * accuracy.
jcobb 0:fba19b344b6d 761 * SAND81-0761, Experimental Systems Operation Division 4721,
jcobb 0:fba19b344b6d 762 * Sandia National Laboratories, Albuquerque, NM.
jcobb 0:fba19b344b6d 763 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 764 static void refrac( struct posdata *pdat )
jcobb 0:fba19b344b6d 765 {
jcobb 0:fba19b344b6d 766 float prestemp; /* temporary pressure/temperature correction */
jcobb 0:fba19b344b6d 767 float refcor; /* temporary refraction correction */
jcobb 0:fba19b344b6d 768 float tanelev; /* tangent of the solar elevation angle */
jcobb 0:fba19b344b6d 769
jcobb 0:fba19b344b6d 770 /* If the sun is near zenith, the algorithm bombs; refraction near 0 */
jcobb 0:fba19b344b6d 771 if ( pdat->elevetr > 85.0 )
jcobb 0:fba19b344b6d 772 refcor = 0.0;
jcobb 0:fba19b344b6d 773
jcobb 0:fba19b344b6d 774 /* Otherwise, we have refraction */
jcobb 0:fba19b344b6d 775 else {
jcobb 0:fba19b344b6d 776 tanelev = tan ( raddeg * pdat->elevetr );
jcobb 0:fba19b344b6d 777 if ( pdat->elevetr >= 5.0 )
jcobb 0:fba19b344b6d 778 refcor = 58.1 / tanelev -
jcobb 0:fba19b344b6d 779 0.07 / ( pow (tanelev,3) ) +
jcobb 0:fba19b344b6d 780 0.000086 / ( pow (tanelev,5) );
jcobb 0:fba19b344b6d 781 else if ( pdat->elevetr >= -0.575 )
jcobb 0:fba19b344b6d 782 refcor = 1735.0 +
jcobb 0:fba19b344b6d 783 pdat->elevetr * ( -518.2 + pdat->elevetr * ( 103.4 +
jcobb 0:fba19b344b6d 784 pdat->elevetr * ( -12.79 + pdat->elevetr * 0.711 ) ) );
jcobb 0:fba19b344b6d 785 else
jcobb 0:fba19b344b6d 786 refcor = -20.774 / tanelev;
jcobb 0:fba19b344b6d 787
jcobb 0:fba19b344b6d 788 prestemp =
jcobb 0:fba19b344b6d 789 ( pdat->press * 283.0 ) / ( 1013.0 * ( 273.0 + pdat->temp ) );
jcobb 0:fba19b344b6d 790 refcor *= prestemp / 3600.0;
jcobb 0:fba19b344b6d 791 }
jcobb 0:fba19b344b6d 792
jcobb 0:fba19b344b6d 793 /* Refracted solar elevation angle */
jcobb 0:fba19b344b6d 794 pdat->elevref = pdat->elevetr + refcor;
jcobb 0:fba19b344b6d 795
jcobb 0:fba19b344b6d 796 /* (limit the degrees below the horizon to 9) */
jcobb 0:fba19b344b6d 797 if ( pdat->elevref < -9.0 )
jcobb 0:fba19b344b6d 798 pdat->elevref = -9.0;
jcobb 0:fba19b344b6d 799
jcobb 0:fba19b344b6d 800 /* Refracted solar zenith angle */
jcobb 0:fba19b344b6d 801 pdat->zenref = 90.0 - pdat->elevref;
jcobb 0:fba19b344b6d 802 pdat->coszen = cos( raddeg * pdat->zenref );
jcobb 0:fba19b344b6d 803 }
jcobb 0:fba19b344b6d 804
jcobb 0:fba19b344b6d 805
jcobb 0:fba19b344b6d 806 /*============================================================================
jcobb 0:fba19b344b6d 807 * Local Void function amass
jcobb 0:fba19b344b6d 808 *
jcobb 0:fba19b344b6d 809 * Airmass
jcobb 0:fba19b344b6d 810 * Kasten, F. and Young, A. 1989. Revised optical air mass
jcobb 0:fba19b344b6d 811 * tables and approximation formula. Applied Optics 28 (22),
jcobb 0:fba19b344b6d 812 * pp. 4735-4738
jcobb 0:fba19b344b6d 813 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 814 static void amass( struct posdata *pdat )
jcobb 0:fba19b344b6d 815 {
jcobb 0:fba19b344b6d 816 if ( pdat->zenref > 93.0 )
jcobb 0:fba19b344b6d 817 {
jcobb 0:fba19b344b6d 818 pdat->amass = -1.0;
jcobb 0:fba19b344b6d 819 pdat->ampress = -1.0;
jcobb 0:fba19b344b6d 820 }
jcobb 0:fba19b344b6d 821 else
jcobb 0:fba19b344b6d 822 {
jcobb 0:fba19b344b6d 823 pdat->amass =
jcobb 0:fba19b344b6d 824 1.0 / ( cos (raddeg * pdat->zenref) + 0.50572 *
jcobb 0:fba19b344b6d 825 pow ((96.07995 - pdat->zenref),-1.6364) );
jcobb 0:fba19b344b6d 826
jcobb 0:fba19b344b6d 827 pdat->ampress = pdat->amass * pdat->press / 1013.0;
jcobb 0:fba19b344b6d 828 }
jcobb 0:fba19b344b6d 829 }
jcobb 0:fba19b344b6d 830
jcobb 0:fba19b344b6d 831
jcobb 0:fba19b344b6d 832 /*============================================================================
jcobb 0:fba19b344b6d 833 * Local Void function prime
jcobb 0:fba19b344b6d 834 *
jcobb 0:fba19b344b6d 835 * Prime and Unprime
jcobb 0:fba19b344b6d 836 * Prime converts Kt to normalized Kt', etc.
jcobb 0:fba19b344b6d 837 * Unprime deconverts Kt' to Kt, etc.
jcobb 0:fba19b344b6d 838 * Perez, R., P. Ineichen, Seals, R., & Zelenka, A. 1990. Making
jcobb 0:fba19b344b6d 839 * full use of the clearness index for parameterizing hourly
jcobb 0:fba19b344b6d 840 * insolation conditions. Solar Energy 45 (2), pp. 111-114
jcobb 0:fba19b344b6d 841 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 842 static void prime( struct posdata *pdat )
jcobb 0:fba19b344b6d 843 {
jcobb 0:fba19b344b6d 844 pdat->unprime = 1.031 * exp ( -1.4 / ( 0.9 + 9.4 / pdat->amass ) ) + 0.1;
jcobb 0:fba19b344b6d 845 pdat->prime = 1.0 / pdat->unprime;
jcobb 0:fba19b344b6d 846 }
jcobb 0:fba19b344b6d 847
jcobb 0:fba19b344b6d 848
jcobb 0:fba19b344b6d 849 /*============================================================================
jcobb 0:fba19b344b6d 850 * Local Void function etr
jcobb 0:fba19b344b6d 851 *
jcobb 0:fba19b344b6d 852 * Extraterrestrial (top-of-atmosphere) solar irradiance
jcobb 0:fba19b344b6d 853 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 854 static void etr( struct posdata *pdat )
jcobb 0:fba19b344b6d 855 {
jcobb 0:fba19b344b6d 856 if ( pdat->coszen > 0.0 ) {
jcobb 0:fba19b344b6d 857 pdat->etrn = pdat->solcon * pdat->erv;
jcobb 0:fba19b344b6d 858 pdat->etr = pdat->etrn * pdat->coszen;
jcobb 0:fba19b344b6d 859 }
jcobb 0:fba19b344b6d 860 else {
jcobb 0:fba19b344b6d 861 pdat->etrn = 0.0;
jcobb 0:fba19b344b6d 862 pdat->etr = 0.0;
jcobb 0:fba19b344b6d 863 }
jcobb 0:fba19b344b6d 864 }
jcobb 0:fba19b344b6d 865
jcobb 0:fba19b344b6d 866
jcobb 0:fba19b344b6d 867 /*============================================================================
jcobb 0:fba19b344b6d 868 * Local Void function localtrig
jcobb 0:fba19b344b6d 869 *
jcobb 0:fba19b344b6d 870 * Does trig on internal variable used by several functions
jcobb 0:fba19b344b6d 871 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 872 static void localtrig( struct posdata *pdat, struct trigdata *tdat )
jcobb 0:fba19b344b6d 873 {
jcobb 0:fba19b344b6d 874 /* define masks to prevent calculation of uninitialized variables */
jcobb 0:fba19b344b6d 875 #define SD_MASK ( L_ZENETR | L_SSHA | S_SBCF | S_SOLAZM )
jcobb 0:fba19b344b6d 876 #define SL_MASK ( L_ZENETR | L_SSHA | S_SBCF | S_SOLAZM )
jcobb 0:fba19b344b6d 877 #define CL_MASK ( L_ZENETR | L_SSHA | S_SBCF | S_SOLAZM )
jcobb 0:fba19b344b6d 878 #define CD_MASK ( L_ZENETR | L_SSHA | S_SBCF )
jcobb 0:fba19b344b6d 879 #define CH_MASK ( L_ZENETR )
jcobb 0:fba19b344b6d 880
jcobb 0:fba19b344b6d 881 if ( tdat->sd < -900.0 ) /* sd was initialized -999 as flag */
jcobb 0:fba19b344b6d 882 {
jcobb 0:fba19b344b6d 883 tdat->sd = 1.0; /* reflag as having completed calculations */
jcobb 0:fba19b344b6d 884 if ( pdat->function | CD_MASK )
jcobb 0:fba19b344b6d 885 tdat->cd = cos ( raddeg * pdat->declin );
jcobb 0:fba19b344b6d 886 if ( pdat->function | CH_MASK )
jcobb 0:fba19b344b6d 887 tdat->ch = cos ( raddeg * pdat->hrang );
jcobb 0:fba19b344b6d 888 if ( pdat->function | CL_MASK )
jcobb 0:fba19b344b6d 889 tdat->cl = cos ( raddeg * pdat->latitude );
jcobb 0:fba19b344b6d 890 if ( pdat->function | SD_MASK )
jcobb 0:fba19b344b6d 891 tdat->sd = sin ( raddeg * pdat->declin );
jcobb 0:fba19b344b6d 892 if ( pdat->function | SL_MASK )
jcobb 0:fba19b344b6d 893 tdat->sl = sin ( raddeg * pdat->latitude );
jcobb 0:fba19b344b6d 894 }
jcobb 0:fba19b344b6d 895 }
jcobb 0:fba19b344b6d 896
jcobb 0:fba19b344b6d 897
jcobb 0:fba19b344b6d 898 /*============================================================================
jcobb 0:fba19b344b6d 899 * Local Void function tilt
jcobb 0:fba19b344b6d 900 *
jcobb 0:fba19b344b6d 901 * ETR on a tilted surface
jcobb 0:fba19b344b6d 902 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 903 static void tilt( struct posdata *pdat )
jcobb 0:fba19b344b6d 904 {
jcobb 0:fba19b344b6d 905 float ca; /* cosine of the solar azimuth angle */
jcobb 0:fba19b344b6d 906 float cp; /* cosine of the panel aspect */
jcobb 0:fba19b344b6d 907 float ct; /* cosine of the panel tilt */
jcobb 0:fba19b344b6d 908 float sa; /* sine of the solar azimuth angle */
jcobb 0:fba19b344b6d 909 float sp; /* sine of the panel aspect */
jcobb 0:fba19b344b6d 910 float st; /* sine of the panel tilt */
jcobb 0:fba19b344b6d 911 float sz; /* sine of the refraction corrected solar zenith angle */
jcobb 0:fba19b344b6d 912
jcobb 0:fba19b344b6d 913
jcobb 0:fba19b344b6d 914 /* Cosine of the angle between the sun and a tipped flat surface,
jcobb 0:fba19b344b6d 915 useful for calculating solar energy on tilted surfaces */
jcobb 0:fba19b344b6d 916 ca = cos ( raddeg * pdat->azim );
jcobb 0:fba19b344b6d 917 cp = cos ( raddeg * pdat->aspect );
jcobb 0:fba19b344b6d 918 ct = cos ( raddeg * pdat->tilt );
jcobb 0:fba19b344b6d 919 sa = sin ( raddeg * pdat->azim );
jcobb 0:fba19b344b6d 920 sp = sin ( raddeg * pdat->aspect );
jcobb 0:fba19b344b6d 921 st = sin ( raddeg * pdat->tilt );
jcobb 0:fba19b344b6d 922 sz = sin ( raddeg * pdat->zenref );
jcobb 0:fba19b344b6d 923 pdat->cosinc = pdat->coszen * ct + sz * st * ( ca * cp + sa * sp );
jcobb 0:fba19b344b6d 924
jcobb 0:fba19b344b6d 925 if ( pdat->cosinc > 0.0 )
jcobb 0:fba19b344b6d 926 pdat->etrtilt = pdat->etrn * pdat->cosinc;
jcobb 0:fba19b344b6d 927 else
jcobb 0:fba19b344b6d 928 pdat->etrtilt = 0.0;
jcobb 0:fba19b344b6d 929
jcobb 0:fba19b344b6d 930 }
jcobb 0:fba19b344b6d 931
jcobb 0:fba19b344b6d 932
jcobb 0:fba19b344b6d 933 /*============================================================================
jcobb 0:fba19b344b6d 934 * Void function S_decode
jcobb 0:fba19b344b6d 935 *
jcobb 0:fba19b344b6d 936 * This function decodes the error codes from S_solpos return value
jcobb 0:fba19b344b6d 937 *
jcobb 0:fba19b344b6d 938 * Requires the long integer return value from S_solpos
jcobb 0:fba19b344b6d 939 *
jcobb 0:fba19b344b6d 940 * Returns descriptive text to stderr
jcobb 0:fba19b344b6d 941 *----------------------------------------------------------------------------*/
jcobb 0:fba19b344b6d 942 void S_decode(long code, struct posdata *pdat)
jcobb 0:fba19b344b6d 943 {
jcobb 0:fba19b344b6d 944 if ( code & (1L << S_YEAR_ERROR) )
jcobb 0:fba19b344b6d 945 fprintf(stderr, "S_decode ==> Please fix the year: %d [1950-2050]\n",
jcobb 0:fba19b344b6d 946 pdat->year);
jcobb 0:fba19b344b6d 947 if ( code & (1L << S_MONTH_ERROR) )
jcobb 0:fba19b344b6d 948 fprintf(stderr, "S_decode ==> Please fix the month: %d\n",
jcobb 0:fba19b344b6d 949 pdat->month);
jcobb 0:fba19b344b6d 950 if ( code & (1L << S_DAY_ERROR) )
jcobb 0:fba19b344b6d 951 fprintf(stderr, "S_decode ==> Please fix the day-of-month: %d\n",
jcobb 0:fba19b344b6d 952 pdat->day);
jcobb 0:fba19b344b6d 953 if ( code & (1L << S_DOY_ERROR) )
jcobb 0:fba19b344b6d 954 fprintf(stderr, "S_decode ==> Please fix the day-of-year: %d\n",
jcobb 0:fba19b344b6d 955 pdat->daynum);
jcobb 0:fba19b344b6d 956 if ( code & (1L << S_HOUR_ERROR) )
jcobb 0:fba19b344b6d 957 fprintf(stderr, "S_decode ==> Please fix the hour: %d\n",
jcobb 0:fba19b344b6d 958 pdat->hour);
jcobb 0:fba19b344b6d 959 if ( code & (1L << S_MINUTE_ERROR) )
jcobb 0:fba19b344b6d 960 fprintf(stderr, "S_decode ==> Please fix the minute: %d\n",
jcobb 0:fba19b344b6d 961 pdat->minute);
jcobb 0:fba19b344b6d 962 if ( code & (1L << S_SECOND_ERROR) )
jcobb 0:fba19b344b6d 963 fprintf(stderr, "S_decode ==> Please fix the second: %d\n",
jcobb 0:fba19b344b6d 964 pdat->second);
jcobb 0:fba19b344b6d 965 if ( code & (1L << S_TZONE_ERROR) )
jcobb 0:fba19b344b6d 966 fprintf(stderr, "S_decode ==> Please fix the time zone: %f\n",
jcobb 0:fba19b344b6d 967 pdat->timezone);
jcobb 0:fba19b344b6d 968 if ( code & (1L << S_INTRVL_ERROR) )
jcobb 0:fba19b344b6d 969 fprintf(stderr, "S_decode ==> Please fix the interval: %d\n",
jcobb 0:fba19b344b6d 970 pdat->interval);
jcobb 0:fba19b344b6d 971 if ( code & (1L << S_LAT_ERROR) )
jcobb 0:fba19b344b6d 972 fprintf(stderr, "S_decode ==> Please fix the latitude: %f\n",
jcobb 0:fba19b344b6d 973 pdat->latitude);
jcobb 0:fba19b344b6d 974 if ( code & (1L << S_LON_ERROR) )
jcobb 0:fba19b344b6d 975 fprintf(stderr, "S_decode ==> Please fix the longitude: %f\n",
jcobb 0:fba19b344b6d 976 pdat->longitude);
jcobb 0:fba19b344b6d 977 if ( code & (1L << S_TEMP_ERROR) )
jcobb 0:fba19b344b6d 978 fprintf(stderr, "S_decode ==> Please fix the temperature: %f\n",
jcobb 0:fba19b344b6d 979 pdat->temp);
jcobb 0:fba19b344b6d 980 if ( code & (1L << S_PRESS_ERROR) )
jcobb 0:fba19b344b6d 981 fprintf(stderr, "S_decode ==> Please fix the pressure: %f\n",
jcobb 0:fba19b344b6d 982 pdat->press);
jcobb 0:fba19b344b6d 983 if ( code & (1L << S_TILT_ERROR) )
jcobb 0:fba19b344b6d 984 fprintf(stderr, "S_decode ==> Please fix the tilt: %f\n",
jcobb 0:fba19b344b6d 985 pdat->tilt);
jcobb 0:fba19b344b6d 986 if ( code & (1L << S_ASPECT_ERROR) )
jcobb 0:fba19b344b6d 987 fprintf(stderr, "S_decode ==> Please fix the aspect: %f\n",
jcobb 0:fba19b344b6d 988 pdat->aspect);
jcobb 0:fba19b344b6d 989 if ( code & (1L << S_SBWID_ERROR) )
jcobb 0:fba19b344b6d 990 fprintf(stderr, "S_decode ==> Please fix the shadowband width: %f\n",
jcobb 0:fba19b344b6d 991 pdat->sbwid);
jcobb 0:fba19b344b6d 992 if ( code & (1L << S_SBRAD_ERROR) )
jcobb 0:fba19b344b6d 993 fprintf(stderr, "S_decode ==> Please fix the shadowband radius: %f\n",
jcobb 0:fba19b344b6d 994 pdat->sbrad);
jcobb 0:fba19b344b6d 995 if ( code & (1L << S_SBSKY_ERROR) )
jcobb 0:fba19b344b6d 996 fprintf(stderr, "S_decode ==> Please fix the shadowband sky factor: %f\n",
jcobb 0:fba19b344b6d 997 pdat->sbsky);
jcobb 0:fba19b344b6d 998 }
jcobb 0:fba19b344b6d 999