You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Compute the delta parameter, which represents sky dome "brightness" in the Perez and Perez-Driesse models.
This is somewhat misleading, because this function is not currently used In the pvlib.irradiance.perez function. Perhaps it should be? If not, then I suggest updating the language. (_calc_zeta's docstring notably only mentions Perez-Driesse.)
In addition, after a helpful communication with @adriesse, it seems that the inaugural pvlib.irradiance.perez function does not indicate in its doctoring that kastenyoung1989 is (apparently) the preferred method for computing the airmass parameter.
Was there ever a discussion about aligning the airmass input, its (default) calculation, and the delta calculation between pvlib.irradiance.perez and pvlib.irradiance.perez_driesse?
(Same question could be made for zeta and _calc_zeta usage, I suppose.)
I have been somewhat frustrated by the divergence in behavior of perez and perez-driesse, with the latter seeming to have better safeguards in place. This was much of the impetus behind #2808.
@markcampanelli can you clarify a bit what you see as the problem(s) and what you suggest as the solution(s)?
@cwhanse Please see this recent commit for a choice that tries to better align perez and perez_driesse inputs and functionality. Of course, a bunch of tests break, and I'd have to sort through and justify+fix all the differences.
I think some of test breakages may have to do with changes between large air masses being bounded as a real number vs. being NaN, but I'd have to dig through the details to verify. Not sure when I'll have more time for that.
irradiance.perez uses the _calc_delta and _calc_zeta helper function that was added for irradiance.perez_driesse
irradiance.perez uses the _calc_zeta helper function that was added for irradiance.perez_driesse
irradiance.perez defaults to calculating airmass with kastenyoung if airmass is not provided, which implies that airmass becomes an optional rather than required argment.
#1 may make sense, _calc_delta adds some handling of 0 / NaN values. #2 is a change in the underlying regressions (I think) so the result would no longer be the model that Perez published. If that's so, then #2 is a problem. #3 is a change in behavior, that is not a significant problem because airmass is fortuitously the last argument before named kwargs. I'm not necessarily opposed, but maybe we can handle the ambiguity by specifying the airmass model in the documentation.
I'm still not clear what problems these changes will fix, or what is being gained by these changes.
@cwhanse Thanks for reviewing the proposed changes. Incidentally, I am not a huge fan of default values in Python, because removing or changing them then becomes a breaking change. I'd probably prefer newly accepting None for airmass while not making it the default.
I'm still not clear what problems these changes will fix, or what is being gained by these changes.
The Perez-Driesse model can be considered a plug-in replacement for the
1990 Perez model using the 'allsitescomposite1990' coefficient set.
Deviations between the two are very small, as demonstrated in [1]_.
Perhaps "plug-in replacement" does not refer to the code implementation in pvlib? I almost always have to change my code when switching between perez and perez_driesse. Granted, these seem to be mostly for edge cases, but they are common enough that it still screws up results and (IMHO) reduces confidence in the library.
Update here on the differences in relative airmass calculations:
In perez_driesse makes an adjustment to the (relative) airmass, be it a non-Noneairmass passed in by the user or returned internally by pvlib.atmosphere.get_relative_airmass (when airmass=None). Specifically, _calc_delta applies a large, but bounded, max value to airmass when the zenith is at/over 90 degrees:
whereas get_relative_airmass normally returns NaN where solar_zenith >= 90.
I wonder how many perez test failures are due to this difference. I also wonder if that maximum airmass is specified anywhere in the literature, which @adriesse may recall. Will try to figure these out as time permits.
"plug-in replacement" is a quote from the paper pertaining to the model rather than the implementation. We did try to implement it in the same spirit by keeping almost the same signature, but did not back-port any improvements, like a cap on F1 for example.
The phrase "(careful using the 1/cos(z) model of AM generation)" has always bothered me because it seems to imply that it is ok to use this model. We probably should have dropped that phrase and put in a comment about KastenYoung instead. And we should have back-ported that.
The limits on the inputs to many models are not discussed in the literature and so we happily extrapolate beyond them in many cases. I think it is our responsibility to deal with limits in a reasonable manner in the implementations. Using Perez for zenith angle > 90 is extrapolating.
It does not make much sense to calculate the path through the atmosphere of sun rays when there are no sun rays, so in some contexts a value of nan seems logical and prevents nonsensical extrapolation of air mass values. Air mass is actually an intermediate variable in the Perez models. In this context, such nans are unhelpful.
If I understand correctly, you are mostly unhappy about non-matching nans. From memory, I think I did not want nans in tilted irradiance when my inputs had zero irradiance. I still don't.
If you want to update perez() to use helper functions, I suggest making a new _calc_epsilon()
Finally, I do think it is a very good idea to align the implementations more!
Activity
cwhanse commentedon Oct 3, 2026
@markcampanelli can you clarify a bit what you see as the problem(s) and what you suggest as the solution(s)?
markcampanelli commentedon Oct 3, 2026
@cwhanse Please see this recent commit for a choice that tries to better align
perezandperez_driesseinputs and functionality. Of course, a bunch of tests break, and I'd have to sort through and justify+fix all the differences.markcampanelli commentedon Oct 3, 2026
I think some of test breakages may have to do with changes between large air masses being bounded as a real number vs. being NaN, but I'd have to dig through the details to verify. Not sure when I'll have more time for that.
cwhanse commentedon Oct 3, 2026
So basically, you are proposing that
irradiance.perezuses the_calc_deltaand_calc_zetahelper function that was added forirradiance.perez_driesseirradiance.perezuses the_calc_zetahelper function that was added forirradiance.perez_driesseirradiance.perezdefaults to calculating airmass withkastenyoungifairmassis not provided, which implies thatairmassbecomes an optional rather than required argment.#1 may make sense,
_calc_deltaadds some handling of 0 / NaN values.#2 is a change in the underlying regressions (I think) so the result would no longer be the model that Perez published. If that's so, then #2 is a problem.
#3 is a change in behavior, that is not a significant problem because
airmassis fortuitously the last argument before named kwargs. I'm not necessarily opposed, but maybe we can handle the ambiguity by specifying the airmass model in the documentation.I'm still not clear what problems these changes will fix, or what is being gained by these changes.
markcampanelli commentedon Oct 3, 2026
@cwhanse Thanks for reviewing the proposed changes. Incidentally, I am not a huge fan of default values in Python, because removing or changing them then becomes a breaking change. I'd probably prefer newly accepting
Noneforairmasswhile not making it the default.The Notes for
perez_driessestate:Perhaps "plug-in replacement" does not refer to the code implementation in
pvlib? I almost always have to change my code when switching betweenperezandperez_driesse. Granted, these seem to be mostly for edge cases, but they are common enough that it still screws up results and (IMHO) reduces confidence in the library.markcampanelli commentedon Oct 4, 2026
Update here on the differences in relative airmass calculations:
In
perez_driessemakes an adjustment to the (relative)airmass, be it a non-Noneairmasspassed in by the user or returned internally bypvlib.atmosphere.get_relative_airmass(whenairmass=None). Specifically,_calc_deltaapplies a large, but bounded, max value toairmasswhen the zenith is at/over 90 degrees:whereas
get_relative_airmassnormally returnsNaNwheresolar_zenith >= 90.I wonder how many
pereztest failures are due to this difference. I also wonder if that maximum airmass is specified anywhere in the literature, which @adriesse may recall. Will try to figure these out as time permits.adriesse commentedon Oct 4, 2026
A few comments on the above discussion:
perez()to use helper functions, I suggest making a new_calc_epsilon()Finally, I do think it is a very good idea to align the implementations more!