How the model works
← Back to the chartA look under the hood of the v2 engine that drives projection-mode Sankey charts: for the US and, since mid-2026, every individual state. Everything visible in this app (the lever sliders, the projection trajectories, the per-source tooltips) is computed from primitives shown here. Pick a section to explore.
Generation sources
Nine sources the engine knows about: Solar, Nuclear, Hydro, Wind, Geothermal, Natural Gas, Coal, Biomass, Petroleum. Each carries ~25 researched values (capex, fixed O&M, LCOE, capacity factor, retirement schedule, learning rate, …) drawn from NREL ATB, EIA, EPA eGRID, and peer-reviewed literature.
Submodels
Structural sub-models that override the simple per-sector monolithic growth math for high-leverage end-uses:
- Vehicle stock (D30 LDV + D31 HDV): Bass-style S-curve adoption with fuel-price and policy feedbacks; LDV curve recalibrated to an AEO-vs-IEA midpoint (D85).
- Storage & VRE integration (D86–D90): storage deployed on an LCOS-vs-value crossing, driven by a duck curve keyed on VRE capacity penetration; a vintage capacity stock (real EIA-860 install-year cohorts) tracks installed solar/wind GW.
- Hydrogen (D32, opt-in): SMR vs electrolysis production split + sector demand.
- Data centers (D37): logistic growth ramp into Industrial grid demand.
- Building heating (D102): residential + commercial heat-pump stock turnover; carves space/water-heating fossil out of the CES and electrifies it at heat-pump COP (1 Q fossil → ~0.31 Q grid). On by default; reduces economy-wide CO₂. Per-state climate brackets since D107 (cold-cluster COP derate MN/WI/MI, warm-cluster FL/TX ahead of the US adoption curve).
Feedback loops
The engine isn't a one-pass calculation. A handful of loops connect per-year outputs back into next-year inputs:
- Wright's-law learning (D20/D34): cumulative deployment shrinks per-source LCOE.
- Demand elasticity (D26): sector demand responds to retail price changes.
- Battery-cost feedback (D27): cheaper batteries decay the VRE integration penalty.
- Duck-curve coupling (D86/D87): VRE capacity penetration deepens the duck curve, which both deflates VRE market value and raises storage's arbitrage value (LCOS-vs-value).
- Dispatch shift (D49): natural gas absorbs coal-retirement gaps via existing-fleet utilization.
- Fuel-price elasticity (D68): gasoline prices advance the BEV S-curve t_mid.
One loop the engine deliberately compresses: real-world interconnection queues, permitting, and equipment supply chains are modeled as per-source build caps (D44). The uncompressed version (who actually gates each step and why) is its own explainer: Gridlock: why it's hard to plug in.
Levers & scenarios
56 user-exposed levers across four families: generation (Wright's-law rates, retirement schedules, build caps), demand (per-sector growth + elasticity), T&D (per-ISO markups), and submodels (storage, vehicle stock, data centers, hydrogen, building heating). Defaults come from research; overrides land in a "basket" the engine consumes per-projection-year.
Wondering why even aggressive lever pulls move the projection gradually? The build caps are doing that on purpose: they compress the real world's interconnection queues, siting fights, and equipment backlogs into per-source annual limits. Gridlock: why it's hard to plug in maps that friction in full, including a "Speed it up" mode whose model-runnable fixes stage these very levers.
Policy layer
A closed-enum mechanism resolver (D29) that turns time-bounded
policies (federal IRA tax credits, state RPS targets, carbon
prices) into engine input adjustments. 15 mechanisms across
carrots (production credit, consumer credit, capex offset, …),
sticks (regulatory capex, excise tax, …), quantity constraints
(mandate floors, electrification mandates), and supply-chain
deployment capacity. Jurisdiction-aware: federal policies fire in
every region; a state policy fires at full strength in its own
state and in states that formally adopted it (§177-style
adoption_states), and at a researched spillover share
in the US aggregate.
State-scale modeling
Every state has a full historical Sankey (EIA SEDS, 2018–2023) and a committed default projection to 2050: the same engine, re-grounded per state:
- Scaling & overrides (D62/D63): US-aggregate submodel parameters scale by each state's load share; 31 states additionally declare researched overrides (tiered coal/nuclear retirement, BEV adoption (CA buys BEVs at ~3× the US rate), data-center concentration, build caps).
- Weather & resources (D91): solar capacity factors follow each state's irradiance, wind follows its NREL wind class, and VRE cost scales inversely (AZ solar is cheap, WY wind is strong).
- Climate-bracket heating (D107): the heat-pump submodel runs cold-climate physics in MN/WI/MI (seasonal COP ~2.3, adoption lagging the US curve) and warm-climate in FL/TX (COP ~3.5, heat pumps long dominant). The two extremes bracket the US average, so unlisted states inherit credible defaults.
- Interstate electricity trade (D105): each state carries its real net position from SEDS: importers like CA show ~0.39 Q flowing in through Net Electricity Imports; exporters like PA/WY/WV send their surplus out through an Electricity Exports node (previously it was misrendered as waste heat). Traded electricity is counted with its embedded generation losses (the SEDS state-accounting convention), so the energy burden follows the buyer. Projections hold each state's position at its baseline, supply-clamped; a price-responsive exchange model was built and backtested but did not beat the baseline-anchored approach on 2018–2023, so it ships lever-gated off (D106).
A "sum of 50 states" aggregation mode exists as a validation harness (each state projected independently, every flow summed), comparing it against the direct US projection is how per-state parameters earn their keep.
Research values & quality tiers
Every quantitative model input is wrapped in a ResearchedValue
(D21) with a quality tier:
- L1 primary (EIA / NREL / EPA / IRENA).
- L2 L1-derived (computed from primary inputs).
- L3 peer-reviewed literature.
- L4 transcribed unverified, triggers the "less-verified source" callout.
One accounting convention worth knowing: every CO₂ number in the app uses the fossil-combustion basis, biomass counts zero, matching the EIA / Ember / LLNL biogenic-zero convention every published benchmark uses. The physical biomass stack CO₂ (~93 Mt per Quad burned) is never hidden: it appears as an explicit "biogenic (not counted)" line on the impact card and the biomass tooltips (D104).
Decision history
The engine's architecture grew through 100+ numbered design
decisions (D1–D107 to date) recorded in DECISIONS.md.
Each entry carries the call, the rationale, and a review-by date
so the design stays auditable, including the negative results
(mechanisms built, backtested, and deliberately kept off).