Metadata-Version: 2.5
Name: cerf
Version: 2.5.0
Summary: An open-source geospatial Python package for assessing and analyzing future electricity technology capacity expansion feasibility.
Project-URL: Repository, https://github.com/IMMM-SFA/cerf
Project-URL: Documentation, https://immm-sfa.github.io/cerf
Author-email: Chris Vernon <chris.vernon@pnnl.gov>, Kendall Mongird <kendall.mongird@pnnl.gov>, Nino Zuljevic <nino.zuljevic@pnnl.gov>
Maintainer-email: Chris Vernon <chris.vernon@pnnl.gov>, Kendall Mongird <kendall.mongird@pnnl.gov>
License: Copyright 2021 Battelle Memorial Institute
        
        Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
        
        1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
        
        2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License-File: LICENSE
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Requires-Dist: geopandas>=0.9.0
Requires-Dist: joblib>=1.0.1
Requires-Dist: matplotlib>=3.3.3
Requires-Dist: numpy>=1.19.4
Requires-Dist: pandas>=1.1.4
Requires-Dist: pyyaml>=5.4.1
Requires-Dist: rasterio>=1.2.3
Requires-Dist: requests>=2.25.1
Requires-Dist: scipy>=1.12
Requires-Dist: shapely>=2.0
Provides-Extra: deploy
Requires-Dist: twine>=4.0.1; extra == 'deploy'
Provides-Extra: docs
Requires-Dist: build>=0.5.1; extra == 'docs'
Requires-Dist: furo>=2024.1.29; extra == 'docs'
Requires-Dist: sphinx-copybutton>=0.5.2; extra == 'docs'
Requires-Dist: sphinx-design>=0.5.0; extra == 'docs'
Requires-Dist: sphinx>=7.2; extra == 'docs'
Provides-Extra: test
Requires-Dist: pytest-cov>=2.12.1; extra == 'test'
Requires-Dist: pytest>=6.0; extra == 'test'
Requires-Dist: ruff>=0.4; extra == 'test'
Description-Content-Type: text/markdown

[![build](https://github.com/IMMM-SFA/cerf/actions/workflows/build.yml/badge.svg)](https://github.com/IMMM-SFA/cerf/actions/workflows/build.yml)
[![DOI](https://zenodo.org/badge/115649750.svg)](https://zenodo.org/badge/latestdoi/115649750)
[![status](https://joss.theoj.org/papers/28fee3407bbbef020fb4bb19bd451407/status.svg)](https://joss.theoj.org/papers/28fee3407bbbef020fb4bb19bd451407)

# 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](#purpose)
- [Installation](#installation)
- [Package data](#package-data)
- [Quick start](#quick-start)
- [How it works](#how-it-works)
- [Documentation](#documentation)
- [Development](#development)
- [Contributing](#contributing)
- [How to cite](#how-to-cite)
- [License](#license)

## 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).

```bash
pip install cerf
```

To install the latest development version from a checkout:

```bash
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):

```python
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:

```python
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:

```python
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:

```python
# 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](https://immm-sfa.github.io/cerf/user_guide.html#cerf-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](https://immm-sfa.github.io/cerf/user_guide.html#fundamental-equations-and-concepts).

## Documentation

- [Getting Started](https://immm-sfa.github.io/cerf/getting_started.html) - installation, package data, Python and
  dependency versions.
- [User Guide](https://immm-sfa.github.io/cerf/user_guide.html) - concepts, equations, configuration file reference,
  and the quickstarter.
- [API Reference](https://immm-sfa.github.io/cerf/cerf.html) - every public function and class.
- [Release Notes](https://immm-sfa.github.io/cerf/release_notes.html) - 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:

```bash
# 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:

```bash
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](https://immm-sfa.github.io/cerf/contributing.html) 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`.
