From 54dcae158ecf90253b80feafaaa492908d02fa13 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Thu, 17 Nov 2022 17:26:38 +0100 Subject: [PATCH 01/12] New faiman_rad function. No tests yet. --- pvlib/temperature.py | 93 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index e52032f6ec..3a8c904d62 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -457,6 +457,99 @@ def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84): return temp_air + temp_difference +def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=0.0, + u0=25.0, u1=6.84, emissivity=0.88, sky_view=1.0): + r''' + Calculate cell or module temperature using the Faiman model augmented + with a radiative loss term. + + The Faiman model uses an empirical heat loss factor model [1]_ and is + adopted in the IEC 61853 standards [2]_ and [3]_. The radiative loss + term was developed in [4]_. + + Usage of this model in the IEC 61853 standard does not distinguish + between cell and module temperature. + + Parameters + ---------- + poa_global : numeric + Total incident irradiance [W/m^2]. + + temp_air : numeric + Ambient dry bulb temperature [C]. + + wind_speed : numeric, default 1.0 + Wind speed in m/s measured at the same height for which the wind loss + factor was determined. The default value 1.0 m/s is the wind + speed at module height used to determine NOCT. [m/s] + + ir_down : numeric, default 0.0 + Downwelling infrared radiation from the sky, measured on a horizontal + surface. [W/m^2] + + u0 : numeric, default 25.0 + Combined heat loss factor coefficient. The default value is one + determined by Faiman for 7 silicon modules. + :math:`\left[\frac{\text{W}/{\text{m}^2}}{\text{C}}\right]` + + u1 : numeric, default 6.84 + Combined heat loss factor influenced by wind. The default value is one + determined by Faiman for 7 silicon modules. + :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` + + emissivity : numeric, default 0.88 + Infrared emissivity of the module surface facing the sky. [-] + + sky_view : numeric, default 1.0 + Effective view factor limiting the radiative exchange between the + module and the sky. [-] + + Returns + ------- + numeric, values in degrees Celsius + + Notes + ----- + All arguments may be scalars or vectors. If multiple arguments + are vectors they must be the same length. + + References + ---------- + .. [1] Faiman, D. (2008). "Assessing the outdoor operating temperature of + photovoltaic modules." Progress in Photovoltaics 16(4): 307-315. + + .. [2] "IEC 61853-2 Photovoltaic (PV) module performance testing and energy + rating - Part 2: Spectral responsivity, incidence angle and module + operating temperature measurements". IEC, Geneva, 2018. + + .. [3] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy + rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. + + .. [4] Driesse, A. et al (2022) "Improving Common PV Module Temperature + Models by Incorporating Radiative Losses to the Sky". SAND2022-11604. + + ''' + # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Nov., 2022 + + # The following lines may seem odd since the values are probably scalar, + # but they serve an indirect and easy way of allowing lists and + # tuples for the other function arguments. + u0 = np.asanyarray(u0) + u1 = np.asanyarray(u1) + emissivity = np.asanyarray(emissivity) + + t_zero = np.array(-273.15) + kstefbolz = np.array(5.670367e-8) + + ir_up = kstefbolz * ((temp_air - t_zero)**4) + qrad_sky = emissivity * sky_view * (ir_up - ir_down) + + heat_input = poa_global - qrad_sky + total_loss_factor = u0 + u1 * wind_speed + temp_difference = heat_input / total_loss_factor + return temp_air + temp_difference + + def ross(poa_global, temp_air, noct): r''' Calculate cell temperature using the Ross model. From c05591300329ba181b849487f881d2c18649e9e1 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Sun, 20 Nov 2022 11:23:32 +0100 Subject: [PATCH 02/12] Adjust arguments and default behaviour. --- pvlib/temperature.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index 3a8c904d62..aca533fd92 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -457,8 +457,8 @@ def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84): return temp_air + temp_difference -def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=0.0, - u0=25.0, u1=6.84, emissivity=0.88, sky_view=1.0): +def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, + u0=25.0, u1=6.84, sky_view=1.0, emissivity=0.88): r''' Calculate cell or module temperature using the Faiman model augmented with a radiative loss term. @@ -533,7 +533,7 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=0.0, # The following lines may seem odd since the values are probably scalar, # but they serve an indirect and easy way of allowing lists and - # tuples for the other function arguments. + # tuples for the other function arguments, and providing Series output. u0 = np.asanyarray(u0) u1 = np.asanyarray(u1) emissivity = np.asanyarray(emissivity) @@ -541,8 +541,11 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=0.0, t_zero = np.array(-273.15) kstefbolz = np.array(5.670367e-8) - ir_up = kstefbolz * ((temp_air - t_zero)**4) - qrad_sky = emissivity * sky_view * (ir_up - ir_down) + if ir_down is None: + qrad_sky = np.array(0.0) + else: + ir_up = kstefbolz * ((temp_air - t_zero)**4) + qrad_sky = emissivity * sky_view * (ir_up - ir_down) heat_input = poa_global - qrad_sky total_loss_factor = u0 + u1 * wind_speed From 2608b8d90d25606526ff658153be09f00dd482c9 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Tue, 22 Nov 2022 16:35:00 +0100 Subject: [PATCH 03/12] Improve doc string, add tests, fix some old tests. --- pvlib/temperature.py | 18 ++++++++++++------ pvlib/tests/test_temperature.py | 28 ++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index aca533fd92..bfd14cf950 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -467,8 +467,7 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, adopted in the IEC 61853 standards [2]_ and [3]_. The radiative loss term was developed in [4]_. - Usage of this model in the IEC 61853 standard does not distinguish - between cell and module temperature. + The model can be used to represent cell or module temperature. Parameters ---------- @@ -497,12 +496,16 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, determined by Faiman for 7 silicon modules. :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` - emissivity : numeric, default 0.88 - Infrared emissivity of the module surface facing the sky. [-] - sky_view : numeric, default 1.0 Effective view factor limiting the radiative exchange between the - module and the sky. [-] + module and the sky. For a tilted array the expressions + (1 + 3*cos(tilt)) / 4 can be used as a first estimate for sky_view + as discussed in [4]_. The default value is for a horizontal module. [-] + + emissivity : numeric, default 0.88 + Infrared emissivity of the module surface facing the sky. The default + value represents the middle of a range of values found in the + literature. [-] Returns ------- @@ -513,6 +516,9 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, All arguments may be scalars or vectors. If multiple arguments are vectors they must be the same length. + If the input `ir_down` is not supplied the model output is the same as the + original Faiman model. + References ---------- .. [1] Faiman, D. (2008). "Assessing the outdoor operating temperature of diff --git a/pvlib/tests/test_temperature.py b/pvlib/tests/test_temperature.py index 5e36714d12..848555d1eb 100644 --- a/pvlib/tests/test_temperature.py +++ b/pvlib/tests/test_temperature.py @@ -108,12 +108,12 @@ def test_pvsyst_cell_eta_m_deprecated(): def test_faiman_default(): result = temperature.faiman(900, 20, 5) - assert_allclose(result, 35.203, 0.001) + assert_allclose(result, 35.203, atol=0.001) def test_faiman_kwargs(): result = temperature.faiman(900, 20, wind_speed=5.0, u0=22.0, u1=6.) - assert_allclose(result, 37.308, 0.001) + assert_allclose(result, 37.308, atol=0.001) def test_faiman_list(): @@ -122,7 +122,7 @@ def test_faiman_list(): winds = [10, 5, 0] result = temperature.faiman(irrads, temps, wind_speed=winds) expected = np.array([0.0, 18.446, 5.0]) - assert_allclose(expected, result, 3) + assert_allclose(expected, result, atol=0.001) def test_faiman_ndarray(): @@ -131,7 +131,27 @@ def test_faiman_ndarray(): winds = np.array([10, 5, 0]) result = temperature.faiman(irrads, temps, wind_speed=winds) expected = np.array([0.0, 18.446, 5.0]) - assert_allclose(expected, result, 3) + assert_allclose(expected, result, atol=0.001) + + +def test_faiman_rad_no_ir(): + result = temperature.faiman_rad(900, 20, 5, ir_down=None) + assert_allclose(result, 35.203, atol=0.001) + + +def test_faiman_rad_ir(): + ir_down = [0, 100, 200, 315.6574, 400] + expected = [-11.111, -7.591, -4.071, -0.000, 2.969] + result = temperature.faiman_rad(0, 0, 0, ir_down) + assert_allclose(result, expected, atol=0.001) + + sky_view = [1.0, 0.5, 0.0] + expected = [-4.071, -2.036, 0.000] + result = temperature.faiman_rad(0, 0, 0, ir_down=200, sky_view=sky_view) + + emissivity = [1.0, 0.88, 0.5, 0.0] + expected = [-4.626, -4.071, -2.313, 0.000] + result = temperature.faiman_rad(0, 0, 0, ir_down=200, emissivity=emissivity) def test_ross(): From 176f91758ad162ccc6c6016708668d6841d697a8 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Tue, 22 Nov 2022 20:57:49 +0100 Subject: [PATCH 04/12] Update pvlib/temperature.py Co-authored-by: Cliff Hansen --- pvlib/temperature.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index bfd14cf950..758bc15165 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -478,7 +478,7 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, Ambient dry bulb temperature [C]. wind_speed : numeric, default 1.0 - Wind speed in m/s measured at the same height for which the wind loss + Wind speed measured at the same height for which the wind loss factor was determined. The default value 1.0 m/s is the wind speed at module height used to determine NOCT. [m/s] From 04a5827c8066087a1af44c47e49fc12cdc9da165 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Tue, 22 Nov 2022 21:29:14 +0100 Subject: [PATCH 05/12] Minor improvements here and there. --- pvlib/temperature.py | 16 +++++++--------- pvlib/tests/test_temperature.py | 13 +++++++++---- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index 758bc15165..c16f4a6525 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -419,7 +419,7 @@ def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84): u1 : numeric, default 6.84 Combined heat loss factor influenced by wind. The default value is one determined by Faiman for 7 silicon modules. - :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` + :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` # noQA: E501 Returns ------- @@ -494,18 +494,19 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, u1 : numeric, default 6.84 Combined heat loss factor influenced by wind. The default value is one determined by Faiman for 7 silicon modules. - :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` + :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` # noQA: E501 sky_view : numeric, default 1.0 Effective view factor limiting the radiative exchange between the module and the sky. For a tilted array the expressions (1 + 3*cos(tilt)) / 4 can be used as a first estimate for sky_view - as discussed in [4]_. The default value is for a horizontal module. [-] + as discussed in [4]_. The default value is for a horizontal module. + [unitless] emissivity : numeric, default 0.88 Infrared emissivity of the module surface facing the sky. The default value represents the middle of a range of values found in the - literature. [-] + literature. [unitless] Returns ------- @@ -537,20 +538,17 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, ''' # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Nov., 2022 - # The following lines may seem odd since the values are probably scalar, - # but they serve an indirect and easy way of allowing lists and - # tuples for the other function arguments, and providing Series output. u0 = np.asanyarray(u0) u1 = np.asanyarray(u1) emissivity = np.asanyarray(emissivity) - t_zero = np.array(-273.15) + abs_zero = np.array(-273.15) kstefbolz = np.array(5.670367e-8) if ir_down is None: qrad_sky = np.array(0.0) else: - ir_up = kstefbolz * ((temp_air - t_zero)**4) + ir_up = kstefbolz * ((temp_air - abs_zero)**4) qrad_sky = emissivity * sky_view * (ir_up - ir_down) heat_input = poa_global - qrad_sky diff --git a/pvlib/tests/test_temperature.py b/pvlib/tests/test_temperature.py index 848555d1eb..5dfb1e777e 100644 --- a/pvlib/tests/test_temperature.py +++ b/pvlib/tests/test_temperature.py @@ -135,8 +135,9 @@ def test_faiman_ndarray(): def test_faiman_rad_no_ir(): - result = temperature.faiman_rad(900, 20, 5, ir_down=None) - assert_allclose(result, 35.203, atol=0.001) + expected = temperature.faiman(900, 20, 5) + result = temperature.faiman_rad(900, 20, 5) + assert_allclose(result, expected) def test_faiman_rad_ir(): @@ -147,11 +148,15 @@ def test_faiman_rad_ir(): sky_view = [1.0, 0.5, 0.0] expected = [-4.071, -2.036, 0.000] - result = temperature.faiman_rad(0, 0, 0, ir_down=200, sky_view=sky_view) + result = temperature.faiman_rad(0, 0, 0, ir_down=200, + sky_view=sky_view) + assert_allclose(result, expected, atol=0.001) emissivity = [1.0, 0.88, 0.5, 0.0] expected = [-4.626, -4.071, -2.313, 0.000] - result = temperature.faiman_rad(0, 0, 0, ir_down=200, emissivity=emissivity) + result = temperature.faiman_rad(0, 0, 0, ir_down=200, + emissivity=emissivity) + assert_allclose(result, expected, atol=0.001) def test_ross(): From 110299b72c4616889fdc614d5c9cdef617c235e5 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Tue, 29 Nov 2022 17:48:34 +0100 Subject: [PATCH 06/12] Add entry in pv_modeling.rst --- docs/sphinx/source/reference/pv_modeling.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sphinx/source/reference/pv_modeling.rst b/docs/sphinx/source/reference/pv_modeling.rst index 31c380c1bb..381b4cead2 100644 --- a/docs/sphinx/source/reference/pv_modeling.rst +++ b/docs/sphinx/source/reference/pv_modeling.rst @@ -40,6 +40,7 @@ PV temperature models temperature.sapm_cell_from_module temperature.pvsyst_cell temperature.faiman + temperature.faiman_rad temperature.fuentes temperature.ross temperature.noct_sam From a51f840ddd6c6d8d8d8786bd294e8aa4308c0d55 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Thu, 1 Dec 2022 22:17:08 +0100 Subject: [PATCH 07/12] Update whatsnew and touch up doc strings. --- docs/sphinx/source/whatsnew/v0.9.4.rst | 11 ++++++++--- pvlib/temperature.py | 26 ++++++++++++++++---------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/sphinx/source/whatsnew/v0.9.4.rst b/docs/sphinx/source/whatsnew/v0.9.4.rst index 8a67c201f0..893d5a51f0 100644 --- a/docs/sphinx/source/whatsnew/v0.9.4.rst +++ b/docs/sphinx/source/whatsnew/v0.9.4.rst @@ -13,9 +13,12 @@ Enhancements * Added a function to calculate one of GHI, DHI, and DNI from values of the other two. :py:func:`~pvlib.irradiance.complete_irradiance` (:issue:`1565`, :pull:`1567`) -* Add optional ``return_components`` parameter to :py:func:`pvlib.irradiance.haydavies` to return +* Added optional ``return_components`` parameter to :py:func:`pvlib.irradiance.haydavies` to return individual diffuse irradiance components (:issue:`1553`, :pull:`1568`) - +* Added a module temperature model that accounts for radiative losses to the sky + in a simplified way, using the Faiman model as an example. + :py:func:`~pvlib.temperature.faiman_rad` + (:issue:`1594`, :pull:`1595`) Bug fixes ~~~~~~~~~ @@ -35,7 +38,6 @@ Benchmarking ~~~~~~~~~~~~~ * Removed ``time_tracker_singleaxis`` function from tracking.py (:issue:`1508`, :pull:`1535`) - Requirements ~~~~~~~~~~~~ @@ -48,3 +50,6 @@ Contributors * Marcus Boumans (:ghuser:`bowie2211`) * Karel De Brabandere (:ghuser:`kdebrab`) * Naman Priyadarshi (:ghuser:`Naman-Priyadarshi`) +* Anton Driesse (:ghuser:`adriesse`) +* Cliff Hansen (:ghuser:`cwhanse`) +* Kevin Anderson (:ghuser:`kanderso-nrel`) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index c16f4a6525..2b9e87ad63 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -318,7 +318,7 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0, u_v : float, default 0.0 Combined heat loss factor influenced by wind. Parameter :math:`U_{v}` in :eq:`pvsyst`. - :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` # noQA: E501 + :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` eta_m : numeric, default None (deprecated, use module_efficiency instead) @@ -375,7 +375,7 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0, >>> params = TEMPERATURE_MODEL_PARAMETERS['pvsyst']['freestanding'] >>> pvsyst_cell(1000, 10, **params) 37.93103448275862 - """ + """ # noQA: E501 if eta_m: warn_deprecated( @@ -413,12 +413,14 @@ def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84): u0 : numeric, default 25.0 Combined heat loss factor coefficient. The default value is one - determined by Faiman for 7 silicon modules. + determined by Faiman for 7 silicon modules + in the Negev desert on an open rack at 30.9° tilt. :math:`\left[\frac{\text{W}/{\text{m}^2}}{\text{C}}\right]` u1 : numeric, default 6.84 Combined heat loss factor influenced by wind. The default value is one - determined by Faiman for 7 silicon modules. + determined by Faiman for 7 silicon modules + in the Negev desert on an open rack at 30.9° tilt. :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` # noQA: E501 Returns @@ -488,13 +490,15 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, u0 : numeric, default 25.0 Combined heat loss factor coefficient. The default value is one - determined by Faiman for 7 silicon modules. + determined by Faiman for 7 silicon modules + in the Negev desert on an open rack at 30.9° tilt. :math:`\left[\frac{\text{W}/{\text{m}^2}}{\text{C}}\right]` u1 : numeric, default 6.84 Combined heat loss factor influenced by wind. The default value is one - determined by Faiman for 7 silicon modules. - :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` # noQA: E501 + determined by Faiman for 7 silicon modules + in the Negev desert on an open rack at 30.9° tilt. + :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` sky_view : numeric, default 1.0 Effective view factor limiting the radiative exchange between the @@ -517,8 +521,9 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, All arguments may be scalars or vectors. If multiple arguments are vectors they must be the same length. - If the input `ir_down` is not supplied the model output is the same as the - original Faiman model. + If the input `ir_down` is `None` the model output is the same as the + original Faiman model. Setting `ir_down` to zero does not have the same + meaning; it leads to very high radiative loss and low module temperature. References ---------- @@ -535,7 +540,8 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, .. [4] Driesse, A. et al (2022) "Improving Common PV Module Temperature Models by Incorporating Radiative Losses to the Sky". SAND2022-11604. - ''' + ''' # noQA: E501 + # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Nov., 2022 u0 = np.asanyarray(u0) From ef05a731322fca765a21d54848e648b19b2fba36 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Thu, 1 Dec 2022 23:23:18 +0100 Subject: [PATCH 08/12] Enhance reference in doc string. --- pvlib/temperature.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index 2b9e87ad63..2ac435e8b6 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -467,7 +467,7 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, The Faiman model uses an empirical heat loss factor model [1]_ and is adopted in the IEC 61853 standards [2]_ and [3]_. The radiative loss - term was developed in [4]_. + term was proposed and developed by Driesse [4]_. The model can be used to represent cell or module temperature. From eafb272f6f23ffc52db50e28ece31f5585aac95b Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Fri, 2 Dec 2022 00:02:44 +0100 Subject: [PATCH 09/12] Add DOI. --- pvlib/temperature.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index 2ac435e8b6..e5e2d7cb41 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -539,7 +539,7 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, .. [4] Driesse, A. et al (2022) "Improving Common PV Module Temperature Models by Incorporating Radiative Losses to the Sky". SAND2022-11604. - + :doi:`10.2172/1884890` ''' # noQA: E501 # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Nov., 2022 From a6e93d072a64fbb30181aee0eb4396e6f780eb42 Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Fri, 2 Dec 2022 18:01:38 +0100 Subject: [PATCH 10/12] Finishing touches. --- docs/sphinx/source/whatsnew/v0.9.4.rst | 2 -- pvlib/temperature.py | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/sphinx/source/whatsnew/v0.9.4.rst b/docs/sphinx/source/whatsnew/v0.9.4.rst index 6d7b4e5773..684b704a73 100644 --- a/docs/sphinx/source/whatsnew/v0.9.4.rst +++ b/docs/sphinx/source/whatsnew/v0.9.4.rst @@ -59,6 +59,4 @@ Contributors * Karel De Brabandere (:ghuser:`kdebrab`) * Naman Priyadarshi (:ghuser:`Naman-Priyadarshi`) * Anton Driesse (:ghuser:`adriesse`) -* Cliff Hansen (:ghuser:`cwhanse`) -* Kevin Anderson (:ghuser:`kanderso-nrel`) * Echedey Luis (:ghuser:`echedey-ls`) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index e5e2d7cb41..0ba15258f5 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -421,7 +421,7 @@ def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84): Combined heat loss factor influenced by wind. The default value is one determined by Faiman for 7 silicon modules in the Negev desert on an open rack at 30.9° tilt. - :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` # noQA: E501 + :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` Returns ------- @@ -444,7 +444,8 @@ def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84): .. [3] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. - ''' + ''' # noQA: E501 + # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Dec., 2019 # The following lines may seem odd since u0 & u1 are probably scalar, From bd05c35597188748ff524380997992351f2990ed Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Tue, 6 Dec 2022 22:59:52 +0100 Subject: [PATCH 11/12] Address review comments. --- docs/sphinx/source/whatsnew/v0.9.4.rst | 2 +- pvlib/temperature.py | 31 +++++++++++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/docs/sphinx/source/whatsnew/v0.9.4.rst b/docs/sphinx/source/whatsnew/v0.9.4.rst index 791dcdd987..51de2f78ef 100644 --- a/docs/sphinx/source/whatsnew/v0.9.4.rst +++ b/docs/sphinx/source/whatsnew/v0.9.4.rst @@ -59,5 +59,5 @@ Contributors * Kevin Anderson (:ghuser:`kanderso-nrel`) * Karel De Brabandere (:ghuser:`kdebrab`) * Naman Priyadarshi (:ghuser:`Naman-Priyadarshi`) -* Anton Driesse (:ghuser:`adriesse`) +* Adam R. Jensen (:ghuser:`AdamRJensen`) * Echedey Luis (:ghuser:`echedey-ls`) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index 0ba15258f5..cd694f0c43 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -9,6 +9,7 @@ from pvlib._deprecation import warn_deprecated from pvlib.tools import _get_sample_intervals import scipy +import scipy.constants import warnings @@ -375,7 +376,7 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0, >>> params = TEMPERATURE_MODEL_PARAMETERS['pvsyst']['freestanding'] >>> pvsyst_cell(1000, 10, **params) 37.93103448275862 - """ # noQA: E501 + """ # noQA: E501 if eta_m: warn_deprecated( @@ -436,6 +437,7 @@ def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84): ---------- .. [1] Faiman, D. (2008). "Assessing the outdoor operating temperature of photovoltaic modules." Progress in Photovoltaics 16(4): 307-315. + :doi:`10.1002/pip.813` .. [2] "IEC 61853-2 Photovoltaic (PV) module performance testing and energy rating - Part 2: Spectral responsivity, incidence angle and module @@ -444,7 +446,11 @@ def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84): .. [3] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. - ''' # noQA: E501 + See also + -------- + pvlib.temperature.faiman_rad + + ''' # noQA: E501 # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Dec., 2019 @@ -522,14 +528,18 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, All arguments may be scalars or vectors. If multiple arguments are vectors they must be the same length. - If the input `ir_down` is `None` the model output is the same as the - original Faiman model. Setting `ir_down` to zero does not have the same - meaning; it leads to very high radiative loss and low module temperature. + When only irradiance, air temperature and wind speed inputs are provided + (`ir_down` is `None`) this function calculates the same device temperature + as the original faiman model. When down-welling long-wave radiation data + are provided as well (`ir_down` is not None) the default u0 and u1 values + from the original model should not be used because a portion of the + radiative losses would be double-counted. References ---------- .. [1] Faiman, D. (2008). "Assessing the outdoor operating temperature of photovoltaic modules." Progress in Photovoltaics 16(4): 307-315. + :doi:`10.1002/pip.813` .. [2] "IEC 61853-2 Photovoltaic (PV) module performance testing and energy rating - Part 2: Spectral responsivity, incidence angle and module @@ -541,7 +551,12 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, .. [4] Driesse, A. et al (2022) "Improving Common PV Module Temperature Models by Incorporating Radiative Losses to the Sky". SAND2022-11604. :doi:`10.2172/1884890` - ''' # noQA: E501 + + See also + -------- + pvlib.temperature.faiman + + ''' # noQA: E501 # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Nov., 2022 @@ -550,12 +565,12 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, emissivity = np.asanyarray(emissivity) abs_zero = np.array(-273.15) - kstefbolz = np.array(5.670367e-8) + sigma = np.array(scipy.constants.Stefan_Boltzmann) if ir_down is None: qrad_sky = np.array(0.0) else: - ir_up = kstefbolz * ((temp_air - abs_zero)**4) + ir_up = sigma * ((temp_air - abs_zero)**4) qrad_sky = emissivity * sky_view * (ir_up - ir_down) heat_input = poa_global - qrad_sky From bae186a251b4bd2aacdf16645b92e1f792eb5b1b Mon Sep 17 00:00:00 2001 From: Anton Driesse Date: Sun, 11 Dec 2022 21:37:20 +0100 Subject: [PATCH 12/12] Whatever it takes to get merged. --- pvlib/temperature.py | 10 +++------- pvlib/tests/test_temperature.py | 6 +++--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/pvlib/temperature.py b/pvlib/temperature.py index cd694f0c43..9748965ccd 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -560,15 +560,11 @@ def faiman_rad(poa_global, temp_air, wind_speed=1.0, ir_down=None, # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Nov., 2022 - u0 = np.asanyarray(u0) - u1 = np.asanyarray(u1) - emissivity = np.asanyarray(emissivity) - - abs_zero = np.array(-273.15) - sigma = np.array(scipy.constants.Stefan_Boltzmann) + abs_zero = -273.15 + sigma = scipy.constants.Stefan_Boltzmann if ir_down is None: - qrad_sky = np.array(0.0) + qrad_sky = 0.0 else: ir_up = sigma * ((temp_air - abs_zero)**4) qrad_sky = emissivity * sky_view * (ir_up - ir_down) diff --git a/pvlib/tests/test_temperature.py b/pvlib/tests/test_temperature.py index 5dfb1e777e..bd6831fd0a 100644 --- a/pvlib/tests/test_temperature.py +++ b/pvlib/tests/test_temperature.py @@ -141,18 +141,18 @@ def test_faiman_rad_no_ir(): def test_faiman_rad_ir(): - ir_down = [0, 100, 200, 315.6574, 400] + ir_down = np.array([0, 100, 200, 315.6574, 400]) expected = [-11.111, -7.591, -4.071, -0.000, 2.969] result = temperature.faiman_rad(0, 0, 0, ir_down) assert_allclose(result, expected, atol=0.001) - sky_view = [1.0, 0.5, 0.0] + sky_view = np.array([1.0, 0.5, 0.0]) expected = [-4.071, -2.036, 0.000] result = temperature.faiman_rad(0, 0, 0, ir_down=200, sky_view=sky_view) assert_allclose(result, expected, atol=0.001) - emissivity = [1.0, 0.88, 0.5, 0.0] + emissivity = np.array([1.0, 0.88, 0.5, 0.0]) expected = [-4.626, -4.071, -2.313, 0.000] result = temperature.faiman_rad(0, 0, 0, ir_down=200, emissivity=emissivity)