def test_solar_elevation_raises_exception_hour(self): """Test an exception is raised if latitudes out of range""" utc_hour = -10.0 msg = 'Hour must be between 0 and 24.0' with self.assertRaisesRegex(ValueError, msg): calc_solar_elevation(self.latitudes, self.longitudes, self.day_of_year, utc_hour)
def test_solar_elevation_raises_exception_lat(self): """Test an exception is raised if latitudes out of range""" latitudes = np.array([-150.0, 50.0, 50.0]) msg = 'Latitudes must be between -90.0 and 90.0' with self.assertRaisesRegex(ValueError, msg): calc_solar_elevation(latitudes, self.longitudes, self.day_of_year, self.utc_hour)
def test_solar_elevation_raises_exception_day_of_year(self): """Test an exception is raised if latitudes out of range""" day_of_year = 367 msg = 'Day of the year must be between 0 and 365' with self.assertRaisesRegex(ValueError, msg): calc_solar_elevation(self.latitudes, self.longitudes, day_of_year, self.utc_hour)
def test_sine_solar_elevation(self): """Test the solar elevation with return_sine equal true.""" expected_results = [-0.00803911, 0.11810263, 0.02403892, -0.11757863] for i, hour in enumerate([8.0, 9.0, 16.0, 17.0]): result = calc_solar_elevation(50.0, 0.0, 10, hour, return_sine=True) self.assertIsInstance(result, float) self.assertAlmostEqual(result, expected_results[i])
def test_basic_solar_elevation_array(self): """Test the solar elevation for an array of lats and lons.""" expected_array = np.array([-3.1423043, -0.46061176, 2.09728301]) result = calc_solar_elevation(self.latitudes, self.longitudes, self.day_of_year, self.utc_hour) self.assertIsInstance(result, np.ndarray) self.assertArrayAlmostEqual(result, expected_array)
def test_basic_solar_elevation_array_360(self): """Test the solar elevation for lons > 180.""" longitudes = np.array([355.0, 0.0, 5.0]) expected_array = np.array([-3.1423043, -0.46061176, 2.09728301]) result = calc_solar_elevation(self.latitudes, longitudes, self.day_of_year, self.utc_hour) self.assertIsInstance(result, np.ndarray) self.assertArrayAlmostEqual(result, expected_array)
def test_basic_solar_elevation(self): """Test the solar elevation for a single point over several hours.""" expected_results = [-0.460611756793, 6.78261282655, 1.37746106416, -6.75237871867] for i, hour in enumerate([8.0, 9.0, 16.0, 17.0]): result = calc_solar_elevation(50.0, 0.0, 10, hour) self.assertIsInstance(result, float) self.assertAlmostEqual(result, expected_results[i])
def test__calc_clearsky_ineichen_grid_properties(target_grid): """Test irradiance values vary over grid as expected.""" lats, lons = get_grid_y_x_values(target_grid) zenith_angle = 90.0 - calc_solar_elevation(lats, lons, day_of_year=0, utc_hour=12) result = GenerateClearskySolarRadiation()._calc_clearsky_ineichen( zenith_angle=zenith_angle, day_of_year=0, surface_altitude=0, linke_turbidity=3 ) # For constant surface_altitude, check that max irradiance occurs for minimum zenith_angle assert np.unravel_index( np.argmax(result, axis=None), result.shape ) == np.unravel_index(np.argmin(zenith_angle, axis=None), zenith_angle.shape) # For constant surface_altitude, check that larger irradiance value at adjacent sites, # occurs for the location with the smaller zenith angle. assert np.all( (result[:, 1:] - result[:, :-1] > 0) == (zenith_angle[:, 1:] - zenith_angle[:, :-1] < 0) ) assert np.all( (result[1:, :] - result[:-1, :] > 0) == (zenith_angle[1:, :] - zenith_angle[:-1, :] < 0) )
def calc_sin_phi(dtval: datetime, lats: ndarray, lons: ndarray) -> ndarray: """ Calculate sin of solar elevation Args: dtval: Date and time. lats: Array 2d of latitudes for each point lons: Array 2d of longitudes for each point Returns: Array of sine of solar elevation at each point """ day_of_year = (dtval - datetime(dtval.year, 1, 1)).days utc_hour = (dtval.hour * 60.0 + dtval.minute) / 60.0 sin_phi = calc_solar_elevation(lats, lons, day_of_year, utc_hour, return_sine=True) return sin_phi
def _calc_clearsky_solar_radiation_data( self, target_grid: Cube, irradiance_times: List[datetime], surface_altitude: ndarray, linke_turbidity: ndarray, temporal_spacing: int, ) -> ndarray: """Evaluate the gridded clearsky solar radiation data over the specified period, calculated on the same spatial grid points as target_grid. Args: target_grid: Cube containing the target spatial grid on which to evaluate irradiance. irradiance_times: Datetimes at which to evaluate the irradiance data. surface_altitude: Surface altitude data, specified in metres. linke_turbidity: Linke turbidity data. temporal_spacing: The time stepping, specified in mins, used in the integration of solar irradiance to produce the accumulated solar radiation. Returns: Gridded irradiance values evaluated over the specified times. """ if lat_lon_determine(target_grid) is not None: lats, lons = transform_grid_to_lat_lon(target_grid) else: lats, lons = get_grid_y_x_values(target_grid) irradiance_data = np.zeros( shape=( len(irradiance_times), target_grid.coord(axis="Y").shape[0], target_grid.coord(axis="X").shape[0], ), dtype=np.float32, ) for time_index, time_step in enumerate(irradiance_times): day_of_year = get_day_of_year(time_step) utc_hour = get_hour_of_day(time_step) zenith_angle = 90.0 - calc_solar_elevation(lats, lons, day_of_year, utc_hour) irradiance_data[time_index, :, :] = self._calc_clearsky_ineichen( zenith_angle, day_of_year, surface_altitude=surface_altitude, linke_turbidity=linke_turbidity, ) # integrate the irradiance data along the time dimension to get the # accumulated solar irradiance. solar_radiation_data = np.trapz(irradiance_data, dx=SECONDS_IN_MINUTE * temporal_spacing, axis=0) return solar_radiation_data