Storage and coupled carriers: modelling power, hydrogen and heat together
Add a battery, an electrolyzer, a hydrogen tank and a heat store to one plant, and find where coupling pays
One wind plant, two weeks of 2025: what each step of coupling saves against separate systems
| Configuration | Winter week (9–15 Dec) | Summer week (14–20 Jul) |
|---|---|---|
| + electrolyzer and tank | $61.3k | $30.5k |
| + heat pump and heat store | $82.3k | $33.2k |
| + waste heat from the electrolyzer | $83.6k | $35.6k |
Separate systems: the plant with its battery, every kg of hydrogen trucked in, all heat from a gas boiler. Each saving is a difference of optimal weekly costs, the same for every best plan.
LP relaxation: in these runs the electrolyzer may run below its 15% minimum load.
With JavaScript on, you add each device yourself and solve the plant's linear program in the browser.
Illustrative plant and prices. 100 MW of wind behind a 50 MW connection, trading at Prairie Town's cost of one more MWh ($0, $40 or $100, lesson 9). Trucked hydrogen $2.50 per kg; boiler heat $15 per MWh.
Real shapes. Wind and the town's demand follow the Southwest Power Pool's 2025 hours (EIA-930); wind is scaled to 33.8%, the U.S. wind fleet's 2025 capacity factor (EIA). Heat demand follows the town's shape to a 15 MW winter peak.
Efficiencies. Battery round trip 0.8259 (DOE 2022 assessment); alkaline minimum load 15% (IRENA 2020); heat pump 3 MWh of heat per MWh (DOE). Electrolyzer 57 kWh per kg: DOE's PEM figure, illustrative here, inside IRENA's 50–78 for alkaline systems.
About 40 guided minutes in eight steps. Solver: HiGHS (open source), loaded on your first solve (about 3.5 MB, once).
Build it in Python · notebook lab, about 45 minutes, then 90 minutes of practice
The same plant in scipy.optimize.linprog(method="highs"), and its exact on/off version with scipy.optimize.milp. assert cells check your costs, savings and prices against the lesson's reference block.
Schedules are printed, not asserted: other plans of the same cost can run the devices differently.
- Download the notebook and the four data files into one folder (in Colab, upload them with the folder icon).
- Open it in Google Colab (File → Upload notebook) or locally with Python 3, NumPy and SciPy 1.9 or later.
- Run all cells (a few seconds), then try the practice tasks at the end.
Notebook (.ipynb) Lesson data Town Year 2025 Capacity factors
What you just did, as diagrams
- One LP, three carriers
- A balance row each hour for power, hydrogen and heat: 2,520 columns and 1,176 rows for a week.
- Storage links the hours
- Battery, tank and heat store each carry a level from hour to hour and end the week where they start.
- Conversion couples the balances
- Coupling: the electrolyzer turns 1 MWh into about 17.5 kg (1,000 ÷ 57); the heat pump turns it into 3 MWh of heat.
- Where coupling pays
- The value of coupling: heat coupling saves $21.0k in the winter week, $2.7k in summer. Conversion and storage need cheap power and heat demand to connect; summer has little heat demand.
- Coupled prices
- When the heat pump sets heat's price, heat is worth power's price ÷ 3: $40 ÷ 3 = $13.33 per MWh of heat.
- LP relaxation
- These costs, savings and prices let the electrolyzer run below its 15% minimum; the exact on/off cost is shown only for the winter hydrogen case.
Go deeper · ModelerThe plant's LP in algebra
For each hour \(t = 0 \dots 167\) (MW over the hour is MWh), with \(t-1\) read cyclically so every level ends the week where it starts. Names as in the code and the notebook:
\[\min \sum_t \Big( p_t\,(\mathit{imp}_t - \mathit{exp}_t) + 2.50\,\mathit{tr}_t + 15\,\mathit{boil}_t \Big)\]
\[ \begin{aligned} \mathit{exp}_t + \mathit{bc}_t + \mathit{ez}_t + \mathit{hp}_t + \mathit{cur}_t - \mathit{imp}_t - \mathit{bd}_t &= w_t && \text{(power)}\\ k\,\mathit{ez}_t + \mathit{tr}_t + L_{t-1} - L_t &= 150 && \text{(hydrogen)}\\ \mathit{COP}\,\mathit{hp}_t + \mathit{rec}_t - \mathit{hin}_t + \mathit{hout}_t + \mathit{boil}_t &= H_t && \text{(heat)}\\ \mathit{COP}\,\mathit{hp}_t + \mathit{rec}_t - \mathit{hin}_t + \mathit{hout}_t &\le 12 && \text{(network)}\\ s_t = s_{t-1} + \eta\,\mathit{bc}_t - \mathit{bd}_t, \quad Q_t &= (1-\lambda)\,Q_{t-1} + \mathit{hin}_t - \mathit{hout}_t && \text{(levels)}\\ 400 \le L_t \le 4{,}000, \quad \mathit{rec}_t \le 0.2\,\mathit{ez}_t, \quad 0 \le \mathit{ez}_t &\le 20 && \text{(limits)} \end{aligned} \]
| Symbol | Meaning | Unit |
|---|---|---|
| \(\mathit{exp}_t\), \(\mathit{imp}_t\) | sold to and bought from the grid, each at most 50 | MW |
| \(p_t\) | Prairie Town’s price | $/MWh |
| \(w_t\), \(\mathit{cur}_t\) | wind, and wind curtailed | MW |
| \(\mathit{bc}_t\), \(\mathit{bd}_t\), \(s_t\) | battery charge, discharge (at most 20) and state of charge (at most 80) | MW, MWh |
| \(\mathit{ez}_t\) | electrolyzer power | MW |
| \(L_t\), \(\mathit{tr}_t\) | hydrogen in the tank, hydrogen trucked in | kg |
| \(\mathit{hp}_t\) | heat pump power (at most 5) | MW |
| \(\mathit{rec}_t\), \(\mathit{boil}_t\), \(H_t\) | heat recovered from the electrolyzer, from the boiler, and demanded | MW of heat |
| \(\mathit{hin}_t\), \(\mathit{hout}_t\), \(Q_t\) | heat store charge, discharge and level (at most 60) | MW, MWh |
| \(k\) | \(1000 / 57\), about 17.54: kg of hydrogen per MWh | kg/MWh |
| \(\eta\) | the battery’s round trip, 0.8259 (DOE’s 82.59%) | share |
| \(\mathit{COP}\) | the heat pump’s coefficient of performance, 3 | MWh of heat per MWh |
| \(\lambda\) | the heat store’s loss, \(1 - 0.98^{1/24}\) (2% a day) | per hour |
- Duals. The power row’s dual, with its sign flipped, is power’s marginal value in that hour; the hydrogen and heat rows’ duals are the marginal costs of one more kg and one more MWh of heat.
- Under this model’s assumptions: fixed sizes, the modelled prices, and the LP relaxation of the minimum load.
- Unique or not. Step 7 offers only hours where each dual is unique; the test checks that raising and lowering the hour’s demand by 0.01 changes the cost at the same rate.
- Size. 2,520 columns and 1,176 rows; HiGHS solves it in tens of milliseconds.
Go deeper · ModelerPart-load limits: two LPs and a mixed-integer program
- The exact rule. Each hour the electrolyzer is on, between 15% and 100% of its size, or off: \(3\,z_t \le \mathit{ez}_t \le 20\,z_t\) with \(z_t \in \{0, 1\}\), a mixed-integer program (M2).
- Two LP stand-ins. Drop the binary and allow any load (a relaxation, never dearer), or force \(z_t = 1\) (always on, never cheaper).
- This winter week: relaxed −$178.6k, exact −$178.6k, forced on −$172.7k. The exact cost lies between the two, as it must.
- No prices from the MILP. Its duals do not exist in the ordinary sense (§9.2); prices come from an LP with the on/off choices fixed.
Go deeperWhat this model leaves out
- Sizes are given: choosing them is capacity expansion (M3), with a year of weeks linked as M3 links them.
- Investment costs: the week's cost counts only buying, selling, trucks and the boiler.
- Perfect foresight: the solver knows the whole week's wind and prices in advance.
- Price-taking: the plant's sales do not move Prairie Town's price.
- Electrochemistry, heat-network hydraulics and the tank's pressure: devices enter as efficiencies and limits.
Check yourself
Myth or fact? “A heat pump on a wind plant saves about the same in every season.”
- Myth
- Fact
Answer
Myth. Here heat coupling saves $21.0k in the winter week and $2.7k in the summer week: in summer there is little heat to make.
Both runs are LP relaxations that let the electrolyzer run below its 15% minimum.
Myth or fact? “Forcing an electrolyzer to stay on above its minimum load is the safe way to write the limit in an LP, and it costs nothing.”
- Myth
- Fact
Answer
Myth. It keeps the plan feasible but costs $6.0k more this winter week than the exact on/off model, which may switch the unit off.
The electrolyzer uses 57 kWh per kg. What coefficient links the power and hydrogen balances, in kg per MWh?
- 57
- 17.5
- 0.057
- 1.75
Answer
17.5: 1,000 ÷ 57 = 17.54 kg per MWh, about 17.5.
57 is kWh per kg, 0.057 is MWh per kg (the inverse), and 1.75 drops a factor of ten.
Numbers, sources and what’s next
Numbers to remember
| Number | What it means | Source |
|---|---|---|
| 17.5 kg per MWh | Hydrogen from 1 MWh at 57 kWh per kg (1,000 ÷ 57 = 17.54, rounded): the coefficient that couples the two balances. | DOE Hydrogen Program Record 24005 · 20 May 2024 |
| 15% to 100% | The load range of an alkaline electrolyzer; PEM units go down to 5%. | IRENA, Green Hydrogen Cost Reduction, Table 6 · December 2020 |
| up to 3 times | The heat a heat pump gives against the electricity it uses. | DOE, Energy Saver Guide, p. 16 · July 2022 |
Next
In the real world
Compared with wind and a battery alone, adding an electrolyzer reduced total system cost by about 7%, and using hydrogen as the storage medium for fuel cells reduced it by about 26%.
Holds when: one planned West Texas wind farm, ERCOT prices, costs from 2020 to 2023. Leaves out: final federal hydrogen credit rules.
Try it yourself
Optional, about 30 minutes; needs Python on your computer (lesson B2).
- Run
examples/configurations.py: four configurations of wind, battery, electrolyzer, tank and fuel cell on a synthetic site, sized and run hour by hour. - Predict first, then switch the electrolyzer to a constant rate (
ModelOptions(electrolyzer_operation="constant")): which sizes change, and how much does flexibility save?
reopt-hydrogen-framework: public example repository · MIT licence · synthetic data.
Sources and further reading
- DOE Hydrogen Program (2024). Record 24005: Clean Hydrogen Production Cost Scenarios with PEM Electrolyzer Technology, Table 1.
- IRENA (2020). Green Hydrogen Cost Reduction, Table 6.
- Viswanathan, V. et al. (2022). 2022 Grid Energy Storage Technology Cost and Performance Assessment. DOE Energy Storage Grand Challenge, Table 4.4.
- DOE (2022). Energy Saver Guide, p. 16.
- Cutler, D. et al. (2017). REopt: A Platform for Energy System Integration and Optimization. NREL/TP-7A40-70022 (a family of site models like this one).
- Li et al. (2024). Towards sustainable integration: techno-economic analysis and future perspectives of Co-located wind and hydrogen energy systems. Journal of Mechanical Design 146(2), 020903.
- Earlier lessons: lesson 9 (state of charge), M1 (duals as marginal values), A8 (storage duration), A16 (hydrogen chains).
Spotted an error, or stuck? Write to hlli@ksu.edu. Corrections are made in place and dated here.
Text licensed CC BY 4.0, code MIT: teachers and students may reuse and adapt it, with credit to Honglin Li.