Source code for prereise.gather.demanddata.bldg_electrification.load_projection_scenario
import numpy as np
from prereise.gather.demanddata.bldg_electrification import const
[docs]class LoadProjectionScenario:
"""Define load projection scenario for a load zone.
For a base scenario, read and save building stock inputs.
For a projection scenario, some fields are projected from base scenario
based on the projection scenario inputs.
:param str id: id of scenario, 'base' refers to modeled base year scenario
:param pandas.Series input_series: precomputed information of building stock floor
area and energy usages for a base scenario. User defined growth inputs for a
projection scenario. This series contains information for a load zone,
which are listed as follows:
#. population
#. total building floor area by type
#. primary energy source types and household fraction for space heating,
cooling, hot water and cooking
#. assumed dominate type of heat pump
#. assumed energy efficiency of cooking and air conditioning.
:param LoadProjectionScenario other: the base scenario instance for a projection
scenario creation. None if creating a base scenario.
"""
def __init__(self, id, input_series, other=None):
self.id = id
self.year = int(input_series["year"])
self.hp_type_heat = input_series.pop("heat_hp_type")
self.hp_type_dhw = input_series.pop("dhw_hp_type")
self.cook_efficiency = input_series.pop("cook_eff")
input_series = input_series.astype("float64")
self.cool_energy_intensity = input_series["cool_energy_intensity(relative)"]
self.stats = input_series
if other is None:
self.stats = (
input_series.dropna()
) # drop rows that only used for defining future scenarios
self._compute_base_scenario()
else:
self._compute_project_scenario(other)
def _compute_base_scenario(self):
self.pop = self.stats["pop"]
self.floor_area_m2 = {
"res": self.stats["res_area_m2"],
"com": self.stats["com_area_m2"],
}
self.hp_heat_area_m2 = (
self.stats["frac_hp_res_heat"] * self.floor_area_m2["res"]
+ self.stats["frac_hp_com_heat"] * self.floor_area_m2["com"]
)
self.hp_heat_frac = self.hp_heat_area_m2 / (
self.floor_area_m2["res"] + self.floor_area_m2["com"]
)
self.resist_heat_area_m2 = (
self.stats["frac_resist_res_heat"] * self.floor_area_m2["res"]
+ self.stats["frac_resist_com_heat"] * self.floor_area_m2["com"]
)
self.resist_heat_frac = self.resist_heat_area_m2 / (
self.floor_area_m2["res"] + self.floor_area_m2["com"]
)
self.elec_cool_m2 = (
self.stats["frac_elec_res_cool"] * self.floor_area_m2["res"]
+ self.stats["frac_elec_com_cool"] * self.floor_area_m2["com"]
)
def _compute_project_scenario(self, other):
self.pop = other.pop * (1 + self.stats["pop_ann_grow_rate"]) ** (
self.year - other.year
)
self.floor_area_m2 = {}
for clas in const.classes:
if np.isnan(self.stats[f"{clas}_area_ann_grow_rate"]):
# floor area growth rate is assumed to be proportional to population
# growth by default, unless user defines a growth rate for floor area
self.floor_area_m2[clas] = other.floor_area_m2[clas] * (
1 + self.stats["pop_ann_grow_rate"]
) ** (self.year - other.year)
else:
self.floor_area_m2[clas] = other.floor_area_m2[clas] * (
1 + self.stats[f"{clas}_area_ann_grow_rate"]
) ** (self.year - other.year)
if not np.isnan(self.stats[f"frac_hp_{clas}_heat"]):
# calculate fraction of floor area using heat pump, resistance heat
# or fossil fuel furnace as major heating appliances
# Users can either define the fractions directly or the shift in major
# heating fuels from the base scenario or assume BAU cases
self.stats[f"ff2hp_{clas}"] = (
1
- self.stats[f"frac_ff_{clas}_heat"]
/ other.stats[f"frac_ff_{clas}_heat"]
)
elif not np.isnan(self.stats[f"ff2hp_{clas}"]):
self.stats[f"frac_hp_{clas}_heat"] = (
other.stats[f"frac_hp_{clas}_heat"]
+ other.stats[f"frac_resist_{clas}_heat"]
* self.stats[f"resist2hp_{clas}"]
+ other.stats[f"frac_ff_{clas}_heat"] * self.stats[f"ff2hp_{clas}"]
)
self.stats[f"frac_resist_{clas}_heat"] = other.stats[
f"frac_resist_{clas}_heat"
] * (1 - self.stats[f"resist2hp_{clas}"])
self.stats[f"frac_ff_{clas}_heat"] = other.stats[
f"frac_ff_{clas}_heat"
] * (1 - self.stats[f"ff2hp_{clas}"])
else:
self.stats[f"frac_hp_{clas}_heat"] = other.stats[f"frac_hp_{clas}_heat"]
self.stats[f"frac_resist_{clas}_heat"] = other.stats[
f"frac_resist_{clas}_heat"
]
self.stats[f"frac_ff_{clas}_heat"] = other.stats[f"frac_ff_{clas}_heat"]
self.stats[f"ff2hp_{clas}"] = 0
self.stats[f"resist2hp_{clas}"] = 0
if np.isnan(self.stats[f"frac_elec_{clas}_cool"]):
self.stats[f"frac_elec_{clas}_cool"] = other.stats[
f"frac_elec_{clas}_cool"
]
if np.isnan(self.stats[f"frac_ff_dhw_{clas}"]):
self.stats[f"frac_ff_dhw_{clas}"] = other.stats[f"frac_ff_dhw_{clas}"]
cook_other = "cook" if clas == "com" else "other"
if np.isnan(self.stats[f"frac_ff_{cook_other}_{clas}"]):
self.stats[f"frac_ff_{cook_other}_{clas}"] = other.stats[
f"frac_ff_{cook_other}_{clas}"
]
self.hp_heat_area_m2 = (
self.stats["frac_hp_res_heat"] * self.floor_area_m2["res"]
+ self.stats["frac_hp_com_heat"] * self.floor_area_m2["com"]
)
self.hp_heat_frac = self.hp_heat_area_m2 / (
self.floor_area_m2["res"] + self.floor_area_m2["com"]
)
self.resist_heat_area_m2 = (
self.stats["frac_resist_res_heat"] * self.floor_area_m2["res"]
+ self.stats["frac_resist_com_heat"] * self.floor_area_m2["com"]
)
self.resist_heat_frac = self.resist_heat_area_m2 / (
self.floor_area_m2["res"] + self.floor_area_m2["com"]
)
self.elec_cool_m2 = (
self.stats["frac_elec_res_cool"] * self.floor_area_m2["res"]
+ self.stats["frac_elec_com_cool"] * self.floor_area_m2["com"]
)
[docs] def floor_area_growth(self, other):
"""
:return (*float*) -- compound floor area growth
"""
return (self.floor_area_m2["res"] + self.floor_area_m2["com"]) / (
other.floor_area_m2["res"] + other.floor_area_m2["com"]
)
[docs] def floor_area_growth_type(self, other, clas):
"""
:return (*float*) -- compound floor area growth by building type
"""
return self.floor_area_m2[clas] / other.floor_area_m2[clas]
[docs] def frac_hp_growth(self, other):
"""
:return (*float*) -- floor area growth ratio that use hp as main heating
appliance
"""
return self.hp_heat_area_m2 / other.hp_heat_area_m2
[docs] def frac_resist_growth(self, other):
"""
:return (*float*) -- floor area growth ratio that use resistance heat as main
heating source
"""
return self.resist_heat_area_m2 / other.resist_heat_area_m2
[docs] def frac_cool_growth(self, other):
"""
:return (*float*) -- floor area growth ratio that have electric air conditioning
"""
return self.elec_cool_m2 / other.elec_cool_m2
[docs] def frac_htg_ff2hp(self, other, clas):
"""
:return (*float*) -- fraction of floor area electrified for heating
"""
return other.stats[f"frac_ff_{clas}_heat"] - self.stats[f"frac_ff_{clas}_heat"]
[docs] def frac_dhw_ff2hp(self, other, clas):
"""
:return (*float*) -- fraction of floor area electrified for dhw
"""
return other.stats[f"frac_ff_dhw_{clas}"] - self.stats[f"frac_ff_dhw_{clas}"]
[docs] def frac_cook_ff2hp(self, other, clas):
"""
:return (*float*) -- fraction of floor area electrified for cooking
"""
cook_other = "cook" if clas == "com" else "other"
return (
other.stats[f"frac_ff_{cook_other}_{clas}"]
- self.stats[f"frac_ff_{cook_other}_{clas}"]
)
[docs] def frac_cooling_eff_change(self, other):
"""
:return (*float*) -- ratio of cooling efficiency improvement compares to base
scenario
"""
return self.cool_energy_intensity / other.cool_energy_intensity
[docs] def compare_hp_heat_type(self, other):
"""
:return (*bool*) -- True if the heat pump type for projection scenario is the
same as that of base scenario, otherwise False
"""
return self.hp_type_heat == other.hp_type_heat