From bca53a79db0da452589e5f6c4146d988b8eb65cc Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Tue, 26 Sep 2023 16:41:00 +0200 Subject: [PATCH 01/15] Add dc-lines to edges of ehv clustering --- etrago/cluster/spatial.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/etrago/cluster/spatial.py b/etrago/cluster/spatial.py index 43af10b9..7c4b4850 100755 --- a/etrago/cluster/spatial.py +++ b/etrago/cluster/spatial.py @@ -395,6 +395,12 @@ def busmap_by_shortest_path(etrago, scn_name, fromlvl, tolvl, cpu_cores=4): transformer = connected_transformer(etrago.network, s_buses) mask = transformer.bus1.isin(buses_of_vlvl(etrago.network, tolvl)) + dc = etrago.network.links[etrago.network.links.carrier == "DC"] + dc.index = "DC_" + dc.index + lines_plus_dc = pd.concat([lines, dc]) + lines_plus_dc = lines_plus_dc[etrago.network.lines.columns] + lines_plus_dc["carrier"] = "AC" + # temporary end points, later replaced by bus1 pendant t_buses = transformer[mask].bus0 @@ -403,7 +409,7 @@ def busmap_by_shortest_path(etrago, scn_name, fromlvl, tolvl, cpu_cores=4): # graph creation edges = [ - (row.bus0, row.bus1, row.length, ix) for ix, row in lines.iterrows() + (row.bus0, row.bus1, row.length, ix) for ix, row in lines_plus_dc.iterrows() ] M = graph_from_edges(edges) From 5e566b1de1b8a126b94ef2b6efeeadb3f8d3f8ae Mon Sep 17 00:00:00 2001 From: ClaraBuettner Date: Tue, 26 Sep 2023 16:41:28 +0200 Subject: [PATCH 02/15] Add buses connected by dc lines to connected_buses --- etrago/tools/utilities.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etrago/tools/utilities.py b/etrago/tools/utilities.py index d44171bc..c3f29dee 100755 --- a/etrago/tools/utilities.py +++ b/etrago/tools/utilities.py @@ -127,6 +127,8 @@ def buses_grid_linked(network, voltage_level): mask = ( network.buses.index.isin(network.lines.bus0) | (network.buses.index.isin(network.lines.bus1)) + | (network.buses.index.isin(network.links.loc[network.links.carrier=="DC", "bus0"])) + | (network.buses.index.isin(network.links.loc[network.links.carrier=="DC", "bus1"])) ) & (network.buses.v_nom.isin(voltage_level)) df = network.buses[mask] From 3edaf2574abfb0013be44f5b37e6e29ae7ef60b1 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 4 Oct 2023 17:36:07 +0200 Subject: [PATCH 03/15] discard DC links under 220kV --- etrago/cluster/electrical.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etrago/cluster/electrical.py b/etrago/cluster/electrical.py index e46d6b0f..a834e8c3 100755 --- a/etrago/cluster/electrical.py +++ b/etrago/cluster/electrical.py @@ -320,6 +320,8 @@ def cluster_on_extra_high_voltage(etrago, busmap, with_time=True): # Dealing with links links = network.links.copy() dc_links = links[links["carrier"] == "DC"] + # Discard links connected to buses under 220 kV + dc_links = dc_links[dc_links.bus0.isin(buses.index)] links = links[links["carrier"] != "DC"] new_links = ( From c63a459fa4b57dee6c4efb1432fad2078344b6d6 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 5 Oct 2023 08:55:39 +0200 Subject: [PATCH 04/15] create hv busmap everytime eHV clus runs --- etrago/cluster/spatial.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/etrago/cluster/spatial.py b/etrago/cluster/spatial.py index 7c4b4850..0cfe098f 100755 --- a/etrago/cluster/spatial.py +++ b/etrago/cluster/spatial.py @@ -409,7 +409,8 @@ def busmap_by_shortest_path(etrago, scn_name, fromlvl, tolvl, cpu_cores=4): # graph creation edges = [ - (row.bus0, row.bus1, row.length, ix) for ix, row in lines_plus_dc.iterrows() + (row.bus0, row.bus1, row.length, ix) + for ix, row in lines_plus_dc.iterrows() ] M = graph_from_edges(edges) @@ -538,24 +539,26 @@ def fetch(): busmap = fetch() - # TODO: Or better try/except/finally - if not busmap: - print("Busmap does not exist and will be created.\n") - - cpu_cores = etrago.args["network_clustering"]["CPU_cores"] - if cpu_cores == "max": - cpu_cores = mp.cpu_count() - else: - cpu_cores = int(cpu_cores) - - busmap_by_shortest_path( - etrago, - scn_name, - fromlvl=[110], - tolvl=[220, 380, 400, 450], - cpu_cores=cpu_cores, + if busmap: + print( + "Existing busmap will be deleted and a new one will be calculated.\n" ) - busmap = fetch() + etrago.engine.execute("""DELETE FROM grid.egon_etrago_hv_busmap""") + + cpu_cores = etrago.args["network_clustering"]["CPU_cores"] + if cpu_cores == "max": + cpu_cores = mp.cpu_count() + else: + cpu_cores = int(cpu_cores) + + busmap_by_shortest_path( + etrago, + scn_name, + fromlvl=[110], + tolvl=[220, 380, 400, 450], + cpu_cores=cpu_cores, + ) + busmap = fetch() return busmap From 421777295e58211c67f5ba85b8b3750751998944 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 5 Oct 2023 15:53:19 +0200 Subject: [PATCH 05/15] make delete_dispensable_ac_buses optional --- etrago/appl.py | 6 ++++++ etrago/cluster/spatial.py | 2 +- etrago/tools/utilities.py | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/etrago/appl.py b/etrago/appl.py index cdf3f3ad..4237ea4b 100644 --- a/etrago/appl.py +++ b/etrago/appl.py @@ -100,6 +100,7 @@ "grid_max_abs_foreign": None, # absolute capacity per voltage level }, }, + "delete_dispensable_ac_buses": False, # bool. Find and delete unnecesary buses "generator_noise": 789456, # apply generator noise, False or seed number "extra_functionality": {}, # Choose function name or {} # Spatial Complexity: @@ -379,6 +380,11 @@ def run_etrago(args, json_path): Limit overall energy production country-wise for each generator by carrier. Set upper/lower limit in p.u. + delete_dispensable_ac_buses: bool + Choose if unnecessary buses should be identified and deleted from the + grid. This buses have no load or generation attached. Additionally, + they are just connected to two other buses. + Default: False. network_clustering_ehv : bool Choose if you want to cluster the full HV/EHV dataset down to only the EHV buses. In that case, all HV buses are assigned to their closest EHV diff --git a/etrago/cluster/spatial.py b/etrago/cluster/spatial.py index 0cfe098f..db3cc161 100755 --- a/etrago/cluster/spatial.py +++ b/etrago/cluster/spatial.py @@ -541,7 +541,7 @@ def fetch(): if busmap: print( - "Existing busmap will be deleted and a new one will be calculated.\n" + "Existing busmap will be deleted and a new one will be calculated." ) etrago.engine.execute("""DELETE FROM grid.egon_etrago_hv_busmap""") diff --git a/etrago/tools/utilities.py b/etrago/tools/utilities.py index c3f29dee..dc66d232 100755 --- a/etrago/tools/utilities.py +++ b/etrago/tools/utilities.py @@ -1081,6 +1081,8 @@ def delete_dispensable_ac_buses(etrago): None. """ + if etrago.args["delete_dispensable_ac_buses"] is False: + return def delete_buses(delete_buses, network): drop_buses = delete_buses.index.to_list() From db95efc116591e13ca38cc24dc189e118bbc8a3b Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 5 Oct 2023 15:57:16 +0200 Subject: [PATCH 06/15] use black --- etrago/tools/utilities.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/etrago/tools/utilities.py b/etrago/tools/utilities.py index dc66d232..ebc858f1 100755 --- a/etrago/tools/utilities.py +++ b/etrago/tools/utilities.py @@ -127,8 +127,16 @@ def buses_grid_linked(network, voltage_level): mask = ( network.buses.index.isin(network.lines.bus0) | (network.buses.index.isin(network.lines.bus1)) - | (network.buses.index.isin(network.links.loc[network.links.carrier=="DC", "bus0"])) - | (network.buses.index.isin(network.links.loc[network.links.carrier=="DC", "bus1"])) + | ( + network.buses.index.isin( + network.links.loc[network.links.carrier == "DC", "bus0"] + ) + ) + | ( + network.buses.index.isin( + network.links.loc[network.links.carrier == "DC", "bus1"] + ) + ) ) & (network.buses.v_nom.isin(voltage_level)) df = network.buses[mask] From 27d1714d417da4ee42b81863775ceccee4e35015 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 9 Oct 2023 09:40:38 +0200 Subject: [PATCH 07/15] include the argument delete_dispensable_ac_buses --- etrago/args.json | 1 + 1 file changed, 1 insertion(+) diff --git a/etrago/args.json b/etrago/args.json index 8693f929..7056e907 100644 --- a/etrago/args.json +++ b/etrago/args.json @@ -51,6 +51,7 @@ }, "generator_noise": 789456, "extra_functionality": {}, + "delete_dispensable_ac_buses": true, "network_clustering_ehv": false, "network_clustering": { "active": true, From 85216abe9b0dc976b2b1adc5914ddd808616f961 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Mon, 9 Oct 2023 09:42:25 +0200 Subject: [PATCH 08/15] adjust description new args --- etrago/appl.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/etrago/appl.py b/etrago/appl.py index 5bf011c8..a53a360e 100644 --- a/etrago/appl.py +++ b/etrago/appl.py @@ -99,10 +99,10 @@ "grid_max_abs_foreign": None, # absolute capacity per voltage level }, }, - "delete_dispensable_ac_buses": False, # bool. Find and delete unnecesary buses "generator_noise": 789456, # apply generator noise, False or seed number "extra_functionality": {}, # Choose function name or {} # Spatial Complexity: + "delete_dispensable_ac_buses": True, # bool. Find and delete expendable buses "network_clustering_ehv": False, # clustering of HV buses to EHV buses "network_clustering": { "active": True, # choose if clustering is activated @@ -385,10 +385,11 @@ def run_etrago(args, json_path): by carrier. Set upper/lower limit in p.u. delete_dispensable_ac_buses: bool - Choose if unnecessary buses should be identified and deleted from the - grid. This buses have no load or generation attached. Additionally, - they are just connected to two other buses. - Default: False. + Choose if electrical buses that are only connecting two lines should be + removed. These buses have no other components attached to them. The + connected lines are merged. This reduces the spatial complexity without + losing any accuracy. + Default: True. network_clustering_ehv : bool Choose if you want to cluster the full HV/EHV dataset down to only the EHV buses. In that case, all HV buses are assigned to their closest EHV From 1027eca1d964f1602ec9ea017cbacdcc24562639 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 17 Oct 2023 15:09:18 +0200 Subject: [PATCH 09/15] include busmap status for eHV clustering --- etrago/appl.py | 18 +++++++- etrago/args.json | 5 ++- etrago/cluster/electrical.py | 20 +++------ etrago/cluster/spatial.py | 84 ++++++++---------------------------- etrago/tools/utilities.py | 2 +- 5 files changed, 47 insertions(+), 82 deletions(-) diff --git a/etrago/appl.py b/etrago/appl.py index a53a360e..699897fe 100644 --- a/etrago/appl.py +++ b/etrago/appl.py @@ -103,7 +103,10 @@ "extra_functionality": {}, # Choose function name or {} # Spatial Complexity: "delete_dispensable_ac_buses": True, # bool. Find and delete expendable buses - "network_clustering_ehv": False, # clustering of HV buses to EHV buses + "network_clustering_ehv": { + "active": False, # choose if clustering of HV buses to EHV buses is activated + "busmap": False, # False or path to stored busmap + }, "network_clustering": { "active": True, # choose if clustering is activated "method": "kmedoids-dijkstra", # choose clustering method: kmeans or kmedoids-dijkstra @@ -390,11 +393,22 @@ def run_etrago(args, json_path): connected lines are merged. This reduces the spatial complexity without losing any accuracy. Default: True. - network_clustering_ehv : bool + network_clustering_ehv : dict + Choose if you want to apply an extra high voltage clustering to the + electrical network. + The provided dictionary can have the following entries: + + * "active" : bool Choose if you want to cluster the full HV/EHV dataset down to only the EHV buses. In that case, all HV buses are assigned to their closest EHV substation, taking into account the shortest distance on power lines. Default: False. + * "busmap" : str + Choose if an stored busmap can be used to make the process quicker, or + a new busmap must be calculated. False or path to the busmap in csv + format should be given. + Default: False + network_clustering : dict Choose if you want to apply a clustering of all network buses and specify settings. diff --git a/etrago/args.json b/etrago/args.json index 7056e907..e64c7b53 100644 --- a/etrago/args.json +++ b/etrago/args.json @@ -52,7 +52,10 @@ "generator_noise": 789456, "extra_functionality": {}, "delete_dispensable_ac_buses": true, - "network_clustering_ehv": false, + "network_clustering_ehv": { + "active": false, + "busmap": false, + }, "network_clustering": { "active": true, "method": "kmedoids-dijkstra", diff --git a/etrago/cluster/electrical.py b/etrago/cluster/electrical.py index 76afc3a8..82ecab19 100755 --- a/etrago/cluster/electrical.py +++ b/etrago/cluster/electrical.py @@ -290,11 +290,6 @@ def cluster_on_extra_high_voltage(etrago, busmap, with_time=True): etrago, busmap, cluster_met="ehv" ) - pd.DataFrame(busmap.items(), columns=["bus0", "bus1"]).to_csv( - "ehv_elecgrid_busmap_result.csv", - index=False, - ) - buses = aggregatebuses( network, busmap, @@ -381,7 +376,6 @@ def cluster_on_extra_high_voltage(etrago, busmap, with_time=True): io.import_series_from_dataframe(network_c, df, one_port, attr) network_c.links, network_c.links_t = group_links(network_c) - network_c.determine_network_topology() return (network_c, busmap) @@ -414,10 +408,10 @@ def delete_ehv_buses_no_lines(network): buses_ac["with_gen"] = buses_ac.index.isin(network.generators.bus) delete_buses = buses_ac[ - (buses_ac["with_line"] is False) - & (buses_ac["with_load"] is False) - & (buses_ac["with_link"] is False) - & (buses_ac["with_gen"] is False) + (buses_ac["with_line"] == False) + & (buses_ac["with_load"] == False) + & (buses_ac["with_link"] == False) + & (buses_ac["with_gen"] == False) ].index if len(delete_buses): @@ -455,8 +449,8 @@ def ehv_clustering(self): """ Cluster the network based on Extra High Voltage (EHV) grid. - If `network_clustering_ehv` argument is True, the function clusters the - network based on the EHV grid. + If 'active' in the `network_clustering_ehv` argument is True, the function + clusters the network based on the EHV grid. Parameters ---------- @@ -468,7 +462,7 @@ def ehv_clustering(self): None """ - if self.args["network_clustering_ehv"]: + if self.args["network_clustering_ehv"]["active"]: logger.info("Start ehv clustering") self.network.generators.control = "PV" diff --git a/etrago/cluster/spatial.py b/etrago/cluster/spatial.py index e2afcd7d..679dcafa 100755 --- a/etrago/cluster/spatial.py +++ b/etrago/cluster/spatial.py @@ -362,7 +362,7 @@ def shortest_path(paths, graph): return df -def busmap_by_shortest_path(etrago, scn_name, fromlvl, tolvl, cpu_cores=4): +def busmap_by_shortest_path(etrago, fromlvl, tolvl, cpu_cores=4): """ Creates a busmap for the EHV-Clustering between voltage levels based on dijkstra shortest path. The result is automatically written to the @@ -379,8 +379,6 @@ def busmap_by_shortest_path(etrago, scn_name, fromlvl, tolvl, cpu_cores=4): Container for all network components. session : sqlalchemy.orm.session.Session object Establishes interactions with the database. - scn_name : str - Name of the scenario. fromlvl : list List of voltage-levels to cluster. tolvl : list @@ -393,8 +391,6 @@ def busmap_by_shortest_path(etrago, scn_name, fromlvl, tolvl, cpu_cores=4): None """ - # cpu_cores = mp.cpu_count() - # data preperation s_buses = buses_grid_linked(etrago.network, fromlvl) lines = connected_grid_lines(etrago.network, s_buses) @@ -476,25 +472,11 @@ def busmap_by_shortest_path(etrago, scn_name, fromlvl, tolvl, cpu_cores=4): df = pd.concat([df, tofill], ignore_index=True, axis=0) df.drop_duplicates(inplace=True) - # prepare data for export - - df["scn_name"] = scn_name - df["version"] = etrago.args["gridversion"] - - if not df.version.any(): - df.version = "testcase" - df.rename(columns={"source": "bus0", "target": "bus1"}, inplace=True) - df.set_index(["scn_name", "bus0", "bus1"], inplace=True) - df.to_sql( - "egon_etrago_hv_busmap", - con=etrago.engine, - schema="grid", - if_exists="append", - ) + busmap = pd.Series(df.bus1.values, index=df.bus0).to_dict() - return + return busmap def busmap_from_psql(etrago): @@ -517,54 +499,26 @@ def busmap_from_psql(etrago): busmap : dict Maps old bus_ids to new bus_ids. """ - scn_name = ( - etrago.args["scn_name"] - if etrago.args["scn_extension"] is None - else etrago.args["scn_name"] - + "_ext_" - + "_".join(etrago.args["scn_extension"]) - ) - - from saio.grid import egon_etrago_hv_busmap - - filter_version = etrago.args["gridversion"] - if not filter_version: - filter_version = "testcase" - - def fetch(): - query = ( - etrago.session.query( - egon_etrago_hv_busmap.bus0, egon_etrago_hv_busmap.bus1 - ) - .filter(egon_etrago_hv_busmap.scn_name == scn_name) - .filter(egon_etrago_hv_busmap.version == filter_version) + if etrago.args["network_clustering_ehv"]["busmap"] is False: + cpu_cores = etrago.args["network_clustering"]["CPU_cores"] + if cpu_cores == "max": + cpu_cores = mp.cpu_count() + else: + cpu_cores = int(cpu_cores) + + busmap = busmap_by_shortest_path( + etrago, + fromlvl=[110], + tolvl=[220, 380, 400, 450], + cpu_cores=cpu_cores, ) - - return dict(query.all()) - - busmap = fetch() - - if busmap: - print( - "Existing busmap will be deleted and a new one will be calculated." + pd.DataFrame(busmap.items(), columns=["bus0", "bus1"]).to_csv( + "ehv_elecgrid_busmap_result.csv", + index=False, ) - etrago.engine.execute("""DELETE FROM grid.egon_etrago_hv_busmap""") - - cpu_cores = etrago.args["network_clustering"]["CPU_cores"] - if cpu_cores == "max": - cpu_cores = mp.cpu_count() else: - cpu_cores = int(cpu_cores) - - busmap_by_shortest_path( - etrago, - scn_name, - fromlvl=[110], - tolvl=[220, 380, 400, 450], - cpu_cores=cpu_cores, - ) - busmap = fetch() + busmap = pd.read_csv(etrago.args["network_clustering_ehv"]["busmap"]) return busmap diff --git a/etrago/tools/utilities.py b/etrago/tools/utilities.py index ebc858f1..164b7c9a 100755 --- a/etrago/tools/utilities.py +++ b/etrago/tools/utilities.py @@ -1878,7 +1878,7 @@ def get_clustering_data(self, path): """ - if (self.args["network_clustering_ehv"]) | ( + if (self.args["network_clustering_ehv"]["active"]) | ( self.args["network_clustering"]["active"] ): path_clus = os.path.join(path, "clustering") From a5c36ad0d6ad382a002fe6b93513d994c6adc582 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Tue, 17 Oct 2023 15:54:10 +0200 Subject: [PATCH 10/15] solve flake8 problem --- etrago/cluster/electrical.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/etrago/cluster/electrical.py b/etrago/cluster/electrical.py index 82ecab19..072b70dc 100755 --- a/etrago/cluster/electrical.py +++ b/etrago/cluster/electrical.py @@ -408,10 +408,10 @@ def delete_ehv_buses_no_lines(network): buses_ac["with_gen"] = buses_ac.index.isin(network.generators.bus) delete_buses = buses_ac[ - (buses_ac["with_line"] == False) - & (buses_ac["with_load"] == False) - & (buses_ac["with_link"] == False) - & (buses_ac["with_gen"] == False) + (~buses_ac["with_line"]) + & (~buses_ac["with_load"]) + & (~buses_ac["with_link"]) + & (~buses_ac["with_gen"]) ].index if len(delete_buses): From 7e0eb63ff856bd74fd31d08789028cbf3184a198 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 18 Oct 2023 13:03:15 +0200 Subject: [PATCH 11/15] fix import busmap eHV --- etrago/cluster/spatial.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etrago/cluster/spatial.py b/etrago/cluster/spatial.py index 679dcafa..637b3bee 100755 --- a/etrago/cluster/spatial.py +++ b/etrago/cluster/spatial.py @@ -519,6 +519,8 @@ def busmap_from_psql(etrago): ) else: busmap = pd.read_csv(etrago.args["network_clustering_ehv"]["busmap"]) + busmap = pd.Series(busmap.bus1.apply(str).values, + index=busmap.bus0.apply(str)).to_dict() return busmap From 9529a8da8bbb4015c82b21b6ee953dbedc320986 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 18 Oct 2023 13:16:09 +0200 Subject: [PATCH 12/15] update name and description of busmap_from_psql --- etrago/cluster/electrical.py | 4 ++-- etrago/cluster/spatial.py | 16 ++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/etrago/cluster/electrical.py b/etrago/cluster/electrical.py index 072b70dc..2a22ce93 100755 --- a/etrago/cluster/electrical.py +++ b/etrago/cluster/electrical.py @@ -39,7 +39,7 @@ import pypsa.io as io from etrago.cluster.spatial import ( - busmap_from_psql, + busmap_ehv_clustering, group_links, kmean_clustering, kmedoids_dijkstra_clustering, @@ -469,7 +469,7 @@ def ehv_clustering(self): delete_ehv_buses_no_lines(self.network) - busmap = busmap_from_psql(self) + busmap = busmap_ehv_clustering(self) self.network, busmap = cluster_on_extra_high_voltage( self, busmap, with_time=True diff --git a/etrago/cluster/spatial.py b/etrago/cluster/spatial.py index 637b3bee..e402f797 100755 --- a/etrago/cluster/spatial.py +++ b/etrago/cluster/spatial.py @@ -479,20 +479,16 @@ def busmap_by_shortest_path(etrago, fromlvl, tolvl, cpu_cores=4): return busmap -def busmap_from_psql(etrago): +def busmap_ehv_clustering(etrago): """ - Retrieves busmap from `model_draft.ego_grid_pf_hv_busmap` on the - [www.openenergy-platform.org] by a given scenario - name. If this busmap does not exist, it is created with default values. + Generates a busmap that can be used to cluster an electrical network to + only extra high voltage buses. If a path to a busmap in a csv file is + passed in the arguments, it loads the csv file and returns it. Parameters ---------- - network : pypsa.Network - Container for all network components. - session : sqlalchemy.orm.session.Session object - Establishes interactions with the database. - scn_name : str - Name of the scenario. + etrago : Etrago + An instance of the Etrago class Returns ------- From b76a7bff2ba7c94972c71d200d0b8cd9a47d5ad9 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Wed, 18 Oct 2023 13:55:56 +0200 Subject: [PATCH 13/15] using Black --- etrago/cluster/spatial.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/etrago/cluster/spatial.py b/etrago/cluster/spatial.py index e402f797..37dbb75e 100755 --- a/etrago/cluster/spatial.py +++ b/etrago/cluster/spatial.py @@ -515,8 +515,9 @@ def busmap_ehv_clustering(etrago): ) else: busmap = pd.read_csv(etrago.args["network_clustering_ehv"]["busmap"]) - busmap = pd.Series(busmap.bus1.apply(str).values, - index=busmap.bus0.apply(str)).to_dict() + busmap = pd.Series( + busmap.bus1.apply(str).values, index=busmap.bus0.apply(str) + ).to_dict() return busmap From 92aeaf1ff934e9e323441aaf778426209bb9ee9e Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 21 Sep 2023 09:28:03 +0200 Subject: [PATCH 14/15] cluster DE no elec buses only to DE --- etrago/cluster/electrical.py | 120 ++++++++++++++--------------------- 1 file changed, 49 insertions(+), 71 deletions(-) diff --git a/etrago/cluster/electrical.py b/etrago/cluster/electrical.py index 2a22ce93..50d2cb55 100755 --- a/etrago/cluster/electrical.py +++ b/etrago/cluster/electrical.py @@ -115,6 +115,27 @@ def adjust_no_electric_network(etrago, busmap, cluster_met): Maps old bus_ids to new bus_ids including all sectors. """ + + def find_de_closest(network, bus_ne): + ac_ehv = network.buses[ + (network.buses.v_nom > 110) + & (network.buses.carrier == "AC") + & (network.buses.country == "DE") + ] + + bus_ne_x = network.buses.loc[bus_ne, "x"] + bus_ne_y = network.buses.loc[bus_ne, "y"] + + ac_ehv["dist"] = ac_ehv.apply( + lambda x: ((x.x - bus_ne_x) ** 2 + (x.y - bus_ne_y) ** 2) + ** (1 / 2), + axis=1, + ) + + new_ehv_bus = ac_ehv.dist.idxmin() + + return new_ehv_bus + network = etrago.network # network2 is supposed to contain all the not electrical or gas buses # and links @@ -135,16 +156,9 @@ def adjust_no_electric_network(etrago, busmap, cluster_met): "rural_heat": "rural_heat_pump", } - # no_elec_to_cluster maps the no electrical buses to the eHV/kmean bus - no_elec_to_cluster = pd.DataFrame( - columns=["cluster", "carrier", "new_bus"] - ).set_index("new_bus") - - max_bus = max([int(item) for item in network.buses.index.to_list()]) - no_elec_conex = [] - # busmap2 maps all the no electrical buses to the new buses based on the - # eHV network + # busmap2 defines how the no electrical buses directly connected to AC + # are going to be clustered busmap2 = {} # Map crossborder AC buses in case that they were not part of the k-mean @@ -160,53 +174,37 @@ def adjust_no_electric_network(etrago, busmap, cluster_met): for bus_out in ac_buses_out.index: busmap2[bus_out] = bus_out + foreign_hv = network.buses[ + (network.buses.country != "DE") + & (network.buses.carrier == "AC") + & (network.buses.v_nom > 110) + ].index + busmap3 = pd.DataFrame(columns=["elec_bus", "carrier", "cluster"]) for bus_ne in network2.buses.index: - bus_hv = -1 carry = network2.buses.loc[bus_ne, "carrier"] - - if ( - len( - network2.links[ - (network2.links["bus1"] == bus_ne) - & (network2.links["carrier"] == map_carrier[carry]) - ] - ) - > 0 - ): + busmap3.at[bus_ne, "carrier"] = carry + try: df = network2.links[ (network2.links["bus1"] == bus_ne) & (network2.links["carrier"] == map_carrier[carry]) ].copy() df["elec"] = df["bus0"].isin(busmap.keys()) - - df = df[df["elec"]] - if len(df) > 0: - bus_hv = df["bus0"][0] - - if bus_hv == -1: - busmap2[bus_ne] = str(bus_ne) + bus_hv = df[df["elec"] == True]["bus0"][0] + bus_ehv = busmap[bus_hv] + if bus_ehv not in foreign_hv: + busmap3.at[bus_ne, "elec_bus"] = bus_ehv + else: + busmap3.at[bus_ne, "elec_bus"] = find_de_closest( + network, bus_ne + ) + except: no_elec_conex.append(bus_ne) - continue - - if ( - (no_elec_to_cluster.cluster == busmap[bus_hv]) - & (no_elec_to_cluster.carrier == carry) - ).any(): - bus_cluster = no_elec_to_cluster[ - (no_elec_to_cluster.cluster == busmap[bus_hv]) - & (no_elec_to_cluster.carrier == carry) - ].index[0] - else: - bus_cluster = str(max_bus + 1) - max_bus = max_bus + 1 - new = pd.DataFrame( - {"cluster": busmap[bus_hv], "carrier": carry}, - index=[bus_cluster], - ) + busmap3.at[bus_ne, "elec_bus"] = bus_ne - no_elec_to_cluster = pd.concat([no_elec_to_cluster, new]) + for a, df in busmap3.groupby(["elec_bus", "carrier"]): + busmap3.loc[df.index, "cluster"] = df.index[0] - busmap2[bus_ne] = bus_cluster + busmap3 = busmap3["cluster"].to_dict() if no_elec_conex: logger.info( @@ -215,17 +213,17 @@ def adjust_no_electric_network(etrago, busmap, cluster_met): ) # rural_heat_store buses are clustered based on the AC buses connected to - # their corresponding rural_heat buses + # their corresponding rural_heat buses. Results saved in busmap4 links_rural_store = etrago.network.links[ etrago.network.links.carrier == "rural_heat_store_charger" ].copy() - busmap3 = {} - links_rural_store["to_ac"] = links_rural_store["bus0"].map(busmap2) + busmap4 = {} + links_rural_store["to_ac"] = links_rural_store["bus0"].map(busmap3) for rural_heat_bus, df in links_rural_store.groupby("to_ac"): cluster_bus = df.bus1.iat[0] for rural_store_bus in df.bus1: - busmap3[rural_store_bus] = cluster_bus + busmap4[rural_store_bus] = cluster_bus # Add the gas buses to the busmap and map them to themself for gas_bus in network.buses[ @@ -236,28 +234,8 @@ def adjust_no_electric_network(etrago, busmap, cluster_met): ].index: busmap2[gas_bus] = gas_bus - busmap = {**busmap, **busmap2, **busmap3} - - # The new buses based on the eHV network for not electrical buses are - # created - if cluster_met in ["kmeans", "kmedoids-dijkstra"]: - network.madd( - "Bus", - names=no_elec_to_cluster.index, - carrier=no_elec_to_cluster.carrier, - ) + busmap = {**busmap, **busmap2, **busmap3, **busmap4} - else: - network.madd( - "Bus", - names=no_elec_to_cluster.index, - carrier=no_elec_to_cluster.carrier.values, - x=network.buses.loc[no_elec_to_cluster.cluster.values, "x"].values, - y=network.buses.loc[no_elec_to_cluster.cluster.values, "y"].values, - country=network.buses.loc[ - no_elec_to_cluster.cluster.values, "country" - ].values, - ) return network, busmap From 79ecf3e81bc1725beff7834b9f1fbdcba3f08e23 Mon Sep 17 00:00:00 2001 From: CarlosEpia Date: Thu, 19 Oct 2023 15:03:39 +0200 Subject: [PATCH 15/15] solve Flake8 problem --- etrago/cluster/electrical.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etrago/cluster/electrical.py b/etrago/cluster/electrical.py index 50d2cb55..538acf29 100755 --- a/etrago/cluster/electrical.py +++ b/etrago/cluster/electrical.py @@ -189,7 +189,7 @@ def find_de_closest(network, bus_ne): & (network2.links["carrier"] == map_carrier[carry]) ].copy() df["elec"] = df["bus0"].isin(busmap.keys()) - bus_hv = df[df["elec"] == True]["bus0"][0] + bus_hv = df[df["elec"]]["bus0"][0] bus_ehv = busmap[bus_hv] if bus_ehv not in foreign_hv: busmap3.at[bus_ne, "elec_bus"] = bus_ehv