Merge pull request #952 from koen-vg/transmission-expansion-limit-reached
Add check for turning off transmission expnasion if limit reached
This commit is contained in:
commit
0a0a35e4a4
@ -104,6 +104,8 @@ Upcoming Release
|
|||||||
|
|
||||||
* Bugfix: allow modelling sector-coupled landlocked regions. (Fixed handling of offshore wind.)
|
* Bugfix: allow modelling sector-coupled landlocked regions. (Fixed handling of offshore wind.)
|
||||||
|
|
||||||
|
* Adapt the disabling of transmission expansion in myopic foresight optimisations when limit is already reached to also handle cost limits.
|
||||||
|
|
||||||
PyPSA-Eur 0.10.0 (19th February 2024)
|
PyPSA-Eur 0.10.0 (19th February 2024)
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
|
@ -124,29 +124,57 @@ def add_brownfield(n, n_p, year):
|
|||||||
n.links.loc[new_pipes, "p_nom_min"] = 0.0
|
n.links.loc[new_pipes, "p_nom_min"] = 0.0
|
||||||
|
|
||||||
|
|
||||||
def disable_grid_expansion_if_LV_limit_hit(n):
|
def disable_grid_expansion_if_limit_hit(n):
|
||||||
if "lv_limit" not in n.global_constraints.index:
|
"""
|
||||||
return
|
Check if transmission expansion limit is already reached; then turn off.
|
||||||
|
|
||||||
|
In particular, this function checks if the total transmission
|
||||||
|
capital cost or volume implied by s_nom_min and p_nom_min are
|
||||||
|
numerically close to the respective global limit set in
|
||||||
|
n.global_constraints. If so, the nominal capacities are set to the
|
||||||
|
minimum and extendable is turned off; the corresponding global
|
||||||
|
constraint is then dropped.
|
||||||
|
"""
|
||||||
|
cols = {"cost": "capital_cost", "volume": "length"}
|
||||||
|
for limit_type in ["cost", "volume"]:
|
||||||
|
glcs = n.global_constraints.query(
|
||||||
|
f"type == 'transmission_expansion_{limit_type}_limit'"
|
||||||
|
)
|
||||||
|
|
||||||
|
for name, glc in glcs.iterrows():
|
||||||
total_expansion = (
|
total_expansion = (
|
||||||
n.lines.eval("s_nom_min * length").sum()
|
(
|
||||||
+ n.links.query("carrier == 'DC'").eval("p_nom_min * length").sum()
|
n.lines.query("p_nom_extendable")
|
||||||
|
.eval(f"s_nom_min * {cols[limit_type]}")
|
||||||
|
.sum()
|
||||||
|
)
|
||||||
|
+ (
|
||||||
|
n.links.query("carrier == 'DC' and p_nom_extendable")
|
||||||
|
.eval(f"p_nom_min * {cols[limit_type]}")
|
||||||
|
.sum()
|
||||||
|
)
|
||||||
).sum()
|
).sum()
|
||||||
|
|
||||||
lv_limit = n.global_constraints.at["lv_limit", "constant"]
|
# Allow small numerical differences
|
||||||
|
if np.abs(glc.constant - total_expansion) / glc.constant < 1e-6:
|
||||||
# allow small numerical differences
|
logger.info(
|
||||||
if lv_limit - total_expansion < 1:
|
f"Transmission expansion {limit_type} is already reached, disabling expansion and limit"
|
||||||
logger.info("LV is already reached, disabling expansion and LV limit")
|
)
|
||||||
extendable_acs = n.lines.query("s_nom_extendable").index
|
extendable_acs = n.lines.query("s_nom_extendable").index
|
||||||
n.lines.loc[extendable_acs, "s_nom_extendable"] = False
|
n.lines.loc[extendable_acs, "s_nom_extendable"] = False
|
||||||
n.lines.loc[extendable_acs, "s_nom"] = n.lines.loc[extendable_acs, "s_nom_min"]
|
n.lines.loc[extendable_acs, "s_nom"] = n.lines.loc[
|
||||||
|
extendable_acs, "s_nom_min"
|
||||||
|
]
|
||||||
|
|
||||||
extendable_dcs = n.links.query("carrier == 'DC' and p_nom_extendable").index
|
extendable_dcs = n.links.query(
|
||||||
|
"carrier == 'DC' and p_nom_extendable"
|
||||||
|
).index
|
||||||
n.links.loc[extendable_dcs, "p_nom_extendable"] = False
|
n.links.loc[extendable_dcs, "p_nom_extendable"] = False
|
||||||
n.links.loc[extendable_dcs, "p_nom"] = n.links.loc[extendable_dcs, "p_nom_min"]
|
n.links.loc[extendable_dcs, "p_nom"] = n.links.loc[
|
||||||
|
extendable_dcs, "p_nom_min"
|
||||||
|
]
|
||||||
|
|
||||||
n.global_constraints.drop("lv_limit", inplace=True)
|
n.global_constraints.drop(name, inplace=True)
|
||||||
|
|
||||||
|
|
||||||
def adjust_renewable_profiles(n, input_profiles, params, year):
|
def adjust_renewable_profiles(n, input_profiles, params, year):
|
||||||
@ -233,7 +261,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
add_brownfield(n, n_p, year)
|
add_brownfield(n, n_p, year)
|
||||||
|
|
||||||
disable_grid_expansion_if_LV_limit_hit(n)
|
disable_grid_expansion_if_limit_hit(n)
|
||||||
|
|
||||||
n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
|
n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
|
||||||
n.export_to_netcdf(snakemake.output[0])
|
n.export_to_netcdf(snakemake.output[0])
|
||||||
|
Loading…
Reference in New Issue
Block a user