What should be built? Capacity expansion with representative periods, validated
Plan on a few weeks, then test the plan on every hour of two weather years
Five ways to choose the weeks, each plan solved under a 200 kt CO₂ cap and then re-run on every hour
| Representative weeks | Estimated cost a year | Estimate error | Unserved, 2025 | Unserved, 2024 | CO₂, 2025 |
|---|---|---|---|---|---|
| 4 typical weeks | $125.9M | −5.5% | 879 MWh | 2,343 MWh | 218 kt |
| 4 typical + 3 extreme weeks | $129.3M | −3.0% | 108 MWh | 589 MWh | 217 kt |
| 8 typical weeks | $127.6M | −4.2% | 750 MWh | 2,559 MWh | 210 kt |
| 8 typical + 3 extreme weeks | $130.9M | −1.8% | 17 MWh | 395 MWh | 209 kt |
| 12 typical + 3 extreme weeks | $131.7M | −1.2% | 0 | 40 MWh | 210 kt |
Estimate error: the weeks' cost against the full-year optimum: $133.2M, an LP with 43,807 columns solved on all 8,760 hours. kt: thousand tonnes. Unserved: demand the plan's plants cannot meet when the plan is re-run hour by hour.
With JavaScript on, you solve these plans yourself in the browser, check them on both years and try three rules for a battery between weeks, with storage energy at $20 per kWh: an illustrative what-if, not a forecast or a sourced cost.
Model: lesson 13's planning LP with EIA and NREL costs, dated in its sources; constant within the year.
Price year: 2025 dollars throughout; NREL's 2024 battery costs are converted with BEA's GDP implicit price deflator (×1.0263). The battery is under 1% of the seven-week plan's yearly cost.
Weather and demand: real 2025 and 2024 hourly shapes of the Southwest Power Pool grid (EIA-930).
2024: scaled to 2025's yearly demand energy and capacity factors; 29 February left out.
Precomputed: the 11- and 15-week plans and the full-year optimum, labelled where shown. Prairie Town: fictional.
Storage what-if (step 8): battery energy at $20 per kWh instead of the sourced $247 in 2025 dollars (lesson 13): an illustrative what-if, not a forecast or a sourced cost.
About 45 guided minutes in ten steps. Solver: HiGHS (open source), loaded on your first solve (about 3.5 MB, once).
Build it in Python · notebook lab, about 60 minutes, then 120 minutes of practice
The same model in scipy.optimize.linprog(method="highs") with sparse matrices. assert cells check your own plans against the reference: the weeks, LP sizes, sizes built, costs, CO₂ and unserved energy.
Hours short and the largest shortfall are printed, not asserted: other schedules of the same cost can spread a shortfall 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 (the full-year optimum takes seconds to a minute), then try the six practice tasks at the end.
What you just did, as diagrams
- Capacity expansion LP
- Decides what to build (seven sizes, paid every year) and how to run it in every modelled hour, at least yearly cost.
- Weights
- Each modelled hour's running cost counts as many times as the hours of the year it stands for.
- Extreme weeks
- Peak demand, peak net load and least wind, kept as they were: they cut the full-year shortfall from 879 to 108 MWh.
- Link between weeks
- A calendar chain of 52 battery levels; without it, each week may start full for free.
- Validation
- Re-run the plan on every hour of 2025 and of 2024; report unserved energy, CO₂ against the cap and the estimate error.
Go deeper · ModelerThe expansion LP in algebra
For each representative week \(p\) and hour \(h = 1 \dots 168\), at least yearly cost:
\[\min \; \sum_i f_i K_i + \sum_p w_p \sum_{h} \big(r_\mathrm{cc}\, g_{p,h} + r_\mathrm{pk}\, q_{p,h}\big)\]
\[ \begin{aligned} a^{w}_{p,h} K_\mathrm{wind} + a^{s}_{p,h} K_\mathrm{solar} + 0.911\,K_\mathrm{nuc} + g_{p,h} + q_{p,h} + d_{p,h} - c_{p,h} &\ge D_{p,h} && \text{(demand)}\\ g_{p,h} \le K_\mathrm{cc}, \quad q_{p,h} \le K_\mathrm{pk}, \quad c_{p,h} + d_{p,h} &\le K_\mathrm{bp} && \text{(sizes)}\\ s_{p,h} = s_{p,h-1} + 0.85\,c_{p,h} - d_{p,h}, \quad s_{p,0} = 0, \quad \ell_p \le s_{p,h} &\le u_p && \text{(battery, within week } p)\\ S_{i+1} = S_i + s_{k(i),168}, \quad S_{53} = S_1, \quad 0 \le S_i + \ell_{k(i)}, \quad S_i + u_{k(i)} &\le K_\mathrm{be} && \text{(link, calendar weeks } i)\\ \textstyle\sum_p w_p \sum_h \big(0.329\, g_{p,h} + 0.484\, q_{p,h}\big) &\le \text{cap} && \text{(CO}_2\text{)}\\ K_i,\ g_{p,h},\ q_{p,h},\ c_{p,h},\ d_{p,h},\ S_i \ge 0, \quad s_{p,h} \text{ free in sign}, \quad \ell_p \le 0 &\le u_p && \text{(domains)} \end{aligned} \]
Each step \(h\) lasts one hour, so a power held for one step (MW) is that much energy (MWh). Sizes, outputs, charge and discharge cannot be negative; the level \(s_{p,h}\) is measured from the week’s start, so it can be.
The weight of a modelled hour: \(w_p = n_p \times 8{,}760 / 8{,}736\), where \(n_p\) is the number of calendar weeks it stands for and the factor spreads the 24 hours of 31 December. A typical week standing for 13 weeks: \(13 \times 8{,}760 / 8{,}736 = 13.04\); an extreme week stands for itself.
| Symbol | Meaning | Unit |
|---|---|---|
| \(K_i\) | size built; battery power \(K_\mathrm{bp}\) | MW |
| \(K_\mathrm{be}\) | battery energy | MWh |
| \(f_i\) | yearly cost of one unit built: capital recovery at 4% real plus fixed O&M; for a plant with constant output, also its fuel and variable O&M | $ per MW-year (per MWh-year) |
| \(w_p\) | hours of the year one modelled hour of week \(p\) stands for | h |
| \(g, q\) | gas combined-cycle and peaker output | MW |
| \(r_\mathrm{cc}, r_\mathrm{pk}\) | running cost of gas | $/MWh |
| \(c, d\) | battery charge and discharge | MW |
| \(s_{p,h}\) | battery level in week \(p\), relative to the week’s start (may be negative) | MWh |
| \(\ell_p, u_p\) | the lowest and highest \(s_{p,h}\) in week \(p\) | MWh |
| \(S_i\) | battery level at the start of calendar week \(i\); \(k(i)\) is the representative week standing for it | MWh |
| \(a^w, a^s\) | wind and solar output per MW built | MW per MW |
| \(0.911\) | nuclear output per MW built, the same in every hour | MW per MW |
| \(D\) | demand | MW |
| \(0.329, 0.484\) | CO₂ per MWh of gas output (heat rate × 0.05291 t per MMBtu): operating CO₂ only | t/MWh |
Cyclic storage replaces the link with \(s_{p,168} = 0\) for every \(p\); no link drops the equation \(S_{i+1} = S_i + s_{k(i),168}\), so each week may start at any level. Fixing every \(K_i\) and running all 8,760 hours as one week, with unserved demand allowed at an illustrative $10,000 per MWh, gives the full-year check.
Go deeper · ModelerHow the weeks are chosen
- Typical weeks. Each season’s weeks (by the month of the week’s middle) are grouped by k-medoids, \(k\) = 1, 2 or 3. Each group’s medoid is the real week closest, hour by hour, to the others in its group: squared differences of demand (as a share of the peak), wind and solar output per MW.
- Scaling. A typical week is scaled so that its group keeps its demand energy, and its wind and solar energy to within 0.5%: no hour may exceed a plant’s size.
- Extremes. The week of the year’s peak demand, of the peak of demand minus reference wind and solar output, and of the least wind are kept as they were, each standing for itself.
- Same weather year. Demand, wind and sun come from the same hours, so their correlation survives.
- Outages are left out of the planning LP: they belong to an adequacy study.
Go deeper · ModelerError measures, and what they cannot tell you
| Measure | Definition | 4 + 3 extreme weeks |
|---|---|---|
| Estimate error | (weeks’ optimal cost) ÷ (full-year optimal cost) − 1 | −3.0% |
| Cost gap | (plan’s spending on the full year) ÷ (weeks’ estimate) − 1. Spending: plants and fuel; no shortage penalty, no cap in the re-run | +1.1% on 2025 |
| Unserved energy | demand not met when the plan is re-run, in MWh, hours and largest shortfall | 108 MWh in 8 hours |
| CO₂ against the cap | the plan’s full-year CO₂ ÷ cap − 1 | +8.7% on 2025 (217 kt), +7.3% on 2024 (215 kt) |
- Four typical weeks leave 879 MWh unserved in 53 hours of 2025, spread over 12 weeks.
- The second year. At 2025’s yearly demand energy, 2024’s demand peaks at 462 MW, against 450 MW in 2025.
- What they cannot tell you. Even the plan optimal on all of 2025 leaves 235 MWh in 18 hours of 2024 unserved.
- Adequacy is judged over many weather years with plant outages, in a Monte Carlo study (A5), by measures such as the loss-of-load expectation (LOLE).
- LOLE is the expected number of days a year with a shortage of any size or length. One criterion is 0.1 days a year, “1 day in 10 years” (PJM Manual 20A, §1.3, June 2026): an expectation, not a promise of one outage a decade.
Go deeperWhat this model leaves out
- Plant outages and reserve margins: adequacy studies treat them over many weather years (A5).
- Start-up costs and minimum run times: on/off decisions make a mixed-integer program (M2).
- Transmission and regions: the town is one bus with no imports.
- Several years of investment, retirements and residual value: a pathway model (M13).
- Uncertainty when building: here the weather is known when the sizes are chosen (M8 chooses them before it is known).
- Costs that change with time: every cost is constant within the year modelled.
Modeler's note: R5 turns these checks into a verification and validation plan, and the Modeler checkpoint CK-M asks you to formulate, solve and verify a model you have not seen.
Check yourself
Myth or fact? “More representative weeks always give a better plan.”
- Myth
- Fact
Answer
Myth. 8 typical weeks leave 750 MWh unserved on the full year; 4 typical + 3 extreme leave 108 MWh. Which weeks matters as much as how many.
Myth or fact? “Leaving out the battery's link between weeks costs only a little accuracy.”
- Myth
- Fact
Answer
Myth. In an illustrative what-if with storage energy at $20 per kWh (not a forecast or a sourced cost):
- the plan with no link builds 2,685 MWh of battery;
- re-run on the full year, it emits 247 kt against a 200 kt cap;
- each week could start charged, for free.
Myth or fact? “A plan that serves every hour of one full year is adequate.”
- Myth
- Fact
Answer
Myth. The plan optimized on all 8,760 hours of 2025 is short in 18 hours of 2024. Adequacy needs plant outages and many weather years.
The seven weeks estimate $129.28M a year; the full-year optimum costs $133.25M. What is the estimate error, as this lesson defines it?
- −3.0%
- +3.1%
- 0.970
- −$3.97M
Answer
−3.0%: 129.28 ÷ 133.25 − 1 = −0.030, with the reference in the denominator. +3.1% reverses the comparison: the full-year optimum is 3.1% above the estimate (133.25 ÷ 129.28 − 1). 0.970 is the ratio before subtracting 1, and −$3.96M is the gap in dollars.
Numbers, sources and what’s next
Numbers to remember
| Number | What it means | Source |
|---|---|---|
| 8,760 h | A year without 29 February. 2024 had 8,784; this lesson leaves its 29 February out. | The calendar |
| 8,760 ÷ 8,736 | 52 weeks hold 8,736 hours; the weights spread the 24 hours of 31 December. | This lesson's model |
| −3.0% | The seven weeks' estimate against the full-year optimum, at 200 kt. | This lesson's model (illustrative town) |
| 0.1 days a year | A loss-of-load expectation criterion, “1 day in 10 years”: expected shortage days, not a promise of one outage a decade. | PJM Manual 20A, §1.2–1.3 (rev. 3, effective 24 June 2026) |
| 52 levels | The calendar chain that carries the battery's charge from week to week. | Kotzur et al. (2018) |
Next
In the real world
Open planning models offer the same choices. GenX's standard storage balance makes each representative period end where it starts; its long-duration storage option links the periods through the calendar, as in this lesson.
Sources and further reading
- Kotzur, L., Markewitz, P., Robinius, M. and Stolten, D. (2018). Time series aggregation for energy system design: Modeling seasonal storage. Applied Energy 213, 123–135.
- Hoffmann, M., Kotzur, L., Stolten, D. and Robinius, M. (2020). A Review on Time Series Aggregation Methods for Energy System Models. Energies 13(3), 641.
- GenX. Long duration storage: the standard storage balance and the inter-period link (documentation, accessed 3 Nov 2026).
- EIA. Hourly Electric Grid Monitor (Form EIA-930): the Southwest Power Pool data for 2025 and 2024 (six-month files, accessed 3 Nov 2026).
- Costs: EIA's Annual Energy Outlook 2026 assumptions (2025 dollars) and NREL's battery cost projections (2024 dollars, converted to 2025 dollars with BEA's GDP implicit price deflator), as listed in lesson 13.
- PJM, Resource Adequacy Planning (2026). PJM Manual 20A: Resource Adequacy Analysis, revision 3, effective 24 June 2026: §1.2 defines the loss-of-load expectation in days per year, §1.3 sets the criterion of 1 day in 10 years, or 0.1 days per year (p. 8; accessed 3 Nov 2026).
- HiGHS. Documentation of the open-source solver used in the page and, through SciPy, in the notebook.
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.