def monthly_mean_daylight_hours(latitude, year=None): """ Calculate mean daylight hours for each month of the year for a given latitude. :param latitude: Latitude [radians] :param year: Year for the daylight hours are required. The only effect of *year* is to change the number of days in Feb to 29 if it is a leap year. If left as the default, None, then a normal (non-leap) year is assumed. :return: Mean daily daylight hours of each month of a year [hours] :rtype: List of floats. """ # validate the latitude argument _check_latitude_rad(latitude) # get the array of days for each month based on whether or not we're in a leap year if year is None or not calendar.isleap(year): month_days = _MONTH_DAYS_NONLEAP else: month_days = _MONTH_DAYS_LEAP # allocate an array of daylight hours for each of the 12 months of the year monthly_mean_dlh = np.zeros((12,)) # keep count of the day of the year day_of_year = 1 # loop over each calendar month to calculate the daylight hours for the month for i, days_in_month in enumerate(month_days): cumulative_daylight_hours = 0.0 # cumulative daylight hours for the month for _ in range(1, days_in_month + 1): daily_solar_declination = solar_declination(day_of_year) daily_sunset_hour_angle = sunset_hour_angle(latitude, daily_solar_declination) cumulative_daylight_hours += daylight_hours(daily_sunset_hour_angle) day_of_year += 1 # calculate the mean daylight hours of the month monthly_mean_dlh[i] = cumulative_daylight_hours / days_in_month return monthly_mean_dlh
def sunset_hour_angle(latitude, sol_dec): """ Calculate sunset hour angle (*Ws*) from latitude and solar declination. Based on FAO equation 25 in Allen et al (1998). :param latitude: Latitude [radians]. Note: *latitude* should be negative if in the southern hemisphere, positive if in the northern hemisphere. :param sol_dec: Solar declination [radians]. Can be calculated using ``sol_dec()``. :return: Sunset hour angle [radians]. :rtype: float """ # validate the latitude and solar declination angle arguments _check_latitude_rad(latitude) _check_sol_dec_rad(sol_dec) cos_sha = -math.tan(latitude) * math.tan(sol_dec) # If tmp is >= 1 there is no sunset, i.e. 24 hours of daylight # If tmp is <= 1 there is no sunrise, i.e. 24 hours of darkness # See http://www.itacanet.org/the-sun-as-a-source-of-energy/part-3-calculating-solar-angles/ # Domain of acos is -1 <= x <= 1 radians (this is not mentioned in FAO-56!) return math.acos(min(max(cos_sha, -1.0), 1.0))