diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index 6eb9113e..2e716066 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -18,7 +18,7 @@ scenario: clusters: - 5 sector_opts: - - 8760H-T-H-B-I-A-dist1 + - 8760h-T-H-B-I-A-dist1 planning_horizons: - 2030 - 2040 diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 6c63abda..d67e2fa2 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -178,6 +178,15 @@ def sanitize_carriers(n, config): n.carriers["color"] = n.carriers.color.where(n.carriers.color != "", colors) +def sanitize_locations(n): + n.buses["x"] = n.buses.x.where(n.buses.x != 0, n.buses.location.map(n.buses.x)) + n.buses["y"] = n.buses.y.where(n.buses.y != 0, n.buses.location.map(n.buses.y)) + n.buses["country"] = n.buses.country.where( + n.buses.country.ne("") & n.buses.country.notnull(), + n.buses.location.map(n.buses.country), + ) + + def add_co2_emissions(n, costs, carriers): """ Add CO2 emissions to the network's carriers attribute. diff --git a/scripts/add_extra_components.py b/scripts/add_extra_components.py index e00e1e5f..731e36be 100644 --- a/scripts/add_extra_components.py +++ b/scripts/add_extra_components.py @@ -56,7 +56,7 @@ import numpy as np import pandas as pd import pypsa from _helpers import configure_logging -from add_electricity import load_costs, sanitize_carriers +from add_electricity import load_costs, sanitize_carriers, sanitize_locations idx = pd.IndexSlice @@ -100,10 +100,9 @@ def attach_stores(n, costs, extendable_carriers): n.madd("Carrier", carriers) buses_i = n.buses.index - bus_sub_dict = {k: n.buses[k].values for k in ["x", "y", "country"]} if "H2" in carriers: - h2_buses_i = n.madd("Bus", buses_i + " H2", carrier="H2", **bus_sub_dict) + h2_buses_i = n.madd("Bus", buses_i + " H2", carrier="H2", location=buses_i) n.madd( "Store", @@ -143,7 +142,7 @@ def attach_stores(n, costs, extendable_carriers): if "battery" in carriers: b_buses_i = n.madd( - "Bus", buses_i + " battery", carrier="battery", **bus_sub_dict + "Bus", buses_i + " battery", carrier="battery", location=buses_i ) n.madd( @@ -246,6 +245,7 @@ if __name__ == "__main__": attach_hydrogen_pipelines(n, costs, extendable_carriers) sanitize_carriers(n, snakemake.config) + sanitize_locations(n) n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) n.export_to_netcdf(snakemake.output[0]) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index 0fab5367..76d8099c 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -507,7 +507,7 @@ def calculate_weighted_prices(n, label, weighted_prices): if carrier in ["H2", "gas"]: load = pd.DataFrame(index=n.snapshots, columns=buses, data=0.0) else: - load = n.loads_t.p_set[buses] + load = n.loads_t.p_set[buses.intersection(n.loads.index)] for tech in value: names = n.links.index[n.links.index.to_series().str[-len(tech) :] == tech] @@ -560,7 +560,10 @@ def calculate_market_values(n, label, market_values): ) revenue = dispatch * n.buses_t.marginal_price[buses] - market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() + if total_dispatch := dispatch.sum().sum(): + market_values.at[tech, label] = revenue.sum().sum() / total_dispatch + else: + market_values.at[tech, label] = np.nan ## Now do market value of links ## @@ -583,7 +586,10 @@ def calculate_market_values(n, label, market_values): revenue = dispatch * n.buses_t.marginal_price[buses] - market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() + if total_dispatch := dispatch.sum().sum(): + market_values.at[tech, label] = revenue.sum().sum() / total_dispatch + else: + market_values.at[tech, label] = np.nan return market_values diff --git a/scripts/make_summary_perfect.py b/scripts/make_summary_perfect.py index 555e5da5..d401b28e 100644 --- a/scripts/make_summary_perfect.py +++ b/scripts/make_summary_perfect.py @@ -265,7 +265,7 @@ def calculate_energy(n, label, energy): totals[no_bus] = float( n.component_attrs[c.name].loc["p" + port, "default"] ) - c_energies -= totals.groupby(c.df.carrier, axis=1).sum() + c_energies -= totals.T.groupby(c.df.carrier).sum().T c_energies = pd.concat([c_energies.T], keys=[c.list_name]) @@ -376,9 +376,8 @@ def calculate_supply_energy(n, label, supply_energy): .groupby(level=0) .sum() .multiply(c.df.loc[items, "sign"]) - .groupby(c.df.loc[items, "carrier"], axis=1) + .T.groupby(c.df.loc[items, "carrier"]) .sum() - .T ) s = pd.concat([s], keys=[c.list_name]) s = pd.concat([s], keys=[i]) @@ -525,9 +524,12 @@ def calculate_weighted_prices(n, label, weighted_prices): # stores[stores > 0.] = 0. # load += -stores - weighted_prices.loc[carrier, label] = ( - load * n.buses_t.marginal_price[buses] - ).sum().sum() / load.sum().sum() + if total_load := load.sum().sum(): + weighted_prices.loc[carrier, label] = ( + load * n.buses_t.marginal_price[buses] + ).sum().sum() / total_load + else: + weighted_prices.loc[carrier, label] = np.nan if carrier[:5] == "space": print(load * n.buses_t.marginal_price[buses]) @@ -562,7 +564,10 @@ def calculate_market_values(n, label, market_values): revenue = dispatch * n.buses_t.marginal_price[buses] - market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() + if total_dispatch := dispatch.sum().sum(): + market_values.at[tech, label] = revenue.sum().sum() / total_dispatch + else: + market_values.at[tech, label] = np.nan ## Now do market value of links ## @@ -585,7 +590,10 @@ def calculate_market_values(n, label, market_values): revenue = dispatch * n.buses_t.marginal_price[buses] - market_values.at[tech, label] = revenue.sum().sum() / dispatch.sum().sum() + if total_dispatch := dispatch.sum().sum(): + market_values.at[tech, label] = revenue.sum().sum() / total_dispatch + else: + market_values.at[tech, label] = np.nan return market_values diff --git a/scripts/plot_hydrogen_network.py b/scripts/plot_hydrogen_network.py index a1183311..95741170 100644 --- a/scripts/plot_hydrogen_network.py +++ b/scripts/plot_hydrogen_network.py @@ -36,7 +36,9 @@ def group_pipes(df, drop_direction=False): lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}", axis=1, ) - return df.groupby(level=0).agg({"p_nom_opt": sum, "bus0": "first", "bus1": "first"}) + return df.groupby(level=0).agg( + {"p_nom_opt": "sum", "bus0": "first", "bus1": "first"} + ) def plot_h2_map(n, regions): diff --git a/scripts/prepare_perfect_foresight.py b/scripts/prepare_perfect_foresight.py index 278472f6..3d72cd8c 100644 --- a/scripts/prepare_perfect_foresight.py +++ b/scripts/prepare_perfect_foresight.py @@ -221,7 +221,7 @@ def concat_networks(years): # set investment periods n.investment_periods = n.snapshots.levels[0] # weighting of the investment period -> assuming last period same weighting as the period before - time_w = n.investment_periods.to_series().diff().shift(-1).fillna(method="ffill") + time_w = n.investment_periods.to_series().diff().shift(-1).ffill() n.investment_period_weightings["years"] = time_w # set objective weightings objective_w = get_investment_weighting( diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index f7e91605..5abd2ce6 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -19,7 +19,7 @@ import pandas as pd import pypsa import xarray as xr from _helpers import update_config_with_sector_opts -from add_electricity import calculate_annuity, sanitize_carriers +from add_electricity import calculate_annuity, sanitize_carriers, sanitize_locations from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2 from networkx.algorithms import complement from networkx.algorithms.connectivity.edge_augmentation import k_edge_augmentation @@ -546,6 +546,14 @@ def patch_electricity_network(n): n.loads_t.p_set.rename(lambda x: x.strip(), axis=1, inplace=True) +def add_eu_bus(n, x=-5.5, y=46): + """ + Add EU bus to the network. + """ + n.add("Bus", "EU", location="EU", x=x, y=y, carrier="none") + n.add("Carrier", "none") + + def add_co2_tracking(n, costs, options): # minus sign because opposite to how fossil fuels used: # CH4 burning puts CH4 down, atmosphere up @@ -1005,6 +1013,7 @@ def insert_electricity_distribution_grid(n, costs): "Store", nodes + " home battery", bus=nodes + " home battery", + location=nodes, e_cyclic=True, e_nom_extendable=True, carrier="home battery", @@ -3527,8 +3536,8 @@ def lossy_bidirectional_links(n, carrier, efficiencies={}): rev_links["reversed"] = True rev_links.index = rev_links.index.map(lambda x: x + "-reversed") + n.links["reversed"] = False n.links = pd.concat([n.links, rev_links], sort=False) - n.links["reversed"] = n.links["reversed"].fillna(False) n.links["length_original"] = n.links["length_original"].fillna(n.links.length) # do compression losses after concatenation to take electricity consumption at bus0 in either direction @@ -3594,6 +3603,8 @@ if __name__ == "__main__": for carrier in conventional: add_carrier_buses(n, carrier) + add_eu_bus(n) + add_co2_tracking(n, costs, options) add_generation(n, costs) @@ -3733,5 +3744,6 @@ if __name__ == "__main__": n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards))) sanitize_carriers(n, snakemake.config) + sanitize_locations(n) n.export_to_netcdf(snakemake.output[0])