Update Naming Convention in Open-Loop Converter Control Strategies#631
Conversation
|
"Would it make sense to add the outputs of the |
genevievestarke
left a comment
There was a problem hiding this comment.
I like having this component inherit the PerformanceModelBaseclass! I think the ultimate goal is to make this its own component and do all the demand-based calculations here. This would move enable these calculations for converter systems, but also move them out of the storage performance models, which will help untangle the system/storage question.
For the second point (and third point), I think that this should be reclassified as a transporter, so that it can output unmet demand (and not a set point). This makes sense to me because it would be used for storage and converters, and it is more of an analysis component (like a combiner) than a control component.
| outputs[f"unmet_{self.commodity}_demand_out"] = np.where( | ||
| remaining_demand > 0, remaining_demand, 0 | ||
| ) | ||
| outputs[f"unused_{self.commodity}_out"] = np.where( | ||
| remaining_demand < 0, -1 * remaining_demand, 0 | ||
| ) | ||
|
|
||
| # Calculate actual output based on demand met and curtailment |
There was a problem hiding this comment.
Is this shared between demand_openloop_converter and flexible_demand_openloop_converter? Could we move these to the base class?
There was a problem hiding this comment.
No - the demand and flexible demand openloop "controllers" both shared the baseclass ConverterOpenLoopControlBase
There was a problem hiding this comment.
oh sorry - totally misunderstood your question. I think that these calculations could be moved to a method in the baseclass
There was a problem hiding this comment.
I agree with including set_point, but most of the below calculations don't make sense to me in a controller. I could see it making sense to have a simple converter or end_use component that goes along with the simplistic controller here.
Big fan!
You asking this question made me dig deeper into how I'm viewing these classes, and I realized I might have some potentially conflicting viewpoints. Mainly, this isn't a That being said, I like the current definition of
Would it make sense to add a new folder/category? Something like If helpful, I'm happy to chat through this more on a call! |
|
@johnjasa @genevievestarke - thanks for the feedback! Quick question: I almost think |
jaredthomas68
left a comment
There was a problem hiding this comment.
I'm not sure I fully understand your plan. As I see it, these components are a mix of control and performance and the two elements should be separated more clearly, not integrated more closely.
I do find the idea of end_use components interesting. I had previously been seeing those as converter that take in resources and output money, or something along those line, but since we are using finance models throughout, the money side is already handled and the end use starts to make more sense to me.
| outputs[f"unmet_{self.commodity}_demand_out"] = np.where( | ||
| remaining_demand > 0, remaining_demand, 0 | ||
| ) | ||
| outputs[f"unused_{self.commodity}_out"] = np.where( | ||
| remaining_demand < 0, -1 * remaining_demand, 0 | ||
| ) | ||
|
|
||
| # Calculate actual output based on demand met and curtailment |
There was a problem hiding this comment.
I agree with including set_point, but most of the below calculations don't make sense to me in a controller. I could see it making sense to have a simple converter or end_use component that goes along with the simplistic controller here.
genevievestarke
left a comment
There was a problem hiding this comment.
I agree with making these demand components!
I like DemandComponentBase option for naming. Otherwise, I agree with all the naming suggestions!
| remaining_demand < 0, -1 * remaining_demand, 0 | ||
| ) | ||
|
|
||
| # Calculate actual output based on demand met and curtailment | ||
| outputs[f"{commodity}_set_point"] = ( | ||
| inputs[f"{commodity}_in"] - outputs[f"{commodity}_unused_commodity"] | ||
| outputs[f"{self.commodity}_out"] = ( |
There was a problem hiding this comment.
would commodity_set_point replace this commodity_out variable, or would there be both?
There was a problem hiding this comment.
there would only be commodity_out, which is equivalent to the commodity_out definition in the storage performance models.
| outputs[f"total_{self.commodity}_produced"] / self.fraction_of_year_simulated | ||
| ) | ||
|
|
||
| outputs["capacity_factor"] = ( |
There was a problem hiding this comment.
I think that there are more useful outputs we can add rather than the capacity factor. I think things based on the demand would be more useful, like total_unmet_demand and total_demand_met, maybe the capacity factor of the demand, and basing them on demand rather than the rated capacity.
Is this necessary because it's inheriting the performance base class?
There was a problem hiding this comment.
The capacity factor is the capacity factor of the demand (total_demand_met/total_demand).
I heard you about those outputs - but I don't see what those outputs would be connected to and they could be easily calculated from the timeseries profiles. So - I think we should add those outputs once they're needed.
| - [`DemandOpenLoopStorageController`](#demand-open-loop-storage-controller) | ||
| - [`DemandOpenLoopConverterController`](#demand-open-loop-converter-controller) | ||
| - [`FlexibleDemandOpenLoopConverterController`](#flexible-demand-open-loop-converter-controller) | ||
| - [`GenericDemandComponent`](#demand-open-loop-converter-controller) |
There was a problem hiding this comment.
I think it would make sense to move the GenericDemandComponent and FlexibleDemandComponent out of the controls portion of the docs and maybe adding it to a new folder called demand?
| @@ -37,7 +37,7 @@ This page documents two core controller types: | |||
|
|
|||
| (demand-open-loop-converter-controller)= | |||
| ### Demand Open-Loop Converter Controller | |||
There was a problem hiding this comment.
Looks like this heading could be updated to the new naming
| @@ -57,19 +57,19 @@ The controller is defined within the `tech_config` and requires these inputs. | |||
|
|
|||
| ```yaml | |||
| control_strategy: | |||
There was a problem hiding this comment.
Does it still live under control_strategy in the tech_config?
There was a problem hiding this comment.
not anymore!
I pulled out the "converter control stuff" from the control_overview.md page and put it in a new page (demand_components). I still need to update the model_overview.md page and the language in the demand_components.md file.
| demand_profile: [10, 10, 12, 15, 14] | ||
| ``` | ||
| For an example of how to use the `DemandOpenLoopConverterController` open-loop control framework, see the following: | ||
| For an example of how to use the `GenericDemandComponent` open-loop control framework, see the following: |
There was a problem hiding this comment.
I'd just search for the word control and remove it :)
| - Converter Controllers: | ||
| - `'DemandOpenLoopConverterController'`: open-loop control; manages resource flow based on demand constraints | ||
| - `'FlexibleDemandOpenLoopConverterController'`: open-loop control; manages resource flow based on demand and flexibility constraints | ||
| - `'GenericDemandComponent'`: open-loop control; manages resource flow based on demand constraints |
There was a problem hiding this comment.
not open-loop controllers?
There was a problem hiding this comment.
I like how these were moved to a demand folder and renamed. It makes more sense after all of the dispatch refactor. Thanks @elenya-grant :)
|
|
||
| class DemandOpenLoopConverterController(ConverterOpenLoopControlBase): | ||
| class GenericDemandComponent(DemandComponentBase): | ||
| """Open-loop controller for converting input supply into met demand. |
There was a problem hiding this comment.
can we update docstring to not say controller? and the description of what it computes?
There was a problem hiding this comment.
I think I've updated all the doc strings and inline comments!
| * ``{commodity}_out``: Actual output delivered. | ||
| * ``unmet_{commodity}_demand_out``: Unmet demand. | ||
| * ``unused_{commodity}_out``: Curtailed production. | ||
| * ``{commodity}_set_point``: Actual output delivered. |
There was a problem hiding this comment.
You removed commodity_set_point right?
There was a problem hiding this comment.
removed it from the doc string!
| # Calculate actual output based on demand met and curtailment | ||
| outputs[f"{commodity}_set_point"] = ( | ||
| inputs[f"{commodity}_in"] - outputs[f"{commodity}_unused_commodity"] | ||
| outputs[f"{self.commodity}_out"] = ( |
There was a problem hiding this comment.
It probably would be helpful to add a description of what commodity_out means in the case of the demand to the docs since it's not particularly intuitive.
| # Calculate actual output based on demand met and curtailment | ||
| outputs[f"{commodity}_set_point"] = ( | ||
| inputs[f"{commodity}_in"] - outputs[f"{commodity}_unused_commodity"] | ||
| outputs[f"{self.commodity}_out"] = ( |
There was a problem hiding this comment.
I think I'll add a figure to the docs explaining some of these outputs. And a note about how the CF will be less than one and the edge case about how to account for that.
| Demand components define rule-based logic for meeting commodity demand profiles without using dynamic system feedback. These components operate independently at each timestep. | ||
|
|
||
| This page documents two core controller types: | ||
| 1. Demand Open-Loop Converter Controller — meets a fixed demand profile. |
There was a problem hiding this comment.
Converter Controller? --> Component?
| commodity_units: kg/h | ||
| demand_profile: [10, 10, 12, 15, 14] | ||
| ``` | ||
| For an example of how to use the `GenericDemandComponent` open-loop control framework, see the following: |
There was a problem hiding this comment.
maybe remove "open-loop control framework"?
|
|
||
|
|
||
| #### Configuration | ||
| The flexible demand controller is defined within the `tech_config` with the following parameters: |
|
|
||
| ```yaml | ||
| model_inputs: | ||
| control_parameters: |
| commodity = self.config.commodity | ||
| remaining_demand = inputs[f"{commodity}_demand"] - inputs[f"{commodity}_in"] | ||
|
|
||
| # remaining_demand = inputs[f"{self.commodity}_demand"] - inputs[f"{self.commodity}_in"] |
| outputs[f"{commodity}_set_point"] = ( | ||
| inputs[f"{commodity}_in"] - outputs[f"{commodity}_unused_commodity"] | ||
| ) | ||
| # flexible_remaining_demand = flexible_demand_profile - inputs[f"{self.commodity}_in"] |
There was a problem hiding this comment.
Remove commented code? I'm assuming this is commented out because it moved to the base class?
| outputs = self.calculate_outputs( | ||
| inputs[f"{self.commodity}_in"], inputs[f"{self.commodity}_demand"], outputs | ||
| ) | ||
| # remaining_demand = inputs[f"{self.commodity}_demand"] - inputs[f"{self.commodity}_in"] |
There was a problem hiding this comment.
Moved to the base class so can be removed?
There was a problem hiding this comment.
removed all commented out code and updated the docs and doc-strings to remove the word "control"
* Remove old iron models (#601) * removed temporary iron and steel models * supported models * update example 28 with updated models * remove outdated files * consolidate iron examples * fix all the stuff I broke * update docs and changelog * update example name and add model names to docs * update changelog --------- Co-authored-by: elenya-grant <116225007+elenya-grant@users.noreply.github.com> * update SMR energy conversion ratio and tests (#606) * update SMR energy conversion ratio and tests * update changelog * docs * minor updates to inline comments * update usage based on hydrogen production --------- Co-authored-by: Rob Hammond <13874373+RHammond2@users.noreply.github.com> Co-authored-by: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Co-authored-by: John Jasa <john.jasa@nrel.gov> Co-authored-by: genevievestarke <103534902+genevievestarke@users.noreply.github.com> Co-authored-by: Jared Thomas <jaredthomas68@gmail.com> Co-authored-by: bayc <christopher.j.bay@gmail.com> Co-authored-by: John Jasa <johnjasa11@gmail.com> Co-authored-by: Jared Thomas <jaredthomas68@users.noreply.github.com> Co-authored-by: Jonathan Martin <94018654+jmartin4u@users.noreply.github.com> Co-authored-by: jmartin4 <jonathan.martin@nrel.gov> Co-authored-by: Jonathan Martin <94018654+jmartin4nrel@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Chris Bay <12664940+bayc@users.noreply.github.com> * Break out Pyomo controller simulation code (#587) * Breakout simulation code * Remove duplicate code * Fix testing * Update doc strings and docs * added docstring for heuristic controller config * fixed issue that I made with the HeuristicLoadFollowingControllerConfig * Update docs/control/pyomo_controllers.md Co-authored-by: Jared Thomas <jaredthomas68@users.noreply.github.com> * Make initialize_parameters() functions the same for both controllers * Apply suggestion from @jaredthomas68 Co-authored-by: Jared Thomas <jaredthomas68@users.noreply.github.com> * Fix doc string format * Update h2integrate/control/control_strategies/heuristic_pyomo_controller.py Co-authored-by: Jared Thomas <jaredthomas68@users.noreply.github.com> * Update h2integrate/control/control_strategies/heuristic_pyomo_controller.py Co-authored-by: Jared Thomas <jaredthomas68@users.noreply.github.com> * Fix ruff formatting --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> Co-authored-by: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Co-authored-by: Jared Thomas <jaredthomas68@users.noreply.github.com> Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> * Bugfix in Charge/Discharge efficiency handling in `StoragePerformanceModel` (#600) * fixed how charge and discharge rates are applied in generic_storage_pyo model --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Tests for non-one battery efficiencies (#610) * add unit tests for openloop storage controller with non-one efficiencies * rearrange usage of pytest.approx so the target comes second and uses approx * update changelog: * Sync Storage Autosizing Model and Pass-Through controller to Align with Pyomo Controllers (#608) * updated the storage autosizing and pass through controller for new control and performance model structure * added subtest for integration with pass through controller * updated to use commodity_set_point instead of input-demand * made set_demand_as_avg_commodity_in a required input parameter * moved passthrough controller to storage subfolder * Added minor changes that got missed in PR 600 --------- Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> * Sync Demand Open Loop Controller and Simple Generic Storage to Align with Pyomo Controllers (#612) * updated simple_generic_storage to simulate storage performance * updated demand openloop controller so discharge setpoint is correct * PySAM Marine Models (#607) * tidal resource model and performance model * add performance values for testing * test power curve scaling * marine cost model * tidal example * integration test * documentation * update docs * small changes * update for failing tests * fix equation rendering * fix segmentation fault * add test for using default pysam config * address reviewer feedback * fix wind pysam * attempt to modify file path handling for resource data * fix path stuff * Sync PySAM Battery and Generic Storage Pyomo Performance models with open-loop controllers (#613) * refactored pysam battery and storage performance models to be compatible with updated open-loop controllers * updated generic storage pyo to use pass through controller * renamed PassThroughOpenLoopController to SimpleStorageOpenLoopController * removed simple_generic_storage * renamed xx_charge_fraction to xx_soc_fraction --------- Co-authored-by: Genevieve Starke <genevieve.starke@nrel.gov> * minor error msg and doc corrections (#618) * CO2 Model Fixes (#617) * units and connecting variables * fix doc page * catch if annual_input_energy is 0 * remove base class * fix oae test * failing doc test * fix value call * final touchs * Bugfix: Update storage models so can use different control types per storage type (#615) * updated logic in pysam batery and generic storage to handle multiple storage types * added tests and bugfix in heuristic with setting efficiencies --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Baseclass for Openloop Storage Control Strategies (#619) * added openloop control storage baseclass * Enable use of Pyomo Controllers in the Storage Autosizing Model (#621) * updated autosizing storage model to be compatible with pyomo controllers * renamed fixures in heuristic controller tests * aggregated heuristic controller tests into one file * added simple test for storage autosizing and heuristic * renamed fixtures in optimized controller tests * aggregated optimized control tests into one file * updated test for heuristic controller with autosizing * updated so simple storage autosizing can run with optimal pyomo control * Generic cost model for converters (#622) * added generic cost model * added tests and updated model * updated example 3 to use new converter model and added to supported models * updated docstrings and input descriptions * updated changelog * added to model overview * Clarified error message --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Introducing multivariable commodity streams (#480) * Working out first steps of multivariable streams * Adding to multivariable streams work * expanding multivariable stream definition * Building out more of the gas combiner * Improving example for multivariable streams * Updating examples and merging * Apply suggestions from code review Co-authored-by: genevievestarke <103534902+genevievestarke@users.noreply.github.com> * Many updates based on PR feedback * Updated to mass fractions for multicommodity stream * renamed a few multicommodity variable names * Added helper functions for multivariable stream definitions * Updated names throughout for multivariable streams * Updated docs for multivariable streams * Added commodity stream tests * Addressing PR feedback * Updates based on PR feedback * Updates based on PR feedback --------- Co-authored-by: genevievestarke <103534902+genevievestarke@users.noreply.github.com> Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> * Removed some shape_by_conn calls due to OM issues (#632) * Removed some shape_by_conn calls due to OM issues * Moved last calls of copy_shape * Fixing test_pipe fail --------- Co-authored-by: jmartin4 <jonathan.martin@nrel.gov> * Move xdsm call in H2IntegrateModel to its own method (#629) * move xdsm creation in H2IModel to a method so user has to call it if desired instead of having it be automatic * update changelog and docs and adjust create_xdsm logic to reflect that it is an optional call * update docs * update docs * update docs for visualization * change xdsm code cell to not execute on build * switch pdf for png * minor comments update in code example * remove xdsm call * Updated XDSM explanation link --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Handling Leap Years in OpenMeteo Resource Data (#633) * updated openmeteo resource models to handle leap day * added resource files for leap year * added tests for leap year resource data * added integration w pvwatts test for leap year * Methodized leap day handling for base class for future resource handling --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Baseclass for Storage Performance Models (#624) * added draft storage model baseclass * updated draft storage baseclass * added docstring to run_storage method * minor updates to comments in storage_model_baseclass * updated storage performance model to inherit baseclass * fixed storage performance model and storage baseclass * updated storage autosizing model * updated pysam battery to use baseclass and removed battery_baseclass * removed commented out code and simplified some docstrings * removed unnecessary docstrings * updated changelog * PR review: minor personal preferences * updated inline comment --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Modified the calc tilt angle function for pysam solar (#646) * Oxygen output from PEM electrolyzer (#642) * added oxygen output from electrolyzer * updated example 14 to calc LCOO --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Removed remaining naming dependencies (#654) * Removed remaining naming dependencies * Added to changelog and fixed CI issue * PR feedback * Fixed schema reqs * Update validators to allow zero values for costs for nuclear * Bugfix: Connecting resource to multiple techs (#655) * bugfix and added test for connecting one resource model to multiple techs * updated changelog * Updated test to call setup to trigger connection error --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Update urls for NLR pages and github repositories (#658) * Update urls for NLR pages and github repositories * Updated from WISDM to NLRWindSystems org for some repos * Updated and removed more NREL references --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> * Enhancement/windows ci (#590) * update installation instructions * add windows to CI and use conda consistently for Python across OS * merge develop and update changelog * adopt 'extras' flag for analysis extras to correctly use optional CI * update changelog * reorder ci setup * update order * attempt python version restructure * reinstate old python version * update URL * move runs-on back to below strategy * add os to optional matrix * reorganize the conditional for extras * convert lists to yaml bullet lists * skip gis-dependent tests when not installed * update changelog * use optional deps for all tests and add single runner for validating dependency-determined skipped tests * reformatting * reduce sql file access scope to functions to avoid windows errors * downgrade temp_dir to a function scope to avoid windows access errors * move temp examples fixture to be in main conftest, and enable repo-wide access * add module scoped example directory copy * apply module scoped example copy fixture to recorder tests and update * update changelog * update miniconda action usage * use the example copy fixture to isolate sql access in tests for potential windows resolution * reorganize changelog * fix typo in parameter name * update workflow * remove max-parallel * Revert "reorganize changelog" This reverts commit 679a38d. * add shell to all tests * don't allow coverage upload to fail ci * uncomment windows * add garbage collection to help with sql file handling * temporarily only run windows to reduce runner usage * add sleep to see if small timeout resolves issue * only run single test * remove garbage collection * fix typo * remove manual folder removal in favor of pytest cleanup * reinstate normal CI processes * add file removal to avoid OpenMDAO silent failure * temporarily only run single file on single windows runner * fix typo * fix typo * move manual recorder_path deletion * put ci back * handle None case * track model state using IntEnum * add xfail for windows because of OpenMDAO improper SQL file handling for Windows * add todo about removing manual removal * restore accidentally deleted file --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> Co-authored-by: kbrunik <kbrunik@gmail.com> * updated CI workflow to disable windows (#668) * Check for extraneous or mis-categorized input parameters (#647) * added dictionary utilities * bugfix in setup() and added start of a test * added fix to calling check_inputs * fixed check_inputs * added another check in check_inputs * updated error messages in check_inputs and fixed example 1 * Added tests * added another subtest to test_check_inputs * fixed tech configs for examples * added some inline comments * check for requisite models and return if none * perform check from note and collapse checking logic * collapse user input regeneration to reduce number of loops * remove nested looping approach * move assert to proper context manager level * add indent level back * fix min combinations logic for passing tests * flatten improperly shared parameterization checking logic * update test to include multiple categories for improperly shared * fix typo * update docstring * added handling for combined cost and performance models * Added tech config fpath to the error messages for parameter checking * changlog * changed strict to True for six converter models * reverted strict setting for electrolyzer --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> Co-authored-by: Hammond, Rob <13874373+RHammond2@users.noreply.github.com> Co-authored-by: kbrunik <kbrunik@gmail.com> * Update Naming Convention in Open-Loop Converter Control Strategies (#631) * renamed outputs in converter openloop controllers * updated tests and examples with updated naming * added performance model outputs to the converter control strategies * moved converter control strategies to demand folder * removed commodity_set_point as output * renamed demand component to be performance model instead of control strategy * moved output calculations to shared method in baseclass --------- Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> Co-authored-by: John Jasa <johnjasa11@gmail.com> * modified state check for setup and run (#669) * Add interactive class hierarchy visualization to docs (#643) * Added class hierarchy diagram * merging * Updated the PR template * Changed class hierarchy embedding * moved class hierachy * Breaking the sphinx narrow rule * Combined colors based on feedback * Updated colors based on Gen's feedback * Shifted diagram location right * Reformatting embedding the class viz structure * Updated dev pyproject for viz tool --------- Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> * Standardize Feedstock Outputs (follow-on to 463) (#523) * added capacity and price as inputs to feedstock component * updated feedstock mdoel to have standard outputs * added commodity_amount_units to FeedstockCostConfig * added standard output to feedstock cost model and connected commodity_out between performance and cost model * renamed config inputs for feedstocks * updated ex 23 which is untested and cleaned up feedstocks.py * minor docstring updates and added comments * added in notes of questions for reviewers to feedstocks.py * updated MMBtu units to MMBtu/h * fixed iron and steel tests * made changes to feedstock * fixed tests * removed unused comment * removed shape from price input * added integration test for feedstock integrated with finance model * updated feedstocks.md * changed based on reviewer feedback * added subtests to test_feedstocks * small changes to feedstock doc * docs --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> Co-authored-by: kbrunik <kbrunik@gmail.com> Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> * Framework to allow for variable dt (#653) * add draft for variable timestep framework * Changed error wording * switch bounds to tuple * minor test correction * include time-series generation functions * add tests for variable dt and update simulation length check for non-hourly dt * update docs * update changelog * update docs and doc strings * restore develop version of utilities.py * update dt bounds error * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fixing tests * Adding time step bounds to all models * Adding time step bounds to the combiner/splitter/transporters * Updates for tests * Adding time step bounds to the custom paper mill performance model * Added time step bounds to paper mill cost --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> Co-authored-by: John Jasa <john.jasa@nrel.gov> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * patch: Variable dt (#671) * update dt bounds error to require `_time_step_bounds` * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Add time step bounds to all tech models * Apply time step bounds check to feedstocks, transporters, and combiners --------- Co-authored-by: John Jasa <johnjasa11@gmail.com> Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> Co-authored-by: John Jasa <john.jasa@nrel.gov> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Remove system-level outputs from storage and replace with demand component (follow-on to 631) (#666) * removed system level calcs from storage and updated most tests * updated examples with storage but dont use storage as a commodity_stream in finances * updated examples with storage defined as a commodity_stream for a finance subgroup * added time_step_bounds to demand components * added test for example 23 * added example for different demand between storage and demand component * added demo for the demand components using example 13 * made it so demand is only input to battery performance model if using feedback control * added standard_capacity_factor as output from storage * added doc page for storage performance models --------- Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> Co-authored-by: John Jasa <johnjasa11@gmail.com> Co-authored-by: kbrunik <kbrunik@gmail.com> * Updating the readme and intro doc page ahead of v0.8 release (#677) * Updating the readme * Updated intro.md and changelog * Minor readme updates * Addressing Kaitlin's comments * Added more lingo to readme * Addressing PR suggestions --------- Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> * Move storage controllers into `storage` folder in `control_strategies` (#678) * moved controllers to storage folder * renamed pyomo controllers to include storage in the control name * moved control strategy tests * moved tests to the right folder * moved pyomo baseclass and controller_opt_problem_state to top-level control_strategies * updated import statements * renamed pyomo baseclass file * updated import for pyomo storage baseclass * made storage chapter in docs * removed backslashes from eqn since they dont render properly on readthedocs * Making changes per Gen's suggestion (#681) * Bump version from 0.7.2 to 0.8.0 --------- Co-authored-by: kbrunik <102193481+kbrunik@users.noreply.github.com> Co-authored-by: elenya-grant <116225007+elenya-grant@users.noreply.github.com> Co-authored-by: Rob Hammond <13874373+RHammond2@users.noreply.github.com> Co-authored-by: genevievestarke <103534902+genevievestarke@users.noreply.github.com> Co-authored-by: Jared Thomas <jaredthomas68@gmail.com> Co-authored-by: bayc <christopher.j.bay@gmail.com> Co-authored-by: Jared Thomas <jaredthomas68@users.noreply.github.com> Co-authored-by: Jonathan Martin <94018654+jmartin4u@users.noreply.github.com> Co-authored-by: jmartin4 <jonathan.martin@nrel.gov> Co-authored-by: Jonathan Martin <94018654+jmartin4nrel@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Chris Bay <12664940+bayc@users.noreply.github.com> Co-authored-by: Genevieve Starke <genevieve.starke@nrel.gov> Co-authored-by: kbrunik <kbrunik@gmail.com>
Update Naming Convention in Open-Loop Converter Control Strategies
NOTE: The intention of this PR is a step in resolving Issue #521. Eventually, the unmet demand and unused commodity calculations done in storage models would instead be done with the use of these demand components (see the follow-on PR, #666). Please keep this in mind when reviewing the new outputs of these models (please see this comment on how that is expected to change)
Update output naming convention in "open-loop converter control strategies" to align with the naming convention of the storage performance models.
f"{commodity}_unmet_demand"->f"unmet_{commodity}_demand_out"f"{commodity}_unused_commodity"->f"unused_{commodity}_out"f"total_{commodity}_unmet_demand"PerformanceModelBaseClassUpdate as of 04/06/2026:
The above changes motivated a larger discussion around these "open-loop converter control strategies" and how they're actually used/what they were intended for. Some additional context on why these were originally put as "control strategies" is listed in Section 5. But - my motivating philosophy to renaming these classes and moving the files is that these components are not used as controllers and are instead ways of representing some generic demand signal. I think a common push-back on this idea is that demand should come from a converter component, but in some cases, we care more about the demand being met than what the demand is "turned into". For example (a common use-case), defining the energy demand of a data center is important so we can design a system to meet that demand and calculate the cost of energy to meet that demand. We are not trying to calculate the cost of the output from the data center, we only care about the inputs. These demand components are used to define a demand, subtract some initial amount from that demand, and output the remaining and excess demand. The unmet demand from the demand component can then be passed to some converter technology as the demand (example 23 is a good reflection of this). These models are primarily used to calculate demand metrics, not define a control strategy.
I propose the following renaming (already done):
ConverterOpenLoopControlBase->DemandComponentBaseDemandOpenLoopConverterController->GenericDemandComponentFlexibleDemandOpenLoopConverterController->FlexibleDemandComponentopenloop_controller_base.py->demand_base.pydemand_openloop_converter_controller.py->generic_demand.pyflexible_demand_openloop_controller.py->flexible_demand.pyOther changes:
compute_outputs()method to the baseclass, which simplified thecompute()methods of the two demand components that inherit itQuestions for reviewers are outlined in Section 2. This is ready for a draft review.
Section 1: Type of Contribution
Section 2: Draft PR Checklist
TODO:
Type of Reviewer Feedback Requested (on Draft PR)
Previous feedback - no longer accepting responses
Would it make sense to add the outputs of the
PerformanceModelBaseclassto these models? These models are more like ways to represent a generic end-use (or reference signal) rather than actual control strategies. So-if they represent an end-use and we may want to calculate the LCO of the end-use demand, then we'd need these to calculate/output rated commodity capacity and capacity factor.What should
commodity_set_pointmean with respect to converter controllers? Right now, it's the total commodity out to meet demand (equivalent tocommodity_outfrom storage performance models). I almost think this should be removed as an output and usecommodity_outinstead. If these are ever being used "as a controller" then it's probably the unmet demand that's being passed to some converter as the demand profile.commodity_set_pointas an output.Since the converter openloop control strategies are more like ways to represent an end-use, should these models be moved from
control/control_strategies/convertersto a different folder (such as):transporters/transporters/demand/converters/end_use/demand/(this is what I went with)end_use/Thoughts on proposed class re-naming:
ConverterOpenLoopControlBase->OpenLoopDemandComponentBaseORDemandComponentBaseDemandOpenLoopConverterController->GenericDemandComponentFlexibleDemandOpenLoopConverterController->FlexibleDemandComponentThoughts on file renaming:
openloop_controller_base.py->demand_base.pydemand_openloop_converter_controller.py->generic_demand.pyflexible_demand_openloop_controller.py->flexible_demand.pyBELOW IS FEEDBACK THAT IS NEWLY REQUESTED
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 3: Related Issues
Section 4: Impacted Areas of the Software
Moved all the files from
h2integrate/control/control_strategies/converters/toh2integrate/demand/Section 4.1: New Files
h2integrate/control/test/test_converter_control_strategies.py: new test file for the tests of theDemandOpenLoopConverterControllerandFlexibleDemandOpenLoopConverterControllerthat previously existed inh2integrate/control/test/test_openloop_controllers.py. This has been moved toh2integrate/demand/test/Section 4.2: Modified Files
h2integrate/control/control_strategies/converters/demand_openloop_converter_controller.pyDemandOpenLoopConverterController: renamed outputs, added performance model outputsh2integrate/control/control_strategies/converters/flexible_demand_openloop_controller.pyFlexibleDemandOpenLoopConverterController: renamed outputs, added performance model outputsh2integrate/control/control_strategies/converters/openloop_controller_base.pyConverterOpenLoopControlBase: removedtotal_commodity_unmet_demandfrom output, updated output naming as outlined in Section 1.Section 5: Additional Supporting Information
These control strategies were developed during the natural-gas for data-center work. When I initially made what is now the
DemandOpenLoopConverterController- I called it a "generic demand component". This was brought into H2I shortly after theDemandOpenLoopStorageController, which, at the time, did similar calculations for unmet demand, excess commodity production, etc. Since the generic demand component had such similarities to the outputs of theDemandOpenLoopStorageController- it was decided to define this as a "converter control strategy".However, since the work on refactoring the storage dispatch and storage performance models (Issue #564, which most relevantly included PR #566, #498, and #612), the storage controllers no longer output the excess commodity produced or unmet demand, these are done in the storage performance models.
At this stage, there is no similar usage between the
DemandOpenLoopStorageControllerand theDemandOpenLoopStorageController. Therefore, I think that its time to refactor the names of these demand components so that they can be used to resolve Issue #521 and be defined based on their primary usage, which is to calculate demand-related metrics rather than function as a controller.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