Skip to content

Commit

Permalink
feat(ducting): Support Ventilation Ducting
Browse files Browse the repository at this point in the history
- Add Support for Ventilation Ducting
- Update Ventilation System to add ducting
- Update tests
  • Loading branch information
ed-p-may authored Mar 14, 2023
2 parents 48da517 + 80b8423 commit af34143
Show file tree
Hide file tree
Showing 29 changed files with 716 additions and 433 deletions.
49 changes: 33 additions & 16 deletions PHX/from_HBJSON/create_hvac.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

from typing import TypeVar, Union

from honeybee_energy_ph.hvac import ventilation, heating, cooling, _base
from honeybee_energy_ph.hvac import ventilation, heating, cooling, _base, ducting
from PHX.model.enums.hvac import PhxVentDuctType
from PHX.model import hvac
from PHX.model.hvac.heating import AnyPhxHeater
from PHX.model.hvac.ventilation import AnyPhxVentilation
from PHX.model.hvac.cooling import AnyPhxCooling


T = TypeVar("T", bound=Union[AnyPhxVentilation, AnyPhxHeater, AnyPhxCooling])


Expand Down Expand Up @@ -114,26 +114,43 @@ def build_phx_ventilator(
return phx_vent


def build_phx_ventilation_sys(
_hbeph_vent: ventilation.PhVentilationSystem,
) -> hvac.PhxDeviceVentilator:
"""Build a new PHX Ventilation Mechanical Device.
def build_phx_duct(_hbph_duct: ducting.PhDuctElement, _vent_unit_id: int) -> hvac.PhxDuctElement:
"""Return a new PHX Ventilation Duct based on an HB-PH Duct.
Arguments:
----------
*_hbeph_vent (ventilation.PhVentilationSystem): The Honeybee-PH Ventilation System
to build the PHX-Ventilation from.
* _hbph_duct (ducting.PhDuctElement): The HB-PH DuctElement to use as
the source.
* _vent_unit_id (int): The ID-Number of the ventilation unit this duct
is assigned to.
Returns:
--------
* (mech.PhxDeviceVentilator): A new mech ventilation device.
* (hvac.PhxDuctElement)
"""

phx_duct = hvac.PhxDuctElement(
_hbph_duct.identifier,
_hbph_duct.display_name,
_vent_unit_id,
)

phx_ventilator = build_phx_ventilator(_hbeph_vent)

# TODO: Distribution...

return phx_ventilator
phx_duct.duct_type = PhxVentDuctType(_hbph_duct.duct_type,)

for hbph_duct_segment in _hbph_duct.segments:
phx_duct.add_segment(
hvac.PhxDuctSegment(
hbph_duct_segment.identifier,
hbph_duct_segment.display_name,
hbph_duct_segment.geometry,
hbph_duct_segment.diameter,
hbph_duct_segment.insulation_thickness,
hbph_duct_segment.insulation_conductivity,
hbph_duct_segment.insulation_reflective
)
)

return phx_duct


def build_phx_exh_vent_dryer(
Expand Down
15 changes: 13 additions & 2 deletions PHX/from_HBJSON/create_variant.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ def add_ventilation_systems_from_hb_rooms(

ph_prop: RoomPhProperties = _hb_room.properties.ph # type: ignore
for hbph_space in ph_prop.spaces:
# ---------------------------------------------------------------------
# -- Get the Honeybee-PH Ventilation system from the space's host room
# -- Note: in the case of a merged room, the space host may not be the same
# -- as _hb_room, so always refer back to the space.host to be sure.
Expand All @@ -519,20 +520,30 @@ def add_ventilation_systems_from_hb_rooms(
if not hbph_vent_sys:
continue

# ---------------------------------------------------------------------
# -- Get or Build the PHX Ventilation Device
# -- If the ventilator already exists, just use that one.
phx_ventilator = _variant.mech_systems.get_mech_device_by_key(hbph_vent_sys.key)
if not phx_ventilator:
# -- otherwise, build a new PH-Ventilator from the HB-hvac
phx_ventilator = create_hvac.build_phx_ventilation_sys(hbph_vent_sys)
phx_ventilator = create_hvac.build_phx_ventilator(hbph_vent_sys)
_variant.mech_systems.add_new_mech_device(hbph_vent_sys.key, phx_ventilator)

# ---------------------------------------------------------------------
# -- Re-set the HBPH Ventilator and sys id_num to keep everything aligned
hbph_vent_sys.id_num = phx_ventilator.id_num

if hbph_vent_sys.ventilation_unit:
hbph_vent_sys.ventilation_unit.id_num = phx_ventilator.id_num

# ---------------------------------------------------------------------
# -- Add PHX Distribution Ducting from the HBPH Ducts
_variant.mech_systems.add_vent_ducting(
create_hvac.build_phx_duct(hbph_vent_sys.duct_01, phx_ventilator.id_num)
)
_variant.mech_systems.add_vent_ducting(
create_hvac.build_phx_duct(hbph_vent_sys.duct_02, phx_ventilator.id_num)
)

return None


Expand Down
1 change: 0 additions & 1 deletion PHX/from_HBJSON/read_HBJSON_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ def read_hb_json_from_file(_file_address: pathlib.Path) -> Dict:
)

with open(_file_address) as json_file:
print(">>>>", json_file)
data = json.load(json_file)

if data.get("type", None) != "Model":
Expand Down
5 changes: 5 additions & 0 deletions PHX/model/enums/hvac.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,8 @@ class PhxExhaustVentType(Enum):
DRYER = 1
KITCHEN_HOOD = 2
USER_DEFINED = 3


class PhxVentDuctType(Enum):
SUPPLY = 1
EXHAUST = 2
52 changes: 49 additions & 3 deletions PHX/model/hvac/ducting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@


from __future__ import annotations
from typing import Dict, List, Any
from typing import Dict, List, Any, ClassVar
from dataclasses import dataclass, field

from ladybug_geometry.geometry3d.polyline import LineSegment3D

from PHX.model.enums.hvac import PhxVentDuctType

@dataclass
class PhxDuctSegment:
"""An individual Duct Segment Segment."""
Expand All @@ -21,8 +23,6 @@ class PhxDuctSegment:
insulation_thickness: float
insulation_conductivity: float
insulation_reflective: bool
insulation_quality: Any
daily_period: float

@property
def length(self) -> float:
Expand All @@ -32,10 +32,23 @@ def length(self) -> float:
class PhxDuctElement:
"""A Duct Element / Run made of one or more PhxDuctSegments."""

_count: ClassVar[int] = 0
id_num: int = field(init=False, default=0)

identifier: str
display_name: str
duct_type: PhxVentDuctType = field(init=False, default=PhxVentDuctType.SUPPLY)
vent_unit_id: int
_segments: Dict = field(default_factory=dict)

def __post_init__(self) -> None:
self.__class__._count += 1
self.id_num = self.__class__._count

@property
def quantity(self) -> int:
return 1

@property
def segments(self) -> List[PhxDuctSegment]:
return list(self._segments.values())
Expand All @@ -44,5 +57,38 @@ def segments(self) -> List[PhxDuctSegment]:
def length(self) -> float:
return sum(_.length for _ in self.segments)

@property
def diameter(self) -> float:
weighted_total = 0.0
for seg in self.segments:
weighted_total += seg.length * seg.diameter
return weighted_total / self.length

@property
def insulation_thickness(self) -> float:
weighted_total = 0.0
for seg in self.segments:
weighted_total += seg.length * seg.insulation_thickness
return weighted_total / self.length

@property
def insulation_conductivity(self) -> float:
weighted_total = 0.0
for seg in self.segments:
weighted_total += seg.length * seg.insulation_conductivity
return weighted_total / self.length

@property
def duct_shape(self) -> int:
return 1

@property
def is_reflective(self) -> bool:
return any({seg.insulation_reflective for seg in self.segments})

@property
def assigned_vent_unit_ids(self) -> List[int]:
return [self.vent_unit_id]

def add_segment(self, _s: PhxDuctSegment) -> None:
self._segments[_s.identifier] = _s
31 changes: 15 additions & 16 deletions PHX/to_WUFI_XML/xml_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -1249,21 +1249,20 @@ def _DistributionHeating(_d):
# ]


def _Duct(_in):
def _PhxDuctElement(_d: hvac.PhxDuctElement) -> List[xml_writable]:
return [
# XML_Node("Name", _d.),
# XML_Node("IdentNr", _d.),
# XML_Node("DuctDiameter", _d.),
# XML_Node("DuctLength", _d.),
# XML_Node("InsulationThickness", _d.),
# XML_Node("ThermalConductivity", _d.),
# XML_Node("Quantity", _d.),
# XML_Node("DuctType", _d.),
# XML_Node("DuctShape", _d.),
# XML_Node("IsReflective", _d.),
# XML_Node("AssignedVentUnits", _d.),
# XML_Node("IdentNrVentUnit", _d.),
# XML_Node("/AssignedVentUnits", _d.),
XML_Node("Name", _d.display_name),
XML_Node("IdentNr", _d.id_num),
XML_Node("DuctDiameter", _d.diameter, "unit", "mm"),
XML_Node("DuctLength", _d.length, "unit", "m"),
XML_Node("InsulationThickness", _d.insulation_thickness, "unit", "mm"),
XML_Node("ThermalConductivity", _d.insulation_conductivity, "unit", "W/mK"),
XML_Node("Quantity", _d.quantity, "unit", "-"),
XML_Node("DuctType", _d.duct_type.value),
XML_Node("DuctShape", _d.duct_shape),
XML_Node("IsReflective", _d.is_reflective),
XML_List("AssignedVentUnits", [XML_Node('IdentNrVentUnit', id, 'index', i)
for i, id in enumerate(_d.assigned_vent_unit_ids)]),
]


Expand Down Expand Up @@ -1366,8 +1365,8 @@ def _PHDistribution(_c: hvac.PhxMechanicalSystemCollection):
TempDistributionCooling(_c.cooling_devices),
_schema_name="_DistributionCooling",
),
# XML_List('DistributionVentilation', [XML_Object('Duct', None, 'index', i)
# for i, d in enumerate([])]),
XML_List('DistributionVentilation', [XML_Object('Duct', d, 'index', i)
for i, d in enumerate(_c.vent_ducting)]),
XML_Node("UseDefaultValues", True),
XML_Node("DeviceInConditionedSpace", True),
]
Expand Down
4 changes: 2 additions & 2 deletions _testing_to_WUFI.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
SOURCE_FILES = [SOURCE_DIR / file for file in SOURCE_FILE_NAMES]
TARGET_DIR = pathlib.Path("tests", "_reference_xml")

# -- Temp"
# -- Temp
SOURCE_FILES = [
pathlib.Path(
"/Users/em/Dropbox/bldgtyp-00/00_PH_Tools/PHX/sample/hbjson/utf_8_write.hbjson"
"/Users/em/Dropbox/bldgtyp-00/00_PH_Tools/PHX/sample/hbjson/ducting_test.hbjson"
)
]
TARGET_DIR = pathlib.Path("sample")
Expand Down
5 changes: 3 additions & 2 deletions tests/_reference_xml/Default_Model_Single_Zone.xml
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@
<Components count="3">
<Component index="0">
<IdentNr>5</IdentNr>
<Name>Room_1_ca4d878b..Face4</Name>
<Name>Room_1_8789e01c..Face4</Name>
<Visual>true</Visual>
<Type>1</Type>
<IdentNrColorI>12</IdentNrColorI>
Expand All @@ -219,7 +219,7 @@
</Component>
<Component index="1">
<IdentNr>6</IdentNr>
<Name>Room_1_ca4d878b..Face5</Name>
<Name>Room_1_8789e01c..Face5</Name>
<Visual>true</Visual>
<Type>1</Type>
<IdentNrColorI>7</IdentNrColorI>
Expand Down Expand Up @@ -537,6 +537,7 @@
<Devices count="0"/>
<PHDistribution>
<DistributionCooling/>
<DistributionVentilation count="0"/>
<UseDefaultValues>true</UseDefaultValues>
<DeviceInConditionedSpace>true</DeviceInConditionedSpace>
</PHDistribution>
Expand Down
Loading

0 comments on commit af34143

Please sign in to comment.