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