-
Notifications
You must be signed in to change notification settings - Fork 27
Added FLORIS wind plant model #372
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 this! I love that we're moving closer and closer to having all the technology models we need integrated into H2I well.
I've made some changes directly to the code and had a few small comments. I welcome feedback from others but think this is in a good spot and can be built upon as needed in further PRs.
What other features need to come in for us to fully replace the HOPP technology models in the examples with a mix of wind/solar/battery? Would we be able to do that once this PR comes in or does more functionality need to be added to H2I?
| default_turbulence_intensity: float = field() | ||
| operational_losses: float = field(validator=range_val(0.0, 100.0)) | ||
| hub_height: float = field(default=-1, validator=validators.ge(-1)) | ||
| floris_operation_model: str = field(default="cosine-loss") |
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.
Non-blocking suggestion: rename to operation_model as the floris is unnecessary because we're already in that technology model?
| # NOTE: could update air density based on elevation if elevation is included | ||
| # in the resource data. | ||
| # would need to duplicate the ``calculate_air_density`` function from HOPP |
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 please make an issue for this and add context/links to the HOPP code where useful?
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 - Created Issue #439
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.
jk - I'm adding it into the floris wrapper now.
| ) | ||
|
|
||
| # make layout for number of turbines | ||
| if self.layout_mode == "basicgrid": |
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.
@elenya-grant, where have you landed on how layout_mode is used here? Correct me if I'm wrong, but currently the only supported layout_mode is basicgrid? I say this because if it's not, then x_pos and y_pos are not created and they're later used for floris_farm
| floris_config["farm"].update(floris_farm) | ||
|
|
||
| # initialize FLORIS | ||
| floris_config["flow_field"].update({"turbulence_intensities": []}) |
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 this line necessary if you're setting the turbulence intensities as part of the time_series wind data? Does this blank turbulence intensities list just get overwritten? I'd suggest removing it if it's not strictly needed.
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 turbulence intensity thing is a bit complicated. But, simply, this does need to be here or else it'll fail because its a required input to the Floris TimeSeries object and a user may not include it in the floris_wake_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.
on your question about layout_mode - The only layout mode option is basicgrid and so an error will be thrown if the layout mode isn't basic grid (because x_pos and y_pos won't exist). Once we get more layout options, I'd be nice to incorporate handling layout stuff into the WindPerformanceBaseClass and have a shared WindPerformanceBaseConfig that can be used with FlorisWindPlantPerformanceModel and PYSAMWindPlantPerformanceModel
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.
Understood, thanks for your explanation here. I agree with your approach
| return rho | ||
|
|
||
|
|
||
| def calculate_air_density_losses(elevation_m: float) -> float: |
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 looks like this and the above function aren't used anywhere? I'd suggest removing until they're used.
| "pressure": "atm", | ||
| "precipitation_rate": "mm/h", | ||
| "relative_humidity": "percent", | ||
| "is_day": "percent", |
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 looked into this and agree with @elenya-grant's findings:
Test 1: Setting unitless input to 0.5
============================================================
Input (unitless): [0.5]
Output (unitless): [0.5]
============================================================
Test 2: Setting percent input to 50
============================================================
Input (percent): [50.]
Output (percent): [50.]
============================================================
Test 3: Set unitless=0.5, read as percent
============================================================
Set as unitless: 0.5
Read as unitless: [0.5]
Read as percent: [50.]
============================================================
Test 4: Set percent=50, read as unitless
============================================================
Set as percent: 50.0
Read as percent: [50.]
Read as unitless: [0.5]
I think we need whatever the HOPP dispatch/battery functionality is then we can move away from it. We may also need to add more wind layout options if any of the examples that use HOPP use a layout that isn't |
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 looks good to be merged in! My last question is if hub_height is something that could be optimized since it's exposed to OpenMDAO?
| "`layout` dictionary. Please set the layout in " | ||
| "floris_wake_config['farm']['layout_x'] and floris_wake_config['farm']['layout_y']" | ||
| " to empty 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.
I like this error message!
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 have a few outstanding concerns, but looking good overall.
| "pressure": "atm", | ||
| "precipitation_rate": "mm/h", | ||
| "relative_humidity": "percent", | ||
| "is_day": "percent", |
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 your results @johnjasa show demonstrate exactly what I said. Percent is between 0 and 100, unitless the range may be 0 to 1. The results above show setting as percent=50 results in a unitless of 0.5.
I think the docs page may be wrong. I've run into issues with this elsewhere. I think unitless = percent/100 and percent is unitless*100, see the test in openmdao for percentage where a unitless of 0.05 corresponds to a percentage of 5.
|
Thanks for your review. Here's a summary of the things I did to address your feedback:
|
…g resource data method
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.
Looks good, thanks!
Added FLORIS wind plant model
Added wind plant performance model for FLORIS.
This model was developed with an emphasis on usability for design sweeps, meaning that some inputs in floris_config file are over-written to use possible design variables such as number of wind turbines and turbine hub-height. Aka - this is not able to accommodate all the possible use-cases that a user may have with running FLORIS in H2I to keep the initial implementation somewhat simple.
Type of Contribution
General PR Checklist
CHANGELOG.mdhas been updated to describe the changes made in this PRdocs/files are up-to-date, or added when necessaryNew Technology Checklist
test_all_examples.pyexamples/README.mddocs/technology_models/docs/technology_models/technology_overview.mdsupported_models.pycreate_financial_modelinh2integrate_model.pydocs/developer_guide/coding_guidelines.mdRelated issues
CacheModelBaseClassImpacted areas of the software
Modified files
h2integrate/core/model_baseclasses.pyCacheBaseConfig.__attrs_post_init__(): updated to only createcache_dirif caching is enabled.h2integrate/converters/hopp/test/test_hopp_caching.pytest_hopp_wrapper_cache_filenames: added cleanup to test to remove folder and files created within testh2integrate/preprocess/test/test_wind_turbine_file_tools.py: added more detailed test for testing floris preprocessing toolsdocs/misc_resources/turbine_models_library_preprocessing.ipynb: added docs to show usage ofexport_turbine_to_floris_format()functionNew files
h2integrate/converters/wind/floris.pyFlorisWindPlantPerformanceModel: performance model for FLORIS.FlorisWindPlantPerformanceConfig: configuration class forFlorisWindPlantPerformanceModelexamples/floris_example/*: example files to run FLORIStests/h2integrate/test_all_examples.py::test_floris_example: integration test for floris exampleh2integrate/converters/wind/test/test_floris_wind.py: unit tests forFlorisWindPlantPerformanceModellibrary/floris_v4_default_template.yaml: floris config with wake parameterslibrary/floris_turbine_Vestas_660kW.yaml: floris config for vestas 660 kW turbine.h2integrate/converters/wind/tools/resource_tools.py: new file containing tool related to wind resource:calculate_air_density(): estimate air density for a specific elevationweighted_average_wind_data_for_hubheight(): weighted average of wind resource data of two hub-heightsaverage_wind_data_for_hubheight(): average wind data over two resource heightsh2integrate/converters/wind/tools/test/test_resource_tools.py: tests for all methods inh2integrate/converters/wind/tools/resource_tools.pyAdditional supporting information
Test results, if applicable