Source code for honeybee_energy_ph.load.ph_equipment

# -*- Python Version: 2.7 -*-
# -*- coding: utf-8 -*-

"""HB-PH Electric Equipment and Appliances."""

import sys

try:
    from typing import Any, ItemsView, Iterator, KeysView, Type, ValuesView
except ImportError:
    pass  # IronPython

try:
    from honeybee import room
except ImportError as e:
    raise ImportError("Failed to import room: {}".format(e))

try:
    from honeybee_energy.schedule.ruleset import ScheduleRuleset
except ImportError as e:
    raise ImportError("Failed to import RoomEnergyProperties: {}".format(e))

try:
    from honeybee_energy_ph.load import _base
except ImportError as e:
    raise ImportError("Failed to import honeybee_energy_ph: {}".format(e))

try:
    from typing import TYPE_CHECKING

    if TYPE_CHECKING:
        from honeybee_energy_ph.properties.load.equipment import ElectricEquipmentPhProperties
        from honeybee_energy_ph.properties.load.lighting import LightingPhProperties
        from honeybee_energy_ph.properties.load.process import ProcessPhProperties
except ImportError:
    pass  # IronPython

try:
    from honeybee_ph_utils.input_tools import input_to_int
except ImportError as e:
    raise ImportError("Failed to import honeybee_ph_utils: {}".format(e))

try:
    from honeybee_ph_standards.programtypes.default_elec_equip import ph_default_equip
except ImportError as e:
    raise ImportError("\nFailed to import honeybee_ph_standards:\n\t{}".format(e))

try:
    from honeybee_energy_ph.load import phius_residential
    from honeybee_energy_ph.load._ph_equip_types import (
        PhClothesDryerType,
        PhClothesWasherType,
        PhCookingType,
        PhDishwasherType,
    )
except ImportError as e:
    raise ImportError("Failed to import PhEquipment types: {}".format(e))


# -----------------------------------------------------------------------------
# - Appliance Base


[docs] class PhEquipment(_base._Base): """Base for PH Equipment / Appliances with the common attributes.""" _phi_default = None _phius_default = None def __init__(self, _host=None, _defaults={}): # type: (ProcessPhProperties | None, dict) -> None super(PhEquipment, self).__init__() self.host = _host self.equipment_type = self.__class__.__name__ self.display_name = "_unnamed_equipment_" self.comment = "" self.reference_quantity = 2 # Zone Occupants self.quantity = 0 self.in_conditioned_space = True self.reference_energy_norm = 2 # Year self.energy_demand = 0.0 # kwh self.energy_demand_per_use = 0.0 # kwh/use self.combined_energy_factor = 0.0 # CEF
[docs] def apply_default_attr_values(self, _defaults={}): # type: (dict[str, Any]) -> None """Sets all the object attributes to default values, as specified in a "defaults" dict.""" if not _defaults: return for k, v in _defaults.items(): setattr(self, k, v)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict[str, Any] d = {} d["display_name"] = self.display_name d["identifier"] = self.identifier d["user_data"] = self.user_data d["equipment_type"] = self.__class__.__name__ d["comment"] = self.comment d["reference_quantity"] = self.reference_quantity d["quantity"] = self.quantity # = 0 d["in_conditioned_space"] = self.in_conditioned_space d["reference_energy_norm"] = self.reference_energy_norm d["energy_demand"] = self.energy_demand d["energy_demand_per_use"] = self.energy_demand_per_use d["combined_energy_factor"] = self.combined_energy_factor return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhEquipment """Set the object attributes from a dictionary""" # -- To be implemented by the equipment, as appropriate. raise NotImplementedError(cls)
[docs] def base_attrs_from_dict(self, _obj, _input_dict): # type: (PhEquipment, dict[str, Any]) -> None """Set the base object attributes from a dictionary Arguments: ---------- * _obj (PhEquipment): The PH Equipment to set the attributes of. * _input_dict (dict): The dictionary to get the attribute values from. Returns: -------- * None """ for attr_name in vars(self).keys(): try: # Strip off underscore so it uses the property setters if attr_name.startswith("_"): attr_name = attr_name[1:] setattr(_obj, attr_name, _input_dict[attr_name]) except KeyError: pass return None
[docs] def merge(self, other, weighting_1=1.0, weighting_2=1.0): # type: (PhEquipment, float, float) -> PhEquipment """ "Merge together two pieces of PhEquipment. Arguments: ---------- * other (PhEquipment): the PhEquipment to merge with. * weighting_1 (float): Optional weighting factor to apply to the 'self' equipment values. * weighting_2 (float): Optional weighting factor to apply to the 'other' equipment values. Returns: -------- * (PhEquipment) The PhEquipment with updated attribute values. """ if self.equipment_type != other.equipment_type: msg = 'Error: Cannot merge PhEquipment with type: "{}" to PhEquipment with type: "{}"'.format( self.equipment_type, other.equipment_type ) raise Exception(msg) self.quantity += other.quantity # ------------ # TODO: Should there be some sort of area-weighted averaging as well? # ------------ return self
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, *Any) -> float """Returns the annual energy use (kWh) of the equipment.""" # -- To be implemented by the equipment, as appropriate. raise NotImplementedError(self)
[docs] def annual_avg_wattage(self, _schedule=None, *args, **kwargs): # type: ( ScheduleRuleset | None, *Any, **Any) -> float """Returns the annual average wattage of the equipment.""" if _schedule is not None: # -- Consider the host schedule.... sched_factor_sum = sum(_schedule.values()) else: sched_factor_sum = 8760 annual_energy_Wh = self.annual_energy_kWh(*args, **kwargs) * 1000 return annual_energy_Wh / sched_factor_sum
def __str__(self): # type: () -> str return "{}(display_name={}, {})".format( self.__class__.__name__, self.display_name, ", ".join(["{}={}".format(str(k), str(v)) for k, v, in vars(self).items()]), ) def __repr__(self): # type: () -> str return str(self)
[docs] def ToString(self): # type: () -> str return str(self)
[docs] @classmethod def phius_default(cls): # type: () -> 'PhEquipment' """Return the default instance of the object.""" if not cls._phius_default: cls._phius_default = cls(_defaults=ph_default_equip[cls.__name__]["PHIUS"]) return cls._phius_default
[docs] @classmethod def phi_default(cls): # type: () -> 'PhEquipment' """Return the default instance of the object.""" if not cls._phi_default: cls._phi_default = cls(_defaults=ph_default_equip[cls.__name__]["PHI"]) return cls._phi_default
# ----------------------------------------------------------------------------- # - Appliances
[docs] class PhDishwasher(PhEquipment): def __init__(self, _defaults={}): super(PhDishwasher, self).__init__() self.display_name = "Kitchen dishwasher" self.capacity_type = 1 self.capacity = 12 self._water_connection = PhDishwasherType("1-DHW CONNECTION") self.apply_default_attr_values(_defaults) @property def water_connection(self): return self._water_connection @water_connection.setter def water_connection(self, _input): # type: (str | int | None) -> None if _input: _input = input_to_int(_input) if not _input: raise ValueError("Invalid input for water_connection: {}".format(_input)) self._water_connection = PhDishwasherType(_input)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhDishwasher, self).to_dict()) d["capacity_type"] = self.capacity_type d["capacity"] = self.capacity d["_water_connection"] = self._water_connection.to_dict() return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhDishwasher new_obj = cls() super(PhDishwasher, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj.capacity_type = _input_dict["capacity_type"] new_obj.capacity = _input_dict["capacity"] new_obj._water_connection = PhDishwasherType.from_dict(_input_dict["_water_connection"]) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float return self.energy_demand
[docs] class PhClothesWasher(PhEquipment): def __init__(self, _defaults={}): super(PhClothesWasher, self).__init__() self.display_name = "Laundry - washer" self.capacity = 0.1274 self.modified_energy_factor = 2.7 self._water_connection = PhClothesWasherType("1-DHW CONNECTION") self.utilization_factor = 1 self.apply_default_attr_values(_defaults) @property def water_connection(self): return self._water_connection @water_connection.setter def water_connection(self, _input): # type: (str | int | None) -> None if _input: _input = input_to_int(_input) if not _input: raise ValueError("Invalid input for water_connection: {}".format(_input)) self._water_connection = PhClothesWasherType(_input)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhClothesWasher, self).to_dict()) d["capacity"] = self.capacity d["modified_energy_factor"] = self.modified_energy_factor d["_water_connection"] = self._water_connection.to_dict() d["utilization_factor"] = self.utilization_factor return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhClothesWasher new_obj = cls() super(PhClothesWasher, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj.capacity = _input_dict["capacity"] new_obj.modified_energy_factor = _input_dict["modified_energy_factor"] new_obj._water_connection = PhClothesWasherType.from_dict(_input_dict["_water_connection"]) new_obj.utilization_factor = _input_dict["utilization_factor"] return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float return self.energy_demand
[docs] class PhClothesDryer(PhEquipment): def __init__(self, _defaults={}): super(PhClothesDryer, self).__init__() self.display_name = "Laundry - dryer" self._dryer_type = PhClothesDryerType("5-ELECTRIC EXHAUST AIR DRYER") self.gas_consumption = 0 self.gas_efficiency_factor = 2.67 self.field_utilization_factor_type = 1 self.field_utilization_factor = 1.18 self.apply_default_attr_values(_defaults) @property def dryer_type(self): return self._dryer_type @dryer_type.setter def dryer_type(self, _input): # type: (str | int | None) -> None if _input: _input = input_to_int(_input) if not _input: raise ValueError("Invalid input for dryer_type: {}".format(_input)) self._dryer_type = PhClothesDryerType(_input)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhClothesDryer, self).to_dict()) d["_dryer_type"] = self._dryer_type.to_dict() d["gas_consumption"] = self.gas_consumption d["gas_efficiency_factor"] = self.gas_efficiency_factor d["field_utilization_factor_type"] = self.field_utilization_factor_type d["field_utilization_factor"] = self.field_utilization_factor return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhClothesDryer new_obj = cls() super(PhClothesDryer, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj._dryer_type = PhClothesDryerType.from_dict(_input_dict["_dryer_type"]) new_obj.gas_consumption = _input_dict["gas_consumption"] new_obj.gas_efficiency_factor = _input_dict["gas_efficiency_factor"] new_obj.field_utilization_factor_type = _input_dict["field_utilization_factor_type"] new_obj.field_utilization_factor = _input_dict["field_utilization_factor"] return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Returns the annual energy use (kWh) of the equipment.""" # -- Appendix N - Normative | Phius 2024 Certification Guidebook v24.1.1 # -- Table 11.6.4.0 prescriptive Path Appliance, Lighting and DHW REference Efficiencies _num_occupants = kwargs.get("_num_occupants", None) if _num_occupants is None: raise ValueError( "'_num_occupants' input is required for the annual_energy_kWh method. Got only: {}".format(kwargs) ) try: return _num_occupants * (283 / 4.5) / self.combined_energy_factor * 8.45 except ZeroDivisionError: return 0
[docs] class PhRefrigerator(PhEquipment): def __init__(self, _defaults={}): super(PhRefrigerator, self).__init__() self.display_name = "Kitchen refrigerator" self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhRefrigerator, self).to_dict()) return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhRefrigerator new_obj = cls() super(PhRefrigerator, new_obj).base_attrs_from_dict(new_obj, _input_dict) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float return self.energy_demand * 365
[docs] class PhFreezer(PhEquipment): def __init__(self, _defaults={}): super(PhFreezer, self).__init__() self.display_name = "Kitchen freezer" self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhFreezer, self).to_dict()) return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhFreezer new_obj = cls() super(PhFreezer, new_obj).base_attrs_from_dict(new_obj, _input_dict) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float return self.energy_demand * 365
[docs] class PhFridgeFreezer(PhEquipment): def __init__(self, _defaults={}): super(PhFridgeFreezer, self).__init__() self.display_name = "Kitchen fridge/freeze combo" self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhFridgeFreezer, self).to_dict()) return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhFridgeFreezer new_obj = cls() super(PhFridgeFreezer, new_obj).base_attrs_from_dict(new_obj, _input_dict) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float return self.energy_demand * 365
[docs] class PhCooktop(PhEquipment): def __init__(self, _defaults={}): super(PhCooktop, self).__init__() self.display_name = "Kitchen cooking" self._cooktop_type = PhCookingType("1-ELECTRICITY") self.apply_default_attr_values(_defaults) @property def cooktop_type(self): return self._cooktop_type @cooktop_type.setter def cooktop_type(self, _input): # type: (str | int | None) -> None if _input: _input = input_to_int(_input) if not _input: raise ValueError("Invalid input for cooktop_type: {}".format(_input)) self._cooktop_type = PhCookingType(_input)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhCooktop, self).to_dict()) d["_cooktop_type"] = self._cooktop_type.to_dict() return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhCooktop new_obj = cls() super(PhCooktop, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj._cooktop_type = PhCookingType.from_dict(_input_dict["_cooktop_type"]) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Return annual energy consumption [kWh] for a single dwelling.""" _num_occupants = kwargs.get("_num_occupants", None) if _num_occupants is None: raise ValueError("'_num_occupants' input is required for the annual_energy_kWh method.") return phius_residential.cooktop(_num_occupants, self.energy_demand)
[docs] class PhPhiusMEL(PhEquipment): def __init__(self, _defaults={}): super(PhPhiusMEL, self).__init__() self.display_name = "PHIUS+ MELS" self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhPhiusMEL, self).to_dict()) return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhPhiusMEL new_obj = cls() super(PhPhiusMEL, new_obj).base_attrs_from_dict(new_obj, _input_dict) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Return annual energy consumption [kWh] for a single dwelling.""" _num_bedrooms = kwargs.get("_num_bedrooms", None) if _num_bedrooms is None: raise ValueError("'_num_bedrooms' input is required for the annual_energy_kWh method.") _floor_area_ft2 = kwargs.get("_floor_area_ft2", None) if _floor_area_ft2 is None: raise ValueError("'_floor_area_ft2' input is required for the annual_energy_kWh method.") return phius_residential.misc_electrical(_num_bedrooms, _floor_area_ft2)
[docs] class PhPhiusLightingInterior(PhEquipment): def __init__(self, _defaults={}): super(PhPhiusLightingInterior, self).__init__() self.display_name = "PHIUS+ Interior Lighting" self.frac_high_efficiency = 1 # CEF self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhPhiusLightingInterior, self).to_dict()) d["frac_high_efficiency"] = self.frac_high_efficiency return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhPhiusLightingInterior new_obj = cls() super(PhPhiusLightingInterior, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj.frac_high_efficiency = _input_dict["frac_high_efficiency"] return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Return the annual energy consumption [kWh] for a single dwelling.""" _floor_area_ft2 = kwargs.get("_floor_area_ft2", None) if _floor_area_ft2 is None: raise ValueError("'_floor_area_ft2' input is required for the annual_energy_kWh method.") return phius_residential.lighting_interior(_floor_area_ft2, self.frac_high_efficiency)
[docs] class PhPhiusLightingExterior(PhEquipment): def __init__(self, _defaults={}): # type: (dict[str, Any]) -> None super(PhPhiusLightingExterior, self).__init__() self.display_name = "PHIUS+ Exterior Lighting" self.frac_high_efficiency = 1 # CEF self.in_conditioned_space = False self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhPhiusLightingExterior, self).to_dict()) d["frac_high_efficiency"] = self.frac_high_efficiency return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict[str, Any]) -> PhPhiusLightingExterior new_obj = cls() super(PhPhiusLightingExterior, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj.frac_high_efficiency = _input_dict["frac_high_efficiency"] return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Return the annual energy consumption [kWh] for a single dwelling.""" _num_bedrooms = kwargs.get("_num_bedrooms", None) if _num_bedrooms is None: raise ValueError("'_num_bedrooms' input is required for the annual_energy_kWh method.") _floor_area_ft2 = kwargs.get("_floor_area_ft2", None) if _floor_area_ft2 is None: raise ValueError("'_floor_area_ft2' input is required for the annual_energy_kWh method.") return phius_residential.lighting_exterior(_floor_area_ft2, self.frac_high_efficiency)
[docs] class PhPhiusLightingGarage(PhEquipment): def __init__(self, _defaults={}): super(PhPhiusLightingGarage, self).__init__() self.display_name = "PHIUS+ Garage Lighting" self.frac_high_efficiency = 1 # CEF self.in_conditioned_space = False self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhPhiusLightingGarage, self).to_dict()) d["frac_high_efficiency"] = self.frac_high_efficiency return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict[str, Any]) -> PhPhiusLightingGarage new_obj = cls() super(PhPhiusLightingGarage, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj.frac_high_efficiency = _input_dict["frac_high_efficiency"] return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Return the annual energy consumption [kWh] for a single dwelling.""" return phius_residential.lighting_garage(self.frac_high_efficiency)
[docs] class PhCustomAnnualElectric(PhEquipment): def __init__(self, _defaults={}): super(PhCustomAnnualElectric, self).__init__() self.display_name = "User defined" self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhCustomAnnualElectric, self).to_dict()) d["energy_demand"] = self.energy_demand return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhCustomAnnualElectric new_obj = cls() super(PhCustomAnnualElectric, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj.energy_demand = _input_dict["energy_demand"] return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float return self.energy_demand
[docs] class PhCustomAnnualLighting(PhEquipment): def __init__(self, _defaults={}): super(PhCustomAnnualLighting, self).__init__() self.display_name = "User defined - lighting" self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhCustomAnnualLighting, self).to_dict()) d["energy_demand"] = self.energy_demand return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhCustomAnnualLighting new_obj = cls() super(PhCustomAnnualLighting, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj.energy_demand = _input_dict["energy_demand"] return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float return self.energy_demand
[docs] class PhCustomAnnualMEL(PhEquipment): def __init__(self, _defaults={}): super(PhCustomAnnualMEL, self).__init__() self.display_name = "User defined - Misc electric loads" self.apply_default_attr_values(_defaults)
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhCustomAnnualMEL, self).to_dict()) d["energy_demand"] = self.energy_demand return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict) -> PhCustomAnnualMEL new_obj = cls() super(PhCustomAnnualMEL, new_obj).base_attrs_from_dict(new_obj, _input_dict) new_obj.energy_demand = _input_dict["energy_demand"] return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float return self.energy_demand
# -- Elevator classes
[docs] class PhElevatorHydraulic(PhEquipment): def __init__(self, _num_dwellings=1): super(PhElevatorHydraulic, self).__init__() self.display_name = "User defined - Misc electric loads" self.comment = "Elevator - Hydraulic" self.set_energy_demand(_num_dwellings) self.quantity = 1
[docs] def set_energy_demand(self, _num_dwellings): """Set the annual energy demand (kWh) based on the number of dwelling units""" if _num_dwellings <= 6: self.energy_demand = 1910.0 elif _num_dwellings <= 20: self.energy_demand = 2150.0 elif _num_dwellings <= 50: self.energy_demand = 2940.0 else: self.energy_demand = 4120.0
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhElevatorHydraulic, self).to_dict()) return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict[str, Any]) -> PhElevatorHydraulic new_obj = cls() super(PhElevatorHydraulic, new_obj).base_attrs_from_dict(new_obj, _input_dict) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Returns the annual energy use (kWh) of the equipment.""" return self.energy_demand
[docs] class PhElevatorGearedTraction(PhEquipment): def __init__(self, _num_dwellings=1): super(PhElevatorGearedTraction, self).__init__() self.display_name = "User defined - Misc electric loads" self.comment = "Elevator - Geared Traction" self.set_energy_demand(_num_dwellings) self.quantity = 1
[docs] def set_energy_demand(self, _num_dwellings): """Set the annual energy demand (kWh) based on the number of dwelling units""" if _num_dwellings <= 6: self.energy_demand = 3150.0 elif _num_dwellings <= 20: self.energy_demand = 3150.0 elif _num_dwellings <= 50: self.energy_demand = 3150.0 else: self.energy_demand = 4550.0
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhElevatorGearedTraction, self).to_dict()) return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict[str, Any]) -> PhElevatorGearedTraction new_obj = cls() super(PhElevatorGearedTraction, new_obj).base_attrs_from_dict(new_obj, _input_dict) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Returns the annual energy use (kWh) of the equipment.""" return self.energy_demand
[docs] class PhElevatorGearlessTraction(PhEquipment): def __init__(self, _num_dwellings=1): super(PhElevatorGearlessTraction, self).__init__() self.display_name = "User defined - Misc electric loads" self.comment = "Elevator - Gearless Traction" self.set_energy_demand(_num_dwellings) self.quantity = 1
[docs] def set_energy_demand(self, _num_dwellings): """Set the annual energy demand (kWh) based on the number of dwelling units""" if _num_dwellings <= 6: self.energy_demand = 7570.0 elif _num_dwellings <= 20: self.energy_demand = 7570.0 elif _num_dwellings <= 50: self.energy_demand = 7570.0 else: self.energy_demand = 7570.0
[docs] def to_dict(self, _abridged=False): # type: (bool) -> dict d = {} d.update(super(PhElevatorGearlessTraction, self).to_dict()) return d
[docs] @classmethod def from_dict(cls, _input_dict): # type: (dict[str, Any]) -> PhElevatorGearlessTraction new_obj = cls() super(PhElevatorGearlessTraction, new_obj).base_attrs_from_dict(new_obj, _input_dict) return new_obj
[docs] def annual_energy_kWh(self, *args, **kwargs): # type: (*Any, **Any) -> float """Returns the annual energy use (kWh) of the equipment.""" return self.energy_demand
[docs] def phius_elevator_by_stories(_num_of_stories): # type: (int) -> Type[PhElevatorHydraulic | PhElevatorGearedTraction | PhElevatorGearlessTraction] """Return the Elevator class, based on the number of stories.""" if _num_of_stories <= 6: return PhElevatorHydraulic elif _num_of_stories <= 20: return PhElevatorGearedTraction else: return PhElevatorGearlessTraction
# ----------------------------------------------------------------------------- # Collections # TODO: Deprecate these classes in favor of new the "Process Load" method. # See: honeybee_energy_ph.load.process.py
[docs] class PhEquipmentBuilder(object): """Constructor class for PH Equipment objects"""
[docs] @classmethod def from_dict(cls, _input_dict, _host=None): # type: (dict, ProcessPhProperties | LightingPhProperties | None) -> PhEquipment """Find the right appliance constructor class from the module based on the 'type' name.""" equipment_type = _input_dict["equipment_type"] valid_class_types = [nm for nm in dir(sys.modules[__name__]) if nm.startswith("Ph")] if equipment_type not in valid_class_types: msg = 'Error: Unknown PH Equipment type? Got: "{}" but only types: {} are allowed?'.format( valid_class_types, equipment_type ) raise Exception(msg) equipment_class = getattr(sys.modules[__name__], equipment_type) # type: Type[PhEquipment] new_equipment = equipment_class.from_dict(_input_dict) return new_equipment
def __str__(self): # type: () -> str return "{}()".format(self.__class__.__name__) def __repr__(self): # type: () -> str return str(self)
[docs] def ToString(self): # type: () -> str return str(self)
[docs] class PhEquipmentCollection(object): """A Collection of PH-Equipment / Appliances. This is stored on the Honeybee-Room's properties.energy.electric_equipment.properties.ph """ def __init__(self, _host=None): # type: (ElectricEquipmentPhProperties | None) -> None self._equipment_set = {} # type: dict[str, PhEquipment] self._host = _host @property def host(self): # type: () -> ElectricEquipmentPhProperties | None return self._host
[docs] def items(self): # type: () -> ItemsView[str, PhEquipment] return self._equipment_set.items()
[docs] def keys(self): # type: () -> KeysView[str] return self._equipment_set.keys()
[docs] def values(self): # type: () -> ValuesView[PhEquipment] return self._equipment_set.values()
[docs] def duplicate(self, new_host=None): # type: (Any) -> PhEquipmentCollection return self.__copy__(new_host)
[docs] def add_equipment(self, _new_equipment, _key=None): # type: (PhEquipment, Any) -> None """Adds a new piece of Ph-Equipment to the collection. Arguments: ---------- * _new_equipment (PhEquipment): The new Ph Equipment to add to the set. * _key (Any): Optional key to use for storing the equipment. If None, the equipment's "identifier" will be used as the key. Returns: -------- * None """ key = _key or _new_equipment.identifier if key in self._equipment_set.keys(): _new_equipment = self._equipment_set[key] return self._equipment_set[key] = _new_equipment return None
[docs] def remove_all_equipment(self): # type: () -> None """Reset the Collection to an empty set.""" self._equipment_set = {}
[docs] def total_collection_wattage(self, _hb_room): # type: (room.Room) -> float """Returns the total annual-average-wattage of the appliances. This value assumes constant 24/7 operation (PH-Style modeling). Arguments: ---------- * _hb_room (room.Room): The reference Honeybee-Room to get occupancy from. Returns: -------- * (float): total Wattage of all installed PH-Equipment in the collection. """ return sum(equip.annual_avg_wattage(_hb_room) for equip in self.values()) # type: ignore
[docs] def to_dict(self): # type: () -> dict d = {} d["equipment_set"] = {} for key, device in self._equipment_set.items(): d["equipment_set"][key] = device.to_dict() return d
[docs] @classmethod def from_dict(cls, _input_dict, _host): # type: (dict, Any) -> PhEquipmentCollection new_obj = cls(_host) for k, device in _input_dict["equipment_set"].items(): if k not in new_obj._equipment_set.keys(): new_obj.add_equipment(PhEquipmentBuilder.from_dict(device), k) return new_obj
def __iter__(self): # type: () -> Iterator[tuple[str, PhEquipment]] for _ in self._equipment_set.items(): yield _ def __setitem__(self, key, attr): # type: (str, PhEquipment) -> None self._equipment_set[key] = attr def __getitem__(self, key): # type: (str) -> PhEquipment return self._equipment_set[key] def __copy__(self, new_host=None): # type: (Any) -> PhEquipmentCollection host = new_host or self._host new_obj = self.__class__(host) for k, v in self._equipment_set.items(): new_obj.add_equipment(v, k) return new_obj def __str__(self): # type: () -> str return "{}({} pieces of equipment)".format(self.__class__.__name__, len(self._equipment_set.keys())) def __repr__(self): # type: () -> str return str(self)
[docs] def ToString(self): # type: () -> str return str(self)