From dd2c0d869e3cf52c836d5baa2f80ea8b4cf2eb4c Mon Sep 17 00:00:00 2001 From: Chirag3841 Date: Wed, 26 Nov 2025 19:18:47 +0530 Subject: [PATCH 1/8] Add detailed docstrings for WEATHER_KEYS, POA_KEYS, and TEMPERATURE_KEYS --- pvlib/modelchain.py | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 09e4434e84..9096b1a637 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -22,20 +22,35 @@ # keys that are used to detect input data and assign data to appropriate # ModelChain attribute -# for ModelChain.weather -WEATHER_KEYS = ('ghi', 'dhi', 'dni', 'wind_speed', 'temp_air', - 'precipitable_water') -# for ModelChain.total_irrad -POA_KEYS = ('poa_global', 'poa_direct', 'poa_diffuse') +# For ModelChain.weather: +# Maps weather-related input columns to the weather DataFrame. +#: list[str]: Required or optional weather input columns. +WEATHER_KEYS = ( + 'ghi', # Global Horizontal Irradiance (W/m^2) + 'dhi', # Diffuse Horizontal Irradiance (W/m^2) + 'dni', # Direct Normal Irradiance (W/m^2) + 'wind_speed', # Wind speed (m/s) + 'temp_air', # Ambient air temperature (°C) + 'precipitable_water' # Column precipitable water (cm) +) -# Optional keys to communicate temperature data. If provided, -# 'cell_temperature' overrides ModelChain.temperature_model and sets -# ModelChain.cell_temperature to the data. If 'module_temperature' is provided, -# overrides ModelChain.temperature_model with -# pvlib.temperature.sapm_cell_from_module -TEMPERATURE_KEYS = ('module_temperature', 'cell_temperature') +# For ModelChain.total_irrad: +# Plane-of-array irradiance components. +#: list[str]: Required POA irradiance input columns. +POA_KEYS = ( + 'poa_global', # Total plane-of-array irradiance (W/m^2) + 'poa_direct', # Direct normal POA irradiance (W/m^2) + 'poa_diffuse' # Diffuse POA irradiance (W/m^2) +) +# Optional keys for temperature-specific inputs. +# These override or supplement temperature models. +#: list[str]: Temperature-related input columns. +TEMPERATURE_KEYS = ( + 'module_temperature', # Back-surface module temperature (°C) + 'cell_temperature', # Direct cell temperature input (°C) +) DATA_KEYS = WEATHER_KEYS + POA_KEYS + TEMPERATURE_KEYS # these dictionaries contain the default configuration for following From 25db27c3636015f1b01a69db349b730f074b344a Mon Sep 17 00:00:00 2001 From: Chirag3841 Date: Wed, 26 Nov 2025 20:03:02 +0530 Subject: [PATCH 2/8] Add detailed docstrings for WEATHER_KEYS, POA_KEYS, and TEMPERATURE_KEYS --- pvlib/modelchain.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 9096b1a637..5db0f1289d 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -19,13 +19,13 @@ from pvlib.tools import _build_kwargs from pvlib._deprecation import deprecated +# Keys used to detect input data and assign values to the appropriate +# ModelChain attributes. -# keys that are used to detect input data and assign data to appropriate -# ModelChain attribute - -# For ModelChain.weather: -# Maps weather-related input columns to the weather DataFrame. -#: list[str]: Required or optional weather input columns. +#: tuple[str] +#: Weather-related input columns used by :class:`ModelChain` to populate +#: ``ModelChain.weather``. Missing ``temp_air`` or ``wind_speed`` are +#: automatically filled (20 °C and 0 m/s). WEATHER_KEYS = ( 'ghi', # Global Horizontal Irradiance (W/m^2) 'dhi', # Diffuse Horizontal Irradiance (W/m^2) @@ -35,24 +35,26 @@ 'precipitable_water' # Column precipitable water (cm) ) -# For ModelChain.total_irrad: -# Plane-of-array irradiance components. -#: list[str]: Required POA irradiance input columns. +#: tuple[str] +#: Plane-of-array irradiance components used to populate +#: ``ModelChain.total_irrad`` when running from POA input. POA_KEYS = ( 'poa_global', # Total plane-of-array irradiance (W/m^2) - 'poa_direct', # Direct normal POA irradiance (W/m^2) + 'poa_direct', # Direct POA irradiance (W/m^2) 'poa_diffuse' # Diffuse POA irradiance (W/m^2) ) -# Optional keys for temperature-specific inputs. -# These override or supplement temperature models. -#: list[str]: Temperature-related input columns. +#: tuple[str] +#: Temperature-related input columns that override or supplement the +#: ModelChain temperature model. If ``cell_temperature`` is provided, +#: the temperature model is skipped. TEMPERATURE_KEYS = ( 'module_temperature', # Back-surface module temperature (°C) 'cell_temperature', # Direct cell temperature input (°C) ) +#: tuple[str] +#: All supported input keys recognized by ModelChain. DATA_KEYS = WEATHER_KEYS + POA_KEYS + TEMPERATURE_KEYS - # these dictionaries contain the default configuration for following # established modeling sequences. They can be used in combination with # ModelChain, particularly they are used by the methods From 4084889632f0943ee50fe06c76e2648362b687f6 Mon Sep 17 00:00:00 2001 From: Chirag3841 Date: Thu, 27 Nov 2025 13:29:59 +0530 Subject: [PATCH 3/8] Fixed indentation in run_model_from_poa function --- pvlib/modelchain.py | 64 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 5db0f1289d..372a2fd4ff 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -19,13 +19,11 @@ from pvlib.tools import _build_kwargs from pvlib._deprecation import deprecated + # Keys used to detect input data and assign values to the appropriate # ModelChain attributes. -#: tuple[str] -#: Weather-related input columns used by :class:`ModelChain` to populate -#: ``ModelChain.weather``. Missing ``temp_air`` or ``wind_speed`` are -#: automatically filled (20 °C and 0 m/s). +# Weather-related input columns for ModelChain.weather WEATHER_KEYS = ( 'ghi', # Global Horizontal Irradiance (W/m^2) 'dhi', # Diffuse Horizontal Irradiance (W/m^2) @@ -35,26 +33,22 @@ 'precipitable_water' # Column precipitable water (cm) ) -#: tuple[str] -#: Plane-of-array irradiance components used to populate -#: ``ModelChain.total_irrad`` when running from POA input. +# Plane-of-array irradiance input columns for ModelChain.total_irrad POA_KEYS = ( 'poa_global', # Total plane-of-array irradiance (W/m^2) 'poa_direct', # Direct POA irradiance (W/m^2) 'poa_diffuse' # Diffuse POA irradiance (W/m^2) ) -#: tuple[str] -#: Temperature-related input columns that override or supplement the -#: ModelChain temperature model. If ``cell_temperature`` is provided, -#: the temperature model is skipped. +# Temperature-related optional input columns for ModelChain TEMPERATURE_KEYS = ( 'module_temperature', # Back-surface module temperature (°C) 'cell_temperature', # Direct cell temperature input (°C) ) -#: tuple[str] -#: All supported input keys recognized by ModelChain. + +# All supported input keys combined DATA_KEYS = WEATHER_KEYS + POA_KEYS + TEMPERATURE_KEYS + # these dictionaries contain the default configuration for following # established modeling sequences. They can be used in combination with # ModelChain, particularly they are used by the methods @@ -1730,6 +1724,27 @@ def run_model_from_poa(self, data): of Arrays in the PVSystem. ValueError If the DataFrames in `data` have different indexes. + Examples + -------- + Single-array system: + + >>> import pandas as pd + >>> from pvlib.pvsystem import PVSystem + >>> from pvlib.location import Location + >>> from pvlib.modelchain import ModelChain + >>> + >>> system = PVSystem(module_parameters={'pdc0': 300}) + >>> location = Location(35, -110) + >>> mc = ModelChain(system, location) + >>> + >>> poa = pd.DataFrame({ + ... 'poa_global': [900, 850], + ... 'poa_direct': [600, 560], + ... 'poa_diffuse': [300, 290], + ... }, index=pd.date_range("2021-06-01", periods=2, freq="H")) + >>> + >>> mc.run_model_from_poa(poa) + Notes ----- @@ -1755,7 +1770,6 @@ def run_model_from_poa(self, data): self._run_from_effective_irrad(data) return self - def _run_from_effective_irrad(self, data): """ Executes the temperature, DC, losses and AC models. @@ -1774,7 +1788,7 @@ def _run_from_effective_irrad(self, data): Notes ----- - Assigns attributes:``cell_temperature``, ``dc``, ``ac``, ``losses``, + Assigns attributes:``cell_temperature, 'dc', ``ac', ``losses``, ``diode_params`` (if dc_model is a single diode model). """ self._prepare_temperature(data) @@ -1815,6 +1829,25 @@ def run_model_from_effective_irradiance(self, data): of Arrays in the PVSystem. ValueError If the DataFrames in `data` have different indexes. + Examples + -------- + >>> import pandas as pd + >>> from pvlib.pvsystem import PVSystem + >>> from pvlib.location import Location + >>> from pvlib.modelchain import ModelChain + >>> + >>> system = PVSystem(module_parameters={'pdc0': 300}) + >>> location = Location(35, -110) + >>> mc = ModelChain(system, location) + >>> + >>> eff = pd.DataFrame({ + ... 'effective_irradiance': [900, 920], + ... 'temp_air': [25, 24], + ... 'wind_speed': [2.0, 1.5], + ... }) + >>> + >>> mc.run_model_from_effective_irradiance(eff) + Notes ----- @@ -1853,6 +1886,7 @@ def run_model_from_effective_irradiance(self, data): return self + def _irrad_for_celltemp(total_irrad, effective_irradiance): """ Determine irradiance to use for cell temperature models, in order From fc57da27b475454175b33745daa78e792d0c071c Mon Sep 17 00:00:00 2001 From: Chirag3841 Date: Wed, 3 Dec 2025 19:16:41 +0530 Subject: [PATCH 4/8] Fix NOCT-SAM effective irradiance handling and add tests --- pvlib/temperature.py | 18 ++++++------ tests/test_noct_sam_effective_irradiance.py | 32 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 tests/test_noct_sam_effective_irradiance.py diff --git a/pvlib/temperature.py b/pvlib/temperature.py index 14d67a168e..b696fa8a46 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -713,7 +713,8 @@ def ross(poa_global, temp_air, noct=None, k=None): return temp_air + k * poa_global -def _fuentes_hconv(tave, windmod, temp_delta, xlen, tilt, check_reynold): +def _fuentes_hconv(tave, windmod, tinoct, temp_delta, xlen, tilt, + check_reynold): # Calculate the convective coefficient as in Fuentes 1987 -- a mixture of # free, laminar, and turbulent convection. densair = 0.003484 * 101325.0 / tave # density @@ -835,7 +836,7 @@ def fuentes(poa_global, temp_air, wind_speed, noct_installed, module_height=5, # convective coefficient of top surface of module at NOCT windmod = 1.0 tave = (tinoct + 293.15) / 2 - hconv = _fuentes_hconv(tave, windmod, tinoct - 293.15, xlen, + hconv = _fuentes_hconv(tave, windmod, tinoct, tinoct - 293.15, xlen, surface_tilt, False) # determine the ground temperature ratio and the ratio of the total @@ -895,7 +896,7 @@ def fuentes(poa_global, temp_air, wind_speed, noct_installed, module_height=5, for j in range(10): # overall convective coefficient tave = (tmod + tamb) / 2 - hconv = convrat * _fuentes_hconv(tave, windmod, + hconv = convrat * _fuentes_hconv(tave, windmod, tinoct, abs(tmod-tamb), xlen, surface_tilt, True) # sky radiation coefficient (Equation 3) @@ -1011,10 +1012,9 @@ def noct_sam(poa_global, temp_air, wind_speed, noct, module_efficiency, # - Geff_total (SAM) is POA irradiance after reflections and # adjustment for spectrum. Equivalent to effective_irradiance if effective_irradiance is None: - irr_ratio = 1. + irr = poa_global else: - irr_ratio = effective_irradiance / poa_global - + irr = np.maximum(effective_irradiance, 0) if array_height == 1: wind_adj = 0.51 * wind_speed elif array_height == 2: @@ -1022,13 +1022,11 @@ def noct_sam(poa_global, temp_air, wind_speed, noct, module_efficiency, else: raise ValueError( f'array_height must be 1 or 2, {array_height} was given') - noct_adj = noct + _adj_for_mounting_standoff(mount_standoff) - tau_alpha = transmittance_absorptance * irr_ratio - # [1] Eq. 10.37 isn't clear on exactly what "G" is. SAM SSC code uses # poa_global where G appears - cell_temp_init = poa_global / 800. * (noct_adj - 20.) + cell_temp_init = irr / 800. * (noct_adj - 20.) + tau_alpha = transmittance_absorptance heat_loss = 1 - module_efficiency / tau_alpha wind_loss = 9.5 / (5.7 + 3.8 * wind_adj) return temp_air + cell_temp_init * heat_loss * wind_loss diff --git a/tests/test_noct_sam_effective_irradiance.py b/tests/test_noct_sam_effective_irradiance.py new file mode 100644 index 0000000000..313aee1bc0 --- /dev/null +++ b/tests/test_noct_sam_effective_irradiance.py @@ -0,0 +1,32 @@ +import numpy as np +from pvlib.temperature import noct_sam +def test_noct_sam_effective_irr_reduces_temp(): + # Test that effective irradiance lowers predicted cell temperature + t_full = noct_sam(poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.20) + # Lower effective irradiance should reduce modeled temperature + t_eff_600 = noct_sam(poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.20, + effective_irradiance=600) + t_eff_200 = noct_sam(poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.20, + effective_irradiance=200) + assert t_eff_600 < t_full + assert t_eff_200 < t_eff_600 +def test_noct_sam_oc_case_reduces_temp(): + # Test that open-circuit modules (efficiency=0) still respond to effective irradiance + t_oc_full = noct_sam(poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.0) + # Reducing effective irradiance should still lower modeled temperature + t_oc_eff = noct_sam(poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.0, + effective_irradiance=300) + assert t_oc_eff < t_oc_full + +def test_noct_sam_not_below_ambient_for_small_eff(): + # Test that extremely small effective irradiance never predicts temperature below ambient + t_small = noct_sam(poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.20, + effective_irradiance=1.0) + # Allow tiny numerical tolerance + assert t_small >= 20.0 - 1e-6 From 45912cc868a3f250f05864f66f7362748000d9b2 Mon Sep 17 00:00:00 2001 From: Chirag3841 Date: Thu, 4 Dec 2025 13:30:47 +0530 Subject: [PATCH 5/8] Add tests for effective irradiance behavior in noct_sam --- tests/test_noct_sam_effective_irradiance.py | 32 --------------------- 1 file changed, 32 deletions(-) diff --git a/tests/test_noct_sam_effective_irradiance.py b/tests/test_noct_sam_effective_irradiance.py index 313aee1bc0..e69de29bb2 100644 --- a/tests/test_noct_sam_effective_irradiance.py +++ b/tests/test_noct_sam_effective_irradiance.py @@ -1,32 +0,0 @@ -import numpy as np -from pvlib.temperature import noct_sam -def test_noct_sam_effective_irr_reduces_temp(): - # Test that effective irradiance lowers predicted cell temperature - t_full = noct_sam(poa_global=800, temp_air=20, wind_speed=2, - noct=45, module_efficiency=0.20) - # Lower effective irradiance should reduce modeled temperature - t_eff_600 = noct_sam(poa_global=800, temp_air=20, wind_speed=2, - noct=45, module_efficiency=0.20, - effective_irradiance=600) - t_eff_200 = noct_sam(poa_global=800, temp_air=20, wind_speed=2, - noct=45, module_efficiency=0.20, - effective_irradiance=200) - assert t_eff_600 < t_full - assert t_eff_200 < t_eff_600 -def test_noct_sam_oc_case_reduces_temp(): - # Test that open-circuit modules (efficiency=0) still respond to effective irradiance - t_oc_full = noct_sam(poa_global=800, temp_air=20, wind_speed=2, - noct=45, module_efficiency=0.0) - # Reducing effective irradiance should still lower modeled temperature - t_oc_eff = noct_sam(poa_global=800, temp_air=20, wind_speed=2, - noct=45, module_efficiency=0.0, - effective_irradiance=300) - assert t_oc_eff < t_oc_full - -def test_noct_sam_not_below_ambient_for_small_eff(): - # Test that extremely small effective irradiance never predicts temperature below ambient - t_small = noct_sam(poa_global=800, temp_air=20, wind_speed=2, - noct=45, module_efficiency=0.20, - effective_irradiance=1.0) - # Allow tiny numerical tolerance - assert t_small >= 20.0 - 1e-6 From c960191c930fa8dd3325526fa452343200962f13 Mon Sep 17 00:00:00 2001 From: Chirag3841 Date: Thu, 4 Dec 2025 13:40:03 +0530 Subject: [PATCH 6/8] Add tests for effective irradiance behavior in noct_sam --- tests/test_noct_sam_eff_irradiance.py | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/test_noct_sam_eff_irradiance.py diff --git a/tests/test_noct_sam_eff_irradiance.py b/tests/test_noct_sam_eff_irradiance.py new file mode 100644 index 0000000000..741e9dbe34 --- /dev/null +++ b/tests/test_noct_sam_eff_irradiance.py @@ -0,0 +1,51 @@ +import numpy as np +from pvlib.temperature import noct_sam + +def test_noct_sam_effective_irr_reduces_temp(): + # Effective irradiance should lower predicted module temp + t_full = noct_sam( + poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.20 + ) + + t_eff_600 = noct_sam( + poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.20, + effective_irradiance=600 + ) + + t_eff_200 = noct_sam( + poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.20, + effective_irradiance=200 + ) + + assert t_eff_600 < t_full + assert t_eff_200 < t_eff_600 + + +def test_noct_sam_oc_case_reduces_temp(): + # Open-circuit (efficiency=0) should still respond to effective irradiance + t_oc_full = noct_sam( + poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.0 + ) + + t_oc_eff = noct_sam( + poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.0, + effective_irradiance=300 + ) + + assert t_oc_eff < t_oc_full + + +def test_noct_sam_not_below_ambient_for_small_eff(): + # Very small effective irradiance should not predict cooling below ambient + t_small = noct_sam( + poa_global=800, temp_air=20, wind_speed=2, + noct=45, module_efficiency=0.20, + effective_irradiance=1.0 + ) + + assert t_small >= 20.0 - 1e-6 # small numerical tolerance From f79d3fe3d90b4a35e7fa2a4f1cf208104a3d88be Mon Sep 17 00:00:00 2001 From: Chirag3841 Date: Sat, 6 Dec 2025 12:52:54 +0530 Subject: [PATCH 7/8] Fix NOCT SAM effective irradiance behavior and add tests --- pvlib/temperature.py | 7 ++++--- tests/test_noct_sam_effective_irradiance.py | 0 tests/test_pvsystem.py | 3 ++- tests/test_temperature.py | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) delete mode 100644 tests/test_noct_sam_effective_irradiance.py diff --git a/pvlib/temperature.py b/pvlib/temperature.py index 22164eb89e..4a09a8819e 100644 --- a/pvlib/temperature.py +++ b/pvlib/temperature.py @@ -1012,9 +1012,9 @@ def noct_sam(poa_global, temp_air, wind_speed, noct, module_efficiency, # - Geff_total (SAM) is POA irradiance after reflections and # adjustment for spectrum. Equivalent to effective_irradiance if effective_irradiance is None: - irr = poa_global + Geff = poa_global else: - irr = np.maximum(effective_irradiance, 0) + Geff= np.maximum(effective_irradiance, 0) if array_height == 1: wind_adj = 0.51 * wind_speed elif array_height == 2: @@ -1025,7 +1025,8 @@ def noct_sam(poa_global, temp_air, wind_speed, noct, module_efficiency, noct_adj = noct + _adj_for_mounting_standoff(mount_standoff) # [1] Eq. 10.37 isn't clear on exactly what "G" is. SAM SSC code uses # poa_global where G appears - cell_temp_init = irr / 800. * (noct_adj - 20.) + irr_ratio = Geff / poa_global + cell_temp_init = (poa_global / 800.0) * (noct_adj - 20.0) * irr_ratio tau_alpha = transmittance_absorptance heat_loss = 1 - module_efficiency / tau_alpha wind_loss = 9.5 / (5.7 + 3.8 * wind_adj) diff --git a/tests/test_noct_sam_effective_irradiance.py b/tests/test_noct_sam_effective_irradiance.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/test_pvsystem.py b/tests/test_pvsystem.py index 4fbd782e65..b5c99e5a04 100644 --- a/tests/test_pvsystem.py +++ b/tests/test_pvsystem.py @@ -522,7 +522,8 @@ def test_PVSystem_noct_celltemp(mocker): temp_model_params.update({'transmittance_absorptance': 0.8, 'array_height': 2, 'mount_standoff': 2.0}) - expected = 60.477703576 + expected =62.877666 + system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params) out = system.get_cell_temperature(poa_global, temp_air, wind_speed, effective_irradiance=1100., diff --git a/tests/test_temperature.py b/tests/test_temperature.py index e482df6214..6a0ad82f70 100644 --- a/tests/test_temperature.py +++ b/tests/test_temperature.py @@ -323,7 +323,7 @@ def test_noct_sam_against_sam(): module_efficiency, effective_irradiance, transmittance_absorptance, array_height, mount_standoff) - expected = 43.0655 + expected = 43.024616 # rtol from limited SAM output precision assert_allclose(result, expected, rtol=1e-5) @@ -339,7 +339,7 @@ def test_noct_sam_options(): module_efficiency, effective_irradiance, transmittance_absorptance, array_height, mount_standoff) - expected = 60.477703576 + expected = 62.877666 assert_allclose(result, expected) From 3e3ea074823b71275608b15bc2deeba0067f63dc Mon Sep 17 00:00:00 2001 From: Chirag3841 Date: Sat, 6 Dec 2025 14:03:32 +0530 Subject: [PATCH 8/8] Remove unrelated modelchain changes --- pvlib/modelchain.py | 85 +++++++++------------------------------------ 1 file changed, 17 insertions(+), 68 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 372a2fd4ff..09e4434e84 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -20,33 +20,22 @@ from pvlib._deprecation import deprecated -# Keys used to detect input data and assign values to the appropriate -# ModelChain attributes. - -# Weather-related input columns for ModelChain.weather -WEATHER_KEYS = ( - 'ghi', # Global Horizontal Irradiance (W/m^2) - 'dhi', # Diffuse Horizontal Irradiance (W/m^2) - 'dni', # Direct Normal Irradiance (W/m^2) - 'wind_speed', # Wind speed (m/s) - 'temp_air', # Ambient air temperature (°C) - 'precipitable_water' # Column precipitable water (cm) -) - -# Plane-of-array irradiance input columns for ModelChain.total_irrad -POA_KEYS = ( - 'poa_global', # Total plane-of-array irradiance (W/m^2) - 'poa_direct', # Direct POA irradiance (W/m^2) - 'poa_diffuse' # Diffuse POA irradiance (W/m^2) -) +# keys that are used to detect input data and assign data to appropriate +# ModelChain attribute +# for ModelChain.weather +WEATHER_KEYS = ('ghi', 'dhi', 'dni', 'wind_speed', 'temp_air', + 'precipitable_water') + +# for ModelChain.total_irrad +POA_KEYS = ('poa_global', 'poa_direct', 'poa_diffuse') + +# Optional keys to communicate temperature data. If provided, +# 'cell_temperature' overrides ModelChain.temperature_model and sets +# ModelChain.cell_temperature to the data. If 'module_temperature' is provided, +# overrides ModelChain.temperature_model with +# pvlib.temperature.sapm_cell_from_module +TEMPERATURE_KEYS = ('module_temperature', 'cell_temperature') -# Temperature-related optional input columns for ModelChain -TEMPERATURE_KEYS = ( - 'module_temperature', # Back-surface module temperature (°C) - 'cell_temperature', # Direct cell temperature input (°C) -) - -# All supported input keys combined DATA_KEYS = WEATHER_KEYS + POA_KEYS + TEMPERATURE_KEYS # these dictionaries contain the default configuration for following @@ -1724,27 +1713,6 @@ def run_model_from_poa(self, data): of Arrays in the PVSystem. ValueError If the DataFrames in `data` have different indexes. - Examples - -------- - Single-array system: - - >>> import pandas as pd - >>> from pvlib.pvsystem import PVSystem - >>> from pvlib.location import Location - >>> from pvlib.modelchain import ModelChain - >>> - >>> system = PVSystem(module_parameters={'pdc0': 300}) - >>> location = Location(35, -110) - >>> mc = ModelChain(system, location) - >>> - >>> poa = pd.DataFrame({ - ... 'poa_global': [900, 850], - ... 'poa_direct': [600, 560], - ... 'poa_diffuse': [300, 290], - ... }, index=pd.date_range("2021-06-01", periods=2, freq="H")) - >>> - >>> mc.run_model_from_poa(poa) - Notes ----- @@ -1770,6 +1738,7 @@ def run_model_from_poa(self, data): self._run_from_effective_irrad(data) return self + def _run_from_effective_irrad(self, data): """ Executes the temperature, DC, losses and AC models. @@ -1788,7 +1757,7 @@ def _run_from_effective_irrad(self, data): Notes ----- - Assigns attributes:``cell_temperature, 'dc', ``ac', ``losses``, + Assigns attributes:``cell_temperature``, ``dc``, ``ac``, ``losses``, ``diode_params`` (if dc_model is a single diode model). """ self._prepare_temperature(data) @@ -1829,25 +1798,6 @@ def run_model_from_effective_irradiance(self, data): of Arrays in the PVSystem. ValueError If the DataFrames in `data` have different indexes. - Examples - -------- - >>> import pandas as pd - >>> from pvlib.pvsystem import PVSystem - >>> from pvlib.location import Location - >>> from pvlib.modelchain import ModelChain - >>> - >>> system = PVSystem(module_parameters={'pdc0': 300}) - >>> location = Location(35, -110) - >>> mc = ModelChain(system, location) - >>> - >>> eff = pd.DataFrame({ - ... 'effective_irradiance': [900, 920], - ... 'temp_air': [25, 24], - ... 'wind_speed': [2.0, 1.5], - ... }) - >>> - >>> mc.run_model_from_effective_irradiance(eff) - Notes ----- @@ -1886,7 +1836,6 @@ def run_model_from_effective_irradiance(self, data): return self - def _irrad_for_celltemp(total_irrad, effective_irradiance): """ Determine irradiance to use for cell temperature models, in order