Skip to content

Commit

Permalink
Merge pull request #504 from ktehranchi/kt/docs
Browse files Browse the repository at this point in the history
multiple fixes
  • Loading branch information
ktehranchi authored Jan 2, 2025
2 parents fd30069 + e173a28 commit 6d60201
Show file tree
Hide file tree
Showing 7 changed files with 313 additions and 26 deletions.
1 change: 1 addition & 0 deletions workflow/rules/build_electricity.smk
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ rule prepare_network:
co2limit_enable=config_provider("electricity", "co2limit_enable", default=False),
gaslimit=config_provider("electricity", "gaslimit"),
gaslimit_enable=config_provider("electricity", "gaslimit_enable", default=False),
transmission_network=config_provider("model_topology", "transmission_network"),
max_hours=config_provider("electricity", "max_hours"),
costs=config_provider("costs"),
autarky=config_provider("electricity", "autarky"),
Expand Down
2 changes: 2 additions & 0 deletions workflow/rules/postprocess.smk
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ rule plot_statistics:
+ "{interconnect}/figures/s{simpl}_cluster_{clusters}/l{ll}_{opts}_{sector}/statistics/generators.csv",
storage_units=RESULTS
+ "{interconnect}/figures/s{simpl}_cluster_{clusters}/l{ll}_{opts}_{sector}/statistics/storage_units.csv",
links=RESULTS
+ "{interconnect}/figures/s{simpl}_cluster_{clusters}/l{ll}_{opts}_{sector}/statistics/links.csv",
log:
"logs/plot_figures/{interconnect}_{simpl}_{clusters}_l{ll}_{opts}_{sector}.log",
threads: 1
Expand Down
7 changes: 1 addition & 6 deletions workflow/scripts/add_extra_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,13 +685,8 @@ def apply_max_annual_growth_rate(n, max_growth):
egs_gens = n.generators[n.generators["p_nom_extendable"] == True]
egs_gens = egs_gens.loc[egs_gens["carrier"].str.contains("EGS")]

all_carriers = (
set(elec_config["extendable_carriers"].get("Generator", []))
| set(elec_config["conventional_carriers"])
| set(elec_config["renewable_carriers"])
)
new_carriers = list(
all_carriers - set(n.generators.carrier.unique())
set(elec_config["extendable_carriers"].get("Generator", [])) - set(n.generators.carrier.unique())
| set(["nuclear"] if "nuclear" in elec_config["extendable_carriers"].get("Generator", []) else []),
)

Expand Down
22 changes: 21 additions & 1 deletion workflow/scripts/cluster_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ def weighting_for_country(n, 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.0 / w.max())).clip(lower=1.0).astype(int)


Expand Down Expand Up @@ -235,6 +235,26 @@ def fix_country_assignment_for_hac(n):
solver_name=solver_name,
)

# Potentiall remove buses and lines from these corner case counties from network
nc_set = set(n_clusters.index.get_level_values(0).unique())
bus_set = set(n.buses.country.unique())
countries_remove = list(bus_set - nc_set)
buses_remove = n.buses[n.buses.country.isin(countries_remove)]
if not buses_remove.empty:
logger.warning(f"Reconciling TAMU and ReEDS Topologies. \n Removing buses: {buses_remove.index}")
for c in n.one_port_components:
component = n.df(c)
rm = component[component.bus.isin(buses_remove.index)]
logger.warning(f"Removing {rm.shape} component {c}")
n.mremove(c, rm.index)
for c in ["Line", "Link"]:
component = n.df(c)
rm = component[component.bus0.isin(buses_remove.index) | component.bus1.isin(buses_remove.index)]
logger.warning(f"Removing {rm.shape} component {c}")
n.mremove(c, rm.index)
n.mremove("Bus", buses_remove.index)
n.determine_network_topology()

def busmap_for_country(x):
prefix = x.name[0] + x.name[1] + " "
logger.debug(f"Determining busmap for country {prefix[:-1]}")
Expand Down
5 changes: 3 additions & 2 deletions workflow/scripts/plot_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ def plot_regional_capacity_additions_bar(n, save):
Plot capacity evolution by NERC region in a stacked bar plot.
"""
data = get_statistics(n, "Optimal Capacity")
data.to_csv(f"{Path(save).parent}/bar_regional_capacity.csv")
data.to_csv(f"{Path(save).parent.parent}/statistics/bar_regional_capacity.csv")
plot_bar(data, n, save, "", "Capacity (GW)", is_capacity=True)


Expand All @@ -400,7 +400,7 @@ def plot_regional_production_bar(n, save):
Plot production evolution by NERC region in a stacked bar plot.
"""
data = get_statistics(n, "Supply")
data.to_csv(f"{Path(save).parent}/bar_regional_production.csv")
data.to_csv(f"{Path(save).parent.parent}/statistics/bar_regional_production.csv")
plot_bar(data, n, save, "", "Production (GWh)")


Expand Down Expand Up @@ -932,6 +932,7 @@ def plot_fuel_costs(
n.statistics().round(2).to_csv(snakemake.output.statistics_summary)
n.generators.to_csv(snakemake.output.generators)
n.storage_units.to_csv(snakemake.output.storage_units)
n.links.to_csv(snakemake.output.links)

# Panel Plots
plot_generator_data_panel(
Expand Down
47 changes: 30 additions & 17 deletions workflow/scripts/prepare_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import pypsa
from _helpers import (
configure_logging,
is_transport_model,
set_scenario_config,
update_config_from_wildcards,
)
Expand Down Expand Up @@ -133,9 +134,10 @@ def add_emission_prices(n, emission_prices={"co2": 0.0}, exclude_co2=False):
n.storage_units["marginal_cost"] += su_ep


def set_line_s_max_pu(n, s_max_pu=0.7):
n.lines["s_max_pu"] = s_max_pu
logger.info(f"N-1 security margin of lines set to {s_max_pu}")
def set_line_s_max_pu(n, transport_model, s_max_pu=0.7):
if not transport_model:
logger.info(f"N-1 security margin of lines set to {s_max_pu}")
n.lines["s_max_pu"] = s_max_pu


def set_transmission_limit(n, ll_type, factor):
Expand Down Expand Up @@ -163,9 +165,11 @@ def set_transmission_limit(n, ll_type, factor):
+ n.links.loc[dc_links, "p_nom"] @ n.links.loc[dc_links, col]
+ n.links.loc[ac_links_existing, "p_nom"] @ n.links.loc[ac_links_existing, col]
)
ref_dc = n.links.loc[dc_links, "p_nom"] @ n.links.loc[dc_links, col]

if factor == "opt" or float(factor) > 1.0:
# if opt allows expansion set respective lines/links to extendable
# all links prior to this point have extendable set to false
n.lines["s_nom_min"] = lines_s_nom
n.lines["s_nom_extendable"] = True

Expand All @@ -176,7 +180,14 @@ def set_transmission_limit(n, ll_type, factor):
n.links.loc[ac_links_exp, "p_nom_extendable"] = True
if factor != "opt":
con_type = "expansion_cost" if ll_type == "c" else "volume_expansion"
rhs = float(factor) * ref
if transport_model:
# Transport models have links split to existing and non-existing
# The global constraint applies to the p_nom_opt of extendable capacity
# thus we must only include the 'new' transmission capacity as reference
rhs = ((float(factor) - 1.0) * ref) + ref_dc
else:
rhs = float(factor) * ref

n.add(
"GlobalConstraint",
f"l{ll_type}_limit",
Expand Down Expand Up @@ -343,6 +354,8 @@ def set_line_nom_max(
configure_logging(snakemake)
set_scenario_config(snakemake)
update_config_from_wildcards(snakemake.config, snakemake.wildcards)
params = snakemake.params
transport_model = is_transport_model(params.transmission_network)

n = pypsa.Network(snakemake.input[0])
Nyears = n.snapshot_weightings.loc[n.investment_periods[0]].objective.sum() / 8760.0
Expand All @@ -353,17 +366,17 @@ def set_line_nom_max(
inv_per_time_weight = n.investment_periods.to_series().diff().shift(-1).ffill().fillna(1)
n.investment_period_weightings["years"] = inv_per_time_weight
# set Investment Period Objective weightings
social_discountrate = snakemake.params.costs["social_discount_rate"]
social_discountrate = params.costs["social_discount_rate"]
objective_w = get_investment_weighting(
n.investment_period_weightings["years"],
social_discountrate,
)
n.investment_period_weightings["objective"] = objective_w

set_line_s_max_pu(n, snakemake.params.lines["s_max_pu"])
set_line_s_max_pu(n, transport_model, params.lines["s_max_pu"])

# temporal averaging
time_resolution = snakemake.params.time_resolution
time_resolution = params.time_resolution
is_string = isinstance(time_resolution, str)
if is_string and time_resolution.lower().endswith("h"):
n = average_every_nhours(n, time_resolution)
Expand All @@ -375,28 +388,28 @@ def set_line_nom_max(
segments = int(time_resolution.lower().replace("seg", ""))
n = apply_time_segmentation(n, segments, solver_name)

if snakemake.params.co2limit_enable:
add_co2limit(n, snakemake.params.co2limit, Nyears)
if params.co2limit_enable:
add_co2limit(n, params.co2limit, Nyears)

if snakemake.params.gaslimit_enable:
add_gaslimit(n, snakemake.params.gaslimit, Nyears)
if params.gaslimit_enable:
add_gaslimit(n, params.gaslimit, Nyears)

emission_prices = snakemake.params.costs["emission_prices"]
emission_prices = params.costs["emission_prices"]
if emission_prices["enable"]:
add_emission_prices(
n,
dict(co2=snakemake.params.costs["emission_prices"]["co2"]),
dict(co2=params.costs["emission_prices"]["co2"]),
)

ll_type, factor = snakemake.wildcards.ll[0], snakemake.wildcards.ll[1:]
set_transmission_limit(n, ll_type, factor)

set_line_nom_max(
n,
s_nom_max_set=snakemake.params.lines.get("s_nom_max", np.inf),
p_nom_max_set=snakemake.params.links.get("p_nom_max", np.inf),
s_nom_max_ext=snakemake.params.lines.get("max_extension", np.inf),
p_nom_max_ext=snakemake.params.links.get("max_extension", np.inf),
s_nom_max_set=params.lines.get("s_nom_max", np.inf),
p_nom_max_set=params.links.get("p_nom_max", np.inf),
s_nom_max_ext=params.lines.get("max_extension", np.inf),
p_nom_max_ext=params.links.get("max_extension", np.inf),
)

n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
Expand Down
Loading

0 comments on commit 6d60201

Please # to comment.