Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
    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}.")
Ejemplo n.º 3
0
    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}."
            )
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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