move building of daily heat profile to its own script
Previously this was handled inside prepare_sector_network.py.
This commit is contained in:
parent
fbff32dcfc
commit
6c20ce83d7
@ -123,7 +123,7 @@ rule cluster_gas_network:
|
||||
"../scripts/cluster_gas_network.py"
|
||||
|
||||
|
||||
rule build_heat_demands:
|
||||
rule build_daily_heat_demand:
|
||||
params:
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
input:
|
||||
@ -131,18 +131,39 @@ rule build_heat_demands:
|
||||
regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson",
|
||||
cutout="cutouts/" + CDIR + config["atlite"]["default_cutout"] + ".nc",
|
||||
output:
|
||||
heat_demand=RESOURCES + "heat_demand_{scope}_elec_s{simpl}_{clusters}.nc",
|
||||
heat_demand=RESOURCES + "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc",
|
||||
resources:
|
||||
mem_mb=20000,
|
||||
threads: 8
|
||||
log:
|
||||
LOGS + "build_heat_demands_{scope}_{simpl}_{clusters}.loc",
|
||||
LOGS + "build_daily_heat_demand_{scope}_{simpl}_{clusters}.loc",
|
||||
benchmark:
|
||||
BENCHMARKS + "build_heat_demands/{scope}_s{simpl}_{clusters}"
|
||||
BENCHMARKS + "build_daily_heat_demand/{scope}_s{simpl}_{clusters}"
|
||||
conda:
|
||||
"../envs/environment.yaml"
|
||||
script:
|
||||
"../scripts/build_heat_demand.py"
|
||||
"../scripts/build_daily_heat_demand.py"
|
||||
|
||||
|
||||
rule build_hourly_heat_demand:
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
input:
|
||||
heat_profile="data/heat_load_profile_BDEW.csv",
|
||||
heat_demand=RESOURCES + "daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc",
|
||||
output:
|
||||
heat_demand=RESOURCES + "hourly_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc",
|
||||
resources:
|
||||
mem_mb=2000,
|
||||
threads: 8
|
||||
log:
|
||||
LOGS + "build_hourly_heat_demand_{scope}_{simpl}_{clusters}.loc",
|
||||
benchmark:
|
||||
BENCHMARKS + "build_hourly_heat_demand/{scope}_s{simpl}_{clusters}"
|
||||
conda:
|
||||
"../envs/environment.yaml"
|
||||
script:
|
||||
"../scripts/build_hourly_heat_demand.py"
|
||||
|
||||
|
||||
rule build_temperature_profiles:
|
||||
@ -727,7 +748,6 @@ rule prepare_sector_network:
|
||||
if config["foresight"] == "overnight"
|
||||
else RESOURCES
|
||||
+ "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv",
|
||||
heat_profile="data/heat_load_profile_BDEW.csv",
|
||||
costs="data/costs_{}.csv".format(config["costs"]["year"])
|
||||
if config["foresight"] == "overnight"
|
||||
else "data/costs_{planning_horizons}.csv",
|
||||
@ -740,9 +760,7 @@ rule prepare_sector_network:
|
||||
simplified_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}.csv",
|
||||
industrial_demand=RESOURCES
|
||||
+ "industrial_energy_demand_elec_s{simpl}_{clusters}_{planning_horizons}.csv",
|
||||
heat_demand_urban=RESOURCES + "heat_demand_urban_elec_s{simpl}_{clusters}.nc",
|
||||
heat_demand_rural=RESOURCES + "heat_demand_rural_elec_s{simpl}_{clusters}.nc",
|
||||
heat_demand_total=RESOURCES + "heat_demand_total_elec_s{simpl}_{clusters}.nc",
|
||||
hourly_heat_demand_total=RESOURCES + "hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc",
|
||||
temp_soil_total=RESOURCES + "temp_soil_total_elec_s{simpl}_{clusters}.nc",
|
||||
temp_soil_rural=RESOURCES + "temp_soil_rural_elec_s{simpl}_{clusters}.nc",
|
||||
temp_soil_urban=RESOURCES + "temp_soil_urban_elec_s{simpl}_{clusters}.nc",
|
||||
|
69
scripts/build_hourly_heat_demand.py
Normal file
69
scripts/build_hourly_heat_demand.py
Normal file
@ -0,0 +1,69 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
Build hourly heat demand time series from daily ones.
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import xarray as xr
|
||||
from _helpers import generate_periodic_profiles, update_config_with_sector_opts
|
||||
from itertools import product
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
||||
snakemake = mock_snakemake(
|
||||
"build_heat_demands",
|
||||
simpl="",
|
||||
clusters=48,
|
||||
)
|
||||
|
||||
snapshots = pd.date_range(freq="h", **snakemake.params.snapshots)
|
||||
|
||||
daily_space_heat_demand = (
|
||||
xr.open_dataarray(snakemake.input.heat_demand)
|
||||
.to_pandas()
|
||||
.reindex(index=snapshots, method="ffill")
|
||||
)
|
||||
|
||||
intraday_profiles = pd.read_csv(snakemake.input.heat_profile, index_col=0)
|
||||
|
||||
sectors = ["residential", "services"]
|
||||
uses = ["water", "space"]
|
||||
|
||||
heat_demand = {}
|
||||
for sector, use in product(sectors, uses):
|
||||
weekday = list(intraday_profiles[f"{sector} {use} weekday"])
|
||||
weekend = list(intraday_profiles[f"{sector} {use} weekend"])
|
||||
weekly_profile = weekday * 5 + weekend * 2
|
||||
intraday_year_profile = generate_periodic_profiles(
|
||||
daily_space_heat_demand.index.tz_localize("UTC"),
|
||||
nodes=daily_space_heat_demand.columns,
|
||||
weekly_profile=weekly_profile,
|
||||
)
|
||||
|
||||
if use == "space":
|
||||
heat_demand[f"{sector} {use}"] = daily_space_heat_demand * intraday_year_profile
|
||||
else:
|
||||
heat_demand[f"{sector} {use}"] = intraday_year_profile
|
||||
|
||||
heat_demand = pd.concat(heat_demand,
|
||||
axis=1,
|
||||
names = ["sector use", "node"])
|
||||
|
||||
heat_demand.index.name="snapshots"
|
||||
|
||||
print(heat_demand)
|
||||
|
||||
print(heat_demand.stack())
|
||||
|
||||
ds = heat_demand.stack().to_xarray()#xr.Dataset.from_dataframe(heat_demand)
|
||||
|
||||
print(ds)
|
||||
|
||||
ds.to_netcdf(snakemake.output.heat_demand)
|
@ -18,7 +18,7 @@ import numpy as np
|
||||
import pandas as pd
|
||||
import pypsa
|
||||
import xarray as xr
|
||||
from _helpers import generate_periodic_profiles, update_config_with_sector_opts
|
||||
from _helpers import update_config_with_sector_opts
|
||||
from add_electricity import calculate_annuity, sanitize_carriers
|
||||
from build_energy_totals import build_co2_totals, build_eea_co2, build_eurostat_co2
|
||||
from networkx.algorithms import complement
|
||||
@ -1639,14 +1639,8 @@ def add_land_transport(n, costs):
|
||||
|
||||
|
||||
def build_heat_demand(n):
|
||||
# copy forward the daily average heat demand into each hour, so it can be multiplied by the intraday profile
|
||||
daily_space_heat_demand = (
|
||||
xr.open_dataarray(snakemake.input.heat_demand_total)
|
||||
.to_pandas()
|
||||
.reindex(index=n.snapshots, method="ffill")
|
||||
)
|
||||
|
||||
intraday_profiles = pd.read_csv(snakemake.input.heat_profile, index_col=0)
|
||||
heat_demand_shape = xr.open_dataset(snakemake.input.hourly_heat_demand_total).to_dataframe().unstack(level=1)
|
||||
|
||||
sectors = ["residential", "services"]
|
||||
uses = ["water", "space"]
|
||||
@ -1654,25 +1648,14 @@ def build_heat_demand(n):
|
||||
heat_demand = {}
|
||||
electric_heat_supply = {}
|
||||
for sector, use in product(sectors, uses):
|
||||
weekday = list(intraday_profiles[f"{sector} {use} weekday"])
|
||||
weekend = list(intraday_profiles[f"{sector} {use} weekend"])
|
||||
weekly_profile = weekday * 5 + weekend * 2
|
||||
intraday_year_profile = generate_periodic_profiles(
|
||||
daily_space_heat_demand.index.tz_localize("UTC"),
|
||||
nodes=daily_space_heat_demand.columns,
|
||||
weekly_profile=weekly_profile,
|
||||
)
|
||||
|
||||
if use == "space":
|
||||
heat_demand_shape = daily_space_heat_demand * intraday_year_profile
|
||||
else:
|
||||
heat_demand_shape = intraday_year_profile
|
||||
name = f"{sector} {use}"
|
||||
|
||||
heat_demand[f"{sector} {use}"] = (
|
||||
heat_demand_shape / heat_demand_shape.sum()
|
||||
heat_demand[name] = (
|
||||
heat_demand_shape[name] / heat_demand_shape[name].sum()
|
||||
).multiply(pop_weighted_energy_totals[f"total {sector} {use}"]) * 1e6
|
||||
electric_heat_supply[f"{sector} {use}"] = (
|
||||
heat_demand_shape / heat_demand_shape.sum()
|
||||
heat_demand_shape[name] / heat_demand_shape[name].sum()
|
||||
).multiply(pop_weighted_energy_totals[f"electricity {sector} {use}"]) * 1e6
|
||||
|
||||
heat_demand = pd.concat(heat_demand, axis=1)
|
||||
|
Loading…
Reference in New Issue
Block a user