From 00aa07242a313755f8de1a2a6da7111f4cc1abf6 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Fri, 8 Dec 2023 17:53:28 +0100 Subject: [PATCH 1/3] add_brownfield: disable grid expansion if LV already hit Numerical problems were causing infeasibilities otherwise --- scripts/add_brownfield.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index 741025801..fb1453fd7 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -119,6 +119,32 @@ def add_brownfield(n, n_p, year): n.links.loc[new_pipes, "p_nom"] = 0.0 n.links.loc[new_pipes, "p_nom_min"] = 0.0 +def disable_grid_expansion_if_LV_limit_hit(n): + if not "lv_limit" in n.global_constraints.index: + return + + #calculate minimum LV + attr = "nom_min" + dc = n.links.index[n.links.carrier == "DC"] + tot = (n.lines["s_" + attr]*n.lines["length"]).sum() + (n.links.loc[dc,"p_" + attr]*n.links.loc[dc,"length"]).sum() + + diff = n.global_constraints.at["lv_limit","constant"]-tot + + #allow small numerical differences + limit = 1 + + if diff < limit: + logger.info(f"LV is already reached (gap {diff}), disabling expansion and LV limit") + expandable_acs = n.lines.index[n.lines.s_nom_extendable] + n.lines.loc[expandable_acs,"s_nom_extendable"] = False + n.lines.loc[expandable_acs,"s_nom"] = n.lines.loc[expandable_acs,"s_nom_min"] + + expandable_dcs = n.links.index[n.links.p_nom_extendable & (n.links.carrier == "DC")] + n.links.loc[expandable_dcs,"p_nom_extendable"] = False + n.links.loc[expandable_dcs,"p_nom"] = n.links.loc[expandable_dcs,"p_nom_min"] + + n.global_constraints.drop("lv_limit", + inplace=True) if __name__ == "__main__": if "snakemake" not in globals(): @@ -150,5 +176,7 @@ def add_brownfield(n, n_p, year): add_brownfield(n, n_p, year) + disable_grid_expansion_if_LV_limit_hit(n) + n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) n.export_to_netcdf(snakemake.output[0]) From 42f11752caa06a57f3b4bde2de24f0d5e5e95255 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 3 Jan 2024 13:35:11 +0100 Subject: [PATCH 2/3] standardise formatting --- scripts/add_brownfield.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index fb1453fd7..ffdaf46be 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -119,32 +119,39 @@ def add_brownfield(n, n_p, year): n.links.loc[new_pipes, "p_nom"] = 0.0 n.links.loc[new_pipes, "p_nom_min"] = 0.0 + def disable_grid_expansion_if_LV_limit_hit(n): if not "lv_limit" in n.global_constraints.index: return - #calculate minimum LV + # calculate minimum LV attr = "nom_min" dc = n.links.index[n.links.carrier == "DC"] - tot = (n.lines["s_" + attr]*n.lines["length"]).sum() + (n.links.loc[dc,"p_" + attr]*n.links.loc[dc,"length"]).sum() + tot = (n.lines["s_" + attr] * n.lines["length"]).sum() + ( + n.links.loc[dc, "p_" + attr] * n.links.loc[dc, "length"] + ).sum() - diff = n.global_constraints.at["lv_limit","constant"]-tot + diff = n.global_constraints.at["lv_limit", "constant"] - tot - #allow small numerical differences + # allow small numerical differences limit = 1 if diff < limit: - logger.info(f"LV is already reached (gap {diff}), disabling expansion and LV limit") + logger.info( + f"LV is already reached (gap {diff}), disabling expansion and LV limit" + ) expandable_acs = n.lines.index[n.lines.s_nom_extendable] - n.lines.loc[expandable_acs,"s_nom_extendable"] = False - n.lines.loc[expandable_acs,"s_nom"] = n.lines.loc[expandable_acs,"s_nom_min"] + n.lines.loc[expandable_acs, "s_nom_extendable"] = False + n.lines.loc[expandable_acs, "s_nom"] = n.lines.loc[expandable_acs, "s_nom_min"] + + expandable_dcs = n.links.index[ + n.links.p_nom_extendable & (n.links.carrier == "DC") + ] + n.links.loc[expandable_dcs, "p_nom_extendable"] = False + n.links.loc[expandable_dcs, "p_nom"] = n.links.loc[expandable_dcs, "p_nom_min"] - expandable_dcs = n.links.index[n.links.p_nom_extendable & (n.links.carrier == "DC")] - n.links.loc[expandable_dcs,"p_nom_extendable"] = False - n.links.loc[expandable_dcs,"p_nom"] = n.links.loc[expandable_dcs,"p_nom_min"] + n.global_constraints.drop("lv_limit", inplace=True) - n.global_constraints.drop("lv_limit", - inplace=True) if __name__ == "__main__": if "snakemake" not in globals(): From deba2a4ed53163ade07d2ba7a64c4f928ae10c72 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Wed, 3 Jan 2024 13:41:42 +0100 Subject: [PATCH 3/3] tidy code --- scripts/add_brownfield.py | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index ffdaf46be..9ddd3d999 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -124,31 +124,25 @@ def disable_grid_expansion_if_LV_limit_hit(n): if not "lv_limit" in n.global_constraints.index: return - # calculate minimum LV - attr = "nom_min" - dc = n.links.index[n.links.carrier == "DC"] - tot = (n.lines["s_" + attr] * n.lines["length"]).sum() + ( - n.links.loc[dc, "p_" + attr] * n.links.loc[dc, "length"] + total_expansion = ( + n.lines.eval("s_nom_min * length").sum() + + n.links.query("carrier == 'DC'").eval("p_nom_min * length").sum() ).sum() - diff = n.global_constraints.at["lv_limit", "constant"] - tot + lv_limit = n.global_constraints.at["lv_limit", "constant"] # allow small numerical differences - limit = 1 - - if diff < limit: + if lv_limit - total_expansion < 1: logger.info( - f"LV is already reached (gap {diff}), disabling expansion and LV limit" + f"LV is already reached (gap {diff} MWkm), disabling expansion and LV limit" ) - expandable_acs = n.lines.index[n.lines.s_nom_extendable] - n.lines.loc[expandable_acs, "s_nom_extendable"] = False - n.lines.loc[expandable_acs, "s_nom"] = n.lines.loc[expandable_acs, "s_nom_min"] + 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"] = n.lines.loc[extendable_acs, "s_nom_min"] - expandable_dcs = n.links.index[ - n.links.p_nom_extendable & (n.links.carrier == "DC") - ] - n.links.loc[expandable_dcs, "p_nom_extendable"] = False - n.links.loc[expandable_dcs, "p_nom"] = n.links.loc[expandable_dcs, "p_nom_min"] + 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"] = n.links.loc[extendable_dcs, "p_nom_min"] n.global_constraints.drop("lv_limit", inplace=True)