Repository navigation
Nonannual resource models - #897
Conversation
| Returns: | ||
| bool: True if the year is a leap year | ||
| """ | ||
| is_leap = (year % 100 == 0 and year % 400 == 0 and year % 4 == 0) or ( |
There was a problem hiding this comment.
This is hard to read. Is there a problem with using the pandas check?
There was a problem hiding this comment.
this is different than proces_leap_day(). This just checks to see if a year (integer) is a resource year - not if resource data contains Feb 29th.
| ) | ||
|
|
||
| # If only running 1 year, then only valid option is 'start_year' | ||
| if n_data_years == 1 and self.config.resource_year_setting != "start_year": |
There was a problem hiding this comment.
Does this still allow for one year with a file?
There was a problem hiding this comment.
yes - if self.config.resource_year_setting it 'start_year' then it runs as it always used to.
jaredthomas68
left a comment
There was a problem hiding this comment.
Lots of what I'm seeing looks very similar to what I have, but with an improved interface and excluding the sampling
…urce year is input as a dummy-value when using filenames setting
genevievestarke
left a comment
There was a problem hiding this comment.
Overall, I think this looks great! I love the functionality here, @elenya-grant!!
I don't have a ton of comments beyond what others have said. I like the ability to have non-consecutive years, and acknowledge that that's responsibility that we put on the user. If I understand it correctly, you can set resource_year, and the number of time steps, and that will give you a consecutive year simulation, right?
I think it makes sense to have resource_year_setting be inferred internally, though I would have to put more time in to see what all the different combinations of specifying data and simulation years that are available.
Finally, I think this is an important feature to have an example on, as well as some nice docs pages to cover all the input options!
| 1) Check if resource data was input. If not, continue to Step 2. | ||
| 2) Determine the resource years and resource filenames to loop through based on | ||
| ``config.resource_year_setting`` | ||
| 3) Loop through the resource years and resource filenames, calling ``get_data()`` |
There was a problem hiding this comment.
| 3) Loop through the resource years and resource filenames, calling ``get_data()`` | |
| 3) Loop through the resource years and resource filenames, calling ``get_data_for_year()`` |
This should be updated in the doc string, right?
There was a problem hiding this comment.
thanks! updated!
| if not infer_years_from_files: | ||
| resource_years = self.inferred_resource_years |
There was a problem hiding this comment.
I'm a little confused what's happening in this line?
There was a problem hiding this comment.
I tried to add inline comments - let me know if its been cleared up?
| # Get the number of hours in the simulation | ||
| hours_simulated = (self.dt / 3600) * self.n_timesteps | ||
|
|
||
| if future_hours_available < hours_simulated: |
There was a problem hiding this comment.
Because this is in hours, it feels like there could be issues with this logic when we move to smaller time steps (if we are using 10 minute time steps, the hours_simulated number could be 8760.5 and future_hours_available could be 8760 since we're going off of rounded hours, even if the data includes the data for 8760.5 times in 10-minutes time steps).
There was a problem hiding this comment.
I see what you're saying - but I think that resource data is always downloaded for one year. If we use 10 min intervals, then future_hours_available would still be 8760 hours (but 6x the number of timesteps). Maybe I don't understand your comment?
There was a problem hiding this comment.
Ok, working through it again, I think it should still be fine! Sorry, it didn't make sense to me earlier in the day :)
…source_api/multi_year
jaredthomas68
left a comment
There was a problem hiding this comment.
Thank you for this @elenya-grant !!!!
| if len(most_often_yr) == 1: | ||
| return most_often_yr[0] | ||
|
|
||
| if len(most_often_yr) > 1: |
|
Thanks for your edits, Elenya! I agree with Kaitlin that if we're going to allow non-consecutive years, we should raise a warning to make it clear to users that's happening. Could you please add that in, or is there a good reason to not do that? I've made new issues #907 and #908 to help track follow-on work based on comments. Please edit those directly if you want! |
Multi-year resource
Updated the API resource models to be able to accommodate multiple years and partial years (with somewhat exhausting handling of leap years even though the solar resource models won't even use it...).
There are 3 different ways that a user can provide inputs if running multiple resource years. The attributes
resource_year_orderandresource_filenameare what indicates what option the user is using. The options are:resource_yearis start year: user providesresource_yearas the first year to get resource data for, the following resource years are auto-calculated based on the number of timesteps and dt of the simulation. If running a simulation <= 1 year, thenresource_filenamecan be a string (or not input, same logic as before) andresource_year_ordermust be None. Consecutive years are auto-calculated based on the number of timesteps in the simulation and the years available for the resource model. An error is raised if not enough future years are available.resource_filenameattribute to use to get the resource data. The number of filenames must match the number of years needed to get the proper number of timesteps.resource_year_ordercan be provided too. Ifresource_year_orderis not provided, then the resource years are estimated from the resource files on the first call (from filenames if using a TMY dataset, from the timeseries data if using other datasets).resource_year_orderis only used if the site changes.resource_year_orderattribute to use to get resource data, the number of resource years provided must match the number of years needed to get the proper number of timesteps.Basically, for running more than 1 year, the valid options are:
resource_yearonly (do not provideresource_year_orderorresource_filename)resource_filenameas a list andresource_year_orderas None (years are inferred)resource_filenameas a list andresource_year_orderas a listresource_year_orderas a list and do not provideresource_filenameOther notable changes:
include_leap_dayattribute which is used for API calls and resource modifications (as necessary)load_data()method doesnt useself.config.resource_yearand instead generalized that logic to be in the resource baseclass.Most new-functionality is tested (right now) in
h2integrate/resource/solar/test/test_multiyear_solar_resource.pyWork planned for Follow-On PR(s):
Section 1: Type of Contribution
Section 2: Draft PR Checklist
TODO:
time_tools.pyanddata_tools.py(in-progress)resource_baseclass.py(in-progress)process_final_resource_data,get_resource_years_from_start_year,check_resource_year)Type of Reviewer Feedback Requested (on Draft PR)
Structural feedback:
_check_resource_yearmethod in the resource_baseclass be turned into a function? not turned into a functionget_resource_years_from_start_year()method in the resource_baseclass be turned into a function? not turned into a function1.
include_leap_dayis True2. the resource year is a leap year
3. the resource year does not contain leap-day-data
filenamessetting, what should happen if the site changes? Should we try to infer the resource year order based on the resource data that was loaded before the site changed? Should we throw a user-warning? Right now, it will just use theresource_yearinput in the config and repeat it for however many timesteps are needed.the usage ofclip_data_to_resource_year()in the resource baseclass is purely because of the OpenMeteo resource models. Should the usage of this function (and it's sister-functionestimate_resource_year_from_data()), be moved to the OpenMeteo resource modelsload_data()method or continue to stay in the resource baseclass? (I think they should be moved to the OpenMeteo resource models).Implementation feedback:
resource_settingoptions?Other feedback:
Section 3: General PR Checklist
docs/files are up-to-date, or added when necessaryCHANGELOG.md"A complete thought. [PR XYZ]((https://github.com/NatLabRockies/H2Integrate/pull/XYZ)", where
XYZshould be replaced with the actual number.Section 4: Related Issues
Section 5: Impacted Areas of the Software
The main changes are in the following files:
h2integrate/resource/resource_baseclass.py: changes to config and baseclass. A lot of the logic that was inget_data()is now in the methodget_data_for_year().h2integrate/resource/utilities/data_tools.py: new file with new toolsh2integrate/resource/utilities/time_tools.py: added and modified some existing tool functionsh2integrate/resource/solar/test/test_multiyear_solar_resource.py: new test file to test multi and partial year logicSection 5.1: New Files
h2integrate/resource/utilities/data_tools.py: new file containing function/tools for processing/modifying/interpretting resource dataseparate_timeseries_and_meta_data(): separate the resource data dictionary into two separate dictionaries, one with meta-data and one with timeseries dataappend_timeseries_data(): append timeseries data from one dictionary to anotherclip_data_to_n_timesteps(): clip timeseries data to a specified number of timestepsclip_data_to_resource_year(): clip timeseries data to a single resource year. Only needed because of OpenMeteo resource models.estimate_resource_year_from_data(): clip timeseries data to a single resource year. Only needed because of OpenMeteo resource models.Section 5.2: Modified Files (of interest)
h2integrate/resource/resource_baseclass.pyResourceBaseAPIConfig: added new attributes or types, noted in section 1. Also added an__attrs_post_init__()method to check for conflicting inputs based on theresource_year_setting.ResourceBaseAPIModelsetup(): added some checks if running more than 1 resource year, basically additional checks based on simulation length andresource_year_settingget_data(): this contains the first two "steps" in the previousget_data()method but now also loops through resource years.get_data_for_year(): this contains the remainder of the logic that previously existed inget_data().process_final_resource_data(): new method that does some final clean-up and testing of resource data after all the resource data for all the necessary resource years has been loaded_check_resource_year(): new method that checks if a resource year is valid (could be simplified, noted with a Note in the code)get_resource_years_from_start_year(): new method. This gets the valid future resource years if usingresource_year_settingas 'start_year'create_url(): addedresource_yearas an inputcreate_filename(): addedresource_yearas an inputh2integrate/resource/utilities/time_tools.pyis_leap_year: new function that returns boolean indicating whether the input year is a leap year or notprocess_leap_day(): modified, the 'checking' part of this function was moved to a new functioncheck_data_length()check_data_length(): new function that contains the previous 'checking' logic that previously existed inprocess_leap_day().get_number_of_resource_years_needed(): new function, determines the number of resource years needed to get enough data for the simulation lengthSection 5.3: Deleted Files
resource_files/wind/*.srwexamples/25_sizing_modes/tech_inputs/hopp_config_tx.yamlresource_files/solar/27.18624_-96.9516_psmv3_60_2013.csvresource_files/solar/34.22_-102.75_psmv3_60_2013.csvresource_files/solar/34.865371_-116.783023_psmv3_60_tmy.csvresource_files/solar/39.7555_-105.2211_psmv3_60_2012.csvresource_files/solar/47.5233_-92.5366_psmv3_60_2013.csvSection 6: Additional Supporting Information
The resource models walk a fine-line between allowing opportunities for possible needed workarounds for single site simulations while also ensuring that when the site has changed, that resource data is updated in cases that it can be.
If a user provides resource data in the config as a dictionary, nothing about this resource data is checked for accuracy or alignment (the resource model basically acts as a pass-through, regardless of if the site changes or anything).
For example, if a resource filename is provided (and that file exists) and the site hasn't changed since setup() has been called, then there is nothing preventing a user from providing a resource file that:
However, if the site changes, then user-provided resource filenames are no longer used and resource data is ensured to be accurate for that site, resource year, timezone, timestep, etc.
This PR aims to maintain that fine-line and allow for the same flexibility as long as the site doesn't change.
Section 7: Test Results, if applicable
Things that are hard to test