def busmap_for_country(x): prefix = x.name[0] + x.name[1] + ' ' if len(x) == 1: return pd.Series(prefix + '0', index=x.index) weight = weighting_for_country(n, x) return prefix + busmap_by_kmeans( n, weight, n_clusters[x.name], buses_i=x.index)
def busmap_for_country(x): prefix = x.name[0] + x.name[1] + ' ' logger.debug("Determining busmap for country {}".format(prefix[:-1])) if len(x) == 1: return pd.Series(prefix + '0', index=x.index) weight = weighting_for_country(n, x) if algorithm == "kmeans": return prefix + busmap_by_kmeans(n, weight, n_clusters[x.name], buses_i=x.index, **algorithm_kwds) elif algorithm == "spectral": return prefix + busmap_by_spectral_clustering(reduce_network(n, x), n_clusters[x.name], **algorithm_kwds) elif algorithm == "louvain": return prefix + busmap_by_louvain(reduce_network(n, x), n_clusters[x.name], **algorithm_kwds) else: raise ValueError(f"`algorithm` must be one of 'kmeans', 'spectral' or 'louvain'. Is {algorithm}.")
def busmap_for_country(x): if isinstance(n_clusters, pd.Series): n_cluster_c = n_clusters[x.name] else: n_cluster_c = n_clusters prefix = x.name[0] + x.name[1] + " " logger.debug(f"Determining busmap for country {prefix[:-1]}") if len(x) == 1: return pd.Series(prefix + "0", index=x.index) weight = weighting_for_country(n, x) if algorithm == "kmeans": return prefix + busmap_by_kmeans( n, weight, n_cluster_c, buses_i=x.index, **algorithm_kwds) elif algorithm == "spectral": return prefix + busmap_by_spectral_clustering( reduce_network(n, x), n_cluster_c, **algorithm_kwds) else: raise ValueError( f"`algorithm` must be one of 'kmeans', 'spectral' or 'louvain'. Is {algorithm}." )
def kmean_clustering(network, n_clusters=10): """ Implement k-mean clustering in existing network Parameters ---------- network : :class:`pypsa.Network Overall container of PyPSA Returns ------- network : pypsa.Network object Container for all network components. """ def weighting_for_scenario(x): b_i = x.index g = normed(gen.reindex(b_i, fill_value=0)) l = normed(load.reindex(b_i, fill_value=0)) w = g + l return (w * (100000. / w.max())).astype(int) def normed(x): return (x / x.sum()).fillna(0.) print('start k-mean clustering') # prepare k-mean # k-means clustering (first try) network.generators.control = "PV" network.buses['v_nom'] = 380. # problem our lines have no v_nom. this is implicitly defined by the connected buses: network.lines["v_nom"] = network.lines.bus0.map(network.buses.v_nom) # adjust the x of the lines which are not 380. lines_v_nom_b = network.lines.v_nom != 380 network.lines.loc[lines_v_nom_b, 'x'] *= (380. / network.lines.loc[lines_v_nom_b, 'v_nom'])**2 network.lines.loc[lines_v_nom_b, 'v_nom'] = 380. trafo_index = network.transformers.index transformer_voltages = pd.concat([ network.transformers.bus0.map(network.buses.v_nom), network.transformers.bus1.map(network.buses.v_nom) ], axis=1) network.import_components_from_dataframe( network.transformers.loc[:, ['bus0', 'bus1', 'x', 's_nom']].assign( x=network.transformers.x * (380. / transformer_voltages.max(axis=1))**2).set_index('T' + trafo_index), 'Line') network.transformers.drop(trafo_index, inplace=True) for attr in network.transformers_t: network.transformers_t[attr] = network.transformers_t[attr].reindex( columns=[]) #define weighting based on conventional 'old' generator spatial distribution non_conv_types = { 'biomass', 'wind', 'solar', 'geothermal', 'load shedding', 'extendable_storage' } # Attention: network.generators.carrier.unique() gen = ( network.generators.loc[(network.generators.carrier.isin(non_conv_types) == False)].groupby('bus').p_nom.sum().reindex( network.buses.index, fill_value=0.) + network.storage_units.loc[ (network.storage_units.carrier.isin(non_conv_types) == False)].groupby('bus').p_nom.sum().reindex(network.buses.index, fill_value=0.)) load = network.loads_t.p_set.mean().groupby(network.loads.bus).sum() # k-mean clustering # busmap = busmap_by_kmeans(network, bus_weightings=pd.Series(np.repeat(1, # len(network.buses)), index=network.buses.index) , n_clusters= 10) weight = weighting_for_scenario(network.buses).reindex(network.buses.index, fill_value=1) busmap = busmap_by_kmeans(network, bus_weightings=pd.Series(weight), n_clusters=n_clusters) # ToDo change function in order to use bus_strategies or similar network.generators['weight'] = 1 aggregate_one_ports = components.one_port_components.copy() aggregate_one_ports.discard('Generator') clustering = get_clustering_from_busmap( network, busmap, aggregate_generators_weighted=True, aggregate_one_ports=aggregate_one_ports) network = clustering.network #network = cluster_on_extra_high_voltage(network, busmap, with_time=True) return network
def kmean_clustering(network, n_clusters=10, load_cluster=False, line_length_factor=1.25, remove_stubs=False, use_reduced_coordinates=False, bus_weight_tocsv=None, bus_weight_fromcsv=None, n_init=10, max_iter=300, tol=1e-4, n_jobs=1): """ Main function of the k-mean clustering approach. Maps an original network to a new one with adjustable number of nodes and new coordinates. Parameters ---------- network : :class:`pypsa.Network Container for all network components. n_clusters : int Desired number of clusters. load_cluster : boolean Loads cluster coordinates from a former calculation. line_length_factor : float Factor to multiply the crow-flies distance between new buses in order to get new line lengths. remove_stubs: boolean Removes stubs and stubby trees (i.e. sequentially reducing dead-ends). use_reduced_coordinates: boolean If True, do not average cluster coordinates, but take from busmap. bus_weight_tocsv : str Creates a bus weighting based on conventional generation and load and save it to a csv file. bus_weight_fromcsv : str Loads a bus weighting from a csv file to apply it to the clustering algorithm. Returns ------- network : pypsa.Network object Container for all network components. """ def weighting_for_scenario(x, save=None): """ """ b_i = x.index g = normed(gen.reindex(b_i, fill_value=0)) l = normed(load.reindex(b_i, fill_value=0)) w = g + l weight = ((w * (100000. / w.max())).astype(int)).reindex( network.buses.index, fill_value=1) if save: weight.to_csv(save) return weight def normed(x): return (x / x.sum()).fillna(0.) print('start k-mean clustering') # prepare k-mean # k-means clustering (first try) network.generators.control = "PV" network.storage_units.control[network.storage_units.carrier == \ 'extendable_storage'] = "PV" network.buses['v_nom'] = 380. # problem our lines have no v_nom. this is implicitly defined by the # connected buses: network.lines["v_nom"] = network.lines.bus0.map(network.buses.v_nom) # adjust the x of the lines which are not 380. lines_v_nom_b = network.lines.v_nom != 380 network.lines.loc[lines_v_nom_b, 'x'] *= \ (380. / network.lines.loc[lines_v_nom_b, 'v_nom'])**2 network.lines.loc[lines_v_nom_b, 'v_nom'] = 380. trafo_index = network.transformers.index transformer_voltages = \ pd.concat([network.transformers.bus0.map(network.buses.v_nom), network.transformers.bus1.map(network.buses.v_nom)], axis=1) network.import_components_from_dataframe( network.transformers. loc[:, ['bus0', 'bus1', 'x', 's_nom', 'capital_cost']].assign( x=network.transformers.x * (380. / transformer_voltages.max(axis=1))**2, length=1).set_index('T' + trafo_index), 'Line') network.transformers.drop(trafo_index, inplace=True) for attr in network.transformers_t: network.transformers_t[attr] = network.transformers_t[attr]\ .reindex(columns=[]) # remove stubs if remove_stubs: network.determine_network_topology() busmap = busmap_by_stubs(network) network.generators['weight'] = network.generators['p_nom'] aggregate_one_ports = components.one_port_components.copy() aggregate_one_ports.discard('Generator') # reset coordinates to the new reduced guys, rather than taking an # average (copied from pypsa.networkclustering) if use_reduced_coordinates: # TODO : FIX THIS HACK THAT HAS UNEXPECTED SIDE-EFFECTS, # i.e. network is changed in place!! network.buses.loc[busmap.index, ['x', 'y']] = network.buses.loc[ busmap, ['x', 'y']].values clustering = get_clustering_from_busmap( network, busmap, aggregate_generators_weighted=True, aggregate_one_ports=aggregate_one_ports, line_length_factor=line_length_factor) network = clustering.network # define weighting based on conventional 'old' generator spatial # distribution non_conv_types = { 'biomass', 'wind_onshore', 'wind_offshore', 'solar', 'geothermal', 'load shedding', 'extendable_storage' } # Attention: network.generators.carrier.unique() gen = ( network.generators.loc[(network.generators.carrier.isin(non_conv_types) == False)].groupby('bus').p_nom.sum().reindex( network.buses.index, fill_value=0.) + network.storage_units.loc[ (network.storage_units.carrier.isin(non_conv_types) == False)].groupby('bus').p_nom.sum().reindex(network.buses.index, fill_value=0.)) load = network.loads_t.p_set.mean().groupby(network.loads.bus).sum() # k-mean clustering # busmap = busmap_by_kmeans(network, bus_weightings=pd.Series(np.repeat(1, # len(network.buses)), index=network.buses.index) , n_clusters= 10) # State whether to create a bus weighting and save it, create or not save # it, or use a bus weighting from a csv file if bus_weight_tocsv is not None: weight = weighting_for_scenario(x=network.buses, save=bus_weight_tocsv) elif bus_weight_fromcsv is not None: weight = pd.Series.from_csv(bus_weight_fromcsv) weight.index = weight.index.astype(str) else: weight = weighting_for_scenario(x=network.buses, save=False) busmap = busmap_by_kmeans(network, bus_weightings=pd.Series(weight), n_clusters=n_clusters, load_cluster=load_cluster, n_init=n_init, max_iter=max_iter, tol=tol, n_jobs=n_jobs) # ToDo change function in order to use bus_strategies or similar network.generators['weight'] = network.generators['p_nom'] aggregate_one_ports = components.one_port_components.copy() aggregate_one_ports.discard('Generator') clustering = get_clustering_from_busmap( network, busmap, aggregate_generators_weighted=True, aggregate_one_ports=aggregate_one_ports) return clustering
def kmean_clustering(network): """ Implement k-mean clustering in existing network ---------- network : :class:`pypsa.Network Overall container of PyPSA Returns ------- """ def weighting_for_scenario(x): b_i = x.index g = normed(gen.reindex(b_i, fill_value=0)) l = normed(load.reindex(b_i, fill_value=0)) w = g + l return (w * (100. / w.max())).astype(int) def normed(x): return (x / x.sum()).fillna(0.) print('start k-mean clustering') # prepare k-mean # k-means clustering (first try) network.generators.control = "PV" network.buses['v_nom'] = 380. # problem our lines have no v_nom. this is implicitly defined by the connected buses: network.lines["v_nom"] = network.lines.bus0.map(network.buses.v_nom) # adjust the x of the lines which are not 380. lines_v_nom_b = network.lines.v_nom != 380 network.lines.loc[lines_v_nom_b, 'x'] *= (380. / network.lines.loc[lines_v_nom_b, 'v_nom'])**2 network.lines.loc[lines_v_nom_b, 'v_nom'] = 380. trafo_index = network.transformers.index transformer_voltages = pd.concat([ network.transformers.bus0.map(network.buses.v_nom), network.transformers.bus1.map(network.buses.v_nom) ], axis=1) network.import_components_from_dataframe( network.transformers.loc[:, ['bus0', 'bus1', 'x', 's_nom']].assign( x=network.transformers.x * (380. / transformer_voltages.max(axis=1))**2).set_index('T' + trafo_index), 'Line') network.transformers.drop(trafo_index, inplace=True) for attr in network.transformers_t: network.transformers_t[attr] = network.transformers_t[attr].reindex( columns=[]) #ToDo: change conv to types minus wind and solar conv_types = { 'biomass', 'run_of_river', 'gas', 'oil', 'coal', 'waste', 'uranium' } # Attention: network.generators.carrier.unique() # conv_types only for SH scenario defined! gen = (network.generators.loc[network.generators.carrier.isin( conv_types)].groupby('bus').p_nom.sum().reindex(network.buses.index, fill_value=0.) + network.storage_units.loc[network.storage_units.carrier.isin( conv_types)].groupby('bus').p_nom.sum().reindex( network.buses.index, fill_value=0.)) load = network.loads_t.p_set.mean().groupby(network.loads.bus).sum() # k-mean clustering # busmap = busmap_by_kmeans(network, bus_weightings=pd.Series(np.repeat(1, # len(network.buses)), index=network.buses.index) , n_clusters= 10) weight = weighting_for_scenario(network.buses).reindex(network.buses.index, fill_value=1) busmap = busmap_by_kmeans(network, bus_weightings=pd.Series(weight), buses_i=network.buses.index, n_clusters=10) # ToDo change function in order to use bus_strategies or similar clustering = get_clustering_from_busmap(network, busmap) network = clustering.network #network = cluster_on_extra_high_voltage(network, busmap, with_time=True) return network