Merge branch 'master' into fix/deprecation-warning-pandas-1.4

This commit is contained in:
Fabian Hofmann 2023-02-07 11:00:02 +01:00 committed by GitHub
commit f94be5c2f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 109 additions and 77 deletions

View File

@ -5,7 +5,7 @@ exclude: "^LICENSES"
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0 rev: v4.4.0
hooks: hooks:
- id: check-merge-conflict - id: check-merge-conflict
- id: end-of-file-fixer - id: end-of-file-fixer
@ -17,7 +17,7 @@ repos:
# Sort package imports alphabetically # Sort package imports alphabetically
- repo: https://github.com/PyCQA/isort - repo: https://github.com/PyCQA/isort
rev: 5.10.1 rev: 5.11.4
hooks: hooks:
- id: isort - id: isort
args: ["--profile", "black", "--filter-files"] args: ["--profile", "black", "--filter-files"]
@ -30,7 +30,7 @@ repos:
# Find common spelling mistakes in comments and docstrings # Find common spelling mistakes in comments and docstrings
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.2.1 rev: v2.2.2
hooks: hooks:
- id: codespell - id: codespell
args: ['--ignore-regex="(\b[A-Z]+\b)"', '--ignore-words-list=fom'] # Ignore capital case words, e.g. country codes args: ['--ignore-regex="(\b[A-Z]+\b)"', '--ignore-words-list=fom'] # Ignore capital case words, e.g. country codes
@ -39,19 +39,19 @@ repos:
# Make docstrings PEP 257 compliant # Make docstrings PEP 257 compliant
- repo: https://github.com/PyCQA/docformatter - repo: https://github.com/PyCQA/docformatter
rev: v1.5.0 rev: v1.6.0.rc1
hooks: hooks:
- id: docformatter - id: docformatter
args: ["--in-place", "--make-summary-multi-line", "--pre-summary-newline"] args: ["--in-place", "--make-summary-multi-line", "--pre-summary-newline"]
- repo: https://github.com/keewis/blackdoc - repo: https://github.com/keewis/blackdoc
rev: v0.3.7 rev: v0.3.8
hooks: hooks:
- id: blackdoc - id: blackdoc
# Formatting with "black" coding style # Formatting with "black" coding style
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 22.8.0 rev: 22.12.0
hooks: hooks:
# Format Python files # Format Python files
- id: black - id: black
@ -67,14 +67,14 @@ repos:
# Do YAML formatting (before the linter checks it for misses) # Do YAML formatting (before the linter checks it for misses)
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.4.0 rev: v2.6.0
hooks: hooks:
- id: pretty-format-yaml - id: pretty-format-yaml
args: [--autofix, --indent, "2", --preserve-quotes] args: [--autofix, --indent, "2", --preserve-quotes]
# Format Snakemake rule / workflow files # Format Snakemake rule / workflow files
- repo: https://github.com/snakemake/snakefmt - repo: https://github.com/snakemake/snakefmt
rev: v0.6.1 rev: v0.8.0
hooks: hooks:
- id: snakefmt - id: snakefmt
@ -87,6 +87,6 @@ repos:
# Check for FSFE REUSE compliance (licensing) # Check for FSFE REUSE compliance (licensing)
- repo: https://github.com/fsfe/reuse-tool - repo: https://github.com/fsfe/reuse-tool
rev: v0.14.0 rev: v1.1.0
hooks: hooks:
- id: reuse - id: reuse

View File

@ -68,7 +68,7 @@ if config["enable"].get("prepare_links_p_nom", False):
"logs/" + RDIR + "prepare_links_p_nom.log", "logs/" + RDIR + "prepare_links_p_nom.log",
threads: 1 threads: 1
resources: resources:
mem_mb=500, mem_mb=1500,
script: script:
"scripts/prepare_links_p_nom.py" "scripts/prepare_links_p_nom.py"
@ -167,7 +167,7 @@ rule base_network:
"benchmarks/" + RDIR + "base_network" "benchmarks/" + RDIR + "base_network"
threads: 1 threads: 1
resources: resources:
mem_mb=500, mem_mb=1500,
script: script:
"scripts/base_network.py" "scripts/base_network.py"
@ -190,7 +190,7 @@ rule build_shapes:
"logs/" + RDIR + "build_shapes.log", "logs/" + RDIR + "build_shapes.log",
threads: 1 threads: 1
resources: resources:
mem_mb=500, mem_mb=1500,
script: script:
"scripts/build_shapes.py" "scripts/build_shapes.py"
@ -657,7 +657,7 @@ rule make_summary:
+ RDIR + RDIR
+ "make_summary/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.log", + "make_summary/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}.log",
resources: resources:
mem_mb=500, mem_mb=1500,
script: script:
"scripts/make_summary.py" "scripts/make_summary.py"
@ -676,7 +676,7 @@ rule plot_summary:
+ RDIR + RDIR
+ "plot_summary/{summary}_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}_{ext}.log", + "plot_summary/{summary}_elec_s{simpl}_{clusters}_ec_l{ll}_{opts}_{country}_{ext}.log",
resources: resources:
mem_mb=500, mem_mb=1500,
script: script:
"scripts/plot_summary.py" "scripts/plot_summary.py"
@ -706,6 +706,6 @@ rule plot_p_nom_max:
+ RDIR + RDIR
+ "plot_p_nom_max/elec_s{simpl}_{clusts}_{techs}_{country}_{ext}.log", + "plot_p_nom_max/elec_s{simpl}_{clusts}_{techs}_{country}_{ext}.log",
resources: resources:
mem_mb=500, mem_mb=1500,
script: script:
"scripts/plot_p_nom_max.py" "scripts/plot_p_nom_max.py"

View File

@ -86,6 +86,7 @@ electricity:
atlite: atlite:
nprocesses: 4 nprocesses: 4
show_progress: false # false saves time
cutouts: cutouts:
# use 'base' to determine geographical bounds and time span from config # use 'base' to determine geographical bounds and time span from config
# base: # base:
@ -262,6 +263,8 @@ clustering:
algorithm: kmeans # choose from: [hac, kmeans] algorithm: kmeans # choose from: [hac, kmeans]
feature: solar+onwind-time # only for hac. choose from: [solar+onwind-time, solar+onwind-cap, solar-time, solar-cap, solar+offwind-cap] etc. feature: solar+onwind-time # only for hac. choose from: [solar+onwind-time, solar+onwind-cap, solar-time, solar-cap, solar+offwind-cap] etc.
exclude_carriers: [] exclude_carriers: []
remove_stubs: true
remove_stubs_across_borders: true
cluster_network: cluster_network:
algorithm: kmeans algorithm: kmeans
feature: solar+onwind-time feature: solar+onwind-time

View File

@ -56,6 +56,7 @@ electricity:
atlite: atlite:
nprocesses: 4 nprocesses: 4
show_progress: false # false saves time
cutouts: cutouts:
be-03-2013-era5: be-03-2013-era5:
module: era5 module: era5

View File

@ -24,3 +24,5 @@ Gridlink,Kingsnorth (UK),Warande (FR),160,,1400,in permitting,,https://tyndp.ent
NeuConnect,Grain (UK),Fedderwarden (DE),680,,1400,in permitting,,https://tyndp.entsoe.eu/tyndp2018/projects/projects/309,0.716666666666667,51.44,8.046524,53.562763 NeuConnect,Grain (UK),Fedderwarden (DE),680,,1400,in permitting,,https://tyndp.entsoe.eu/tyndp2018/projects/projects/309,0.716666666666667,51.44,8.046524,53.562763
NordBalt,Klaipeda (LT),Nybro (SE),450,,700,built,,https://en.wikipedia.org/wiki/NordBalt,21.256667,55.681667,15.854167,56.767778 NordBalt,Klaipeda (LT),Nybro (SE),450,,700,built,,https://en.wikipedia.org/wiki/NordBalt,21.256667,55.681667,15.854167,56.767778
Estlink 1,Harku (EE),Espoo (FI),105,,350,built,,https://en.wikipedia.org/wiki/Estlink,24.560278,59.384722,24.551667,60.203889 Estlink 1,Harku (EE),Espoo (FI),105,,350,built,,https://en.wikipedia.org/wiki/Estlink,24.560278,59.384722,24.551667,60.203889
Greenlink,Waterford (IE),Pembroke (UK),,180,500,under construction,,https://tyndp2022-project-platform.azurewebsites.net/projectsheets/transmission/286,-6.987,52.260,-4.986,51.686
Celtic Interconnector,Aghada (IE),La Martyre (FR),,572,700,under consideration,,https://tyndp2022-project-platform.azurewebsites.net/projectsheets/transmission/107,-8.16642,51.91413,-4.184,48.459

1 Name Converterstation 1 Converterstation 2 Length (given) (km) Length (distance*1.2) (km) Power (MW) status replaces Ref x1 y1 x2 y2
24 NeuConnect Grain (UK) Fedderwarden (DE) 680 1400 in permitting https://tyndp.entsoe.eu/tyndp2018/projects/projects/309 0.716666666666667 51.44 8.046524 53.562763
25 NordBalt Klaipeda (LT) Nybro (SE) 450 700 built https://en.wikipedia.org/wiki/NordBalt 21.256667 55.681667 15.854167 56.767778
26 Estlink 1 Harku (EE) Espoo (FI) 105 350 built https://en.wikipedia.org/wiki/Estlink 24.560278 59.384722 24.551667 60.203889
27 Greenlink Waterford (IE) Pembroke (UK) 180 500 under construction https://tyndp2022-project-platform.azurewebsites.net/projectsheets/transmission/286 -6.987 52.260 -4.986 51.686
28 Celtic Interconnector Aghada (IE) La Martyre (FR) 572 700 under consideration https://tyndp2022-project-platform.azurewebsites.net/projectsheets/transmission/107 -8.16642 51.91413 -4.184 48.459

View File

@ -36,12 +36,20 @@ Link:
"5583": "7428" # bus0 == bus1 to remove link in remove_unconnected_components (Sardinia) "5583": "7428" # bus0 == bus1 to remove link in remove_unconnected_components (Sardinia)
"13588": "7428" # bus0 == bus1 to remove link in remove_unconnected_components (Sardinia) "13588": "7428" # bus0 == bus1 to remove link in remove_unconnected_components (Sardinia)
"T23": "6355" # bus0 == bus1 to remove link in remove_unconnected_components (NordBalt) "T23": "6355" # bus0 == bus1 to remove link in remove_unconnected_components (NordBalt)
"14815": "5939" # Kainachtal
"8706": "6448"
bus1: bus1:
index: index:
"12931": "8152" # BorWin3 "12931": "8152" # BorWin3
"5582": "2382" # combine link 5583 + 5582 in 5582 (Sardinia) "5582": "2382" # combine link 5583 + 5582 in 5582 (Sardinia)
"13589": "1349" # combine link 13589 + 13588 in 13589 (Sardinia) "13589": "1349" # combine link 13589 + 13588 in 13589 (Sardinia)
"14820": "6354" # NordBalt "14820": "6354" # NordBalt
"14810": "6365" # Skagerrak
"8708": "6448"
"8394": "6695"
"14813": "7052"
"8009": "5939"
"5601": "7052" # Link Sweden - Lübeck
length: length:
index: index:
"5582": 26.39 # new length of combined links (sum) "5582": 26.39 # new length of combined links (sum)
@ -53,6 +61,7 @@ Line:
bus0: bus0:
index: index:
"14573": "7179" #fix bus-id substation in PT (220/380kV issue) "14573": "7179" #fix bus-id substation in PT (220/380kV issue)
"14756": "8577" # Deeside connection
v_nom: v_nom:
index: index:
"14573": 220 # 220/380kV issue of substation in PT "14573": 220 # 220/380kV issue of substation in PT

View File

@ -10,6 +10,10 @@ Release Notes
Upcoming Release Upcoming Release
================ ================
* Fix EQ constraint for the case no hydro inflow is available
* Bugfix in the reserve constraint will increase demand related reserve requirements
**New Features** **New Features**
* Carriers of generators can now be excluded from aggregation in clustering network and simplify network. * Carriers of generators can now be excluded from aggregation in clustering network and simplify network.

View File

@ -61,14 +61,16 @@ It is also possible to allow less or more carbon-dioxide emissions. Here, we lim
.. literalinclude:: ../config.tutorial.yaml .. literalinclude:: ../config.tutorial.yaml
:language: yaml :language: yaml
:lines: 35,37 :start-at: electricity:
:end-before: exentable_carriers:
PyPSA-Eur also includes a database of existing conventional powerplants. PyPSA-Eur also includes a database of existing conventional powerplants.
We can select which types of powerplants we like to be included: We can select which types of powerplants we like to be included:
.. literalinclude:: ../config.tutorial.yaml .. literalinclude:: ../config.tutorial.yaml
:language: yaml :language: yaml
:lines: 35,51 :start-at: extendable_carriers:
:end-before: max_hours:
To accurately model the temporal and spatial availability of renewables such as wind and solar energy, we rely on historical weather data. To accurately model the temporal and spatial availability of renewables such as wind and solar energy, we rely on historical weather data.
It is advisable to adapt the required range of coordinates to the selection of countries. It is advisable to adapt the required range of coordinates to the selection of countries.
@ -83,14 +85,21 @@ For example, we may want to use the ERA-5 dataset for solar and not the default
.. literalinclude:: ../config.tutorial.yaml .. literalinclude:: ../config.tutorial.yaml
:language: yaml :language: yaml
:lines: 63,106,107 :start-at: be-03-2013-era5:
:end-at: module:
.. literalinclude:: ../config.tutorial.yaml
:language: yaml
:start-at: solar:
:end-at: cutout:
Finally, it is possible to pick a solver. For instance, this tutorial uses the open-source solvers CBC and Ipopt and does not rely Finally, it is possible to pick a solver. For instance, this tutorial uses the open-source solvers CBC and Ipopt and does not rely
on the commercial solvers Gurobi or CPLEX (for which free academic licenses are available). on the commercial solvers Gurobi or CPLEX (for which free academic licenses are available).
.. literalinclude:: ../config.tutorial.yaml .. literalinclude:: ../config.tutorial.yaml
:language: yaml :language: yaml
:lines: 188,198,199 :start-at: solver:
:end-before: plotting:
.. note:: .. note::

View File

@ -10,7 +10,7 @@ dependencies:
- python>=3.8 - python>=3.8
- pip - pip
- pypsa>=0.20 - pypsa>=0.21.3
- atlite>=0.2.9 - atlite>=0.2.9
- dask - dask
@ -25,19 +25,19 @@ dependencies:
- pytables - pytables
- lxml - lxml
- powerplantmatching>=0.5.4 - powerplantmatching>=0.5.4
- numpy - numpy<1.24
- pandas>=1.4 - pandas>=1.4
- geopandas>=0.11.0 - geopandas>=0.11.0
- xarray - xarray
- netcdf4 - netcdf4
- networkx - networkx
- scipy - scipy
- shapely<2.0 # need to address deprecations - shapely<2.0
- progressbar2 - progressbar2
- pyomo - pyomo
- matplotlib - matplotlib<3.6
- proj - proj
- fiona <= 1.18.20 # Till issue https://github.com/Toblerity/Fiona/issues/1085 is not solved - fiona
- country_converter - country_converter
# Keep in conda environment when calling ipython # Keep in conda environment when calling ipython

View File

@ -28,7 +28,6 @@ def configure_logging(snakemake, skip_handlers=False):
skip_handlers : True | False (default) skip_handlers : True | False (default)
Do (not) skip the default handlers created for redirecting output to STDERR and file. Do (not) skip the default handlers created for redirecting output to STDERR and file.
""" """
import logging import logging
kwargs = snakemake.config.get("logging", dict()).copy() kwargs = snakemake.config.get("logging", dict()).copy()

View File

@ -111,7 +111,6 @@ def calculate_annuity(n, r):
discount rate of r, e.g. annuity(20, 0.05) * 20 = 1.6 discount rate of r, e.g. annuity(20, 0.05) * 20 = 1.6
""" """
if isinstance(r, pd.Series): if isinstance(r, pd.Series):
return pd.Series(1 / n, index=r.index).where( return pd.Series(1 / n, index=r.index).where(
r == 0, r / (1.0 - 1.0 / (1.0 + r) ** n) r == 0, r / (1.0 - 1.0 / (1.0 + r) ** n)

View File

@ -69,7 +69,6 @@ def voronoi_partition_pts(points, outline):
------- -------
polygons : N - ndarray[dtype=Polygon|MultiPolygon] polygons : N - ndarray[dtype=Polygon|MultiPolygon]
""" """
points = np.asarray(points) points = np.asarray(points)
if len(points) == 1: if len(points) == 1:
@ -107,7 +106,7 @@ def voronoi_partition_pts(points, outline):
polygons.append(poly) polygons.append(poly)
return np.array(polygons, dtype=object) return polygons
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -189,7 +189,6 @@ def manual_adjustment(load, fn_load, powerstatistics):
Manual adjusted and interpolated load time-series with UTC Manual adjusted and interpolated load time-series with UTC
timestamps x ISO-2 countries timestamps x ISO-2 countries
""" """
if powerstatistics: if powerstatistics:
if "MK" in load.columns: if "MK" in load.columns:
if "AL" not in load.columns or load.AL.isnull().values.all(): if "AL" not in load.columns or load.AL.isnull().values.all():

View File

@ -84,7 +84,7 @@ if __name__ == "__main__":
# adjusted boundaries # adjusted boundaries
shapes = gpd.read_file(snakemake.input.natura).to_crs(3035) shapes = gpd.read_file(snakemake.input.natura).to_crs(3035)
raster = ~geometry_mask(shapes.geometry, out_shape[::-1], transform) raster = ~geometry_mask(shapes.geometry, out_shape, transform)
raster = raster.astype(rio.uint8) raster = raster.astype(rio.uint8)
with rio.open( with rio.open(

View File

@ -129,6 +129,8 @@ def countries(naturalearth, country_list):
s = df.set_index("name")["geometry"].map(_simplify_polys) s = df.set_index("name")["geometry"].map(_simplify_polys)
if "RS" in country_list: if "RS" in country_list:
s["RS"] = s["RS"].union(s.pop("KV")) s["RS"] = s["RS"].union(s.pop("KV"))
# cleanup shape union
s["RS"] = Polygon(s["RS"].exterior.coords)
return s return s
@ -145,7 +147,7 @@ def eez(country_shapes, eez, country_list):
lambda s: _simplify_polys(s, filterremote=False) lambda s: _simplify_polys(s, filterremote=False)
) )
s = gpd.GeoSeries( s = gpd.GeoSeries(
{k: v for k, v in s.iteritems() if v.distance(country_shapes[k]) < 1e-3} {k: v for k, v in s.items() if v.distance(country_shapes[k]) < 1e-3}
) )
s = s.to_frame("geometry") s = s.to_frame("geometry")
s.index.name = "name" s.index.name = "name"

View File

@ -222,7 +222,6 @@ def distribute_clusters(n, n_clusters, focus_weights=None, solver_name="cbc"):
""" """
Determine the number of clusters per country. Determine the number of clusters per country.
""" """
L = ( L = (
n.loads_t.p_set.mean() n.loads_t.p_set.mean()
.groupby(n.loads.bus) .groupby(n.loads.bus)

View File

@ -235,7 +235,6 @@ def calculate_supply(n, label, supply):
calculate the max dispatch of each component at the buses where the loads calculate the max dispatch of each component at the buses where the loads
are attached. are attached.
""" """
load_types = n.buses.carrier.unique() load_types = n.buses.carrier.unique()
for i in load_types: for i in load_types:
@ -296,7 +295,6 @@ def calculate_supply_energy(n, label, supply_energy):
calculate the total dispatch of each component at the buses where the loads calculate the total dispatch of each component at the buses where the loads
are attached. are attached.
""" """
load_types = n.buses.carrier.unique() load_types = n.buses.carrier.unique()
for i in load_types: for i in load_types:
@ -556,9 +554,13 @@ if __name__ == "__main__":
opts="Co2L-24H", opts="Co2L-24H",
country="all", country="all",
) )
network_dir = os.path.join("..", "results", "networks") network_dir = os.path.join(
"..", "results", "networks", snakemake.config["run"]["name"]
)
else: else:
network_dir = os.path.join("results", "networks") network_dir = os.path.join(
"results", "networks", snakemake.config["run"]["name"]
)
configure_logging(snakemake) configure_logging(snakemake)
config = snakemake.config config = snakemake.config

View File

@ -92,7 +92,7 @@ def plot_costs(infn, config, fn=None):
print(df.sum()) print(df.sum())
new_index = (preferred_order & df.index).append( new_index = (preferred_order.intersection(df.index)).append(
df.index.difference(preferred_order) df.index.difference(preferred_order)
) )
@ -149,7 +149,7 @@ def plot_energy(infn, config, fn=None):
print(df.sum()) print(df.sum())
new_index = (preferred_order & df.index).append( new_index = (preferred_order.intersection(df.index)).append(
df.index.difference(preferred_order) df.index.difference(preferred_order)
) )

View File

@ -111,11 +111,15 @@ def simplify_network_to_380(n):
""" """
Fix all lines to a voltage level of 380 kV and remove all transformers. Fix all lines to a voltage level of 380 kV and remove all transformers.
The function preserves the transmission capacity for each line while updating The function preserves the transmission capacity for each line while
its voltage level, line type and number of parallel bundles (num_parallel). updating
its voltage level, line type and number of parallel bundles
(num_parallel).
Transformers are removed and connected components are moved from their Transformers are removed and connected components are moved from
starting bus to their ending bus. The corresponding starting buses are their
starting bus to their ending bus. The corresponding starting buses
are
removed as well. removed as well.
""" """
logger.info("Mapping all network lines onto a single 380kV layer") logger.info("Mapping all network lines onto a single 380kV layer")
@ -217,7 +221,7 @@ def _adjust_capital_costs_using_connection_costs(n, connection_costs_to_bus, out
tech, tech,
", ".join( ", ".join(
"{:.0f} Eur/MW/a for `{}`".format(d, b) "{:.0f} Eur/MW/a for `{}`".format(d, b)
for b, d in costs.iteritems() for b, d in costs.items()
), ),
) )
) )
@ -369,7 +373,7 @@ def simplify_links(n, costs, config, output, aggregation_strategies=dict()):
n.mremove("Link", all_links) n.mremove("Link", all_links)
static_attrs = n.components["Link"]["attrs"].loc[lambda df: df.static] static_attrs = n.components["Link"]["attrs"].loc[lambda df: df.static]
for attr, default in static_attrs.default.iteritems(): for attr, default in static_attrs.default.items():
params.setdefault(attr, default) params.setdefault(attr, default)
n.links.loc[name] = pd.Series(params) n.links.loc[name] = pd.Series(params)
@ -395,7 +399,11 @@ def simplify_links(n, costs, config, output, aggregation_strategies=dict()):
def remove_stubs(n, costs, config, output, aggregation_strategies=dict()): def remove_stubs(n, costs, config, output, aggregation_strategies=dict()):
logger.info("Removing stubs") logger.info("Removing stubs")
busmap = busmap_by_stubs(n) # ['country']) across_borders = config["clustering"]["simplify_network"].get(
"remove_stubs_across_borders", True
)
matching_attrs = [] if across_borders else ["country"]
busmap = busmap_by_stubs(n, matching_attrs)
connection_costs_to_bus = _compute_connection_costs_to_bus(n, busmap, costs, config) connection_costs_to_bus = _compute_connection_costs_to_bus(n, busmap, costs, config)
@ -530,6 +538,10 @@ if __name__ == "__main__":
n, technology_costs, snakemake.config, snakemake.output, aggregation_strategies n, technology_costs, snakemake.config, snakemake.output, aggregation_strategies
) )
busmaps = [trafo_map, simplify_links_map]
cluster_config = snakemake.config["clustering"]["simplify_network"]
if cluster_config.get("remove_stubs", True):
n, stub_map = remove_stubs( n, stub_map = remove_stubs(
n, n,
technology_costs, technology_costs,
@ -537,15 +549,9 @@ if __name__ == "__main__":
snakemake.output, snakemake.output,
aggregation_strategies=aggregation_strategies, aggregation_strategies=aggregation_strategies,
) )
busmaps.append(stub_map)
busmaps = [trafo_map, simplify_links_map, stub_map] if cluster_config.get("to_substations", False):
cluster_config = snakemake.config.get("clustering", {}).get("simplify_network", {})
if (
cluster_config.get("clustering", {})
.get("simplify_network", {})
.get("to_substations", False)
):
n, substation_map = aggregate_to_substations(n, aggregation_strategies) n, substation_map = aggregate_to_substations(n, aggregation_strategies)
busmaps.append(substation_map) busmaps.append(substation_map)

View File

@ -216,6 +216,7 @@ def add_EQ_constraints(n, o, scaling=1e-1):
.T.groupby(ggrouper, axis=1) .T.groupby(ggrouper, axis=1)
.apply(join_exprs) .apply(join_exprs)
) )
if not n.storage_units_t.inflow.empty:
lhs_spill = ( lhs_spill = (
linexpr( linexpr(
( (
@ -228,6 +229,8 @@ def add_EQ_constraints(n, o, scaling=1e-1):
) )
lhs_spill = lhs_spill.reindex(lhs_gen.index).fillna("") lhs_spill = lhs_spill.reindex(lhs_gen.index).fillna("")
lhs = lhs_gen + lhs_spill lhs = lhs_gen + lhs_spill
else:
lhs = lhs_gen
define_constraints(n, lhs, ">=", rhs, "equity", "min") define_constraints(n, lhs, ">=", rhs, "equity", "min")
@ -278,7 +281,7 @@ def add_operational_reserve_margin_constraint(n, config):
).sum(1) ).sum(1)
# Total demand at t # Total demand at t
demand = n.loads_t.p.sum(1) demand = n.loads_t.p_set.sum(1)
# VRES potential of non extendable generators # VRES potential of non extendable generators
capacity_factor = n.generators_t.p_max_pu[vres_i.difference(ext_i)] capacity_factor = n.generators_t.p_max_pu[vres_i.difference(ext_i)]
@ -321,7 +324,6 @@ def add_operational_reserve_margin(n, sns, config):
Build reserve margin constraints based on the formulation given in Build reserve margin constraints based on the formulation given in
https://genxproject.github.io/GenX/dev/core/#Reserves. https://genxproject.github.io/GenX/dev/core/#Reserves.
""" """
define_variables(n, 0, np.inf, "Generator", "r", axes=[sns, n.generators.index]) define_variables(n, 0, np.inf, "Generator", "r", axes=[sns, n.generators.index])
add_operational_reserve_margin_constraint(n, config) add_operational_reserve_margin_constraint(n, config)
@ -389,11 +391,7 @@ def solve_network(n, config, opts="", **kwargs):
if skip_iterations: if skip_iterations:
network_lopf( network_lopf(
n, n, solver_name=solver_name, solver_options=solver_options, **kwargs
solver_name=solver_name,
solver_options=solver_options,
extra_functionality=extra_functionality,
**kwargs
) )
else: else:
ilopf( ilopf(
@ -403,7 +401,6 @@ def solve_network(n, config, opts="", **kwargs):
track_iterations=track_iterations, track_iterations=track_iterations,
min_iterations=min_iterations, min_iterations=min_iterations,
max_iterations=max_iterations, max_iterations=max_iterations,
extra_functionality=extra_functionality,
**kwargs **kwargs
) )
return n return n
@ -432,6 +429,7 @@ if __name__ == "__main__":
n, n,
snakemake.config, snakemake.config,
opts, opts,
extra_functionality=extra_functionality,
solver_dir=tmpdir, solver_dir=tmpdir,
solver_logfile=snakemake.log.solver, solver_logfile=snakemake.log.solver,
) )

View File

@ -54,6 +54,7 @@ electricity:
atlite: atlite:
nprocesses: 4 nprocesses: 4
show_progress: false # false saves time
cutouts: cutouts:
be-03-2013-era5: be-03-2013-era5:
module: era5 module: era5