diff --git a/docs/sphinx/source/whatsnew/v0.9.2.rst b/docs/sphinx/source/whatsnew/v0.9.2.rst index 893cc65639..799823f986 100644 --- a/docs/sphinx/source/whatsnew/v0.9.2.rst +++ b/docs/sphinx/source/whatsnew/v0.9.2.rst @@ -8,15 +8,17 @@ Deprecations Enhancements ~~~~~~~~~~~~ +* albedo can now be provided as a column in the `weather` DataFrame input to + :py:method:`pvlib.modelchain.ModelChain.run_model`. (:issue:`1387`, :pull:`1469`) Bug fixes ~~~~~~~~~ * :py:func:`pvlib.irradiance.get_total_irradiance` and :py:func:`pvlib.solarposition.spa_python` now raise an error instead - of silently ignoring unknown parameters (:pull:`1437`) + of silently ignoring unknown parameters. (:pull:`1437`) * Fix a bug in :py:func:`pvlib.solarposition.sun_rise_set_transit_ephem` where passing localized timezones with large UTC offsets could return - rise/set/transit times for the wrong day in recent versions of ``ephem`` + rise/set/transit times for the wrong day in recent versions of ``ephem``. (:issue:`1449`, :pull:`1448`) @@ -43,4 +45,5 @@ Contributors * Naman Priyadarshi (:ghuser:`Naman-Priyadarshi`) * Chencheng Luo (:ghuser:`roger-lcc`) * Prajwal Borkar (:ghuser:`PrajwalBorkar`) +* Cliff Hansen (:ghuser:`cwhanse`) * Kevin Anderson (:ghuser:`kanderso-nrel`) diff --git a/pvlib/clearsky.py b/pvlib/clearsky.py index 311d683674..2f5cd68c62 100644 --- a/pvlib/clearsky.py +++ b/pvlib/clearsky.py @@ -960,8 +960,8 @@ def bird(zenith, airmass_relative, aod380, aod500, precipitable_water, Extraterrestrial radiation [W/m^2], defaults to 1364[W/m^2] asymmetry : numeric Asymmetry factor, defaults to 0.85 - albedo : numeric - Albedo, defaults to 0.2 + albedo : numeric, default 0.2 + Ground surface albedo. [unitless] Returns ------- diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 3de4d96f65..03ddd13f5a 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -304,7 +304,7 @@ def beam_component(surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, def get_total_irradiance(surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, ghi, dhi, dni_extra=None, airmass=None, - albedo=.25, surface_type=None, + albedo=0.25, surface_type=None, model='isotropic', model_perez='allsitescomposite1990'): r""" @@ -344,7 +344,7 @@ def get_total_irradiance(surface_tilt, surface_azimuth, airmass : None or numeric, default None Relative airmass (not adjusted for pressure). [unitless] albedo : numeric, default 0.25 - Surface albedo. [unitless] + Ground surface albedo. [unitless] surface_type : None or str, default None Surface type. See :py:func:`~pvlib.irradiance.get_ground_diffuse` for the list of accepted values. @@ -1872,7 +1872,7 @@ def gti_dirint(poa_global, aoi, solar_zenith, solar_azimuth, times, applied. albedo : numeric, default 0.25 - Surface albedo + Ground surface albedo. [unitless] model : String, default 'perez' Irradiance model. See :py:func:`get_sky_diffuse` for allowed values. diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 2798c39a68..8bdb924d0a 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1339,6 +1339,16 @@ def _prep_inputs_solar_pos(self, weather): **kwargs) return self + def _prep_inputs_albedo(self, weather): + """ + Get albedo from weather + """ + try: + self.results.albedo = _tuple_from_dfs(weather, 'albedo') + except KeyError: + self.results.albedo = None + return self + def _prep_inputs_airmass(self): """ Assign airmass @@ -1471,11 +1481,17 @@ def prepare_inputs(self, weather): Parameters ---------- - weather : DataFrame, or tuple or list of DataFrame + weather : DataFrame, or tuple or list of DataFrames Required column names include ``'dni'``, ``'ghi'``, ``'dhi'``. - Optional column names are ``'wind_speed'``, ``'temp_air'``; if not + Optional column names are ``'wind_speed'``, ``'temp_air'``, + ``'albedo'``. + + If optional columns ``'wind_speed'``, ``'temp_air'`` are not provided, air temperature of 20 C and wind speed - of 0 m/s will be added to the DataFrame. + of 0 m/s will be added to the `weather` DataFrame. + + If optional column ``'albedo'`` is provided, albedo values in the + ModelChain's PVSystem.arrays are ignored. If `weather` is a tuple or list, it must be of the same length and order as the Arrays of the ModelChain's PVSystem. @@ -1494,7 +1510,7 @@ def prepare_inputs(self, weather): Notes ----- Assigns attributes to ``results``: ``times``, ``weather``, - ``solar_position``, ``airmass``, ``total_irrad``, ``aoi`` + ``solar_position``, ``airmass``, ``total_irrad``, ``aoi``, ``albedo``. See also -------- @@ -1507,6 +1523,7 @@ def prepare_inputs(self, weather): self._prep_inputs_solar_pos(weather) self._prep_inputs_airmass() + self._prep_inputs_albedo(weather) # PVSystem.get_irradiance and SingleAxisTracker.get_irradiance # and PVSystem.get_aoi and SingleAxisTracker.get_aoi @@ -1531,6 +1548,7 @@ def prepare_inputs(self, weather): _tuple_from_dfs(self.results.weather, 'dni'), _tuple_from_dfs(self.results.weather, 'ghi'), _tuple_from_dfs(self.results.weather, 'dhi'), + albedo=self.results.albedo, airmass=self.results.airmass['airmass_relative'], model=self.transposition_model ) @@ -1724,16 +1742,32 @@ def run_model(self, weather): Parameters ---------- weather : DataFrame, or tuple or list of DataFrame - Irradiance column names must include ``'dni'``, ``'ghi'``, and - ``'dhi'``. If optional columns ``'temp_air'`` and ``'wind_speed'`` + Column names must include: + + - ``'dni'`` + - ``'ghi'`` + - ``'dhi'`` + + Optional columns are: + + - ``'temp_air'`` + - ``'cell_temperature'`` + - ``'module_temperature'`` + - ``'wind_speed'`` + - ``'albedo'`` + + If optional columns ``'temp_air'`` and ``'wind_speed'`` are not provided, air temperature of 20 C and wind speed of 0 m/s are added to the DataFrame. If optional column ``'cell_temperature'`` is provided, these values are used instead - of `temperature_model`. If optional column `module_temperature` + of `temperature_model`. If optional column ``'module_temperature'`` is provided, `temperature_model` must be ``'sapm'``. - If list or tuple, must be of the same length and order as the - Arrays of the ModelChain's PVSystem. + If optional column ``'albedo'`` is provided, ``'albedo'`` may not + be present on the ModelChain's PVSystem.Arrays. + + If weather is a list or tuple, it must be of the same length and + order as the Arrays of the ModelChain's PVSystem. Returns ------- diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 6bb89f34a3..3f37f66da2 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -134,7 +134,7 @@ class PVSystem: a single array is created from the other parameters (e.g. `surface_tilt`, `surface_azimuth`). Must contain at least one Array, if length of arrays is 0 a ValueError is raised. If `arrays` is - specified the following parameters are ignored: + specified the following PVSystem parameters are ignored: - `surface_tilt` - `surface_azimuth` @@ -157,13 +157,16 @@ class PVSystem: North=0, East=90, South=180, West=270. albedo : None or float, default None - The ground albedo. If ``None``, will attempt to use - ``surface_type`` and ``irradiance.SURFACE_ALBEDOS`` - to lookup albedo. + Ground surface albedo. If ``None``, then ``surface_type`` is used + to look up a value in ``irradiance.SURFACE_ALBEDOS``. + If ``surface_type`` is also None then a ground surface albedo + of 0.25 is used. For time-dependent albedos, add ``'albedo'`` to + the input ``'weather'`` DataFrame for + :py:class:`pvlib.modelchain.ModelChain` methods. surface_type : None or string, default None - The ground surface type. See ``irradiance.SURFACE_ALBEDOS`` - for valid values. + The ground surface type. See ``irradiance.SURFACE_ALBEDOS`` for + valid values. module : None or string, default None The model name of the modules. @@ -333,30 +336,32 @@ def get_aoi(self, solar_zenith, solar_azimuth): @_unwrap_single_value def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi, - dni_extra=None, airmass=None, model='haydavies', - **kwargs): + albedo=None, dni_extra=None, airmass=None, + model='haydavies', **kwargs): """ Uses the :py:func:`irradiance.get_total_irradiance` function to calculate the plane of array irradiance components on a tilted - surface defined by ``self.surface_tilt``, - ``self.surface_azimuth``, and ``self.albedo``. + surface defined by ``self.surface_tilt`` and ``self.surface_azimuth```. Parameters ---------- - solar_zenith : float or Series. + solar_zenith : float or Series Solar zenith angle. - solar_azimuth : float or Series. + solar_azimuth : float or Series Solar azimuth angle. dni : float or Series or tuple of float or Series - Direct Normal Irradiance + Direct Normal Irradiance. [W/m2] ghi : float or Series or tuple of float or Series - Global horizontal irradiance + Global horizontal irradiance. [W/m2] dhi : float or Series or tuple of float or Series - Diffuse horizontal irradiance - dni_extra : None, float or Series, default None - Extraterrestrial direct normal irradiance + Diffuse horizontal irradiance. [W/m2] + albedo : None, float or Series, default None + Ground surface albedo. [unitless] + dni_extra : None, float, Series or tuple of float or Series, + default None + Extraterrestrial direct normal irradiance. [W/m2] airmass : None, float or Series, default None - Airmass + Airmass. [unitless] model : String, default 'haydavies' Irradiance model. @@ -376,17 +381,26 @@ def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi, poa_irradiance : DataFrame or tuple of DataFrame Column names are: ``'poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', 'poa_ground_diffuse'``. + + See also + -------- + :py:func:`pvlib.irradiance.get_total_irradiance` """ dni = self._validate_per_array(dni, system_wide=True) ghi = self._validate_per_array(ghi, system_wide=True) dhi = self._validate_per_array(dhi, system_wide=True) + + albedo = self._validate_per_array(albedo, system_wide=True) + return tuple( array.get_irradiance(solar_zenith, solar_azimuth, dni, ghi, dhi, - dni_extra, airmass, model, + albedo=albedo, + dni_extra=dni_extra, airmass=airmass, + model=model, **kwargs) - for array, dni, ghi, dhi in zip( - self.arrays, dni, ghi, dhi + for array, dni, ghi, dhi, albedo in zip( + self.arrays, dni, ghi, dhi, albedo ) ) @@ -1258,14 +1272,14 @@ class Array: If not provided, a FixedMount with zero tilt is used. albedo : None or float, default None - The ground albedo. If ``None``, will attempt to use - ``surface_type`` to look up an albedo value in - ``irradiance.SURFACE_ALBEDOS``. If a surface albedo - cannot be found then 0.25 is used. + Ground surface albedo. If ``None``, then ``surface_type`` is used + to look up a value in ``irradiance.SURFACE_ALBEDOS``. + If ``surface_type`` is also None then a ground surface albedo + of 0.25 is used. surface_type : None or string, default None - The ground surface type. See ``irradiance.SURFACE_ALBEDOS`` - for valid values. + The ground surface type. See ``irradiance.SURFACE_ALBEDOS`` for valid + values. module : None or string, default None The model name of the modules. @@ -1425,15 +1439,14 @@ def get_aoi(self, solar_zenith, solar_azimuth): solar_zenith, solar_azimuth) def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi, - dni_extra=None, airmass=None, model='haydavies', - **kwargs): + albedo=None, dni_extra=None, airmass=None, + model='haydavies', **kwargs): """ Get plane of array irradiance components. Uses the :py:func:`pvlib.irradiance.get_total_irradiance` function to calculate the plane of array irradiance components for a surface - defined by ``self.surface_tilt`` and ``self.surface_azimuth`` with - albedo ``self.albedo``. + defined by ``self.surface_tilt`` and ``self.surface_azimuth``. Parameters ---------- @@ -1442,15 +1455,17 @@ def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi, solar_azimuth : float or Series. Solar azimuth angle. dni : float or Series - Direct Normal Irradiance - ghi : float or Series + Direct normal irradiance. [W/m2] + ghi : float or Series. [W/m2] Global horizontal irradiance dhi : float or Series - Diffuse horizontal irradiance + Diffuse horizontal irradiance. [W/m2] + albedo : None, float or Series, default None + Ground surface albedo. [unitless] dni_extra : None, float or Series, default None - Extraterrestrial direct normal irradiance + Extraterrestrial direct normal irradiance. [W/m2] airmass : None, float or Series, default None - Airmass + Airmass. [unitless] model : String, default 'haydavies' Irradiance model. @@ -1463,7 +1478,14 @@ def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi, poa_irradiance : DataFrame Column names are: ``'poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', 'poa_ground_diffuse'``. + + See also + -------- + :py:func:`pvlib.irradiance.get_total_irradiance` """ + if albedo is None: + albedo = self.albedo + # not needed for all models, but this is easier if dni_extra is None: dni_extra = irradiance.get_extra_radiation(solar_zenith.index) @@ -1476,10 +1498,10 @@ def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi, orientation['surface_azimuth'], solar_zenith, solar_azimuth, dni, ghi, dhi, + albedo=albedo, dni_extra=dni_extra, airmass=airmass, model=model, - albedo=self.albedo, **kwargs) def get_iam(self, aoi, iam_model='physical'): diff --git a/pvlib/tests/test_clearsky.py b/pvlib/tests/test_clearsky.py index 15fc74e383..d603cbcdfe 100644 --- a/pvlib/tests/test_clearsky.py +++ b/pvlib/tests/test_clearsky.py @@ -756,6 +756,30 @@ def test_bird(): assert np.allclose( testdata['Dif Hz'].where(dusk, 0.), diffuse_horz[1:48], rtol=1e-3 ) + # repeat test with albedo as a Series + alb_series = pd.Series(0.2, index=times) + irrads = clearsky.bird( + zenith, airmass, aod_380nm, aod_500nm, h2o_cm, o3_cm, press_mB * 100., + etr, b_a, alb_series + ) + Eb, Ebh, Gh, Dh = (irrads[_] for _ in field_names) + direct_beam = pd.Series(np.where(dawn, Eb, 0.), index=times).fillna(0.) + assert np.allclose( + testdata['Direct Beam'].where(dusk, 0.), direct_beam[1:48], rtol=1e-3 + ) + direct_horz = pd.Series(np.where(dawn, Ebh, 0.), index=times).fillna(0.) + assert np.allclose( + testdata['Direct Hz'].where(dusk, 0.), direct_horz[1:48], rtol=1e-3 + ) + global_horz = pd.Series(np.where(dawn, Gh, 0.), index=times).fillna(0.) + assert np.allclose( + testdata['Global Hz'].where(dusk, 0.), global_horz[1:48], rtol=1e-3 + ) + diffuse_horz = pd.Series(np.where(dawn, Dh, 0.), index=times).fillna(0.) + assert np.allclose( + testdata['Dif Hz'].where(dusk, 0.), diffuse_horz[1:48], rtol=1e-3 + ) + # test keyword parameters irrads2 = clearsky.bird( zenith, airmass, aod_380nm, aod_500nm, h2o_cm, dni_extra=etr diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 80986f26c3..ff66c4457b 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -120,29 +120,38 @@ def test_get_extra_radiation_invalid(): irradiance.get_extra_radiation(300, method='invalid') -def test_grounddiffuse_simple_float(): +def test_get_ground_diffuse_simple_float(): result = irradiance.get_ground_diffuse(40, 900) assert_allclose(result, 26.32000014911496) -def test_grounddiffuse_simple_series(irrad_data): +def test_get_ground_diffuse_simple_series(irrad_data): ground_irrad = irradiance.get_ground_diffuse(40, irrad_data['ghi']) assert ground_irrad.name == 'diffuse_ground' -def test_grounddiffuse_albedo_0(irrad_data): +def test_get_ground_diffuse_albedo_0(irrad_data): ground_irrad = irradiance.get_ground_diffuse( 40, irrad_data['ghi'], albedo=0) assert 0 == ground_irrad.all() +def test_get_ground_diffuse_albedo_series(times): + albedo = pd.Series(0.2, index=times) + ground_irrad = irradiance.get_ground_diffuse( + 45, pd.Series(1000, index=times), albedo) + expected = albedo * 0.5 * (1 - np.sqrt(2) / 2.) * 1000 + expected.name = 'diffuse_ground' + assert_series_equal(ground_irrad, expected) + + def test_grounddiffuse_albedo_invalid_surface(irrad_data): with pytest.raises(KeyError): irradiance.get_ground_diffuse( 40, irrad_data['ghi'], surface_type='invalid') -def test_grounddiffuse_albedo_surface(irrad_data): +def test_get_ground_diffuse_albedo_surface(irrad_data): result = irradiance.get_ground_diffuse(40, irrad_data['ghi'], surface_type='sand') assert_allclose(result, [0, 3.731058, 48.778813, 12.035025], atol=1e-4) @@ -387,6 +396,26 @@ def test_get_total_irradiance(irrad_data, ephem_data, dni_et, 'poa_ground_diffuse'] +def test_get_total_irradiance_albedo( + irrad_data, ephem_data, dni_et, relative_airmass): + models = ['isotropic', 'klucher', + 'haydavies', 'reindl', 'king', 'perez'] + albedo = pd.Series(0.2, index=ephem_data.index) + for model in models: + total = irradiance.get_total_irradiance( + 32, 180, + ephem_data['apparent_zenith'], ephem_data['azimuth'], + dni=irrad_data['dni'], ghi=irrad_data['ghi'], + dhi=irrad_data['dhi'], + dni_extra=dni_et, airmass=relative_airmass, + model=model, + albedo=albedo) + + assert total.columns.tolist() == ['poa_global', 'poa_direct', + 'poa_diffuse', 'poa_sky_diffuse', + 'poa_ground_diffuse'] + + @pytest.mark.parametrize('model', ['isotropic', 'klucher', 'haydavies', 'reindl', 'king', 'perez']) def test_get_total_irradiance_scalars(model): @@ -698,6 +727,14 @@ def test_gti_dirint(): assert_frame_equal(output, expected) + # test with albedo as a Series + albedo = pd.Series(0.05, index=times) + output = irradiance.gti_dirint( + poa_global, aoi, zenith, azimuth, times, surface_tilt, surface_azimuth, + albedo=albedo) + + assert_frame_equal(output, expected) + # test temp_dew input temp_dew = np.array([70, 80, 20]) output = irradiance.gti_dirint( diff --git a/pvlib/tests/test_modelchain.py b/pvlib/tests/test_modelchain.py index f4a92eadad..1c990d73e8 100644 --- a/pvlib/tests/test_modelchain.py +++ b/pvlib/tests/test_modelchain.py @@ -497,6 +497,24 @@ def test_prepare_inputs_multi_weather( assert len(mc.results.total_irrad) == num_arrays +@pytest.mark.parametrize("input_type", [tuple, list]) +def test_prepare_inputs_albedo_in_weather( + sapm_dc_snl_ac_system_Array, location, input_type): + times = pd.date_range(start='20160101 1200-0700', + end='20160101 1800-0700', freq='6H') + mc = ModelChain(sapm_dc_snl_ac_system_Array, location) + weather = pd.DataFrame({'ghi': 1, 'dhi': 1, 'dni': 1, 'albedo': 0.5}, + index=times) + # weather as a single DataFrame + mc.prepare_inputs(weather) + num_arrays = sapm_dc_snl_ac_system_Array.num_arrays + assert len(mc.results.total_irrad) == num_arrays + # repeat with tuple of weather + mc.prepare_inputs(input_type((weather, weather))) + num_arrays = sapm_dc_snl_ac_system_Array.num_arrays + assert len(mc.results.total_irrad) == num_arrays + + def test_prepare_inputs_no_irradiance(sapm_dc_snl_ac_system, location): mc = ModelChain(sapm_dc_snl_ac_system, location) weather = pd.DataFrame() diff --git a/pvlib/tests/test_pvsystem.py b/pvlib/tests/test_pvsystem.py index 1141e490e9..a6ffe93d46 100644 --- a/pvlib/tests/test_pvsystem.py +++ b/pvlib/tests/test_pvsystem.py @@ -1689,14 +1689,37 @@ def test_PVSystem_get_irradiance(): irrads['dhi']) expected = pd.DataFrame(data=np.array( - [[ 883.65494055, 745.86141676, 137.79352379, 126.397131 , - 11.39639279], - [ 0. , -0. , 0. , 0. , 0. ]]), + [[883.65494055, 745.86141676, 137.79352379, 126.397131, 11.39639279], + [0., -0., 0., 0., 0.]]), columns=['poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', 'poa_ground_diffuse'], index=times) + assert_frame_equal(irradiance, expected, check_less_precise=2) + +def test_PVSystem_get_irradiance_albedo(): + system = pvsystem.PVSystem(surface_tilt=32, surface_azimuth=135) + times = pd.date_range(start='20160101 1200-0700', + end='20160101 1800-0700', freq='6H') + location = Location(latitude=32, longitude=-111) + solar_position = location.get_solarposition(times) + irrads = pd.DataFrame({'dni': [900, 0], 'ghi': [600, 0], 'dhi': [100, 0], + 'albedo': [0.5, 0.5]}, + index=times) + # albedo as a Series + irradiance = system.get_irradiance(solar_position['apparent_zenith'], + solar_position['azimuth'], + irrads['dni'], + irrads['ghi'], + irrads['dhi'], + albedo=irrads['albedo']) + expected = pd.DataFrame(data=np.array( + [[895.05134334, 745.86141676, 149.18992658, 126.397131, 22.79279558], + [0., -0., 0., 0., 0.]]), + columns=['poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', + 'poa_ground_diffuse'], + index=times) assert_frame_equal(irradiance, expected, check_less_precise=2) diff --git a/pvlib/tests/test_tracking.py b/pvlib/tests/test_tracking.py index c88c92b248..bf6a77eeea 100644 --- a/pvlib/tests/test_tracking.py +++ b/pvlib/tests/test_tracking.py @@ -393,6 +393,25 @@ def test_get_irradiance(): assert_frame_equal(irradiance, expected, check_less_precise=2) + # test with albedo as a Series + irrads['albedo'] = [0.5, 0.5] + with np.errstate(invalid='ignore'): + irradiance = system.get_irradiance(tracker_data['surface_tilt'], + tracker_data['surface_azimuth'], + solar_zenith, + solar_azimuth, + irrads['dni'], + irrads['ghi'], + irrads['dhi'], + albedo=irrads['albedo']) + + expected = pd.Series(data=[21.05514984, nan], index=times, + name='poa_ground_diffuse') + + assert_series_equal(irradiance['poa_ground_diffuse'], expected, + check_less_precise=2) + + def test_SingleAxisTracker___repr__(): with pytest.warns(pvlibDeprecationWarning): diff --git a/pvlib/tracking.py b/pvlib/tracking.py index 951f2e886e..c3df9e1f7e 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -187,7 +187,8 @@ def get_aoi(self, surface_tilt, surface_azimuth, solar_zenith, @_unwrap_single_value def get_irradiance(self, surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, ghi, dhi, - dni_extra=None, airmass=None, model='haydavies', + albedo=None, dni_extra=None, airmass=None, + model='haydavies', **kwargs): """ Uses the :func:`irradiance.get_total_irradiance` function to @@ -214,6 +215,8 @@ def get_irradiance(self, surface_tilt, surface_azimuth, Global horizontal irradiance dhi : float or Series Diffuse horizontal irradiance + albedo : None, float or Series, default None + Ground surface albedo. [unitless] dni_extra : float or Series, default None Extraterrestrial direct normal irradiance airmass : float or Series, default None @@ -244,6 +247,13 @@ def get_irradiance(self, surface_tilt, surface_azimuth, ghi = self._validate_per_array(ghi, system_wide=True) dhi = self._validate_per_array(dhi, system_wide=True) + if albedo is None: + # assign default albedo here because SingleAxisTracker + # initializes albedo to None + albedo = 0.25 + + albedo = self._validate_per_array(albedo, system_wide=True) + return tuple( irradiance.get_total_irradiance( surface_tilt, @@ -254,10 +264,10 @@ def get_irradiance(self, surface_tilt, surface_azimuth, dni_extra=dni_extra, airmass=airmass, model=model, - albedo=self.arrays[0].albedo, + albedo=albedo, **kwargs) - for array, dni, ghi, dhi in zip( - self.arrays, dni, ghi, dhi + for array, dni, ghi, dhi, albedo in zip( + self.arrays, dni, ghi, dhi, albedo ) )