Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
8 changes: 8 additions & 0 deletions docs/sphinx/source/reference/pv_modeling/system_models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,11 @@ ADR model

pvarray.pvefficiency_adr
pvarray.fit_pvefficiency_adr

PVGIS model
^^^^^^^^^^^

.. autosummary::
:toctree: ../generated/

pvsystem.huld
3 changes: 2 additions & 1 deletion docs/sphinx/source/whatsnew/v0.10.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ v0.10.4 (Anticipated March, 2024)

Enhancements
~~~~~~~~~~~~
* Added the Huld PV model (:pull:`1940`)


Bug fixes
Expand All @@ -27,4 +28,4 @@ Requirements

Contributors
~~~~~~~~~~~~

* Cliff Hansen (:ghuser:`cwhanse`)
75 changes: 75 additions & 0 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -2845,6 +2845,81 @@ def pvwatts_dc(g_poa_effective, temp_cell, pdc0, gamma_pdc, temp_ref=25.):
return pdc


def _infer_k_huld(cell_type):
# from PVGIS documentation, Section 5.2.3, accessed 12/22/2023
huld_params = {'cSi': (-0.017237, -0.040465, -0.004702, 0.000149,
0.000170, 0.000005),
'CIS': (-0.005554, -0.038724, -0.003723, -0.000905,
-0.001256, 0.000001),
'CdTe': (-0.046689, -0.072844, -0.002262, 0.000276,
0.000159, -0.000006)}
return huld_params[cell_type]


def huld(effective_irradiance, temp_mod, pdc0, k=None, cell_type=None):
r"""
Power (DC) using the Huld model.

The Huld model [1]_ is used by PVGIS and is given by


.. math::

P_{dc} = G' ( P_{dc0} + k_1 \log(G') + k_2 \log^2 (G') + k_3 T' +
k_4 T' \log(G') + k_5 T' \log^2 (G') + k_6 T'^2)

G' = \frac{G_{poa eff}}{1000}

T' = T_{mod} - 25 °C


Parameters
----------
effective_irradiance : numeric
The irradiance that is converted to photocurrent. [W/m^2]
temp_mod: numeric
Module back-surface temperature. [C]
pdc0: numeric
Power of the modules at 1000 W/m^2 and cell reference temperature. [W]
k : tuple, optional
Empirical coefficients used in the power model. Length 6. If `k` is
not provided, `cell_type` must be specified.
cell_type : str, optional
If provided, must be one of `'cSi'`, `'CIS'`, or `'CdTe'`. Used to look
up default values for `k` if `k` is not specified.

Returns
-------
pdc: numeric
DC power. [W]

Raises
------
ValueError
If neither `k` nor `cell_type` are specified.

References
----------
.. [1] T. Huld, G. Friesen, A. Skoczek, R. Kenny, T. Sample, M. Field,
E. Dunlop. A power-rating model for crystalline silicon PV modules.
Solar Energy Materials and Solar Cells 95, (2011), pp. 3359-3369.
:doi:`10.1016/j.solmat.2011.07.026`.
"""
if k is None:
if cell_type is not None:
k = _infer_k_huld(cell_type)
else:
raise ValueError('Either k or cell_type must be specified')

gprime = effective_irradiance / 1000
tprime = temp_mod - 25
# Eq. 1 in [1]
pdc = gprime * (pdc0 + k[0] * np.log(gprime) + k[1] * np.log(gprime)**2 +
k[2] * tprime + k[3] * tprime * np.log(gprime) +
k[4] * tprime * np.log(gprime)**2 + k[5] * tprime**2)
return pdc


def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2,
connections=0.5, lid=1.5, nameplate_rating=1, age=0,
availability=3):
Expand Down
22 changes: 22 additions & 0 deletions pvlib/tests/test_pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -2549,3 +2549,25 @@ def test_Array_temperature_missing_parameters(model, keys):
array.temperature_model_parameters = params
with pytest.raises(KeyError, match=match):
array.get_cell_temperature(irrads, temps, winds, model)


def test_huld():
pdc0 = 100
res = pvsystem.huld(1000, 25, pdc0, cell_type='cSi')
assert np.isclose(res, pdc0)
exp_sum = np.exp(1) * (np.sum(pvsystem._infer_k_huld('cSi')) + pdc0)
res = pvsystem.huld(1000*np.exp(1), 26, pdc0, cell_type='cSi')
assert np.isclose(res, exp_sum)
res = pvsystem.huld(100, 30, pdc0, k=(1, 1, 1, 1, 1, 1))
exp_100 = 0.1 * (pdc0 + np.log(0.1) + np.log(0.1)**2 + + 5 + 5*np.log(0.1)
+ 5*np.log(0.1)**2 + 25)
assert np.isclose(res, exp_100)
# Series input
eff_irr = pd.Series([1000, 100])
tm = pd.Series([25, 30])
expected = pd.Series([pdc0, exp_100])
res = pvsystem.huld(eff_irr, tm, pdc0, k=(1, 1, 1, 1, 1, 1))
assert_allclose(res, expected)
with pytest.raises(ValueError,
match='Either k or cell_type must be specified'):
res = pvsystem.huld(1000, 25, 100)