Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
- Enable `PySAMWindPlantPerformanceModel` to accept more than 300 turbines by overriding the default maximum in the PySAM model. [PR 831](https://github.com/NatLabRockies/H2Integrate/pull/831)
- Add `PySAMWavePerformanceModel` and `WaveResource` to wrap PySAM MhkWave as an H2I performance model, replacing the HOPP wave module in example 09. [PR 825](https://github.com/NatLabRockies/H2Integrate/pull/825)
- Replace HOPP with native H2I wind, solar, and battery models in example 11. Adds `percent_load_missed` and `curtailment_percent` outputs to `DemandComponentBase`, allows zero capacity in wind/solar/battery performance models. [PR 826](https://github.com/NatLabRockies/H2Integrate/pull/826)
- Add heterogeneous-commodity system-level control that translates demand for one commodity into upstream set-points across converters using static per-technology conversion ratios defined in the tech config. [PR TBD](https://github.com/NatLabRockies/H2Integrate/pull/TBD)
- Extend the heterogeneous-commodity control to prefer measured conversion ratios computed from each converter's consumed and produced streams per timestep, falling back to the static ratio when a measurement is unavailable. [PR TBD](https://github.com/NatLabRockies/H2Integrate/pull/TBD)
- Add the `35_system_level_control/heterogeneous_commodity` example, which serves an ammonia demand from a wind, battery, grid, electrolyzer, hydrogen-storage, and ammonia synthesis loop chain to demonstrate demand propagating from ammonia to hydrogen to electricity. The example uses profit-maximizing control so that wind always runs, the battery charges on wind surplus and discharges to cover deficits, and the grid is only dispatched to backfill the electricity that wind and the battery cannot supply, and it generates dispatch and dynamic conversion-ratio figures. [PR TBD](https://github.com/NatLabRockies/H2Integrate/pull/TBD)
- Add a system block diagram and a conversion-ratio chain figure to the heterogeneous-commodity example that show the technologies, their control classifications, the per-converter conversion ratios, and how those ratios multiply to propagate ammonia demand back into hydrogen and electricity demand. [PR TBD](https://github.com/NatLabRockies/H2Integrate/pull/TBD)

## 0.9 [August 10, 2026]

Expand Down
6 changes: 6 additions & 0 deletions docs/control/system_level_control/slc_demand_following.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ The inputs for technologies classified as `feedstock` are:
The `DemandFollowingControl` controller can be used in hybrid systems where technologies produce different commodities.
For example, in a system where an electrolyzer produces hydrogen and the demand commodity is hydrogen, the controller can set the electricity-generating *curtailable* technologies' set-points to meet the hydrogen demand.

The controller can also propagate demand backward across converters, which are technologies whose output commodity differs from an input commodity they consume.
When a converter has a controllable producer for one of its input commodities, the demand for the converter's output commodity is translated into a demand for that input commodity using a conversion ratio.
The controller prefers a measured conversion ratio, computed per timestep from the converter's consumed and produced streams, and falls back to a static ratio supplied under `technologies.<tech>.model_inputs.control_parameters.conversion_ratios` when a measurement is unavailable.
This propagation can chain across multiple converters. For example, an ammonia demand is translated into a hydrogen demand across an ammonia synthesis loop, and that hydrogen demand is then translated into an electricity demand across an electrolyzer, which the curtailable and dispatchable electricity technologies serve.
The `examples/35_system_level_control/heterogeneous_commodity` example demonstrates this end to end with a wind, battery, grid, electrolyzer, hydrogen-storage, and ammonia synthesis loop chain served against an ammonia demand. The example uses profit-maximizing control, so wind always runs, the battery charges on wind surplus and discharges to cover deficits, and the grid is only dispatched to backfill the electricity that wind and the battery cannot supply. Its runner script writes dispatch and dynamic conversion-ratio figures to an `outputs` folder.

This framework provides a starting point for hybrid energy system control but is intended to be extended with more sophisticated strategies for complex multi-commodity systems.

## Limitations
Expand Down
22 changes: 21 additions & 1 deletion docs/control/system_level_control/system_level_control_base.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,27 @@ Setup I/O for SLC controllers.
- `_setup_tech_category()`
- `_setup_feedstock_category()`
- `find_converter_techs()`
- Note: this method is currently is not used but will be used for heterogeneous commodity systems.

Heterogeneous-commodity conversion. These methods let a controller translate demand
for one commodity into demand for the upstream commodities that a converter consumes
to produce it (for example, translating ammonia demand into hydrogen demand across a
synthesis loop, and then into electricity demand across an electrolyzer).
- `detect_commodity_converters()`
- Module-level helper that identifies converter technologies (technologies whose
output commodity differs from an input commodity) that have a controllable
producer for that input commodity, so demand can propagate backward across them.
- `_build_conversion_ratios()`
- Registers each converter's `{commodity}_consumed` inputs and reads any static
conversion ratios supplied under
`technologies.<tech>.model_inputs.control_parameters.conversion_ratios`.
- `_conversion_ratio()`
- Returns the per-timestep conversion ratio for a converter. It prefers a measured
ratio computed from the converter's consumed and produced streams, and falls back
to the static ratio from the technology config when a measurement is unavailable.
- `_accumulate_derived_demand()`
- Adds the demand derived through a converter (output demand times conversion ratio)
to the upstream commodity's demand, warning only when neither a measured nor a
static ratio is available.

Functions for controlling components based on assigned control classifier.
- `_subtract_curtailable()`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: driver_config
description: This analysis runs a wind and battery powered green ammonia plant under system-level control
general:
folder_output: outputs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: H2Integrate_config
driver_config: driver_config.yaml
plant_config: plant_config.yaml
technology_config: tech_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: plant_config
description: This plant is located in Texas, USA.
sites:
site:
latitude: 30.6617
longitude: -101.7096
resources:
wind_resource:
resource_model: WTKNLRDeveloperAPIWindResource
resource_parameters:
resource_year: 2013
# array of arrays containing left-to-right technology interconnections
technology_interconnections:
# wind output available for battery charging (electricity_in)
- [wind, battery, electricity, cable]
# wind to the combined electricity output
- [wind, elec_combiner, electricity, cable]
# battery net output to the combined electricity output
- [battery, elec_combiner, electricity, cable]
# dispatchable grid backup to the combined electricity output
- [grid, elec_combiner, electricity, cable]
# combined electricity to the electrolyzer
- [elec_combiner, electrolyzer, electricity, cable]
# electrolyzer to hydrogen storage
- [electrolyzer, h2_storage, hydrogen, pipe]
# combine the hydrogen streams from the electrolyzer and storage
- [electrolyzer, h2_combiner, hydrogen, pipe]
- [h2_storage, h2_combiner, hydrogen, pipe]
# hydrogen supply to the ammonia synthesis loop
- [h2_combiner, ammonia, hydrogen, pipe]
# nitrogen and electricity feedstocks for the synthesis loop
- [n2_feedstock, ammonia, nitrogen, pipe]
- [electricity_feedstock, ammonia, electricity, cable]
# ammonia supply to the ammonia demand
- [ammonia, ammonia_load_demand, ammonia, pipe]
resource_to_tech_connections:
# connect the wind resource to the wind technology
- [site.wind_resource, wind, wind_resource_data]
plant:
plant_life: 30
simulation:
n_timesteps: 8760
dt: 3600
system_level_control:
control_strategy: ProfitMaximizationControl
demand_component: ammonia_load_demand
# Profit-maximizing dispatch. The controller honors each technology's control
# classification, which produces the desired behavior for this plant:
# - wind is flexible, so it always runs at its available (curtailable) output;
# - the battery is storage, so it charges on surplus and discharges to cover deficits;
# - the grid is a dispatchable source, so merit-order dispatch only calls on it to
# backfill the electricity that wind and the battery cannot supply.
# Ammonia is produced at every timestep where its sell price exceeds its marginal
# cost, so the whole chain runs whenever ammonia production is profitable.
control_parameters:
commodity_sell_price: 0.60 # USD/kg ammonia sell price (above the marginal cost so demand is served)
cost_per_tech:
# Ammonia marginal cost is taken from its upstream nitrogen and direct-electricity
# feedstocks; the grid, wind, and battery are not feedstocks and are not summed here.
ammonia: feedstock
# Static seed ratios for the commodity converters, keyed by technology. The
# controller prefers the measured ratio (input_consumed / output_produced)
# once the solver has values and uses these seeds on iteration zero and for
# zero-output timesteps. Feedstock-supplied inputs (for example nitrogen into
# the synloop) are not controller-managed and need no ratio.
conversion_parameters:
electrolyzer:
electricity_per_hydrogen: 51.0 # kWh electricity per kg hydrogen
ammonia:
hydrogen_per_ammonia: 0.2 # kg hydrogen per kg ammonia
electricity_per_ammonia: 0.530645243 # kWh electricity per kg ammonia
solver_options:
solver_name: gauss_seidel
max_iter: 50
convergence_tolerance: 1.0e-6
finance_parameters:
finance_groups:
profast_lco:
finance_model: ProFastLCO
model_inputs:
params:
analysis_start_year: 2032
installation_time: 36 # months
inflation_rate: 0.0 # 0 for nominal analysis
discount_rate: 0.09
debt_equity_ratio: 2.62
property_tax_and_insurance: 0.03
total_income_tax_rate: 0.257
capital_gains_tax_rate: 0.15
sales_tax_rate: 0.07375
debt_interest_rate: 0.07
debt_type: Revolving debt
loan_period_if_used: 0
cash_onhand_months: 1
admin_expense: 0.00
capital_items:
depr_type: MACRS
depr_period: 5
refurb: [0.]
finance_subgroups:
ammonia:
commodity: ammonia
commodity_stream: ammonia
finance_groups: [profast_lco]
technologies:
- wind
- battery
- grid
- electrolyzer
- h2_storage
- n2_feedstock
- electricity_feedstock
- ammonia
cost_adjustment_parameters:
cost_year_adjustment_inflation: 0.025 # used to adjust modeled costs to target_dollar_year
target_dollar_year: 2022
Loading
Loading