From 3a94fa61017a6d51cee759dac6e69847046d8569 Mon Sep 17 00:00:00 2001 From: PH Tools Date: Tue, 28 Jan 2025 16:54:29 -0500 Subject: [PATCH] fix(phius-res): Update all Phius Residential Components - Remove older Phius Multi-Family, replace with 'get' compo - Update all Residential Program components - Update installer versions --- hbph_installer.gh | Bin 15496 -> 17208 bytes .../src/HBPH - Add PH Equipment.py | 2 +- ...HBPH - Get Phius Multi-Family Load Data.py | 78 +++++ .../src/HBPH - Phius MF Res Calculator.py | 2 +- ... - Get Phius Multi-Family Load Data.ghuser | Bin 0 -> 3535 bytes honeybee_ph_rhino/_component_info_.py | 10 +- .../gh_compo_io/program/__init__.py | 7 +- .../program/_deprecated_/__init__.py | 0 .../{ => _deprecated_}/add_elec_equip.py | 0 .../{ => _deprecated_}/phius_MF_calc.py | 49 ++-- .../gh_compo_io/program/get_phius_mf_data.py | 267 ++++++++++++++++++ .../gh_compo_io/program/get_res_occupancy.py | 11 +- .../gh_compo_io/program/set_dwelling.py | 72 ++++- .../gh_compo_io/program/set_res_occupancy.py | 4 +- ...te_single_family.py => set_res_program.py} | 24 +- 15 files changed, 470 insertions(+), 56 deletions(-) create mode 100644 honeybee_grasshopper_ph/src/HBPH - Get Phius Multi-Family Load Data.py create mode 100644 honeybee_grasshopper_ph/user_objects/HBPH - Get Phius Multi-Family Load Data.ghuser create mode 100644 honeybee_ph_rhino/gh_compo_io/program/_deprecated_/__init__.py rename honeybee_ph_rhino/gh_compo_io/program/{ => _deprecated_}/add_elec_equip.py (100%) rename honeybee_ph_rhino/gh_compo_io/program/{ => _deprecated_}/phius_MF_calc.py (91%) create mode 100644 honeybee_ph_rhino/gh_compo_io/program/get_phius_mf_data.py rename honeybee_ph_rhino/gh_compo_io/program/{create_single_family.py => set_res_program.py} (97%) diff --git a/hbph_installer.gh b/hbph_installer.gh index cd47e4113820c091e1e0a29b3b195c8f9fea3f13..ce0cb25c260f6828dc110860a5603eaac0e6b5a8 100644 GIT binary patch literal 17208 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 L{{sL3|NjF3xR=HL literal 15496 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 K0RRC1{{sL89XWmg diff --git a/honeybee_grasshopper_ph/src/HBPH - Add PH Equipment.py b/honeybee_grasshopper_ph/src/HBPH - Add PH Equipment.py index 44b473f..39d201e 100644 --- a/honeybee_grasshopper_ph/src/HBPH - Add PH Equipment.py +++ b/honeybee_grasshopper_ph/src/HBPH - Add PH Equipment.py @@ -75,7 +75,7 @@ ghenv.Component.Name = "HBPH - Add PH Equipment" DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev=False) if DEV: - from honeybee_ph_rhino.gh_compo_io.program import add_elec_equip as gh_compo_io + from honeybee_ph_rhino.gh_compo_io.program._deprecated_ import add_elec_equip as gh_compo_io reload(gh_compo_io) reload(gh_io) diff --git a/honeybee_grasshopper_ph/src/HBPH - Get Phius Multi-Family Load Data.py b/honeybee_grasshopper_ph/src/HBPH - Get Phius Multi-Family Load Data.py new file mode 100644 index 0000000..a8a315d --- /dev/null +++ b/honeybee_grasshopper_ph/src/HBPH - Get Phius Multi-Family Load Data.py @@ -0,0 +1,78 @@ +# +# 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) 2025, 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+ +# +""" +....desc.... +- +EM January 28, 2025 + Args: + + _hb_rooms: (list[Room]) + + Returns: + +""" + +import scriptcontext as sc +import Rhino as rh +import rhinoscriptsyntax as rs +import ghpythonlib.components as ghc +import Grasshopper as gh + +try: + from honeybee_ph_rhino import gh_compo_io +except ImportError as e: + raise ImportError('\nFailed to import honeybee_ph_rhino:\n\t{}'.format(e)) + +try: + from ph_gh_component_io import gh_io +except ImportError as e: + raise ImportError('\nFailed to import ph_gh_component_io:\n\t{}'.format(e)) + + +#------------------------------------------------------------------------------- +import honeybee_ph_rhino._component_info_ +reload(honeybee_ph_rhino._component_info_) +ghenv.Component.Name = "HBPH - Get Phius Multi-Family Load Data" +DEV = honeybee_ph_rhino._component_info_.set_component_params(ghenv, dev="250128") +if DEV: + from honeybee_ph_rhino.gh_compo_io.program import get_phius_mf_data as gh_compo_io + reload(gh_compo_io) + reload(gh_io) + +# ------------------------------------------------------------------------------ +# -- GH Interface +IGH = gh_io.IGH( ghdoc, ghenv, sc, rh, rs, ghc, gh ) + + +#------------------------------------------------------------------------------- +# -- Create the new Single-Family Home Program from the Rooms +gh_compo_interface = gh_compo_io.GHCompo_GetPhiusMFLoadData( + IGH, + _hb_rooms, +) +( + res_data_by_story_, + res_totals_, + non_res_program_data_, + non_res_room_data_, + non_res_totals_, +) = gh_compo_interface.run() \ No newline at end of file diff --git a/honeybee_grasshopper_ph/src/HBPH - Phius MF Res Calculator.py b/honeybee_grasshopper_ph/src/HBPH - Phius MF Res Calculator.py index 8eda5ab..b59f414 100644 --- a/honeybee_grasshopper_ph/src/HBPH - Phius MF Res Calculator.py +++ b/honeybee_grasshopper_ph/src/HBPH - Phius MF Res Calculator.py @@ -118,7 +118,7 @@ reload(gh_io) from honeybee_energy_ph.load import phius_mf reload(phius_mf) - from honeybee_ph_rhino.gh_compo_io.program import phius_MF_calc as gh_compo_io + from honeybee_ph_rhino.gh_compo_io.program._deprecated_ import phius_MF_calc as gh_compo_io reload(gh_compo_io) diff --git a/honeybee_grasshopper_ph/user_objects/HBPH - Get Phius Multi-Family Load Data.ghuser b/honeybee_grasshopper_ph/user_objects/HBPH - Get Phius Multi-Family Load Data.ghuser new file mode 100644 index 0000000000000000000000000000000000000000..ef87bc6bdeb302d6dda7d08f3ccab861d9922574 GIT binary patch literal 3535 zcmV;=4KVUtS7%TYY!VJNArukmQbGVhx-_Xu?*XKVp-2Le1du=|f=HDRiXc^*^e(+f z6X}8|A}Z3Q2#63NQ9gP*_-?+to7~?wf1Y_4Z0&=>nIYX!&c3H-0tWnBXtfYN zC_|m|6x~@^Zw=Hmg7TRZ1G{7ob=N~c+6Z5iD;5{{4~E7-OVZqcUI*pljKg^OVz8e7 zRG?C4;&PThw_r)IE(~IX@bp9A0wJc9SZvFG@9IsibmWvHWRWxyD3ZHMNu<~$k6 zluLQ-mhx@mg~G-99(wLrNekn8C*3${8vf!7>}d!2q84uOdMI@<`YWrI`FhC(~+yze4rF75OlLvnJH+uRvre`V-o(?O1n3G*Pm1)^Jo!^}&2xzcI1u)eI zDNVxZzSicy;9184GwkDoEnRAkAd^M}K~5H`=uHm9N-JVKC=TU4 z49Bk}A=*%Tx-!8YiMhMqXihQ#^PXzYBW5!o*M$)>6z7IJ@68I^K`rjhic0SQXo0Xb3 zRo)fx9`s=_yENYry)t-^0tiwTtEwIuJ%)%|&8aai^|1Exds3RE?5aCxOyMoS!>o0V zJYldT{0)^;6B`F*J<)l2BzL?thnEarxQYZH2}XutQXf3k@*rw2kKQA{3hHJNsFT^( zS;+mFUF5{@7a-JS;iNHfE^M>5bFl3)el?z&F4}G_n2`_Gcf+4cf=dg1`mh^13fA?s zj<>ZGQkr*yhCcn#8AA~a3edq__n`w`w6J1hV`rBNvn(C>^c zg;UAt2RoW`aCGyxa&7LZEnDS6(G3{q&)eoprxD$h&0)dKQGbilPX zX6VAEU&5$A_*Q^-zctzpbNH|veX+?&@I=XU5Z);c=dC}kUy>qkMo(zMj5ULDul58U zGR!93nV`*uA;>>Zp`%7zkH}eJ5A_*@OuU__0_I<=AT8xb+9a0koV~7W#Wkh-m(}fV z*?1k#U5gNYqukLF|Lzb!HUE0x07q~8JnD(WvOV3-R@s7yw0&XfrqSYdl5qBT5TReH zaz4yY&I7i+LkC#x& z;F?eg`P>`_PZKZyN(fVPEg-u0X44Ot^dA8uyD9191th5o^lE!+9I(IZC4yJN7p4^x zyLI0nm^s8m%9j2tv)!lalap&uEQD1~sd}_gvxxSCdD2LtvD6m>jbo&me5@3ibKX+Y z^@{G^3ItZDzCterRHlX$9fVrSE%J#l%xfKvgeN@Hn37IM9o;OSn=` zf+htP!&_3Q_3|kiI32M)O7{3=6@B(dyYSaJBWS~YV@SB-^_~#_MK#UNpo?D^T4}YM zPe!-DoC3ghZd2qRl+5QeV5n=VQ={b+!C>g=fFjy5GuE!YY?E3Ll!w zLr~^n)TW60sDF4*#6Zj303r#|NBKg`(HK7;2+YsJ7bB^MxR3D&gqUCvE)X4rF9KwW zad!V-;Klzz=>6S7`(J)OCqoGk0MK;X;mPIOY&-W-K5RKHLlP4+)p=K2myEq2q+cVs| zDrr!zL#Y!PsgVXZ7qa3ry1Ou|%2)e(XF4!ipSV4|zdzD8uk5q=vSB#7(JCaO{3z55 zMok$GBXh-B#urP@q*>4i&9`EWGPSO{B|XecT(fs$e`7x4TN#BH8`HG?!cZBD%edx@ zHz_NB5Be-K7;Tx_1AqO?CN4G0gHaH1u?((%2ZWLZ5V{IIWr{y%F)Fg_lbxIif^bcH z5z+Ll9f;D=O;;~p+tt~7ji1n87uxL-!d%C$t8o8@EREHu>RGRfmPd^acV-?hDnL9i z3SJrooN{1B;CRK6=Ye$J*FrWQ5;m0VTo#t?O?lYD4ot@?mB$kQ28qY#ht8#rIkTge$B3XOV?t z;IidfHr7a=)Mr_dOXhTXYMj8!-Jx+(t*cMcA_u}smtn05N{y~na!0+cyE^$fZW%yB z(WV>MWwslc-5;C4lV7P~{GxtlrOPS=KafTV!lBhewrp?<9;8JT&7oaX>I>7VG=o_V zeRl8od_lCV0`M`Kdrmh2*S;v5>Id^Q5%K;YLlmVVqxp7n4N*6|DSsUjVr6>mT_Pl+jCKYqEM|4%6-&6rh91OAk?F#3No8le z5uZQ(##h79kmUh%c!t-}6}TKR<~iq0>R55){+%bWNQ3q7%=klZ{GiR#Td;ia+>Nc0 z-MoV@HSSZZC;p4$-WzyqLJ%8zYeo#BzMr-9{Y$7id~f^aQ}ykEr#G%2kV>*)j|-xD zu5P?sC4{Ibo-WPs51amaP1=P$h8;6R9ddbWy4IEC^}MB}<#SKAnsQ?t*F(NA;&d0r z*$vCD?L&F0CVU%&zRgv~G%s09(1vV?4Dz4u6GLquqJI9VZT=FoI(^_>rEH?2QltA) z$Qjv~`7R;CL`SO3hvpIuFS~h*A-J>;ej-Stv|8C;>+|!y4bF4-W&=m4TvXSN^drQq z~?$62PsT}7`Hj>nQx5Tyo`p(-4KJ2gbVsgZrjcC%0cY%x0k8c-z zYWpx9FV8}>dHR$Mv5;b2*sc}Z-zmkU=EcvREs9;5!_NC-EO_g*W#yQd#K_6?+BOQ+|tPo8WEOc~e2_-Y26`GcaDi^G!YfO|b3d z^}cD-+MH3aKZCs@;zAmMTvMf!7htU#hLv;-5qL=)8q5pnj86+vz23`|+&;w+*_fiP z{C;QA!;*i*zjoC_bJtcow@^H=&8*|-t?_#T|EoWv;#f7G?IKch()GE9_YdmEOL;&J zzjJ+qJ1#i%J&L%)f5py+6c7FDQ8m`|ds; zbtdWF-2S(z`H_*(lalMJcaM6uFW+~Wo8NYt?pdO}M^!-X$z|RAslE72(|m8k{($4~ zrmxp#5Fx;6_2{E#%g4?UszW%deXIjXcP85beR%WiuW)`((Odc<|NmYC%Upvzg21pYD35;u J009600|2~X+0p<2 literal 0 HcmV?d00001 diff --git a/honeybee_ph_rhino/_component_info_.py b/honeybee_ph_rhino/_component_info_.py index ba4645c..916b97e 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.8.01" +RELEASE_VERSION = "Honeybee-PH v1.8.02" CATEGORY = "HB-PH" SUB_CATEGORIES = { 0: "00 | Utils", @@ -316,7 +316,7 @@ "Category": CATEGORY, "SubCategory": 1, }, - "HBPH - Create Program - Single Family Home": { + "HBPH - Set Residential Program": { "NickName": "Create SFH Program", "Message": RELEASE_VERSION, "Category": CATEGORY, @@ -334,6 +334,12 @@ "Category": CATEGORY, "SubCategory": 1, }, + "HBPH - Get Phius Multi-Family Load Data": { + "NickName": "Get Phius MF Data", + "Message": RELEASE_VERSION, + "Category": CATEGORY, + "SubCategory": 1, + }, # -- Windows "HBPH - Create PH Window Frame Element": { "NickName": "Create Frame Element", diff --git a/honeybee_ph_rhino/gh_compo_io/program/__init__.py b/honeybee_ph_rhino/gh_compo_io/program/__init__.py index f52ff08..94ff6d5 100644 --- a/honeybee_ph_rhino/gh_compo_io/program/__init__.py +++ b/honeybee_ph_rhino/gh_compo_io/program/__init__.py @@ -1,11 +1,12 @@ -from honeybee_ph_rhino.gh_compo_io.program.add_elec_equip import GHCompo_AddElecEquip from honeybee_ph_rhino.gh_compo_io.program.add_process_equip import GHCompo_AddProcessEquip from honeybee_ph_rhino.gh_compo_io.program.create_elec_equip import GHCompo_CreateElecEquip from honeybee_ph_rhino.gh_compo_io.program.create_operating_period import GHCompo_CreateOccPeriod -from honeybee_ph_rhino.gh_compo_io.program.create_single_family import GHCompo_CreatePHProgramSingleFamilyHome from honeybee_ph_rhino.gh_compo_io.program.create_vent_schd import GHCompo_CreateVentSched from honeybee_ph_rhino.gh_compo_io.program.find_phius_program import GHCompo_FindPhiusProgram from honeybee_ph_rhino.gh_compo_io.program.get_res_occupancy import GHCompo_GetResOccupancy -from honeybee_ph_rhino.gh_compo_io.program.phius_MF_calc import GHCompo_CalcPhiusMFLoads +from honeybee_ph_rhino.gh_compo_io.program.set_res_program import GHCompo_CreatePHProgramSingleFamilyHome from honeybee_ph_rhino.gh_compo_io.program.set_dwelling import GHCompo_SetDwelling from honeybee_ph_rhino.gh_compo_io.program.set_res_occupancy import GHCompo_SetResOccupancy +# -- +from honeybee_ph_rhino.gh_compo_io.program._deprecated_.add_elec_equip import GHCompo_AddElecEquip +from honeybee_ph_rhino.gh_compo_io.program._deprecated_.phius_MF_calc import GHCompo_CalcPhiusMFLoads diff --git a/honeybee_ph_rhino/gh_compo_io/program/_deprecated_/__init__.py b/honeybee_ph_rhino/gh_compo_io/program/_deprecated_/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/honeybee_ph_rhino/gh_compo_io/program/add_elec_equip.py b/honeybee_ph_rhino/gh_compo_io/program/_deprecated_/add_elec_equip.py similarity index 100% rename from honeybee_ph_rhino/gh_compo_io/program/add_elec_equip.py rename to honeybee_ph_rhino/gh_compo_io/program/_deprecated_/add_elec_equip.py diff --git a/honeybee_ph_rhino/gh_compo_io/program/phius_MF_calc.py b/honeybee_ph_rhino/gh_compo_io/program/_deprecated_/phius_MF_calc.py similarity index 91% rename from honeybee_ph_rhino/gh_compo_io/program/phius_MF_calc.py rename to honeybee_ph_rhino/gh_compo_io/program/_deprecated_/phius_MF_calc.py index af8705d..8a60f1e 100644 --- a/honeybee_ph_rhino/gh_compo_io/program/phius_MF_calc.py +++ b/honeybee_ph_rhino/gh_compo_io/program/_deprecated_/phius_MF_calc.py @@ -3,6 +3,7 @@ """GHCompo Interface: HBPH - Phius MF Res Calculator.""" +# TODO: REMOVE THIS MODULE... now just 'get' the data... from collections import defaultdict @@ -33,7 +34,7 @@ raise ImportError("\nFailed to import honeybee_energy_ph:\n\t{}".format(e)) try: - from honeybee_ph_rhino import gh_io + from ph_gh_component_io import gh_io except ImportError as e: raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e)) @@ -104,6 +105,8 @@ def check_inputs(_hb_rooms, _IGH): ) print(msg) _IGH.warning(msg) + else: + print("{} Stories found".format(len({rm.story for rm in _hb_rooms}))) # -- Check that al the rooms have "PH-Spaces" rm_with_error = spaces_error(_hb_rooms) @@ -129,7 +132,7 @@ def check_inputs(_hb_rooms, _IGH): def sort_rooms_by_story(_hb_rooms): - # type (list[room.Room]) -> list[list[room.Room]] + # type: (list[room.Room]) -> list[list[room.Room]] """Returns lists of the rooms, organized by their Honeybee 'story'. Arguments: @@ -147,6 +150,14 @@ def sort_rooms_by_story(_hb_rooms): return [d[story_key] for story_key in sorted(d.keys())] +def room_is_dwelling(_hb_room): + # type: (room.Room) -> bool + """Return True if the Honeybee-Room is a 'dwelling' (residential)?""" + hb_room_prop_e = getattr(_hb_room.properties, "energy") # type: RoomEnergyProperties + hb_room_prop_e_prop_ph = getattr(hb_room_prop_e.people.properties, "ph") # type: PeoplePhProperties + return hb_room_prop_e_prop_ph.is_residential + + # ----------------------------------------------------------------------------- # -- Component Interface @@ -173,38 +184,39 @@ def __init__( self.include_garage = bool(_include_garage) self.hb_rooms = _hb_rooms + msg = ( + "Deprecation Warning: This component should not be used any longer. Please use the new" + "'HBPH - Set Residential Program' component instead." + ) + print(msg) + self.IGH.error(msg) + raise Exception(msg) + + @property def num_dwelling_units(self): # type: () -> int - return sum( - rm.properties.energy.people.properties.ph.number_dwelling_units - for rm in self.hb_rooms - if self._room_is_dwelling(rm) - ) + """Return the total number of dwellings in the list of HB-Rooms.""" + ph_dwelling_objs = {r.properties.energy.people.properties.ph.dwellings for r in self.hb_rooms} # type: ignore + print("Found {} unique PH-Dwelling objects".format(len(ph_dwelling_objs))) + return sum(d.num_dwellings for d in ph_dwelling_objs) @property def num_of_stories(self): # type: () -> int return len({rm.story for rm in self.hb_rooms}) - def _room_is_dwelling(self, _hb_room): - # type: (room.Room) -> bool - """Return True if the Honeybee-Room is a 'dwelling' (residential)?""" - hb_room_prop_e = _hb_room.properties.energy # type: RoomEnergyProperties - hb_room_prop_e_prop_ph = hb_room_prop_e.people.properties.ph # type: PeoplePhProperties - return hb_room_prop_e_prop_ph.is_residential - def calc_res_electric_consumption(self, _hb_res_rooms): # type: (List[room.Room]) -> Tuple[List[str], float, float, float, float, List[str]] - # --------------------------------------------------------------------------- + # ------------------------------------------------------------------------------- # -- Determine the Input Res Honeybee Room attributes by story rooms_by_story = sort_rooms_by_story(_hb_res_rooms) phius_stories = [phius_mf.PhiusResidentialStory(room_list) for room_list in rooms_by_story] phius_stories = sorted(phius_stories, reverse=True) - # --------------------------------------------------------------------------- + # ------------------------------------------------------------------------------- # -- Calculate the total Res. Elec. Energy Consumption mel_by_story = [story.mel for story in phius_stories] lighting_int_by_story = [story.lighting_int for story in phius_stories] @@ -216,6 +228,7 @@ def calc_res_electric_consumption(self, _hb_res_rooms): total_res_ext_lighting = sum(lighting_ext_by_story) total_res_garage_lighting = sum(lighting_garage_by_story) + # ------------------------------------------------------------------------------- # -- Collect for output preview res_data_by_story_ = [ ",".join( @@ -400,8 +413,8 @@ def run(self): if self.hb_rooms: # --------------------------------------------------------------------------- # -- Break out the Res from the non-Res HB-Rooms - hb_res_rooms_ = [rm for rm in self.hb_rooms if self._room_is_dwelling(rm)] - hb_nonres_rooms_ = [rm for rm in self.hb_rooms if not self._room_is_dwelling(rm)] + hb_res_rooms_ = [rm for rm in self.hb_rooms if room_is_dwelling(rm)] + hb_nonres_rooms_ = [rm for rm in self.hb_rooms if not room_is_dwelling(rm)] if not hb_res_rooms_: msg = "Warning: No Residential HB-Rooms found?" diff --git a/honeybee_ph_rhino/gh_compo_io/program/get_phius_mf_data.py b/honeybee_ph_rhino/gh_compo_io/program/get_phius_mf_data.py new file mode 100644 index 0000000..47484a6 --- /dev/null +++ b/honeybee_ph_rhino/gh_compo_io/program/get_phius_mf_data.py @@ -0,0 +1,267 @@ +# -*- coding: utf-8 -*- +# -*- Python Version: 2.7 -*- + +"""GHCompo Interface: HBPH - Get Phius Multi-Family Load Data.""" + +from collections import defaultdict + +try: + from typing import Any, Type +except ImportError: + pass #IronPython 2.7 + +try: + from honeybee.room import Room +except ImportError as e: + raise ImportError("\nFailed to import honeybee:\n\t{}".format(e)) + +try: + from honeybee_energy.properties.room import RoomEnergyProperties +except ImportError as e: + raise ImportError("\nFailed to import honeybee:\n\t{}".format(e)) + +try: + from honeybee_ph.properties.room import RoomPhProperties +except ImportError as e: + raise ImportError("\nFailed to import honeybee:\n\t{}".format(e)) + +try: + from honeybee_energy_ph.load import ph_equipment, phius_mf + from honeybee_energy_ph.properties.load.people import PeoplePhProperties +except ImportError as e: + raise ImportError("\nFailed to import honeybee_energy_ph:\n\t{}".format(e)) + +try: + from ph_gh_component_io import gh_io +except ImportError as e: + raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e)) + + +# ----------------------------------------------------------------------------- + + +def stories_error(_hb_rooms): + # type (list[Room]) -> bool + """Returns False if HBE-Stories are less than 2.""" + try: + stories = {rm.story for rm in _hb_rooms} + if len(stories) < 2: + return True + else: + return False + except AttributeError as e: + return True + + +def spaces_error(_hb_rooms): + # type: (list[Room]) -> Room | None + """Returns any Honeybee Room which does not have PH-Spaces.""" + for rm in _hb_rooms: + if len(rm.properties.ph.spaces) == 0: # type: ignore + return rm + return None + + +def people_error(_hb_rooms): + # type: (list[Room]) -> Room | None + """Returns any room that does not have the 'People' HBE property applied.""" + for rm in _hb_rooms: + if rm.properties.energy.people is None: # type: ignore + return rm + return None + + +def check_res_room_inputs(_hb_rooms, _IGH): + # type: (list[Room], gh_io.IGH) -> None + """Validate the input Honeybee-Rooms.""" + if not _hb_rooms: + msg = "Warning: No Residential HB-Rooms found?" + print(msg) + _IGH.warning(msg) + + # -- Check the HBE-Stories + if stories_error(_hb_rooms): + msg = ( + "Warning: It appears that there is only 1 Honeybee-Story assigned to the " + "Honeybee-Rooms? If that is true, ignore this warning. Otherwise, check that you " + "have used the Honeybee 'Set Story' component to properly assign story ID numbers " + "to each of the rooms in the project. This calculator sorts the rooms by story, " + "so it is important to set the story attribute before using this component." + ) + print(msg) + _IGH.warning(msg) + else: + print("{} Stories found".format(len({rm.story for rm in _hb_rooms}))) + + # -- Check that al the rooms have "PH-Spaces" + rm_with_error = spaces_error(_hb_rooms) + if rm_with_error: + msg = ( + "Error: There are no PH-Spaces assigned to room: '{}'. Please be sure to assign the " + "PH-Spaces before using this component. Use the HB-PH 'Create Spaces' and 'Add Spaces' " + "components in order to add Spaces to all the Honeybee-Rooms.".format(rm_with_error.display_name) + ) + print(msg) + _IGH.error(msg) + + # -- Check that all the rooms have a "People" + rm = people_error(_hb_rooms) + if rm_with_error: + msg = ( + "Error: There is no 'People' property assigned to room: '{}'. Be sure to use " + "the HB-PH 'Set Occupancy' component to assign the number of bedrooms per-HB-Room " + "before using this calculator.".format(rm_with_error.display_name) + ) + _IGH.error(msg) + print(msg) + + +def room_is_dwelling(_hb_room): + # type: (Room) -> bool + """Return True if the Honeybee-Room is a 'dwelling' (residential)?""" + hb_room_prop_e = getattr(_hb_room.properties, "energy") # type: RoomEnergyProperties + hb_room_prop_e_prop_ph = getattr(hb_room_prop_e.people.properties, "ph") # type: PeoplePhProperties + return hb_room_prop_e_prop_ph.is_residential + + +def sort_rooms_by_story(_hb_rooms): + # type: (list[Room]) -> list[list[Room]] + """Returns lists of the rooms, grouped by their Honeybee 'story'.""" + + d = defaultdict(list) + for rm in _hb_rooms: + d[rm.story].append(rm) + return [d[story_key] for story_key in sorted(d.keys())] + + + +# ----------------------------------------------------------------------------- + + +def get_residential_room_data(_hb_rooms, _area_unit): + # type: (list[Room], str) -> tuple[list, list] + """Calculate the annual electric consumption for the residential rooms.""" + + # ------------------------------------------------------------------------------- + # -- Determine the Input Res Honeybee Room attributes by story + rooms_by_story = sort_rooms_by_story(_hb_rooms) + phius_stories = [phius_mf.PhiusResidentialStory(room_list, _area_unit) for room_list in rooms_by_story] + phius_stories = sorted(phius_stories, reverse=True) + + # ------------------------------------------------------------------------------- + # -- Collect for output preview + res_data_by_story_ = [ + ",".join( + [ + str(story.story_number), + str(story.total_floor_area_ft2), + str(story.total_number_dwellings), + str(story.total_number_bedrooms), + ] + ) + for story in phius_stories + ] + res_totals_ = [ + ",".join( + [ + str(story.design_occupancy), + str(story.mel), + str(story.lighting_int), + str(story.lighting_ext), + str(story.lighting_garage), + ] + ) + for story in phius_stories + ] + res_totals_.insert( + 0, + str( + "FLOOR-Design Occupancy, FLOOR-Televisions + Mis. Elec. Loads (kWh/yr), FLOOR-Interior Lighting (kWh/yr), FLOOR-Exterior Lighting (kWh/yr), Garage Lighting (kWh/yr)" + ), + ) + + return ( + res_data_by_story_, + res_totals_, + ) + + +def get_non_residential_room_data(_hb_rooms): + # type: (list[Room]) -> tuple[list, list, list] + """Calculate the annual electric consumption for the non-residential rooms.""" + + prog_collection = phius_mf.PhiusNonResProgramCollection() + + # -- Build a new Phius Non-Res-Space for each PH-Space found + non_res_spaces = [] # type: list[phius_mf.PhiusNonResRoom] + for hb_room in _hb_rooms: + room_prop_ph = getattr(hb_room.properties, "ph") # type: RoomPhProperties + for space in room_prop_ph.spaces: + new_nonres_space = phius_mf.PhiusNonResRoom.from_ph_space(space) + prog_collection.add_program(new_nonres_space.program_type) + non_res_spaces.append(new_nonres_space) + + # -- Collect the program data for preview / output + non_res_program_data_ = prog_collection.to_phius_mf_workbook() + + non_res_room_data_ = [sp.to_phius_mf_workbook() for sp in sorted(non_res_spaces, key=lambda x: x.name)] + non_res_totals_ = [sp.to_phius_mf_workbook_results() for sp in sorted(non_res_spaces, key=lambda x: x.name)] + non_res_totals_.insert( + 0, + str( + "Lighting Power Density (W/sf), Usage (days/year), Daily Usage (hrs/day), MELCOMM (kWh/yr.sf), LIGHTCOMM (kWh/yr), MELCOMM (kWh/yr)" + ), + ) + + return ( + non_res_program_data_, + non_res_room_data_, + non_res_totals_, + ) + + +# ----------------------------------------------------------------------------- +# -- Component Interface + + +class GHCompo_GetPhiusMFLoadData(object): + def __init__(self, _IGH, _hb_rooms, *args, **kwargs): + # type: (gh_io.IGH, list[Room], *Any, **Any) -> None + self.IGH=_IGH + self.hb_rooms=_hb_rooms + + def run(self): + # type: () -> tuple[list, list, list, list, list] + if not self.hb_rooms: + return [], [], [], [], [] + + # --------------------------------------------------------------------- + # -- Break out the Res, from the Non-Res. HB-Rooms + hb_res_rooms_ = [rm for rm in self.hb_rooms if room_is_dwelling(rm)] + hb_nonres_rooms_ = [rm for rm in self.hb_rooms if not room_is_dwelling(rm)] + + # -- Check the inputs for errors, display warnings + check_res_room_inputs(hb_res_rooms_, self.IGH) + + # -- Calculate the annual electric consumption for the rooms + # --------------------------------------------------------------------- + ( + res_data_by_story_, + res_totals_, + ) = get_residential_room_data(hb_res_rooms_, self.IGH.get_rhino_areas_unit_name()) + + # --------------------------------------------------------------------- + ( + non_res_program_data_, + non_res_room_data_, + non_res_totals_, + ) = get_non_residential_room_data(hb_nonres_rooms_) + + # --------------------------------------------------------------------- + return ( + res_data_by_story_, + res_totals_, + non_res_program_data_, + non_res_room_data_, + non_res_totals_, + ) diff --git a/honeybee_ph_rhino/gh_compo_io/program/get_res_occupancy.py b/honeybee_ph_rhino/gh_compo_io/program/get_res_occupancy.py index 02dcec6..8d9f876 100644 --- a/honeybee_ph_rhino/gh_compo_io/program/get_res_occupancy.py +++ b/honeybee_ph_rhino/gh_compo_io/program/get_res_occupancy.py @@ -6,19 +6,17 @@ from statistics import mean try: - from honeybee.properties import RoomProperties from honeybee.room import Room except ImportError as e: raise ImportError("\nFailed to import honeybee:\n\t{}".format(e)) try: - from honeybee_energy.load import people from honeybee_energy.properties.room import RoomEnergyProperties except ImportError as e: raise ImportError("\nFailed to import honeybee_energy:\n\t{}".format(e)) try: - from honeybee_energy_ph.properties.load.people import PeoplePhProperties, PhDwellings + from honeybee_energy_ph.properties.load.people import PeoplePhProperties except ImportError as e: raise ImportError("\nFailed to import honeybee_energy_ph:\n\t{}".format(e)) @@ -63,10 +61,9 @@ def get_area_value_in_unit(_IGH, _input, _target_unit): def get_num_of_dwellings(_hb_rooms): # type: (list[Room]) -> int """Return the total number of dwellings in the list of HB-Rooms.""" - zones = set() - for hb_room in _hb_rooms: - zones.add(hb_room.zone) - return len(zones) + ph_dwelling_objs = {r.properties.energy.people.properties.ph.dwellings for r in _hb_rooms} # type: ignore + print("Found {} unique PH-Dwelling objects".format(len(ph_dwelling_objs))) + return sum(d.num_dwellings for d in ph_dwelling_objs) class GHCompo_GetResOccupancy(object): diff --git a/honeybee_ph_rhino/gh_compo_io/program/set_dwelling.py b/honeybee_ph_rhino/gh_compo_io/program/set_dwelling.py index ed4d728..0dd4873 100644 --- a/honeybee_ph_rhino/gh_compo_io/program/set_dwelling.py +++ b/honeybee_ph_rhino/gh_compo_io/program/set_dwelling.py @@ -3,6 +3,8 @@ """GHCompo Interface: HBPH - Set Dwelling.""" +import os + try: from Grasshopper import DataTree # type: ignore from Grasshopper.Kernel.Data import GH_Path # type: ignore @@ -11,21 +13,65 @@ pass # IronPython 2.7 try: + from honeybee.config import folders from honeybee.room import Room from honeybee.typing import clean_and_id_ep_string except ImportError as e: raise ImportError("\nFailed to import honeybee:\n\t{}".format(e)) +try: + from honeybee_energy.load.people import People + from honeybee_energy.schedule.ruleset import ScheduleRuleset + from honeybee_energy.properties.room import RoomEnergyProperties +except ImportError as e: + raise ImportError("\nFailed to import honeybee_energy:\n\t{}".format(e)) + +try: + from honeybee_energy_ph.properties.load.people import PhDwellings +except ImportError as e: + raise ImportError("\nFailed to import honeybee_energy_ph:\n\t{}".format(e)) + +try: + from honeybee_energy_ph.properties.load.people import PeoplePhProperties +except ImportError as e: + raise ImportError("\nFailed to import honeybee_energy_ph:\n\t{}".format(e)) + +try: + from honeybee_ph_standards.schedules._load_schedules import load_schedules_from_json_file +except ImportError as e: + raise ImportError("\nFailed to import honeybee_ph_standards:\n\t{}".format(e)) + try: from ph_gh_component_io import gh_io except ImportError as e: raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e)) + # ----------------------------------------------------------------------------- # -- Component Interface + +def get_new_people(_hbe_people, _occ_schd, _act_schd): + # type: (People | None, ScheduleRuleset, ScheduleRuleset) -> People + """Get a new HBE-People object.""" + if _hbe_people is None: + return People( + clean_and_id_ep_string("People"), + 0, + _occ_schd, + _act_schd, + ) + else: + return _hbe_people.duplicate() # type: ignore + + class GHCompo_SetDwelling(object): + file_pth = os.path.join( + folders.python_package_path, "honeybee_ph_standards", "schedules", "hbph_sfh_occupancy.json" + ) + default_occ_schd = load_schedules_from_json_file(file_pth)["hbph_sfh_Occupant_Presence"] + default_activity_schd = load_schedules_from_json_file(file_pth)["hbph_sfh_Occupant_Activity"] def __init__(self, _IGH, _hb_rooms): # type: (gh_io.IGH, DataTree[Room]) -> None @@ -36,11 +82,27 @@ def run(self): # type: () -> DataTree[Room] hb_rooms_ = DataTree[Object]() for i, branch in enumerate(self.hb_rooms.Branches): - temp_ = [] + + # -- Create a new Dwelling Object to be applied to all the Rooms dwelling_name = clean_and_id_ep_string("HBPH_DWELLING") + ph_dwellings_obj = PhDwellings(_num_dwellings=1) + ph_dwellings_obj.identifier = dwelling_name + + # -- Set the Dwelling information on all the Rooms + dup_rooms_ = [] for hb_room in branch: - new_room = hb_room.duplicate() - new_room.zone = dwelling_name - temp_.append(new_room) - hb_rooms_.AddRange(temp_, GH_Path(i)) + print("Setting room: '{}' to residential dwelling: '{}'".format(hb_room.display_name, dwelling_name)) + dup_room = hb_room.duplicate() # type: Room + dup_room.zone = dwelling_name + dup_room_prop_e = getattr(dup_room.properties, "energy") # type: RoomEnergyProperties + + # -- Build the new People and add to the HB-Room + # -- Note: be sure to duplicate the People before changing the dwelling. + dup_ppl = get_new_people(dup_room_prop_e.people, self.default_occ_schd, self.default_activity_schd) + ppl_prop_ph = getattr(dup_ppl.properties, "ph") # type: PeoplePhProperties + ppl_prop_ph.dwellings = ph_dwellings_obj + dup_room_prop_e.people = dup_ppl + + dup_rooms_.append(dup_room) + hb_rooms_.AddRange(dup_rooms_, GH_Path(i)) return hb_rooms_ diff --git a/honeybee_ph_rhino/gh_compo_io/program/set_res_occupancy.py b/honeybee_ph_rhino/gh_compo_io/program/set_res_occupancy.py index 50348a4..b501964 100644 --- a/honeybee_ph_rhino/gh_compo_io/program/set_res_occupancy.py +++ b/honeybee_ph_rhino/gh_compo_io/program/set_res_occupancy.py @@ -68,7 +68,9 @@ def _group_rooms_by_dwellings(_hb_rooms): """Group the HB-Rooms by their 'dwelling'.""" room_groups = defaultdict(list) for hb_room in _hb_rooms: - room_groups[hb_room.zone].append(hb_room) + rm_prop_e = getattr(hb_room.properties, "energy") # type: RoomEnergyProperties + ppl_prop_ph = getattr(rm_prop_e.people.properties, "ph") # type: PeoplePhProperties + room_groups[ppl_prop_ph.dwellings.identifier].append(hb_room) return [v for v in room_groups.values()] diff --git a/honeybee_ph_rhino/gh_compo_io/program/create_single_family.py b/honeybee_ph_rhino/gh_compo_io/program/set_res_program.py similarity index 97% rename from honeybee_ph_rhino/gh_compo_io/program/create_single_family.py rename to honeybee_ph_rhino/gh_compo_io/program/set_res_program.py index 9ee50bf..36fc8c0 100644 --- a/honeybee_ph_rhino/gh_compo_io/program/create_single_family.py +++ b/honeybee_ph_rhino/gh_compo_io/program/set_res_program.py @@ -1,12 +1,11 @@ # -*- coding: utf-8 -*- # -*- Python Version: 2.7 -*- -"""GHCompo Interface: HBPH - Create Program: Single Family Home.""" +"""GHCompo Interface: HBPH - Set Residential Program.""" from collections import defaultdict import os from statistics import mean -from functools import partial try: from System import Object # type: ignore @@ -39,16 +38,6 @@ except ImportError as e: raise ImportError("\nFailed to import honeybee_energy:\n\t{}".format(e)) -try: - from honeybee_ph.properties.room import RoomPhProperties -except ImportError as e: - raise ImportError("\nFailed to import honeybee_ph:\n\t{}".format(e)) - -try: - from honeybee_ph_standards.schedules._load_schedules import load_schedules_from_json_file -except ImportError as e: - raise ImportError("\nFailed to import honeybee_ph_standards:\n\t{}".format(e)) - try: from honeybee_energy_ph.load import ph_equipment from honeybee_energy_ph.properties.load.process import ProcessPhProperties @@ -57,11 +46,6 @@ except ImportError as e: raise ImportError("\nFailed to import honeybee_energy_ph:\n\t{}".format(e)) -try: - from ph_gh_component_io import gh_io -except ImportError as e: - raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e)) - try: from ph_units.converter import convert from ph_units.parser import parse_input @@ -73,6 +57,11 @@ except ImportError as e: raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e)) +try: + from ph_gh_component_io import gh_io +except ImportError as e: + raise ImportError("\nFailed to import honeybee_ph_rhino:\n\t{}".format(e)) + def get_total_spaces_area_rh_doc_units(_hb_rooms): # type: (list[Room]) -> float @@ -406,7 +395,6 @@ def get_net_floor_area(self, _hb_rooms): net_floor_area_in_rh_doc_units = get_total_spaces_area_rh_doc_units(_hb_rooms) if not net_floor_area_in_rh_doc_units: raise ValueError("Failed to get net floor area of HB-Rooms?") - net_floor_area_m2 = get_area_value_in_unit(self.IGH, net_floor_area_in_rh_doc_units, "M2") net_floor_area_ft2 = get_area_value_in_unit(self.IGH, net_floor_area_in_rh_doc_units, "FT2") return net_floor_area_ft2