DRAFT: Handle dni/dhi=0/0 in irradiance.perez without NaNs#2808
DRAFT: Handle dni/dhi=0/0 in irradiance.perez without NaNs#2808markcampanelli wants to merge 15 commits into
Conversation
| # eventually be used as indicies for coeffecient look ups | ||
| ebin = np.digitize(eps, (0., 1.065, 1.23, 1.5, 1.95, 2.8, 4.5, 6.2)) | ||
| ebin = np.array(ebin) # GH 642 | ||
| ebin[np.isnan(eps)] = 0 |
There was a problem hiding this comment.
@pvlib/maintainers I question if this is wise. Perhaps if a user passes a NaN for DNI or DHI (presumably resulting in a NaN for eps), then the function should fail?
There was a problem hiding this comment.
I think nan in -> nan out is the philosophy we try to adhere to. Dunno what makes more sense for this specific case.
There was a problem hiding this comment.
K thanks. Sorry I had missed that.
There was a problem hiding this comment.
It ain't something to be sorry about, it a legitimate question (the motto, better safe than sorry).
Discussions related to this point:
- Consider updating pvlib.tracking.singleaxis() to return zeros (or similar) for nighttime instead of NaNs #2539
- Set negative values of AOI loss to 0 rather than np.nan #338
And there was one regarding ModelChain, don't remember exactly where.
There was a problem hiding this comment.
I added many more combinations of NaN DNI and DHI to the new tests.
There was a problem hiding this comment.
@echedey-ls So in my testing, I realized that if airmass is NaN, then this trumps DNI or DHI being NaN, and the result is zero instead of NaN (including the components, when returned). That sounds like incorrect behavior. Would you agree?
There was a problem hiding this comment.
I changed the function's behavior to preserve NaNs inherited from DHI or DNI. New test now passing again.
| diffuse_components['poa_horizon'] = dhi * term3 | ||
|
|
||
| # Set values of components to 0 when sky_diffuse is 0 | ||
| mask = sky_diffuse == 0 |
There was a problem hiding this comment.
@cbcrespo I think this is where one has to be careful about the order of operations when computing the components first and then summing to get the total.
A very edgy case here would be if the components added up to zero, but are themselves not all zero (indeed some components can legitimately be negative in this model). This would likely be exceedingly rare for typical floating point calculations, however.
That said, I think the algorithm semantics would be easier to follow if:
- The components were computed first.
- The sum of components was computed next.
- Finally, the total and components are all set to zero if the sum is (strictly) negative.
Although, if a negative total comes out, should this function raise instead?
(I tend to like things to break obviously rather than fail silently, and a negative total sounds like a model breakage to me, but I could be mis-interpreting the situation.)
There was a problem hiding this comment.
On second thought, the "spirit of pvlib-python" might be to set everything to NaN if the total comes out negative, instead of raising.
|
@pvlib/maintainers I have two outstanding issues before moving this out of DRAFT and requesting a full review:
I think returning NaNs instead of raising is probably closer to what users expect, but I am not sure here. If this is true, then I can change both of the above cases to return NaNs. |
There was a problem hiding this comment.
@markcampanelli can you populate this table? I'm having trouble following the intent of handling the combinations of 0 and/or NaN
| air mass | DHI | DNI | sky diffuse output |
|---|---|---|---|
| 0 | 0 | 0 | |
| 0 | 0 | NaN | |
| 0 | NaN | 0 | |
| 0 | NaN | NaN | |
| NaN | 0 | 0 | |
| NaN | 0 | NaN | |
| NaN | NaN | 0 | |
| NaN | NaN | NaN |
| surface using the surface tilt angle, surface azimuth angle, diffuse | ||
| horizontal irradiance, direct normal irradiance, extraterrestrial | ||
| irradiance, sun zenith angle, sun azimuth angle, and relative (not | ||
| pressure-corrected) airmass. Optionally a selector may be used to | ||
| use any of Perez's model coefficient sets. | ||
| horizontal irradiance (DHI), direct normal irradiance (DNI), | ||
| extraterrestrial irradiance, sun zenith angle, sun azimuth angle, and | ||
| relative (not pressure-corrected) airmass. Optionally a selector may be |
There was a problem hiding this comment.
Let's remove the list of input quantities. That was ported from Matlab before the current docstring format was settled.
I added components columns and four rows to the end of your table template. The first added row shows a negative sky-diffuse The last two added rows actually raise a After making this table, it is unclear to me if a NaN airmass should supersede a "nonsensical" DHI+DNI combo, for example, DHI=0 and DNI=100. If "NaN airmass wins", then the output is all zeros, if "nonsensical DHI+DNI" wins, then output is all NaNs. Which to choose? |
Co-authored-by: Cliff Hansen <cwhanse@sandia.gov>
Co-authored-by: Cliff Hansen <cwhanse@sandia.gov>
|
@cwhanse If I remove raising the More broadly, should this |
|
@markcampanelli as a general rule (but not always), pvlib avoids checking inputs. GIGO applies. Case e is an exception to the usual nan-in/nan-out philosophy, but it's been that way forever so I'm not inclined to suggest changing it. Case j is a variation of case e, so to be consistent, 0 output. Case l is a problem that illustrates why the nan-in/nan-out rule has value. If pvlib outputs nan, then we'd do that by removing the overwriting airmass nan with 0 (Cases e and j). Since I'm not inclined to change that behavior, pvlib outputs 0 for case l. Otherwise we write some more complicated logic - ugh. Case i: I'd prefer to output the negative numbers rather than substituting nan where the values are non-physical (this was likely the motivation for overwriting airmass nan). Outputting nan should be a clue that you've got nan inputs. Outputting negative irradiance is a different signal - you're using the model outside it's intended range. |
return_components=True#2801docs/sphinx/source/referencefor API changes.docs/sphinx/source/whatsnewfor all changes. Includes link to the GitHub Issue with:issue:`num`or this Pull Request with:pull:`num`. Includes contributor name and/or GitHub username (link with:ghuser:`user`).remote-data) and Milestone are assigned to the Pull Request and linked Issue.