Multi-Scenario Architecture¶
This page explains how PowerGenome's scenario management system works internally. For step-by-step instructions on setting up scenarios, see Run Multi-Scenario Studies.
The problem scenarios solve¶
A single capacity expansion study typically involves multiple assumptions about uncertain inputs — technology costs, fuel prices, demand growth, policy stringency. Rather than running PowerGenome once per assumption set by hand, the scenario system lets you define a matrix of cases and process them in a single invocation.
Two types of variation¶
PowerGenome distinguishes between two kinds of parameter variation:
1. Planning-year variation (year-keyed values)¶
When a parameter naturally varies over time — e.g., capital costs fall as technology matures — you encode this directly in the settings using a year-keyed dictionary:
No scenario definitions CSV is needed. PowerGenome resolves these automatically for each planning year. See Year-Keyed Values for details.
2. Case variation (scenario management)¶
When you want to compare alternative futures — e.g., low vs. high gas price, with vs. without a carbon tax — you define cases in a CSV file and describe parameter swaps in settings_management:
# settings_management.yml
settings_management:
all_years:
gas_price:
low:
fuel_scenarios:
naturalgas: low_price
high:
fuel_scenarios:
naturalgas: high_price
The scenario matrix¶
The scenario definitions CSV defines the full set of runs. Each row is one (case, year) pair:
| Column | Description |
|---|---|
case_id |
Unique identifier for a scenario run |
year |
Planning year — must match a period end year from model_periods |
| (other columns) | Dimension names that correspond to settings_management keys |
Every case_id must have one row per model year. For a model with 3 years and 4 cases, the CSV has 12 rows.
How settings are constructed for each case¶
For each (case_id, year) pair PowerGenome:
- Starts from the base settings loaded from the settings folder
- Applies year-keyed resolution — any parameter that is a year-keyed dict is resolved to its value for this planning year
- Applies
all_yearsswaps — entries insettings_management.all_yearsare applied to every year - Applies year-specific swaps — entries in
settings_management.<year>are then applied - Within each year block, dimension columns from the scenario CSV row are matched to sub-keys, and the corresponding parameter dict is deep-merged into settings
The result is an independent, fully resolved settings dictionary for that specific run. Each case's settings do not affect any other case.
Deep merge behavior¶
Parameter swap dictionaries are deep-merged. This means nested structures like resource_modifiers or new_gen_not_available are updated key-by-key rather than replaced wholesale:
# Base settings
resource_modifiers:
UtilityPV_Class1_Moderate:
capex_mw: 1.0
# Scenario swap: solar_cost = low
resource_modifiers:
UtilityPV_Class1_Moderate:
capex_mw: 0.8 # overrides only capex_mw; other keys are preserved
However, lists are replaced entirely — not merged. If a swap sets new_resources to a new list, the base new_resources list is discarded.
The all_cases selector¶
Within a year block, all_cases applies to every run regardless of case dimension values:
settings_management:
2040:
all_cases:
carbon_tax: 75 # Applied to every 2040 run
tech_cost:
low:
atb_cost_case: Advanced
This is useful for policy parameters that change year-over-year but don't vary across scenarios.
Output folder structure¶
Each (case_id, year) pair writes to its own folder:
results/
└── <case_id>/
└── Inputs/
└── Inputs_p<period_number>/
├── system/
│ ├── Demand_data.csv
│ ├── Fuels_data.csv
│ └── Network.csv
├── resources/
│ └── ...
├── policies/
│ └── ...
└── powergenome_case_settings.yml
Inputs_p1 corresponds to the first planning period, Inputs_p2 to the second, and so on. The powergenome_case_settings.yml file records the exact resolved settings used for that run — useful for debugging or reproducing results.
Running without scenario definitions¶
If scenario_definitions_fn is absent from settings, PowerGenome creates one implicit "case" called Inputs for each period end year in model_periods. This is equivalent to a scenario CSV with one row per year:
Year-keyed values in settings are still resolved per year.
Related documentation¶
- Run Multi-Scenario Studies: Step-by-step instructions
- Scenario Management Settings: Complete parameter reference
- Year-Keyed Values: Per-year parameter resolution
- Data Pipeline Flow: How scenario settings flow through the pipeline