// Compute apparent sunset on a titled surface facing the equator // Duffie and Beckman (1991) eqn 2.19.3b public static double GetApparentSunsetHourAngleEquator // (o) apparent sunset hour angle [radians] (double Slope // (i) slope of receiving surface [radians] , double Lat // (i) latitude [radians, N > 0] , double Decl // (i) declination [radians] ) { double IsNorth, Aux1, Aux2; IsNorth = (Lat > 0) ? 1 : -1; Aux1 = Astro.GetSunsetHourAngle(Lat, Decl); Aux2 = Astro.GetSunsetHourAngle(Lat - IsNorth * Slope, Decl); return(Math.Min(Aux1, Aux2)); }
// 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; } } }