Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
821 commits
Select commit Hold shift + click to select a range
a099f37
update submodule
lindnemi Jul 12, 2024
dfbe97e
exclude the "co2 sequestered" store from accounting
lindnemi Jul 12, 2024
cbab80d
get "link" dont drop "store" to avoid errors
lindnemi Jul 12, 2024
bc33283
minor improvements for exports
lindnemi Jul 15, 2024
cb034cf
Merge branch 'main' into database-pypsa-de
lindnemi Jul 15, 2024
d8dd908
Merge pull request #129 from PyPSA/database-pypsa-de
lindnemi Jul 15, 2024
05ea328
checkout corresponding branch in pypsa-eur
lindnemi Jul 15, 2024
58353d2
add config prefix
lindnemi Jul 17, 2024
4d6f5c0
correct year for renewable estimation
lindnemi Jul 17, 2024
4ef47da
limit offshore expansion in 2030
lindnemi Jul 18, 2024
5805e4e
new cutout from Fabian
lindnemi Jul 22, 2024
506ef1e
additional keys
lindnemi Jul 22, 2024
2738d71
update submodule
lindnemi Jul 23, 2024
5e2bb1c
use the modded n.statistics to get investments
lindnemi Jul 23, 2024
10823ab
add offwind transmission investment
lindnemi Jul 24, 2024
5c99468
minor fixes
lindnemi Jul 24, 2024
b50b441
add endpoints to investment averages
lindnemi Jul 24, 2024
ce826c3
adapt to pypsa upstream changes
lindnemi Jul 24, 2024
8452faf
minor fix
lindnemi Jul 24, 2024
3136f71
explicitly report offwind investments
lindnemi Jul 24, 2024
463b899
update submodule
lindnemi Jul 25, 2024
1e0bff9
update submodule
lindnemi Jul 25, 2024
59333db
reduce DH buildout potential, especially for CurPol and WorstCase
lindnemi Jul 25, 2024
d8f0d65
changes to update submodule to master
lindnemi Jul 26, 2024
16f1df8
Merge branch 'main' into cutout-2019
lindnemi Jul 29, 2024
42d1ca1
update to upstream changes
lindnemi Jul 29, 2024
ec3fa2d
adapt to pypsa changes
lindnemi Jul 29, 2024
4583111
Merge branch 'main' into investment-exports
lindnemi Jul 29, 2024
7c58bf8
rename investment -> overnight_cost
lindnemi Jul 30, 2024
a14c4a5
more investment -> overnight_cost renaming
lindnemi Jul 30, 2024
bfe6e73
final touches for the renaming
lindnemi Jul 30, 2024
083e6ab
added new script for DH modifications
Jun 12, 2024
6a9286c
function for update of urban heat loads
Jun 14, 2024
dbc2c37
Preserve aggregate DH demand
Jun 17, 2024
aa12459
Merge pull request #143 from PyPSA/investment-exports
lindnemi Jul 30, 2024
1559e74
update submodule
lindnemi Jul 30, 2024
2eb035d
quickfix for pypsa version until new release
lindnemi Jul 30, 2024
8f3d743
add subnodes and loads
Jul 31, 2024
11bf8cf
adjust snapshots
lindnemi Jul 31, 2024
d40cd9f
update submodule
lindnemi Jul 31, 2024
0ed85d1
Merge branch 'main' into high-spatial
lindnemi Jul 31, 2024
1154cbc
ignore errors when dropping stores
lindnemi Jul 31, 2024
547782a
Merge pull request #107 from PyPSA/high-spatial
lindnemi Jul 31, 2024
8449ab8
Update pypsa version
lindnemi Jul 31, 2024
276542b
use NEP DC costs
lindnemi Aug 1, 2024
64ee6f6
make unravelling of oil bus consistent with new refineries
nworbmot Aug 2, 2024
d231363
upstream fix for connection_overnight_cost
lindnemi Aug 2, 2024
c5bd066
fix renwable: config key
lindnemi Aug 2, 2024
4df0915
Merge branch 'main' into cutout-2019
lindnemi Aug 2, 2024
dd0e396
Merge pull request #142 from PyPSA/cutout-2019
lindnemi Aug 2, 2024
e381c93
rename cutout
lindnemi Aug 2, 2024
ca52fef
Merge branch 'main' into refineries
lindnemi Aug 2, 2024
986bfee
update exporter
lindnemi Aug 2, 2024
b71842a
update DC stations costs
lindnemi Aug 2, 2024
02815cd
Merge branch 'main' into update-offwind-connection-cost
lindnemi Aug 2, 2024
2d295ca
Merge pull request #149 from PyPSA/update-offwind-connection-cost
lindnemi Aug 2, 2024
ab563e6
Create Changelog.md
lindnemi Aug 5, 2024
e2e4149
Create PULL_REQUEST_TEMPLATE.md
lindnemi Aug 5, 2024
7e06505
ci: add validator
lkstrp Aug 2, 2024
15efdb1
select images and add repo owner path
lkstrp Aug 5, 2024
1778dc1
load chps, change function header
Aug 6, 2024
f9096c2
Merge pull request #111 from PyPSA/ci-config
lindnemi Aug 6, 2024
048c46d
Merge branch 'main' into refineries
lindnemi Aug 6, 2024
8435176
Merge pull request #150 from PyPSA/refineries
lindnemi Aug 6, 2024
1d12751
Update PULL_REQUEST_TEMPLATE.md
lindnemi Aug 6, 2024
c15fdb3
Update Changelog.md
lindnemi Aug 6, 2024
d7c98c2
update submodule
lindnemi Aug 6, 2024
009f660
Update .pre-commit-config.yaml
lkstrp Aug 6, 2024
ceb7ce8
remove reuse check
lkstrp Aug 6, 2024
ca1f43c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 6, 2024
63c83f9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 6, 2024
98a2acb
Merge pull request #156 from PyPSA/lkstrp-patch-1
lindnemi Aug 6, 2024
fc8bf80
Using config_provider for additional functionality exclusively (#154)
toniseibold Aug 6, 2024
0324120
Create .git-blame-ignore-revs (#158)
lkstrp Aug 6, 2024
f807830
minor changes for running single node network (#160)
JulianGeis Aug 7, 2024
d90aca1
Fix hydrogen import boundary condition (#159)
toniseibold Aug 7, 2024
0a060dc
Accounting renewable CH4 without spatially resolved CH4 network (#146)
toniseibold Aug 7, 2024
d21a5c2
Hydrogen Gas Turbines and Retrofitting of Gas Turbines (#151)
toniseibold Aug 9, 2024
db914f6
minor fixes
lindnemi Aug 9, 2024
4aab9c8
Include spain (#163)
lindnemi Aug 9, 2024
1fef55b
[pre-commit.ci] pre-commit autoupdate (#165)
pre-commit-ci[bot] Aug 13, 2024
8dd49cb
Update post-discretization size for H2 (#167)
lindnemi Aug 13, 2024
004f4bc
ci: adjust ci to new validator (#164)
lkstrp Aug 14, 2024
0bd5246
Modify dh systems (#113)
cpschau Aug 14, 2024
d87f4af
Limit German CO2 sequestration in each investment year (#170)
nworbmot Aug 15, 2024
2e10863
fix (#169)
lkstrp Aug 15, 2024
33916de
update submodule
lindnemi Aug 15, 2024
0e53799
ci: add dependabot (#172)
lkstrp Aug 16, 2024
b69cd06
merge main
Aug 19, 2024
77f0bdd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 19, 2024
1eef9c6
Bump lkstrp/pypsa-validator in the github-actions group (#173)
dependabot[bot] Aug 19, 2024
4df060c
Merge branch 'main' into add_subnodes
lkstrp Aug 19, 2024
7bc5749
changed data source to Fernwärmeatlas; changed script structure; incl…
Aug 20, 2024
9944878
fixed nodal EB with gas boiler; fixed snakemake issues
Aug 21, 2024
c7ec368
changed input for add_brownfield
Aug 21, 2024
1fbecbc
geolocations from file instead of geocoding
Aug 21, 2024
c97e56e
added links and stores except from heat pumps; adapted snakemake inpu…
Aug 23, 2024
fe47933
add ASHP
Aug 27, 2024
c081ff4
fix bugs for heat pump integration
Aug 27, 2024
039aaad
Bump lkstrp/pypsa-validator to `v0.1.4` (#178)
lkstrp Sep 2, 2024
0f6e528
Merging master into Ariadne 2 (#177)
lindnemi Sep 3, 2024
1dcc6ea
Biogas (#184)
lindnemi Sep 6, 2024
cb041ab
Adding Italy (#183)
toniseibold Sep 6, 2024
d79ae3d
Updating cost horizon data (#182)
toniseibold Sep 6, 2024
6293d3b
Adding overnight costs in `modify_prenetwork` (#181)
toniseibold Sep 6, 2024
055aca6
update submodule
lindnemi Sep 6, 2024
bcd73c1
bump prefix
lindnemi Sep 6, 2024
a4c3104
Implement rising hub heights for wind; profile smoothing for offshore…
nworbmot Sep 6, 2024
70d9739
update submodule
lindnemi Sep 9, 2024
c69e83b
Bump lkstrp/pypsa-validator to v0.2.0 (#185)
lkstrp Sep 10, 2024
8b67210
improve exporter stability
lindnemi Sep 10, 2024
f6013f0
importve numerical stability of exporter
lindnemi Sep 10, 2024
68318ae
update snakemake
lindnemi Sep 10, 2024
b7acb59
update submodule
lindnemi Sep 10, 2024
9595f7c
update submodule
lindnemi Sep 10, 2024
ddeeae1
downgrade submodule
lindnemi Sep 11, 2024
e5f56de
update pypsa and submodule
lindnemi Sep 11, 2024
7e36af1
Bump lkstrp/pypsa-validator from 0.2.0 to 0.2.1 in the github-actions…
dependabot[bot] Sep 13, 2024
a5ce933
make exporter more robust
lindnemi Sep 13, 2024
07c1edd
add gas trade to exporter
lindnemi Sep 13, 2024
01871cc
Update Germany specific costs (NEP, onwind, pellets) (#193)
lindnemi Sep 16, 2024
abf8fc1
Merge remote-tracking branch 'origin/main' into add_subnodes
Sep 16, 2024
e7ec95e
add marginal_cost for international trade links
lindnemi Sep 17, 2024
ebdddd0
round exported data to 5 significant decimals
lindnemi Sep 17, 2024
e799e12
Merge remote-tracking branch 'origin/main' into add_subnodes
Sep 17, 2024
f5e8d2b
adjustments to cop netcdf and existing heating distribution
Sep 18, 2024
cd75664
fix extension of existing_heating df
Sep 19, 2024
5b9ed82
fix snakemake issue for existing heating
Sep 19, 2024
2d6949e
dirty fix for workflow and optional output
Sep 20, 2024
1a2ed80
match CHP by LAU shapes
Sep 24, 2024
913da0b
added industry heat load
Sep 24, 2024
8dbb0cd
make workflow run after merge
Oct 22, 2024
ade4e85
add heat vent and remove load shedder
Oct 23, 2024
ce3d85b
fix workflow
Nov 14, 2024
1901d24
uncomment get_data
Nov 14, 2024
e76741b
add type hints and docstrings; clean-up unused code snippets; simplif…
Dec 2, 2024
f5d4363
change variable name row to subnode
Dec 2, 2024
892ead0
add fernwaermeatlas data
Dec 2, 2024
11b3ec9
change docstring to numpy
Dec 12, 2024
c1aaae8
add comments
Dec 12, 2024
57aa50c
another docstring conversion to numpy format
Dec 13, 2024
af60c52
one more numpy docstring
Dec 13, 2024
fa36e00
Pre-merge: remapped directory structure
Feb 13, 2025
189a7c6
Merge branch 'add_subnodes_remapped' into add_subnodes
Feb 14, 2025
c5def7c
Adjust add_existing_baseyear to allow for subnodes
Feb 14, 2025
d2f2721
fix snakefile
Feb 17, 2025
7bee646
Add geothermal-sourced central heat pumps (#1359)
amos-schledorn Dec 2, 2024
e072a5c
fix workflow
Dec 13, 2024
b37c040
cleaned up unnecessary code
TomKae00 Dec 4, 2024
da66842
EEM paper setup
Feb 25, 2025
a988333
replace corine with osm land cover data
Feb 25, 2025
330884d
mv ptes land eligibility to prepare_subnodes; fix ptes initialization…
Feb 27, 2025
092e3ed
update prepare_sector_network
Feb 27, 2025
de4fe8a
increase eem resolution
Feb 27, 2025
d7496e6
update TTES efficiencies
Feb 27, 2025
ae7ad2e
fix land eligibility
Mar 7, 2025
b9c106f
adjust snakemake mem requirements
Mar 7, 2025
c656cd5
fix eem config
Mar 7, 2025
37e98f4
fix ptes query
Mar 7, 2025
4caf3e3
multithreaded potential calculation
Mar 10, 2025
8677562
use raster data from census to refine district heating areas
Mar 12, 2025
2a723b5
add resolution for exclusion container as parameter
Mar 13, 2025
7fae6de
Merge branch 'main' into refine_dh_areas
Mar 19, 2025
980d468
preliminary fixes after merge
Mar 19, 2025
d3d9f3a
Add PTES and introduce PTES/TES energy-to-power ratios (#1546)
TomKae00 Mar 14, 2025
9087994
adjustments to new geothermal potentials and heat_stores
Mar 20, 2025
d8ee5ef
hot fix for missing geothermal potentials in GB
Mar 20, 2025
b73bdb5
adjust reference of df with subnodes to correctly handle demand(subno…
Mar 20, 2025
df75573
CHP plants in buffered dh area based on census instead of LAU
Mar 20, 2025
e77bb20
fix COP revision of predecessing network
Mar 24, 2025
a416e5b
single execution of build_existing_chp_de
Mar 24, 2025
3c56fb6
adjust path in snakefile to networks subdirectory
Mar 24, 2025
72e7c5d
convert chps to eops if no urban central heat bus is available
Mar 24, 2025
eb33bfa
reference cities as bus locations
Mar 24, 2025
8c40e95
adjust docstring
Mar 24, 2025
3c85e7f
adjust query of chp input path to removal of wildcards
Mar 24, 2025
594ee66
updating mean cost data
toniseibold Mar 19, 2025
979f565
rename sysgf scenario file
Mar 24, 2025
d0944a1
adjust chp path in add_existing_baseyear inputs
Mar 24, 2025
eba68fe
rename referenced sysgf scenario file
Mar 24, 2025
e76d4fd
Revert "CHP plants in buffered dh area based on census instead of LAU"
Mar 25, 2025
4242bd4
remove outdated heat source rules
Mar 28, 2025
54e5146
adjust subnode loads
Apr 3, 2025
0bab6d5
remove if-clause from snakefile
Apr 3, 2025
fb91229
skip adjustments in prepare_sector_network if subnodes activated
Apr 3, 2025
b3cc8d1
Merge remote-tracking branch 'origin/main' into refine_dh_areas
Apr 3, 2025
e874752
aligned mean costs files
Apr 4, 2025
5224f7b
clean-up prepare_sector_network
Apr 4, 2025
1106d9f
clean-up heating files
Apr 4, 2025
04f2ae9
Fix: wildcards of build_renewable_profiles for scenario management 'b…
lindnemi Apr 14, 2025
df93666
rename prefix
lindnemi Apr 14, 2025
03e343d
use absolute imports
lindnemi Apr 14, 2025
4ed9713
switch back to get from _helpers
lindnemi Apr 14, 2025
4ef92fc
remove duplicate aviation sector
lindnemi Apr 15, 2025
07b8b3f
get correct investments year for aviation
lindnemi Apr 15, 2025
9e17e5c
load_costs instead of prepare_costs
lindnemi Apr 15, 2025
89f9ecc
simplify nep_costs
lindnemi Apr 15, 2025
d6aca0b
adjust to new naming of wind generators with resource classes
lindnemi Apr 15, 2025
306e989
some more conforming with upstream changes
lindnemi Apr 15, 2025
0ef0b64
add another color for 2050
lindnemi Apr 15, 2025
ac429e1
Merge remote-tracking branch 'origin/main' into refine_dh_areas
Apr 16, 2025
a846eec
Merge remote-tracking branch 'origin/merge-master-april' into refine_…
Apr 16, 2025
c7a7038
complement datafiles
Apr 16, 2025
8407dc9
fix investments outside DE
Apr 17, 2025
62e1016
start by making Mix the default scenario
lindnemi May 7, 2025
4589583
make script more robust
lindnemi May 7, 2025
d9c35d1
- change syntax of national co2_budget
lindnemi May 7, 2025
fafaf90
simplify scenario definitions, fallback to defaults more often
lindnemi May 7, 2025
94941cd
change prefix
lindnemi May 7, 2025
ac8456f
ariadne_template is data not resources
lindnemi May 12, 2025
653fd49
fix rounding error
lindnemi May 12, 2025
396fa62
Merge branch 'main' into simplify-scenarios
lindnemi May 12, 2025
e4a22b1
disable interactive mode in final plotting script
lindnemi May 13, 2025
aae794b
Merge branch 'simplify-scenarios' of github.com:PyPSA/pypsa-de into s…
lindnemi May 13, 2025
891eb9f
decouple ariadne DB pre-workflow from scenario management
lindnemi May 13, 2025
014c222
fix key error
lindnemi May 14, 2025
1f7ce92
review: addition, removal and renaming of config parameters; removed …
May 14, 2025
7b86796
Merge remote-tracking branch 'origin/main' into refine_dh_areas
May 14, 2025
c3f2f80
Merge remote-tracking branch 'origin/simplify-scenarios' into refine_…
May 14, 2025
486ac2b
adjust configs
May 15, 2025
643ea21
allow for dynamic ptes capacity and remove cases for ptes as storage …
May 15, 2025
e506603
revert restriction of mother node ptes potentials
May 15, 2025
98d094e
Merge remote-tracking branch 'origin/main' into refine_dh_areas
May 15, 2025
9f8f909
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 15, 2025
a3f9a04
Modularize and refactor add_subnodes
May 15, 2025
e5abe49
doc: extended docstring of add_subnodes
May 15, 2025
98d3b63
Merge branch 'refine_dh_areas' into ptes_paper
May 19, 2025
77ea20e
fix foreign reference investments
May 20, 2025
fcb50b1
adjust sysgf config to fixed foreign investments
May 20, 2025
cadb9c2
fix foreign reference investments
May 20, 2025
b79bd56
add docstring
May 20, 2025
c3f2075
add changelog entry
May 20, 2025
de12fd9
rename parameters and functions; allow investments on EU buses; allow…
May 22, 2025
d0006ac
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 22, 2025
9ccb081
first draft
Jun 5, 2025
5b5e95d
improved draft
Jun 6, 2025
231f419
change sysgf summary output in snakefile
Jun 10, 2025
3b8002f
rename parameters and functions; allow investments on EU buses; allow…
May 22, 2025
bc9307c
work in progress
Jul 1, 2025
fe26655
work in progress
Jul 7, 2025
9c67ce6
config_provider usage; upper and lower bound distinction;
Jul 7, 2025
4160dad
Merge branch 'main' into fix-foreign-investments
Jul 7, 2025
9d37529
Refactor foreign investments configuration and logic in the network s…
Jul 14, 2025
11cd8cd
Merge branch 'fix-foreign-investments' of github.com:PyPSA/pypsa-de i…
Jul 14, 2025
4495930
Merge remote-tracking branch 'origin/main' into fix-foreign-investments
Jul 14, 2025
9d35205
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 14, 2025
1e2786b
refactor: remove system path adjustment
Jul 14, 2025
76240f1
Merge branch 'fix-foreign-investments' of github.com:PyPSA/pypsa-de i…
Jul 14, 2025
69be1c3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 14, 2025
db944b5
set small slack as default (recommended in combination with one itera…
Jul 18, 2025
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 CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Changelog
- Provide option to fix foreign investments outside Germany to optimized capacities of reference scenario
- Longer lifetime (40 years) is only applied to existing gas CHPs, not new ones. Added a new config entry `existing_capacities:fill_value_gas_chp_lifetime`
- Bugfix: gas CHPs are extendable again
- Simplified scenarion definition and made `Mix` the default scenario
Expand Down
16 changes: 16 additions & 0 deletions Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,17 @@ rule modify_district_heat_share:
"scripts/pypsa-de/modify_district_heat_share.py"


def get_reference_network(w):
ref_scenario = config_provider("fix_foreign_investments", "reference_scenario")(w)
if (
config_provider("fix_foreign_investments", "enable")(w)
and w.run != ref_scenario
):
return f"results/{config_provider("run", "prefix")(w)}/{ref_scenario}/networks/base_s_{w.clusters}_{w.opts}_{w.sector_opts}_{w.planning_horizons}.nc"
else:
return []


rule modify_prenetwork:
params:
efuel_export_ban=config_provider("solving", "constraints", "efuel_export_ban"),
Expand Down Expand Up @@ -553,6 +564,10 @@ rule modify_prenetwork:
shipping_methanol_share=config_provider("sector", "shipping_methanol_share"),
mwh_meoh_per_tco2=config_provider("sector", "MWh_MeOH_per_tCO2"),
scale_capacity=config_provider("scale_capacity"),
fix_foreign_investments=lambda w: config_provider("fix_foreign_investments")(w),
enable_fix_foreign_investments=lambda w: config_provider(
"fix_foreign_investments", "enable"
)(w),
input:
costs_modifications="ariadne-data/costs_{planning_horizons}-modifications.csv",
network=resources(
Expand Down Expand Up @@ -581,6 +596,7 @@ rule modify_prenetwork:
regions_onshore=resources("regions_onshore_base_s_{clusters}.geojson"),
regions_offshore=resources("regions_offshore_base_s_{clusters}.geojson"),
offshore_connection_points="ariadne-data/offshore_connection_points.csv",
reference_network=get_reference_network,
output:
network=resources(
"networks/base_s_{clusters}_{opts}_{sector_opts}_{planning_horizons}_final.nc"
Expand Down
9 changes: 8 additions & 1 deletion config/config.de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run
run:
prefix: 20253006_fix_chp_lifetime
prefix: 20250714_fix_neighbours
name:
# - ExPol
- KN2045_Mix
Expand Down Expand Up @@ -77,6 +77,13 @@ existing_capacities:
# Germany plus 12 "Stromnachbarn"
countries: ['AT', 'BE', 'CH', 'CZ', 'DE', 'DK', 'FR', 'GB', 'LU', 'NL', 'NO', 'PL', 'SE', 'ES', 'IT']

fix_foreign_investments:
enable: false
reference_scenario: KN2045_Mix
nom_min: true
nom_max: true
slack: 1.e-5

# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#snapshots
snapshots:
start: "2019-01-01"
Expand Down
3 changes: 3 additions & 0 deletions rules/solve_myopic.smk
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ rule solve_sector_network_myopic:
),
custom_extra_functionality=input_custom_extra_functionality,
energy_year=config_provider("energy", "energy_totals_year"),
fix_foreign_investments=config_provider(
"fix_foreign_investments"
)
input:
network=resources(
"networks/base_s_{clusters}_{opts}_{sector_opts}_{planning_horizons}_final.nc"
Expand Down
237 changes: 234 additions & 3 deletions scripts/pypsa-de/modify_prenetwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
import pypsa
from shapely.geometry import Point

from scripts._helpers import configure_logging, mock_snakemake, sanitize_custom_columns
from scripts._helpers import (
configure_logging,
mock_snakemake,
sanitize_custom_columns,
set_scenario_config,
update_config_from_wildcards,
)
from scripts.add_electricity import load_costs
from scripts.prepare_sector_network import lossy_bidirectional_links

Expand Down Expand Up @@ -1265,6 +1271,212 @@ def scale_capacity(n, scaling):
]


def _get_component_pair(n, n_ref, component_type):
"""
Get component dataframes from both networks.

Parameters
----------
n : pypsa.Network
Network object to modify.
n_ref : pypsa.Network
Reference network object.
component_type : str
Component type name.

Returns
-------
tuple
(component, baseline_component) dataframes.
"""
if component_type == "StorageUnit":
component = getattr(n, "storage_units")
baseline_component = getattr(n_ref, "storage_units")
else:
component = getattr(n, component_type.lower() + "s")
baseline_component = getattr(n_ref, component_type.lower() + "s")
return component, baseline_component


def _identify_non_german_extendable(component, component_type):
"""
Identify non-German extendable components.

Parameters
----------
component : pd.DataFrame
Component dataframe.
component_type : str
Component type name.

Returns
-------
pd.Series
Boolean series indicating components to fix.
"""
# Identify non-German nodes
if component_type in ["Line", "Link"]:
# For lines and links, check both buses
non_german = component.filter(regex="bus[012]").apply(
lambda x: (~x.str.startswith("DE").any()) & (not x.name.startswith("EU")),
axis=1,
)
else:
# For other components, check if bus is not in Germany
non_german = ~component.bus.str.startswith(("DE", "EU"))

# Only fix extendable components
extendable = (
component.e_nom_extendable
if component_type == "Store"
else (
component.s_nom_extendable
if component_type == "Line"
else component.p_nom_extendable
)
)
return non_german & extendable


def _apply_capacity_limits(
n, component_type, indices, baseline_component, slack, nom_min, nom_max
):
"""
Apply capacity limits to components.

Parameters
----------
n : pypsa.Network
Network object to modify.
component_type : str
Component type name.
indices : pd.Index
Indices of components to modify.
baseline_component : pd.DataFrame
Reference component dataframe.
slack : float
Slack factor to apply to capacity limits.
nom_min : bool
Whether to set minimum capacity limit.
nom_max : bool
Whether to set maximum capacity limit.
"""
# Determine capacity attributes based on component type
if component_type == "Store":
nom_attr, nom_opt_attr, nom_min_attr, nom_max_attr, extendable_attr = (
"e_nom",
"e_nom_opt",
"e_nom_min",
"e_nom_max",
"e_nom_extendable",
)
component_df = n.stores
elif component_type == "Line":
nom_attr, nom_opt_attr, nom_min_attr, nom_max_attr, extendable_attr = (
"s_nom",
"s_nom_opt",
"s_nom_min",
"s_nom_max",
"s_nom_extendable",
)
component_df = n.lines
else:
nom_attr, nom_opt_attr, nom_min_attr, nom_max_attr, extendable_attr = (
"p_nom",
"p_nom_opt",
"p_nom_min",
"p_nom_max",
"p_nom_extendable",
)
component_df = n.df(component_type)

if nom_min and nom_max and slack == 0:
# If both min and max are set, use optimized value directly
component_df.loc[indices, nom_attr] = baseline_component.loc[
indices, nom_opt_attr
]
component_df.loc[indices, extendable_attr] = False
else:
if nom_min:
component_df.loc[indices, nom_min_attr] = baseline_component.loc[
indices
].apply(
lambda row: max(
np.floor(row[nom_opt_attr]) * (1 - slack),
row[nom_min_attr],
),
axis=1,
)
if nom_max:
component_df.loc[indices, nom_max_attr] = baseline_component.loc[
indices
].apply(
lambda row: min(
np.ceil(row[nom_opt_attr]) * (1 + slack),
row[nom_max_attr],
),
axis=1,
)


def fix_foreign_investments(n, n_ref, slack=0, nom_min=True, nom_max=False):
"""
For all extendable components located outside Germany, this function sets their
minimum and maximum capacity limits to match the optimized capacity from a
reference network. This effectively fixes the investment decisions for these
components to their reference values.

Components are identified as non-German based on their bus location:
- For Line and Link: any connected bus is outside Germany
- For other components: the primary bus is outside Germany

Capacities of EU components are not fixed.

Only components with extendable capacity are modified (those with
[p|s|e]_nom_extendable set to True).

Parameters
----------
n : pypsa.Network
Network object to modify.
n_ref : pypsa.Network
Reference network object containing optimized capacity values.
slack : float, optional
Slack factor to apply to the capacity limits. Default is 0.
nom_min : bool, optional
Whether to set the minimum capacity limit. Default is True.
nom_max : bool, optional
Whether to set the maximum capacity limit. Default is False.

Returns
-------
None
Network is modified in-place with updated capacity limits.
"""
# List of component types that can have investment decisions
investment_components = ["Generator", "StorageUnit", "Store", "Link", "Line"]

# For each component type
for component_type in investment_components:
component, baseline_component = _get_component_pair(n, n_ref, component_type)

to_fix = _identify_non_german_extendable(component, component_type)

if not any(to_fix):
continue

indices = component.index[to_fix]

# Set optimized capacity from reference network as lower and upper
# bound rounding values to the nearest integer and inserting slack
# to avoid constraint violations
_apply_capacity_limits(
n, component_type, indices, baseline_component, slack, nom_min, nom_max
)

logger.info(f"Fixed {sum(to_fix)} {component_type} components outside Germany")


if __name__ == "__main__":
if "snakemake" not in globals():
snakemake = mock_snakemake(
Expand All @@ -1274,11 +1486,13 @@ def scale_capacity(n, scaling):
opts="",
ll="vopt",
sector_opts="none",
planning_horizons="2025",
run="KN2045_Mix",
planning_horizons="2045",
run="KN2045_Mix_10solarCAPEX_notfixed",
)

configure_logging(snakemake)
set_scenario_config(snakemake)
update_config_from_wildcards(snakemake.config, snakemake.wildcards)
logger.info("Adding Ariadne-specific functionality")

n = pypsa.Network(snakemake.input.network)
Expand Down Expand Up @@ -1347,4 +1561,21 @@ def scale_capacity(n, scaling):

sanitize_custom_columns(n)

if (
snakemake.params["fix_foreign_investments"]["enable"]
and snakemake.wildcards.run
!= snakemake.params["fix_foreign_investments"]["reference_scenario"]
):
logger.info(
"Fixing investments for components outside Germany based on the reference scenario."
)
n_ref = pypsa.Network(snakemake.input.reference_network)
fix_foreign_investments(
n,
n_ref,
snakemake.params["fix_foreign_investments"]["slack"],
snakemake.params["fix_foreign_investments"]["nom_min"],
snakemake.params["fix_foreign_investments"]["nom_max"],
)

n.export_to_netcdf(snakemake.output.network)
Loading
Loading