-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Implement enhanced Faiman temperature model #1595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Early comments welcome, as always! @jsstein @mtheristis |
Ready for review. I'll do the sphinx stuff when it is clear which release this goes into. (The upcoming one I hope.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have a test that checks the output of this function matches the output of faiman, for default parameters.
:math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]` | ||
|
||
sky_view : numeric, default 1.0 | ||
Effective view factor limiting the radiative exchange between the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is "effective" adding something here? sky_view
looks to be the fraction of the sky dome "seen" by the module, so that's the usual view factor. I wonder if the formula could be considered part of the model and the input would be surface_tilt
, but I'll defer to the model author.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I snuck in the "effective" because the infra-red sky is very non-isotropic and that needs to be taken into account. The formula is really just a starting point for future work, not adequately explored and validated.
Co-authored-by: Cliff Hansen <[email protected]>
You mean, the test should call faiman to determine the expected value? |
Yes |
Additional reviewer(s) invited! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adriesse I've tagged this for 0.9.4 if you're ready to add a what'snew entry for this PR
Last chance to comment! @jsstein @mtheristis |
@adriesse, I am sorry for the delay. Out of curiosity, is there a reason we are only focusing on Faiman here? Or will the others (SAPM, NOCT, PVSyst) come later? |
Good questions. There were multiple considerations in my head. I decided to do one in order to keep the PR to a reasonable size and work through integration issues on one function rather than four at a time. I picked Faiman because it is the simplest but also because it is used in IEC 61853. When this feature is released I will point it out to interested parties in the working group for that standard. If there is user demand I see no problem to implement the other three and maybe enhance the generic linear model too. |
Understood. I am just thinking that we mind end up with X versions of a same base model, and the users might be confused with their differences. Is there a way to have an option when running faiman to say "include_radiative_losses = True/False"? Or is this bad practice? |
Well, it has taken a lot of years for the first enhancement to arrive and I'm not planning another one! Presenting this as an enhancement of something that people feel familiar and comfortable with is a strategy to gain acceptance more readily. It could
Perhaps in the system class or model chain something like this is possible. I'm not sure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool stuff and nice investigations :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reviewing, Adam. I'm glad you found the work interesting!
I responded with some comments and will hold off on code changes to see what other comments might appear...
PS. Sorry, I thought these would appear as replies to your comments. :(
PPS. Oh they do show up as replies. They're above as well as below! :)
pvlib/temperature.py
Outdated
u0 = np.asanyarray(u0) | ||
u1 = np.asanyarray(u1) | ||
emissivity = np.asanyarray(emissivity) | ||
|
||
abs_zero = np.array(-273.15) | ||
sigma = np.array(scipy.constants.Stefan_Boltzmann) | ||
|
||
if ir_down is None: | ||
qrad_sky = np.array(0.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
u0 = np.asanyarray(u0) | |
u1 = np.asanyarray(u1) | |
emissivity = np.asanyarray(emissivity) | |
abs_zero = np.array(-273.15) | |
sigma = np.array(scipy.constants.Stefan_Boltzmann) | |
if ir_down is None: | |
qrad_sky = np.array(0.0) | |
poa_global = np.asanyarray(poa_global) | |
temp_air = np.asanyarray(temp_air) | |
wind_speed = np.asanyarray(wind_speed) | |
ir_down = np.asanyarray(ir_down) | |
u0 = np.asanyarray(u0) | |
u1 = np.asanyarray(u1) | |
sky_view = np.asanyarray(sky_view) | |
emissivity = np.asanyarray(emissivity) | |
abs_zero = -273.15 | |
sigma = scipy.constants.Stefan_Boltzmann | |
if ir_down is None: | |
qrad_sky = 0.0 |
I see that the usage of np.asanyarray is very carefully chosen such that all inputs can be passed as lists and directly or indirectly be converted to arrays. The indirect conversion to arrays (by multiplying a list something array-like) seems undesirable and unintuitive to the user. Why not instead just convert all the inputs to array-like in the beginning and be straightforward about it?
It's not a blocker for me, but this is the point that I was trying to raise earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the whole I believe this function behaves like numpy would. The reason for the indirect and partial approach is to allow pandas and xarray data structures to be propagated from the first four arguments. Try it, you might like it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about this function requires any of the np.asanyarray
calls? np.asanyarray
is not robust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, now I see the hidden conversation about allowing list
input. That is not needed and comes at a cost of disallowing arbitrary array-like input that doesn't fully support the asanyarray machinery (e.g. dask, or whatever the pydata library of the month is).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on what doesn't work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I'm getting more push-back than expected on something which I though was a very simple technique to make the function very flexible. If there is a concrete down-side I'd like to learn about it, especially the risks associated with asanyarray
(which could be replaced with asarray
in this particular function). I've use this technique before and am likely to use it again unless there really is a problem with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function is already very flexible because you did a good job writing it :). It doesn't need asanyarray
! Here's a concrete downside for asanyarray
:
In [1]: import numpy as np
In [2]: import dask.array as da
In [3]: da.from_array([0, 1])
Out[3]: dask.array<array, shape=(2,), dtype=int32, chunksize=(2,), chunktype=numpy.ndarray>
In [4]: np.asanyarray(da.from_array([0, 1]))
Out[4]: array([0, 1])
In [5]: np.asarray(da.from_array([0, 1]))
Out[5]: array([0, 1])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
np.asanyarray
is not robust.
I am curious to learn more about this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Anton, here's a quote from NEP16
Sometimes people suggest using np.asanyarray for this purpose, but unfortunately its semantics are exactly backwards: it guarantees that the object it returns uses the same memory layout as an ndarray, but tells you nothing at all about its semantics, which makes it essentially impossible to use safely in practice.
The scientific python brain trust has discussed solutions in a variety of venues and I find it very difficult to track, but here's a very incomplete list of links:
- https://numpy.org/neps/nep-0022-ndarray-duck-typing-overview.html
- https://labs.quansight.org/blog/2021/11/pydata-extensibility-vision
- https://discuss.scientific-python.org/t/spec-2-api-dispatch/173
I think we have another issue or two related to this, so probably best to continue discussion there rather than a closed PR :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! That was educational!
Thank for all the reviews!! |
docs/sphinx/source/reference
for API changes.docs/sphinx/source/whatsnew
for 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.