Skip to content

Revert "Accept albedo in weather input to ModelChain.run_model method" #1477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions docs/sphinx/source/whatsnew/v0.9.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@ 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`)


Expand All @@ -45,5 +43,4 @@ Contributors
* Naman Priyadarshi (:ghuser:`Naman-Priyadarshi`)
* Chencheng Luo (:ghuser:`roger-lcc`)
* Prajwal Borkar (:ghuser:`PrajwalBorkar`)
* Cliff Hansen (:ghuser:`cwhanse`)
* Kevin Anderson (:ghuser:`kanderso-nrel`)
4 changes: 2 additions & 2 deletions pvlib/clearsky.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, default 0.2
Ground surface albedo. [unitless]
albedo : numeric
Albedo, defaults to 0.2

Returns
-------
Expand Down
6 changes: 3 additions & 3 deletions pvlib/irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -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=0.25, surface_type=None,
albedo=.25, surface_type=None,
model='isotropic',
model_perez='allsitescomposite1990'):
r"""
Expand Down Expand Up @@ -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
Ground surface albedo. [unitless]
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.
Expand Down Expand Up @@ -1872,7 +1872,7 @@ def gti_dirint(poa_global, aoi, solar_zenith, solar_azimuth, times,
applied.

albedo : numeric, default 0.25
Ground surface albedo. [unitless]
Surface albedo

model : String, default 'perez'
Irradiance model. See :py:func:`get_sky_diffuse` for allowed values.
Expand Down
52 changes: 9 additions & 43 deletions pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1339,16 +1339,6 @@ 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
Expand Down Expand Up @@ -1481,17 +1471,11 @@ def prepare_inputs(self, weather):

Parameters
----------
weather : DataFrame, or tuple or list of DataFrames
weather : DataFrame, or tuple or list of DataFrame
Required column names include ``'dni'``, ``'ghi'``, ``'dhi'``.
Optional column names are ``'wind_speed'``, ``'temp_air'``,
``'albedo'``.

If optional columns ``'wind_speed'``, ``'temp_air'`` are not
Optional column names are ``'wind_speed'``, ``'temp_air'``; if not
provided, air temperature of 20 C and wind speed
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.
of 0 m/s will be added to the DataFrame.

If `weather` is a tuple or list, it must be of the same length and
order as the Arrays of the ModelChain's PVSystem.
Expand All @@ -1510,7 +1494,7 @@ def prepare_inputs(self, weather):
Notes
-----
Assigns attributes to ``results``: ``times``, ``weather``,
``solar_position``, ``airmass``, ``total_irrad``, ``aoi``, ``albedo``.
``solar_position``, ``airmass``, ``total_irrad``, ``aoi``

See also
--------
Expand All @@ -1523,7 +1507,6 @@ 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
Expand All @@ -1548,7 +1531,6 @@ 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
)
Expand Down Expand Up @@ -1742,32 +1724,16 @@ def run_model(self, weather):
Parameters
----------
weather : DataFrame, or tuple or list of DataFrame
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'``
Irradiance column names must include ``'dni'``, ``'ghi'``, and
``'dhi'``. 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 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.
If list or tuple, must be of the same length and order as the
Arrays of the ModelChain's PVSystem.

Returns
-------
Expand Down
96 changes: 37 additions & 59 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 PVSystem parameters are ignored:
specified the following parameters are ignored:

- `surface_tilt`
- `surface_azimuth`
Expand All @@ -157,16 +157,13 @@ class PVSystem:
North=0, East=90, South=180, West=270.

albedo : None or float, default None
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.
The ground albedo. If ``None``, will attempt to use
``surface_type`` and ``irradiance.SURFACE_ALBEDOS``
to lookup albedo.

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.
Expand Down Expand Up @@ -336,32 +333,30 @@ def get_aoi(self, solar_zenith, solar_azimuth):

@_unwrap_single_value
def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi,
albedo=None, dni_extra=None, airmass=None,
model='haydavies', **kwargs):
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`` and ``self.surface_azimuth```.
surface defined by ``self.surface_tilt``,
``self.surface_azimuth``, and ``self.albedo``.

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. [W/m2]
Direct Normal Irradiance
ghi : float or Series or tuple of float or Series
Global horizontal irradiance. [W/m2]
Global horizontal irradiance
dhi : float or Series or tuple of float or Series
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]
Diffuse horizontal irradiance
dni_extra : None, float or Series, default None
Extraterrestrial direct normal irradiance
airmass : None, float or Series, default None
Airmass. [unitless]
Airmass
model : String, default 'haydavies'
Irradiance model.

Expand All @@ -381,26 +376,17 @@ 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,
albedo=albedo,
dni_extra=dni_extra, airmass=airmass,
model=model,
dni_extra, airmass, model,
**kwargs)
for array, dni, ghi, dhi, albedo in zip(
self.arrays, dni, ghi, dhi, albedo
for array, dni, ghi, dhi in zip(
self.arrays, dni, ghi, dhi
)
)

Expand Down Expand Up @@ -1272,14 +1258,14 @@ class Array:
If not provided, a FixedMount with zero tilt is used.

albedo : None or float, default None
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.
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.

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.
Expand Down Expand Up @@ -1439,14 +1425,15 @@ def get_aoi(self, solar_zenith, solar_azimuth):
solar_zenith, solar_azimuth)

def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi,
albedo=None, dni_extra=None, airmass=None,
model='haydavies', **kwargs):
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``.
defined by ``self.surface_tilt`` and ``self.surface_azimuth`` with
albedo ``self.albedo``.

Parameters
----------
Expand All @@ -1455,17 +1442,15 @@ 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. [W/m2]
ghi : float or Series. [W/m2]
Direct Normal Irradiance
ghi : float or Series
Global horizontal irradiance
dhi : float or Series
Diffuse horizontal irradiance. [W/m2]
albedo : None, float or Series, default None
Ground surface albedo. [unitless]
Diffuse horizontal irradiance
dni_extra : None, float or Series, default None
Extraterrestrial direct normal irradiance. [W/m2]
Extraterrestrial direct normal irradiance
airmass : None, float or Series, default None
Airmass. [unitless]
Airmass
model : String, default 'haydavies'
Irradiance model.

Expand All @@ -1478,14 +1463,7 @@ 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)
Expand All @@ -1498,10 +1476,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'):
Expand Down
24 changes: 0 additions & 24 deletions pvlib/tests/test_clearsky.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,30 +756,6 @@ 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
Expand Down
Loading