@@ -1023,7 +1023,9 @@ def _set_celltemp(self, model):
1023
1023
-------
1024
1024
self
1025
1025
"""
1026
- poa = _tuple_from_dfs (self .results .total_irrad , 'poa_global' )
1026
+
1027
+ poa = _irrad_for_celltemp (self .results .total_irrad ,
1028
+ self .results .effective_irradiance )
1027
1029
temp_air = _tuple_from_dfs (self .weather , 'temp_air' )
1028
1030
wind_speed = _tuple_from_dfs (self .weather , 'wind_speed' )
1029
1031
self .results .cell_temperature = model (poa , temp_air , wind_speed )
@@ -1464,13 +1466,22 @@ def prepare_inputs_from_poa(self, data):
1464
1466
return self
1465
1467
1466
1468
def _get_cell_temperature (self , data ,
1467
- total_irrad , temperature_model_parameters ):
1469
+ poa , temperature_model_parameters ):
1468
1470
"""Extract the cell temperature data from a DataFrame.
1469
1471
1470
- If 'cell_temperature' column exists then it is returned. If
1471
- 'module_temperature' column exists then it is used to calculate
1472
- the cell temperature. If neither column exists then None is
1472
+ If 'cell_temperature' column exists in data then it is returned. If
1473
+ 'module_temperature' column exists in data, then it is used with poa to
1474
+ calculate the cell temperature. If neither column exists then None is
1473
1475
returned.
1476
+
1477
+ Parameters
1478
+ ----------
1479
+ data : DataFrame (not a tuple of DataFrame)
1480
+ poa : Series (not a tuple of Series)
1481
+
1482
+ Returns
1483
+ -------
1484
+ Series
1474
1485
"""
1475
1486
if 'cell_temperature' in data :
1476
1487
return data ['cell_temperature' ]
@@ -1483,14 +1494,14 @@ def _get_cell_temperature(self, data,
1483
1494
# use SAPM cell temperature model only
1484
1495
return pvlib .temperature .sapm_cell_from_module (
1485
1496
module_temperature = data ['module_temperature' ],
1486
- poa_global = total_irrad [ 'poa_global' ] ,
1497
+ poa_global = poa ,
1487
1498
deltaT = temperature_model_parameters ['deltaT' ])
1488
1499
1489
- def _prepare_temperature_single_array (self , data ):
1490
- """Set cell_temperature using a single weather data frame."""
1500
+ def _prepare_temperature_single_array (self , data , poa ):
1501
+ """Set cell_temperature using a single data frame."""
1491
1502
self .results .cell_temperature = self ._get_cell_temperature (
1492
1503
data ,
1493
- self . results . total_irrad ,
1504
+ poa ,
1494
1505
self .system .temperature_model_parameters
1495
1506
)
1496
1507
if self .results .cell_temperature is None :
@@ -1505,7 +1516,7 @@ def _prepare_temperature(self, data=None):
1505
1516
If 'data' contains 'cell_temperature', these values are assigned to
1506
1517
attribute ``cell_temperature``. If 'data' contains 'module_temperature`
1507
1518
and `temperature_model' is 'sapm', cell temperature is calculated using
1508
- :py:func:`pvlib.temperature.sapm_celL_from_module `. Otherwise, cell
1519
+ :py:func:`pvlib.temperature.sapm_cell_from_module `. Otherwise, cell
1509
1520
temperature is calculated by 'temperature_model'.
1510
1521
1511
1522
Parameters
@@ -1521,14 +1532,16 @@ def _prepare_temperature(self, data=None):
1521
1532
Assigns attribute ``results.cell_temperature``.
1522
1533
1523
1534
"""
1535
+ poa = _irrad_for_celltemp (self .results .total_irrad ,
1536
+ self .results .effective_irradiance )
1524
1537
if not isinstance (data , tuple ) and self .system .num_arrays > 1 :
1538
+ # broadcast data to all arrays
1525
1539
data = (data ,) * self .system .num_arrays
1526
1540
elif not isinstance (data , tuple ):
1527
- return self ._prepare_temperature_single_array (data )
1541
+ return self ._prepare_temperature_single_array (data , poa )
1528
1542
given_cell_temperature = tuple (itertools .starmap (
1529
1543
self ._get_cell_temperature ,
1530
- zip (data , self .results .total_irrad ,
1531
- self .system .temperature_model_parameters )
1544
+ zip (data , poa , self .system .temperature_model_parameters )
1532
1545
))
1533
1546
# If cell temperature has been specified for all arrays return
1534
1547
# immediately and do not try to compute it.
@@ -1716,10 +1729,8 @@ def run_model_from_effective_irradiance(self, data=None):
1716
1729
----------
1717
1730
data : DataFrame, or list or tuple of DataFrame
1718
1731
Required column is ``'effective_irradiance'``.
1719
- If optional column ``'cell_temperature'`` is provided, these values
1720
- are used instead of `temperature_model`. If optional column
1721
- ``'module_temperature'`` is provided, `temperature_model` must be
1722
- ``'sapm'``.
1732
+ Optional columns include ``'cell_temperature'``,
1733
+ ``'module_temperature'`` and ``'poa_global'``.
1723
1734
1724
1735
If the ModelChain's PVSystem has multiple arrays, `data` must be a
1725
1736
list or tuple with the same length and order as the PVsystem's
@@ -1740,6 +1751,20 @@ def run_model_from_effective_irradiance(self, data=None):
1740
1751
1741
1752
Notes
1742
1753
-----
1754
+ Optional ``data`` columns ``'cell_temperature'``,
1755
+ ``'module_temperature'`` and ``'poa_global'`` are used for determining
1756
+ cell temperature.
1757
+
1758
+ * If optional column ``'cell_temperature'`` is present, these values
1759
+ are used and `temperature_model` is ignored.
1760
+ * If optional column ``'module_temperature'`` is preset,
1761
+ `temperature_model` must be ``'sapm'``.
1762
+ * Otherwise, cell temperature is calculated using `temperature_model`.
1763
+
1764
+ The cell temperature models require plane-of-array irradiance as input.
1765
+ If optional column ``'poa_global'`` is present, these data are used.
1766
+ If ``'poa_global'`` is not present, ``'effective_irradiance'`` is used.
1767
+
1743
1768
Assigns attributes: ``weather``, ``total_irrad``,
1744
1769
``effective_irradiance``, ``cell_temperature``, ``dc``, ``ac``,
1745
1770
``losses``, ``diode_params`` (if dc_model is a single diode model).
@@ -1760,6 +1785,29 @@ def run_model_from_effective_irradiance(self, data=None):
1760
1785
return self
1761
1786
1762
1787
1788
+ def _irrad_for_celltemp (total_irrad , effective_irradiance ):
1789
+ """
1790
+ Determine irradiance to use for cell temperature models, in order
1791
+ of preference 'poa_global' then 'effective_irradiance'
1792
+
1793
+ Returns
1794
+ -------
1795
+ Series or tuple of Series
1796
+ tuple if total_irrad is a tuple of DataFrame
1797
+
1798
+ """
1799
+ if isinstance (total_irrad , tuple ):
1800
+ if all (['poa_global' in df for df in total_irrad ]):
1801
+ return _tuple_from_dfs (total_irrad , 'poa_global' )
1802
+ else :
1803
+ return effective_irradiance
1804
+ else :
1805
+ if 'poa_global' in total_irrad :
1806
+ return total_irrad ['poa_global' ]
1807
+ else :
1808
+ return effective_irradiance
1809
+
1810
+
1763
1811
def _snl_params (inverter_params ):
1764
1812
"""Return True if `inverter_params` includes parameters for the
1765
1813
Sandia inverter model."""
0 commit comments