add release notes, minor code improvements
This commit is contained in:
parent
d98ad95332
commit
2183e742b2
@ -28,6 +28,24 @@ Upcoming Release
|
||||
|
||||
* Cluster residential and services heat buses by default. Can be disabled with ``cluster_heat_buses: false``.
|
||||
|
||||
* Bugfix: Do not reduce district heat share when building population-weighted
|
||||
energy statistics. Previously the district heating share was being multiplied
|
||||
by the population weighting, reducing the DH share with multiple nodes.
|
||||
|
||||
* Move building of daily heat profile to its own rule
|
||||
:mod:`build_hourly_heat_demand` from :mod:`prepare_sector_network`.
|
||||
|
||||
* In :mod:`build_energy_totals`, district heating shares are now reported in a
|
||||
separate file.
|
||||
|
||||
* Move calculation of district heating share to its own rule
|
||||
:mod:`build_district_heat_share`.
|
||||
|
||||
* Move building of distribution of existing heating to own rule
|
||||
:mod:`build_existing_heating_distribution`. This makes the distribution of
|
||||
existing heating to urban/rural, residential/services and spatially more
|
||||
transparent.
|
||||
|
||||
|
||||
PyPSA-Eur 0.9.0 (5th January 2024)
|
||||
==================================
|
||||
|
@ -20,6 +20,12 @@ Rule ``add_existing_baseyear``
|
||||
|
||||
.. automodule:: add_existing_baseyear
|
||||
|
||||
Rule ``build_existing_heating_distribution``
|
||||
==============================================================================
|
||||
|
||||
.. automodule:: build_existing_heating_distribution
|
||||
|
||||
|
||||
Rule ``build_ammonia_production``
|
||||
==============================================================================
|
||||
|
||||
@ -60,10 +66,20 @@ Rule ``build_gas_network``
|
||||
|
||||
.. automodule:: build_gas_network
|
||||
|
||||
Rule ``build_heat_demand``
|
||||
Rule ``build_daily_heat_demand``
|
||||
==============================================================================
|
||||
|
||||
.. automodule:: build_heat_demand
|
||||
.. automodule:: build_daily_heat_demand
|
||||
|
||||
Rule ``build_hourly_heat_demand``
|
||||
==============================================================================
|
||||
|
||||
.. automodule:: build_hourly_heat_demand
|
||||
|
||||
Rule ``build_district_heat_share``
|
||||
==============================================================================
|
||||
|
||||
.. automodule:: build_district_heat_share
|
||||
|
||||
Rule ``build_industrial_distribution_key``
|
||||
==============================================================================
|
||||
|
@ -28,9 +28,10 @@ rule solve_sector_network:
|
||||
+ "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_memory.log",
|
||||
python=RESULTS
|
||||
+ "logs/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}_python.log",
|
||||
threads: config["solving"]["solver_options"][config["solving"]["solver"]["options"]].get(
|
||||
"threads", 4
|
||||
)
|
||||
threads:
|
||||
config["solving"]["solver_options"][
|
||||
config["solving"]["solver"]["options"]
|
||||
].get("threads", 4)
|
||||
resources:
|
||||
mem_mb=config["solving"]["mem"],
|
||||
walltime=config["solving"].get("walltime", "12:00:00"),
|
||||
|
@ -451,7 +451,7 @@ def add_heating_capacities_installed_before_baseyear(
|
||||
efficiency=efficiency,
|
||||
capital_cost=costs.at[costs_name, "efficiency"]
|
||||
* costs.at[costs_name, "fixed"],
|
||||
p_nom=existing_heating[(name, f"{heat_pump_type} heat pump")][nodes] * ratio / costs.at[costs_name, "efficiency"],
|
||||
p_nom=existing_heating.loc[nodes, (name, f"{heat_pump_type} heat pump")] * ratio / costs.at[costs_name, "efficiency"],
|
||||
build_year=int(grouping_year),
|
||||
lifetime=costs.at[costs_name, "lifetime"],
|
||||
)
|
||||
@ -470,7 +470,7 @@ def add_heating_capacities_installed_before_baseyear(
|
||||
* costs.at[f"{name_type} resistive heater", "fixed"]
|
||||
),
|
||||
p_nom=(
|
||||
existing_heating[(name, "resistive heater")][nodes]
|
||||
existing_heating.loc[nodes, (name, "resistive heater")]
|
||||
* ratio
|
||||
/ costs.at[f"{name_type} resistive heater", "efficiency"]
|
||||
),
|
||||
@ -493,7 +493,7 @@ def add_heating_capacities_installed_before_baseyear(
|
||||
* costs.at[f"{name_type} gas boiler", "fixed"]
|
||||
),
|
||||
p_nom=(
|
||||
existing_heating[(name, "gas boiler")][nodes]
|
||||
existing_heating.loc[nodes, (name, "gas boiler")]
|
||||
* ratio
|
||||
/ costs.at[f"{name_type} gas boiler", "efficiency"]
|
||||
),
|
||||
@ -514,7 +514,7 @@ def add_heating_capacities_installed_before_baseyear(
|
||||
capital_cost=costs.at["decentral oil boiler", "efficiency"]
|
||||
* costs.at["decentral oil boiler", "fixed"],
|
||||
p_nom= (
|
||||
existing_heating[(name, "oil boiler")][nodes]
|
||||
existing_heating.loc[nodes, (name, "oil boiler")]
|
||||
* ratio
|
||||
/ costs.at["decentral oil boiler", "efficiency"]),
|
||||
build_year=int(grouping_year),
|
||||
|
@ -18,7 +18,8 @@ if __name__ == "__main__":
|
||||
from _helpers import mock_snakemake
|
||||
|
||||
snakemake = mock_snakemake(
|
||||
"build_heat_demands",
|
||||
"build_daily_heat_demands",
|
||||
scope="total",
|
||||
simpl="",
|
||||
clusters=48,
|
||||
)
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors
|
||||
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
@ -21,9 +21,10 @@ if __name__ == "__main__":
|
||||
from _helpers import mock_snakemake
|
||||
|
||||
snakemake = mock_snakemake(
|
||||
"build_heat_demands",
|
||||
"build_district_heat_share",
|
||||
simpl="",
|
||||
clusters=48,
|
||||
planning_horizons="2050",
|
||||
)
|
||||
|
||||
investment_year = int(snakemake.wildcards.planning_horizons[-4:])
|
||||
@ -68,10 +69,10 @@ if __name__ == "__main__":
|
||||
f"resulting in new average share of {dist_fraction_node.mean():.2%}"
|
||||
)
|
||||
|
||||
df = pd.DataFrame(dtype=float)
|
||||
|
||||
df["original district heat share"] = district_heat_share
|
||||
df["district fraction of node"] = dist_fraction_node
|
||||
df["urban fraction"] = urban_fraction
|
||||
df = pd.DataFrame({
|
||||
"original district heat share": district_heat_share,
|
||||
"district fraction of node": dist_fraction_node,
|
||||
"urban fraction": urban_fraction
|
||||
}, dtype=float)
|
||||
|
||||
df.to_csv(snakemake.output.district_heat_share)
|
||||
|
@ -583,10 +583,10 @@ def build_district_heat_share(countries, idees):
|
||||
# Missing district heating share
|
||||
dh_share = pd.read_csv(
|
||||
snakemake.input.district_heat_share, index_col=0, usecols=[0, 1]
|
||||
)
|
||||
).div(100).squeeze()
|
||||
# make conservative assumption and take minimum from both data sets
|
||||
district_heat_share = pd.concat(
|
||||
[district_heat_share, dh_share.reindex(index=district_heat_share.index) / 100], axis=1
|
||||
[district_heat_share, dh_share.reindex_like(district_heat_share)], axis=1
|
||||
).min(axis=1)
|
||||
|
||||
district_heat_share.name = "district heat share"
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-FileCopyrightText: : 2020-2023 The PyPSA-Eur Authors
|
||||
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
@ -7,8 +7,6 @@ Builds table of existing heat generation capacities for initial planning
|
||||
horizon.
|
||||
"""
|
||||
import pandas as pd
|
||||
import sys
|
||||
from pypsa.descriptors import Dict
|
||||
import numpy as np
|
||||
import country_converter as coco
|
||||
|
||||
@ -17,19 +15,13 @@ cc = coco.CountryConverter()
|
||||
|
||||
def build_existing_heating():
|
||||
# retrieve existing heating capacities
|
||||
techs = [
|
||||
"gas boiler",
|
||||
"oil boiler",
|
||||
"resistive heater",
|
||||
"air heat pump",
|
||||
"ground heat pump",
|
||||
]
|
||||
|
||||
existing_heating = pd.read_csv(snakemake.input.existing_heating,
|
||||
index_col=0,
|
||||
header=0)
|
||||
|
||||
# data for Albania, Montenegro and Macedonia not included in database existing_heating.loc["Albania"] = np.nan
|
||||
# data for Albania, Montenegro and Macedonia not included in database
|
||||
existing_heating.loc["Albania"] = np.nan
|
||||
existing_heating.loc["Montenegro"] = np.nan
|
||||
existing_heating.loc["Macedonia"] = np.nan
|
||||
|
||||
@ -104,5 +96,14 @@ def build_existing_heating():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
||||
snakemake = mock_snakemake(
|
||||
"build_existing_heating_distribution",
|
||||
simpl="",
|
||||
clusters=48,
|
||||
planning_horizons=2050,
|
||||
)
|
||||
|
||||
build_existing_heating()
|
||||
|
@ -6,19 +6,19 @@
|
||||
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
|
||||
|
||||
|
||||
import pandas as pd
|
||||
import xarray as xr
|
||||
from _helpers import generate_periodic_profiles
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "snakemake" not in globals():
|
||||
from _helpers import mock_snakemake
|
||||
|
||||
snakemake = mock_snakemake(
|
||||
"build_heat_demands",
|
||||
"build_hourly_heat_demands",
|
||||
scope="total",
|
||||
simpl="",
|
||||
clusters=48,
|
||||
)
|
||||
@ -58,12 +58,6 @@ if __name__ == "__main__":
|
||||
|
||||
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 = heat_demand.stack().to_xarray()
|
||||
|
||||
ds.to_netcdf(snakemake.output.heat_demand)
|
||||
|
@ -1654,7 +1654,7 @@ def build_heat_demand(n):
|
||||
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}"] = (
|
||||
electric_heat_supply[name] = (
|
||||
heat_demand_shape[name] / heat_demand_shape[name].sum()
|
||||
).multiply(pop_weighted_energy_totals[f"electricity {sector} {use}"]) * 1e6
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user