Merge pull request #415 from p-glaum/exclude_carrier_clustering

add feature: aggregate carrier exclusion
This commit is contained in:
Fabian Neumann 2022-09-22 12:52:34 +02:00 committed by GitHub
commit 899acb38da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 27 additions and 7 deletions

View File

@ -256,9 +256,11 @@ clustering:
to_substations: false # network is simplified to nodes with positive or negative power injection (i.e. substations or offwind connections) to_substations: false # network is simplified to nodes with positive or negative power injection (i.e. substations or offwind connections)
algorithm: kmeans # choose from: [hac, kmeans] algorithm: kmeans # choose from: [hac, kmeans]
feature: solar+onwind-time # only for hac. choose from: [solar+onwind-time, solar+onwind-cap, solar-time, solar-cap, solar+offwind-cap] etc. feature: solar+onwind-time # only for hac. choose from: [solar+onwind-time, solar+onwind-cap, solar-time, solar-cap, solar+offwind-cap] etc.
exclude_carriers: []
cluster_network: cluster_network:
algorithm: kmeans algorithm: kmeans
feature: solar+onwind-time feature: solar+onwind-time
exclude_carriers: []
aggregation_strategies: aggregation_strategies:
generators: generators:
p_nom_max: sum # use "min" for more conservative assumptions p_nom_max: sum # use "min" for more conservative assumptions

View File

@ -187,9 +187,11 @@ clustering:
to_substations: false # network is simplified to nodes with positive or negative power injection (i.e. substations or offwind connections) to_substations: false # network is simplified to nodes with positive or negative power injection (i.e. substations or offwind connections)
algorithm: kmeans # choose from: [hac, kmeans] algorithm: kmeans # choose from: [hac, kmeans]
feature: solar+onwind-time # only for hac. choose from: [solar+onwind-time, solar+onwind-cap, solar-time, solar-cap, solar+offwind-cap] etc. feature: solar+onwind-time # only for hac. choose from: [solar+onwind-time, solar+onwind-cap, solar-time, solar-cap, solar+offwind-cap] etc.
exclude_carriers: []
cluster_network: cluster_network:
algorithm: kmeans algorithm: kmeans
feature: solar+onwind-time feature: solar+onwind-time
exclude_carriers: []
aggregation_strategies: aggregation_strategies:
generators: generators:
p_nom_max: sum # use "min" for more conservative assumptions p_nom_max: sum # use "min" for more conservative assumptions

View File

@ -3,9 +3,11 @@ simplify_network,,,
-- to_substations,bool,"{'true','false'}","Aggregates all nodes without power injection (positive or negative, i.e. demand or generation) to electrically closest ones" -- to_substations,bool,"{'true','false'}","Aggregates all nodes without power injection (positive or negative, i.e. demand or generation) to electrically closest ones"
-- algorithm,str,"One of {kmeans, hac, modularity}", -- algorithm,str,"One of {kmeans, hac, modularity}",
-- feature,str,"Str in the format carrier1+carrier2+...+carrierN-X, where CarrierI can be from {solar, onwind, offwind, ror} and X is one of {cap, time}.", -- feature,str,"Str in the format carrier1+carrier2+...+carrierN-X, where CarrierI can be from {solar, onwind, offwind, ror} and X is one of {cap, time}.",
cluster_network -- exclude_carriers,list,"List of Str like [ 'solar', 'onwind'] or empy list []","List of carriers which will not be aggregated. If empty, all carriers will be aggregated."
cluster_network,,,
-- algorithm,str,"One of {kmeans, hac}", -- algorithm,str,"One of {kmeans, hac}",
-- feature,str,"Str in the format carrier1+carrier2+...+carrierN-X, where CarrierI can be from {solar, onwind, offwind, ror} and X is one of {cap, time}.", -- feature,str,"Str in the format carrier1+carrier2+...+carrierN-X, where CarrierI can be from {solar, onwind, offwind, ror} and X is one of {cap, time}.",
-- exclude_carriers,list,"List of Str like [ 'solar', 'onwind'] or empy list []","List of carriers which will not be aggregated. If empty, all carriers will be aggregated."
aggregation_strategies,,, aggregation_strategies,,,
-- generators,,, -- generators,,,
-- -- {key},str,"{key} can be any of the component of the generator (str). Its value can be any that can be converted to pandas.Series using getattr(). For example one of {min, max, sum}.","Aggregates the component according to the given strategy. For example, if sum, then all values within each cluster are summed to represent the new generator." -- -- {key},str,"{key} can be any of the component of the generator (str). Its value can be any that can be converted to pandas.Series using getattr(). For example one of {min, max, sum}.","Aggregates the component according to the given strategy. For example, if sum, then all values within each cluster are summed to represent the new generator."

Can't render this file because it has a wrong number of fields in line 6.

View File

@ -10,7 +10,7 @@ Release Notes
Upcoming Release Upcoming Release
================ ================
* new feature * Carriers of generators can now be excluded from aggregation in clustering network and simplify network.
PyPSA-Eur 0.6.1 (20th September 2022) PyPSA-Eur 0.6.1 (20th September 2022)
===================================== =====================================
@ -35,7 +35,6 @@ PyPSA-Eur 0.6.1 (20th September 2022)
* The marginal costs of conventional generators are now taking the plant-specific * The marginal costs of conventional generators are now taking the plant-specific
efficiency into account where available. efficiency into account where available.
PyPSA-Eur 0.6.0 (10th September 2022) PyPSA-Eur 0.6.0 (10th September 2022)
===================================== =====================================

View File

@ -475,6 +475,10 @@ if __name__ == "__main__":
] ]
) )
exclude_carriers = snakemake.config["clustering"]["cluster_network"].get(
"exclude_carriers", []
)
aggregate_carriers = set(n.generators.carrier) - set(exclude_carriers)
if snakemake.wildcards.clusters.endswith("m"): if snakemake.wildcards.clusters.endswith("m"):
n_clusters = int(snakemake.wildcards.clusters[:-1]) n_clusters = int(snakemake.wildcards.clusters[:-1])
aggregate_carriers = snakemake.config["electricity"].get( aggregate_carriers = snakemake.config["electricity"].get(
@ -482,10 +486,8 @@ if __name__ == "__main__":
) )
elif snakemake.wildcards.clusters == "all": elif snakemake.wildcards.clusters == "all":
n_clusters = len(n.buses) n_clusters = len(n.buses)
aggregate_carriers = None # All
else: else:
n_clusters = int(snakemake.wildcards.clusters) n_clusters = int(snakemake.wildcards.clusters)
aggregate_carriers = None # All
if n_clusters == len(n.buses): if n_clusters == len(n.buses):
# Fast-path if no clustering is necessary # Fast-path if no clustering is necessary

View File

@ -232,6 +232,7 @@ def _aggregate_and_move_components(
output, output,
aggregate_one_ports={"Load", "StorageUnit"}, aggregate_one_ports={"Load", "StorageUnit"},
aggregation_strategies=dict(), aggregation_strategies=dict(),
exclude_carriers=None,
): ):
def replace_components(n, c, df, pnl): def replace_components(n, c, df, pnl):
n.mremove(c, n.df(c).index) n.mremove(c, n.df(c).index)
@ -245,8 +246,9 @@ def _aggregate_and_move_components(
_, generator_strategies = get_aggregation_strategies(aggregation_strategies) _, generator_strategies = get_aggregation_strategies(aggregation_strategies)
carriers = set(n.generators.carrier) - set(exclude_carriers)
generators, generators_pnl = aggregategenerators( generators, generators_pnl = aggregategenerators(
n, busmap, custom_strategies=generator_strategies n, busmap, carriers=carriers, custom_strategies=generator_strategies
) )
replace_components(n, "Generator", generators, generators_pnl) replace_components(n, "Generator", generators, generators_pnl)
@ -375,12 +377,17 @@ def simplify_links(n, costs, config, output, aggregation_strategies=dict()):
logger.debug("Collecting all components using the busmap") logger.debug("Collecting all components using the busmap")
exclude_carriers = config["clustering"]["simplify_network"].get(
"exclude_carriers", []
)
_aggregate_and_move_components( _aggregate_and_move_components(
n, n,
busmap, busmap,
connection_costs_to_bus, connection_costs_to_bus,
output, output,
aggregation_strategies=aggregation_strategies, aggregation_strategies=aggregation_strategies,
exclude_carriers=exclude_carriers,
) )
return n, busmap return n, busmap
@ -392,12 +399,17 @@ def remove_stubs(n, costs, config, output, aggregation_strategies=dict()):
connection_costs_to_bus = _compute_connection_costs_to_bus(n, busmap, costs, config) connection_costs_to_bus = _compute_connection_costs_to_bus(n, busmap, costs, config)
exclude_carriers = config["clustering"]["simplify_network"].get(
"exclude_carriers", []
)
_aggregate_and_move_components( _aggregate_and_move_components(
n, n,
busmap, busmap,
connection_costs_to_bus, connection_costs_to_bus,
output, output,
aggregation_strategies=aggregation_strategies, aggregation_strategies=aggregation_strategies,
exclude_carriers=exclude_carriers,
) )
return n, busmap return n, busmap
@ -489,7 +501,7 @@ if __name__ == "__main__":
if "snakemake" not in globals(): if "snakemake" not in globals():
from _helpers import mock_snakemake from _helpers import mock_snakemake
snakemake = mock_snakemake("simplify_network", simpl="f") snakemake = mock_snakemake("simplify_network", simpl="")
configure_logging(snakemake) configure_logging(snakemake)
n = pypsa.Network(snakemake.input.network) n = pypsa.Network(snakemake.input.network)

View File

@ -187,6 +187,7 @@ clustering:
cluster_network: cluster_network:
algorithm: kmeans algorithm: kmeans
feature: solar+onwind-time feature: solar+onwind-time
exclude_carriers: ["OCGT", "offwind-ac", "coal"]
aggregation_strategies: aggregation_strategies:
generators: generators:
p_nom_max: sum # use "min" for more conservative assumptions p_nom_max: sum # use "min" for more conservative assumptions