SAPM_EFF_IRRAD
This function converts plane-of-array direct and diffuse irradiance into the effective irradiance actually absorbed by module cells under the Sandia model. It applies both a spectral adjustment based on absolute airmass and an incidence-angle modifier based on angle of incidence.
The SAPM effective irradiance relationship is:
E_e = f_1(AM_a) \left(E_b f_2(AOI) + f_d E_d\right)
Here f_1 is the spectral response polynomial, f_2 is the angle-of-incidence modifier, and f_d is the diffuse fraction coefficient. Supply the required coefficients as a 2D list of key-value pairs such as [["A0", 1.0], ["B0", 1.0], ["FD", 1.0]].
Excel Usage
=SAPM_EFF_IRRAD(poa_direct, poa_diffuse, airmass_absolute, aoi, module_params)
poa_direct(float, required): Direct irradiance on the plane of array (W/m^2).poa_diffuse(float, required): Diffuse irradiance on the plane of array (W/m^2).airmass_absolute(float, required): Absolute airmass (unitless).aoi(float, required): Angle of incidence (degrees).module_params(list[list], required): 2D list of SAPM coefficients [[‘key’, value], …].
Returns (float): Effective irradiance (W/m^2), or an error string.
Example 1: Standard Effective Irradiance
Inputs:
| poa_direct | poa_diffuse | airmass_absolute | aoi | module_params | |
|---|---|---|---|---|---|
| 800 | 100 | 1.5 | 30 | A0 | 1 |
| A1 | 0 | ||||
| A2 | 0 | ||||
| A3 | 0 | ||||
| A4 | 0 | ||||
| B0 | 1 | ||||
| B1 | 0 | ||||
| B2 | 0 | ||||
| B3 | 0 | ||||
| B4 | 0 | ||||
| B5 | 0 | ||||
| FD | 1 |
Excel formula:
=SAPM_EFF_IRRAD(800, 100, 1.5, 30, {"A0",1;"A1",0;"A2",0;"A3",0;"A4",0;"B0",1;"B1",0;"B2",0;"B3",0;"B4",0;"B5",0;"FD",1})
Expected output:
900
Example 2: Diffuse-only irradiance case
Inputs:
| poa_direct | poa_diffuse | airmass_absolute | aoi | module_params | |
|---|---|---|---|---|---|
| 0 | 200 | 1.5 | 30 | A0 | 1 |
| A1 | 0 | ||||
| A2 | 0 | ||||
| A3 | 0 | ||||
| A4 | 0 | ||||
| B0 | 1 | ||||
| B1 | 0 | ||||
| B2 | 0 | ||||
| B3 | 0 | ||||
| B4 | 0 | ||||
| B5 | 0 | ||||
| FD | 1 |
Excel formula:
=SAPM_EFF_IRRAD(0, 200, 1.5, 30, {"A0",1;"A1",0;"A2",0;"A3",0;"A4",0;"B0",1;"B1",0;"B2",0;"B3",0;"B4",0;"B5",0;"FD",1})
Expected output:
200
Example 3: Reduced diffuse fraction coefficient
Inputs:
| poa_direct | poa_diffuse | airmass_absolute | aoi | module_params | |
|---|---|---|---|---|---|
| 700 | 100 | 1.5 | 30 | A0 | 1 |
| A1 | 0 | ||||
| A2 | 0 | ||||
| A3 | 0 | ||||
| A4 | 0 | ||||
| B0 | 1 | ||||
| B1 | 0 | ||||
| B2 | 0 | ||||
| B3 | 0 | ||||
| B4 | 0 | ||||
| B5 | 0 | ||||
| FD | 0.8 |
Excel formula:
=SAPM_EFF_IRRAD(700, 100, 1.5, 30, {"A0",1;"A1",0;"A2",0;"A3",0;"A4",0;"B0",1;"B1",0;"B2",0;"B3",0;"B4",0;"B5",0;"FD",0.8})
Expected output:
780
Example 4: Spectral scaling below unity
Inputs:
| poa_direct | poa_diffuse | airmass_absolute | aoi | module_params | |
|---|---|---|---|---|---|
| 800 | 100 | 1.5 | 30 | A0 | 0.95 |
| A1 | 0 | ||||
| A2 | 0 | ||||
| A3 | 0 | ||||
| A4 | 0 | ||||
| B0 | 1 | ||||
| B1 | 0 | ||||
| B2 | 0 | ||||
| B3 | 0 | ||||
| B4 | 0 | ||||
| B5 | 0 | ||||
| FD | 1 |
Excel formula:
=SAPM_EFF_IRRAD(800, 100, 1.5, 30, {"A0",0.95;"A1",0;"A2",0;"A3",0;"A4",0;"B0",1;"B1",0;"B2",0;"B3",0;"B4",0;"B5",0;"FD",1})
Expected output:
855
Python Code
Show Code
from pvlib.pvsystem import sapm_effective_irradiance as result_func
def sapm_eff_irrad(poa_direct, poa_diffuse, airmass_absolute, aoi, module_params):
"""
Calculate SAPM effective irradiance accounting for spectral and incidence losses.
See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.pvsystem.sapm_effective_irradiance.html
This example function is provided as-is without any representation of accuracy.
Args:
poa_direct (float): Direct irradiance on the plane of array (W/m^2).
poa_diffuse (float): Diffuse irradiance on the plane of array (W/m^2).
airmass_absolute (float): Absolute airmass (unitless).
aoi (float): Angle of incidence (degrees).
module_params (list[list]): 2D list of SAPM coefficients [['key', value], ...].
Returns:
float: Effective irradiance (W/m^2), or an error string.
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
eb = float(poa_direct)
ed = float(poa_diffuse)
am = float(airmass_absolute)
ao = float(aoi)
module_params = to2d(module_params)
if not isinstance(module_params, list) or not all(isinstance(row, list) for row in module_params):
return "Error: module_params must be a 2D list of key-value pairs"
mod_dict = {}
for row in module_params:
if len(row) >= 2:
key = str(row[0]).strip()
val = row[1]
try:
val = float(val)
except (TypeError, ValueError):
pass
mod_dict[key] = val
res = result_func(
poa_direct=eb,
poa_diffuse=ed,
airmass_absolute=am,
aoi=ao,
module=mod_dict
)
return float(res)
except Exception as e:
return f"Error: {str(e)}"