Skip to content

Repository files navigation

build DOI status

cerf

Capacity Expansion Regional Feasibility model - an open-source geospatial Python package for evaluating and analyzing the feasibility of future electricity technology capacity expansion plans.

cerf takes a scenario-driven expansion plan (for example, the number of new power plants of each technology required per region and year from a parent energy-economy model such as GCAM) and sites each plant on a 1 km grid in the least-cost feasible location. Cost is expressed as Net Locational Cost (NLC): the cost of interconnecting to the electricity transmission network or gas pipeline network, minus the plant's Net Operational Value (NOV) given the local locational marginal price and technology-specific operating costs. Technologies compete for each grid cell; suitability rasters remove land that cannot be built on, and each sited plant excludes a buffer around itself so that service-area congestion emerges from the siting itself.

Full documentation: https://immm-sfa.github.io/cerf

Contents

Purpose

cerf was created to:

  • Evaluate the feasibility of a future scenario-driven electricity technology capacity expansion plan as generated by a parent model.
  • Site power plants in the least-cost configuration when considering regional economics and on-the-ground barriers to siting.
  • Assist planners and modelers of alternate future realizations of the electricity system in understanding how siting costs and service-area congestion may respond under certain stressors.

Installation

cerf requires Python 3.10 or newer and is tested on Python 3.10, 3.11 and 3.12 (Linux in CI; macOS and Windows are expected to work).

pip install cerf

To install the latest development version from a checkout:

git clone https://github.com/IMMM-SFA/cerf.git
cd cerf
pip install -e ".[test]"

Runtime dependencies are declared in pyproject.toml (NumPy, SciPy, pandas, rasterio, GeoPandas, Shapely 2, joblib, PyYAML, requests, matplotlib). A matching conda environment is provided in environment.yml.

Package data

The package itself is kept small; the sample data needed to run the examples (CONUS region and LMP-zone rasters, technology suitability rasters, HIFLD substations, EIA gas pipelines, illustrative hourly LMPs, and sample configuration files for 2010, 2030 and 2050) is hosted on Zenodo and installed on demand (about 195 MB):

import cerf

cerf.install_package_data()

By default the data is installed into the package's data directory. Pass data_dir="/some/path" to install elsewhere; the configuration file must then point at those paths. The download retries automatically on Zenodo rate limits and transient errors.

Quick start

Run the packaged 2010 sample for all CONUS regions and plot the result:

import cerf

# sample configuration for 2010; edit the returned dictionary to customise the run
config = cerf.load_sample_config(2010)

# site every technology in every region; returns one row per sited plant
result_df = cerf.run(config_dict=config, write_output=False)

# map of sited plants coloured by technology
cerf.plot_siting(result_df)

Runs can be made reproducible (settings: randomize: False, seed_value: 0) and chained across years by passing the previous year's output as initialize_site_data, so that plants sited earlier - and their buffers - are respected until they retire:

result_2010 = cerf.run(config_dict=cerf.load_sample_config(2010), write_output=False)
result_2030 = cerf.run(config_dict=cerf.load_sample_config(2030), write_output=False,
                       initialize_site_data=result_2010)

Regions are independent, so they can be processed in parallel with any joblib backend:

# threads share the staged arrays in memory (fast, deterministic when seeded)
result_df = cerf.run(config_dict=config, write_output=False, method="threading", n_jobs=4)

# separate processes; each region is cropped to its bounding box before dispatch
result_df = cerf.run(config_dict=config, write_output=False, method="loky", n_jobs=-1)

n_jobs=-1 uses all processors (-2 all but one), following joblib. A step-by-step version of this example is in the Quickstarter and the accompanying notebook in notebooks/.

How it works

For each run year cerf:

  1. Stages the grid: reads the region raster once, builds per-technology arrays of locational marginal price, interconnection cost (Euclidean distance to the nearest substation of sufficient voltage or gas pipeline, in the raster's own units, times a cost per km and an annuity factor), generation, operating cost and NOV, and combines the technology suitability rasters (honouring each raster's nodata value).
  2. Competes technologies region by region: in each iteration the cheapest available cell for each technology is found, the overall cheapest technology wins that cell, its buffer is removed from every technology's search space, and the process repeats until every technology's expansion target is met or no suitable land remains.
  3. Aggregates the sited plants into a single data frame (optionally written to CSV) with 29 attributes per plant, including coordinates, grid index, LMP zone, costs, and retirement year.

The equations for NOV, interconnection cost and the levelization factors are documented in the User Guide.

Documentation

  • Getting Started - installation, package data, Python and dependency versions.
  • User Guide - concepts, equations, configuration file reference, and the quickstarter.
  • API Reference - every public function and class.
  • Release Notes - changes in each version.

Development

Clone the repository and install in editable mode with the test extras (see above). The test suite has two tiers:

# fast unit suite; runs on a fresh checkout without the package data (about one second)
pytest -m "not package_data"

# full suite including end-to-end runs on the sample data; fails instead of skipping if the data is missing
pytest --require-package-data

# lint (configuration in pyproject.toml)
ruff check cerf tests benchmark

Every change that touches the siting path must leave the seeded reference run unchanged:

python benchmark/run_reference.py --compare

This runs the 2010 sample for all regions with a fixed seed and compares every sited plant against benchmark/reference/cerf_sited_2010_conus_seed0.csv; it also reports staging and competition timings. Continuous integration runs the lint, the fast suite, and the full suite plus the regression check on Python 3.10-3.12.

A Dockerfile is provided that builds an image with cerf and its package data pre-installed for use on MSD-LIVE.

Contributing

Whether you find a typo in the documentation, find a bug, or want to develop functionality that you think will make cerf more robust, you are welcome to contribute. Please open an issue to discuss substantial changes first, and see the Contribution Guidelines for the workflow, coding conventions and how pull requests are reviewed.

How to cite

If you use cerf in your work, please cite the software paper:

Vernon, C.R., Rice, J.S., Zuljevic, N., Mongird, K., Nelson, K., Iyer, G., Voisin, N., Binsted, M. (2021). cerf: A Python package to evaluate the feasibility and costs of power plant siting for alternative futures. Journal of Open Source Software, 6(65), 3601. https://doi.org/10.21105/joss.03601

A CITATION.cff file is included for citation managers, and each release is archived on Zenodo (DOI badge above).

License

cerf is released under the BSD 2-Clause License; see LICENSE. The software is provided as is without warranty; see DISCLAIMER.

About

The Capacity Expansion Regional Feasibility (CERF) model

Resources

Stars

17 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages