-
Notifications
You must be signed in to change notification settings - Fork 1.1k
NREL non-uniform irradiance mismatch loss for bifacial modules #2046
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
Changes from 64 commits
Commits
Show all changes
87 commits
Select commit
Hold shift + click to select a range
9c68605
Preliminar implementation, tests, docs and gallery example
echedey-ls 7c17712
Merge branch 'main' into nrel-mismatch-loss
echedey-ls 23320db
Update versionadded
echedey-ls 47fa80d
Add example
echedey-ls 84346d2
docstring update
echedey-ls bdb9955
Update v0.11.0.rst
echedey-ls 914d009
who would have guessed it's always the linter?
echedey-ls 29f4c66
Update plot_irradiance_nonuniformity_loss.py
echedey-ls 03011d3
equation fixes
echedey-ls de1744a
RMAD properties application typo
echedey-ls 7f27c9f
does this fix the link?
echedey-ls 2cdc95f
yet another link
echedey-ls 0698839
These links will never work, I suppose
echedey-ls 7f27f1c
Move some "Notes" equations to example and rearrange things there
echedey-ls 58c05bd
give this equation it's space
echedey-ls b973959
eq rendering fixes?
echedey-ls 448b647
maths are not mathing today
echedey-ls 5768473
???
echedey-ls b1a7e4a
??? x2
echedey-ls d1b476d
??? x3
echedey-ls d037314
i feel stupid for this
echedey-ls 4ec952b
Change preprint ref to published one
echedey-ls b0cadb5
Published paper coeffs
echedey-ls 9f51b68
Lots of improvements
echedey-ls 67d3737
Linter - also missing Eq (7)
echedey-ls 10ac204
Test polynomial input
echedey-ls 9290f41
Math
echedey-ls c7b94a0
Test exception
echedey-ls 3599991
Update pvsystem.py
echedey-ls c965225
Update plot_irradiance_nonuniformity_loss.py
echedey-ls 0c15443
Add fill factor ratio
echedey-ls d141189
ª
echedey-ls 8a19a4d
Trying new things
echedey-ls c32f78a
Revert "Trying new things"
echedey-ls 5f69b6d
Update pvsystem.py
echedey-ls 4c354ea
:(
echedey-ls a2de166
:((
echedey-ls b572f45
I hope we dont miss that reference
echedey-ls 1b0565b
Update pvsystem.py
echedey-ls 87f46f0
Remove second section of the example
echedey-ls ae775ec
Minor text upgrade
echedey-ls 4c75534
Merge branch 'main' into nrel-mismatch-loss
echedey-ls 1906e20
Update pvsystem.py
echedey-ls f5863ce
Port to namespace `pvlib.bifacial`
echedey-ls a7d3f7e
Rename to ``power_mismatch_deline``, document in ``bifacial.rst``
echedey-ls 84f702f
fillfactor only for predefined models
echedey-ls 3ad18a6
Docstring rewording
echedey-ls b6c6fb2
Linter
echedey-ls 18a397f
More docs rewording
echedey-ls 1d7d86c
Merge branch 'main' into nrel-mismatch-loss
echedey-ls 8bae370
Apply suggestions from Dax
echedey-ls 75ae58b
Unneded image Dominguez_et_al_PVSC2023.png
echedey-ls b106ff8
Rename file
echedey-ls 4c78987
Fix equations
echedey-ls 56c7d2e
yup it didnt save
echedey-ls d225a6d
lintaaaaaaarrrr
echedey-ls 36f3be0
Eq 7 numbering
echedey-ls 0c99269
Revert unintended changes
echedey-ls a46245a
Adam code review
echedey-ls a4a32e0
Links?
echedey-ls 88273ba
Referencing equations manually
echedey-ls f096a0a
Polynomial links
echedey-ls 5945b74
Dont abuse math mode
echedey-ls adbcbeb
Update loss_models.py
echedey-ls 6f5c69f
I forgot
echedey-ls 770b4a5
Adam Code Review
echedey-ls 329312a
Merge branch 'main' into nrel-mismatch-loss
echedey-ls 9d0411b
Merge branch 'main' into nrel-mismatch-loss
echedey-ls a9d507f
whatsnews
echedey-ls 243de31
Update v0.11.0.rst
echedey-ls 204f8b7
Weird that some tests pass and others dont
echedey-ls a88cb4c
Update loss_models.py
echedey-ls 0136b3a
document
echedey-ls c6ca308
Update loss_models.py
echedey-ls adad0c1
Kevin's review (I)
echedey-ls 6fafcb4
Kevin's review (II)
echedey-ls 436b0e2
Kevin's review (III)
echedey-ls 7d91db6
Update v0.11.1.rst
echedey-ls b1b51bd
minor changes
echedey-ls 3991800
Forgot to update tests
echedey-ls aeaabb4
Accordingly modify model, IO, docs to unitless model
echedey-ls 9289412
Update loss_models.py
echedey-ls f025133
Update loss_models.py
echedey-ls 69a5acf
Apply suggestions from code review
echedey-ls 945d61a
Code review from Cliff
echedey-ls cecc337
Rendering issues, code review from Kevin
echedey-ls 289dbeb
Little missing newline
echedey-ls File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
125 changes: 125 additions & 0 deletions
125
docs/examples/bifacial/plot_irradiance_nonuniformity_loss.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
""" | ||
Plot Irradiance Non-uniformity Loss | ||
=================================== | ||
|
||
Calculate the DC power lost to non-uniformity in a bifacial PV array | ||
""" | ||
|
||
# %% | ||
# The incident irradiance on the backside of a bifacial PV module is | ||
# not uniform due to neighboring rows, the ground albedo and site conditions. | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# When each cell works at different irradiance levels, the power produced by | ||
# the module is less than the sum of the power produced by each cell since the | ||
# maximum power point (MPP) of each cell is different, but cells connected in | ||
# series will operate at the same current. | ||
# This is known as irradiance non-uniformity loss. | ||
# | ||
# Calculating the IV curve of each cell and then matching the working point of | ||
# the whole module is computationally expensive, so a simple model to account | ||
# for this loss is of interest. Deline et al. [1]_ proposed a model based on | ||
# the Relative Mean Absolute Difference (RMAD) of the irradiance of each cell. | ||
# They did also use the standard deviation of the cells' irradiances, but they | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# found that the RMAD was a better predictor of the mismatch loss. | ||
# | ||
# This example demonstrates how to model the irradiance non-uniformity loss | ||
# from the irradiance levels of each cell in a PV module. | ||
# | ||
# The function | ||
# :py:func:`pvlib.bifacial.power_mismatch_deline ` is | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# used to transform the Relative Mean Absolute Difference (RMAD) of the | ||
# irradiance into a power loss percentage. Down below you will find a | ||
# numpy-based implementation of the RMAD function. | ||
# | ||
# References | ||
# ---------- | ||
# .. [1] C. Deline, S. Ayala Pelaez, S. MacAlpine, and C. Olalla, 'Estimating | ||
# and parameterizing mismatch power loss in bifacial photovoltaic | ||
# systems', Progress in Photovoltaics: Research and Applications, vol. 28, | ||
# no. 7, pp. 691-703, 2020, :doi:`10.1002/pip.3259`. | ||
# | ||
# .. sectionauthor:: Echedey Luis <echelual (at) gmail.com> | ||
|
||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
from matplotlib.cm import ScalarMappable | ||
from matplotlib.colors import Normalize | ||
|
||
from pvlib.bifacial import power_mismatch_deline | ||
|
||
# %% | ||
# Problem description | ||
# ------------------- | ||
# Let's set a fixed irradiance to each cell row of the PV array with the values | ||
# described in Figure 1 (A), [1]_. We will cover this case for educational | ||
# purposes, although it can be achieved with the packages | ||
# :ref:`solarfactors <https://github.com/pvlib/solarfactors/>` and | ||
# :ref:`bifacial_radiance <https://github.com/NREL/bifacial_radiance>`. | ||
# | ||
# Here we set and plot the global irradiance level of each cell. | ||
|
||
x = np.arange(12, 0, -1) | ||
y = np.arange(6, 0, -1) | ||
cells_irrad = np.repeat([1059, 976, 967, 986, 1034, 1128], len(x)).reshape( | ||
len(y), len(x) | ||
) | ||
|
||
color_map = "gray" | ||
color_norm = Normalize(930, 1150) | ||
|
||
fig, ax = plt.subplots() | ||
fig.suptitle("Global Irradiance Levels of Each Cell") | ||
fig.colorbar( | ||
ScalarMappable(cmap=color_map, norm=color_norm), | ||
ax=ax, | ||
orientation="vertical", | ||
label="$[W/m^2]$", | ||
) | ||
ax.set_aspect("equal") | ||
ax.pcolormesh( | ||
x, | ||
y, | ||
cells_irrad, | ||
shading="nearest", | ||
edgecolors="black", | ||
cmap=color_map, | ||
norm=color_norm, | ||
) | ||
|
||
# %% | ||
# Relative Mean Absolute Difference | ||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
# Calculate the Relative Mean Absolute Difference (RMAD) of the cells' | ||
# irradiances with the following function, Eq. (4) of [1]_: | ||
# | ||
# .. math:: | ||
# | ||
# \Delta \left[ \% \right] = \frac{1}{n^2 \bar{G}_{total}} | ||
# \sum_{i=1}^{n} \sum_{j=1}^{n} \lvert G_{total,i} - G_{total,j} \rvert | ||
# | ||
|
||
|
||
def rmad(data, axis=None): | ||
""" | ||
Relative Mean Absolute Difference. | ||
https://stackoverflow.com/a/19472336/19371110 | ||
""" | ||
mad = np.mean(np.absolute(data - np.mean(data, axis)), axis) | ||
return mad / np.mean(data, axis) | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
rmad_cells = rmad(cells_irrad) | ||
|
||
# this is the same as a column's RMAD! | ||
print(rmad_cells == rmad(cells_irrad[:, 0])) | ||
|
||
# %% | ||
# Mismatch Loss | ||
# ^^^^^^^^^^^^^ | ||
# Calculate the power loss percentage due to the irradiance non-uniformity | ||
# with the function | ||
# :py:func:`pvlib.bifacial.power_mismatch_deline `. | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
mismatch_loss = power_mismatch_deline(rmad_cells) | ||
|
||
print(f"RMAD of the cells' irradiance: {rmad_cells:.3} [unitless]") | ||
print(f"Power loss due to the irradiance non-uniformity: {mismatch_loss:.3%}") | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
import numpy as np | ||
|
||
from typing import Literal | ||
|
||
|
||
def power_mismatch_deline( | ||
rmad, | ||
model: Literal[ | ||
"fixed-tilt", "single-axis-tracking" | ||
] = "single-axis-tracking", | ||
fillfactor: float = None, | ||
): | ||
r""" | ||
Estimate DC power loss due to irradiance non-uniformity. | ||
|
||
This model is described for bifacial modules in [1]_, where the backside | ||
irradiance is less uniform due to mounting and site conditions. | ||
|
||
Depending on the mounting type, the power loss is estimated with either | ||
equation (11) or (12) of [1]_. Passing a custom polynomial is also valid. | ||
|
||
Use ``fillfactor`` to account for different fill factors between the | ||
trained model and the module of interest. | ||
For example, if the fill factor of the module of interest is | ||
0.65, then set ``fillfactor=0.65``. | ||
|
||
.. versionadded:: 0.11.0 | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Parameters | ||
---------- | ||
rmad : numeric | ||
The Relative Mean Absolute Difference of the cell-by-cell total | ||
irradiance. [Unitless] | ||
Check out the *Notes* section for the equation to calculate it from the | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
bifaciality and the front and back irradiances. | ||
|
||
model : str, numpy.polynomial.polynomial.Polynomial or list, default ``"single-axis-tracking"`` | ||
The model coefficients to use. | ||
If a string, it must be one of the following: | ||
|
||
* ``"fixed-tilt"``: Eq. (11) of [1]_. | ||
* ``"single-axis-tracking"``: Eq. (12) of [1]_. | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
If a :external:class:`numpy.polynomial.polynomial.Polynomial`, | ||
it is evaluated as is. | ||
|
||
If neither a string nor a ``Polynomial``, it must be the coefficients | ||
of a polynomial in ``rmad``, where the first element is the constant | ||
term and the last element is the highest order term. A | ||
:external:class:`~numpy.polynomial.polynomial.Polynomial` | ||
will be created internally. | ||
|
||
fillfactor : float, optional | ||
Fill factor at standard test condition (STC) of the module. | ||
Accounts for different fill factors between the trained model and the | ||
module under non-uniform irradiance. | ||
Models from [1]_ were calculated for a ``fillfactor`` of 0.79. | ||
This parameter will only be used if ``model`` is a string. | ||
Raises a ``ValueError`` if the model is a custom polynomial. | ||
Internally, this argument applies :ref:`Equation (7) <fillfactor_eq>`. | ||
|
||
Returns | ||
------- | ||
loss : numeric | ||
The power loss. | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Raises | ||
------ | ||
ValueError | ||
If the model is not a string and ``fillfactor`` is not ``None``. | ||
|
||
Notes | ||
----- | ||
The models implemented are equations (11) and (12) of [1]_: | ||
|
||
.. math:: | ||
|
||
\text{model="fixed-tilt"} & \Rightarrow M[\%] = | ||
0.142 \Delta[\%] + 0.032 \Delta[\%]^2 \qquad & \text{(11)} | ||
|
||
\text{model="single-axis-tracking"} & \Rightarrow M[\%] = | ||
0.054 \Delta[\%] + 0.068 \Delta[\%]^2 \qquad & \text{(12)} | ||
|
||
where :math:`\Delta[\%]` is the Relative Mean Absolute Difference of the | ||
global irradiance, Eq. (4) of [1]_ and [2]_. | ||
|
||
The losses definition is Eq. (1) of [1]_, and it's defined as a loss of the | ||
output power: | ||
|
||
.. math:: | ||
|
||
M[\%] = 1 - \frac{P_{Array}}{\sum P_{Cells}} \qquad \text{(1)} | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
To account for a module with a fill factor distinct from the one used to | ||
train the model (0.79), the output of the model can be modified by Eq. (7): | ||
|
||
.. _fillfactor_eq: | ||
|
||
.. math:: | ||
|
||
M[\%]_{FF_1} = M[\%]_{FF_0} \frac{FF_1}{FF_0} \qquad \text{(7)} | ||
|
||
In the section *See Also*, you will find two packages that can be used to | ||
calculate the irradiance at different points of the module. | ||
|
||
.. note:: | ||
The global irradiance RMAD is different from the backside irradiance | ||
RMAD. | ||
|
||
In case the RMAD of the backside irradiance is known, the global RMAD can | ||
be calculated as follows, assuming the front irradiance RMAD is | ||
negligible [2]_: | ||
|
||
.. math:: | ||
|
||
RMAD(k \cdot X + c) = RMAD(X) \cdot k \frac{k \bar{X}}{k \bar{X} + c} | ||
= RMAD(X) \cdot k \frac{1}{1 + \frac{c}{k \bar{X}}} | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
by similarity with equation (2) of [1]_: | ||
|
||
.. math:: | ||
|
||
G_{total\,i} = G_{front\,i} + \phi_{Bifi} G_{rear\,i} \qquad \text{(2)} | ||
|
||
See Also | ||
-------- | ||
`solarfactors <https://github.com/pvlib/solarfactors/>`_ | ||
Calculate the irradiance at different points of the module. | ||
`bifacial_radiance <https://github.com/NREL/bifacial_radiance>`_ | ||
Calculate the irradiance at different points of the module. | ||
|
||
References | ||
---------- | ||
.. [1] C. Deline, S. Ayala Pelaez, S. MacAlpine, and C. Olalla, 'Estimating | ||
and parameterizing mismatch power loss in bifacial photovoltaic | ||
systems', Progress in Photovoltaics: Research and Applications, vol. 28, | ||
no. 7, pp. 691-703, 2020, :doi:`10.1002/pip.3259`. | ||
.. [2] “Mean absolute difference,” Wikipedia, Sep. 05, 2023. | ||
https://en.wikipedia.org/wiki/Mean_absolute_difference#Relative_mean_absolute_difference | ||
(accessed 2024-04-14). | ||
""" # noqa: E501 | ||
if isinstance(model, str): | ||
_MODEL_POLYNOMS = { | ||
"fixed-tilt": [0, 0.142, 0.032], # Eq. (11), [1] | ||
"single-axis-tracking": [0, 0.054, 0.068], # Eq. (12), [1] | ||
} | ||
try: | ||
model_polynom = np.polynomial.Polynomial(_MODEL_POLYNOMS[model]) | ||
except KeyError: | ||
raise ValueError( | ||
f"Invalid model '{model}'. Available models are " | ||
f"{list(_MODEL_POLYNOMS.keys())}." | ||
) | ||
else: | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if fillfactor: | ||
# Use fillfactor to modify output of a known trained model | ||
# Eq. (7), [1] | ||
model_polynom = model_polynom * fillfactor / 0.79 | ||
else: | ||
if fillfactor: | ||
raise ValueError( | ||
"Fill factor can only be used with predefined models. " | ||
"Modify polynomial or multiply output by " | ||
"'module_fillfactor / training_fillfactor'." | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
if isinstance(model, np.polynomial.Polynomial): | ||
model_polynom = model | ||
else: # expect an iterable | ||
model_polynom = np.polynomial.Polynomial(coef=model) | ||
|
||
return model_polynom(rmad) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.