From planning portfolios to feasible hourly operation
The model asks whether a capacity portfolio can meet demand hour by hour while respecting transmission, renewable availability, thermal limits and stored-water dynamics.
Operational dispatch
Build and assess a full-year PyPSA network: congestion, dispatch, spill, curtailment, prices and adequacy.
Integrated modelling
Designed to receive long-term investment choices and demand trajectories from BC-Nexus, with spatial VRE inputs from RESource.
Not a production grid model
A research model with imputed electrical parameters and ongoing baseline calibration. Results require scenario-specific validation.
Integrated framework
Install, configure, prepare, build
src/ layout. uv is the documented runner; dependencies include PyPSA, atlite, GeoPandas, pandas, xarray and plotting libraries.1 · Create the environment
uv sync
2 · Review configuration
| File | Responsibility |
|---|---|
config/params.yaml | Scenario, snapshots, cutout resolution and stage parameters. |
config/data.yaml | Input, output and remote-data paths only. |
config/base_network.yaml | Power factor, frequency, line reactance and transformer assumptions. |
config/coders.yaml | CODERS API tables, schemas and aliases. |
3 · Run staged preparation
uv run python -m workflow.scripts.prepare_base_network uv run python -m workflow.scripts.prepare_assets uv run python -m workflow.scripts.prepare_profiles
4 · Build the network
uv run python -m workflow.scripts.build_model
workflow/run_pypsa_bc.py remains available as a legacy all-in-one path, but it hard-codes the 2021 load input and calls older preparation functions. Prefer the staged entry points while the workflow migration is completed.Expected outputs
Prepared network tables are written under data/processed_data/network/; technology profiles under data/processed_data/; PyPSA component dictionaries under data/pypsa_data/; and the default assembled network to results/pypsa/prepared_net.nc.
What is represented
| Dimension | Current representation |
|---|---|
| Objective | PyPSA economic dispatch / linear network optimization assembled by build_model.py. |
| Time | Default: hourly, 1 Jan–31 Dec 2021; 8,760 snapshots. ERA5 cutout uses UTC bounds corresponding to Pacific time. |
| Space | Detailed CODERS substation/line network prepared first; the build can aggregate BC assets to GADM level-2 regional districts and add external trade nodes. |
| Supply | Reservoir and run-of-river hydro, wind, solar, thermal, cogeneration, optional nuclear expansion, imports and a feasibility/backstop supply. |
| Demand | BC Hydro balancing-authority profile spatially disaggregated with CEEI residential and commercial/SMI weights. |
| Expansion | Committed and candidate VRE/nuclear sites can be added; transmission is typically fixed unless explicitly overridden. |
| Unit commitment | Disabled by default (UC: false); thermal dispatch is therefore normally continuous rather than integer commitment. |
Primary components
Bus
Electrical voltage nodes, aggregated regional buses, external trade nodes, fuel buses and water buses.
Line / transformer
AC transmission and voltage conversion from the prepared CODERS topology.
Generator / Link / Store
Electric generation, multi-port energy conversion and reservoir energy storage.
CODERS topology, enriched for PyPSA
The reusable network package prepares lines, derives buses from line endpoints, and inserts transformers where a substation spans voltage levels. The build stage can remap component buses to administrative regions and collapse parallel inter-regional corridors.
| Parameter | Current rule | Confidence |
|---|---|---|
| Line capacity | CODERS summer MVA where present; otherwise MW converted with configured power factor. The assumption log currently records ttc_summer as proxy. | Verify |
| Reactance | Voltage-to-reactance lookup in base_network.yaml. | Literature check |
| Resistance / conductor | Closest ampacity match to the custom Chapter 13 line table. | Imputed |
| Shunt capacitance | 8.85 nF/km. | Assumed |
| Transformer | Generic 2,000 MVA type; 10% short-circuit voltage, 0.3% resistance and configured tap range. | Placeholder |
Water is routed explicitly through cascades
Reservoir hydro is represented with water buses, Stores and Links rather than a single PyPSA StorageUnit. This supports upstream/downstream cascade routing, turbine conversion, reservoir energy and spill.
Generator on water bus
inflow and routing junction
release / spill link
MWh-water, cyclic option
stored-water node
turbine discharge link
Hydro data contract
Static physics—reservoir storage, discharge and cascade order—is separated from volatile CODERS fleet attributes. A versioned static inventory is joined to each CODERS release, then converted to the legacy cascade schema consumed by create_hydro_assets. GRanD/GDW and Water Use Plan data can replace frozen legacy values as they are verified.
A reproducible path from sources to network
| Source | Use | Key handling |
|---|---|---|
| CODERS | Generators, existing hydro, lines, substations | Central alias/required-column layer in config/coders.yaml; local table cache. |
| ERA5 + atlite | Wind, solar, runoff and cutout | 0.25° default grid; 2021 weather year. |
| HydroBASINS | Catchments and hydro routing | North American and Arctic level-12 basin files. |
| GADM | Province and regional-district polygons | Level 1 scope; level 2 spatial aggregation/disaggregation. |
| BC Hydro / CEEI | Hourly demand and sectoral spatial weights | Profile repair, normalization and annual-total scaling. |
| NRCan CWTD / Global Wind Atlas | Turbine inventory, model crosswalk, siting checks | Public fetch plus turbine power-curve dictionary. |
How information and energy move
Model assembly
Bus · Line · Transformer
Generator · Link · Store
Load · availability · inflow
capacity · trade · EV
8,760 snapshots
dispatch · flow · price · storage
Demand disaggregation
p_set by busWhat must be known before interpreting results
| Area | Assumption / default | Consequence |
|---|---|---|
| Temporal | Single 2021 weather/load shape; hourly resolution. | No inter-annual hydrology or climate variability unless rerun with another cutout. |
| Reservoir initial state | Current assumption log records e_initial = 0; cyclic storage may be enabled in built networks. | Cold-start and cyclic conditions must be checked on the actual network file. |
| Hydro head | Dam height may proxy rated head; turbine efficiency converts volume to energy. | Reservoir energy capacity inherits head uncertainty. |
| Transmission security | Older model documentation cites an 85% loading/security threshold; verify whether s_max_pu is set in each built network. | Do not assume N-1 security solely from nominal ratings. |
| Thermal operations | Unit commitment off; gas-grid flag off by default. | No binary start/stop physics in the default run. |
| Load | Regional CEEI weights applied to a provincial hourly shape. | Local temporal diversity is not independently observed. |
| Backstop | Feasibility generation may be added. | Any dispatch indicates unmet capacity or deliverability, not real generation. |
The machine-maintained source of record is docs/ASSUMPTION_REPORT.md, populated through pypsa_bc.reporting.assumptions. Scenario runs should append assumptions rather than overwrite the register.
Use evidence, not polish, as the release gate
| Capability | Status | Required check |
|---|---|---|
| Package/config split | Implemented | Confirm all scripts now read migrated parameters from the correct YAML. |
| Base network preparation | Implemented | Resolve CODERS transmission data gaps and validate imputed electrical values. |
| Hydro static/volatile pipeline | Implemented | Increase independently verified reservoir inventory and record capacity convention. |
| 2021 baseline | Target | Reproduce annual/monthly load, hydro generation, trade and observed operational ranges. |
| Threshold feedback | Adaptation needed | Read spill from Links and state of charge from Stores, not StorageUnits. |
Minimum run QA
Energy balance
Annual load, generation, imports/exports, losses and storage change reconcile.
Adequacy
Backstop dispatch is zero for a feasible baseline; investigate every non-zero hour.
Hydro
Seasonal storage, spill, inflow calibration and generation match credible ranges.
Network
Line loading, congestion duration and nodal prices are plausible and traceable.
VRE
Capacity factors, profiles, asset locations and curtailment are checked for anomalies.
Provenance
Input versions, scenario controls and modelling assumptions are recorded.
A reading path for users and contributors
Network components, optimization and time-series conventions. atlite documentation ↗
ERA5 cutouts and renewable resource conversion. Existing model report
Scenario-oriented network, dispatch and post-processing interpretation. Hydro data pipeline
Static inventory, CODERS refresh, legacy adapter and capacity convention. CODERS schema runbook
Aliases, required fields, version changes and provenance. Baseline calibration roadmap
2021 targets, data needs and post-solve checks. Package structure
Separation of reusable package, orchestration and configuration. Hydro cascade data contract
Region-agnostic turbine, reservoir, flow and policy tables.
Where to look when extending the model
| Area | Location | Responsibility |
|---|---|---|
| Configuration | src/pypsa_bc/attributes_parser.py | Single access point for the four YAML configuration files. |
| Network | src/pypsa_bc/network/ | Bus, line and transformer sanitation, enrichment and tables. |
| Hydrology | src/pypsa_bc/hydro.py | Basins, cutouts, inflows, calibration, RoR and cascade calculations. |
| Data clients | src/pypsa_bc/data/ | CODERS, downloads, hydro inventory builders and adapters. |
| Reporting | src/pypsa_bc/reporting/ | Logging, assumptions and data provenance. |
| Workflow | workflow/scripts/ | Preparation, formatting and network assembly entry points. |
| Visualization | src/pypsa_bc/vis/ | Plot helpers and the Dash results viewer. |
src/pypsa_bc; workflow modules should orchestrate configuration, package calls and outputs. Paths belong in data.yaml, physical assumptions in base_network.yaml, and run controls in params.yaml.