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

Fix geothermal heat potentials #1516

Merged
merged 24 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d1b4bd3
feat: refactor build_heat_source_potentials into build_geothermal_hea…
amos-schledorn Jan 22, 2025
e1d0951
feat: remove unnecessary snapshot index
amos-schledorn Jan 22, 2025
8caf588
chore: refactor accordingly
amos-schledorn Jan 22, 2025
c3174eb
feat: fix scaling factor
amos-schledorn Jan 23, 2025
43ddea2
Merge remote-tracking branch 'origin/master' into fix-isi-heat-potent…
amos-schledorn Jan 24, 2025
78af02f
feat: remove obsolete retrieve
amos-schledorn Jan 27, 2025
6efd49c
docs: update docs
amos-schledorn Jan 27, 2025
2b1e3b6
docs: update release notes
amos-schledorn Jan 27, 2025
afb0710
Merge 'master' into feature
amos-schledorn Jan 27, 2025
3080d25
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 27, 2025
ec50506
Merge branch 'master' into fix-isi-heat-potentials
amos-schledorn Feb 11, 2025
2c45c8e
feat: use retrieve separate retrieve rules
amos-schledorn Feb 11, 2025
6383374
merge remote
amos-schledorn Feb 11, 2025
54dd441
merge origin/master
amos-schledorn Feb 11, 2025
b4b1a02
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 11, 2025
15aa654
feat: remove conda env from new retrieve rules
amos-schledorn Feb 11, 2025
c0161a7
fix file names
amos-schledorn Feb 12, 2025
2afb3ad
fix config passing
amos-schledorn Feb 12, 2025
3e9e0e6
merge origin
amos-schledorn Feb 12, 2025
08427e2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 12, 2025
fdba9a5
Merge branch 'master' into fix-isi-heat-potentials
amos-schledorn Feb 12, 2025
b948a39
Merge branch 'master' into fix-isi-heat-potentials
amos-schledorn Feb 17, 2025
bc011db
style: remove snakemake access in add_heat
amos-schledorn Feb 17, 2025
2042066
Merge remote-tracking branch 'origin/fix-isi-heat-potentials' into fi…
amos-schledorn Feb 17, 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
9 changes: 1 addition & 8 deletions config/config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -482,16 +482,9 @@ sector:
heat_exchanger_pinch_point_temperature_difference: 5 #K
isentropic_compressor_efficiency: 0.8
heat_loss: 0.0
heat_utilisation_potentials:
limited_heat_sources:
geothermal:
# activate for 85C hydrothermal
# key: hydrothermal_85
# constant_temperature_celsius: 85
key: hydrothermal_65
constant_temperature_celsius: 65
column_name: Energy_TWh
unit: TWh
full_load_hours: 4000
direct_utilisation_heat_sources:
- geothermal
heat_pump_sources:
Expand Down
8 changes: 2 additions & 6 deletions doc/configtables/sector.csv
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@ district_heating,--,,`prepare_sector_network.py <https://github.com/PyPSA/pypsa-
-- -- heat_exchanger_pinch_point_temperature_difference,K,float,Heat pump pinch point temperature difference in heat exchangers assumed for approximation.
-- -- isentropic_compressor_efficiency,--,float,Isentropic efficiency of heat pump compressor assumed for approximation. Must be between 0 and 1.
-- -- heat_loss,--,float,Heat pump heat loss assumed for approximation. Must be between 0 and 1.
-- heat_utilisation_potentials,--,Dictionary with names of heat sources for which data by Fraunhofer ISI (`Manz et al. 2024 <https://www.sciencedirect.com/science/article/pii/S0960148124001769>) should be used,
-- limited_heat_sources,--,Dictionary with names of limited heat sources (not air) for which data by Fraunhofer ISI (`Manz et al. 2024 <https://www.sciencedirect.com/science/article/pii/S0960148124001769>) is used,
-- -- geothermal,-,Name of the heat source. Must be the same as in ``heat_pump_sources``,
-- -- -- key,-,string used to complete URL for data download - e.g. `geothermal_65` or `geothermal_85`","i.e file names in `Fordatis <https://fordatis.fraunhofer.de/handle/fordatis/341.3?mode=simple>`"
-- -- -- constant_temperature_celsius,C,heat source temperature,
-- -- -- column_name,-,name of the data column in retrieved GeoDataFrame,
-- -- -- unit,-,unit of heat source potential must be in (K/M/G/T)Wh,
-- -- -- full_load_hours,h,assumed full-load hours in Manz et al. (used to scale from utilisation to technical potential),
-- -- -- constant_temperature_celsius,°C,heat source temperature,
-- direct_utilisation_heat_sources,--,List of heat sources for direct heat utilisation in district heating. Must be in the keys of `heat_utilisation_potentials` (e.g. ``geothermal``),
-- heat_pump_sources,--,,
-- -- urban central,--,List of heat sources for heat pumps in urban central heating,
Expand Down
4 changes: 3 additions & 1 deletion doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Release Notes
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)
* Bugfix: Geothermal heat potentials are now restricted to those in close proximity to future district heating areas as projected by Manz et al. 2024. Includes a refactoring change: Building of generic technical potentials from heat utilisation potentials was changed to specific computation of geothermal heat potentials.

- ...

- 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.

Expand Down
53 changes: 32 additions & 21 deletions rules/build_sector.smk
Original file line number Diff line number Diff line change
Expand Up @@ -276,26 +276,35 @@ rule build_central_heating_temperature_profiles:
"../scripts/build_central_heating_temperature_profiles/run.py"


rule build_heat_source_potentials:
rule build_geothermal_heat_potential:
params:
heat_utilisation_potentials=config_provider(
"sector", "district_heating", "heat_utilisation_potentials"
drop_leap_day=config_provider("enable", "drop_leap_day"),
countries=config_provider("countries"),
constant_temperature_celsius=config_provider(
"sector",
"district_heating",
"limited_heat_sources",
"geothermal",
"constant_temperature_celsius",
),
input:
utilisation_potential="data/heat_source_utilisation_potentials/{heat_source}.gpkg",
isi_heat_potentials="data/isi_heat_utilisation_potentials.xlsx",
regions_onshore=resources("regions_onshore_base_s_{clusters}.geojson"),
lau_regions="data/lau_regions.zip",
output:
resources("heat_source_potential_{heat_source}_base_s_{clusters}.csv"),
heat_source_power=resources(
"heat_source_power_geothermal_base_s_{clusters}.csv"
),
resources:
mem_mb=2000,
log:
logs("build_heat_source_potentials_{heat_source}_s_{clusters}.log"),
logs("build_heat_source_potentials_geothermal_s_{clusters}.log"),
benchmark:
benchmarks("build_heat_source_potentials/{heat_source}_s_{clusters}")
benchmarks("build_heat_source_potentials/geothermal_s_{clusters}")
conda:
"../envs/environment.yaml"
script:
"../scripts/build_heat_source_potentials/run.py"
"../scripts/build_geothermal_heat_potential.py"


rule build_cop_profiles:
Expand All @@ -310,8 +319,8 @@ rule build_cop_profiles:
"sector", "district_heating", "heat_pump_cop_approximation"
),
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
heat_utilisation_potentials=config_provider(
"sector", "district_heating", "heat_utilisation_potentials"
limited_heat_sources=config_provider(
"sector", "district_heating", "limited_heat_sources"
),
snapshots=config_provider("snapshots"),
input:
Expand Down Expand Up @@ -343,8 +352,8 @@ rule build_direct_heat_source_utilisation_profiles:
direct_utilisation_heat_sources=config_provider(
"sector", "district_heating", "direct_utilisation_heat_sources"
),
heat_utilisation_potentials=config_provider(
"sector", "district_heating", "heat_utilisation_potentials"
limited_heat_sources=config_provider(
"sector", "district_heating", "limited_heat_sources"
),
snapshots=config_provider("snapshots"),
input:
Expand Down Expand Up @@ -1059,17 +1068,19 @@ rule build_egs_potentials:
"../scripts/build_egs_potentials.py"


def input_heat_source_potentials(w):
def input_heat_source_power(w):

return {
heat_source_name: resources(
"heat_source_potential_" + heat_source_name + "_base_s_{clusters}.csv"
"heat_source_power_" + heat_source_name + "_base_s_{clusters}.csv"
)
for heat_source_name in config_provider(
"sector", "district_heating", "heat_utilisation_potentials"
)(w).keys()
"sector", "heat_pump_sources", "urban central"
)(w)
if heat_source_name
in config_provider("sector", "heat_pump_sources", "urban central")(w)
in config_provider("sector", "district_heating", "limited_heat_sources")(
w
).keys()
}


Expand Down Expand Up @@ -1097,15 +1108,15 @@ rule prepare_sector_network:
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
heat_systems=config_provider("sector", "heat_systems"),
energy_totals_year=config_provider("energy", "energy_totals_year"),
heat_utilisation_potentials=config_provider(
"sector", "district_heating", "heat_utilisation_potentials"
),
direct_utilisation_heat_sources=config_provider(
"sector", "district_heating", "direct_utilisation_heat_sources"
),
limited_heat_sources=config_provider(
"sector", "district_heating", "limited_heat_sources"
),
input:
unpack(input_profile_offwind),
unpack(input_heat_source_potentials),
unpack(input_heat_source_power),
**rules.cluster_gas_network.output,
**rules.build_gas_input_locations.output,
snapshot_weightings=resources(
Expand Down
43 changes: 29 additions & 14 deletions rules/retrieve.smk
Original file line number Diff line number Diff line change
Expand Up @@ -650,23 +650,38 @@ if config["enable"]["retrieve"]:
script:
"../scripts/retrieve_osm_boundaries.py"


if config["enable"]["retrieve"]:

rule retrieve_heat_source_utilisation_potentials:
params:
heat_source="{heat_source}",
heat_utilisation_potentials=config_provider(
"sector", "district_heating", "heat_utilisation_potentials"
rule retrieve_geothermal_heat_utilisation_potentials:
input:
isi_heat_potentials=storage(
"https://fordatis.fraunhofer.de/bitstream/fordatis/341.3/12/Results_DH_Matching_Cluster.xlsx",
keep_local=True,
),
output:
"data/isi_heat_utilisation_potentials.xlsx",
log:
"logs/retrieve_heat_source_potentials_{heat_source}.log",
resources:
mem_mb=500,
"logs/retrieve_geothermal_heat_utilisation_potentials.log",
threads: 1
retries: 2
run:
move(input[0], output[0])

rule retrieve_lau_regions:
input:
lau_regions=storage(
"https://gisco-services.ec.europa.eu/distribution/v2/lau/download/ref-lau-2019-01m.geojson.zip",
keep_local=True,
),
output:
"data/heat_source_utilisation_potentials/{heat_source}.gpkg",
script:
"../scripts/retrieve_heat_source_utilisation_potentials.py"
lau_regions="data/lau_regions.geojson",
log:
"logs/retrieve_lau_regions.log",
lau_regions="data/lau_regions.zip",
log:
"logs/retrieve_lau_regions.log",
threads: 1
retries: 2
run:
move(input[0], output[0])


if config["enable"]["retrieve"]:
Expand Down
4 changes: 2 additions & 2 deletions scripts/build_cop_profiles/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ def get_cop(
f"temp_{heat_source.replace('ground', 'soil')}_total"
]
)
elif heat_source in snakemake.params.heat_utilisation_potentials.keys():
elif heat_source in snakemake.params.limited_heat_sources.keys():
source_inlet_temperature_celsius = (
snakemake.params.heat_utilisation_potentials[heat_source][
snakemake.params.limited_heat_sources[heat_source][
"constant_temperature_celsius"
]
)
Expand Down
4 changes: 2 additions & 2 deletions scripts/build_direct_heat_source_utilisation_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def get_source_temperature(heat_source_key: str):
If the heat source is unknown (not in `config`).
"""

if heat_source_key in snakemake.params.heat_utilisation_potentials.keys():
return snakemake.params.heat_utilisation_potentials[heat_source_key][
if heat_source_key in snakemake.params.limited_heat_sources.keys():
return snakemake.params.limited_heat_sources[heat_source_key][
"constant_temperature_celsius"
]
else:
Expand Down
Loading
Loading