Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve consistency of nuclear modelling #1540

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ include: "rules/development.smk"

if config["foresight"] == "overnight":

configfile: "config/config.default.overnight.yaml"
include: "rules/solve_overnight.smk"


Expand Down
14 changes: 14 additions & 0 deletions config/config.default.overnight.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-FileCopyrightText: Contributors to PyPSA-Eur <https://github.com/pypsa/pypsa-eur>
#
# SPDX-License-Identifier: CC0-1.0

pypsa_eur:
Generator:
- onwind
- offwind-ac
- offwind-dc
- offwind-float
- solar-hsat
- solar
- ror
- nuclear
1 change: 0 additions & 1 deletion config/config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ pypsa_eur:
- solar-hsat
- solar
- ror
- nuclear
StorageUnit:
- PHS
- hydro
Expand Down
1 change: 1 addition & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Upcoming Release
- Added option to specify the cutout directory in the configuration file. This allows to the user to specify the directory where the cutouts are stored. Use it by setting ``atlite: cutout_directory:`` in the configuration file. (https://github.com/PyPSA/pypsa-eur/pull/1515)

- Bug fix: Added setting ``run: use_shadow_directory:`` (default: ``true``) which sets the ``shadow`` parameter of the snakemake workflow. Configuring to ``true`` sets snakemake ``shadow`` parameter to ``shalloow``, ``false`` to `Ǹone``. Should be set to ``false`` for those cases, where snakemake has an issue with finding missing input/output files in solving rules.
- Improve consistency of nuclear modelling (https://github.com/PyPSA/pypsa-eur/pull/1540).

PyPSA-Eur v2025.01.0 (24th January 2025)
========================================
Expand Down
14 changes: 0 additions & 14 deletions rules/build_electricity.smk
Original file line number Diff line number Diff line change
Expand Up @@ -625,20 +625,6 @@ def input_profile_tech(w):
}


def input_conventional(w):
carriers = [
*config_provider("electricity", "conventional_carriers")(w),
*config_provider("electricity", "extendable_carriers", "Generator")(w),
]
return {
f"conventional_{carrier}_{attr}": fn
for carrier, d in config_provider("conventional", default={})(w).items()
if carrier in carriers
for attr, fn in d.items()
if str(fn).startswith("data/")
}


rule add_electricity:
params:
line_length_factor=config_provider("lines", "length_factor"),
Expand Down
14 changes: 14 additions & 0 deletions rules/common.smk
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,17 @@ def solved_previous_horizon(w):
+ planning_horizon_p
+ ".nc"
)


def input_conventional(w):
carriers = [
*config_provider("electricity", "conventional_carriers")(w),
*config_provider("electricity", "extendable_carriers", "Generator")(w),
]
return {
f"conventional_{carrier}_{attr}": fn
for carrier, d in config_provider("conventional", default={})(w).items()
if carrier in carriers
for attr, fn in d.items()
if str(fn).startswith("data/")
}
3 changes: 3 additions & 0 deletions rules/solve_myopic.smk
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ rule add_existing_baseyear:
costs=config_provider("costs"),
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
energy_totals_year=config_provider("energy", "energy_totals_year"),
conventional=config_provider("conventional"),
conventional_carriers=config_provider("electricity","conventional_carriers"),
input:
unpack(input_conventional),
network=resources(
"networks/base_s_{clusters}_{opts}_{sector_opts}_{planning_horizons}.nc"
),
Expand Down
3 changes: 3 additions & 0 deletions rules/solve_perfect.smk
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ rule add_existing_baseyear:
costs=config_provider("costs"),
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
energy_totals_year=config_provider("energy", "energy_totals_year"),
conventional=config_provider("conventional"),
conventional_carriers=config_provider("electricity","conventional_carriers"),
input:
unpack(input_conventional),
network=resources(
"networks/base_s_{clusters}_{opts}_{sector_opts}_{planning_horizons}.nc"
),
Expand Down
2 changes: 1 addition & 1 deletion scripts/add_electricity.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ def attach_conventional_generators(
{attr: n.generators.loc[idx].bus.map(bus_values).dropna()}
)
else:
# Single value affecting all generators of technology k indiscriminantely of country
# Single value affecting all generators of technology k indiscriminately of country
n.generators.loc[idx, attr] = values


Expand Down
37 changes: 35 additions & 2 deletions scripts/add_existing_baseyear.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def add_existing_renewables(df_agg, costs):
df_agg.at[name, "bus"] = node


def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, baseyear):
def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, baseyear, conventional_carriers, conventional_params, conventional_inputs):
"""
Parameters
----------
Expand All @@ -131,6 +131,7 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas
costs :
to read lifetime to estimate YearDecomissioning
baseyear : int
conventional_params:
"""
logger.debug(
f"Adding power capacities installed before {baseyear} from"
Expand Down Expand Up @@ -359,6 +360,28 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas
efficiency2=costs.at[key, "efficiency-heat"],
lifetime=lifetime_assets.loc[new_capacity.index],
)

for carrier_i in set(conventional_params) & set(conventional_carriers):
# Links with technology affected
idx = n.links.query("carrier == @carrier_i").index

for attr in list(set(conventional_params[carrier_i]) & set(n.links)):
values = conventional_params[carrier_i][attr]

if f"conventional_{carrier_i}_{attr}" in conventional_inputs:
# Values affecting links of technology k country-specific
# First map link buses to countries; then map countries to p_max_pu
values = pd.read_csv(
snakemake.input[f"conventional_{carrier_i}_{attr}"], index_col=0
).iloc[:, 0]
bus_values = n.buses.country.map(values)
n.links.update(
{attr: n.links.loc[idx].bus1.map(bus_values).dropna()}
)
else:
# Single value affecting all links of technology k indiscriminately of country
n.links.loc[idx, attr] = values

# check if existing capacities are larger than technical potential
existing_large = n.generators[
n.generators["p_nom_min"] > n.generators["p_nom_max"]
Expand Down Expand Up @@ -660,8 +683,18 @@ def add_heating_capacities_installed_before_baseyear(

grouping_years_power = snakemake.params.existing_capacities["grouping_years_power"]
grouping_years_heat = snakemake.params.existing_capacities["grouping_years_heat"]
conventional_inputs = {
k: v for k, v in snakemake.input.items() if k.startswith("conventional_")
}

add_power_capacities_installed_before_baseyear(
n, grouping_years_power, costs, baseyear
n,
grouping_years_power,
costs,
baseyear,
snakemake.params.conventional_carriers,
snakemake.params.conventional,
conventional_inputs
)

if options["heating"]:
Expand Down