-
Notifications
You must be signed in to change notification settings - Fork 27
Enable multiple site functionality #434
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
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
johnjasa
left a comment
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 being on the ball and putting this together! It adds some neat capability that we'll obviously need for multiple projects, and I love that you've both modified existing examples and added a new example to really showcase everything.
I put mostly high-level comments and questions throughout. Happy to chat through them if you'd find it useful, but I'm hoping others can see my thoughts typed out here and benefit from them as they review this PR too.
| site_groups: | ||
| solar_site: | ||
| site_model: "location" | ||
| site_parameters: | ||
| latitude: 30.6617 | ||
| longitude: -101.7096 | ||
| resources: | ||
| solar_resource: | ||
| resource_model: "goes_aggregated_solar_v4_api" | ||
| resource_parameters: | ||
| resource_year: 2013 | ||
| resource_dir: "../11_hybrid_energy_plant/tech_inputs/weather/solar" | ||
| resource_filename: "30.6617_-101.7096_psmv3_60_2013.csv" | ||
| wind_site: | ||
| site_model: "location" | ||
| site_parameters: | ||
| latitude: 35.2018863 | ||
| longitude: -101.945027 | ||
| resources: | ||
| wind_resource: | ||
| resource_model: "wind_toolkit_v2_api" | ||
| resource_parameters: | ||
| resource_year: 2012 |
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 updating this example (that already uses disparate locations) for the new site setup!
| resource_filename: "30.6617_-101.7096_psmv3_60_2013.csv" | ||
| site_groups: | ||
| solar_site: | ||
| site_model: "location" |
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 other values are you envisioning being allowed for site_model? is it always "location"? or is it a nickname for a location?
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.
"location" or "boundary" are the current options, they're in supported_models
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 don't see why they need to be different models. Could we just make boundaries optional and allow techs that need boundaries to throw an error if no boundaries are provided?
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.
removed the idea of "site_model" since we only have one site component model now.
| wind_site.wind_resource.latitude,wind_site.wind_resource.longitude,solar_site.solar_resource.latitude,solar_site.solar_resource.longitude,solar.system_capacity_DC | ||
| 35.2018863,-101.945027,35.2018863,-101.945027,25000.0 | ||
| 35.2018863,-101.945027,35.2018863,-101.945027,50000.0 | ||
| 35.2018863,-101.945027,34.22,-102.75,25000.0 | ||
| 35.2018863,-101.945027,34.22,-102.75,50000.0 | ||
| 39.22629,-82.938,35.2018863,-101.945027,25000.0 | ||
| 39.22629,-82.938,35.2018863,-101.945027,50000.0 | ||
| 39.22629,-82.938,34.22,-102.75,25000.0 | ||
| 39.22629,-82.938,34.22,-102.75,50000.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.
Correct me if I'm wrong: all of these sites required API access to download weather information because we don't have the data saved in the repo. That means that this example can't be easily tested via CI as we don't have the API key included. Is that right? If so, do you have another way to test multiple sites in an integration test?
I know you didn't tackle this for this stage of the PR because you're looking for high-level feedback, but I'm commenting this now mostly so I don't forget!
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 catching that! I can update the locations and add in a resource file or two if needed so that it can run with the CI tests. I am not sure whether I have a unit test or integration test yet - I'll be sure to add those in though!
| site_parameters: | ||
| latitude: 34.22 | ||
| longitude: -102.75 |
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 we have latitude and longitude live at the same level as site_model and get rid of the site_parameters nesting? Do you expect other values to go into that site_parameters level later that aren't represented here? I ask this because we could remove some nesting this way and it more closely matches the case when there's one site and lat and lon are at that top level alongside resources
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 was trying to format the site things similar to the finance groups and the technology definitions. We define a model and the the model_inputs but - I suppose that's not fully necessary. I think that it maybe does make sense to have latitude and longitude live at the same level as site_model and to remove site parameters/
| if "site_groups" not in self.plant_config: | ||
| if "site" in self.plant_config: |
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'm not in love with the ability to have either site or site_groups at the top level, mostly because it leads to logic like this and the fact that the user has two potential entry points. I do love that you've been thinking about backwards compatibility and made sure the other way works too.
That being said, do you see the ability to have site_groups and site available remaining for all future versions of H2I? Is there a world where we only allow users to define sites as plural and the singular case is a subset of that?
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.
It could also just be site and check for lat and lon in the next level of nesting and if not there then we know it's multiple sites.
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.
Yeah - either of these options seem good to me!
If we choose one way of defining site or site_groups - then should we also require that the site is specified in resource_to_tech_connections if theres only one site? Prior to this PR - the resource_to_tech_connections looked like this:
resource_to_tech_connections: [
['wind_resource', 'wind', 'wind_resource_data'],
['solar_resource', 'solar', 'solar_resource_data'],
]but - should we require it to be?
resource_to_tech_connections: [
['site.wind_resource', 'wind', 'wind_resource_data'],
['site.solar_resource', 'solar', 'solar_resource_data'],
]The logic in H2I connect_technologies() right now is that if there isn't a . in the first entry of a connection (lets call it resource_source), it will connect f"site.{resource_source}" to the second entry of the connection (the tech). But - if there is a . in the resource_source, then it'll connect f"{resource_source}" to the tech, because the . indicates that the site was specified in the connection.
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.
Great question and thanks for the context. In the case of having just one site, I like the idea of not having to specify the site in the connections. I don't love the behind-the-scenes logic based on the .. I do like the idea of connections looking the same if you have one site or multiple, though. I think I'm leaning towards requiring the latter (so the site is always specified), mostly so the connections look the same if you have one site or multiple. Open to feedback 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.
I agree with @johnjasa here that consistency is better in this case than backwards compatibility.
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 also agree with this! I'd rather it be specified than inconsistent!
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.
@johnjasa - do you prefer site or site_groups as the top-level key? I think site_groups makes more sense.
| if "site" not in plant_config and "site_groups" not in plant_config: | ||
| msg = "Missing attribute site or site_groups in plant_config" | ||
| raise ValueError(msg) |
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.
Nice check here!
| if "site" in self.plant_config: | ||
| resource_models = self.plant_config.get("site", {}).get("resources", {}) | ||
| if "site_groups" in self.plant_config: | ||
| resource_models = {} | ||
| for site_grp, site_grp_inputs in self.plant_config["site_groups"].items(): | ||
| for resource_key, resource_params in site_grp_inputs.get("resources", {}).items(): | ||
| resource_models[f"{site_grp}-{resource_key}"] = resource_params | ||
|
|
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.
This is another spot that motivates my previous comment about potentially moving towards just one way to define site(s) in the future. This could lead to more easily maintainable code once we no longer need the backwards compatibility.
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'm down to only have one way of defining sites!
h2integrate/core/sites.py
Outdated
| class BoundarySiteComponent(SiteBaseComponent): | ||
| def __init__(self, site_config: dict, name=None, val=1.0, **kwargs): | ||
| self.config = BoundarySiteComponentConfig.from_dict(site_config) | ||
| super().__init__(name, val, **kwargs) | ||
|
|
||
| def set_outputs(self): | ||
| # latitude and longitude are set as outputs in ``SiteBaseComponent.__init__()`` | ||
| self.add_output("elevation", val=self.config.elevation, units="m") | ||
|
|
||
| for i, boundary in enumerate(self.config.boundaries): | ||
| self.add_output(f"boundary_{i}_x", val=np.array(boundary.get("x", []))) | ||
| self.add_output(f"boundary_{i}_y", val=np.array(boundary.get("y", []))) |
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.
Tell me more about this component; why does it exist and what does it do differently than the location site above?
In general, since we're not necessarily doing plant layout or really considering the boundaries, I'm thinking we could get rid of all notion of boundaries within H2I. In the future, we could reexamine and add that capability when needed. I'm not asking you to change this PR or remove all the boundaries from here, but would you be amenable with that path forward? Is there a reason to include boundaries at this time?
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 idea with site_model is to specify different types of sites, to me the different types of sites that I could envision immediately are:
- unbounded location ("location" model)
- bounded location ("boundary" model - I'm not sure if Ard takes into account site boundaries (@jaredthomas68), but that's why I added it in for now. Happy to remove it for the time being since its unused)
- transit/transport route model with multiple lat/lons.
All that being said - the BoundarySiteComponent is not necessary for this 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.
Got it, thanks again for the detail. I'd say we should stick to just one site definition type using lat/lon right now, remove the BoundarySiteComponent and then you wouldn't need the inherited class structure for the sites. I do really like that you started down that path, though! My goal is to keep the available models and options limited to things that are actually implemented until we get further down the line.
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.
Ard does include boundaries, but can just own their definition. I imagine we will need boundary definition eventually, especially for nice visualizations, but I also think we don't need them defined right now outside of wind farm codes that require them that is.
| prefix="finance_", | ||
| ) | ||
|
|
||
| def create_site_model(self): |
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.
In general, I'd like to see more comments and docstrings in this method, but I acknowledge right now we're giving high-level feedback so this might shift. More just noting it for later -- and I'll acknowledge that the existing method didn't have a docstring!
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 added a simple doc strings and in-line comments.
|
Thanks for your responses and iteration here, @elenya-grant! Based on that, I'd say we should:
I put more context in my text responses to you, but do let me know if you want clarification on anything. |
jaredthomas68
left a comment
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 really like where this is going. Thank you @elenya-grant! I left some comments, but nothing major outside of what has already been mentioned. I left a few comments though.
I did not note specifically, but it looks like there are no tests for specific methods/functions. I would like to see each method or function added have accompanying tests.
| " latitude: 47.5233\n", | ||
| " longitude: -92.5366\n", | ||
| " elevation_m: 439.0\n", | ||
| " elevation: 439.0\n", |
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 like having the _m in here for clarity. Why did you decide to remove 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.
cause we can specify units within OpenMDAO, but I see the value of having '_m' in the variable name in the plant config, whereas the variable name for the site (which has units) could just be elevation.
| # connect the wind resource to the wind technology | ||
| ['wind_resource', 'wind', 'wind_resource_data'], | ||
| ['solar_resource', 'solar', 'solar_resource_data'], | ||
| ['wind_site.wind_resource', 'wind', 'wind_resource_data'], |
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.
in other places we have connections that can be different lengths for when certain information is used or not. I'm fine with the . syntax, but it may be good to have a consistent approach. - non-blocking comment.
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.
an alternative would be to change resource_to_tech_connections to be 4-length tuple:
['wind_site', 'wind_resource', 'wind', 'wind_resource_data']
where the organization is [site_name, resource_name, tech_name, variable_to_pass]
do you like the 4-length tuple more than the 3-length tuple (['wind_site.wind_resource', 'wind', 'wind_resource_data']) which is formatted as [site_name.resource_name, tech_name, variable_to_pass]`?
I'd also be curious what @johnjasa, @kbrunik, and @genevievestarke think about the different ways of organizing resource_to_tech_connections to accommodate this new update.
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 I'm still pro 3-way connection. I know we discussed in the standup but I see that being most similar to our current tech connections. Potentially could be reopened in the future but I see it working as 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.
I like where we landed after our discussion with the 3-way connection!
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.
Same
| if "site_groups" not in self.plant_config: | ||
| if "site" in self.plant_config: |
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 agree with @johnjasa here that consistency is better in this case than backwards compatibility.
| site_group = self.create_site_group(plant_config_reorg, site_info) | ||
| self.model.add_subsystem(site_name, site_group) | ||
|
|
||
| def create_site_group(self, plant_config_dict: dict, site_config: dict): |
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.
If there is a way to simplify the logic so we can use class attributes instead of creating copies of the configs I think it would help avoid errors. I think having a single syntax for sites (site_groups > site, etc) would make it so you could use the class attributes self.plant_config and self.site_config directly instead of passing them around.
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 did make it somewhat simpler by not allowing backward compatibility with the previous format of sites.
Some of this complexity is similar to the complexity required for the finance groups and subgroups, because the resource models (and finance models) expect certain keys in the plant_config and don't know the name of their model. Resource models expect site at a top-level (rather than 'sites') and since the resource models are blind to what site they're apart of (or what the name of that site is), we have to reformat the plant config prior to initializing the resource models to only include the site that the resource model is connected to.
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.
OK, I still don't love the copying, but I'll role with it. Thanks for the explanation and some simplification
h2integrate/core/sites.py
Outdated
| class BoundarySiteComponent(SiteBaseComponent): | ||
| def __init__(self, site_config: dict, name=None, val=1.0, **kwargs): | ||
| self.config = BoundarySiteComponentConfig.from_dict(site_config) | ||
| super().__init__(name, val, **kwargs) | ||
|
|
||
| def set_outputs(self): | ||
| # latitude and longitude are set as outputs in ``SiteBaseComponent.__init__()`` | ||
| self.add_output("elevation", val=self.config.elevation, units="m") | ||
|
|
||
| for i, boundary in enumerate(self.config.boundaries): | ||
| self.add_output(f"boundary_{i}_x", val=np.array(boundary.get("x", []))) | ||
| self.add_output(f"boundary_{i}_y", val=np.array(boundary.get("y", []))) |
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.
Ard does include boundaries, but can just own their definition. I imagine we will need boundary definition eventually, especially for nice visualizations, but I also think we don't need them defined right now outside of wind farm codes that require them that is.
genevievestarke
left a comment
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 this is looking really good!! I don't have specific comments beyond the other comments made on this PR. Thank you for your work on this @elenya-grant !
|
Just discussed this more with Elenya and Kaitlin:
|
kbrunik
left a comment
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.
This looks great! Thanks :)
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.
Can we update from xx and the 23 to 27?
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.
done!
| The `resource_to_tech_connections` section in your plant configuration file defines how different technologies are connected to sites and the resource data for that site. | ||
| This is how the H2I framework establishes the necessary OpenMDAO connections between your sites and technologies based on these specifications. | ||
|
|
||
| Resource to technology connections are defined as an array of 3-element arrays in your `plant_config.yaml`: |
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.
Are these arrays or lists?
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.
idk - I used the word array because that what was used in docs/user_guide/connecting_technologies.md to describe the technology interconnections.
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 array is valid here, as yaml has a slightly different lingo than Python: https://stackoverflow.com/a/33136212
| - **site_name**: Name of the site for the resource model | ||
| - **resource_name**: Name of the resource model outputting the resource data | ||
| - **tech_name**: Name of the technology receiving the input resourec data | ||
| - **variable_name**: The resource variable name to pass from the site to the technology ("wind_resource_data" for wind technology models, and "solar_resource_data" for solar technology models.) |
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.
All of the rest of the things in this list can be named whatever you want, I believe, but does this one have to be either "wind_resource_data" or "solar_resource_data"?
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.
yes! I can add a note for that!
| Some examples that define a single site with multiple resources are: | ||
| - `examples/23_solar_wind_ng_demand/plant_config.yaml` | ||
|
|
||
| ### Multiple sites with resources |
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 these sections with the corresponding examples are fantastic! I think for this last one though, the case with two wind farms would be more descriptive than doing a wind and solar example, just to show how the naming can work.
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.
good point! I will update it!
johnjasa
left a comment
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.
Nice, I like the work you put into this iterating based on others' feedback! It's really a nice improvement. I pushed up some nano doc formatting changes.
| The `resource_to_tech_connections` section in your plant configuration file defines how different technologies are connected to sites and the resource data for that site. | ||
| This is how the H2I framework establishes the necessary OpenMDAO connections between your sites and technologies based on these specifications. | ||
|
|
||
| Resource to technology connections are defined as an array of 3-element arrays in your `plant_config.yaml`: |
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 array is valid here, as yaml has a slightly different lingo than Python: https://stackoverflow.com/a/33136212
| # connect the wind resource to the wind technology | ||
| ['wind_resource', 'wind', 'wind_resource_data'], | ||
| ['solar_resource', 'solar', 'solar_resource_data'], | ||
| ['wind_site.wind_resource', 'wind', 'wind_resource_data'], |
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 like where we landed after our discussion with the 3-way connection!
Dismissing as we discussed this in the standup; if not re-reviewed by Friday, will just bring it in. Thanks!
jaredthomas68
left a comment
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 this is ready to be pulled it.
| # connect the wind resource to the wind technology | ||
| ['wind_resource', 'wind', 'wind_resource_data'], | ||
| ['solar_resource', 'solar', 'solar_resource_data'], | ||
| ['wind_site.wind_resource', 'wind', 'wind_resource_data'], |
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.
Same
| site_group = self.create_site_group(plant_config_reorg, site_info) | ||
| self.model.add_subsystem(site_name, site_group) | ||
|
|
||
| def create_site_group(self, plant_config_dict: dict, site_config: dict): |
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.
OK, I still don't love the copying, but I'll role with it. Thanks for the explanation and some simplification
Enable multiple site functionality
This PR introduces a way to define multiple sites. This is a first-pass at enabling this functionality at a high-level. This PR is intended to lay some preliminary groundwork for further detailed work with site definitions, such as having certain technologies at specific sites (this is not part of this PR). This implementation is intended to be able to handle existing site definitions while being able to handle multiple site definitions. The use-cases this enables are being able to run a design sweep with wind and solar resource at different locations. Before, site locations could only be swept if wind and solar resource were for the same latitude/longitude.
Multiple sites can be defined using "sites" rather than "site" in the plant_config.yaml. Each site is expected to define latitude, longitude, and resources (if needed) for that site:
Each site group (
om.Group()) has asitesubsystem (which is defined by latitude and longitude at the moment) and subsystems for each resource defined inresourcesfor that site.Remaining Question for Reviewers (No longer applicable, going with Option 1)
Currently,
resource_to_tech_connectionsnow requires the site name to be specified as a 3 element list in this format:An alternative approach would be to use a 4 element list in this format:
What do y'all like more? 3-element list or 4-element list?
Section 1: Type of Contribution
Section 2: Draft PR Checklist
TODO:
H2IntegrateModelmethodsType of Reviewer Feedback Requested (on Draft PR)
Structural feedback:
h2integrate/core/sites.py?Implementation feedback:
Other feedback:
Section 3: General PR Checklist
docs/files are up-to-date, or added when necessaryCHANGELOG.mdhas been updated to describe the changes made in this PRSection 3: Related Issues
Section 4: Impacted Areas of the Software
Section 4.1: New Files
docs/user_guide/defining_sites_and_resources.md: doc page for defining sites andresource_to_tech_connectionsh2intergate/core/sites.py: new file containing site components and configsSiteLocationComponentConfig: configuration class forSiteLocationComponentSiteLocationComponent: site location component with outputs of latitude, longitude, and elevationSiteBaseConfig: Base configuration class for site modelsSiteBaseComponent: Baseom.IndepVarCompcomponent class for site componentsexamples/xx_site_doe_diff/*: new example that runs a design of experiments with wind and solar resource at different locationsSection 4.2: Modified Files
h2integrate/core/h2integrate_model.py-
connect_technologies(): updated logic related toresource_to_tech_connections. The two main updates are:- updated initialization of
resource_modelsvariable to handlesitessite definition. This variable is used to throw errors in case theres an extra or missing resource to technology connection- the actual connection between resource data and technology model has logic to handle multiple sites.
-
create_site_model(): new method that creates multiple site groups-
create_site_group(): new method heavily based on the functionality in the previouscreate_site_model()method, but includes inputs. This is called within the newcreate_site_model()method.h2integrate/core/inputs/plant_schema.yaml: removed "site" as a required key, added "sites" as a required key.examples/26_floris: expanded example to check that no errors arise with having multiple sites outputwind_resource_data.plant_config.yaml: added another site for another wind plant. Added technology_interconnections, and added more finance subgroupstech_config.yaml: added another wind farm model using PySAM (utility wind plant), renamed floris wind plant tech to "distributed_wind_plant" and added a combiner.Tests (new and modified):
examples/test/test_all_examples.py::test_floris_example: updated for expanded example. Added subtests to check that latitude and longitude for each wind site is as expectedexamples/test/test_all_examples.py::test_sweeping_different_resource_sites_doe: new integration test for added exampleh2integrate/converters/iron/test/test_iron_transport.py: updated fixture forplant_configto be compatible with changes to iron transport model.h2integrate/preprocess/test/test_wind_turbine_file_tools.py: updated to reformat plant config for creating wind resource models.Other modified files:
docs/user_guide/how_to_set_up_an_analysis.ipynb: removedyearfrom plant config. Added updates to what information is provided under 'plant' section of the plant config.examples/15_wind_solar_electrolyzer/plant_config.yaml: updated example 15 to show usage of defining multiple sitesh2integrate/converters/iron/iron_transport.py: had to update way of accessing latitude and longitude from plant config, this was a temporary fix (requires that the site name is 'site') and should be updated so latitude and longitude are an input to the transport model. This update would be part of a separate PR that defines a framework for connecting sites to technologies (rather than resources from a site to technologies).Other Modified Example Files:
plant_config.yamlfiles were reformatted to be compatible with new framework.examples/16_natural_gas/plant_config.yamlexamples/20_solar_electrolyzer_doe/plant_config.yamlexamples/22_site_doe/plant_config.yamlexamples/24_solar_battery_grid/plant_config.yamlexamples/17_splitter_wind_doc_h2/plant_config.yamlexamples/21_iron_mn_to_il/plant_config.yamlexamples/21_iron_mn_to_il/plant_config_old.yamlexamples/25_sizing_modes/plant_config.yamlexamples/23_solar_wind_ng_demand/plant_config.yamlSection 5: Additional Supporting Information
Suppose we want to run a single simulation where wind resource data is pulled for the location (30.6617, -101.7096) and solar resource data is pulled for the location (35.2018863, -101.945027). There are two ways this could be done:
Option 1: using a single site:
Option 2: using multiple sites or running design of experiments:
Section 6: Test Results, if applicable
Section 7 (Optional): New Model Checklist
docs/developer_guide/coding_guidelines.mdattrsclass to define theConfigto load in attributes for the modelBaseConfigorCostModelBaseConfiginitialize()method,setup()method,compute()methodCostModelBaseClasssupported_models.pycreate_financial_modelinh2integrate_model.pytest_all_examples.pydocs/user_guide/model_overview.mddocs/section<model_name>.mdis added to the_toc.yml