// Compute apparent sunrise and sunset times on a tilted surface of any orientation // Duffie and Beckman (1991) eqn 2.20.5e to 2.20.5i public static void CalcApparentSunsetHourAngle (double Lat // (i) latitude [radians] , double Decl // (i) declination [radians] , double Slope // (i) slope of receiving surface [radians] , double Azimuth // (i) azimuth angle of receiving surface [radians] , out double AppSunrise // (o) apparent sunrise hour angle [radians] , out double AppSunset // (o) apparent sunset hour angle [radians] , out double Sunset // (o) true sunset hour angle [radians] ) { // Declarations double aux1, aux2, aux3, disc; double cosInc, SunZenith, SunAzimuth; double A, B, C; // Calculate true sunset and parameters A, B and C Sunset = Astro.GetSunsetHourAngle(Lat, Decl); A = Math.Cos(Slope) + Math.Tan(Lat) * Math.Cos(Azimuth) * Math.Sin(Slope); B = Math.Cos(Sunset) * Math.Cos(Slope) + Math.Tan(Decl) * Math.Sin(Slope) * Math.Cos(Azimuth); C = Math.Sin(Slope) * Math.Sin(Azimuth) / Math.Cos(Lat); // Pathological case: the sun does not rise if (Sunset == 0) { AppSunrise = AppSunset = 0; return; } // Normal case aux1 = A * A + C * C; disc = aux1 - B * B; // Check discriminant. If it is positive or zero, the sun rises (tangentially) // on the surface. In that case, calculate apparent sunrise and apparent // sunset if (disc >= 0) { aux2 = C * Math.Sqrt(disc) / aux1; aux3 = A * B / aux1; AppSunrise = Math.Min(Sunset, Math.Acos(aux3 + aux2)); AppSunset = Math.Min(Sunset, Math.Acos(aux3 - aux2)); if ((A > 0 && B > 0) || (A >= B)) { AppSunrise = -AppSunrise; } else { AppSunset = -AppSunset; } } // If discriminant is negative, the surface is either always or never // illuminated during the day. To find which case applies, compute the // cosine of the angle of incidence on the surface at noon. If it is less // than zero, then the surface is always in the dark. If it is greater // than zero, then the surface is always illuminated else { Astro.CalcSunPositionHourAngle(Decl, 0, Lat, out SunZenith, out SunAzimuth); cosInc = GetCosIncidenceAngle(SunZenith, SunAzimuth, Slope, Azimuth); if (cosInc < 0) { AppSunrise = AppSunset = 0; } else { AppSunrise = -Sunset; AppSunset = Sunset; } } }
// Calculation for inverter output power, using efficiency curve public void Calculate ( int DayOfYear // Day of year (1-365) , double Hour // Hour of day, in decimal format (11.75 = 11:45 a.m.) ) { double itsSLatR = Utilities.ConvertDtoR(itsSLat); double itsSLongR = Utilities.ConvertDtoR(itsSLong); double itsMLongR = Utilities.ConvertDtoR(itsMLong); try { if (DayOfYear < 1 || DayOfYear > 365 || Hour < 0 || Hour > 24) { throw new CASSYSException("Sun.Calculate: Invalid time stamp for sun position calculation"); } } catch (CASSYSException cs) { ErrorLogger.Log(cs, ErrLevel.FATAL); } // Compute declination and normal extraterrestrial Irradiance if day has changed // Compute Sunrise and Sunset hour angles if (DayOfYear != itsCurrentDayOfYear) { itsCurrentDayOfYear = DayOfYear; itsCurrentDecl = Astro.GetDeclination(itsCurrentDayOfYear); itsCurrentNExtra = Astro.GetNormExtra(itsCurrentDayOfYear); // Variables used to hold the apparent/true sunset and sunrise hour angles double appSunRiseHA; // Hour angle for Sunrise [radians] double appSunsetHA; // Hour angle for Sunset [radians] double trueSunsetHA; // True Sunset Hour angle [radians] // Invoking the Tilt method to get the values Tilt.CalcApparentSunsetHourAngle(itsSLatR, itsCurrentDecl, itsSurfaceSlope, Azimuth, out appSunRiseHA, out appSunsetHA, out trueSunsetHA); // Assigning to the output values AppSunriseHour = Math.Abs(appSunRiseHA) * Util.HAtoR; AppSunsetHour = Util.NoonHour + appSunsetHA * Util.HAtoR; TrueSunSetHour = Util.NoonHour + trueSunsetHA * Util.HAtoR; TrueSunRiseHour = TrueSunSetHour - Astro.GetDayLength(itsSLatR, itsCurrentDecl); // If using local standard time then modify the sunrise and sunset to match the local time stamp. if (itsLSTFlag) { TrueSunSetHour -= Astro.GetATmsST(DayOfYear, itsSLongR, itsMLongR) / 60; // Going from solar to local time TrueSunRiseHour = TrueSunSetHour - Astro.GetDayLength(itsSLatR, itsCurrentDecl); } } // Compute hour angle double SolarTime = Hour; if (itsLSTFlag) { SolarTime += Astro.GetATmsST(DayOfYear, itsSLongR, itsMLongR) / 60; // Going from local to solar time } double HourAngle = Astro.GetHourAngle(SolarTime); // Compute azimuth and zenith angles Astro.CalcSunPositionHourAngle(itsCurrentDecl, HourAngle, itsSLatR, out Zenith, out Azimuth); // Compute normal extraterrestrial Irradiance NExtra = itsCurrentNExtra; // Compute air mass AirMass = Astro.GetAirMass(Zenith); }