diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 7e964a44..c5f9ecf3 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -250,13 +250,14 @@ rule build_renewable_profiles: script: "../scripts/build_renewable_profiles.py" + rule build_monthly_prices: input: co2_price_raw="data/validation/emission-spot-primary-market-auction-report-2019-data.xls", - fuel_price_raw="data/validation/energy-price-trends-xlsx-5619002.xlsx" + fuel_price_raw="data/validation/energy-price-trends-xlsx-5619002.xlsx", output: co2_price="data/validation/CO2_price_2019.csv", - fuel_price="data/validation/monthly_fuel_price.csv" + fuel_price="data/validation/monthly_fuel_price.csv", log: LOGS + "build_monthly_prices.log", threads: 1 @@ -267,6 +268,7 @@ rule build_monthly_prices: script: "../scripts/build_monthly_prices.py" + rule build_hydro_profile: params: hydro=config["renewable"]["hydro"], diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 3dd7c8ae..e6e2c4e3 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -382,17 +382,14 @@ def attach_conventional_generators( .rename(index=lambda s: "C" + str(s)) ) ppl["efficiency"] = ppl.efficiency.fillna(ppl.efficiency_r) - - fuel_price = (fuel_price.assign(OCGT=fuel_price['gas'], - CCGT=fuel_price['gas']) - .drop("gas", axis=1)) + fuel_price = fuel_price.assign(OCGT=fuel_price["gas"], CCGT=fuel_price["gas"]).drop( + "gas", axis=1 + ) fuel_price = fuel_price.reindex(ppl.carrier, axis=1) fuel_price.fillna(costs.fuel, inplace=True) fuel_price.columns = ppl.index - marginal_cost = ( - (fuel_price.div(ppl.efficiency)).add(ppl.carrier.map(costs.VOM)) - ) + marginal_cost = (fuel_price.div(ppl.efficiency)).add(ppl.carrier.map(costs.VOM)) logger.info( "Adding {} generators with capacities [GW] \n{}".format( @@ -715,7 +712,8 @@ def add_nice_carrier_names(n, config): logger.warning(f"tech_colors for carriers {missing_i} not defined in config.") n.carriers["color"] = colors -#%% + +# %% if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -753,11 +751,9 @@ if __name__ == "__main__": conventional_inputs = { k: v for k, v in snakemake.input.items() if k.startswith("conventional_") } - - m_fuel_price = pd.read_csv(snakemake.input.fuel_price, - index_col=[0], header=[0]) - m_fuel_price.index = pd.date_range(start='2019-01-01', end='2019-12-01', - freq='MS') + + m_fuel_price = pd.read_csv(snakemake.input.fuel_price, index_col=[0], header=[0]) + m_fuel_price.index = pd.date_range(start="2019-01-01", end="2019-12-01", freq="MS") fuel_price = m_fuel_price.reindex(n.snapshots).fillna(method="ffill") attach_conventional_generators( n, diff --git a/scripts/build_monthly_prices.py b/scripts/build_monthly_prices.py index 435f274b..baf15b4f 100644 --- a/scripts/build_monthly_prices.py +++ b/scripts/build_monthly_prices.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ -Created on Tue May 16 10:37:35 2023 +Created on Tue May 16 10:37:35 2023. This script extracts monthly fuel prices of oil, gas, coal and lignite, as well as CO2 prices @@ -40,8 +40,9 @@ Data sources: Data was accessed at 16.5.2023 """ -import pandas as pd import logging + +import pandas as pd from _helpers import configure_logging logger = logging.getLogger(__name__) @@ -49,69 +50,75 @@ logger = logging.getLogger(__name__) validation_year = 2019 # sheet names to pypsa syntax -sheet_name_map = {"5.1 Hard coal and lignite": "coal", - "5.2 Mineral oil" : "oil", - "5.3.1 Natural gas - indices":"gas"} +sheet_name_map = { + "5.1 Hard coal and lignite": "coal", + "5.2 Mineral oil": "oil", + "5.3.1 Natural gas - indices": "gas", +} # keywords in datasheet -keywords = {"coal": " GP09-051 Hard coal", - "lignite": " GP09-052 Lignite and lignite briquettes", - "oil": " GP09-0610 10 Mineral oil, crude", - "gas": "GP09-062 Natural gas" - } +keywords = { + "coal": " GP09-051 Hard coal", + "lignite": " GP09-052 Lignite and lignite briquettes", + "oil": " GP09-0610 10 Mineral oil, crude", + "gas": "GP09-062 Natural gas", +} # import fuel price 2015 in Eur/MWh # source for coal, oil, gas, Agora, slide 24 [2] # source lignite, price for 2020, scaled by price index, ENTSO-E [3] -price_2015 = {"coal": 8.3, - "oil": 30.6, - "gas": 20.6, - "lignite": 3.8} # 2020 3.96/1.04 +price_2015 = {"coal": 8.3, "oil": 30.6, "gas": 20.6, "lignite": 3.8} # 2020 3.96/1.04 + def get_fuel_price(): - fuel_price = pd.read_excel(snakemake.input.fuel_price_raw, - sheet_name=list(sheet_name_map.keys())) - fuel_price = {sheet_name_map[key]: value for key, value in fuel_price.items() - if key in sheet_name_map} + fuel_price = pd.read_excel( + snakemake.input.fuel_price_raw, sheet_name=list(sheet_name_map.keys()) + ) + fuel_price = { + sheet_name_map[key]: value + for key, value in fuel_price.items() + if key in sheet_name_map + } # lignite and hard coal are on the same sheet fuel_price["lignite"] = fuel_price["coal"] - + def extract_df(sheet, keyword): # Create a DatetimeIndex for the first day of each month of a given year - dti = pd.date_range(start=f'{validation_year}-01-01', - end=f'{validation_year}-12-01', freq='MS') + dti = pd.date_range( + start=f"{validation_year}-01-01", end=f"{validation_year}-12-01", freq="MS" + ) # Extract month names month_list = dti.month start = fuel_price[sheet].index[(fuel_price[sheet] == keyword).any(axis=1)] - df = fuel_price[sheet].loc[start[0]:start[0]+18,:] + df = fuel_price[sheet].loc[start[0] : start[0] + 18, :] df.dropna(axis=0, inplace=True) - df.iloc[:,0] = df.iloc[:,0].apply(lambda x: int(x.replace(" ...", ""))) + df.iloc[:, 0] = df.iloc[:, 0].apply(lambda x: int(x.replace(" ...", ""))) df.set_index(df.columns[0], inplace=True) df = df.iloc[:, :12] df.columns = month_list return df - + m_price = {} for carrier, keyword in keywords.items(): df = extract_df(carrier, keyword).loc[validation_year] - m_price[carrier] = df.mul(price_2015[carrier]/100) - + m_price[carrier] = df.mul(price_2015[carrier] / 100) + pd.concat(m_price, axis=1).to_csv(snakemake.output.fuel_price) + def get_co2_price(): # emission price - CO2_price = pd.read_excel(snakemake.input.co2_price_raw, index_col=1, - header=5) + CO2_price = pd.read_excel(snakemake.input.co2_price_raw, index_col=1, header=5) CO2_price["Auction Price €/tCO2"].to_csv(snakemake.output.co2_price) if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake + snakemake = mock_snakemake("build_monthly_prices") - + configure_logging(snakemake) - + get_fuel_price() get_co2_price() - diff --git a/scripts/prepare_network.py b/scripts/prepare_network.py index 58ee94d0..4217ba10 100755 --- a/scripts/prepare_network.py +++ b/scripts/prepare_network.py @@ -106,17 +106,19 @@ def add_emission_prices(n, emission_prices={"co2": 0.0}, exclude_co2=False): n.generators["marginal_cost"] += gen_ep su_ep = n.storage_units.carrier.map(ep) / n.storage_units.efficiency_dispatch n.storage_units["marginal_cost"] += su_ep - + def add_emission_prices_t(n): - co2_price = pd.read_csv(snakemake.input.co2_price, index_col=0, - parse_dates=True) + co2_price = pd.read_csv(snakemake.input.co2_price, index_col=0, parse_dates=True) co2_price = co2_price[~co2_price.index.duplicated()] - co2_price = co2_price.reindex(n.snapshots).fillna(method="ffill").fillna(method="bfill") + co2_price = ( + co2_price.reindex(n.snapshots).fillna(method="ffill").fillna(method="bfill") + ) emissions = n.generators.carrier.map(n.carriers.co2_emissions) - co2_cost = (expand_series(emissions, n.snapshots).T - .mul(co2_price.iloc[:,0], axis=0)) - n.generators_t.marginal_cost += (co2_cost.reindex(columns=n.generators_t.marginal_cost.columns)) + co2_cost = expand_series(emissions, n.snapshots).T.mul(co2_price.iloc[:, 0], axis=0) + n.generators_t.marginal_cost += co2_cost.reindex( + columns=n.generators_t.marginal_cost.columns + ) def set_line_s_max_pu(n, s_max_pu=0.7): @@ -250,7 +252,7 @@ def set_line_nom_max(n, s_nom_max_set=np.inf, p_nom_max_set=np.inf): n.links.p_nom_max.clip(upper=p_nom_max_set, inplace=True) -#%% +# %% if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -338,7 +340,9 @@ if __name__ == "__main__": add_emission_prices(n, snakemake.params.costs["emission_prices"]) break if "ept" in o: - logger.info("Setting time dependent emission prices according spot market price") + logger.info( + "Setting time dependent emission prices according spot market price" + ) add_emission_prices_t(n) ll_type, factor = snakemake.wildcards.ll[0], snakemake.wildcards.ll[1:] diff --git a/scripts/solve_network.py b/scripts/solve_network.py index c6e170e9..8f1b57b8 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -149,7 +149,6 @@ def prepare_network( planning_horizons=None, co2_sequestration_potential=None, ): - if snakemake.config["existing_capacities"]["unit_commitment"]: add_unit_commitment(n, snakemake.input.unit_commitment_params)