Skip to content

Commit 9a3d1b7

Browse files
adriessewholmgren
authored andcommitted
Implement IEC 61853 module temperature model (#834)
* First functional function. * Fixed defaults and docstring; added tests and sphinx entries. * Small but important docstring changes.
1 parent a8b85c3 commit 9a3d1b7

File tree

4 files changed

+110
-2
lines changed

4 files changed

+110
-2
lines changed

docs/sphinx/source/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ PV temperature models
233233
temperature.sapm_cell
234234
temperature.sapm_module
235235
temperature.pvsyst_cell
236+
temperature.faiman
236237

237238
Single diode models
238239
-------------------

docs/sphinx/source/whatsnew/v0.7.0.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,12 @@ Other API Changes
119119

120120
Enhancements
121121
~~~~~~~~~~~~
122+
* Created one new temperature model function:
123+
:py:func:`pvlib.temperature.faiman`. (:issue:`750`)
122124
* Created two new incidence angle modifier (IAM) functions:
123125
:py:func:`pvlib.iam.martin_ruiz` and :py:func:`pvlib.iam.interp`. (:issue:`751`)
126+
* Created one new incidence angle modifier (IAM) function for diffuse irradiance:
127+
:py:func:`pvlib.iam.martin_ruiz_diffuse`. (:issue:`751`)
124128
* Add the `martin_ruiz` IAM function as an option for `ModelChain.aoi_model`.
125129
* Updated the file for module parameters for the CEC model, from the SAM file
126130
dated 2017-6-5 to the SAM file dated 2019-03-05. (:issue:`761`)
@@ -138,8 +142,6 @@ Enhancements
138142
* Add `timeout` to :py:func:`pvlib.iotools.get_psm3`.
139143
* Add :py:func:`~pvlib.scaling.wvm`, a port of the wavelet variability model for
140144
computing reductions in variability due to a spatially distributed plant.
141-
* Created one new incidence angle modifier (IAM) function for diffuse irradiance:
142-
:py:func:`pvlib.iam.martin_ruiz_diffuse`. (:issue:`751`)
143145
* Add :py:meth:`~pvlib.location.Location.from_epw`, a method to create a Location
144146
object from epw metadata, typically coming from `pvlib.iotools.epw.read_epw`.
145147

pvlib/temperature.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,69 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0,
269269
heat_input = poa_global * alpha_absorption * (1 - eta_m)
270270
temp_difference = heat_input / total_loss_factor
271271
return temp_air + temp_difference
272+
273+
274+
def faiman(poa_global, temp_air, wind_speed=1.0, u0=25.0, u1=6.84):
275+
'''
276+
Calculate cell or module temperature using an empirical heat loss factor
277+
model as proposed by Faiman [1] and adopted in the IEC 61853
278+
standards [2] and [3].
279+
280+
Usage of this model in the IEC 61853 standard does not distinguish
281+
between cell and module temperature.
282+
283+
Parameters
284+
----------
285+
poa_global : numeric
286+
Total incident irradiance [W/m^2].
287+
288+
temp_air : numeric
289+
Ambient dry bulb temperature [C].
290+
291+
wind_speed : numeric, default 1.0
292+
Wind speed in m/s measured at the same height for which the wind loss
293+
factor was determined. The default value 1.0 m/s is the wind
294+
speed at module height used to determine NOCT. [m/s]
295+
296+
u0 : numeric, default 25.0
297+
Combined heat loss factor coefficient. The default value is one
298+
determined by Faiman for 7 silicon modules. [W/(m^2 C)].
299+
300+
u1 : numeric, default 6.84
301+
Combined heat loss factor influenced by wind. The default value is one
302+
determined by Faiman for 7 silicon modules. [(W/m^2 C)(m/s)].
303+
304+
Returns
305+
-------
306+
numeric, values in degrees Celsius
307+
308+
Notes
309+
-----
310+
All arguments may be scalars or vectors. If multiple arguments
311+
are vectors they must be the same length.
312+
313+
References
314+
----------
315+
[1] Faiman, D. (2008). "Assessing the outdoor operating temperature of
316+
photovoltaic modules." Progress in Photovoltaics 16(4): 307-315.
317+
318+
[2] "IEC 61853-2 Photovoltaic (PV) module performance testing and energy
319+
rating - Part 2: Spectral responsivity, incidence angle and module
320+
operating temperature measurements". IEC, Geneva, 2018.
321+
322+
[3] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy
323+
rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018.
324+
325+
'''
326+
# Contributed by Anton Driesse (@adriesse), PV Performance Labs. Dec., 2019
327+
328+
# The following lines may seem odd since u0 & u1 are probably scalar,
329+
# but it serves an indirect and easy way of allowing lists and
330+
# tuples for the other function arguments.
331+
u0 = np.asanyarray(u0)
332+
u1 = np.asanyarray(u1)
333+
334+
total_loss_factor = u0 + u1 * wind_speed
335+
heat_input = poa_global
336+
temp_difference = heat_input / total_loss_factor
337+
return temp_air + temp_difference

pvlib/test/test_temperature.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,45 @@ def test_pvsyst_cell_series():
9090
assert_series_equal(expected, result)
9191

9292

93+
def test_faiman_default():
94+
result = temperature.faiman(900, 20, 5)
95+
assert_allclose(result, 35.203, 0.001)
96+
97+
98+
def test_faiman_kwargs():
99+
result = temperature.faiman(900, 20, wind_speed=5.0, u0=22.0, u1=6.)
100+
assert_allclose(result, 37.308, 0.001)
101+
102+
103+
def test_faiman_list():
104+
temps = [0, 10, 5]
105+
irrads = [0, 500, 0]
106+
winds = [10, 5, 0]
107+
result = temperature.faiman(irrads, temps, wind_speed=winds)
108+
expected = np.array([0.0, 18.446, 5.0])
109+
assert_allclose(expected, result, 3)
110+
111+
112+
def test_faiman_ndarray():
113+
temps = np.array([0, 10, 5])
114+
irrads = np.array([0, 500, 0])
115+
winds = np.array([10, 5, 0])
116+
result = temperature.faiman(irrads, temps, wind_speed=winds)
117+
expected = np.array([0.0, 18.446, 5.0])
118+
assert_allclose(expected, result, 3)
119+
120+
121+
def test_faiman_series():
122+
times = pd.date_range(start="2015-01-01", end="2015-01-02", freq="12H")
123+
temps = pd.Series([0, 10, 5], index=times)
124+
irrads = pd.Series([0, 500, 0], index=times)
125+
winds = pd.Series([10, 5, 0], index=times)
126+
127+
result = temperature.faiman(irrads, temps, wind_speed=winds)
128+
expected = pd.Series([0.0, 18.446, 5.0], index=times)
129+
assert_series_equal(expected, result)
130+
131+
93132
def test__temperature_model_params():
94133
params = temperature._temperature_model_params('sapm',
95134
'open_rack_glass_glass')

0 commit comments

Comments
 (0)