Merge pull request #260 from PyPSA/extendable-pnommin

fix p_nom_min values for extendable carriers with positive p_nom
This commit is contained in:
Martha Frysztacki [frɨʂtat͡skʲ] 2021-07-02 11:34:16 +02:00 committed by GitHub
commit 334e20a306
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 5 deletions

View File

@ -24,6 +24,7 @@ Upcoming Release
* The ``focus_weights`` are now also considered when pre-clustering in the :mod:`simplify_network` rule [`#241 <https://github.com/PyPSA/pypsa-eur/pull/241>`_].
* Continuous integration testing switches to Github Actions from Travis CI [`#252 <https://github.com/PyPSA/pypsa-eur/pull/252>`_].
* Bugfix in :mod:`build_renewable_profile` where offshore wind profiles could no longer be created [`#249 <https://github.com/PyPSA/pypsa-eur/pull/249>`_].
* Bugfix: Lower expansion limit of extendable carriers is now set to the existing capacity, i.e. ``p_nom_min = p_nom`` (0 before). Simultaneously, the upper limit (``p_nom_max``) is now the maximum of the installed capacity (``p_nom``) and the previous estimate based on land availability (``p_nom_max``) [`#260 <https://github.com/PyPSA/pypsa-eur/pull/260>`_].
PyPSA-Eur 0.3.0 (7th December 2020)
==================================

View File

@ -125,6 +125,14 @@ def load_network_for_plots(fn, tech_costs, config, combine_hydro_ps=True):
return n
def update_p_nom_max(n):
# if extendable carriers (solar/onwind/...) have capacity >= 0,
# e.g. existing assets from the OPSD project are included to the network,
# the installed capacity might exceed the expansion limit.
# Hence, we update the assumptions.
n.generators.p_nom_max = n.generators[['p_nom_min', 'p_nom_max']].max(1)
def aggregate_p_nom(n):
return pd.concat([
n.generators.groupby("carrier").p_nom_opt.sum(),

View File

@ -84,7 +84,7 @@ It further adds extendable ``generators`` with **zero** capacity for
"""
import logging
from _helpers import configure_logging
from _helpers import configure_logging, update_p_nom_max
import pypsa
import pandas as pd
@ -501,6 +501,7 @@ def attach_OPSD_renewables(n):
caps = caps / gens_per_bus.reindex(caps.index, fill_value=1)
n.generators.p_nom.update(gens.bus.map(caps).dropna())
n.generators.p_nom_min.update(gens.bus.map(caps).dropna())
@ -536,6 +537,7 @@ def estimate_renewable_capacities(n, tech_map=None):
.groupby(n.generators.bus.map(n.buses.country))
.transform(lambda s: normed(s) * tech_capacities.at[s.name])
.where(lambda s: s>0.1, 0.)) # only capacities above 100kW
n.generators.loc[tech_i, 'p_nom_min'] = n.generators.loc[tech_i, 'p_nom']
def add_nice_carrier_names(n, config=None):
@ -575,6 +577,7 @@ if __name__ == "__main__":
estimate_renewable_capacities(n)
attach_OPSD_renewables(n)
update_p_nom_max(n)
add_nice_carrier_names(n)

View File

@ -122,7 +122,7 @@ Exemplary unsolved network clustered to 37 nodes:
"""
import logging
from _helpers import configure_logging
from _helpers import configure_logging, update_p_nom_max
import pypsa
import os
@ -282,7 +282,7 @@ def clustering_for_n_clusters(n, n_clusters, custom_busmap=False, aggregate_carr
aggregate_generators_carriers=aggregate_carriers,
aggregate_one_ports=["Load", "StorageUnit"],
line_length_factor=line_length_factor,
generator_strategies={'p_nom_max': p_nom_max_strategy},
generator_strategies={'p_nom_max': p_nom_max_strategy, 'p_nom_min': np.sum},
scale_link_capital_costs=False)
if not n.links.empty:
@ -379,6 +379,8 @@ if __name__ == "__main__":
extended_link_costs=hvac_overhead_cost,
focus_weights=focus_weights)
update_p_nom_max(n)
clustering.network.export_to_netcdf(snakemake.output.network)
for attr in ('busmap', 'linemap'): #also available: linemap_positive, linemap_negative
getattr(clustering, attr).to_csv(snakemake.output[attr])

View File

@ -83,7 +83,7 @@ The rule :mod:`simplify_network` does up to four things:
"""
import logging
from _helpers import configure_logging
from _helpers import configure_logging, update_p_nom_max
from cluster_network import clustering_for_n_clusters, cluster_regions
from add_electricity import load_costs
@ -198,7 +198,7 @@ def _aggregate_and_move_components(n, busmap, connection_costs_to_bus, aggregate
_adjust_capital_costs_using_connection_costs(n, connection_costs_to_bus)
generators, generators_pnl = aggregategenerators(n, busmap)
generators, generators_pnl = aggregategenerators(n, busmap, custom_strategies={'p_nom_min': np.sum})
replace_components(n, "Generator", generators, generators_pnl)
for one_port in aggregate_one_ports:
@ -365,6 +365,8 @@ if __name__ == "__main__":
busmaps.append(cluster_map)
else:
n.buses = n.buses.drop(['symbol', 'tags', 'under_construction', 'substation_lv', 'substation_off'], axis=1)
update_p_nom_max(n)
n.export_to_netcdf(snakemake.output.network)