From 8f82b100cca358d4e97719bc21c0474d38ef02a1 Mon Sep 17 00:00:00 2001 From: Muhammad Rebaal <122050424+Muhammad-Rebaal@users.noreply.github.com> Date: Fri, 21 Mar 2025 20:53:24 +0500 Subject: [PATCH 1/5] Enhanced the Software with Semi-Integration --- tests/test_semi_integration.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/test_semi_integration.py diff --git a/tests/test_semi_integration.py b/tests/test_semi_integration.py new file mode 100644 index 0000000000..77ffaeccb9 --- /dev/null +++ b/tests/test_semi_integration.py @@ -0,0 +1,27 @@ +import numpy as np +from pvlib import temperature +from pvlib import pvsystem + +# Get the pvsyst_cell function directly +from pvlib.temperature import pvsyst_cell + + +def test_pvsyst_cell_semi_integrated(): + """Test semi-integrated PVsyst cell temperature model.""" + poa = 1000 # W/m^2 + temp_air = 25 # °C + wind_speed = 1 # m/s + + # Test with default parameters for semi_integrated + result = pvsyst_cell(poa, temp_air, wind_speed, u_c=20.0, u_v=0.0) + expected = temp_air + ((poa * 0.9 * (1 - 0.1)) / (20.0 + 0.0 * wind_speed)) + assert np.isclose(result, expected) + + # Test with temperature.pvsyst_cell wrapper + temp_params = {'u_c': 20.0, 'u_v': 0.0} + mount = pvsystem.FixedMount(surface_tilt=30, surface_azimuth=180, + racking_model='semi_integrated') + array = pvsystem.Array(mount=mount, module_type='glass_glass', + temperature_model_parameters=temp_params) + result = array.get_cell_temperature(poa, temp_air, wind_speed, 'pvsyst') + assert np.isclose(result, expected) \ No newline at end of file From 8ebab014128779a5b16f91ba5278d69c9610c6d1 Mon Sep 17 00:00:00 2001 From: Muhammad Rebaal <122050424+Muhammad-Rebaal@users.noreply.github.com> Date: Sat, 22 Mar 2025 00:46:13 +0500 Subject: [PATCH 2/5] Enhancement Changes Updated --- pvlib/pvsystem.py | 13 +++++++------ pvlib/temperature.py | 13 ++++++++++++- tests/test_pvsystem.py | 18 ++++++++++++++++++ tests/test_semi_integration.py | 27 --------------------------- 4 files changed, 37 insertions(+), 34 deletions(-) delete mode 100644 tests/test_semi_integration.py diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index b762372ae7..783d2541b0 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -1008,10 +1008,13 @@ def _infer_temperature_model_params(self): return temperature._temperature_model_params('sapm', param_set) elif 'freestanding' in param_set: return temperature._temperature_model_params('pvsyst', - 'freestanding') + 'freestanding') elif 'insulated' in param_set: # after SAPM to avoid confusing keys return temperature._temperature_model_params('pvsyst', - 'insulated') + 'insulated') + elif 'semi_integrated' in param_set: # Add this condition + return temperature._temperature_model_params('pvsyst', + 'semi_integrated') else: return {} @@ -1395,12 +1398,10 @@ class FixedMount(AbstractMount): West=270. [degrees] racking_model : str, optional - Valid strings are ``'open_rack'``, ``'close_mount'``, - ``'insulated_back'``, ``'freestanding'`` and ``'insulated'``. + Valid strings are 'open_rack', 'close_mount', 'insulated_back', + 'freestanding', 'insulated', and 'semi_integrated'. Used to identify a parameter set for the SAPM or PVsyst cell temperature model. - See :py:func:`~pvlib.temperature.sapm_module` and - :py:func:`~pvlib.temperature.pvsyst_cell` for definitions. module_height : float, optional The height above ground of the center of the module [m]. Used for diff --git a/pvlib/temperature.py b/pvlib/temperature.py index ab31ffaf56..b30ba1c531 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -21,7 +21,8 @@ 'insulated_back_glass_polymer': {'a': -2.81, 'b': -.0455, 'deltaT': 0}, }, 'pvsyst': {'freestanding': {'u_c': 29.0, 'u_v': 0}, - 'insulated': {'u_c': 15.0, 'u_v': 0}} + 'insulated': {'u_c': 15.0, 'u_v': 0}, + 'semi_integrated': {'u_c': 20.0, 'u_v': 0}} } """Dictionary of temperature parameters organized by model. @@ -365,6 +366,16 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0, alpha_absorption : numeric, default 0.9 Absorption coefficient. Parameter :math:`\alpha` in :eq:`pvsyst`. + freestanding : Uc = 29 W/(m^2*C), Uv = 0 W/(m^2*C*m/s) + + insulated : Uc = 15 W/(m^2*C), Uv = 0 W/(m^2*C*m/s) + + semi_integrated : Uc = 20 W/(m^2*C), Uv = 0 W/(m^2*C*m/s) + (for roof mounted systems with air flow beneath modules) + + PVUSA : Uc = 25 W/(m^2*C), Uv = 1.2 W/(m^2*C*m/s) + + Returns ------- numeric, values in degrees Celsius diff --git a/tests/test_pvsystem.py b/tests/test_pvsystem.py index ebd015d348..9735e11504 100644 --- a/tests/test_pvsystem.py +++ b/tests/test_pvsystem.py @@ -2504,3 +2504,21 @@ 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_pvsyst_semi_integrated_params(): + """Test that semi_integrated racking model correctly gets PVsyst parameters.""" + # Create a mount with semi_integrated racking model + mount = pvsystem.FixedMount(surface_tilt=30, surface_azimuth=180, + racking_model='semi_integrated') + + # Create an array with this mount + array = pvsystem.Array(mount=mount, module_type='glass_glass') + + # Get the inferred temperature model parameters + params = array._infer_temperature_model_params() + + # Check that the correct parameters were returned + assert 'u_c' in params + assert 'u_v' in params + assert params['u_c'] == 20.0 + assert params['u_v'] == 0.0 \ No newline at end of file diff --git a/tests/test_semi_integration.py b/tests/test_semi_integration.py deleted file mode 100644 index 77ffaeccb9..0000000000 --- a/tests/test_semi_integration.py +++ /dev/null @@ -1,27 +0,0 @@ -import numpy as np -from pvlib import temperature -from pvlib import pvsystem - -# Get the pvsyst_cell function directly -from pvlib.temperature import pvsyst_cell - - -def test_pvsyst_cell_semi_integrated(): - """Test semi-integrated PVsyst cell temperature model.""" - poa = 1000 # W/m^2 - temp_air = 25 # °C - wind_speed = 1 # m/s - - # Test with default parameters for semi_integrated - result = pvsyst_cell(poa, temp_air, wind_speed, u_c=20.0, u_v=0.0) - expected = temp_air + ((poa * 0.9 * (1 - 0.1)) / (20.0 + 0.0 * wind_speed)) - assert np.isclose(result, expected) - - # Test with temperature.pvsyst_cell wrapper - temp_params = {'u_c': 20.0, 'u_v': 0.0} - mount = pvsystem.FixedMount(surface_tilt=30, surface_azimuth=180, - racking_model='semi_integrated') - array = pvsystem.Array(mount=mount, module_type='glass_glass', - temperature_model_parameters=temp_params) - result = array.get_cell_temperature(poa, temp_air, wind_speed, 'pvsyst') - assert np.isclose(result, expected) \ No newline at end of file From b20fb3818cf73d93bb6ef9445df3f869be711858 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Wed, 7 May 2025 08:16:32 -0400 Subject: [PATCH 3/5] cleanup --- pvlib/pvsystem.py | 15 +++++++++------ pvlib/temperature.py | 30 +++++++++++------------------- tests/test_pvsystem.py | 25 +++++++------------------ 3 files changed, 27 insertions(+), 43 deletions(-) diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 783d2541b0..b37838a07a 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -1008,13 +1008,13 @@ def _infer_temperature_model_params(self): return temperature._temperature_model_params('sapm', param_set) elif 'freestanding' in param_set: return temperature._temperature_model_params('pvsyst', - 'freestanding') + 'freestanding') elif 'insulated' in param_set: # after SAPM to avoid confusing keys return temperature._temperature_model_params('pvsyst', - 'insulated') - elif 'semi_integrated' in param_set: # Add this condition + 'insulated') + elif 'semi_integrated' in param_set: return temperature._temperature_model_params('pvsyst', - 'semi_integrated') + 'semi_integrated') else: return {} @@ -1398,10 +1398,13 @@ class FixedMount(AbstractMount): West=270. [degrees] racking_model : str, optional - Valid strings are 'open_rack', 'close_mount', 'insulated_back', - 'freestanding', 'insulated', and 'semi_integrated'. + Valid strings are ``'open_rack'``, ``'close_mount'``, + ``'insulated_back'``, ``'freestanding'``, ``'insulated'`` and + ``'semi_integrated'``. Used to identify a parameter set for the SAPM or PVsyst cell temperature model. + See :py:func:`~pvlib.temperature.sapm_module` and + :py:func:`~pvlib.temperature.pvsyst_cell` for definitions. module_height : float, optional The height above ground of the center of the module [m]. Used for diff --git a/pvlib/temperature.py b/pvlib/temperature.py index b30ba1c531..908305d475 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -366,16 +366,6 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0, alpha_absorption : numeric, default 0.9 Absorption coefficient. Parameter :math:`\alpha` in :eq:`pvsyst`. - freestanding : Uc = 29 W/(m^2*C), Uv = 0 W/(m^2*C*m/s) - - insulated : Uc = 15 W/(m^2*C), Uv = 0 W/(m^2*C*m/s) - - semi_integrated : Uc = 20 W/(m^2*C), Uv = 0 W/(m^2*C*m/s) - (for roof mounted systems with air flow beneath modules) - - PVUSA : Uc = 25 W/(m^2*C), Uv = 1.2 W/(m^2*C*m/s) - - Returns ------- numeric, values in degrees Celsius @@ -393,19 +383,21 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0, air temperature :math:`T_{a}` (C) and wind speed :math:`WS` (m/s). Model output is cell temperature :math:`T_{C}`. Model parameters depend both on the module construction and its mounting. Parameters are provided in - [1]_ for open (freestanding) and close (insulated) mounting configurations, - , and are coded for convenience in + [1]_ for open (freestanding), close (insulated), and intermediate + (semi_integrate) mounting configurations, and are coded for convenience in :data:`~pvlib.temperature.TEMPERATURE_MODEL_PARAMETERS`. The heat loss factors provided represent the combined effect of convection, radiation and conduction, and their values are experimentally determined. - +--------------+---------------+---------------+ - | Mounting | :math:`U_{c}` | :math:`U_{v}` | - +==============+===============+===============+ - | freestanding | 29.0 | 0.0 | - +--------------+---------------+---------------+ - | insulated | 15.0 | 0.0 | - +--------------+---------------+---------------+ + +-----------------+---------------+---------------+ + | Mounting | :math:`U_{c}` | :math:`U_{v}` | + +=================+===============+===============+ + | freestanding | 29.0 | 0.0 | + +-----------------+---------------+---------------+ + | insulated | 15.0 | 0.0 | + +-----------------+---------------+---------------+ + | semi_integrated | 20.0 | 0.0 | + +-----------------+---------------+---------------+ Mounting cases can be described in terms of air flow across and around the rear-facing surface of the module: diff --git a/tests/test_pvsystem.py b/tests/test_pvsystem.py index 9735e11504..93965356a4 100644 --- a/tests/test_pvsystem.py +++ b/tests/test_pvsystem.py @@ -702,6 +702,13 @@ def test_Array__infer_temperature_model_params(): expected = temperature.TEMPERATURE_MODEL_PARAMETERS[ 'pvsyst']['insulated'] assert expected == array._infer_temperature_model_params() + array = pvsystem.Array(mount=FixedMount(0, 180, + racking_model='semi_integrated'), + module_parameters={}, + module_type=None) + expected = temperature.TEMPERATURE_MODEL_PARAMETERS[ + 'pvsyst']['semi_integrated'] + assert expected == array._infer_temperature_model_params() def test_Array__infer_cell_type(): @@ -2504,21 +2511,3 @@ 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_pvsyst_semi_integrated_params(): - """Test that semi_integrated racking model correctly gets PVsyst parameters.""" - # Create a mount with semi_integrated racking model - mount = pvsystem.FixedMount(surface_tilt=30, surface_azimuth=180, - racking_model='semi_integrated') - - # Create an array with this mount - array = pvsystem.Array(mount=mount, module_type='glass_glass') - - # Get the inferred temperature model parameters - params = array._infer_temperature_model_params() - - # Check that the correct parameters were returned - assert 'u_c' in params - assert 'u_v' in params - assert params['u_c'] == 20.0 - assert params['u_v'] == 0.0 \ No newline at end of file From 42835bb5961c61b5fb990b4360a688344515468c Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Wed, 7 May 2025 08:19:01 -0400 Subject: [PATCH 4/5] whatsnew --- docs/sphinx/source/whatsnew/v0.12.1.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/sphinx/source/whatsnew/v0.12.1.rst b/docs/sphinx/source/whatsnew/v0.12.1.rst index 88cdfc6848..44cee7c1da 100644 --- a/docs/sphinx/source/whatsnew/v0.12.1.rst +++ b/docs/sphinx/source/whatsnew/v0.12.1.rst @@ -30,6 +30,8 @@ Enhancements :py:func:`~pvlib.iotools.get_nsrdb_psm4_full_disc`, :py:func:`~pvlib.iotools.read_nsrdb_psm4`, and :py:func:`~pvlib.iotools.parse_nsrdb_psm4`. (:issue:`2326`, :pull:`2378`) +* Add ``'semi_integrated'`` parameters for the PVsyst temperature model. + (:issue:`2330`, :pull:`2415`) Documentation ~~~~~~~~~~~~~ @@ -62,3 +64,4 @@ Contributors * Will Hobbs (:ghuser:`williamhobbs`) * Kevin Anderson (:ghuser:`kandersolar`) * Will Holmgren (:ghuser:`wholmgren`) +* Muhammad Rebaal (:ghuser:`Muhammad-Rebaal`) From dff2daf8d6e2b98cc7c3c900c06fa5487430bf59 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Wed, 7 May 2025 08:23:06 -0400 Subject: [PATCH 5/5] bit more cleanup --- pvlib/pvsystem.py | 5 +++-- pvlib/temperature.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 9669e05a8b..a1d93bd59e 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -1397,7 +1397,7 @@ class FixedMount(AbstractMount): racking_model : str, optional Valid strings are ``'open_rack'``, ``'close_mount'``, - ``'insulated_back'``, ``'freestanding'``, ``'insulated'`` and + ``'insulated_back'``, ``'freestanding'``, ``'insulated'``, and ``'semi_integrated'``. Used to identify a parameter set for the SAPM or PVsyst cell temperature model. @@ -1479,7 +1479,8 @@ class SingleAxisTrackerMount(AbstractMount): racking_model : str, optional Valid strings are ``'open_rack'``, ``'close_mount'``, - ``'insulated_back'``, ``'freestanding'`` and ``'insulated'``. + ``'insulated_back'``, ``'freestanding'``, ``'insulated'``, and + ``'semi_integrated'``. Used to identify a parameter set for the SAPM or PVsyst cell temperature model. ``'open_rack'`` or ``'freestanding'`` should be used for systems with single-axis trackers. diff --git a/pvlib/temperature.py b/pvlib/temperature.py index 908305d475..6c274d79b7 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -384,7 +384,7 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0, output is cell temperature :math:`T_{C}`. Model parameters depend both on the module construction and its mounting. Parameters are provided in [1]_ for open (freestanding), close (insulated), and intermediate - (semi_integrate) mounting configurations, and are coded for convenience in + (semi_integrated) mounting configurations, and are coded for convenience in :data:`~pvlib.temperature.TEMPERATURE_MODEL_PARAMETERS`. The heat loss factors provided represent the combined effect of convection, radiation and conduction, and their values are experimentally determined.