85c356297a
* Add logging to logfiles to all snakemake workflow scripts. * Fix missing quotation marks in Snakefile. * Apply suggestions from code review Co-Authored-By: Fabian Neumann <fabian.neumann@outlook.de> * Apply suggestions from code review Co-Authored-By: Fabian Neumann <fabian.neumann@outlook.de> * doc: fix _ec_ filenames in docs * Allow logging message format to be specified in config.yaml. * Add logging for Snakemake rule 'retrieve_databundle '. * Add limited logging to STDERR only for retrieve_*.py scripts. * Import progressbar module only on demand. * Fix logging to file and enable concurrent printing to STDERR for most scripts. * Add new 'logging_format' option to Travis CI test config.yaml. * Add missing parenthesis (bug fix) and cross-os compatible paths. * Fix typos in messages. * Use correct log files for logging (bug fix). * doc: fix line references * config: logging_format in all configs * doc: add doc for logging_format * environment: update to powerplantmatching 0.4.3 * doc: update line references for tutorial.rst * Change logging configuration scheme for config.yaml. * Add helper function for doing basic logging configuration. * Add logpath for prepare_links_p_nom rule. * Outsource basic logging configuration for all scripts to _helper submodule. * Update documentation for changed config.yaml structure. Instead of 'logging_level' and 'logging_format', now 'logging' with subcategories is used. * _helpers: Change configure_logging signature.
141 lines
4.9 KiB
Python
141 lines
4.9 KiB
Python
# coding: utf-8
|
|
"""
|
|
Retrieves conventional powerplant capacities and locations from `powerplantmatching <https://github.com/FRESNA/powerplantmatching>`_, assigns these to buses and creates a ``.csv`` file. It is possible to amend the powerplant database with custom entries provided in ``data/custom_powerplants.csv``.
|
|
|
|
Relevant Settings
|
|
-----------------
|
|
|
|
.. code:: yaml
|
|
|
|
electricity:
|
|
powerplants_filter:
|
|
custom_powerplants:
|
|
|
|
.. seealso::
|
|
Documentation of the configuration file ``config.yaml`` at
|
|
:ref:`electricity`
|
|
|
|
Inputs
|
|
------
|
|
|
|
- ``networks/base.nc``: confer :ref:`base`.
|
|
- ``data/custom_powerplants.csv``: custom powerplants in the same format as `powerplantmatching <https://github.com/FRESNA/powerplantmatching>`_ provides
|
|
|
|
Outputs
|
|
-------
|
|
|
|
- ``resource/powerplants.csv``: A list of conventional power plants (i.e. neither wind nor solar) with fields for name, fuel type, technology, country, capacity in MW, duration, commissioning year, retrofit year, latitude, longitude, and dam information as documented in the `powerplantmatching README <https://github.com/FRESNA/powerplantmatching/blob/master/README.md>`_; additionally it includes information on the closest substation/bus in ``networks/base.nc``.
|
|
|
|
.. image:: ../img/powerplantmatching.png
|
|
:scale: 30 %
|
|
|
|
**Source:** `powerplantmatching on GitHub <https://github.com/FRESNA/powerplantmatching>`_
|
|
|
|
Description
|
|
-----------
|
|
|
|
The configuration options ``electricity: powerplants_filter`` and ``electricity: custom_powerplants`` can be used to control whether data should be retrieved from the original powerplants database or from custom amendmends. These specify `pandas.query <https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.query.html>`_ commands.
|
|
|
|
1. Adding all powerplants from custom:
|
|
|
|
.. code:: yaml
|
|
|
|
powerplants_filter: false
|
|
custom_powerplants: true
|
|
|
|
2. Replacing powerplants in e.g. Germany by custom data:
|
|
|
|
.. code:: yaml
|
|
|
|
powerplants_filter: Country not in ['Germany']
|
|
custom_powerplants: true
|
|
|
|
or
|
|
|
|
.. code:: yaml
|
|
|
|
powerplants_filter: Country not in ['Germany']
|
|
custom_powerplants: Country in ['Germany']
|
|
|
|
|
|
3. Adding additional built year constraints:
|
|
|
|
.. code:: yaml
|
|
|
|
powerplants_filter: Country not in ['Germany'] and YearCommissioned <= 2015
|
|
custom_powerplants: YearCommissioned <= 2015
|
|
|
|
"""
|
|
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
from _helpers import configure_logging
|
|
|
|
from scipy.spatial import cKDTree as KDTree
|
|
|
|
import pypsa
|
|
import powerplantmatching as pm
|
|
import pandas as pd
|
|
|
|
def add_custom_powerplants(ppl):
|
|
custom_ppl_query = snakemake.config['electricity']['custom_powerplants']
|
|
if not custom_ppl_query:
|
|
return ppl
|
|
add_ppls = pd.read_csv(snakemake.input.custom_powerplants, index_col=0)
|
|
if isinstance(custom_ppl_query, str):
|
|
add_ppls.query(add_ppls, inplace=True)
|
|
return ppl.append(add_ppls, sort=False)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
if 'snakemake' not in globals():
|
|
from vresutils.snakemake import MockSnakemake, Dict
|
|
|
|
snakemake = MockSnakemake(
|
|
input=Dict(base_network='networks/base.nc',
|
|
custom_powerplants='data/custom_powerplants.csv'),
|
|
output=['resources/powerplants.csv']
|
|
)
|
|
|
|
configure_logging(snakemake)
|
|
|
|
n = pypsa.Network(snakemake.input.base_network)
|
|
countries = n.buses.country.unique()
|
|
|
|
ppl = (pm.powerplants(from_url=True)
|
|
.powerplant.fill_missing_decommyears()
|
|
.powerplant.convert_country_to_alpha2()
|
|
.query('Fueltype not in ["Solar", "Wind"] and Country in @countries')
|
|
.replace({'Technology': {'Steam Turbine': 'OCGT'}})
|
|
.assign(Fueltype=lambda df: (
|
|
df.Fueltype
|
|
.where(df.Fueltype != 'Natural Gas',
|
|
df.Technology.replace('Steam Turbine',
|
|
'OCGT').fillna('OCGT')))))
|
|
|
|
ppl_query = snakemake.config['electricity']['powerplants_filter']
|
|
if isinstance(ppl_query, str):
|
|
ppl.query(ppl_query, inplace=True)
|
|
|
|
ppl = add_custom_powerplants(ppl) # add carriers from own powerplant files
|
|
|
|
cntries_without_ppl = [c for c in countries if c not in ppl.Country.unique()]
|
|
|
|
for c in countries:
|
|
substation_i = n.buses.query('substation_lv and country == @c').index
|
|
kdtree = KDTree(n.buses.loc[substation_i, ['x','y']].values)
|
|
ppl_i = ppl.query('Country == @c').index
|
|
|
|
ppl.loc[ppl_i, 'bus'] = substation_i[kdtree.query(ppl.loc[ppl_i,
|
|
['lon','lat']].values)[1]]
|
|
|
|
if cntries_without_ppl:
|
|
logging.warning(f"No powerplants known in: {', '.join(cntries_without_ppl)}")
|
|
|
|
bus_null_b = ppl["bus"].isnull()
|
|
if bus_null_b.any():
|
|
logging.warning(f"Couldn't find close bus for {bus_null_b.sum()} powerplants")
|
|
|
|
ppl.to_csv(snakemake.output[0])
|