diff --git a/hbph_installer.gh b/hbph_installer.gh index 5c81362..598043d 100644 Binary files a/hbph_installer.gh and b/hbph_installer.gh differ diff --git a/honeybee_ph_rhino/_component_info_.py b/honeybee_ph_rhino/_component_info_.py index 50d4bf1..e491148 100644 --- a/honeybee_ph_rhino/_component_info_.py +++ b/honeybee_ph_rhino/_component_info_.py @@ -5,7 +5,7 @@ These are called when the component is instantiated within the Grasshopper canvas. """ -RELEASE_VERSION = "Honeybee-PH v1.7.06" +RELEASE_VERSION = "Honeybee-PH v1.7.07" CATEGORY = "HB-PH" SUB_CATEGORIES = { 0: "00 | Utils", diff --git a/honeybee_ph_rhino/gh_compo_io/assmbly_create_heterogeneous_material.py b/honeybee_ph_rhino/gh_compo_io/assmbly_create_heterogeneous_material.py index c9cc05e..d0a7dde 100644 --- a/honeybee_ph_rhino/gh_compo_io/assmbly_create_heterogeneous_material.py +++ b/honeybee_ph_rhino/gh_compo_io/assmbly_create_heterogeneous_material.py @@ -24,7 +24,11 @@ raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e)) try: - from honeybee_energy_ph.properties.materials.opaque import CellPositionError, EnergyMaterialPhProperties + from honeybee_energy_ph.properties.materials.opaque import ( + CellPositionError, + EnergyMaterialPhProperties, + PhDivisionGrid, + ) except ImportError as e: raise ImportError("\nFailed to import honeybee_energy_ph:\n\t{}".format(e)) @@ -89,6 +93,18 @@ def __init__(self, IGH, _base_material, _additional_materials, _column_widths, _ self.column_widths = _column_widths self.row_heights = _row_heights + @property + def all_materials(self): + # type: () -> List[opaque.EnergyMaterial] + """Get all the materials including the base and additional materials.""" + mats = [] + for mat in self.additional_materials: + if mat is not None: + mats.append(mat) + if self.base_material is not None: + mats.insert(0, self.base_material) + return mats + def ready(self): # type: () -> bool """Check if all the inputs are ready, perform some cleanup on the inputs.""" @@ -175,33 +191,55 @@ def check_material_conductivities(self, material): self.IGH.error(msg) break + def set_cell_material(self, _division_grid, _column, _row, _material): + # type: (PhDivisionGrid, int, int, opaque.EnergyMaterial) -> None + print( + "Setting Material at: Column-{} | Row-{} to '{}' [id={}]".format( + _column, _row, _material.display_name, id(_material) + ) + ) + try: + _division_grid.set_cell_material(_column, _row, _material) + except CellPositionError as e: + print("- " * 25) + print("WARNING: Check the '_column_widths' and '_row_heights' inputs.\n") + raise e + def run(self): # type: () -> Tuple[Optional[opaque.EnergyMaterial], Optional[Any]] if not self.ready() or not self.base_material: return (self.base_material, None) - # -- Setup the Base Material Division Grid - new_material_ = self.base_material.duplicate() - ph_prop = new_material_.properties.ph # type: EnergyMaterialPhProperties # type: ignore + # -------------------------------------------------------------------------------------------------------------- + # -- Setup the Division Grid + division_grid = PhDivisionGrid() + division_grid.set_column_widths(self.column_widths) + division_grid.set_row_heights(self.row_heights) - ph_prop.divisions.set_column_widths(self.column_widths) - ph_prop.divisions.set_row_heights(self.row_heights) + for row in range(division_grid.row_count): + for col in range(division_grid.column_count): + division_grid.set_cell_material(col, row, self.base_material) for material in self.additional_materials: - col = material.properties.ph.user_data.get("column_position", 0) # type: ignore - row = material.properties.ph.user_data.get("row_position", 0) # type: ignore - print( - "Setting Material at: Column-{} | Row-{} to '{}' [id={}]".format( - col, row, material.display_name, id(material) - ) - ) - try: - ph_prop.divisions.set_cell_material(col, row, material) - except CellPositionError as e: - print("- " * 25) - print("WARNING: Check the '_column_widths' and '_row_heights' inputs.\n") - raise e - + hbph_mat_props = getattr(material.properties, "ph") # type: EnergyMaterialPhProperties + col = hbph_mat_props.user_data.get("column_position", 0) + row = hbph_mat_props.user_data.get("row_position", 0) + self.set_cell_material(division_grid, col, row, material) + + # -------------------------------------------------------------------------------------------------------------- + # -- Create a new Hybrid Material + base_material = division_grid.get_base_material() + if not base_material: + return (None, None) + new_material_ = base_material.duplicate() + nm = "+".join([_.display_name for _ in self.all_materials]) + new_material_.display_name = nm + new_material_.identifier = nm + new_material_.conductivity = division_grid.get_equivalent_conductivity() + hbph_props = getattr(new_material_.properties, "ph") # type: EnergyMaterialPhProperties + hbph_props.divisions = division_grid + + # -------------------------------------------------------------------------------------------------------------- self.check_material_thicknesses(new_material_) self.check_material_conductivities(new_material_) diff --git a/honeybee_ph_rhino/gh_compo_io/assmbly_create_wood_framing_material.py b/honeybee_ph_rhino/gh_compo_io/assmbly_create_wood_framing_material.py index 33b0fae..11ddadb 100644 --- a/honeybee_ph_rhino/gh_compo_io/assmbly_create_wood_framing_material.py +++ b/honeybee_ph_rhino/gh_compo_io/assmbly_create_wood_framing_material.py @@ -29,7 +29,7 @@ raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e)) try: - from honeybee_energy_ph.properties.materials.opaque import EnergyMaterialPhProperties + from honeybee_energy_ph.properties.materials.opaque import EnergyMaterialPhProperties, PhDivisionGrid except ImportError as e: raise ImportError("\nFailed to import honeybee_energy_ph:\n\t{}".format(e)) @@ -92,19 +92,31 @@ def default_wood_framing_material(self): roughness="MediumRough", thickness=0.1, ) - - mat_.properties.ph.ph_color = PhColor.from_argb(255, 255, 128, 0) + hbph_props = getattr(mat_, "properties") # type: EnergyMaterialPhProperties + hbph_props.ph_color = PhColor.from_argb(255, 255, 128, 0) return mat_ def _convert(self, value, to_unit="M"): # type: (Union[float, int, str], str) -> float return convert(*parse_input(value), _target_unit=to_unit) or 0.0 + def check_material_type(self, _material): + # type: (opaque.EnergyMaterial) -> opaque.EnergyMaterial | None + if not isinstance(_material, opaque.EnergyMaterial): + msg = "ERROR: Material '{}' of type '{}' is not allowed. Use only EnergyMaterial.".format( + _material, type(_material) + ) + print(msg) + self.IGH.error(msg) + return None + else: + return _material + def check_material_conductivity(self, _material): - # type: (opaque.EnergyMaterial) -> None + # type: (opaque.EnergyMaterial) -> opaque.EnergyMaterial | None if _material.conductivity > 10.0: msg = ( - "WARNING: Material '{}' has a very high conductivity value of {:.2f} W/m-K. " + "ERROR: Material '{}' has a very high conductivity value of {:.2f} W/m-K. " "Note that metal elements like steel studs and metal fasteners may NOT be " "used as part of heterogeneous assemblies (as per ISO 6946).".format( _material.display_name, _material.conductivity @@ -112,29 +124,42 @@ def check_material_conductivity(self, _material): ) print(msg) self.IGH.error(msg) + return None + else: + return _material + + def check_material(self, _material): + # type: (opaque.EnergyMaterial | None) -> opaque.EnergyMaterial | None + if _material is None: + return None + if not self.check_material_type(_material): + return None + if not self.check_material_conductivity(_material): + return None + return _material def run(self): # type: () -> Tuple[Optional[opaque.EnergyMaterial], Optional[List[Brep]]] - if self.insulation_material is None or self.wood_framing_material is None: + insulation_material = self.check_material(self.insulation_material) + if not insulation_material: return (None, None) - # -- Check - self.check_material_conductivity(self.wood_framing_material) - self.check_material_conductivity(self.insulation_material) - - # -- Setup the Division Grid - new_material_ = self.insulation_material.duplicate() - ph_prop = new_material_.properties.ph # type: EnergyMaterialPhProperties + wood_framing_material = self.check_material(self.wood_framing_material) + if not wood_framing_material: + return (None, None) + # -------------------------------------------------------------------------------------------------------------- + # -- Setup the new Division Grid + division_grid = PhDivisionGrid() insulation_width = (self.wood_framing_member_oc_spacing - self.wood_framing_member_width) / 2 - ph_prop.divisions.set_column_widths( + division_grid.set_column_widths( [ insulation_width, self.wood_framing_member_width, insulation_width, ] ) - ph_prop.divisions.set_row_heights( + division_grid.set_row_heights( [ self.top_plate_width, self.element_total_length - self.top_plate_width - self.bottom_plate_width, @@ -142,23 +167,46 @@ def run(self): ] ) - # -- Set the Wood Framing Materials on the relevant cells - for row_number in range(ph_prop.divisions.row_count): - ph_prop.divisions.set_cell_material(1, row_number, self.wood_framing_material) + # -------------------------------------------------------------------------------------------------------------- + # -- Set the Materials on the cells + + # -- Set the 'stud' to the framing material (column-1) + for row_number in range(division_grid.row_count): + division_grid.set_cell_material(0, row_number, insulation_material) + division_grid.set_cell_material(1, row_number, wood_framing_material) + division_grid.set_cell_material(2, row_number, insulation_material) + # -- Set the top-plate if self.top_plate_width != 0: - ph_prop.divisions.set_cell_material(0, 0, self.wood_framing_material) - ph_prop.divisions.set_cell_material(2, 0, self.wood_framing_material) + division_grid.set_cell_material(0, 0, wood_framing_material) + division_grid.set_cell_material(1, 0, wood_framing_material) + division_grid.set_cell_material(2, 0, wood_framing_material) + # -- Set the bottom-plate if self.bottom_plate_width != 0: - ph_prop.divisions.set_cell_material(0, ph_prop.divisions.row_count - 1, self.wood_framing_material) - ph_prop.divisions.set_cell_material(2, ph_prop.divisions.row_count - 1, self.wood_framing_material) - + division_grid.set_cell_material(0, division_grid.row_count - 1, wood_framing_material) + division_grid.set_cell_material(1, division_grid.row_count - 1, wood_framing_material) + division_grid.set_cell_material(2, division_grid.row_count - 1, wood_framing_material) + + # -------------------------------------------------------------------------------------------------------------- + # -- Create a new Hybrid Material + base_material = division_grid.get_base_material() + if not base_material: + return (None, None) + new_material_ = base_material.duplicate() + nm = "{} + {}".format(insulation_material.display_name, wood_framing_material.display_name) + new_material_.display_name = nm + new_material_.identifier = nm + new_material_.conductivity = division_grid.get_equivalent_conductivity() + hbph_props = getattr(new_material_.properties, "ph") # type: EnergyMaterialPhProperties + hbph_props.divisions = division_grid + + # -------------------------------------------------------------------------------------------------------------- # -- Generate the Preview preview_ = generate_preview( self.IGH, - convert_list_of_values(ph_prop.divisions.column_widths, self.IGH.get_rhino_unit_system_name()), - convert_list_of_values(ph_prop.divisions.row_heights, self.IGH.get_rhino_unit_system_name()), + convert_list_of_values(division_grid.column_widths, self.IGH.get_rhino_unit_system_name()), + convert_list_of_values(division_grid.row_heights, self.IGH.get_rhino_unit_system_name()), ) return new_material_, preview_ diff --git a/honeybee_ph_rhino/gh_compo_io/assmbly_set_material_column_and_row.py b/honeybee_ph_rhino/gh_compo_io/assmbly_set_material_column_and_row.py index fee30e9..d398860 100644 --- a/honeybee_ph_rhino/gh_compo_io/assmbly_set_material_column_and_row.py +++ b/honeybee_ph_rhino/gh_compo_io/assmbly_set_material_column_and_row.py @@ -51,7 +51,7 @@ def run(self): row_position = gh_io.input_to_int(str(self.row_position)) hbe_material_ = self.hbe_material.duplicate() - ph_prop = hbe_material_.properties.ph # type: EnergyMaterialPhProperties + ph_prop = getattr(hbe_material_.properties, "ph") # type: EnergyMaterialPhProperties if not hasattr(ph_prop, "user_data"): ph_prop.user_data = {} diff --git a/requirements.txt b/requirements.txt index 5a3dbf8..76c35d4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -honeybee-core>=1.58.53 -honeybee-energy>=1.109.6 -ladybug-rhino>=1.42.17 -honeybee-ph>=1.28.15 -PHX>=1.47.6 -PH-units>=1.5.14 \ No newline at end of file +honeybee-core>=1.61.1 +honeybee-energy>=1.111.0 +ladybug-rhino>=1.43.1 +honeybee-ph>=1.28.20 +PHX>=1.48.0 +PH-units>=1.5.17 \ No newline at end of file