From cfb979a0d0f037a24b9d916b726805108386049b Mon Sep 17 00:00:00 2001 From: Martha Maria <53824825+eb5194@users.noreply.github.com> Date: Thu, 3 Dec 2020 15:17:16 +0100 Subject: [PATCH] Custom busmap for clustering (#193) * add option to use custom clustermaps from data folder * adapt default config to custom busmap * input file from Snakefile * adapt input description * add option to use custom clustermaps from data folder * adapt default config to custom busmap * input file from Snakefile * adapt input description * Snakefile: custom_busmap in cluster_network input is now csv * cluster_network: custom_busmap is now read as csv file, adaptions of description * simplify_network: adapt descriptions * configfiles: add cutom_clustermaps switch * unify clustarmap and busmap names * unify clustermap and busmap names * test/config: unify clustermap and busmap names * cluster_network: make clustering_for_n_clusters compatible with simplify_network * simplify_network: make compatible with changes in cluster_network.py * Update scripts/cluster_network.py * Update scripts/simplify_network.py * Update scripts/simplify_network.py * Update scripts/cluster_network.py * Update scripts/cluster_network.py * cluster_network: move custom_busmap flag to enable; simplify names * cluster_network: move custom_busmap flag to enable; simplify names * custom_busmap: add documentation * cluster_network: add default for custom_busmap for compatibility with old configs * cluster_network: add default for custom_busmap for compatibility with old configs Co-authored-by: martha.frysztacki Co-authored-by: Fabian Neumann --- Snakefile | 2 ++ config.default.yaml | 1 + config.tutorial.yaml | 1 + doc/configtables/toplevel.csv | 3 ++- doc/release_notes.rst | 7 +++++-- scripts/cluster_network.py | 25 +++++++++++++++++-------- scripts/simplify_network.py | 6 +++--- test/config.test1.yaml | 1 + 8 files changed, 32 insertions(+), 14 deletions(-) diff --git a/Snakefile b/Snakefile index 133f7843..6b92999e 100644 --- a/Snakefile +++ b/Snakefile @@ -244,6 +244,8 @@ rule cluster_network: regions_onshore="resources/regions_onshore_{network}_s{simpl}.geojson", regions_offshore="resources/regions_offshore_{network}_s{simpl}.geojson", busmap=ancient('resources/busmap_{network}_s{simpl}.csv'), + custom_busmap=("data/custom_busmap_{network}_s{simpl}_{clusters}.csv" + if config["enable"].get("custom_busmap", False) else []), tech_costs=COSTS output: network='networks/{network}_s{simpl}_{clusters}.nc', diff --git a/config.default.yaml b/config.default.yaml index 98f8ed67..0d299fe5 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -32,6 +32,7 @@ enable: retrieve_cutout: true build_natura_raster: false retrieve_natura_raster: true + custom_busmap: false electricity: voltages: [220., 300., 380.] diff --git a/config.tutorial.yaml b/config.tutorial.yaml index aed8693e..80b8c7a0 100755 --- a/config.tutorial.yaml +++ b/config.tutorial.yaml @@ -31,6 +31,7 @@ enable: retrieve_cutout: true build_natura_raster: false retrieve_natura_raster: true + custom_busmap: false electricity: voltages: [220., 300., 380.] diff --git a/doc/configtables/toplevel.csv b/doc/configtables/toplevel.csv index 7eb7dd61..4592161b 100644 --- a/doc/configtables/toplevel.csv +++ b/doc/configtables/toplevel.csv @@ -13,4 +13,5 @@ enable,,, -- build_cutout,bool,"{true, false}","Switch to enable the building of cutouts via the rule :mod:`build_cutout`." -- retrieve_cutout,bool,"{true, false}","Switch to enable the retrieval of cutouts from zenodo with :mod:`retrieve_cutout`." -- build_natura_raster,bool,"{true, false}","Switch to enable the creation of the raster ``natura.tiff`` via the rule :mod:`build_natura_raster`." --- retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`." \ No newline at end of file +-- retrieve_natura_raster,bool,"{true, false}","Switch to enable the retrieval of ``natura.tiff`` from zenodo with :mod:`retrieve_natura_raster`." +-- custom_busmap,bool,"{true, false}","Switch to enable the use of custom busmaps in rule :mod:`cluster_network`. If activated the rule looks for provided busmaps at ``data/custom_busmap_elec_s{simpl}_{clusters}.csv`` which should have the same format as ``resources/busmap_elec_s{simpl}_{clusters}.csv``, i.e. the index should contain the buses of ``networks/elec_s{simpl}.nc``." \ No newline at end of file diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 065310c6..bec532e6 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -42,6 +42,11 @@ Upcoming Release * The mappings for clustered lines and buses produced by the ``simplify_network`` and ``cluster_network`` rules changed from Hierarchical Data Format (.h5) to Comma-Separated Values format (.csv) (`#198 `_) +* Added an option to use custom busmaps in rule :mod:`cluster_network`. To use this feature set ``enable: custom_busmap: true``. + Then, the rule looks for custom busmaps at ``data/custom_busmap_elec_s{simpl}_{clusters}.csv``, + which should have the same format as ``resources/busmap_elec_s{simpl}_{clusters}.csv``. + i.e. the index should contain the buses of ``networks/elec_s{simpl}.nc`` (`#193 `_). + * Fixed a bug for storage units such that individual store and dispatch efficiencies are correctly taken account of rather than only their round-trip efficiencies. In the cost database (``data/costs.csv``) the efficiency of battery inverters should be stated as per discharge/charge rather than per roundtrip (`#202 _). @@ -51,8 +56,6 @@ Upcoming Release * Electricity consumption data is now directly retrieved from the `OPSD website `_ using the rule ``build_load_data``. The user can decide whether to take the ENTSOE power statistics data (defaul) or the ENTSOE transparency data. - - PyPSA-Eur 0.2.0 (8th June 2020) ================================== diff --git a/scripts/cluster_network.py b/scripts/cluster_network.py index 620d8868..3fbe2d68 100644 --- a/scripts/cluster_network.py +++ b/scripts/cluster_network.py @@ -33,8 +33,9 @@ Inputs - ``resources/regions_onshore_{network}_s{simpl}.geojson``: confer :ref:`simplify` - ``resources/regions_offshore_{network}_s{simpl}.geojson``: confer :ref:`simplify` -- ``resources/clustermaps_{network}_s{simpl}.h5``: confer :ref:`simplify` +- ``resources/busmap_{network}_s{simpl}.csv``: confer :ref:`simplify` - ``networks/{network}_s{simpl}.nc``: confer :ref:`simplify` +- ``data/custom_busmap_{network}_s{simpl}_{clusters}.csv``: optional input Outputs ------- @@ -49,7 +50,8 @@ Outputs .. image:: ../img/regions_offshore_elec_s_X.png :scale: 33 % -- ``resources/clustermaps_{network}_s{simpl}_{clusters}.h5``: Mapping of buses and lines from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; has keys ['/busmap', '/busmap_s', '/linemap', '/linemap_negative', '/linemap_positive'] +- ``resources/busmap_{network}_s{simpl}_{clusters}.csv``: Mapping of buses from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; +- ``resources/linemap_{network}_s{simpl}_{clusters}.csv``: Mapping of lines from ``networks/elec_s{simpl}.nc`` to ``networks/elec_s{simpl}_{clusters}.nc``; - ``networks/{network}_s{simpl}_{clusters}.nc``: .. image:: ../img/elec_s_X.png @@ -267,10 +269,9 @@ def plot_busmap_for_n_clusters(n, n_clusters=50): n.plot(bus_colors=busmap.map(dict(zip(cs, cr)))) del cs, cr -def clustering_for_n_clusters(n, n_clusters, aggregate_carriers=None, - line_length_factor=1.25, potential_mode='simple', - solver_name="cbc", algorithm="kmeans", - extended_link_costs=0, focus_weights=None): +def clustering_for_n_clusters(n, n_clusters, custom_busmap=False, aggregate_carriers=None, + line_length_factor=1.25, potential_mode='simple', solver_name="cbc", + algorithm="kmeans", extended_link_costs=0, focus_weights=None): if potential_mode == 'simple': p_nom_max_strategy = np.sum @@ -280,8 +281,15 @@ def clustering_for_n_clusters(n, n_clusters, aggregate_carriers=None, raise AttributeError("potential_mode should be one of 'simple' or 'conservative', " "but is '{}'".format(potential_mode)) + if custom_busmap: + busmap = pd.read_csv(snakemake.input.custom_busmap, index_col=0, squeeze=True) + busmap.index = busmap.index.astype(str) + logger.info(f"Imported custom busmap from {snakemake.input.custom_busmap}") + else: + busmap = busmap_for_n_clusters(n, n_clusters, solver_name, focus_weights, algorithm) + clustering = get_clustering_from_busmap( - n, busmap_for_n_clusters(n, n_clusters, solver_name, focus_weights, algorithm), + n, busmap, bus_strategies=dict(country=_make_consense("Bus", "country")), aggregate_generators_weighted=True, aggregate_generators_carriers=aggregate_carriers, @@ -363,7 +371,8 @@ if __name__ == "__main__": return v potential_mode = consense(pd.Series([snakemake.config['renewable'][tech]['potential'] for tech in renewable_carriers])) - clustering = clustering_for_n_clusters(n, n_clusters, aggregate_carriers, + custom_busmap = snakemake.config["enable"].get("custom_busmap", False) + clustering = clustering_for_n_clusters(n, n_clusters, custom_busmap, aggregate_carriers, line_length_factor=line_length_factor, potential_mode=potential_mode, solver_name=snakemake.config['solving']['solver']['name'], diff --git a/scripts/simplify_network.py b/scripts/simplify_network.py index d030a283..53631005 100644 --- a/scripts/simplify_network.py +++ b/scripts/simplify_network.py @@ -62,7 +62,7 @@ Outputs .. image:: ../img/regions_offshore_elec_s .png :scale: 33 % -- ``resources/clustermaps_{network}_s{simpl}.h5``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec_s{simpl}.nc``; has keys ['/busmap_s'] +- ``resources/busmap_{network}_s{simpl}.csv``: Mapping of buses from ``networks/elec.nc`` to ``networks/elec_s{simpl}.nc``; - ``networks/{network}_s{simpl}.nc``: .. image:: ../img/elec_s.png @@ -315,7 +315,7 @@ def remove_stubs(n): return n, busmap def cluster(n, n_clusters): - logger.info("Clustering to {} buses".format(n_clusters)) + logger.info(f"Clustering to {n_clusters} buses") renewable_carriers = pd.Index([tech for tech in n.generators.carrier.unique() @@ -329,7 +329,7 @@ def cluster(n, n_clusters): potential_mode = (consense(pd.Series([snakemake.config['renewable'][tech]['potential'] for tech in renewable_carriers])) if len(renewable_carriers) > 0 else 'conservative') - clustering = clustering_for_n_clusters(n, n_clusters, potential_mode=potential_mode, + clustering = clustering_for_n_clusters(n, n_clusters, custom_busmap=False, potential_mode=potential_mode, solver_name=snakemake.config['solving']['solver']['name']) return clustering.network, clustering.busmap diff --git a/test/config.test1.yaml b/test/config.test1.yaml index e8f17758..0ea71ca4 100755 --- a/test/config.test1.yaml +++ b/test/config.test1.yaml @@ -31,6 +31,7 @@ enable: retrieve_cutout: true build_natura_raster: false retrieve_natura_raster: true + custom_busmap: false electricity: voltages: [220., 300., 380.]