update myopic mode to heat system declarations
This commit is contained in:
parent
10e0b30a40
commit
5362c37696
@ -69,6 +69,7 @@ rule add_brownfield:
|
|||||||
snapshots=config_provider("snapshots"),
|
snapshots=config_provider("snapshots"),
|
||||||
drop_leap_day=config_provider("enable", "drop_leap_day"),
|
drop_leap_day=config_provider("enable", "drop_leap_day"),
|
||||||
carriers=config_provider("electricity", "renewable_carriers"),
|
carriers=config_provider("electricity", "renewable_carriers"),
|
||||||
|
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
|
||||||
input:
|
input:
|
||||||
unpack(input_profile_tech_brownfield),
|
unpack(input_profile_tech_brownfield),
|
||||||
simplify_busmap=resources("busmap_elec_s{simpl}.csv"),
|
simplify_busmap=resources("busmap_elec_s{simpl}.csv"),
|
||||||
@ -77,18 +78,7 @@ rule add_brownfield:
|
|||||||
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
||||||
network_p=solved_previous_horizon, #solved network at previous time step
|
network_p=solved_previous_horizon, #solved network at previous time step
|
||||||
costs=resources("costs_{planning_horizons}.csv"),
|
costs=resources("costs_{planning_horizons}.csv"),
|
||||||
cop_soil_decentral_heating=resources(
|
cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"),
|
||||||
"cop_soil_decentral_heating_elec_s{simpl}_{clusters}.nc"
|
|
||||||
),
|
|
||||||
cop_air_decentral_heating=resources(
|
|
||||||
"cop_air_decentral_heating_elec_s{simpl}_{clusters}.nc"
|
|
||||||
),
|
|
||||||
cop_air_central_heating=resources(
|
|
||||||
"cop_air_central_heating_elec_s{simpl}_{clusters}.nc"
|
|
||||||
),
|
|
||||||
cop_soil_central_heating=resources(
|
|
||||||
"cop_soil_central_heating_elec_s{simpl}_{clusters}.nc"
|
|
||||||
),
|
|
||||||
output:
|
output:
|
||||||
RESULTS
|
RESULTS
|
||||||
+ "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
+ "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
||||||
|
@ -438,8 +438,8 @@ def add_heating_capacities_installed_before_baseyear(
|
|||||||
currently assumed heating capacities split between residential and
|
currently assumed heating capacities split between residential and
|
||||||
services proportional to heating load in both 50% capacities
|
services proportional to heating load in both 50% capacities
|
||||||
in rural buses 50% in urban buses
|
in rural buses 50% in urban buses
|
||||||
cop: dict
|
cop: xr.DataArray
|
||||||
Dictionary with time-dependent coefficients of performance (COPs) for air and ground heat pumps as values and keys "air decentral", "ground decentral", "air central", "ground central"
|
DataArray with time-dependent coefficients of performance (COPs) heat pumps. Coordinates are heat sources (see config), heat system types (see :file:`scripts/enums/HeatSystemType.py`), nodes and snapshots.
|
||||||
time_dep_hp_cop: bool
|
time_dep_hp_cop: bool
|
||||||
If True, time-dependent (dynamic) COPs are used for heat pumps
|
If True, time-dependent (dynamic) COPs are used for heat pumps
|
||||||
"""
|
"""
|
||||||
@ -452,66 +452,65 @@ def add_heating_capacities_installed_before_baseyear(
|
|||||||
n.buses.location[n.buses.index.str.contains(f"{heat_system} heat")]
|
n.buses.location[n.buses.index.str.contains(f"{heat_system} heat")]
|
||||||
)
|
)
|
||||||
|
|
||||||
if (not heat_system.is_central) and options["electricity_distribution_grid"]:
|
if (not heat_system == HeatSystem.URBAN_CENTRAL) and options["electricity_distribution_grid"]:
|
||||||
nodes_elec = nodes + " low voltage"
|
nodes_elec = nodes + " low voltage"
|
||||||
else:
|
else:
|
||||||
nodes_elec = nodes
|
nodes_elec = nodes
|
||||||
|
|
||||||
# Add heat pumps
|
too_large_grouping_years = [gy for gy in grouping_years if gy >= int(baseyear)]
|
||||||
heat_source = snakemake.params.heat_pump_sources[heat_system.system_type.value]
|
if too_large_grouping_years:
|
||||||
costs_name = f"{heat_system.system_type} {heat_source}-sourced heat pump"
|
logger.warning(
|
||||||
|
f"Grouping years >= baseyear are ignored. Dropping {too_large_grouping_years}."
|
||||||
efficiency = (
|
)
|
||||||
cop.sel(heat_system=heat_system.system_type.value, heat_source=heat_source, name=nodes)
|
valid_grouping_years = pd.Series(
|
||||||
.to_pandas()
|
[
|
||||||
.reindex(index=n.snapshots)
|
int(grouping_year)
|
||||||
if options["time_dep_hp_cop"]
|
for grouping_year in grouping_years
|
||||||
else costs.at[costs_name, "efficiency"]
|
if int(grouping_year) + default_lifetime > int(baseyear)
|
||||||
)
|
and int(grouping_year) < int(baseyear)
|
||||||
|
]
|
||||||
too_large_grouping_years = [gy for gy in grouping_years if gy >= int(baseyear)]
|
|
||||||
if too_large_grouping_years:
|
|
||||||
logger.warning(
|
|
||||||
f"Grouping years >= baseyear are ignored. Dropping {too_large_grouping_years}."
|
|
||||||
)
|
)
|
||||||
valid_grouping_years = pd.Series(
|
|
||||||
[
|
|
||||||
int(grouping_year)
|
|
||||||
for grouping_year in grouping_years
|
|
||||||
if int(grouping_year) + default_lifetime > int(baseyear)
|
|
||||||
and int(grouping_year) < int(baseyear)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
assert valid_grouping_years.is_monotonic_increasing
|
assert valid_grouping_years.is_monotonic_increasing
|
||||||
|
|
||||||
# get number of years of each interval
|
# get number of years of each interval
|
||||||
_years = valid_grouping_years.diff()
|
_years = valid_grouping_years.diff()
|
||||||
# Fill NA from .diff() with value for the first interval
|
# Fill NA from .diff() with value for the first interval
|
||||||
_years[0] = valid_grouping_years[0] - baseyear + default_lifetime
|
_years[0] = valid_grouping_years[0] - baseyear + default_lifetime
|
||||||
# Installation is assumed to be linear for the past
|
# Installation is assumed to be linear for the past
|
||||||
ratios = _years / _years.sum()
|
ratios = _years / _years.sum()
|
||||||
|
|
||||||
for ratio, grouping_year in zip(ratios, valid_grouping_years):
|
for ratio, grouping_year in zip(ratios, valid_grouping_years):
|
||||||
|
# Add heat pumps
|
||||||
|
for heat_source in snakemake.params.heat_pump_sources[heat_system.system_type.value]:
|
||||||
|
costs_name = heat_system.heat_pump_costs_name(heat_source)
|
||||||
|
|
||||||
n.madd(
|
efficiency = (
|
||||||
"Link",
|
cop.sel(heat_system=heat_system.system_type.value, heat_source=heat_source, name=nodes)
|
||||||
nodes,
|
.to_pandas()
|
||||||
suffix=f" {heat_system} {heat_source} heat pump-{grouping_year}",
|
.reindex(index=n.snapshots)
|
||||||
bus0=nodes_elec,
|
if options["time_dep_hp_cop"]
|
||||||
bus1=nodes + " " + heat_system.value + " heat",
|
else costs.at[costs_name, "efficiency"]
|
||||||
carrier=f"{heat_system} {heat_source} heat pump",
|
)
|
||||||
efficiency=efficiency,
|
|
||||||
capital_cost=costs.at[costs_name, "efficiency"]
|
n.madd(
|
||||||
* costs.at[costs_name, "fixed"],
|
"Link",
|
||||||
p_nom=existing_heating.loc[
|
nodes,
|
||||||
nodes, (heat_system.value, f"{heat_source} heat pump")
|
suffix=f" {heat_system} {heat_source} heat pump-{grouping_year}",
|
||||||
]
|
bus0=nodes_elec,
|
||||||
* ratio
|
bus1=nodes + " " + heat_system.value + " heat",
|
||||||
/ costs.at[costs_name, "efficiency"],
|
carrier=f"{heat_system} {heat_source} heat pump",
|
||||||
build_year=int(grouping_year),
|
efficiency=efficiency,
|
||||||
lifetime=costs.at[costs_name, "lifetime"],
|
capital_cost=costs.at[costs_name, "efficiency"]
|
||||||
)
|
* costs.at[costs_name, "fixed"],
|
||||||
|
p_nom=existing_heating.loc[
|
||||||
|
nodes, (heat_system.value, f"{heat_source} heat pump")
|
||||||
|
]
|
||||||
|
* ratio
|
||||||
|
/ costs.at[costs_name, "efficiency"],
|
||||||
|
build_year=int(grouping_year),
|
||||||
|
lifetime=costs.at[costs_name, "lifetime"],
|
||||||
|
)
|
||||||
|
|
||||||
# add resistive heater, gas boilers and oil boilers
|
# add resistive heater, gas boilers and oil boilers
|
||||||
n.madd(
|
n.madd(
|
||||||
@ -520,42 +519,42 @@ def add_heating_capacities_installed_before_baseyear(
|
|||||||
suffix=f" {heat_system} resistive heater-{grouping_year}",
|
suffix=f" {heat_system} resistive heater-{grouping_year}",
|
||||||
bus0=nodes_elec,
|
bus0=nodes_elec,
|
||||||
bus1=nodes + " " + heat_system.value + " heat",
|
bus1=nodes + " " + heat_system.value + " heat",
|
||||||
carrier=heat_system + " resistive heater",
|
carrier=heat_system.value + " resistive heater",
|
||||||
efficiency=costs.at[f"{heat_system.system_type} resistive heater", "efficiency"],
|
efficiency=costs.at[heat_system.resistive_heater_costs_name, "efficiency"],
|
||||||
capital_cost=(
|
capital_cost=(
|
||||||
costs.at[f"{heat_system.system_type} resistive heater", "efficiency"]
|
costs.at[heat_system.resistive_heater_costs_name, "efficiency"]
|
||||||
* costs.at[f"{heat_system.system_type} resistive heater", "fixed"]
|
* costs.at[heat_system.resistive_heater_costs_name, "fixed"]
|
||||||
),
|
),
|
||||||
p_nom=(
|
p_nom=(
|
||||||
existing_heating.loc[nodes, (heat_system.value, "resistive heater")]
|
existing_heating.loc[nodes, (heat_system.value, "resistive heater")]
|
||||||
* ratio
|
* ratio
|
||||||
/ costs.at[f"{heat_system.system_type} resistive heater", "efficiency"]
|
/ costs.at[heat_system.resistive_heater_costs_name, "efficiency"]
|
||||||
),
|
),
|
||||||
build_year=int(grouping_year),
|
build_year=int(grouping_year),
|
||||||
lifetime=costs.at[f"{heat_system.system_type} resistive heater", "lifetime"],
|
lifetime=costs.at[heat_system.resistive_heater_costs_name, "lifetime"],
|
||||||
)
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes,
|
nodes,
|
||||||
suffix=f" {heat_system} gas boiler-{grouping_year}",
|
suffix=f"{heat_system} gas boiler-{grouping_year}",
|
||||||
bus0="EU gas" if "EU gas" in spatial.gas.nodes else nodes + " gas",
|
bus0="EU gas" if "EU gas" in spatial.gas.nodes else nodes + " gas",
|
||||||
bus1=nodes + " " + heat_system + " heat",
|
bus1=f"{nodes} {heat_system} heat",
|
||||||
bus2="co2 atmosphere",
|
bus2="co2 atmosphere",
|
||||||
carrier=heat_system + " gas boiler",
|
carrier=heat_system.value + " gas boiler",
|
||||||
efficiency=costs.at[f"{heat_system.system_type} gas boiler", "efficiency"],
|
efficiency=costs.at[heat_system.gas_boiler_costs_name, "efficiency"],
|
||||||
efficiency2=costs.at["gas", "CO2 intensity"],
|
efficiency2=costs.at["gas", "CO2 intensity"],
|
||||||
capital_cost=(
|
capital_cost=(
|
||||||
costs.at[f"{heat_system.system_type} gas boiler", "efficiency"]
|
costs.at[heat_system.gas_boiler_costs_name, "efficiency"]
|
||||||
* costs.at[f"{heat_system.system_type} gas boiler", "fixed"]
|
* costs.at[heat_system.gas_boiler_costs_name, "fixed"]
|
||||||
),
|
),
|
||||||
p_nom=(
|
p_nom=(
|
||||||
existing_heating.loc[nodes, (heat_system, "gas boiler")]
|
existing_heating.loc[nodes, (heat_system.value, "gas boiler")]
|
||||||
* ratio
|
* ratio
|
||||||
/ costs.at[f"{heat_system.system_type} gas boiler", "efficiency"]
|
/ costs.at[heat_system.gas_boiler_costs_name, "efficiency"]
|
||||||
),
|
),
|
||||||
build_year=int(grouping_year),
|
build_year=int(grouping_year),
|
||||||
lifetime=costs.at[f"{heat_system.system_type} gas boiler", "lifetime"],
|
lifetime=costs.at[heat_system.gas_boiler_costs_name, "lifetime"],
|
||||||
)
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
@ -563,20 +562,20 @@ def add_heating_capacities_installed_before_baseyear(
|
|||||||
nodes,
|
nodes,
|
||||||
suffix=f" {heat_system} oil boiler-{grouping_year}",
|
suffix=f" {heat_system} oil boiler-{grouping_year}",
|
||||||
bus0=spatial.oil.nodes,
|
bus0=spatial.oil.nodes,
|
||||||
bus1=nodes + " " + heat_system + " heat",
|
bus1=f"{nodes} {heat_system} heat",
|
||||||
bus2="co2 atmosphere",
|
bus2="co2 atmosphere",
|
||||||
carrier=heat_system + " oil boiler",
|
carrier=heat_system.value + " oil boiler",
|
||||||
efficiency=costs.at["decentral oil boiler", "efficiency"],
|
efficiency=costs.at[heat_system.oil_boiler_costs_name, "efficiency"],
|
||||||
efficiency2=costs.at["oil", "CO2 intensity"],
|
efficiency2=costs.at["oil", "CO2 intensity"],
|
||||||
capital_cost=costs.at["decentral oil boiler", "efficiency"]
|
capital_cost=costs.at[heat_system.oil_boiler_costs_name, "efficiency"]
|
||||||
* costs.at["decentral oil boiler", "fixed"],
|
* costs.at[heat_system.oil_boiler_costs_name, "fixed"],
|
||||||
p_nom=(
|
p_nom=(
|
||||||
existing_heating.loc[nodes, (heat_system, "oil boiler")]
|
existing_heating.loc[nodes, (heat_system.value, "oil boiler")]
|
||||||
* ratio
|
* ratio
|
||||||
/ costs.at["decentral oil boiler", "efficiency"]
|
/ costs.at[heat_system.oil_boiler_costs_name, "efficiency"]
|
||||||
),
|
),
|
||||||
build_year=int(grouping_year),
|
build_year=int(grouping_year),
|
||||||
lifetime=costs.at[f"{heat_system.system_type} gas boiler", "lifetime"],
|
lifetime=costs.at[f"{heat_system.central_or_decentral} gas boiler", "lifetime"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# delete links with p_nom=nan corresponding to extra nodes in country
|
# delete links with p_nom=nan corresponding to extra nodes in country
|
||||||
@ -651,28 +650,7 @@ if __name__ == "__main__":
|
|||||||
n=n,
|
n=n,
|
||||||
baseyear=baseyear,
|
baseyear=baseyear,
|
||||||
grouping_years=grouping_years_heat,
|
grouping_years=grouping_years_heat,
|
||||||
cop={
|
cop=xr.open_dataarray(snakemake.input.cop_profiles),
|
||||||
"air decentral": xr.open_dataarray(
|
|
||||||
snakemake.input.cop_air_decentral_heating
|
|
||||||
)
|
|
||||||
.to_pandas()
|
|
||||||
.reindex(index=n.snapshots),
|
|
||||||
"ground decentral": xr.open_dataarray(
|
|
||||||
snakemake.input.cop_soil_decentral_heating
|
|
||||||
)
|
|
||||||
.to_pandas()
|
|
||||||
.reindex(index=n.snapshots),
|
|
||||||
"air central": xr.open_dataarray(
|
|
||||||
snakemake.input.cop_air_central_heating
|
|
||||||
)
|
|
||||||
.to_pandas()
|
|
||||||
.reindex(index=n.snapshots),
|
|
||||||
"ground central": xr.open_dataarray(
|
|
||||||
snakemake.input.cop_soil_central_heating
|
|
||||||
)
|
|
||||||
.to_pandas()
|
|
||||||
.reindex(index=n.snapshots),
|
|
||||||
},
|
|
||||||
time_dep_hp_cop=options["time_dep_hp_cop"],
|
time_dep_hp_cop=options["time_dep_hp_cop"],
|
||||||
costs=costs,
|
costs=costs,
|
||||||
default_lifetime=snakemake.params.existing_capacities[
|
default_lifetime=snakemake.params.existing_capacities[
|
||||||
|
@ -210,7 +210,7 @@ class HeatSystem(Enum):
|
|||||||
|
|
||||||
def heat_pump_costs_name(self, heat_source: str) -> str:
|
def heat_pump_costs_name(self, heat_source: str) -> str:
|
||||||
"""
|
"""
|
||||||
Generates the name for the heat pump costs based on the heat source.
|
Generates the name for the heat pump costs based on the heat source and system.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
@ -223,3 +223,41 @@ class HeatSystem(Enum):
|
|||||||
The name for the heat pump costs.
|
The name for the heat pump costs.
|
||||||
"""
|
"""
|
||||||
return f"{self.central_or_decentral} {heat_source}-sourced heat pump"
|
return f"{self.central_or_decentral} {heat_source}-sourced heat pump"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def resistive_heater_costs_name(self) -> str:
|
||||||
|
"""
|
||||||
|
Generates the name for the resistive heater costs based on the heat system.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The name for the heater costs.
|
||||||
|
"""
|
||||||
|
return f"{self.central_or_decentral} resistive heater"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gas_boiler_costs_name(self) -> str:
|
||||||
|
"""
|
||||||
|
Generates the name for the gas boiler costs based on the heat system.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The name for the gas boiler costs.
|
||||||
|
"""
|
||||||
|
return f"{self.central_or_decentral} gas boiler"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def oil_boiler_costs_name(self) -> str:
|
||||||
|
"""
|
||||||
|
Generates the name for the oil boiler costs based on the heat system.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The name for the oil boiler costs.
|
||||||
|
"""
|
||||||
|
return "decentral oil boiler"
|
||||||
|
|
||||||
|
|
||||||
|
@ -1802,7 +1802,7 @@ def build_heat_demand(n):
|
|||||||
return heat_demand
|
return heat_demand
|
||||||
|
|
||||||
|
|
||||||
def add_heat(n, costs):
|
def add_heat(n, costs, cop):
|
||||||
logger.info("Add heat sector")
|
logger.info("Add heat sector")
|
||||||
|
|
||||||
sectors = ["residential", "services"]
|
sectors = ["residential", "services"]
|
||||||
@ -1833,7 +1833,6 @@ def add_heat(n, costs):
|
|||||||
# 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2
|
# 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2
|
||||||
solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3
|
solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3
|
||||||
|
|
||||||
cop = xr.open_dataarray(snakemake.input.cop_profiles)
|
|
||||||
for (
|
for (
|
||||||
heat_system
|
heat_system
|
||||||
) in (
|
) in (
|
||||||
@ -4098,7 +4097,7 @@ if __name__ == "__main__":
|
|||||||
add_land_transport(n, costs)
|
add_land_transport(n, costs)
|
||||||
|
|
||||||
if options["heating"]:
|
if options["heating"]:
|
||||||
add_heat(n, costs)
|
add_heat(n=n, costs=costs, cop=xr.open_dataarray(snakemake.input.cop_profiles))
|
||||||
|
|
||||||
if options["biomass"]:
|
if options["biomass"]:
|
||||||
add_biomass(n, costs)
|
add_biomass(n, costs)
|
||||||
|
Loading…
Reference in New Issue
Block a user