diff --git a/config.default.yaml b/config.default.yaml index ab0e2f8e..edd88567 100755 --- a/config.default.yaml +++ b/config.default.yaml @@ -64,7 +64,30 @@ electricity: powerplants_filter: (DateOut >= 2022 or DateOut != DateOut) # use pandas query strings here, e.g. Country in ['Germany'] custom_powerplants: false - conventional_carriers: [nuclear, oil, OCGT, CCGT, coal, lignite, geothermal, biomass] + conventional_carriers: + technologies: [nuclear, oil, OCGT, CCGT, coal, lignite, geothermal, biomass] + # Limit energy availability from these sources -> p_max_pu + # syntax: + # : or : + energy_availability_factors: + # From IAEA + # https://pris.iaea.org/PRIS/WorldStatistics/ThreeYrsEnergyAvailabilityFactor.aspx (2022-04-08) + nuclear: + BE: 0.65 + BG: 0.89 + CZ: 0.82 + FI: 0.92 + FR: 0.70 + DE: 0.88 + HU: 0.90 + NL: 0.86 + RO: 0.92 + SK: 0.89 + SI: 0.94 + ES: 0.89 + SE: 0.82 + CH: 0.86 + GB: 0.67 renewable_capacities_from_OPSD: [] # onwind, offwind, solar estimate_renewable_capacities: diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 97a24291..f07176ad 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -25,7 +25,10 @@ Energy Security Release (April 2022) * Add operational reserve margin constraint analogous to `GenX implementation `_. Can be activated with config setting ``electricity: operational_reserve:``. -* Add function to add global constraint on use of gas in :mod:`prepare_network`. This can be activated with `electricity: gaslimit:` given in MWh. +* Add function to add global constraint on use of gas in :mod:`prepare_network`. This can be activated with `electricity: gaslimit:` given in MWh. + +* Add configuration option to implement Energy Availability Factors (EAFs) for conventional generation technologies. +* Implement country-specific EAFs for nuclear power plants based on IAEA 2018-2020 reported country averages. * The powerplants that have been shut down before 2021 are filtered out. diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 961b87dc..ab3aa321 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -290,8 +290,9 @@ def attach_wind_and_solar(n, costs, input_profiles, technologies, line_length_fa p_max_pu=ds['profile'].transpose('time', 'bus').to_pandas()) -def attach_conventional_generators(n, costs, ppl, carriers): +def attach_conventional_generators(n, costs, ppl, conventional_carriers): + carriers = conventional_carriers["technologies"] _add_missing_carriers_from_costs(n, costs, carriers) ppl = (ppl.query('carrier in @carriers').join(costs, on='carrier') @@ -309,6 +310,22 @@ def attach_conventional_generators(n, costs, ppl, carriers): capital_cost=0) logger.warning(f'Capital costs for conventional generators put to 0 EUR/MW.') + + for k,v in conventional_carriers["energy_availability_factors"].items(): + + # Generators with technology affected + idx = n.generators.query("carrier == @k").index + + if isinstance(v, float): + # Single value affecting all generators of technology k indiscriminantely of country + n.generators.loc[idx, "p_max_pu"] = v + elif isinstance(v, dict): + v = pd.Series(v) + + # Values affecting generators of technology k country-specific + # First map generator buses to countries; then map countries to p_max_pu + n.generators["p_max_pu"] = n.generators.loc[idx]["bus"].replace(n.buses["country"]).replace(v) + def attach_hydro(n, costs, ppl, profile_hydro, hydro_capacities, carriers, **config): @@ -556,8 +573,7 @@ if __name__ == "__main__": update_transmission_costs(n, costs, snakemake.config['lines']['length_factor']) - carriers = snakemake.config['electricity']['conventional_carriers'] - attach_conventional_generators(n, costs, ppl, carriers) + attach_conventional_generators(n, costs, ppl, snakemake.config["electricity"]["conventional_carriers"]) carriers = snakemake.config['renewable'] attach_wind_and_solar(n, costs, snakemake.input, carriers, snakemake.config['lines']['length_factor'])