honeybee-energy 1.116.106__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- honeybee_energy/__init__.py +24 -0
- honeybee_energy/__main__.py +4 -0
- honeybee_energy/_extend_honeybee.py +145 -0
- honeybee_energy/altnumber.py +21 -0
- honeybee_energy/baseline/__init__.py +2 -0
- honeybee_energy/baseline/create.py +608 -0
- honeybee_energy/baseline/data/__init__.py +1 -0
- honeybee_energy/baseline/data/constructions.csv +64 -0
- honeybee_energy/baseline/data/fen_ratios.csv +15 -0
- honeybee_energy/baseline/data/lpd_building.csv +21 -0
- honeybee_energy/baseline/data/pci_2016.csv +22 -0
- honeybee_energy/baseline/data/pci_2019.csv +22 -0
- honeybee_energy/baseline/data/pci_2022.csv +22 -0
- honeybee_energy/baseline/data/shw.csv +21 -0
- honeybee_energy/baseline/pci.py +512 -0
- honeybee_energy/baseline/result.py +371 -0
- honeybee_energy/boundarycondition.py +128 -0
- honeybee_energy/cli/__init__.py +69 -0
- honeybee_energy/cli/baseline.py +475 -0
- honeybee_energy/cli/edit.py +327 -0
- honeybee_energy/cli/lib.py +1154 -0
- honeybee_energy/cli/result.py +810 -0
- honeybee_energy/cli/setconfig.py +124 -0
- honeybee_energy/cli/settings.py +569 -0
- honeybee_energy/cli/simulate.py +380 -0
- honeybee_energy/cli/translate.py +1714 -0
- honeybee_energy/cli/validate.py +224 -0
- honeybee_energy/config.json +11 -0
- honeybee_energy/config.py +842 -0
- honeybee_energy/construction/__init__.py +1 -0
- honeybee_energy/construction/_base.py +374 -0
- honeybee_energy/construction/air.py +325 -0
- honeybee_energy/construction/dictutil.py +89 -0
- honeybee_energy/construction/dynamic.py +607 -0
- honeybee_energy/construction/opaque.py +460 -0
- honeybee_energy/construction/shade.py +319 -0
- honeybee_energy/construction/window.py +1096 -0
- honeybee_energy/construction/windowshade.py +847 -0
- honeybee_energy/constructionset.py +1655 -0
- honeybee_energy/dictutil.py +56 -0
- honeybee_energy/generator/__init__.py +5 -0
- honeybee_energy/generator/loadcenter.py +204 -0
- honeybee_energy/generator/pv.py +535 -0
- honeybee_energy/hvac/__init__.py +21 -0
- honeybee_energy/hvac/_base.py +124 -0
- honeybee_energy/hvac/_template.py +270 -0
- honeybee_energy/hvac/allair/__init__.py +22 -0
- honeybee_energy/hvac/allair/_base.py +349 -0
- honeybee_energy/hvac/allair/furnace.py +168 -0
- honeybee_energy/hvac/allair/psz.py +131 -0
- honeybee_energy/hvac/allair/ptac.py +163 -0
- honeybee_energy/hvac/allair/pvav.py +109 -0
- honeybee_energy/hvac/allair/vav.py +128 -0
- honeybee_energy/hvac/detailed.py +337 -0
- honeybee_energy/hvac/doas/__init__.py +28 -0
- honeybee_energy/hvac/doas/_base.py +345 -0
- honeybee_energy/hvac/doas/fcu.py +127 -0
- honeybee_energy/hvac/doas/radiant.py +329 -0
- honeybee_energy/hvac/doas/vrf.py +81 -0
- honeybee_energy/hvac/doas/wshp.py +91 -0
- honeybee_energy/hvac/heatcool/__init__.py +23 -0
- honeybee_energy/hvac/heatcool/_base.py +177 -0
- honeybee_energy/hvac/heatcool/baseboard.py +61 -0
- honeybee_energy/hvac/heatcool/evapcool.py +72 -0
- honeybee_energy/hvac/heatcool/fcu.py +92 -0
- honeybee_energy/hvac/heatcool/gasunit.py +53 -0
- honeybee_energy/hvac/heatcool/radiant.py +269 -0
- honeybee_energy/hvac/heatcool/residential.py +77 -0
- honeybee_energy/hvac/heatcool/vrf.py +54 -0
- honeybee_energy/hvac/heatcool/windowac.py +70 -0
- honeybee_energy/hvac/heatcool/wshp.py +62 -0
- honeybee_energy/hvac/idealair.py +699 -0
- honeybee_energy/internalmass.py +310 -0
- honeybee_energy/lib/__init__.py +1 -0
- honeybee_energy/lib/_loadconstructions.py +194 -0
- honeybee_energy/lib/_loadconstructionsets.py +117 -0
- honeybee_energy/lib/_loadmaterials.py +83 -0
- honeybee_energy/lib/_loadprogramtypes.py +125 -0
- honeybee_energy/lib/_loadschedules.py +87 -0
- honeybee_energy/lib/_loadtypelimits.py +64 -0
- honeybee_energy/lib/constructions.py +207 -0
- honeybee_energy/lib/constructionsets.py +95 -0
- honeybee_energy/lib/materials.py +67 -0
- honeybee_energy/lib/programtypes.py +125 -0
- honeybee_energy/lib/schedules.py +61 -0
- honeybee_energy/lib/scheduletypelimits.py +31 -0
- honeybee_energy/load/__init__.py +1 -0
- honeybee_energy/load/_base.py +190 -0
- honeybee_energy/load/daylight.py +397 -0
- honeybee_energy/load/dictutil.py +47 -0
- honeybee_energy/load/equipment.py +771 -0
- honeybee_energy/load/hotwater.py +543 -0
- honeybee_energy/load/infiltration.py +460 -0
- honeybee_energy/load/lighting.py +480 -0
- honeybee_energy/load/people.py +497 -0
- honeybee_energy/load/process.py +472 -0
- honeybee_energy/load/setpoint.py +816 -0
- honeybee_energy/load/ventilation.py +550 -0
- honeybee_energy/material/__init__.py +1 -0
- honeybee_energy/material/_base.py +166 -0
- honeybee_energy/material/dictutil.py +59 -0
- honeybee_energy/material/frame.py +367 -0
- honeybee_energy/material/gas.py +1087 -0
- honeybee_energy/material/glazing.py +854 -0
- honeybee_energy/material/opaque.py +1351 -0
- honeybee_energy/material/shade.py +1360 -0
- honeybee_energy/measure.py +472 -0
- honeybee_energy/programtype.py +723 -0
- honeybee_energy/properties/__init__.py +1 -0
- honeybee_energy/properties/aperture.py +333 -0
- honeybee_energy/properties/door.py +342 -0
- honeybee_energy/properties/extension.py +244 -0
- honeybee_energy/properties/face.py +274 -0
- honeybee_energy/properties/model.py +2640 -0
- honeybee_energy/properties/room.py +1747 -0
- honeybee_energy/properties/shade.py +314 -0
- honeybee_energy/properties/shademesh.py +262 -0
- honeybee_energy/reader.py +48 -0
- honeybee_energy/result/__init__.py +1 -0
- honeybee_energy/result/colorobj.py +648 -0
- honeybee_energy/result/emissions.py +290 -0
- honeybee_energy/result/err.py +101 -0
- honeybee_energy/result/eui.py +100 -0
- honeybee_energy/result/generation.py +160 -0
- honeybee_energy/result/loadbalance.py +890 -0
- honeybee_energy/result/match.py +202 -0
- honeybee_energy/result/osw.py +90 -0
- honeybee_energy/result/rdd.py +59 -0
- honeybee_energy/result/zsz.py +190 -0
- honeybee_energy/run.py +1577 -0
- honeybee_energy/schedule/__init__.py +1 -0
- honeybee_energy/schedule/day.py +626 -0
- honeybee_energy/schedule/dictutil.py +59 -0
- honeybee_energy/schedule/fixedinterval.py +1012 -0
- honeybee_energy/schedule/rule.py +619 -0
- honeybee_energy/schedule/ruleset.py +1867 -0
- honeybee_energy/schedule/typelimit.py +310 -0
- honeybee_energy/shw.py +315 -0
- honeybee_energy/simulation/__init__.py +1 -0
- honeybee_energy/simulation/control.py +214 -0
- honeybee_energy/simulation/daylightsaving.py +185 -0
- honeybee_energy/simulation/dictutil.py +51 -0
- honeybee_energy/simulation/output.py +646 -0
- honeybee_energy/simulation/parameter.py +606 -0
- honeybee_energy/simulation/runperiod.py +443 -0
- honeybee_energy/simulation/shadowcalculation.py +295 -0
- honeybee_energy/simulation/sizing.py +546 -0
- honeybee_energy/ventcool/__init__.py +5 -0
- honeybee_energy/ventcool/_crack_data.py +91 -0
- honeybee_energy/ventcool/afn.py +289 -0
- honeybee_energy/ventcool/control.py +269 -0
- honeybee_energy/ventcool/crack.py +126 -0
- honeybee_energy/ventcool/fan.py +493 -0
- honeybee_energy/ventcool/opening.py +365 -0
- honeybee_energy/ventcool/simulation.py +314 -0
- honeybee_energy/writer.py +1078 -0
- honeybee_energy-1.116.106.dist-info/METADATA +113 -0
- honeybee_energy-1.116.106.dist-info/RECORD +162 -0
- honeybee_energy-1.116.106.dist-info/WHEEL +5 -0
- honeybee_energy-1.116.106.dist-info/entry_points.txt +2 -0
- honeybee_energy-1.116.106.dist-info/licenses/LICENSE +661 -0
- honeybee_energy-1.116.106.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
"""Variable Air Volume (VAV) HVAC system."""
|
|
3
|
+
from __future__ import division
|
|
4
|
+
|
|
5
|
+
from ._base import _AllAirBase
|
|
6
|
+
|
|
7
|
+
from honeybee._lockable import lockable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@lockable
|
|
11
|
+
class VAV(_AllAirBase):
|
|
12
|
+
"""Variable Air Volume (VAV) HVAC system (aka. System 7 or 8).
|
|
13
|
+
|
|
14
|
+
All rooms/zones are connected to a central air loop that is kept at a constant
|
|
15
|
+
central temperature of 12.8C (55F). The central temperature is maintained by a
|
|
16
|
+
cooling coil, which runs whenever the combination of return air and fresh outdoor
|
|
17
|
+
air is greater than 12.8C, as well as a heating coil, which runs whenever
|
|
18
|
+
the combination of return air and fresh outdoor air is less than 12.8C.
|
|
19
|
+
|
|
20
|
+
Each air terminal for the connected rooms/zones contains its own reheat coil,
|
|
21
|
+
which runs whenever the room is not in need of the cooling supplied by the 12.8C
|
|
22
|
+
central air.
|
|
23
|
+
|
|
24
|
+
The central cooling coil is always a chilled water coil, which is connected to a
|
|
25
|
+
chilled water loop operating at 6.7C (44F). All heating coils are hot water coils
|
|
26
|
+
except when Gas Coil equipment_type is used (in which case coils are gas)
|
|
27
|
+
or when Parallel Fan-Powered (PFP) boxes equipment_type is used (in which case
|
|
28
|
+
coils are electric resistance). Hot water temperature is 82C (180F) for
|
|
29
|
+
boiler/district heating and 49C (120F) when ASHP is used.
|
|
30
|
+
|
|
31
|
+
VAV systems are the traditional baseline system for commercial buildings
|
|
32
|
+
taller than 5 stories or larger than 14,000 m2 (150,000 ft2) of floor area.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
identifier: Text string for system identifier. Must be < 100 characters
|
|
36
|
+
and not contain any EnergyPlus special characters. This will be used to
|
|
37
|
+
identify the object across a model and in the exported IDF.
|
|
38
|
+
vintage: Text for the vintage of the template system. This will be used
|
|
39
|
+
to set efficiencies for various pieces of equipment within the system.
|
|
40
|
+
Choose from the following.
|
|
41
|
+
|
|
42
|
+
* DOE_Ref_Pre_1980
|
|
43
|
+
* DOE_Ref_1980_2004
|
|
44
|
+
* ASHRAE_2004
|
|
45
|
+
* ASHRAE_2007
|
|
46
|
+
* ASHRAE_2010
|
|
47
|
+
* ASHRAE_2013
|
|
48
|
+
* ASHRAE_2016
|
|
49
|
+
* ASHRAE_2019
|
|
50
|
+
|
|
51
|
+
equipment_type: Text for the specific type of the system and equipment. (Default:
|
|
52
|
+
the first option below) Choose from.
|
|
53
|
+
|
|
54
|
+
* VAV_Chiller_Boiler
|
|
55
|
+
* VAV_Chiller_ASHP
|
|
56
|
+
* VAV_Chiller_DHW
|
|
57
|
+
* VAV_Chiller_PFP
|
|
58
|
+
* VAV_Chiller_GasCoil
|
|
59
|
+
* VAV_ACChiller_Boiler
|
|
60
|
+
* VAV_ACChiller_ASHP
|
|
61
|
+
* VAV_ACChiller_DHW
|
|
62
|
+
* VAV_ACChiller_PFP
|
|
63
|
+
* VAV_ACChiller_GasCoil
|
|
64
|
+
* VAV_DCW_Boiler
|
|
65
|
+
* VAV_DCW_ASHP
|
|
66
|
+
* VAV_DCW_DHW
|
|
67
|
+
* VAV_DCW_PFP
|
|
68
|
+
* VAV_DCW_GasCoil
|
|
69
|
+
|
|
70
|
+
economizer_type: Text to indicate the type of air-side economizer used on
|
|
71
|
+
the system. (Default: NoEconomizer). Choose from the following.
|
|
72
|
+
|
|
73
|
+
* NoEconomizer
|
|
74
|
+
* DifferentialDryBulb
|
|
75
|
+
* DifferentialEnthalpy
|
|
76
|
+
* DifferentialDryBulbAndEnthalpy
|
|
77
|
+
* FixedDryBulb
|
|
78
|
+
* FixedEnthalpy
|
|
79
|
+
* ElectronicEnthalpy
|
|
80
|
+
|
|
81
|
+
sensible_heat_recovery: A number between 0 and 1 for the effectiveness
|
|
82
|
+
of sensible heat recovery within the system. (Default: 0).
|
|
83
|
+
latent_heat_recovery: A number between 0 and 1 for the effectiveness
|
|
84
|
+
of latent heat recovery within the system. (Default: 0).
|
|
85
|
+
demand_controlled_ventilation: Boolean to note whether demand controlled
|
|
86
|
+
ventilation should be used on the system, which will vary the amount
|
|
87
|
+
of ventilation air according to the occupancy schedule of the
|
|
88
|
+
Rooms. (Default: False).
|
|
89
|
+
|
|
90
|
+
Properties:
|
|
91
|
+
* identifier
|
|
92
|
+
* display_name
|
|
93
|
+
* vintage
|
|
94
|
+
* equipment_type
|
|
95
|
+
* economizer_type
|
|
96
|
+
* sensible_heat_recovery
|
|
97
|
+
* latent_heat_recovery
|
|
98
|
+
* demand_controlled_ventilation
|
|
99
|
+
* schedules
|
|
100
|
+
* has_district_heating
|
|
101
|
+
* has_district_cooling
|
|
102
|
+
* user_data
|
|
103
|
+
* properties
|
|
104
|
+
|
|
105
|
+
Note:
|
|
106
|
+
[1] American Society of Heating, Refrigerating and Air-Conditioning Engineers,
|
|
107
|
+
Inc. (2007). Ashrae standard 90.1. Atlanta, GA. https://www.ashrae.org/\
|
|
108
|
+
technical-resources/standards-and-guidelines/read-only-versions-of-ashrae-standards
|
|
109
|
+
"""
|
|
110
|
+
__slots__ = ()
|
|
111
|
+
|
|
112
|
+
EQUIPMENT_TYPES = (
|
|
113
|
+
'VAV_Chiller_Boiler',
|
|
114
|
+
'VAV_Chiller_ASHP',
|
|
115
|
+
'VAV_Chiller_DHW',
|
|
116
|
+
'VAV_Chiller_PFP',
|
|
117
|
+
'VAV_Chiller_GasCoil',
|
|
118
|
+
'VAV_ACChiller_Boiler',
|
|
119
|
+
'VAV_ACChiller_ASHP',
|
|
120
|
+
'VAV_ACChiller_DHW',
|
|
121
|
+
'VAV_ACChiller_PFP',
|
|
122
|
+
'VAV_ACChiller_GasCoil',
|
|
123
|
+
'VAV_DCW_Boiler',
|
|
124
|
+
'VAV_DCW_ASHP',
|
|
125
|
+
'VAV_DCW_DHW',
|
|
126
|
+
'VAV_DCW_PFP',
|
|
127
|
+
'VAV_DCW_GasCoil'
|
|
128
|
+
)
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
"""Detailed HVAC system object defined using IronBug or OpenStudio .NET bindings."""
|
|
3
|
+
from __future__ import division
|
|
4
|
+
|
|
5
|
+
from honeybee._lockable import lockable
|
|
6
|
+
|
|
7
|
+
from ._base import _HVACSystem
|
|
8
|
+
from .idealair import IdealAirSystem
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@lockable
|
|
12
|
+
class DetailedHVAC(_HVACSystem):
|
|
13
|
+
"""Detailed HVAC system object defined using IronBug or OpenStudio .NET bindings.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
identifier: Text string for detailed system identifier. Must be < 100 characters
|
|
17
|
+
and not contain any EnergyPlus special characters.
|
|
18
|
+
specification: A JSON-serializable dictionary representing the full
|
|
19
|
+
specification of the detailed system. This can be obtained by calling
|
|
20
|
+
the ToJson() method on any IronBug HVAC system and then serializing
|
|
21
|
+
the resulting JSON string into a Python dictionary using the native
|
|
22
|
+
Python json package. Note that the Rooms that the HVAC is assigned to
|
|
23
|
+
must be specified as ThermalZones under this specification in order
|
|
24
|
+
for the resulting Model this HVAC is a part of to be valid.
|
|
25
|
+
|
|
26
|
+
Properties:
|
|
27
|
+
* identifier
|
|
28
|
+
* specification
|
|
29
|
+
* thermal_zones
|
|
30
|
+
* design_type
|
|
31
|
+
* air_loop_count
|
|
32
|
+
* economizer_type
|
|
33
|
+
* sensible_heat_recovery
|
|
34
|
+
* latent_heat_recovery
|
|
35
|
+
* display_name
|
|
36
|
+
* user_data
|
|
37
|
+
"""
|
|
38
|
+
NO_AIR_LOOP = 'Ironbug.HVAC.IB_NoAirLoop'
|
|
39
|
+
AIR_LOOP = 'Ironbug.HVAC.IB_AirLoopHVAC'
|
|
40
|
+
BRANCHES = 'Ironbug.HVAC.IB_AirLoopBranches'
|
|
41
|
+
OA_SYSTEM = 'Ironbug.HVAC.IB_OutdoorAirSystem'
|
|
42
|
+
OA_CONTROLLER = 'Ironbug.HVAC.IB_ControllerOutdoorAir'
|
|
43
|
+
HEAT_RECOVERY = 'Ironbug.HVAC.IB_HeatExchangerAirToAirSensibleAndLatent'
|
|
44
|
+
HR_SENSIBLE = (
|
|
45
|
+
'SensibleEffectivenessat75CoolingAirFlow',
|
|
46
|
+
'SensibleEffectivenessat75HeatingAirFlow'
|
|
47
|
+
)
|
|
48
|
+
HR_LATENT = (
|
|
49
|
+
'LatentEffectivenessat75CoolingAirFlow',
|
|
50
|
+
'LatentEffectivenessat75HeatingAirFlow'
|
|
51
|
+
)
|
|
52
|
+
ECONOMIZER_TYPES = ('NoEconomizer', 'DifferentialDryBulb', 'DifferentialEnthalpy',
|
|
53
|
+
'DifferentialDryBulbAndEnthalpy', 'FixedDryBulb',
|
|
54
|
+
'FixedEnthalpy', 'ElectronicEnthalpy')
|
|
55
|
+
|
|
56
|
+
__slots__ = ('_specification', '_thermal_zones', '_design_type', '_air_loop_count',
|
|
57
|
+
'_economizer_type', '_sensible_heat_recovery', '_latent_heat_recovery')
|
|
58
|
+
|
|
59
|
+
def __init__(self, identifier, specification):
|
|
60
|
+
"""Initialize DetailedHVAC."""
|
|
61
|
+
# initialize base HVAC system properties
|
|
62
|
+
_HVACSystem.__init__(self, identifier)
|
|
63
|
+
self.specification = specification
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def specification(self):
|
|
67
|
+
"""Get or set a dictionary for the full specification of this HVAC.
|
|
68
|
+
|
|
69
|
+
This can be obtained by calling the SaveAsJson() method on any IronBug HVAC
|
|
70
|
+
system and then serializing the resulting JSON string into a Python dictionary
|
|
71
|
+
using the native Python json package.
|
|
72
|
+
"""
|
|
73
|
+
return self._specification
|
|
74
|
+
|
|
75
|
+
@specification.setter
|
|
76
|
+
def specification(self, value):
|
|
77
|
+
assert isinstance(value, dict), 'Expected dictionary for DetailedHVAC' \
|
|
78
|
+
'object specification. Got {}.'.format(type(value))
|
|
79
|
+
thermal_zones, design_type, air_loop_count = [], 'HeatCool', 0
|
|
80
|
+
econ_type, sensible_hr, latent_hr = 'NoEconomizer', 0, 0
|
|
81
|
+
try:
|
|
82
|
+
for a_loop in value['AirLoops']:
|
|
83
|
+
if a_loop['$type'].startswith(self.NO_AIR_LOOP):
|
|
84
|
+
# get all of the zones on the demand side
|
|
85
|
+
for zone in a_loop['ThermalZones']:
|
|
86
|
+
for z_attr in zone['CustomAttributes']:
|
|
87
|
+
if z_attr['Field']['FullName'] == 'Name':
|
|
88
|
+
thermal_zones.append(z_attr['Value'])
|
|
89
|
+
elif a_loop['$type'].startswith(self.AIR_LOOP):
|
|
90
|
+
# determine whether it's an AllAir system or DOAS system
|
|
91
|
+
air_loop_count += 1
|
|
92
|
+
design_type = 'AllAir'
|
|
93
|
+
if 'SizingSystem' in a_loop and \
|
|
94
|
+
'CustomAttributes' in a_loop['SizingSystem']:
|
|
95
|
+
for sz_attr in a_loop['SizingSystem']['CustomAttributes']:
|
|
96
|
+
if sz_attr['Field']['FullName'] == 'TypeofLoadtoSizeOn':
|
|
97
|
+
if sz_attr['Value'] == 'VentilationRequirement':
|
|
98
|
+
design_type = 'DOAS'
|
|
99
|
+
# determine the type of economizer or heat recovery
|
|
100
|
+
for comp in a_loop['SupplyComponents']:
|
|
101
|
+
if comp['$type'].startswith(self.OA_SYSTEM):
|
|
102
|
+
for child in comp['Children']:
|
|
103
|
+
if child['$type'].startswith(self.OA_CONTROLLER):
|
|
104
|
+
if 'CustomAttributes' in child:
|
|
105
|
+
for attr in child['CustomAttributes']:
|
|
106
|
+
f_name = attr['Field']['FullName']
|
|
107
|
+
if f_name == 'EconomizerControlType':
|
|
108
|
+
econ_type = self._f_econ(attr['Value'])
|
|
109
|
+
if 'IBProperties' in comp and \
|
|
110
|
+
'OAStreamObjs' in comp['IBProperties']:
|
|
111
|
+
for oa_comp in comp['IBProperties']['OAStreamObjs']:
|
|
112
|
+
if oa_comp['$type'].startswith(self.HEAT_RECOVERY):
|
|
113
|
+
if 'CustomAttributes' in oa_comp:
|
|
114
|
+
for oa_attr in oa_comp['CustomAttributes']:
|
|
115
|
+
f_name = oa_attr['Field']['FullName']
|
|
116
|
+
if f_name in self.HR_SENSIBLE:
|
|
117
|
+
sensible_hr = oa_attr['Value']
|
|
118
|
+
if f_name in self.HR_LATENT:
|
|
119
|
+
latent_hr = oa_attr['Value']
|
|
120
|
+
# get all of the zones on the demand side
|
|
121
|
+
for comp in a_loop['DemandComponents']:
|
|
122
|
+
if comp['$type'].startswith(self.BRANCHES):
|
|
123
|
+
for branch in comp['Branches']:
|
|
124
|
+
for z_attr in branch[0]['CustomAttributes']:
|
|
125
|
+
if z_attr['Field']['FullName'] == 'Name':
|
|
126
|
+
thermal_zones.append(z_attr['Value'])
|
|
127
|
+
else:
|
|
128
|
+
raise ValueError('DetailedHVAC specification does not contain '
|
|
129
|
+
'any ThermalZones that can be matched to Rooms.')
|
|
130
|
+
except KeyError as e:
|
|
131
|
+
raise ValueError('DetailedHVAC specification is not valid:\n{}'.format(e))
|
|
132
|
+
self._thermal_zones = tuple(thermal_zones)
|
|
133
|
+
self._design_type = design_type
|
|
134
|
+
self._air_loop_count = air_loop_count
|
|
135
|
+
self._economizer_type = econ_type
|
|
136
|
+
self._sensible_heat_recovery = sensible_hr
|
|
137
|
+
self._latent_heat_recovery = latent_hr
|
|
138
|
+
self._specification = value
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def thermal_zones(self):
|
|
142
|
+
"""Get a tuple of strings for the Rooms/Zones to which the HVAC is assigned."""
|
|
143
|
+
return self._thermal_zones
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def design_type(self):
|
|
147
|
+
"""Text for the structure of the system. It will be one of the following.
|
|
148
|
+
|
|
149
|
+
* AllAir
|
|
150
|
+
* DOAS
|
|
151
|
+
* HeatCool
|
|
152
|
+
"""
|
|
153
|
+
return self._design_type
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def air_loop_count(self):
|
|
157
|
+
"""Get an integer for the number of air loops in the system."""
|
|
158
|
+
return self._air_loop_count
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def economizer_type(self):
|
|
162
|
+
"""Get text to indicate the type of air-side economizer.
|
|
163
|
+
|
|
164
|
+
Choose from the following options.
|
|
165
|
+
|
|
166
|
+
* NoEconomizer
|
|
167
|
+
* DifferentialDryBulb
|
|
168
|
+
* DifferentialEnthalpy
|
|
169
|
+
* DifferentialDryBulbAndEnthalpy
|
|
170
|
+
* FixedDryBulb
|
|
171
|
+
* FixedEnthalpy
|
|
172
|
+
* ElectronicEnthalpy
|
|
173
|
+
"""
|
|
174
|
+
return self._economizer_type
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def sensible_heat_recovery(self):
|
|
178
|
+
"""Get a number for the effectiveness of sensible heat recovery."""
|
|
179
|
+
return self._sensible_heat_recovery
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def latent_heat_recovery(self):
|
|
183
|
+
"""Get a number for the effectiveness of latent heat recovery."""
|
|
184
|
+
return self._latent_heat_recovery
|
|
185
|
+
|
|
186
|
+
def sync_room_ids(self, room_map):
|
|
187
|
+
"""Sync this DetailedHVAC with Rooms that had their IDs changed.
|
|
188
|
+
|
|
189
|
+
This is useful after running the Model.reset_ids() command to ensure that
|
|
190
|
+
the bi-directional Room references between DetailedHVAC and Honeybee Rooms
|
|
191
|
+
is correct.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
room_map: A dictionary that relates the original Rooms identifiers (keys)
|
|
195
|
+
to the new identifiers (values) of the Rooms in the Model.
|
|
196
|
+
"""
|
|
197
|
+
thermal_zones, air_loop_count = [], 0
|
|
198
|
+
hvac_spec = self._specification
|
|
199
|
+
for a_loop in hvac_spec['AirLoops']:
|
|
200
|
+
if a_loop['$type'].startswith(self.NO_AIR_LOOP):
|
|
201
|
+
for zone in a_loop['ThermalZones']:
|
|
202
|
+
for z_attr in zone['CustomAttributes']:
|
|
203
|
+
if z_attr['Field']['FullName'] == 'Name':
|
|
204
|
+
z_attr['Value'] = room_map[z_attr['Value']]
|
|
205
|
+
thermal_zones.append(z_attr['Value'])
|
|
206
|
+
elif a_loop['$type'].startswith(self.AIR_LOOP):
|
|
207
|
+
air_loop_count += 1
|
|
208
|
+
for comp in a_loop['DemandComponents']:
|
|
209
|
+
if comp['$type'].startswith(self.BRANCHES):
|
|
210
|
+
for branch in comp['Branches']:
|
|
211
|
+
for z_attr in branch[0]['CustomAttributes']:
|
|
212
|
+
if z_attr['Field']['FullName'] == 'Name':
|
|
213
|
+
z_attr['Value'] = room_map[z_attr['Value']]
|
|
214
|
+
thermal_zones.append(z_attr['Value'])
|
|
215
|
+
# unlock object and set attributes
|
|
216
|
+
was_locked = False
|
|
217
|
+
if self._locked:
|
|
218
|
+
was_locked = True
|
|
219
|
+
self.unlock()
|
|
220
|
+
self._air_loop_count = air_loop_count
|
|
221
|
+
self._thermal_zones = tuple(thermal_zones)
|
|
222
|
+
self._specification = hvac_spec
|
|
223
|
+
if was_locked: # set the object back to being locked
|
|
224
|
+
self.lock()
|
|
225
|
+
|
|
226
|
+
def to_ideal_air_equivalent(self):
|
|
227
|
+
"""This method is NOT YET IMPLEMENTED."""
|
|
228
|
+
econ_typ = self.economizer_type
|
|
229
|
+
if econ_typ not in self.ECONOMIZER_TYPES[:3]:
|
|
230
|
+
enth_types = ('FixedEnthalpy', 'ElectronicEnthalpy')
|
|
231
|
+
econ_typ = 'DifferentialEnthalpy' if econ_typ in enth_types \
|
|
232
|
+
else 'DifferentialDryBulb'
|
|
233
|
+
i_sys = IdealAirSystem(
|
|
234
|
+
self.identifier, economizer_type=econ_typ,
|
|
235
|
+
sensible_heat_recovery=self.sensible_heat_recovery,
|
|
236
|
+
latent_heat_recovery=self.latent_heat_recovery)
|
|
237
|
+
i_sys._display_name = self._display_name
|
|
238
|
+
return i_sys
|
|
239
|
+
|
|
240
|
+
@classmethod
|
|
241
|
+
def from_dict(cls, data):
|
|
242
|
+
"""Create a HVAC object from a dictionary.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
data: A HVAC dictionary in following the format below.
|
|
246
|
+
|
|
247
|
+
.. code-block:: python
|
|
248
|
+
|
|
249
|
+
{
|
|
250
|
+
"type": "DetailedHVAC",
|
|
251
|
+
"identifier": "Classroom1_System", # identifier for the HVAC
|
|
252
|
+
"display_name": "Custom VAV System", # name for the HVAC
|
|
253
|
+
"specification": {} # dictionary for the full HVAC specification
|
|
254
|
+
}
|
|
255
|
+
"""
|
|
256
|
+
assert data['type'] == 'DetailedHVAC', \
|
|
257
|
+
'Expected {} dictionary. Got {}.'.format('DetailedHVAC', data['type'])
|
|
258
|
+
new_obj = cls(data['identifier'], data['specification'])
|
|
259
|
+
if 'display_name' in data and data['display_name'] is not None:
|
|
260
|
+
new_obj.display_name = data['display_name']
|
|
261
|
+
if 'user_data' in data and data['user_data'] is not None:
|
|
262
|
+
new_obj.user_data = data['user_data']
|
|
263
|
+
return new_obj
|
|
264
|
+
|
|
265
|
+
@classmethod
|
|
266
|
+
def from_dict_abridged(cls, data, schedule_dict):
|
|
267
|
+
"""Create a HVAC object from an abridged dictionary.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
data: An abridged dictionary in following the format below.
|
|
271
|
+
schedule_dict: A dictionary with schedule identifiers as keys and honeybee
|
|
272
|
+
schedule objects as values.
|
|
273
|
+
|
|
274
|
+
.. code-block:: python
|
|
275
|
+
|
|
276
|
+
{
|
|
277
|
+
"type": "DetailedHVAC",
|
|
278
|
+
"identifier": "Classroom1_System", # identifier for the HVAC
|
|
279
|
+
"display_name": "Custom VAV System", # name for the HVAC
|
|
280
|
+
"specification": {} # dictionary for the full HVAC specification
|
|
281
|
+
}
|
|
282
|
+
"""
|
|
283
|
+
# this is the same as the from_dict method for as long as there are not schedules
|
|
284
|
+
return cls.from_dict(data)
|
|
285
|
+
|
|
286
|
+
def to_dict(self, abridged=False):
|
|
287
|
+
"""DetailedHVAC dictionary representation.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
abridged: Boolean to note whether the full dictionary describing the
|
|
291
|
+
object should be returned (False) or just an abridged version (True).
|
|
292
|
+
This input currently has no effect but may eventually have one if
|
|
293
|
+
schedule-type properties are exposed on this object.
|
|
294
|
+
"""
|
|
295
|
+
base = {'type': 'DetailedHVAC'}
|
|
296
|
+
base['identifier'] = self.identifier
|
|
297
|
+
base['specification'] = self.specification
|
|
298
|
+
if self._display_name is not None:
|
|
299
|
+
base['display_name'] = self.display_name
|
|
300
|
+
if self._user_data is not None:
|
|
301
|
+
base['user_data'] = self.user_data
|
|
302
|
+
return base
|
|
303
|
+
|
|
304
|
+
def _f_econ(self, value):
|
|
305
|
+
clean_input = value.lower()
|
|
306
|
+
for key in self.ECONOMIZER_TYPES:
|
|
307
|
+
if key.lower() == clean_input:
|
|
308
|
+
value = key
|
|
309
|
+
break
|
|
310
|
+
else:
|
|
311
|
+
raise ValueError(
|
|
312
|
+
'economizer_type {} is not recognized.\nChoose from the '
|
|
313
|
+
'following:\n{}'.format(value, self.ECONOMIZER_TYPES))
|
|
314
|
+
return value
|
|
315
|
+
|
|
316
|
+
def __copy__(self):
|
|
317
|
+
new_obj = self.__class__(self.identifier, self.specification.copy())
|
|
318
|
+
new_obj._display_name = self._display_name
|
|
319
|
+
new_obj._user_data = None if self._user_data is None else self._user_data.copy()
|
|
320
|
+
return new_obj
|
|
321
|
+
|
|
322
|
+
def __key(self):
|
|
323
|
+
"""A tuple based on the object properties, useful for hashing."""
|
|
324
|
+
return (self._identifier, self._air_loop_count) + self._thermal_zones
|
|
325
|
+
|
|
326
|
+
def __hash__(self):
|
|
327
|
+
return hash(self.__key())
|
|
328
|
+
|
|
329
|
+
def __eq__(self, other):
|
|
330
|
+
return isinstance(other, self.__class__) and self.__key() == other.__key()
|
|
331
|
+
|
|
332
|
+
def __ne__(self, other):
|
|
333
|
+
return not self.__eq__(other)
|
|
334
|
+
|
|
335
|
+
def __repr__(self):
|
|
336
|
+
return 'DetailedHVAC: {} [air loops: {}] [zones: {}]'.format(
|
|
337
|
+
self.display_name, self.air_loop_count, len(self.thermal_zones))
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Template Dedicated Outdoor Air System (DOAS) HVAC definitions.
|
|
2
|
+
|
|
3
|
+
DOAS systems separate minimum ventilation supply from the satisfaction of heating
|
|
4
|
+
+ cooling demand. Ventilation air tends to be supplied at neutral temperatures
|
|
5
|
+
(close to room air temperature) and heating / cooling loads are met with additional
|
|
6
|
+
pieces of zone equipment (eg. Fan Coil Units (FCUs)).
|
|
7
|
+
|
|
8
|
+
Because DOAS systems only have to cool down and re-heat the minimum ventilation air,
|
|
9
|
+
they tend to use less energy than all-air systems. They also tend to use less energy
|
|
10
|
+
to distribute heating + cooling by pumping around hot/cold water or refrigerant
|
|
11
|
+
instead of blowing hot/cold air. However, they do not provide as good of control
|
|
12
|
+
over humidity and so they may not be appropriate for rooms with high latent loads
|
|
13
|
+
like auditoriums, kitchens, laundromats, etc.
|
|
14
|
+
|
|
15
|
+
Properties:
|
|
16
|
+
* HVAC_TYPES_DICT: A dictionary containing pointers to the classes of each
|
|
17
|
+
HVAC system. The keys of this dictionary are the names of the HVAC
|
|
18
|
+
classes (eg. 'FCU').
|
|
19
|
+
* EQUIPMENT_TYPES_DICT: A dictionary containing pointers to the classes of
|
|
20
|
+
the HVAC systems. The keys of this dictionary are the names of the HVAC
|
|
21
|
+
systems as they appear in the OpenStudio standards gem and include the
|
|
22
|
+
specific equipment in the system (eg. 'DOAS with fan coil chiller with boiler').
|
|
23
|
+
"""
|
|
24
|
+
from ._base import _DOASEnumeration
|
|
25
|
+
|
|
26
|
+
_doas_types = _DOASEnumeration(import_modules=True)
|
|
27
|
+
HVAC_TYPES_DICT = _doas_types.types_dict
|
|
28
|
+
EQUIPMENT_TYPES_DICT = _doas_types.equipment_types_dict
|