Skip to content

Commit

Permalink
Merge pull request #478 from ktehranchi/kt/cutouts
Browse files Browse the repository at this point in the history
Refactor TCT, RPS opts; Adds renewable weather year param.
  • Loading branch information
ktehranchi authored Nov 25, 2024
2 parents a0d1dd9 + ad8e2d4 commit 1c56f4f
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 190 deletions.
2 changes: 1 addition & 1 deletion docs/source/configtables/opts.csv
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ Trigger, Description, Definition, Status
``SAFE``, Add a capacity reserve margin of a certain fraction above the peak demand to which renewable generators and storage do *not* contribute. Ignores network., ``solve_network`` `add_opts_constraints() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/solve_network.py#L73>`__,In active use
``SAFER``,Adds Regional Capacity Reserve Margin (SAFE) Constraints for defined region- set to a percentage above peak demand level for which renewables and storage do not contribute to. , ``solve_network``,In active use
``Ep``, Add cost for a carbon-dioxide price configured in ``costs: emission_prices: co2`` to ``marginal_cost`` of generators (other emission types listed in ``network.carriers`` possible as well), ``prepare_network``: `add_emission_prices() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L24>`_ and its `caller <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L158>`__, In active use
``CCL``,Add minimum or maximum levels of generator nominal capacity per carrier for individual countries. Each constraint can be designated for a specified planning horizon in multi-period models. Opts and path for agg_p_nom_minmax.csv must be defined, ``solve_network``, In active use
``TCT``,"Add minimum or maximum levels of generator nominal capacity per carrier(s), per region(s), per investment horizon. Opts and path for technology_capacity_targets.csv must be defined", ``solve_network``, In active use
``CH4L``,"Add an overall absolute gas limit. If configured in ``electricity: gaslimit`` it is given in MWh thermal, if a float is appended, the overall gaslimit is assumed to be given in TWh thermal (e.g. ``CH4L200`` limits gas dispatch to 200 TWh termal)", ``prepare_network``: ``add_gaslimit()``, In active use
2 changes: 1 addition & 1 deletion workflow/envs/environment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ dependencies:
- pip

- pypsa==0.30.2
- atlite==0.2.14
- atlite==0.3.0
- linopy==0.3.14

# Dependencies of the workflow itself
Expand Down
21 changes: 5 additions & 16 deletions workflow/repo_data/config/config.common.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
foresight: 'perfect'

# docs :
renewable:
onwind:
cutout: era5_2019
cutout: era5
resource:
method: wind
turbine: Vestas_V112_3MW
Expand All @@ -21,7 +20,7 @@ renewable:
clip_p_max_pu: 1.e-2
extendable: true
offwind:
cutout: era5_2019
cutout: era5
resource:
method: wind
turbine: NREL_ReferenceTurbine_2020ATB_5.5MW
Expand All @@ -39,7 +38,7 @@ renewable:
clip_p_max_pu: 1.e-2
extendable: true
offwind_floating:
cutout: era5_2019
cutout: era5
resource:
method: wind
turbine: NREL_ReferenceTurbine_2020ATB_15MW_offshore
Expand All @@ -58,7 +57,7 @@ renewable:
clip_p_max_pu: 1.e-2
extendable: true
solar:
cutout: era5_2019
cutout: era5
resource:
method: pv
panel: CSi
Expand All @@ -73,7 +72,7 @@ renewable:
clip_p_max_pu: 1.e-2
extendable: true
hydro:
cutout: era5_2019
cutout: era5
carriers: [ror, PHS, hydro]
PHS_max_hours: 6
resource:
Expand Down Expand Up @@ -120,16 +119,6 @@ atlite:
dx: 0.3
dy: 0.3

lines:
types: # All temporary values, need to be updated
115.: "Al/St 240/40 2-bundle 220.0"
138.: "Al/St 240/40 2-bundle 220.0"
161.: "Al/St 240/40 2-bundle 220.0"
230.: "Al/St 240/40 2-bundle 220.0"
345.: "Al/St 240/40 4-bundle 380.0"
500.: "Al/St 560/50 4-bundle 750.0"
765.: "Al/St 560/50 4-bundle 750.0"


lines:
types: #Temp values, replaced.
Expand Down
5 changes: 4 additions & 1 deletion workflow/repo_data/config/config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ model_topology:
enable:
build_cutout: false

renewable_weather_years: [2019]

snapshots:
start: "2019-01-01"
end: "2020-01-01"
Expand All @@ -46,7 +48,7 @@ electricity:
retirement: economic # "economic" or "technical"
SAFE_reservemargin: 0.14
regional_Co2_limits: 'config/policy_constraints/regional_Co2_limits.csv'
agg_p_nom_limits: 'config/policy_constraints/agg_p_nom_minmax.csv'
technology_capacity_targets: 'config/policy_constraints/technology_capacity_targets.csv'
portfolio_standards: 'config/policy_constraints/portfolio_standards.csv'
SAFE_regional_reservemargins: 'config/policy_constraints/SAFE_regional_prm.csv'
transmission_interface_limits: 'config/policy_constraints/transmission_interface_limits.csv'
Expand Down Expand Up @@ -77,6 +79,7 @@ electricity:
# docs :
conventional:
unit_commitment: false
must_run: false
dynamic_fuel_price:
enable: false
pudl: true
Expand Down
5 changes: 4 additions & 1 deletion workflow/repo_data/config/config.tutorial.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ model_topology:
enable:
build_cutout: false

renewable_weather_years: [2019]

snapshots:
start: "2019-01-01"
end: "2020-01-01"
Expand All @@ -46,7 +48,7 @@ electricity:
retirement: economic # "economic" or "technical"
SAFE_reservemargin: 0.14
regional_Co2_limits: 'config/policy_constraints/regional_Co2_limits.csv'
agg_p_nom_limits: 'config/policy_constraints/agg_p_nom_minmax.csv'
technology_capacity_targets: 'config/policy_constraints/technology_capacity_targets.csv'
portfolio_standards: 'config/policy_constraints/portfolio_standards.csv'
SAFE_regional_reservemargins: 'config/policy_constraints/SAFE_regional_prm.csv'
transmission_interface_limits: 'config/policy_constraints/transmission_interface_limits.csv'
Expand Down Expand Up @@ -77,6 +79,7 @@ electricity:
# docs :
conventional:
unit_commitment: false
must_run: false
dynamic_fuel_price:
enable: false
pudl: true
Expand Down

This file was deleted.

22 changes: 13 additions & 9 deletions workflow/rules/build_electricity.smk
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ if config["enable"].get("build_cutout", False):

rule build_cutout:
params:
snapshots=config["snapshots"],
cutouts=config["atlite"]["cutouts"],
interconnects=config["atlite"]["interconnects"],
snapshots=config_provider("snapshots"),
cutouts=config_provider("atlite", "cutouts"),
interconnects=config_provider("atlite", "interconnects"),
input:
regions_onshore=RESOURCES
+ "{interconnect}/Geospatial/country_shapes.geojson",
Expand Down Expand Up @@ -169,7 +169,6 @@ rule build_renewable_profiles:
renewable=config["renewable"],
snapshots=config["snapshots"],
input:
base_network=RESOURCES + "{interconnect}/elec_base_network.nc",
corine=ancient(
DATA
+ "copernicus/PROBAV_LC100_global_v3.0.1_2019-nrt_Discrete-Classification-map_USA_EPSG-4326.tif"
Expand All @@ -194,11 +193,16 @@ rule build_renewable_profiles:
if w.technology in ("onwind", "solar")
else RESOURCES + "{interconnect}/Geospatial/regions_offshore.geojson"
),
cutout=lambda w: "cutouts/"
+ CDIR
+ "{interconnect}_"
+ config["renewable"][w.technology]["cutout"]
+ ".nc",
cutout=lambda wildcards: expand(
"cutouts/"
+ CDIR
+ "{interconnect}_"
+ config["renewable"][wildcards.technology]["cutout"]
+ "_{renewable_weather_year}"
+ ".nc",
renewable_weather_year=config["renewable_weather_years"],
interconnect=config["scenario"]["interconnect"],
),
output:
profile=RESOURCES + "{interconnect}/profile_{technology}.nc",
availability=RESULTS + "{interconnect}/land_use_availability_{technology}.png",
Expand Down
5 changes: 2 additions & 3 deletions workflow/scripts/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ def configure_logging(snakemake, skip_handlers=False):
skip_handlers : True | False (default)
Do (not) skip the default handlers created for redirecting output to STDERR and file.
"""

import logging

kwargs = snakemake.config.get("logging", dict()).copy()
Expand Down Expand Up @@ -671,8 +670,8 @@ def update_config_from_wildcards(config, w, inplace=True):
if "A" in opts:
config["sector"]["agriculture"] = True

if "CCL" in opts:
config["solving"]["constraints"]["CCL"] = True
if "TCT" in opts:
config["solving"]["constraints"]["TCT"] = True

eq_value = get_opt(opts, r"^EQ+\d*\.?\d+(c|)")
for o in opts:
Expand Down
6 changes: 4 additions & 2 deletions workflow/scripts/add_electricity.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,9 @@ def load_powerplants(


def match_nearest_bus(plants_subset, buses_subset):
"""Assign the nearest bus to each plant in the given subsets."""
"""
Assign the nearest bus to each plant in the given subsets.
"""
if plants_subset.empty or buses_subset.empty:
return plants_subset

Expand Down Expand Up @@ -866,7 +868,7 @@ def main(snakemake):
n.snapshots,
)

if params.conventional["must_run"]:
if params.conventional.get("must_run", False):
# TODO (@ktehranchi): In the future the plants that are must-run should not be clustered and instead retire according to lifetime
apply_must_run_ratings(
n,
Expand Down
9 changes: 6 additions & 3 deletions workflow/scripts/build_cutout.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
import geopandas as gpd
import pandas as pd
from _helpers import configure_logging, get_snapshots
from pandas import Timestamp

logger = logging.getLogger(__name__)

Expand All @@ -106,9 +107,11 @@
configure_logging(snakemake)

# data set and temporal patameters
cutout_params = snakemake.params.cutouts[snakemake.wildcards.cutout]
snapshots = get_snapshots(snakemake.params.snapshots)
time = [snapshots[0], snapshots[-1]]
module, year = snakemake.wildcards.cutout.split("_")
cutout_params = {"module": module}

# Construct the time range based on the year
time = [Timestamp(f"{year}-01-01 00:00:00"), Timestamp(f"{year}-12-31 23:00:00")]
cutout_params["time"] = slice(*cutout_params.get("time", time))

# geographical extent parameters
Expand Down
5 changes: 4 additions & 1 deletion workflow/scripts/build_renewable_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ def plot_data(data):
client = None

sns = get_snapshots(snakemake.params.snapshots)
cutout = atlite.Cutout(snakemake.input.cutout).sel(time=sns)
logger.info(f'using cutout "{snakemake.input.cutout}"')
cutout = atlite.Cutout(snakemake.input.cutout[0]).sel(
time=sns,
) # Patch fix with [0] move expand in snakemake rule to add_elec for multiple cutouts

regions = gpd.read_file(snakemake.input.regions)

Expand Down
Loading

0 comments on commit 1c56f4f

Please sign in to comment.