Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
168766a
include code from usage: pyomo [-h] [--version]
jaredthomas68 Oct 2, 2025
df63126
include storage rule file
jaredthomas68 Oct 9, 2025
73f87d7
Merge remote-tracking branch 'origin/develop' into pyomo_opt
bayc Nov 17, 2025
80782e1
Merge branch 'pyomo_opt' into feature/pyomo_opt
genevievestarke Nov 18, 2025
6971220
Halfway there for pyomo opt
genevievestarke Dec 2, 2025
5a2ce87
Add first objective function
genevievestarke Dec 5, 2025
c7923c4
Updated dispatch optimization framework - add hybrid dispatch rule
genevievestarke Dec 9, 2025
38c929d
Merge remote-tracking branch 'origin/develop' into feature/pyomo_opt
bayc Dec 9, 2025
03d7c1d
Adding hybrid linking constraints and connecting variables in pyomo m…
genevievestarke Dec 11, 2025
9509748
Merge branch 'feature/pyomo_opt' of https://github.com/genevievestark…
bayc Dec 11, 2025
5fa7165
Merge remote-tracking branch 'origin/develop' into feature/pyomo_opt
bayc Dec 11, 2025
2194701
Merge remote-tracking branch 'origin/develop' into feature/pyomo_opt
bayc Dec 15, 2025
c2f1bbb
Final structural changes
genevievestarke Dec 16, 2025
4d676fb
Fix import statement
genevievestarke Dec 16, 2025
0c642d0
Fix imports and setter method
genevievestarke Dec 16, 2025
22e411f
First draft of running code
genevievestarke Dec 23, 2025
efc2069
Update example
genevievestarke Dec 30, 2025
8650683
Merge branch 'develop' into feature/pyomo_opt
kbrunik Jan 2, 2026
e947332
test
kbrunik Jan 2, 2026
581e101
fix precommits
kbrunik Jan 2, 2026
1dbb52b
Merge branch 'develop' into feature/pyomo_opt
johnjasa Jan 5, 2026
4f2faea
Fixing merge errors
johnjasa Jan 6, 2026
39ad186
Minor spelling changes
johnjasa Jan 6, 2026
ec3ad18
Update example
genevievestarke Jan 7, 2026
b1cc99b
Update controller problem state method from Elenya
genevievestarke Jan 7, 2026
24cc0b8
Update example and changelog
genevievestarke Jan 7, 2026
abf9d49
Clean up pyomo storage baseclass file
genevievestarke Jan 7, 2026
a2da8b9
Merge branch 'develop' into feature/pyomo_opt
johnjasa Jan 7, 2026
5a26e58
Cleanups to feature/pyomo opt (#2)
elenya-grant Jan 9, 2026
72205b2
Enable heuristic dispatch to run with new pyomo changes
genevievestarke Jan 12, 2026
5c16393
Clean up added files and example
genevievestarke Jan 17, 2026
6de9803
Adding first tests - do not pass yet
genevievestarke Jan 21, 2026
dc059b9
Merge branch 'develop' into feature/pyomo_opt
genevievestarke Jan 21, 2026
5d36008
Update docs and rename example
genevievestarke Jan 21, 2026
ba6d65d
Align naming with develop branch
genevievestarke Jan 21, 2026
bb8e7d8
Update Ex 02 and update pyomo_controllers with naming in develop
genevievestarke Jan 21, 2026
6a1d050
updated other example tech configs
elenya-grant Jan 21, 2026
57bf534
ran precommit on some files
elenya-grant Jan 21, 2026
0acaa30
precommit on pyomo_controllers.py
elenya-grant Jan 21, 2026
e3d0315
Update test formatting
genevievestarke Jan 21, 2026
a509354
Update pyomo storage rule for test
genevievestarke Jan 21, 2026
2342730
Fix SOC linking bug
genevievestarke Jan 23, 2026
c2604b6
Testing update - partial
genevievestarke Jan 26, 2026
5f33847
Make new test for optimized pyomo dispatch
genevievestarke Jan 26, 2026
363bfbf
Update optimal controller test
genevievestarke Jan 27, 2026
f42f935
Update test with new site definition
genevievestarke Jan 27, 2026
bfd4e9c
Merge branch 'develop' into feature/pyomo_opt
genevievestarke Jan 27, 2026
db32b3a
Update example for merging in develop
genevievestarke Jan 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Added standalone iron DRI and steel EAF performance and cost models
- Added capability to have transport models that require user input parameters
- Add geologic hydrogen surface processing converter
- Add optimal dispatch of storage for load following
- Add baseclass for caching functionality
- Added postprocessing function to save timeseries
- Minor reorg for profast tools
Expand Down
15 changes: 12 additions & 3 deletions docs/control/pyomo_controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@
# Pyomo control framework
[Pyomo](https://www.pyomo.org/about) is an open-source optimization software package. It is used in H2Integrate to facilitate modeling and solving control problems, specifically to determine optimal dispatch strategies for dispatchable technologies.

Pyomo control, allows for the possibility of feedback control at specified intervals, but can also be used for open-loop control if desired. In the pyomo control framework in H2Integrate, each technology can have control rules associated with them that are in turn passed to the pyomo control component, which is owned by the storage technology. The pyomo control component combines the technology rules into a single pyomo model, which is then passed to the storage technology performance model inside a callable dispatch function. The dispatch function also accepts a simulation method from the performance model and iterates between the pyomo model for dispatch commands and the performance simulation function to simulated performance with the specified commands. The dispatch function runs in specified time windows for dispatch and performance until the whole simulation time has been run.
Pyomo control allows for the possibility of feedback control at specified intervals, but can also be used for open-loop control if desired. In the pyomo control framework in H2Integrate, each technology can have control rules associated with them that are in turn passed to the pyomo control component, which is owned by the storage technology. The pyomo control component combines the technology rules into a single pyomo model, which is then passed to the storage technology performance model inside a callable dispatch function. The dispatch function also accepts a simulation method from the performance model and iterates between the pyomo model for dispatch commands and the performance simulation function to simulate performance with the specified commands. The dispatch function runs in specified time windows for dispatch and performance until the whole simulation time has been run.

An example of an N2 diagram for a system using the pyomo control framework for hydrogen storage and dispatch is shown below ([click here for an interactive version](./figures/pyomo-n2.html)). Note the control rules being passed to the dispatch component and the dispatch function, containing the full pyomo model, being passed to the performance model for the battery/storage technology. Another important thing to recognize, in contrast to the open-loop control framework, is that the storage technology outputs (commodity out, SOC, unused commodity, etc) are passed out of the performance model when using the Pyomo control framework rather than from the control component.

![](./figures/pyomo-n2.png)

The pyomo control framework currently supports both a simple heuristic method and an optimized dispatch method for load following control.

(heuristic-load-following-controller)=
## Heuristic Load Following Controller
The pyomo control framework currently supports only a simple heuristic method, `heuristic_load_following_controller`, but we plan to extend the framework to be able to run a full dispatch optimization using a pyomo solver. When using the pyomo framework, a `dispatch_rule_set` for each technology connected to the storage technology must also be specified. These will typically be `pyomo_dispatch_generic_converter` for generating technologies, and `pyomo_dispatch_generic_storage` for storage technologies. More complex rule sets may be developed as needed.
The simple heuristic method is specified by setting the storage control to `heuristic_load_following_controller`. When using the pyomo framework, a `dispatch_rule_set` for each technology connected to the storage technology must also be specified. These will typically be `pyomo_dispatch_generic_converter` for generating technologies, and `pyomo_dispatch_generic_storage` for storage technologies. More complex rule sets may be developed as needed.

For an example of how to use the pyomo control framework with the `heuristic_load_following_controller`, see
For an example of how to use the heuristic pyomo control framework with the `heuristic_load_following_controller`, see
- `examples/18_pyomo_heuristic_wind_battery_dispatch`

(optimized-load-following-controller)=
## Optimized Load Following Controller
The optmimized dispatch method is specified by setting the storage control to `optimized_dispatch_controller`. The same `dispatch_rule_set` for each technology connected to the storage technology is followed as in the heuristic case. This method maximizes the load met while minimizing the cost of the system (operating cost) over each specified time window.

For an example of how to use the optimized pyomo control framework with the `optimized_dispatch_controller`, see
- `examples/27_pyomo_optimized_dispatch`
5 changes: 1 addition & 4 deletions examples/01_onshore_steel_mn/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ technologies:
model_inputs:
shared_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
max_charge_rate: 375740.4 #kW
max_capacity: 375745.2 #kWh
n_control_window: 24
Expand All @@ -100,11 +101,7 @@ technologies:
power_capex: 311 # $/kW from 2024 ATB year 2025
opex_fraction: 0.024999840573439444
control_parameters:
commodity_storage_units: "kW"
tech_name: "battery"
dispatch_rule_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"

electrolyzer:
performance_model:
Expand Down
6 changes: 2 additions & 4 deletions examples/02_texas_ammonia/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ technologies:
model_inputs:
shared_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
max_charge_rate: 96.0 #kW
max_capacity: 96.0 #kWh
n_control_window: 24
Expand All @@ -98,11 +99,8 @@ technologies:
power_capex: 311 # $/kW from 2024 ATB year 2025
opex_fraction: 0.025
control_parameters:
commodity_storage_units: "kW"
tech_name: "battery"
dispatch_rule_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"

electrolyzer:
performance_model:
model: "eco_pem_electrolyzer_performance"
Expand Down
6 changes: 2 additions & 4 deletions examples/09_co2/direct_ocean_capture/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ technologies:
model_inputs:
shared_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
max_charge_rate: 50000 #kW
max_capacity: 200000 #kWh
n_control_window: 24
Expand All @@ -91,11 +92,8 @@ technologies:
power_capex: 317 # $/kW from 2024 ATB year 2025
opex_fraction: 0.02536510376633359
control_parameters:
commodity_storage_units: "kW"
tech_name: "battery"
dispatch_rule_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"

doc:
performance_model:
model: "direct_ocean_capture_performance"
Expand Down
6 changes: 2 additions & 4 deletions examples/09_co2/ocean_alkalinity_enhancement/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ technologies:
model_inputs:
shared_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
max_charge_rate: 50000 #kW
max_capacity: 200000 #kWh
n_control_window: 24
Expand All @@ -68,11 +69,8 @@ technologies:
power_capex: 317 # $/kW from 2024 ATB year 2025
opex_fraction: 0.02536510376633359
control_parameters:
commodity_storage_units: "kW"
tech_name: "battery"
dispatch_rule_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"

oae:
performance_model:
model: "ocean_alkalinity_enhancement_performance"
Expand Down
6 changes: 2 additions & 4 deletions examples/12_ammonia_synloop/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ technologies:
model_inputs:
shared_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
max_charge_rate: 96.0 #kW
max_capacity: 96.0 #kWh
n_control_window: 24
Expand All @@ -98,11 +99,8 @@ technologies:
power_capex: 311 # $/kW from 2024 ATB year 2025
opex_fraction: 0.025
control_parameters:
commodity_storage_units: "kW"
tech_name: "battery"
dispatch_rule_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"

electrolyzer:
performance_model:
model: "eco_pem_electrolyzer_performance"
Expand Down
5 changes: 1 addition & 4 deletions examples/18_pyomo_heuristic_dispatch/tech_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ technologies:
model_inputs:
shared_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
max_charge_rate: 100000
max_capacity: 500000
n_control_window: 24
Expand All @@ -64,8 +65,4 @@ technologies:
power_capex: 311 # $/kW from 2024 ATB year 2025
opex_fraction: 0.25 # 0.25% of capex per year from 2024 ATB
control_parameters:
commodity_storage_units: "kW"
tech_name: "battery"
dispatch_rule_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ technologies:
model: "atb_battery_cost"
model_inputs:
shared_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
max_charge_rate: 100000
max_capacity: 500000
n_control_window: 24
Expand All @@ -65,9 +67,4 @@ technologies:
power_capex: 311 # $/kW from 2024 ATB year 2025
opex_fraction: 0.25 # 0.25% of capex per year from 2024 ATB
control_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
tech_name: "wrong_tech_name"
dispatch_rule_parameters:
commodity_name: "electricity"
commodity_storage_units: "kW"
5 changes: 5 additions & 0 deletions examples/27_pyomo_optimized_dispatch/driver_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: "driver_config"
description: "This analysis runs a hybrid plant to dispatch storage optimally to meet an electrical load."

general:
folder_output: outputs
73 changes: 73 additions & 0 deletions examples/27_pyomo_optimized_dispatch/plant_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: "plant_config"
description: "This plant is located in TX, USA..."

sites:
site:
latitude: 35.2018863
longitude: -101.945027

resources:
wind_resource:
resource_model: "wind_toolkit_v2_api"
resource_parameters:
resource_year: 2012

plant:
plant_life: 30

# array of arrays containing left-to-right technology
# interconnections; can support bidirectional connections
# with the reverse definition.
# this will naturally grow as we mature the interconnected tech
technology_interconnections: [
["wind", "battery", "electricity", "cable"],
]

# array of arrays containing left-to-right technology, technology doing the dispatching
# in this case, battery is connected to battery because there are controls rules for
# the battery and battery is controlling the dispatching
tech_to_dispatch_connections: [
["wind", "battery"],
["battery", "battery"],
]

resource_to_tech_connections: [
# connect the wind resource to the wind technology
['site.wind_resource', 'wind', 'wind_resource_data'],
]

finance_parameters:
finance_groups:
commodity: "electricity"
finance_model: "ProFastComp"
model_inputs:
params:
analysis_start_year: 2032
installation_time: 36 # months
inflation_rate: 0.0 # 0 for nominal analysis
discount_rate: 0.09 # nominal return based on 2024 ATB baseline workbook for land-based wind
debt_equity_ratio: 2.62 # 2024 ATB uses 72.4% debt for land-based wind
property_tax_and_insurance: 0.03 # p-tax https://www.house.mn.gov/hrd/issinfo/clsrates.aspx # insurance percent of CAPEX estimated based on https://www.nrel.gov/docs/fy25osti/91775.pdf
total_income_tax_rate: 0.257 # 0.257 tax rate in 2024 atb baseline workbook, value here is based on federal (21%) and state in MN (9.8)
capital_gains_tax_rate: 0.15 # H2FAST default
sales_tax_rate: 0.07375 # total state and local sales tax in St. Louis County https://taxmaps.state.mn.us/salestax/
debt_interest_rate: 0.07 # based on 2024 ATB nominal interest rate for land-based wind
debt_type: "Revolving debt" # can be "Revolving debt" or "One time loan". Revolving debt is H2FAST default and leads to much lower LCOH
loan_period_if_used: 0 # H2FAST default, not used for revolving debt
cash_onhand_months: 1 # H2FAST default
admin_expense: 0.00 # percent of sales H2FAST default
capital_items:
depr_type: "MACRS" # can be "MACRS" or "Straight line" - MACRS may be better and can reduce LCOH by more than $1/kg and is spec'd in the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507
depr_period: 5 # years - for clean energy facilities as specified by the IRS MACRS schedule https://www.irs.gov/publications/p946#en_US_2020_publink1000107507
cost_adjustment_parameters:
cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year
target_dollar_year: 2022
finance_subgroups:
all_electricity:
commodity: "electricity"
commodity_stream: "wind" # use all electricity generated from wind in finance calc
technologies: ["wind", "battery"]
dispatched_electricity:
commodity: "electricity"
commodity_stream: "battery" #use only dispatched electricity from battery in finance calc
technologies: ["wind", "battery"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: "H2Integrate_config"

system_summary: "This hybrid plant contains wind and battery storage technologies. The system is designed to meet a specific electrical load."

driver_config: "driver_config.yaml"
technology_config: "tech_config_error_for_testing.yaml"
plant_config: "plant_config.yaml"
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: "H2Integrate_config"

system_summary: "This hybrid plant contains wind and battery storage technologies. The system is designed to dispatch storage optimally meet a specific electrical load."

driver_config: "driver_config.yaml"
technology_config: "tech_config.yaml"
plant_config: "plant_config.yaml"
Loading