Skip to content

Accept albedo in weather input to ModelChain.run_model method #1478

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 32 commits into from
Aug 19, 2022
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d0c52b6
permit albedo to be a Series
cwhanse Jun 9, 2022
e64a940
work on modelchain
cwhanse Jun 10, 2022
de34639
Merge branch 'master' of https://github.com/pvlib/pvlib-python into a…
cwhanse Jun 13, 2022
0fa45e8
fix tests
cwhanse Jun 13, 2022
cdf853e
shh stickler, docstrings
cwhanse Jun 13, 2022
b3ee156
improve coverage
cwhanse Jun 13, 2022
9e1ce0e
improve coverage correctly
cwhanse Jun 13, 2022
59a37da
finalize coverage, stickler
cwhanse Jun 13, 2022
0295dd0
whatsnew
cwhanse Jun 13, 2022
b9a7308
from review
cwhanse Jun 13, 2022
e518996
Merge branch 'master' of https://github.com/pvlib/pvlib-python into a…
cwhanse Jun 20, 2022
e4c5fa5
don't mutate inputs
cwhanse Jun 20, 2022
acb3657
get_irradiance in tracking.py
cwhanse Jun 20, 2022
2bd97b8
shh stickler
cwhanse Jun 20, 2022
5f0d455
shh stickler
cwhanse Jun 20, 2022
0a10e56
improvements from review
cwhanse Jun 21, 2022
122e992
Merge branch 'pvlib:master' into albedo
cwhanse Jun 21, 2022
cbe2099
update whatsnew
cwhanse Jun 21, 2022
15ff086
Merge branch 'master' of https://github.com/pvlib/pvlib-python into a…
cwhanse Jun 21, 2022
d787675
Merge branch 'albedo' of https://github.com/cwhanse/pvlib-python into…
cwhanse Jun 21, 2022
18a4ed1
Apply suggestions from code review
cwhanse Jun 23, 2022
e2e9f5e
docstring improvements
cwhanse Jun 23, 2022
18bb4d5
Merge branch 'master' into albedo
cwhanse Jul 22, 2022
0bde3c7
Apply suggestions from code review
cwhanse Jul 30, 2022
2ea9c97
Update pvlib/tests/test_irradiance.py
cwhanse Jul 30, 2022
ab2c11a
from review
cwhanse Jul 30, 2022
4340bb0
one more
cwhanse Jul 30, 2022
6193147
more use of fixture, add Array.get_irradiance test
cwhanse Aug 1, 2022
0ecfb7d
more decimal places
cwhanse Aug 1, 2022
af6ff0e
spacing
cwhanse Aug 10, 2022
100a8a1
line length
cwhanse Aug 17, 2022
1a835b1
write albedo from system.arrays to ModelChainResult
cwhanse Aug 18, 2022
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
10 changes: 8 additions & 2 deletions docs/sphinx/source/whatsnew/v0.9.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,26 @@ 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:`1478`)
* albedo is now available as an input to :py:meth:`pvlib.pvsystem.PVSystem.get_irradiance`
and :py:meth:`pvlib.pvsystem.Array.get_irradiance`. (:pull:`1478`)
* :py:func:`pvlib.iotools.read_surfrad` now also accepts remote files
with https links in addition to files on the SURFRAD FTP server
(:pull:`1459`)
* Add :py:func:`pvlib.tracking.calc_surface_orientation` for calculating
single-axis tracker ``surface_tilt`` and ``surface_azimuth`` from
rotation angles. (:issue:`1471`, :pull:`1480`)


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 Down Expand Up @@ -55,6 +60,7 @@ Contributors
* Naman Priyadarshi (:ghuser:`Naman-Priyadarshi`)
* Chencheng Luo (:ghuser:`roger-lcc`)
* Prajwal Borkar (:ghuser:`PrajwalBorkar`)
* Cliff Hansen (:ghuser:`cwhanse`)
* Kevin Anderson (:ghuser:`kanderso-nrel`)
* Cliff Hansen (:ghuser:`cwhanse`)
* Jules Chéron (:ghuser:`jules-ch`)
Expand Down
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
Albedo, defaults to 0.2
albedo : numeric, default 0.2
Ground surface albedo. [unitless]

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=.25, surface_type=None,
albedo=0.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
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.
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
Surface albedo
Ground surface albedo. [unitless]

model : String, default 'perez'
Irradiance model. See :py:func:`get_sky_diffuse` for allowed values.
Expand Down
52 changes: 43 additions & 9 deletions pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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
--------
Expand All @@ -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
Expand All @@ -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
)
Expand Down Expand Up @@ -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
-------
Expand Down
97 changes: 59 additions & 38 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 parameters are ignored:
specified the following PVSystem parameters are ignored:

- `surface_tilt`
- `surface_azimuth`
Expand All @@ -157,13 +157,14 @@ 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.

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 @@ -333,30 +334,33 @@ 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``.
calculate the plane of array irradiance components on the tilted
surfaces defined by each array's ``surface_tilt`` and
``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.

Expand All @@ -376,17 +380,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
)
)

Expand Down Expand Up @@ -1258,14 +1271,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.
Expand Down Expand Up @@ -1425,15 +1438,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
----------
Expand All @@ -1442,15 +1454,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.

Expand All @@ -1463,7 +1477,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)
Expand All @@ -1476,10 +1497,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
Loading