Skip to content
19 changes: 9 additions & 10 deletions pvlib/temperature.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1011,24 +1012,22 @@ 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.
Geff = poa_global
else:
irr_ratio = effective_irradiance / poa_global

Geff= np.maximum(effective_irradiance, 0)
if array_height == 1:
wind_adj = 0.51 * wind_speed
elif array_height == 2:
wind_adj = 0.61 * wind_speed
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.)
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)
return temp_air + cell_temp_init * heat_loss * wind_loss
Expand Down
51 changes: 51 additions & 0 deletions tests/test_noct_sam_eff_irradiance.py
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion tests/test_pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_temperature.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)


Expand Down