-
Notifications
You must be signed in to change notification settings - Fork 1.1k
implement transient moving-average thermal model #1081
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
Comments
@mjprilliman FYI |
I've taken a look at implementing this but am not satisfied with what I've come up with so far. Here are my notes in case anyone else is working on this. Option 1:
|
Hi Kevin, I'd like to help with this implementation. I had previously written a standalone Python script that was running the model accurately but I will have to revisit to see how or if it can tie in with the existing framework. I am working on SAM features this week but I can start working on this next week (possibly late this week) if that works. |
For reference this is the Python function I was using in my grad studies, although most of the model development and validation was done in Matlab. |
@kanderso-nrel I didn't realize that If performance is a roadblock, for irregular data on short intervals, resampling seems appropriate. |
Thanks @mjprilliman, it'll be interesting to see how your implementation compares. It's good to have a reference implementation too. I don't think this function is tied to a deadline so of course whenever you can find the time for it is fine.
@cwhanse I forgot to mention this earlier but you can specify |
def moving_average(x, window=5):
"""
Moving average of numpy array
Parameters
----------
x : numeric
a numpy array to average
window : int
the window over which to average
Returns
-------
an array of the same size with index at beginning of window
If ``window <= 1`` then do nothing and return ``x``.
"""
if window <= 1: return x
m = window - 1
y = np.pad(x, (0, m), 'edge')
z = 0
for n in range(window):
z += np.roll(y, -n)
return z[:-m] / window It's right bounded, so not sure how to backfill or center. I using |
The built-in functions are definitely way faster. The problem is that I didn't see a way to implement the exponential weighting using only the built-in functions, so I went with
The issue there, assuming we want to accommodate irregular sampling, is that the window size can vary based on how many timestamps fall into the last |
I recently became aware of |
Here are a few prototype implementations. Note that the output is very slightly different from the function @mjprilliman posted above -- I've not yet chased down the difference but it's good enough for proof of concept anyway. tl;dr: the numpy-based implementations are quite fast but assume regular sampling. https://gist.github.com/kanderso-nrel/1d6da384d7af8afc24c230f1f144eb57 I still think it's a shame to not support irregular sampling, but the performance penalty of using pandas here is so huge that I think we should just require regular sampling. It's certainly much better than nothing, which is what we've had since this issue was opened (October 2020...). One question for @mjprilliman: the handful of temperature near the start of the inputs don't have a full window of previous conditions to average across. The numpy implementations in my notebook linked above return NaN for those points, but your example implementation uses whatever values are available, even if they don't comprise a full 20-minute window. I think yours is more faithful to the reference's equations, but I wonder if mine is more consistent with its spirit? Which approach do you think makes sense here? |
Hi Kevin, Thanks for these examples. For your question, I would say the spirit of the model would be to include anything within the window even if there is not a full window to look back on. But taking model speed into account I think your v3 and v4 approaches make the most sense even without the partial window calculations. I would imagine in most use cases the first 20 minutes of data would occur in thermal equilibrium (night time) so a steady-state model would be sufficient. There could always be edge cases where some of the thermal inertia is not captured in the first time steps of a model but I think the speed up is worth more. Just my thoughts maybe @jsstein feels differently. |
Nice work, Kevin. Based on a comment in the code, I wonder if this could help for the pandas version: |
I think the numpy functions could be modified to do this without a meaningful increase in runtime. I'll try that out before opening a PR. Thanks! @adriesse I think that SO answer is essentially the same approach taken in the notebook: use the index of the moving subset to retrieve the corresponding subset of other columns. Maybe that notebook code could be made clearer, but I think the workaround to access multiple time series in a single rolling window is the same. Great minds think alike I guess ;) |
I don't see that as a major problem. This function operates on the output of a temperature model (applies a form of exponential smoothing). It is likely that a user calculated that output with a regular time index. Even if not, the smoothing basically justifies interpolation on the input cell temperature and wind speed to a regular index, in the following sense: output from applying the function to interpolated input is likely to be very similar to output when applying the function to the non-regular input then interpolating the output. |
New Feature
Implement the transient moving-average model proposed by Matt Prillman
Describe the solution you'd like
a new function
pvlib.temperature.prillman(times, ...)
Describe alternatives you've considered
see also #1080
Additional context
see NREL/ssc#261
The text was updated successfully, but these errors were encountered: