Skip to content

Added irradiance_loss_pvsyst function to pvsystem #1000

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 33 commits into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
693e60d
Added irradiance_loss_pvsyst function to pvsystem module and method t…
btaute Jul 8, 2020
ad09984
Updated formatting
btaute Jul 9, 2020
896e71f
fixing loss equation formatting
btaute Jul 10, 2020
430ab3d
Fix math formatting
btaute Jul 10, 2020
06efce1
Added Tests
btaute Jul 10, 2020
43ac80e
fix formatting in tests
btaute Jul 10, 2020
1bd866b
more test formatting fixes
btaute Jul 10, 2020
7969ce5
Updated v0.8.0 What's New
btaute Jul 10, 2020
8b617b7
Added Issue Number to v0.8.0 What's New
btaute Jul 10, 2020
2361db2
Update pvlib/pvsystem.py
btaute Jul 21, 2020
e0e168c
Update pvlib/pvsystem.py
btaute Jul 21, 2020
b7169bd
Update pvlib/pvsystem.py
btaute Jul 22, 2020
607bdb9
Update pvlib/tests/test_pvsystem.py
btaute Jul 22, 2020
6c408f5
Update pvlib/tests/test_pvsystem.py
btaute Jul 22, 2020
4b33177
Update pvlib/tests/test_pvsystem.py
btaute Jul 22, 2020
29cccdd
Updated params and output to be percents
btaute Jul 22, 2020
25fc424
fix indents
btaute Jul 22, 2020
5d488e7
Changed function to generic combine_loss_factors
btaute Aug 4, 2020
6f2f976
Changed function to generic combine_loss_factors
btaute Aug 4, 2020
3a90af3
Merge branch 'master' of https://github.com/btaute/pvlib-python
btaute Aug 4, 2020
6c5e5a9
fixed test typo
btaute Aug 4, 2020
49a7f04
indentation fix
btaute Aug 4, 2020
50590d3
whitespace fix
btaute Aug 4, 2020
48fd3b4
Moved combine_loss_factors to PV System Effects
btaute Aug 4, 2020
7107119
Apply suggestions from code review
btaute Aug 4, 2020
0b6ae04
fill_method docstring update
btaute Aug 4, 2020
ce50282
Merge branch 'master' of https://github.com/btaute/pvlib-python
btaute Aug 4, 2020
62e9af3
fill_method docstring update
btaute Aug 4, 2020
0d1e95c
Merge branch 'master' into master
btaute Sep 2, 2020
d8abcfe
Update v0.8.0.rst
btaute Sep 2, 2020
4391540
Update pvsystem.py
btaute Sep 2, 2020
1af4854
Update test_pvsystem.py
btaute Sep 2, 2020
70f2fa8
Update v0.8.0.rst
btaute Sep 2, 2020
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
6 changes: 6 additions & 0 deletions docs/sphinx/source/whatsnew/v0.8.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Enhancements
* Add :py:func:`pvlib.iam.marion_diffuse` and
:py:func:`pvlib.iam.marion_integrate` to calculate IAM values for
diffuse irradiance. (:pull:`984`)
* Add :py:func:`pvlib.pvsystem.irradiance_losses_pvsyst` and
:py:meth:`pvlib.pvsystem.PVSystem.irradiance_losses_pvsyst` to calculate
cumulative losses on the effective irradiance with a style similar to PVSyst.
Partialy addresses :issue:`988`. Contributed by Brock Taute :ghuser:`btaute`

Bug fixes
~~~~~~~~~
Expand All @@ -35,6 +39,8 @@ Testing
applied to functions that require args or kwargs. (:pull:`973`)
* Test added for :py:class:`pvlib.modelchain.ModelChain` to confirm ValueError when
``ac_model`` is an invalid string. (:pull:`886`)
* Tests added for :py:func:`pvlib.pvsystem.irradiance_losses_pvsyst` and
:py:meth:`pvlib.pvsystem.PVSystem.irradiance_losses_pvsyst`

Documentation
~~~~~~~~~~~~~
Expand Down
83 changes: 83 additions & 0 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,22 @@ def pvwatts_ac(self, pdc):
return inverter.pvwatts(pdc, self.inverter_parameters['pdc0'],
**kwargs)

def irradiance_loss_pvsyst(self, effective_irradiance,
irradiance_shading_loss, irradiance_snow_loss,
irradiance_soiling_loss):
"""
Calculates plane of array irradiance losses using a model based on the
PVSyst methodology. A wrapper for
:py:func:`pvlib.pvsystem.irradiance_loss_pvsyst`.

See :py:func:`pvlib.pvsystem.irradiance_loss_pvsyst` for details.
"""

return irradiance_loss_pvsyst(effective_irradiance,
irradiance_shading_loss,
irradiance_snow_loss,
irradiance_soiling_loss)

def localize(self, location=None, latitude=None, longitude=None,
**kwargs):
"""Creates a LocalizedPVSystem object using this object
Expand Down Expand Up @@ -2537,6 +2553,73 @@ def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2,
return losses


def irradiance_loss_pvsyst(effective_irradiance, irradiance_shading_loss,
irradiance_snow_loss, irradiance_soiling_loss):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function would return the same thing if the user permuted the loss arguments. We could consider *losses for a more general and extensible approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea. I believe calling out the losses explicitly helps guide new users, but I think an in-depth tutorial can serve that purpose better while allowing for more flexibility here.

If we make this update, I don't think the function name "irradiance_loss_pvsyst" is apt anymore. The point of the function is that it allows a convenient way to compound any irradiance losses that should be applied to the total POA (not specific to beam, diffuse, or ground POA). Maybe that means it should be called "compound_effective_irradiance_losses?" Maybe "combine_effective_irradiance_losses?"

A future implementation more inline with PVSyst should be a "pvsyst_effective_irradiance" function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to combine_loss_factors or similar for a general purpose function, since the PVWatts model does the same calculation on a different set of inputs.

I think it's helpful to also have a function named irradiance_loss_pvsyst or similar, with arguments that are easily recognized by someone used to using the PVsyst loss model. If we keep a _pvsyst function, it should return effective_irradiance with losses applied, instead of the loss factor.

effective_irradiance_pvsyst implies that the function also calculates and applies reflection and spectral mismatch modifiers, which is a larger scope that this PR.

r"""
Calculates plane of array irradiance losses using a model based on the
PVSyst methodology [1]_ of linearly reducing the effective irradiance on a
module. This doesn't account for the electrical losses due to irregular
irradiance on different solar cell strings but rather reduces the
irradiance input to the single diode equation.

The losses are compounded using the following equation:

.. math::

L_{total}(\%) = 100 [ 1 - \Pi_i ( 1 - \frac{L_i}{100} ) ]

Note the parameters must each be a series with a DatetimeIndex. The
index of the returned series will be the same as the effective_irradiance
index. All other parameters will be resampled to match this index with
a "fill forward" method for filling holes.

Parameters
----------
effective_irradiance : Series
The irradiance (W/m2) that is to be reduced. Plane-of-array
irradiance that already accounts for Angle of Incidence and
Spectral losses.

irradiance_shading_loss : Series
The fraction of the solar panel that is shaded.

irradiance_snow_loss : Series
The fraction of the solar panel that is covered with snow.

irradiance_soiling_loss : Series
The fraction of the irradiance prevented from reaching the solar
cells due to soiling of the solar panel.

Returns
-------
losses: Series
Irradiance (W/m2) reduction due to compounded losses.

References
----------
.. [1] "Simulation process: Irradiances and PV-array"
https://www.pvsyst.com/help/simulation_process.htm
(2020).

"""

fill_method = 'ffill'

shading_loss = irradiance_shading_loss.reindex_like(effective_irradiance,
method=fill_method)

snow_loss = irradiance_snow_loss.reindex_like(effective_irradiance,
method=fill_method)

soiling_loss = irradiance_soiling_loss.reindex_like(effective_irradiance,
method=fill_method)

irradiance_losses = effective_irradiance * (
1 - (1 - shading_loss) * (1 - snow_loss) * (1 - soiling_loss))

return irradiance_losses


ashraeiam = deprecated('0.7', alternative='iam.ashrae', name='ashraeiam',
removal='0.8')(iam.ashrae)

Expand Down
32 changes: 32 additions & 0 deletions pvlib/tests/test_pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1347,6 +1347,38 @@ def test_PVSystem_pvwatts_ac_kwargs(mocker):
assert out < pdc


def make_irradiance_loss_pvsyst_test_series():
final_index = pd.date_range(start='1/1/1990 12:00', periods=365, freq='D')
effective_irradiance = pd.Series(1000, index=final_index)
shading = pd.Series(.1, index=final_index)
snow = pd.Series(.05, index=pd.date_range(start='1/1/1990 12:00',
periods=365*2, freq='D'))
soiling = pd.Series(.02, index=pd.date_range(start='1/1/1990',
periods=12, freq='MS'))
expected = pd.Series(162.1, index=final_index)

return {'effective_irradiance': effective_irradiance,
'shading': shading, 'snow': snow,
'soiling': soiling, 'expected': expected}


def test_irradiance_loss_pvsyst():
params = make_irradiance_loss_pvsyst_test_series()
out = pvsystem.irradiance_loss_pvsyst(params['effective_irradiance'],
params['shading'], params['snow'],
params['soiling'])
assert_series_equal(params['expected'], out)


def test_PVSystem_irradiance_loss_pvsyst():
system = pvsystem.PVSystem()
params = make_irradiance_loss_pvsyst_test_series()
out = system.irradiance_loss_pvsyst(params['effective_irradiance'],
params['shading'], params['snow'],
params['soiling'])
assert_series_equal(params['expected'], out)


@fail_on_pvlib_version('0.8')
def test_deprecated_08():
# deprecated function pvsystem.sapm_celltemp
Expand Down