Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
1b9f88d
renamed outputs in converter openloop controllers
elenya-grant Mar 26, 2026
2b3d0c1
updated tests and examples with updated naming
elenya-grant Mar 26, 2026
2af6329
Merge remote-tracking branch 'h2i_upstream/develop' into dispatch/con…
elenya-grant Mar 27, 2026
c59a20e
Merge branch 'develop' into dispatch/converter_ol_sync
kbrunik Mar 31, 2026
eab6d09
added performance model outputs to the converter control strategies
elenya-grant Apr 1, 2026
1e54ed2
udpated plant configs in test_openloop_controllers.py
elenya-grant Apr 1, 2026
1852db4
Merge branch 'develop' into dispatch/converter_ol_sync
johnjasa Apr 1, 2026
b1b62c9
moved converter control strategies to separate file
elenya-grant Apr 1, 2026
a97292c
Merge branch 'dispatch/converter_ol_sync' of github.com:elenya-grant/…
elenya-grant Apr 6, 2026
2d6b0c5
moved converter control strategies to demand folder
elenya-grant Apr 6, 2026
0e6b3e8
updated import paths for demand components
elenya-grant Apr 6, 2026
2986dff
removed commodity_set_point as output
elenya-grant Apr 6, 2026
1f71c9d
Merge remote-tracking branch 'h2i_upstream/develop' into dispatch/con…
elenya-grant Apr 7, 2026
9672ecc
renamed demand files
elenya-grant Apr 7, 2026
7ad7b59
renamed demand classes and configs
elenya-grant Apr 7, 2026
9ace0ad
Merge branch 'develop' into dispatch/converter_ol_sync
kbrunik Apr 8, 2026
8444cdf
renamed demand component to be performance model instead of control s…
elenya-grant Apr 8, 2026
2093b81
moved output calculations to shared method in baseclass
elenya-grant Apr 8, 2026
1510bd2
Merge branch 'dispatch/converter_ol_sync' of github.com:elenya-grant/…
elenya-grant Apr 8, 2026
d116ad8
removed the word controller from docstrings
elenya-grant Apr 8, 2026
7c5b9e5
draft update to docs
elenya-grant Apr 8, 2026
1046419
removed system level calcs from storage and updated most tests
elenya-grant Apr 9, 2026
65dc07b
updated optimal controller tests
elenya-grant Apr 9, 2026
89a4ced
updated example 1 and 2
elenya-grant Apr 9, 2026
5032e41
updated examples 1, 2, and 12
elenya-grant Apr 10, 2026
24cb283
updated examples with storage but dont use storage as a commodity_str…
elenya-grant Apr 10, 2026
92d9854
updated examples with storage defined as a commodity_stream for a fin…
elenya-grant Apr 10, 2026
3001732
tried to fix doc page
elenya-grant Apr 10, 2026
572a020
fixed test failing in sql_to_csv because of additional outputs
elenya-grant Apr 10, 2026
2bd17d8
updated example 12 so tests pass
elenya-grant Apr 10, 2026
c71ba77
Merge branch 'develop' into storage/standalone_outputs
johnjasa Apr 10, 2026
7596e27
updated framework tests that used example 1
elenya-grant Apr 10, 2026
f47966d
Merge remote-tracking branch 'upstream/develop' into HEAD
kbrunik Apr 11, 2026
9c8b7c1
made demand an input only if using feedback control
elenya-grant Apr 13, 2026
90e56be
merged in develop
elenya-grant Apr 13, 2026
8988ae8
undid change for demand only input for feedback controllers
elenya-grant Apr 13, 2026
140c368
Merge remote-tracking branch 'origin/storage/standalone_outputs' into…
elenya-grant Apr 13, 2026
7e3b3f3
updated demand docs with figures
elenya-grant Apr 13, 2026
d9ad39e
added time_step_bounds to demand components
elenya-grant Apr 13, 2026
a0202a7
added small bit about demand component to controller_demostrations.md
elenya-grant Apr 13, 2026
8094ee8
updated plotting part of controller demo doc page
elenya-grant Apr 13, 2026
738173c
added test for example 23
elenya-grant Apr 13, 2026
eaa17e8
added example for different demand between storage and demand component
elenya-grant Apr 13, 2026
75fa5f5
added subtests for example 13
elenya-grant Apr 13, 2026
a01b5af
minor update to controller_demonstrations doc page to use EXAMPLE_DIR
elenya-grant Apr 13, 2026
5a510aa
added wind resource file for example 23
elenya-grant Apr 13, 2026
21082b7
added demo for the demand components using example 13
elenya-grant Apr 13, 2026
9ecd357
fixed demand_demo.md
elenya-grant Apr 13, 2026
6ebd865
made it so demand is only input to battery performance model if using…
elenya-grant Apr 13, 2026
ed710a5
typo fix in example 13 plant config
elenya-grant Apr 13, 2026
46116b6
Merge branch 'develop' into storage/standalone_outputs
johnjasa Apr 14, 2026
0c9c665
minor changes to docs and some logic based on feedback
elenya-grant Apr 14, 2026
6308329
Merge branch 'storage/standalone_outputs' of github.com:elenya-grant/…
elenya-grant Apr 14, 2026
6720139
added battery performance plots to demand demo
elenya-grant Apr 14, 2026
34f5a8c
added subtests for example and minor updates based on feedback
elenya-grant Apr 14, 2026
41a177b
added xdsm to demand_demo doc page
elenya-grant Apr 14, 2026
864b124
added standard_capacity_factor as output from storage
elenya-grant Apr 14, 2026
ff1b98c
minor updates to example 13 subtests
elenya-grant Apr 14, 2026
62347b5
make some subtests more loose because of floating point precision dif…
elenya-grant Apr 14, 2026
98047ec
added doc page for storage performance models
elenya-grant Apr 14, 2026
0704c24
added subtests for capacity factor calcs and minor update to docs
elenya-grant Apr 14, 2026
15e7573
minor update to example tests
elenya-grant Apr 14, 2026
d7694f3
docs
kbrunik Apr 15, 2026
ec95ba5
docs fix
kbrunik Apr 15, 2026
6254ee6
no api call but tests fail
kbrunik Apr 15, 2026
7a96ec6
updated example so using pre-downloaded resource data
elenya-grant Apr 15, 2026
231f1d9
updated changelog
elenya-grant Apr 15, 2026
5b8e4dc
updated doc page
elenya-grant Apr 15, 2026
4a228fa
added dt to doc eqn
elenya-grant Apr 15, 2026
226bc74
minor update to cf doc page
elenya-grant Apr 15, 2026
2329b36
added underscore t to numerator in doc page
elenya-grant Apr 15, 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 @@ -52,6 +52,7 @@
- The `DemandOpenLoopConverterController` has been renamed to `GenericDemandComponent`
- Modified CI setup so Windows is temporarily disabled and also so unit, regression, and integration tests are run in separate jobs to speed up testing and provide more information on test failures. [PR 668](https://github.com/NatLabRockies/H2Integrate/pull/668)
- Added infrastructure for running models with non-hourly time steps via a class attribute `_time_step_bounds` and sets new time step bounds of 5-minutes to 1-hour for the grid components. [PR 653](https://github.com/NatLabRockies/H2Integrate/pull/653) and [PR 671](https://github.com/NatLabRockies/H2Integrate/pull/671)
- Remove demand-related outputs from storage performance models and replace usage with demand components [PR 666](https://github.com/NatLabRockies/H2Integrate/pull/666)

## 0.7.2 [April 9, 2026]

Expand Down
9 changes: 6 additions & 3 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,22 @@ parts:
- file: technology_models/atb_costs_pv.md
- file: technology_models/atb_costs_wind.md
- file: technology_models/co2.md
- file: technology_models/simple_generic_storage.md
- file: technology_models/methanol.md
- file: technology_models/ammonia.md
- file: technology_models/pysam_battery.md
- file: technology_models/wind_plant_ard.md
- file: technology_models/geologic_hydrogen.md
- file: technology_models/grid
- file: technology_models/hydrogen_storage.md
- file: technology_models/h2_fuel_cell.md
- file: technology_models/h2_smr.md
- file: technology_models/iron_ewin.md
- file: technology_models/iron_mine.md
- file: technology_models/iron_dri.md
- file: technology_models/steel_eaf.md
- file: technology_models/storage_models_index.md
sections:
- file: technology_models/simple_generic_storage.md
- file: technology_models/pysam_battery.md
- file: technology_models/hydrogen_storage.md
- caption: Resource Models
chapters:
- file: resource/resource_index
Expand All @@ -72,6 +74,7 @@ parts:
- caption: Demand
chapters:
- file: demand/demand_components
- file: demand/demand_demo
- caption: Finance Models
chapters:
- file: finance_models/financial_analyses
Expand Down
1 change: 1 addition & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
storage
transporters
tools
demand
```
49 changes: 26 additions & 23 deletions docs/control/controller_demonstrations.md
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 was looking at the docs for this and I think it could make sense to update example 14 and the outputs in this demonstration to show how the demand to the h2_storage and the h2_load_demand can be different and how that impacts the analysis. I would also recommend updating the tech_config executable block because it doesn't include the h2_load_demand and I think that would be helpful to showcase.

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.

That's a good idea - I will work on that!

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.

I think that example 1 or 2 may be a better candidate. Those ones have a battery and we could set the battery demand profile to 10% of the electrolyzer rated capacity and then add/set an electricity component demand profile equal to the electrolyzer rated capacity. There is nothing that hydrogen is going to in example 14 which makes it hard to come up with a storage why the storage demand profile would be different than the demand component demand profile.

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.

I made a new example (example 13) and used that to make a demand_demo.md page in the demand docs folder.

Original file line number Diff line number Diff line change
Expand Up @@ -17,48 +17,51 @@ kernelspec:
from pathlib import Path
from matplotlib import pyplot as plt
from h2integrate.core.h2integrate_model import H2IntegrateModel
from h2integrate import EXAMPLE_DIR

```

## Hydrogen Dispatch

The following example is an expanded form of `examples/14_wind_hydrogen_dispatch`.

Here, we're highlighting the dispatch controller setup from
`examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml`. Please note some sections are removed
simply to highlight the controller sections
`examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml`. Please note some sections are removed simply to highlight the controller sections

```{literalinclude} ../../examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml
:language: yaml
:lineno-start: 52
:linenos: true
:lines: 52,53-54,57-58,59-71
```

We also include a demand technology to calculate how much demand is met, how much commodity is unused to meet the demand, and how much demand is remaining:

```{literalinclude} ../../examples/14_wind_hydrogen_dispatch/inputs/tech_config.yaml
:language: yaml
:lineno-start: 54
:lineno-start: 79
:linenos: true
:lines: 54,59-61,67-74
:lines: 79-86
```


Using the primary configuration, we can create, run, and postprocess an H2Integrate model.

```{code-cell} ipython3
# Create an H2Integrate model
model = H2IntegrateModel(Path("../../examples/14_wind_hydrogen_dispatch/inputs/h2i_wind_to_h2_storage.yaml"))
model = H2IntegrateModel(EXAMPLE_DIR/"14_wind_hydrogen_dispatch"/"inputs"/"h2i_wind_to_h2_storage.yaml")

# Run the model
model.run()
Comment thread
elenya-grant marked this conversation as resolved.
model.post_process()
```

Now, we can visualize the demand profiles over time.

```{code-cell} ipython3
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(8, 6), layout="tight")

start_hour = 0
end_hour = 200
total_time_steps = model.prob.get_val("h2_storage.SOC").size
demand_profile = [
model.technology_config["technologies"]["h2_storage"]["model_inputs"]["shared_parameters"][
"demand_profile"
]
* 1e-3
] * total_time_steps
start_hour = 800
end_hour = 1000
xvals = list(range(start_hour, end_hour))

ax1.plot(
Expand All @@ -74,41 +77,41 @@ ax2.plot(
)
ax2.plot(
xvals,
model.prob.get_val("h2_storage.unused_hydrogen_out", units="t/h")[start_hour:end_hour],
model.prob.get_val("h2_load_demand.unused_hydrogen_out", units="t/h")[start_hour:end_hour],
linestyle=":",
label="H$_2$ Unused (kg)",
)
ax2.plot(
xvals,
model.prob.get_val("h2_storage.unmet_hydrogen_demand_out", units="t/h")[start_hour:end_hour],
model.prob.get_val("h2_load_demand.unmet_hydrogen_demand_out", units="t/h")[start_hour:end_hour],
linestyle=":",
label="H$_2$ Unmet Demand (kg)",
)
ax2.plot(
xvals,
model.prob.get_val("h2_storage.hydrogen_out", units="t/h")[start_hour:end_hour],
model.prob.get_val("h2_load_demand.hydrogen_out", units="t/h")[start_hour:end_hour],
linestyle="-",
label="H$_2$ Delivered (kg)",
)
ax2.plot(
xvals,
demand_profile[start_hour:end_hour],
model.prob.get_val("h2_load_demand.hydrogen_demand", units="t/h")[start_hour:end_hour],
linestyle="--",
label="H$_2$ Demand (kg)",
)

ax1.set_ylabel("SOC (%)")
ax1.grid()
ax1.set_axisbelow(True)
ax1.set_xlim(0, 200)
ax1.set_ylim(0, 50)
ax1.set_xlim(start_hour, end_hour)
ax1.set_ylim(60, 100)

ax2.set_ylabel("H$_2$ Hourly (t)")
ax2.set_xlabel("Timestep (hr)")
ax2.grid()
ax2.set_axisbelow(True)
ax2.set_ylim(0, 20)
ax2.set_yticks(range(0, 21, 2))
ax2.set_ylim(0, 18)
ax2.set_yticks(range(0, 19, 2))

plt.legend(ncol=3)
fig.show()
Expand Down
31 changes: 25 additions & 6 deletions docs/demand/demand_components.md
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 these figures really help illustrate what the calculations are doing :) thank you!

Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
# Demand components

- [`GenericDemandComponent`](#generic-demand-component)
- [`FlexibleDemandComponent`](#flexible-demand-component)
# Demand Components

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 demand types:
1. Generic Demand Component — meets a fixed demand profile.
2. Flexible Demand Component — adjusts demand up or down within flexible bounds.
1. [`GenericDemandComponent`](#generic-demand-component) — meets a fixed demand profile.
2. [`FlexibleDemandComponent`](#flexible-demand-component) — adjusts demand up or down within flexible bounds.


(demand-component-inputs-and-outputs)=
## Demand component inputs and outputs
The inputs to the demand components are the `{commodity}_demand` profile and the `{commodity}_in` profile. The `{commodity}_in` profile is the initial commodity used to satisfy the demand. Suppose the `{commodity}_in` (pink) and `{commodity}_demand` (green) profiles look like whats shown below:

![](./figures/demand_inputs.png)

The demand components then compute the following output profiles:
- `unmet_{commodity}_demand_out`: Unmet demand (non-zero when supply < demand, otherwise 0.)
- `unused_{commodity}_out`: Unused commodity (non-zero when supply > demand, otherwise 0.)

![](./figures/demand_calcs.png)

- `commodity_out`: Delivered output (commodity supplied to demand sink)

![](./figures/demand_commodity_out.png)

The demand components also compute the following outputs:
- `capacity_factor`: the ratio of the demand that's been met to the full demand
- `rated_commodity_production`: the maximum value of the demand profile


(generic-demand-component)=
### Generic Demand Component
Expand Down
Loading
Loading