Streamlined computations for applying Marion diffuse-IAM corrections?

44 views
Skip to first unread message

Mark Campanelli

unread,
May 10, 2024, 12:37:21 PMMay 10
to pvlib-python
Hi,

  It is unclear to me if there is a streamlined computational "wrapper" in pvlib that allows one to compute all the IAM-corrected POA components and their total (inc. without computing some things twice using different existing wrapper functions).

  Below is the lower-level way that I do this now (excerpted from https://github.com/markcampanelli/pvpmc2024/blob/main/tutorial/2_dc_performance_prediction.ipynb). Note that this approach may be specific to model choices in perez.

-Mark

# Compute angle of incidence of sun on POA.
aoi_deg = pvlib.irradiance.aoi(
array["surface_tilt_deg"],
array["surface_azimuth_deg"],
weather["apparent_zenith"],
weather["azimuth"],
)
# Compute direct component on POA.
poa_components = pandas.DataFrame(
data={"direct": numpy.maximum(weather["dni"] * numpy.cos(numpy.radians(aoi_deg)), 0)},
index=weather.index
)
# Compute sky-diffuse components on POA using Perez allsitescomposite1990.
poa_components_perez = pvlib.irradiance.perez(
array["surface_tilt_deg"],
array["surface_azimuth_deg"],
weather["dhi"],
weather["dni"],
pvlib.irradiance.get_extra_radiation(weather.index),
weather["apparent_zenith"],
weather["azimuth"],
airmass=pvlib.atmosphere.get_relative_airmass(weather["apparent_zenith"]),
model="allsitescomposite1990", # Cf. albuquerque1988
return_components=True,
)
poa_components["circumsolar"] = poa_components_perez["circumsolar"]
poa_components["isotropic"] = poa_components_perez["isotropic"]
poa_components["horizon"] = poa_components_perez["horizon"]

# Compute ground-diffuse component on POA.
poa_components["ground_diffuse"] = pvlib.irradiance.get_ground_diffuse(
array["surface_tilt_deg"],
weather["ghi"],
albedo=array["albedo"],
)

# Compute total POA irradiance.
poa_components["total"] = numpy.sum(poa_components.to_numpy(), axis=1)
# Compute IAMs for diffuse components.
# pvlib.iam.marion_diffuse cannot make use of our custom fit IAM function,
# so instead use lower level pvlib.iam.marion_integrate for each component.
diffuse_iam = {}
for region in ["sky", "horizon", "ground"]:
diffuse_iam[region] = pvlib.iam.marion_integrate(
lambda angle_deg: iam(angle_deg=angle_deg), array["surface_tilt_deg"], region
)
# Compute IAM-corrected effective POA irradiance.
poa_components["total_eff"] = iam(angle_deg=aoi_deg) * (
poa_components["direct"] + poa_components["circumsolar"]) + \
diffuse_iam["sky"] * poa_components["isotropic"] + \
diffuse_iam["horizon"] * poa_components["horizon"] + \
diffuse_iam["ground"] * poa_components["ground_diffuse"]

Mark Campanelli

unread,
May 12, 2024, 11:16:35 AMMay 12
to pvlib-python
To simplify and standardize one small part of this workflow, I opened an issue and PR to allow one to pass a custom IAM function (including the existing pvlib.iam.interp) to the high-level pvlib.iam.marion_diffuse function. The PR would also add pvlib.iam.pchip, which generates piecewise-cubic Hermite interpolating polynomial from (AOI, IAM) data. I have found PCHIP to have particularly nice properties for IEC 61853-2 IAM measurement data. Seethe new tests for example of that.

https://github.com/pvlib/pvlib-python/issues/2049
https://github.com/pvlib/pvlib-python/pull/2050

I tried to follow the coding style I see already in pvlib, but I have some outstanding questions about some items such as the proper level of input validation and the need to support pandas.Series.

-Mark
Reply all
Reply to author
Forward
0 new messages