/*============================================================================ * Local Void function ssha * * Sunset hour angle, degrees * Iqbal, M. 1983. An Introduction to Solar Radiation. * Academic Press, NY., page 16 *----------------------------------------------------------------------------*/ private static void ssha(PosData pdat, TrigData tdat) { float cssha; /* cosine of the sunset hour angle */ float cdcl; /* ( cd * cl ) */ localtrig(pdat, tdat); cdcl = tdat.cd * tdat.cl; if (fabs(cdcl) >= 0.001f) { cssha = -tdat.sl * tdat.sd / cdcl; /* This keeps the cosine from blowing on roundoff */ if (cssha < -1.0f) pdat.ssha = 180.0f; else if (cssha > 1.0f) pdat.ssha = 0.0f; else pdat.ssha = degrad * acos(cssha); } else if (((pdat.declin >= 0.0f) && (pdat.latitude > 0.0f)) || ((pdat.declin < 0.0f) && (pdat.latitude < 0.0f))) pdat.ssha = 180.0f; else pdat.ssha = 0.0f; }
/*============================================================================ * Local Void function sbcf * * Shadowband correction factor * Drummond, A. J. 1956. A contribution to absolute pyrheliometry. * Q. J. R. Meteorol. Soc. 82, pp. 481-493 *----------------------------------------------------------------------------*/ private static void sbcf(PosData pdat, TrigData tdat) { float p, t1, t2; /* used to compute sbcf */ localtrig(pdat, tdat); p = 0.6366198f * pdat.sbwid / pdat.sbrad * pow(tdat.cd, 3); t1 = tdat.sl * tdat.sd * pdat.ssha * raddeg; t2 = tdat.cl * tdat.cd * sin(pdat.ssha * raddeg); pdat.sbcf = pdat.sbsky + 1.0f / (1.0f - p * (t1 + t2)); }
/*============================================================================ * Local Void function sazm * * Solar azimuth angle * Iqbal, M. 1983. An Introduction to Solar Radiation. * Academic Press, NY., page 15 *----------------------------------------------------------------------------*/ private static void sazm(PosData pdat, TrigData tdat) { float ca; /* cosine of the solar azimuth angle */ float ce; /* cosine of the solar elevation */ float cecl; /* ( ce * cl ) */ float se; /* sine of the solar elevation */ localtrig(pdat, tdat); ce = cos(raddeg * pdat.elevetr); se = sin(raddeg * pdat.elevetr); pdat.azim = 180.0f; cecl = ce * tdat.cl; if (fabs(cecl) >= 0.001) { ca = (se * tdat.sl - tdat.sd) / cecl; if (ca > 1.0f) ca = 1.0f; else if (ca < -1.0f) ca = -1.0f; pdat.azim = 180.0f - acos(ca) * degrad; if (pdat.hrang > 0.0f) pdat.azim = 360.0f - pdat.azim; } }
/*============================================================================ * Local Void function localtrig * * Does trig on internal variable used by several functions *----------------------------------------------------------------------------*/ private static void localtrig(PosData pdat, TrigData tdat) { /* define masks to prevent calculation of uninitialized variables */ const int SD_MASK = (L_ZENETR | L_SSHA | S_SBCF | S_SOLAZM); const int SL_MASK = (L_ZENETR | L_SSHA | S_SBCF | S_SOLAZM); const int CL_MASK = (L_ZENETR | L_SSHA | S_SBCF | S_SOLAZM); const int CD_MASK = (L_ZENETR | L_SSHA | S_SBCF); const int CH_MASK = (L_ZENETR); if (tdat.sd < -900.0f) /* sd was initialized -999 as flag */ { tdat.sd = 1.0f; /* reflag as having completed calculations */ if ((pdat.function | CD_MASK) != 0) tdat.cd = cos(raddeg * pdat.declin); if ((pdat.function | CH_MASK) != 0) tdat.ch = cos(raddeg * pdat.hrang); if ((pdat.function | CL_MASK) != 0) tdat.cl = cos(raddeg * pdat.latitude); if ((pdat.function | SD_MASK) != 0) tdat.sd = sin(raddeg * pdat.declin); if ((pdat.function | SL_MASK) != 0) tdat.sl = sin(raddeg * pdat.latitude); } }
/*============================================================================ * Long integer function S_solpos, adapted from the VAX solar libraries * * This function calculates the apparent solar position and the * intensity of the sun (theoretical maximum solar energy) from * time and place on Earth. * * Requires (from the struct posdata parameter): * Date and time: * year * daynum (requirement depends on the S_DOY switch) * month (requirement depends on the S_DOY switch) * day (requirement depends on the S_DOY switch) * hour * minute * second * interval DEFAULT 0 * Location: * latitude * longitude * Location/time adjuster: * timezone * Atmospheric pressure and temperature: * press DEFAULT 1013.0 mb * temp DEFAULT 10.0 degrees C * Tilt of flat surface that receives solar energy: * aspect DEFAULT 180 (South) * tilt DEFAULT 0 (Horizontal) * Function Switch (codes defined in solpos.h) * function DEFAULT S_ALL * * Returns (via the struct posdata parameter): * everything defined in the struct posdata in solpos.h. *----------------------------------------------------------------------------*/ public static long S_solpos(PosData pdat) { long retval; TrigData trigdat = new TrigData(); /* initialize the trig structure */ trigdat.sd = -999.0f; /* flag to force calculation of trig data */ trigdat.cd = 1.0f; trigdat.ch = 1.0f; /* set the rest of these to something safe */ trigdat.cl = 1.0f; trigdat.sl = 1.0f; if ((retval = validate(pdat)) != 0) { /* validate the inputs */ return retval; } if ((pdat.function & L_DOY) != 0) { doy2dom(pdat); /* convert input doy to month-day */ } else { dom2doy(pdat); /* convert input month-day to doy */ } if ((pdat.function & L_GEOM) != 0) { geometry(pdat); /* do basic geometry calculations */ } if ((pdat.function & L_ZENETR) != 0) { /* etr at non-refracted zenith angle */ zen_no_ref(pdat, trigdat); } if ((pdat.function & L_SSHA) != 0) { /* Sunset hour calculation */ ssha(pdat, trigdat); } if ((pdat.function & L_SBCF) != 0) { /* Shadowband correction factor */ sbcf(pdat, trigdat); } if ((pdat.function & L_TST) != 0) { /* true solar time */ tst(pdat); } if ((pdat.function & L_SRSS) != 0) { /* sunrise/sunset calculations */ srss(pdat); } if ((pdat.function & L_SOLAZM) != 0) { /* solar azimuth calculations */ sazm(pdat, trigdat); } if ((pdat.function & L_REFRAC) != 0) { /* atmospheric refraction calculations */ refrac(pdat); } if ((pdat.function & L_AMASS) != 0) { /* airmass calculations */ amass(pdat); } if ((pdat.function & L_PRIME) != 0) { /* kt-prime/unprime calculations */ prime(pdat); } if ((pdat.function & L_ETR) != 0) { /* ETR and ETRN (refracted) */ etr(pdat); } if ((pdat.function & L_TILT) != 0) { /* tilt calculations */ tilt(pdat); } return 0; }
/*============================================================================ * Local Void function zen_no_ref * * ETR solar zenith angle * Iqbal, M. 1983. An Introduction to Solar Radiation. * Academic Press, NY., page 15 *----------------------------------------------------------------------------*/ private static void zen_no_ref(PosData pdat, TrigData tdat) { float cz; /* cosine of the solar zenith angle */ localtrig(pdat, tdat); cz = tdat.sd * tdat.sl + tdat.cd * tdat.cl * tdat.ch; /* (watch out for the roundoff errors) */ if (fabs(cz) > 1.0f) { if (cz >= 0.0f) cz = 1.0f; else cz = -1.0f; } pdat.zenetr = acos(cz) * degrad; /* (limit the degrees below the horizon to 9 [+90 . 99]) */ if (pdat.zenetr > 99.0f) pdat.zenetr = 99.0f; pdat.elevetr = 90.0f - pdat.zenetr; }