From eedfcd67aaf9c31a76bd97559165e13a27a81721 Mon Sep 17 00:00:00 2001 From: PH Tools Date: Sat, 1 Apr 2023 14:59:44 +0200 Subject: [PATCH] feat(collections): Add new GH Collection Components - Add Custom Collection Components - Add Air-Layer HB Material Component - Add 'Get Material' Component - Add Import from Flixo Component - Add Construction-from-JSON component --- .../src/HBPH - Calc Air Layer HB Material.py | 81 +++++++++++ .../src/HBPH - Create Custom Collection.py | 74 ++++++++++ .../HBPH - Create Detailed Constructions.py | 79 +++++++++++ .../src/HBPH - Get Brep Subface Materials.py | 64 +++++++++ .../src/HBPH - Get From Custom Collection.py | 64 +++++++++ .../src/HBPH - Import Flixo Materials.py | 62 +++++++++ .../HBPH - Calc Air Layer HB Material.ghuser | Bin 0 -> 5523 bytes .../HBPH - Create Custom Collection.ghuser | Bin 0 -> 3672 bytes ...BPH - Create Detailed Constructions.ghuser | Bin 0 -> 5165 bytes .../HBPH - Get Brep Subface Materials.ghuser | Bin 0 -> 3661 bytes .../HBPH - Get From Custom Collection.ghuser | Bin 0 -> 3574 bytes .../HBPH - Import Flixo Materials.ghuser | Bin 0 -> 3817 bytes honeybee_ph_rhino/_component_info_.py | 39 +++++- honeybee_ph_rhino/gh_compo_io/__init__.py | 9 +- .../assmbly_create_air_layer_mat.py | 130 ++++++++++++++++++ .../assmbly_create_detailed_const.py | 90 ++++++++++++ .../gh_compo_io/assmbly_import_flixo_mats.py | 126 +++++++++++++++++ .../gh_compo_io/util_create_collection.py | 94 +++++++++++++ .../gh_compo_io/util_get_brep_subface_mats.py | 61 ++++++++ .../gh_compo_io/util_get_from_collection.py | 31 +++++ honeybee_ph_rhino/gh_io.py | 5 + 21 files changed, 1007 insertions(+), 2 deletions(-) create mode 100644 honeybee_grasshopper_ph/src/HBPH - Calc Air Layer HB Material.py create mode 100644 honeybee_grasshopper_ph/src/HBPH - Create Custom Collection.py create mode 100644 honeybee_grasshopper_ph/src/HBPH - Create Detailed Constructions.py create mode 100644 honeybee_grasshopper_ph/src/HBPH - Get Brep Subface Materials.py create mode 100644 honeybee_grasshopper_ph/src/HBPH - Get From Custom Collection.py create mode 100644 honeybee_grasshopper_ph/src/HBPH - Import Flixo Materials.py create mode 100644 honeybee_grasshopper_ph/user_objects/HBPH - Calc Air Layer HB Material.ghuser create mode 100644 honeybee_grasshopper_ph/user_objects/HBPH - Create Custom Collection.ghuser create mode 100644 honeybee_grasshopper_ph/user_objects/HBPH - Create Detailed Constructions.ghuser create mode 100644 honeybee_grasshopper_ph/user_objects/HBPH - Get Brep Subface Materials.ghuser create mode 100644 honeybee_grasshopper_ph/user_objects/HBPH - Get From Custom Collection.ghuser create mode 100644 honeybee_grasshopper_ph/user_objects/HBPH - Import Flixo Materials.ghuser create mode 100644 honeybee_ph_rhino/gh_compo_io/assmbly_create_air_layer_mat.py create mode 100644 honeybee_ph_rhino/gh_compo_io/assmbly_create_detailed_const.py create mode 100644 honeybee_ph_rhino/gh_compo_io/assmbly_import_flixo_mats.py create mode 100644 honeybee_ph_rhino/gh_compo_io/util_create_collection.py create mode 100644 honeybee_ph_rhino/gh_compo_io/util_get_brep_subface_mats.py create mode 100644 honeybee_ph_rhino/gh_compo_io/util_get_from_collection.py diff --git a/honeybee_grasshopper_ph/src/HBPH - Calc Air Layer HB Material.py b/honeybee_grasshopper_ph/src/HBPH - Calc Air Layer HB Material.py new file mode 100644 index 0000000..2b62a65 --- /dev/null +++ b/honeybee_grasshopper_ph/src/HBPH - Calc Air Layer HB Material.py @@ -0,0 +1,81 @@ +# +# Honeybee-PH: A Plugin for adding Passive-House data to LadybugTools Honeybee-Energy Models +# +# This component is part of the PH-Tools toolkit . +# +# Copyright (c) 2022, PH-Tools and bldgtyp, llc +# Honeybee-PH is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# Honeybee-PH is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# For a copy of the GNU General Public License +# see . +# +# @license GPL-3.0+ +# +""" +Create a new Honeybee-Energy "Air-Layer" material. This calculator will +determine an equivalent conductivity based on the parameters input. The +procedue implemented here follows the PHPP v9/10 which closely matches the +ISO-6946-2017, Appendix D method. This material can be used in Honeybee +Constructions to approiximate the insulating effect of closed air-layers +such as service caviies. +- +Note: This "Air-Layer" is only suitable for CLOSED air layers which +are have a length AND width at least 10x the thickness, and which have less +thank 5 deg-K temperature change accross the layer. +- +EM April 1, 2023 + Args: + _heat_flow_direction: Input either - +"1-Upwards" +"2-Horizontal" +"3-Downwards" + + _thickness: (mm) The thickness of the Air Layer + + _srfc_1_emissivity: (%) Default=0.9 + + _srfc_2_emissivity: (%) Default=0.9 + + Returns: + marterial_: The new Honeybee-Energy Material. +""" + +import scriptcontext as sc +import Rhino as rh +import rhinoscriptsyntax as rs +import ghpythonlib.components as ghc +import Grasshopper as gh + +from honeybee_ph_rhino import gh_compo_io, gh_io + +# ------------------------------------------------------------------------------ +import honeybee_ph_rhino._component_info_ +reload(honeybee_ph_rhino._component_info_) +ghenv.Component.Name = "HBPH - Calc Air Layer HB Material" +DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev=False) +if DEV: + from honeybee_ph_rhino.gh_compo_io import assmbly_create_air_layer_mat as gh_compo_io + reload(gh_compo_io) + +# ------------------------------------------------------------------------------ +# -- GH Interface +IGH = gh_io.IGH( ghdoc, ghenv, sc, rh, rs, ghc, gh ) + +# ------------------------------------------------------------------------------ +gh_compo_interface = gh_compo_io.GHCompo_AirLayerMaterial( + IGH, + _display_name, + _heat_flow_direction, + _thickness, + _srfc_1_emissivity, + _srfc_1_emissivity + ) +material_ = gh_compo_interface.run() \ No newline at end of file diff --git a/honeybee_grasshopper_ph/src/HBPH - Create Custom Collection.py b/honeybee_grasshopper_ph/src/HBPH - Create Custom Collection.py new file mode 100644 index 0000000..2ff11f7 --- /dev/null +++ b/honeybee_grasshopper_ph/src/HBPH - Create Custom Collection.py @@ -0,0 +1,74 @@ +# +# Honeybee-PH: A Plugin for adding Passive-House data to LadybugTools Honeybee-Energy Models +# +# This component is part of the PH-Tools toolkit . +# +# Copyright (c) 2022, PH-Tools and bldgtyp, llc +# Honeybee-PH is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# Honeybee-PH is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# For a copy of the GNU General Public License +# see . +# +# @license GPL-3.0+ +# +""" +Create a new custom "Collection" of items. This collection works just like +a normal python 'Dictionary' and allows for item set and get using the typical +square bracket notation (ie: collection["my_key"] = my_value, etc.) + +If provided, the collection will use the "_key_name" as the dictionary "key", +for all items and if left blank will use the items 'id()' as the key +- +EM April 1, 2023 + Args: + _name: (str) An optional display_name for the collection. + + _key_name: (str): Default='id(item)'. Provide the name of the item's + 'key' atribute you would like to use when storing the item + to a dictionary. Be sure all items have this attribute. + + _items: (Collection) An iterable collection of items you would + like to add to the new CustomCollection object. + + Returns: + collection_: The new CustomCollection object with the items stored + according to their 'key' (or 'id' by default). +""" + +import scriptcontext as sc +import Rhino as rh +import rhinoscriptsyntax as rs +import ghpythonlib.components as ghc +import Grasshopper as gh + +from honeybee_ph_rhino import gh_compo_io, gh_io + +# ------------------------------------------------------------------------------ +import honeybee_ph_rhino._component_info_ +reload(honeybee_ph_rhino._component_info_) +ghenv.Component.Name = "HBPH - Create Custom Collection" +DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev=False) +if DEV: + from honeybee_ph_rhino.gh_compo_io import util_create_collection as gh_compo_io + reload(gh_compo_io) + +# ------------------------------------------------------------------------------ +# -- GH Interface +IGH = gh_io.IGH( ghdoc, ghenv, sc, rh, rs, ghc, gh ) + +# ------------------------------------------------------------------------------ +gh_compo_interface = gh_compo_io.GHCompo_CreateCustomCollection( + IGH, + _name, + _key_name, + _items, + ) +collection_ = gh_compo_interface.run() \ No newline at end of file diff --git a/honeybee_grasshopper_ph/src/HBPH - Create Detailed Constructions.py b/honeybee_grasshopper_ph/src/HBPH - Create Detailed Constructions.py new file mode 100644 index 0000000..ab51b30 --- /dev/null +++ b/honeybee_grasshopper_ph/src/HBPH - Create Detailed Constructions.py @@ -0,0 +1,79 @@ +# +# Honeybee-PH: A Plugin for adding Passive-House data to LadybugTools Honeybee-Energy Models +# +# This component is part of the PH-Tools toolkit . +# +# Copyright (c) 2022, PH-Tools and bldgtyp, llc +# Honeybee-PH is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# Honeybee-PH is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# For a copy of the GNU General Public License +# see . +# +# @license GPL-3.0+ +# +""" +Create new Honeybee-Energy Constructions based on a JSON file and a set of +Honeybee-Energy Materials. Note that the input JSON describing the construction +should be a normal HB JSON, except that this component also allows for an optional +"thickness" attribute which will set the thickness of each material layer as +the new construction is built. For example - + +"W1 - Below Grade Conc. Wall": { + "type": "OpaqueConstructionAbridged", + "identifier": "W1 - Below Grade Conc. Wall", + "materials": ["Concrete (Heavily Reinforced) [R-0.05/in]", "XPS [R-5.0/in]"], + "thicknesses": ["8in", "6in"] +} + +Will create a new construction and set the thicknesses of the layers as indicated (8in, then 6in). + +- +EM April 1, 2023 + Args: + _materials (List[EnergyMaterials]): A list of the Honeybee-Energy materials + that you would like to use to create the Honeybee Constructions. + + _path: (str) The path (or paths) to the .JSON file which describes the + Honeybee-Constructions. + + Returns: + constructions_: The new Honeybee-Energy Constructions, built from the + Honeybee-Energy Materials input. +""" + +import scriptcontext as sc +import Rhino as rh +import rhinoscriptsyntax as rs +import ghpythonlib.components as ghc +import Grasshopper as gh + +from honeybee_ph_rhino import gh_compo_io, gh_io + +# ------------------------------------------------------------------------------ +import honeybee_ph_rhino._component_info_ +reload(honeybee_ph_rhino._component_info_) +ghenv.Component.Name = "HBPH - Create Detailed Constructions" +DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev=False) +if DEV: + from honeybee_ph_rhino.gh_compo_io import assmbly_create_detailed_const as gh_compo_io + reload(gh_compo_io) + +# ------------------------------------------------------------------------------ +# -- GH Interface +IGH = gh_io.IGH( ghdoc, ghenv, sc, rh, rs, ghc, gh ) + +# ------------------------------------------------------------------------------ +gh_compo_interface = gh_compo_io.GHCompo_CreateDetailedConstructions( + IGH, + _path, + _materials, + ) +constructions_ = gh_compo_interface.run() \ No newline at end of file diff --git a/honeybee_grasshopper_ph/src/HBPH - Get Brep Subface Materials.py b/honeybee_grasshopper_ph/src/HBPH - Get Brep Subface Materials.py new file mode 100644 index 0000000..5d2ef9a --- /dev/null +++ b/honeybee_grasshopper_ph/src/HBPH - Get Brep Subface Materials.py @@ -0,0 +1,64 @@ +# +# Honeybee-PH: A Plugin for adding Passive-House data to LadybugTools Honeybee-Energy Models +# +# This component is part of the PH-Tools toolkit . +# +# Copyright (c) 2022, PH-Tools and bldgtyp, llc +# Honeybee-PH is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# Honeybee-PH is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# For a copy of the GNU General Public License +# see . +# +# @license GPL-3.0+ +# +""" +Get all of the Rhino Material Names for the subfaces of a closed Brep. This is +useful wheh using Materials as the 'key' for assigning things like constructions, +boundary-conditions or other sub-face specific values. +- +EM April 1, 2023 + Args: + _breps: (List[Guid]) A List of Brep Guid values. + + Returns: + subface_geometry_: The subface surfaces of the input Brep. + + material_names_: The names of the Materials assigned to the + subface surfaces of the input Breps. +""" + +import scriptcontext as sc +import Rhino as rh +import rhinoscriptsyntax as rs +import ghpythonlib.components as ghc +import Grasshopper as gh + +from honeybee_ph_rhino import gh_compo_io, gh_io + +# ------------------------------------------------------------------------------ +import honeybee_ph_rhino._component_info_ +reload(honeybee_ph_rhino._component_info_) +ghenv.Component.Name = "HBPH - Get Brep Subface Materials" +DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev=False) +if DEV: + from honeybee_ph_rhino.gh_compo_io import util_get_brep_subface_mats as gh_compo_io + reload(gh_compo_io) + +# ------------------------------------------------------------------------------ +# -- GH Interface +IGH = gh_io.IGH( ghdoc, ghenv, sc, rh, rs, ghc, gh ) + +# ------------------------------------------------------------------------------ +gh_compo_interface = gh_compo_io.GHCompo_GetSubFaceMaterials( + IGH, + _breps + ) +subface_geometry_, material_names_ = gh_compo_interface.run() \ No newline at end of file diff --git a/honeybee_grasshopper_ph/src/HBPH - Get From Custom Collection.py b/honeybee_grasshopper_ph/src/HBPH - Get From Custom Collection.py new file mode 100644 index 0000000..29d87ba --- /dev/null +++ b/honeybee_grasshopper_ph/src/HBPH - Get From Custom Collection.py @@ -0,0 +1,64 @@ +# +# Honeybee-PH: A Plugin for adding Passive-House data to LadybugTools Honeybee-Energy Models +# +# This component is part of the PH-Tools toolkit . +# +# Copyright (c) 2022, PH-Tools and bldgtyp, llc +# Honeybee-PH is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# Honeybee-PH is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# For a copy of the GNU General Public License +# see . +# +# @license GPL-3.0+ +# +""" +Get all of the Rhino Material Names for the subfaces of a closed Brep. This is +useful wheh using Materials as the 'key' for assigning things like constructions, +boundary-conditions or other sub-face specific values. +- +EM April 1, 2023 + Args: + _collection: (List[Guid]) A CustomCollection to get items from. + + _keys: (List[str]) A list of the keys to 'get' from the collection + + Returns: + values_: The items found, or None if not found. +""" + +import scriptcontext as sc +import Rhino as rh +import rhinoscriptsyntax as rs +import ghpythonlib.components as ghc +import Grasshopper as gh + +from honeybee_ph_rhino import gh_compo_io, gh_io + +# ------------------------------------------------------------------------------ +import honeybee_ph_rhino._component_info_ +reload(honeybee_ph_rhino._component_info_) +ghenv.Component.Name = "HBPH - Get From Custom Collection" +DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev=False) +if DEV: + from honeybee_ph_rhino.gh_compo_io import util_get_from_collection as gh_compo_io + reload(gh_compo_io) + +# ------------------------------------------------------------------------------ +# -- GH Interface +IGH = gh_io.IGH( ghdoc, ghenv, sc, rh, rs, ghc, gh ) + +# ------------------------------------------------------------------------------ +gh_compo_interface = gh_compo_io.GHCompo_GetFromCustomCollection( + IGH, + _collection, + _keys, + ) +values_ = gh_compo_interface.run() \ No newline at end of file diff --git a/honeybee_grasshopper_ph/src/HBPH - Import Flixo Materials.py b/honeybee_grasshopper_ph/src/HBPH - Import Flixo Materials.py new file mode 100644 index 0000000..7c6a6a1 --- /dev/null +++ b/honeybee_grasshopper_ph/src/HBPH - Import Flixo Materials.py @@ -0,0 +1,62 @@ +# +# Honeybee-PH: A Plugin for adding Passive-House data to LadybugTools Honeybee-Energy Models +# +# This component is part of the PH-Tools toolkit . +# +# Copyright (c) 2022, PH-Tools and bldgtyp, llc +# Honeybee-PH is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# Honeybee-PH is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# For a copy of the GNU General Public License +# see . +# +# @license GPL-3.0+ +# +""" +Import "Infomind Flixo" material .csv files as Honeybee-Energy Materials. This is +useful if you are trying to load materials from Flixo for use in your energy model. +- +EM March 31, 2023 + Args: + _path: (str) The path (or paths) to the Flixo .csv files you would like + to import as Honeybee-Energy Materials. + + Returns: + materials_: The new Honeybee-Energy materials which were created from the + Flixo .csv files. +""" + +import scriptcontext as sc +import Rhino as rh +import rhinoscriptsyntax as rs +import ghpythonlib.components as ghc +import Grasshopper as gh + +from honeybee_ph_rhino import gh_compo_io, gh_io + +# ------------------------------------------------------------------------------ +import honeybee_ph_rhino._component_info_ +reload(honeybee_ph_rhino._component_info_) +ghenv.Component.Name = "HBPH - Import Flixo Materials" +DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev=False) +if DEV: + from honeybee_ph_rhino.gh_compo_io import assmbly_import_flixo_mats as gh_compo_io + reload(gh_compo_io) + +# ------------------------------------------------------------------------------ +# -- GH Interface +IGH = gh_io.IGH( ghdoc, ghenv, sc, rh, rs, ghc, gh ) + +# ------------------------------------------------------------------------------ +gh_compo_interface = gh_compo_io.GHCompo_ImportFlixoMaterials( + IGH, + _path + ) +materials_ = gh_compo_interface.run() \ No newline at end of file diff --git a/honeybee_grasshopper_ph/user_objects/HBPH - Calc Air Layer HB Material.ghuser b/honeybee_grasshopper_ph/user_objects/HBPH - Calc Air Layer HB Material.ghuser new file mode 100644 index 0000000000000000000000000000000000000000..1e8c88a14f81a4a9f2afbf19b1609e1287671475 GIT binary patch literal 5523 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 bqw~%v=*$UD|NT>xR$c)Z1T@AVkRJaB9f1zR literal 0 HcmV?d00001 diff --git a/honeybee_grasshopper_ph/user_objects/HBPH - Get Brep Subface Materials.ghuser b/honeybee_grasshopper_ph/user_objects/HBPH - Get Brep Subface Materials.ghuser new file mode 100644 index 0000000000000000000000000000000000000000..6b2ccaff35f1ecd06a3f07d8b79f602ff319644c GIT binary patch literal 3661 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 literal 0 HcmV?d00001 diff --git a/honeybee_grasshopper_ph/user_objects/HBPH - Get From Custom Collection.ghuser b/honeybee_grasshopper_ph/user_objects/HBPH - Get From Custom Collection.ghuser new file mode 100644 index 0000000000000000000000000000000000000000..a40b8699969646c2d035d54cc935352feb3d0d62 GIT binary patch literal 3574 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 literal 0 HcmV?d00001 diff --git a/honeybee_grasshopper_ph/user_objects/HBPH - Import Flixo Materials.ghuser b/honeybee_grasshopper_ph/user_objects/HBPH - Import Flixo Materials.ghuser new file mode 100644 index 0000000000000000000000000000000000000000..1d6edf6dc360d48efa736c601c8869d47e9986cd GIT binary patch literal 3817 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 literal 0 HcmV?d00001 diff --git a/honeybee_ph_rhino/_component_info_.py b/honeybee_ph_rhino/_component_info_.py index ead8cae..702103e 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.0.28" +RELEASE_VERSION = "Honeybee-PH v1.0.29" CATEGORY = "HB-PH" SUB_CATEGORIES = { 0: "00 | Utils", @@ -336,6 +336,24 @@ "Category": CATEGORY, "SubCategory": 1, }, + "HBPH - Import Flixo Materials": { + "NickName": "Import Flixo Mats.", + "Message": RELEASE_VERSION, + "Category": CATEGORY, + "SubCategory": 1, + }, + "HBPH - Create Detailed Constructions": { + "NickName": "Create Detailed Constructions", + "Message": RELEASE_VERSION, + "Category": CATEGORY, + "SubCategory": 1, + }, + "HBPH - Calc Air Layer HB Material": { + "NickName": "Create Air Layer Mat", + "Message": RELEASE_VERSION, + "Category": CATEGORY, + "SubCategory": 1, + }, # -- Shading "HBPH - Create Building Shading": { "NickName": "Create Shading", @@ -418,6 +436,25 @@ "Category": CATEGORY, "SubCategory": 4, }, + # -- Utility + "HBPH - Get Brep Subface Materials": { + "NickName": "Get Subface Mats", + "Message": RELEASE_VERSION, + "Category": CATEGORY, + "SubCategory": 4, + }, + "HBPH - Create Custom Collection": { + "NickName": "Create Collection", + "Message": RELEASE_VERSION, + "Category": CATEGORY, + "SubCategory": 4, + }, + "HBPH - Get From Custom Collection": { + "NickName": "Get From Collection", + "Message": RELEASE_VERSION, + "Category": CATEGORY, + "SubCategory": 4, + }, } diff --git a/honeybee_ph_rhino/gh_compo_io/__init__.py b/honeybee_ph_rhino/gh_compo_io/__init__.py index 7fad946..4db4f3c 100644 --- a/honeybee_ph_rhino/gh_compo_io/__init__.py +++ b/honeybee_ph_rhino/gh_compo_io/__init__.py @@ -25,6 +25,9 @@ # -- Envelope from honeybee_ph_rhino.gh_compo_io.assmbly_create_sd_const import GHCompo_CreateSDConstructions from honeybee_ph_rhino.gh_compo_io.assmbly_create_mixed_mat import GHCompo_CreateMixedHBMaterial +from honeybee_ph_rhino.gh_compo_io.assmbly_import_flixo_mats import GHCompo_ImportFlixoMaterials +from honeybee_ph_rhino.gh_compo_io.assmbly_create_detailed_const import GHCompo_CreateDetailedConstructions +from honeybee_ph_rhino.gh_compo_io.assmbly_create_air_layer_mat import GHCompo_AirLayerMaterial from honeybee_ph_rhino.gh_compo_io.set_spec_heat_cap import GHCompo_SetRoomSpecHeatCaps # -- Mech from honeybee_ph_rhino.gh_compo_io.mech_create_vent_sys import GHCompo_CreateVentSystem @@ -68,4 +71,8 @@ from honeybee_ph_rhino.gh_compo_io.write_PHPP import GHCompo_WriteToPHPP # -- Foundations from honeybee_ph_rhino.gh_compo_io.foundations_add import GHCompo_AddFoundations -from honeybee_ph_rhino.gh_compo_io.foundations_create import GHCompo_CreateFoundations \ No newline at end of file +from honeybee_ph_rhino.gh_compo_io.foundations_create import GHCompo_CreateFoundations +# -- Utility +from honeybee_ph_rhino.gh_compo_io.util_create_collection import GHCompo_CreateCustomCollection +from honeybee_ph_rhino.gh_compo_io.util_get_from_collection import GHCompo_GetFromCustomCollection +from honeybee_ph_rhino.gh_compo_io.util_get_brep_subface_mats import GHCompo_GetSubFaceMaterials \ No newline at end of file diff --git a/honeybee_ph_rhino/gh_compo_io/assmbly_create_air_layer_mat.py b/honeybee_ph_rhino/gh_compo_io/assmbly_create_air_layer_mat.py new file mode 100644 index 0000000..d34199b --- /dev/null +++ b/honeybee_ph_rhino/gh_compo_io/assmbly_create_air_layer_mat.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +# -*- Python Version: 2.7 -*- + +"""GHCompo Interface: HBPH - Calc Air Layer HB Material.""" + +try: + from typing import Optional +except ImportError: + pass # IronPython 2.7 + +from honeybee.typing import clean_ep_string +from honeybee_energy.material.opaque import EnergyMaterial + +try: + from honeybee_ph_rhino import gh_io + from honeybee_ph_rhino.gh_compo_io import ghio_validators +except ImportError as e: + raise ImportError('\nFailed to import honeybee_ph_rhino:\n\t{}'.format(e)) + +try: + from honeybee_ph_utils.input_tools import input_to_int +except: + raise ImportError('\nFailed to import honeybee_ph_utils:\n\t{}'.format(e)) + +class GHCompo_AirLayerMaterial(object): + """Equivalent Thermal Conductivity of Still Air Layers according to PHPP method. + + Applicable to assembly air-layers which are up to 300m thick (12in) AND where + the width and length of the layer are BOTH >10x the thickness of the layer. + This method is similar to the ISO-6946-2017, Appendix D method but not identical. + """ + + display_name = ghio_validators.HBName("display_name") + thickness = ghio_validators.UnitM("thickness") + e_1 = ghio_validators.FloatPercentage("e_1") + e_2 = ghio_validators.FloatPercentage("e_2") + + def __init__(self, _IGH, _name, _hf_direction, _thickness, _e1, _e2): + # type: (gh_io.IGH, str, str, float, float, float) -> None + self.IGH = _IGH + self.hf_direction = input_to_int(_hf_direction, 2) + self.thickness = _thickness or 0.000 + self.e_1 = _e1 or 0.9 + self.e_2 = _e2 or 0.9 + self.display_name = _name or "PH_AirLayer_({:.3f}m_{})".format(self.thickness, self.orientation) + + @property + def h_r(self): + # type: () -> float + """Radiative Coefficient (W/m2-K)""" + return 5.1 / ( 1 / self.e_1 + 1 / self.e_2 - 1) + + @property + def alpha(self): + # type: () -> int + """Surface normal direction in degrees. 0=up, 180=down""" + if self.hf_direction == 1: + return 0 # Upwards + elif self.hf_direction == 2: + return 90 # Horizontal + elif self.hf_direction == 3: + return 180 + else: + raise Exception("Error: Surface orientation not allowed.") + + @property + def orientation(self): + # type: () -> str + """Surface normal direction description""" + if self.hf_direction == 1: + return "Upwards Heat Flow" + elif self.hf_direction == 2: + return "Horizontal Heat Flow" + elif self.hf_direction == 3: + return "Downwards Heat Flow" + else: + raise Exception("Error: Surface orientation not allowed.") + + @property + def h_a(self): + # type: () -> float + """Conduction / Convection Coefficient (W/m2-K) + + h a is determined by conduction in still air for narrow airspaces and + by convection in wide cavities. For calculations in accordance with + ISO-6946-2017, it is the larger of 0.025/d and the value of h_a obtained from + Table D.1 or Table D.2. In Tables D.1 and D.2, d is the thickness of the + airspace in the direction of heat flow, in metres, and ΔT is the temperature + difference across the airspace, in kelvins. Table D.1 should be used when + the temperature difference across the airspace is less than or equal to 5K. + """ + + if self.alpha == 0: + # Upwards + return max(1.95, 0.025/self.thickness) + elif self.alpha == 90: + # Horizontal + return max(1.25, 0.025/self.thickness) + elif self.alpha == 180: + # Downwards + return max(0.12 * (self.thickness**-0.44), 0.025/self.thickness) + else: + raise Exception("Error: Surface orientation not") + + @property + def thermal_conductivity(self): + # type: () -> float + """W/mK""" + return self.thickness * (self.h_a + self.h_r) + + def create_new_HB_Material(self): + # type: () -> EnergyMaterial + return EnergyMaterial( + identifier = self.display_name, + thickness = self.thickness, + conductivity= self.thermal_conductivity, + density = 999.999, + specific_heat = 999.999, + roughness = 'MediumRough', + thermal_absorptance = 0.9, + solar_absorptance = 0.7, + visible_absorptance = None + ) + + def run(self): + # type: () -> Optional[EnergyMaterial] + if not self.thickness or not self.hf_direction: + return None + + return self.create_new_HB_Material() \ No newline at end of file diff --git a/honeybee_ph_rhino/gh_compo_io/assmbly_create_detailed_const.py b/honeybee_ph_rhino/gh_compo_io/assmbly_create_detailed_const.py new file mode 100644 index 0000000..4ba53e3 --- /dev/null +++ b/honeybee_ph_rhino/gh_compo_io/assmbly_create_detailed_const.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# -*- Python Version: 2.7 -*- + +"""GHCompo Interface: HBPH - Create Detailed Constructions.""" + +try: + from typing import List, Optional, Dict, Any +except ImportError: + pass # IronPython 2.7 + +import os +import json + +from honeybee_energy.material.opaque import EnergyMaterial +from honeybee_energy.construction.opaque import OpaqueConstruction +from honeybee.typing import clean_ep_string + +from ph_units.parser import parse_input +from ph_units.converter import convert + +from honeybee_ph_rhino import gh_io + +class GHCompo_CreateDetailedConstructions(object): + + def __init__(self, _IGH, _path, _materials): + # type: (gh_io.IGH, str, List[EnergyMaterial]) -> None + self.IGH = _IGH + self._path = str(_path) + self.materials = _materials + + @property + def path(self): + # type: () -> Optional[str] + if not os.path.exists(self._path): + return None + + file_extension = str(os.path.splitext(self._path)[1]).upper() + if not file_extension == ".JSON": + msg = "Error: please input only .JSON files." + self.IGH.warning(msg) + return None + + return self._path + + def create_materials(self, _const_data): + # type: (Dict[str, Any]) -> List[EnergyMaterial] + + # -- Turn the materials into a dict + materials = {m.display_name:m for m in self.materials} + + materials_ = [] + for i, mat_name in enumerate(_const_data["materials"]): + + base_mat = materials[mat_name] + + # -- If thicknesses are provided, try and set the thickness + try: + value, unit = parse_input(_const_data["thicknesses"][i]) + thickness = convert(value, unit, "M") + except: + thickness = base_mat.thickness + + # -- build the new material + new_mat = base_mat.duplicate() + new_mat.identifier = "{}_{:.3f}m".format(base_mat.display_name, thickness) + new_mat.thickness = thickness + new_mat.lock() + + materials_.append(new_mat) + + return materials_ + + def run(self): + # type: () -> List[OpaqueConstruction] + if not self.path or not self.materials: + return [] + + # Load the file + with open(self.path) as json_file: + input_data = json.load(json_file) + + constructions_ = [] + for const_data in input_data.values(): + new_const = OpaqueConstruction( + identifier=clean_ep_string(const_data["identifier"]), + materials = self.create_materials(const_data) + ) + constructions_.append(new_const) + + return constructions_ \ No newline at end of file diff --git a/honeybee_ph_rhino/gh_compo_io/assmbly_import_flixo_mats.py b/honeybee_ph_rhino/gh_compo_io/assmbly_import_flixo_mats.py new file mode 100644 index 0000000..2cccdb7 --- /dev/null +++ b/honeybee_ph_rhino/gh_compo_io/assmbly_import_flixo_mats.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# -*- Python Version: 2.7 -*- + +"""GHCompo Interface: HBPH - Import Flixo Materials.""" + +try: + from typing import Optional, List +except ImportError: + pass # IronPython 2.7 + +from itertools import izip +import os +from io import open as io_open + +from honeybee.typing import clean_ep_string +from honeybee_energy.material.opaque import EnergyMaterial +from honeybee_ph_rhino import gh_io + +class FlixoDataItem(object): + + def __init__(self, *args, **kwargs): + for k, v in kwargs.items(): + setattr(self, str(k), str(v)) + + @property + def display_name(self): + # type: () -> str + return getattr(self, "Name", "") + + @property + def conductivity(self): + # type: () -> Optional[float] + try: + return float(getattr(self, "LambdaHor")) + except: + return None + + def __str__(self): + # type: () -> str + return "{}(display_name={})".format(self.__class__.__name__, self.display_name) + + def __repr__(self): + return str(self) + + def ToString(self): + return str(self) + + +class GHCompo_ImportFlixoMaterials(object): + THICKNESS = 1.0 #m + DENSITY = 999.9999 + SPEC_HEAT = 999.999 + ROUGHNESS = "Rough" + THERM_ABS = 0.9 + SOL_ABS = 0.7 + VIS_ABS = 0.7 + + def __init__(self, _IGH, _path): + # type: (gh_io.IGH, str) -> None + self.IGH = _IGH + self._path = str(_path) + + @property + def path(self): + # type: () -> Optional[str] + if not os.path.exists(self._path): + return None + + file_extension = str(os.path.splitext(self._path)[1]).upper() + if not file_extension == ".CSV": + msg = "Error: please input only .CSV files." + self.IGH.warning(msg) + return None + + return self._path + + def build_headers(self, _headers): + # type: (str) -> List[str] + headers_list = _headers.split(";") + + headers_ = [] + for header_name in headers_list: + + counter = len([header_name for h in headers_ if "{}_".format(header_name) in h or header_name in h]) + if counter != 0: + header_name = "{}_{}".format(header_name, counter) + headers_.append(header_name) + + return headers_ + + def build_flixo_data_from_inputs(self, _data): + # type: (List[str]) -> List[FlixoDataItem] + flixo_data_items = [] + headers = self.build_headers(_data[1]) + for item in _data[2:]: + flixo_data_items.append( + FlixoDataItem( + **{k:v for k, v in izip(headers, item.split(";")[1:])} + ) + ) + return flixo_data_items + + def build_hb_materials(self, _flixo_data_items): + # type: (List[FlixoDataItem]) -> List[EnergyMaterial] + materials_ = [] + for fl in sorted(_flixo_data_items, key=lambda f: f.display_name): + if not fl.display_name: + continue + + hb_mat = EnergyMaterial( + clean_ep_string(fl.display_name), self.THICKNESS, fl.conductivity, self.DENSITY, + self.SPEC_HEAT, self.ROUGHNESS, self.THERM_ABS, self.SOL_ABS, self.VIS_ABS) + materials_.append(hb_mat) + return materials_ + + def run(self): + # type: () -> List[EnergyMaterial] + if not self.path: + return [] + + # -- Get the file data + with io_open(self.path) as f: + data = f.readlines() + + flixo_data_items = self.build_flixo_data_from_inputs(data) + return self.build_hb_materials(flixo_data_items) diff --git a/honeybee_ph_rhino/gh_compo_io/util_create_collection.py b/honeybee_ph_rhino/gh_compo_io/util_create_collection.py new file mode 100644 index 0000000..2aed76d --- /dev/null +++ b/honeybee_ph_rhino/gh_compo_io/util_create_collection.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# -*- Python Version: 2.7 -*- + +"""GHCompo Interface: HBPH - Create Custom Collection.""" + +try: + from typing import Collection, TypeVar, ValuesView, KeysView, ItemsView, Dict, List, Optional + T = TypeVar("T") +except ImportError: + pass #IronPython 2.7 + +try: + from honeybee_ph_rhino import gh_io +except ImportError as e: + raise ImportError('\nFailed to import honeybee_ph_rhino:\n\t{}'.format(e)) + + +class CustomCollection(object): + + """A custom 'Collection' class which works like a Python Dictionary.""" + + def __init__(self, _display_name="", *args, **kwargs): + # type: (str, List, Dict) -> None + self.display_name = _display_name or "" + self._storage = {} + + def keys(self): + # type: () -> KeysView[str] + return self._storage.keys() + + def items(self): + # type: () -> ItemsView[str, T] + return self._storage.items() + + def values(self): + # type: () -> ValuesView[T] + return self._storage.values() + + def __setitem__(self, k, v): + # type: (str, T) -> None + self._storage[k] = v + + def __getitem__(self, k): + # type: (str) -> T + return self._storage[k] + + def get(self, k, default): + # type: (str, T) -> Optional[T] + return self._storage.get(k, default) + + def __str__(self): + # type: () -> str + return '{} {} ({} items)\n{}'.format( + self.__class__.__name__, + self.display_name, + len(self._storage), + "\n".join([ + "\t - Key: {} = {}...".format(k, str(v)[:25].replace("\n", "")) + for k, v in self.items() + ] + ) + ) + + def __repr__(self): + return str(self) + + def ToString(self): + return str(self) + +class GHCompo_CreateCustomCollection(object): + + def __init__(self, _IGH, _name, _key_name, _items, *args, **kwargs): + # type: (gh_io.IGH, str, str, Collection, List, Dict) -> None + self.IGH = _IGH + self.name = _name + self.key_name = _key_name + self.items = _items + + def key(self, _item): + # type: (T) -> str + """Return the Key to use when storing the value. Returns id(item) by default.""" + if self.key_name: + return str(getattr(_item, self.key_name)) + else: + return str(id(_item)) + + def run(self): + # type: () -> CustomCollection + collection_ = CustomCollection(self.name) + + for item in self.items: + collection_[self.key(item)] = item + + return collection_ \ No newline at end of file diff --git a/honeybee_ph_rhino/gh_compo_io/util_get_brep_subface_mats.py b/honeybee_ph_rhino/gh_compo_io/util_get_brep_subface_mats.py new file mode 100644 index 0000000..28e62bc --- /dev/null +++ b/honeybee_ph_rhino/gh_compo_io/util_get_brep_subface_mats.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# -*- Python Version: 2.7 -*- + +"""GHCompo Interface: HBPH - Get Brep Subface Materials.""" + +try: + from typing import Dict, List, Tuple, Any +except ImportError: + pass #IronPython 2.7 + +try: + from Grasshopper import DataTree # type: ignore + from Grasshopper.Kernel.Data import GH_Path # type: ignore + from System import Object # type: ignore +except: + pass # outside Rhino / Grasshopper + +try: + from honeybee_ph_rhino import gh_io +except ImportError as e: + raise ImportError('\nFailed to import honeybee_ph_rhino:\n\t{}'.format(e)) + + +class GHCompo_GetSubFaceMaterials(object): + + def __init__(self, _IGH, _brep_guids, *args, **kwargs): + # type: (gh_io.IGH, List, List, Dict) -> None + self.IGH = _IGH + self.brep_guids = _brep_guids + + def get_brep_face_data(self, _brep_guid): + # type: (Any, Any) -> Tuple[List, List] + geo_ = [] + names_ = [] + brep = self.IGH.rs.coercebrep(_brep_guid) + for face in brep.Faces: + # -- Add the face geometry to the output set + geo_.append(face) + + # -- Get the BrepFace's Material Name and add to the output + compo_index = self.IGH.Rhino.Geometry.ComponentIndex( + self.IGH.Rhino.Geometry.ComponentIndexType.BrepFace, + face.FaceIndex + ) + brep_obj = self.IGH.Rhino.RhinoDoc.ActiveDoc.Objects.FindId(_brep_guid) + mat_name = self.IGH.Rhino.DocObjects.RhinoObject.GetMaterial(brep_obj, compo_index).Name + names_.append(mat_name) + + return geo_, names_ + + def run(self): + subface_geo_ = DataTree[Object]() + mat_names_ = DataTree[Object]() + + with self.IGH.context_rh_doc(): + for i, brep_guid in enumerate(self.brep_guids): + faces, mats = self.get_brep_face_data(brep_guid) + subface_geo_.AddRange(faces, GH_Path(i)) + mat_names_.AddRange(mats, GH_Path(i)) + + return subface_geo_, mat_names_ \ No newline at end of file diff --git a/honeybee_ph_rhino/gh_compo_io/util_get_from_collection.py b/honeybee_ph_rhino/gh_compo_io/util_get_from_collection.py new file mode 100644 index 0000000..3baf009 --- /dev/null +++ b/honeybee_ph_rhino/gh_compo_io/util_get_from_collection.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# -*- Python Version: 2.7 -*- + +"""GHCompo Interface: HBPH - Get From Custom Collection.""" + +try: + from typing import Dict, List +except ImportError: + pass #IronPython 2.7 + +try: + from honeybee_ph_rhino import gh_io +except ImportError as e: + raise ImportError('\nFailed to import honeybee_ph_rhino:\n\t{}'.format(e)) + +from honeybee_ph_rhino.gh_compo_io.util_create_collection import CustomCollection + +class GHCompo_GetFromCustomCollection(object): + + def __init__(self, _IGH, _collection, _keys, *args, **kwargs): + # type: (gh_io.IGH, CustomCollection, List[str], List, Dict) -> None + self.IGH = _IGH + self.collection = _collection + self.keys = _keys + + def run(self): + # type: () -> List + if not self.collection or not self.keys: + return [] + + return [self.collection.get(key, None) for key in self.keys] \ No newline at end of file diff --git a/honeybee_ph_rhino/gh_io.py b/honeybee_ph_rhino/gh_io.py index 974ec23..70dc692 100644 --- a/honeybee_ph_rhino/gh_io.py +++ b/honeybee_ph_rhino/gh_io.py @@ -77,6 +77,11 @@ def __init__(self, _ghdoc, _ghenv, _sc, _rh, _rs, _ghc, _gh): self.ghpythonlib_components = _ghc self.Grasshopper = _gh + @property + def rs(self): + """Convenience Attribute Alias.""" + return self.rhinoscriptsyntax + def gh_compo_find_input_index_by_name(self, _input_name): # type: (str) -> int """