Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
19ff6e1
initial example files for plm for a converter
jaredthomas68 May 15, 2026
d026a8a
run converter plm with single demand profile
jaredthomas68 May 15, 2026
c653a77
merge from develop
jaredthomas68 May 26, 2026
c1564c2
Merge branch 'develop' into control-converter
jaredthomas68 May 27, 2026
1d80254
have precommit ignore demand profiles for converter plm example
jaredthomas68 May 27, 2026
bcd95c2
peak load converter working with multiple demand profiles
jaredthomas68 May 27, 2026
d58cbf9
minor plot updates
jaredthomas68 May 27, 2026
0f99537
remove incorrect comments
jaredthomas68 May 28, 2026
3d7dc9c
add key file that was missed earlier
jaredthomas68 May 29, 2026
3b2fdfd
include init file
jaredthomas68 May 29, 2026
eafbf14
update units/naming
jaredthomas68 Jun 1, 2026
d885c12
bugfix, grap element instead of array
jaredthomas68 Jun 2, 2026
b964811
Merge branch 'develop' into control-converter
kbrunik Jun 9, 2026
19b84f9
include price dispatch capability to converter demand control
jaredthomas68 Jun 9, 2026
6193c9a
Merge remote-tracking branch 'myfork/control-converter' into control-…
jaredthomas68 Jun 9, 2026
1602280
wip
jaredthomas68 Jun 11, 2026
2afd03b
include unit definitions for peak cutoff
jaredthomas68 Jun 16, 2026
6296b1a
Merge branch 'develop' into control-converter
jaredthomas68 Jun 16, 2026
c124ecb
update naming:
jaredthomas68 Jun 17, 2026
b4f54ba
Fuel Cell Operational Calculations (#5)
kbrunik Jun 18, 2026
7b8c33a
resolve merge conflict
jaredthomas68 Jul 24, 2026
8bc1616
move demand profiles for examples to library and update converter plm…
jaredthomas68 Jul 24, 2026
d0abe9f
put converter and storage peak load management examples in subfolders…
jaredthomas68 Jul 24, 2026
6c5caed
reformat and fix pre-commit hook ignores
jaredthomas68 Jul 24, 2026
e09472a
move heuristic plm examples to 33_peak_load_management_heuristics
jaredthomas68 Jul 24, 2026
fd466c6
rename run files for example 33
jaredthomas68 Jul 24, 2026
02ea362
update docstrings and example descriptions for plm heuristic
jaredthomas68 Jul 24, 2026
c448201
update descriptions
jaredthomas68 Jul 24, 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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ repos:
- id: yamlfix
# Exclude YAML files that are used as inputs for testing or examples, or ones for desired schedule in HOPP as they
# expect misformatted YAML files.
exclude: ^(h2integrate/core/test/inputs/.*|examples/11_hybrid_energy_plant/tech_inputs/desired_schedules/.*|examples/33_peak_load_management/demand_profiles/.*|examples/34_plm_optimized_dispatch/demand_profiles/.*)$
exclude: ^(h2integrate/core/test/inputs/.*|examples/11_hybrid_energy_plant/tech_inputs/desired_schedules/.*|library/demand_profiles/.*|examples/34_plm_optimized_dispatch/demand_profiles/.*)$
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.8.1
Expand Down
5 changes: 0 additions & 5 deletions examples/33_peak_load_management/driver_config.yaml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: driver_config
description: Driver configuration for peak load management converter heuristic control
general:
folder_output: outputs
create_om_reports: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: plant_config
description: Plant configuration for peak load management converter heuristic control
plant:
plant_life: 30
simulation:
n_timesteps: 8760
dt: 3600
timezone: -6
start_time: 2025/07/01 00:00:00
technology_interconnections:
- [hydrogen_feedstock, fuel_cell, hydrogen, pipe]
- [fuel_cell, electrical_load_demand, [electricity_out, electricity_in]]
- [electrical_load_demand, grid_buy, [unmet_electricity_demand_out, electricity_set_point]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""
Example 33: Peak load management converter heuristic dispatch

This example demonstrates peak load management dispatch open loop control of a converter
with two demand profiles of interest

In this example, the fuel-cell converter command is determined by a simple open-loop
threshold heuristic that uses two profiles:

1. demand_profile (local set-point)
2. demand_profile_upstream (supervisory or upstream signal)

At each time step, dispatch is only considered when either profile exceeds its configured
cutoff. For electricity-mode upstream control, the commanded dispatch is based on the
larger exceedance of the two profiles and is then limited by both the instantaneous local
demand and converter capacity. This creates a peak-shaving command profile for the
converter without storage state-of-charge dynamics or optimization.

The output figure compares the original local demand, upstream demand, cutoff thresholds,
converter output, resulting unmet demand, and grid purchases.

"""

import numpy as np
import matplotlib.pyplot as plt

from h2integrate import H2IntegrateModel
from h2integrate.core.utilities import build_time_series_from_plant_config


# Create, setup, and run the H2Integrate model
model = H2IntegrateModel("33_plm_converter_heuristic.yaml")

model.setup()
# om.n2(model.prob)
model.run()
model.post_process()

demand_profile = model.prob.get_val("fuel_cell.electricity_command_value", units="kW")
# plot the results for the first week
demand_profile_upstream = np.array(
model.technology_config["technologies"]["fuel_cell"]["model_inputs"]["control_parameters"][
"demand_profile_upstream"
]
)
demand_profile_peak_cutoff = model.technology_config["technologies"]["fuel_cell"]["model_inputs"][
"control_parameters"
]["demand_profile_peak_cutoff"]
demand_profile_upstream_peak_cutoff = model.technology_config["technologies"]["fuel_cell"][
"model_inputs"
]["control_parameters"]["demand_profile_upstream_peak_cutoff"]
grid_output = model.prob.get_val("grid_buy.electricity_out", units="MW")

time_series = build_time_series_from_plant_config(model.plant_config)

n_plot = 24 * 7
time_plot = time_series[:n_plot]

fig, ax = plt.subplots(3, 1, sharex=True, figsize=(10, 5))
ax[0].plot(time_plot, demand_profile_upstream[:n_plot] * 1e-3, label="Upstream demand")
ax[0].plot(time_plot, demand_profile[:n_plot] * 1e-3, label="Original demand")
ax[0].axhline(
demand_profile_peak_cutoff * 1e-3, label="Demand peak cutoff", color="k", linestyle="--"
)
ax[0].axhline(
demand_profile_upstream_peak_cutoff * 1e-3,
label="Upstream demand peak cutoff",
color="k",
linestyle=":",
)
ax[0].set(ylabel="Power (MW)", ylim=[-2, 2])
ax[0].legend(frameon=True, ncol=3)

ax[1].plot(time_plot, demand_profile[:n_plot] * 1e-3, label="Original demand (MW)")
ax[1].plot(
time_plot,
model.prob.get_val("fuel_cell.electricity_out", units="MW")[:n_plot],
label="fuel_cell dispatch",
)
ax[1].set(ylabel="Power (MW)", ylim=[-2, 2])
ax[1].legend(frameon=False, ncol=2)

ax[2].plot(time_plot, demand_profile[:n_plot] * 1e-3, label="Original demand (MW)")
ax[2].plot(
time_plot,
model.prob.get_val("electrical_load_demand.unmet_electricity_demand_out", units="MW")[:n_plot],
label="New demand profile",
)
ax[2].plot(time_plot, grid_output[:n_plot], label="Grid purchase (MW)", linestyle=":")

ax[2].set(ylabel="Power (MW)", ylim=[-2, 2])
ax[2].legend(frameon=False, ncol=3)
ax[2].tick_params(axis="x", labelrotation=90)

for axis in ax:
axis.minorticks_on()
axis.grid(True, which="major", alpha=0.45, linewidth=0.8)
axis.grid(True, which="minor", alpha=0.2, linewidth=0.5)

plt.tight_layout()
plt.savefig("example_peak_load_dispatch.png", transparent=False)
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: technology_config
description: This plant dispatches a fuel cell to reduce peak demand
technologies:
hydrogen_feedstock:
performance_model:
model: FeedstockPerformanceModel
cost_model:
model: FeedstockCostModel
model_inputs:
shared_parameters:
commodity: hydrogen
commodity_rate_units: kg/h
performance_parameters:
rated_capacity: 50.0 # kg of H2/hour
cost_parameters:
cost_year: 2022
price: 5.0 # USD/kg H2
annual_cost: 0.
start_up_cost: 0.0
fuel_cell:
performance_model:
model: LinearH2FuelCellPerformanceModel
cost_model:
model: H2FuelCellCostModel
control_strategy:
model: PeakLoadManagementHeuristicOpenLoopConverterController
model_inputs:
shared_parameters:
system_capacity_kw: 1000.0
performance_parameters:
fuel_cell_efficiency_hhv: 0.50
uptime_hours_until_eol: 80000
cost_parameters:
capex_per_kw: 200.0
fixed_opex_per_kw_per_year: 10.0
variable_opex_per_kwh: 0.0
cost_year: 2018
control_parameters:
commodity: electricity
commodity_rate_units: kW
demand_profile: !include demand_profiles/demand_profile.yaml
demand_profile_upstream: !include demand_profiles/demand_profile_upstream.yaml
demand_profile_peak_cutoff: 400.0
demand_profile_upstream_peak_cutoff: 1000.0
electrical_load_demand:
performance_model:
model: GenericDemandComponent
model_inputs:
performance_parameters:
commodity: electricity
commodity_rate_units: kW
demand_profile: !include demand_profiles/demand_profile.yaml
grid_buy:
performance_model:
model: GridPerformanceModel
cost_model:
model: GridCostModel
model_inputs:
shared_parameters:
interconnection_size: 100000
cost_parameters:
cost_year: 2024
fixed_interconnection_cost: 0.0
interconnection_capex_per_kw: 0.0
interconnection_opex_per_kw: 0.0
electricity_buy_price: 0.09

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it could be good to have both peak load management examples (storage and converter) in the same folder 33_peak_load_management and then have nested folders for each example.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's update name of this file so it's not the same as the storage PLM file.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: H2Integrate_config
system_summary: Peak load management dispatch
driver_config: driver_config.yaml
technology_config: tech_config.yaml
plant_config: plant_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: driver_config
description: Driver configuration for peak load management storage heuristic control
general:
folder_output: outputs
create_om_reports: false
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: plant_config
description: Demonstrates multivariable streams with a gas combiner
description: Plant configuration for peak load management storage heuristic control
plant:
plant_life: 30
simulation:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Example 33: Peak load management dispatch
Example 33: Peak load management storage heuristic dispatch

This example demonstrates:
1. Peak load management dispatch open loop control with two demand profiles of interest
Expand Down Expand Up @@ -32,7 +32,7 @@


# Create, setup, and run the H2Integrate model
model = H2IntegrateModel("33_peak_load_management.yaml")
model = H2IntegrateModel("33_plm_storage_heuristic.yaml")

model.setup()
model.run()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: technology_config
description: This plant charges a battery from the grid to reduce peak demand
description: This plant dispatches a battery to reduce peak demand
technologies:
battery:
performance_model:
Expand Down
3 changes: 3 additions & 0 deletions h2integrate/control/control_strategies/converters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from h2integrate.control.control_strategies.converters.plm_openloop_converter_controller import (
PeakLoadManagementHeuristicOpenLoopConverterController,
)
Loading
Loading