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.
Files changed (162) hide show
  1. honeybee_energy/__init__.py +24 -0
  2. honeybee_energy/__main__.py +4 -0
  3. honeybee_energy/_extend_honeybee.py +145 -0
  4. honeybee_energy/altnumber.py +21 -0
  5. honeybee_energy/baseline/__init__.py +2 -0
  6. honeybee_energy/baseline/create.py +608 -0
  7. honeybee_energy/baseline/data/__init__.py +1 -0
  8. honeybee_energy/baseline/data/constructions.csv +64 -0
  9. honeybee_energy/baseline/data/fen_ratios.csv +15 -0
  10. honeybee_energy/baseline/data/lpd_building.csv +21 -0
  11. honeybee_energy/baseline/data/pci_2016.csv +22 -0
  12. honeybee_energy/baseline/data/pci_2019.csv +22 -0
  13. honeybee_energy/baseline/data/pci_2022.csv +22 -0
  14. honeybee_energy/baseline/data/shw.csv +21 -0
  15. honeybee_energy/baseline/pci.py +512 -0
  16. honeybee_energy/baseline/result.py +371 -0
  17. honeybee_energy/boundarycondition.py +128 -0
  18. honeybee_energy/cli/__init__.py +69 -0
  19. honeybee_energy/cli/baseline.py +475 -0
  20. honeybee_energy/cli/edit.py +327 -0
  21. honeybee_energy/cli/lib.py +1154 -0
  22. honeybee_energy/cli/result.py +810 -0
  23. honeybee_energy/cli/setconfig.py +124 -0
  24. honeybee_energy/cli/settings.py +569 -0
  25. honeybee_energy/cli/simulate.py +380 -0
  26. honeybee_energy/cli/translate.py +1714 -0
  27. honeybee_energy/cli/validate.py +224 -0
  28. honeybee_energy/config.json +11 -0
  29. honeybee_energy/config.py +842 -0
  30. honeybee_energy/construction/__init__.py +1 -0
  31. honeybee_energy/construction/_base.py +374 -0
  32. honeybee_energy/construction/air.py +325 -0
  33. honeybee_energy/construction/dictutil.py +89 -0
  34. honeybee_energy/construction/dynamic.py +607 -0
  35. honeybee_energy/construction/opaque.py +460 -0
  36. honeybee_energy/construction/shade.py +319 -0
  37. honeybee_energy/construction/window.py +1096 -0
  38. honeybee_energy/construction/windowshade.py +847 -0
  39. honeybee_energy/constructionset.py +1655 -0
  40. honeybee_energy/dictutil.py +56 -0
  41. honeybee_energy/generator/__init__.py +5 -0
  42. honeybee_energy/generator/loadcenter.py +204 -0
  43. honeybee_energy/generator/pv.py +535 -0
  44. honeybee_energy/hvac/__init__.py +21 -0
  45. honeybee_energy/hvac/_base.py +124 -0
  46. honeybee_energy/hvac/_template.py +270 -0
  47. honeybee_energy/hvac/allair/__init__.py +22 -0
  48. honeybee_energy/hvac/allair/_base.py +349 -0
  49. honeybee_energy/hvac/allair/furnace.py +168 -0
  50. honeybee_energy/hvac/allair/psz.py +131 -0
  51. honeybee_energy/hvac/allair/ptac.py +163 -0
  52. honeybee_energy/hvac/allair/pvav.py +109 -0
  53. honeybee_energy/hvac/allair/vav.py +128 -0
  54. honeybee_energy/hvac/detailed.py +337 -0
  55. honeybee_energy/hvac/doas/__init__.py +28 -0
  56. honeybee_energy/hvac/doas/_base.py +345 -0
  57. honeybee_energy/hvac/doas/fcu.py +127 -0
  58. honeybee_energy/hvac/doas/radiant.py +329 -0
  59. honeybee_energy/hvac/doas/vrf.py +81 -0
  60. honeybee_energy/hvac/doas/wshp.py +91 -0
  61. honeybee_energy/hvac/heatcool/__init__.py +23 -0
  62. honeybee_energy/hvac/heatcool/_base.py +177 -0
  63. honeybee_energy/hvac/heatcool/baseboard.py +61 -0
  64. honeybee_energy/hvac/heatcool/evapcool.py +72 -0
  65. honeybee_energy/hvac/heatcool/fcu.py +92 -0
  66. honeybee_energy/hvac/heatcool/gasunit.py +53 -0
  67. honeybee_energy/hvac/heatcool/radiant.py +269 -0
  68. honeybee_energy/hvac/heatcool/residential.py +77 -0
  69. honeybee_energy/hvac/heatcool/vrf.py +54 -0
  70. honeybee_energy/hvac/heatcool/windowac.py +70 -0
  71. honeybee_energy/hvac/heatcool/wshp.py +62 -0
  72. honeybee_energy/hvac/idealair.py +699 -0
  73. honeybee_energy/internalmass.py +310 -0
  74. honeybee_energy/lib/__init__.py +1 -0
  75. honeybee_energy/lib/_loadconstructions.py +194 -0
  76. honeybee_energy/lib/_loadconstructionsets.py +117 -0
  77. honeybee_energy/lib/_loadmaterials.py +83 -0
  78. honeybee_energy/lib/_loadprogramtypes.py +125 -0
  79. honeybee_energy/lib/_loadschedules.py +87 -0
  80. honeybee_energy/lib/_loadtypelimits.py +64 -0
  81. honeybee_energy/lib/constructions.py +207 -0
  82. honeybee_energy/lib/constructionsets.py +95 -0
  83. honeybee_energy/lib/materials.py +67 -0
  84. honeybee_energy/lib/programtypes.py +125 -0
  85. honeybee_energy/lib/schedules.py +61 -0
  86. honeybee_energy/lib/scheduletypelimits.py +31 -0
  87. honeybee_energy/load/__init__.py +1 -0
  88. honeybee_energy/load/_base.py +190 -0
  89. honeybee_energy/load/daylight.py +397 -0
  90. honeybee_energy/load/dictutil.py +47 -0
  91. honeybee_energy/load/equipment.py +771 -0
  92. honeybee_energy/load/hotwater.py +543 -0
  93. honeybee_energy/load/infiltration.py +460 -0
  94. honeybee_energy/load/lighting.py +480 -0
  95. honeybee_energy/load/people.py +497 -0
  96. honeybee_energy/load/process.py +472 -0
  97. honeybee_energy/load/setpoint.py +816 -0
  98. honeybee_energy/load/ventilation.py +550 -0
  99. honeybee_energy/material/__init__.py +1 -0
  100. honeybee_energy/material/_base.py +166 -0
  101. honeybee_energy/material/dictutil.py +59 -0
  102. honeybee_energy/material/frame.py +367 -0
  103. honeybee_energy/material/gas.py +1087 -0
  104. honeybee_energy/material/glazing.py +854 -0
  105. honeybee_energy/material/opaque.py +1351 -0
  106. honeybee_energy/material/shade.py +1360 -0
  107. honeybee_energy/measure.py +472 -0
  108. honeybee_energy/programtype.py +723 -0
  109. honeybee_energy/properties/__init__.py +1 -0
  110. honeybee_energy/properties/aperture.py +333 -0
  111. honeybee_energy/properties/door.py +342 -0
  112. honeybee_energy/properties/extension.py +244 -0
  113. honeybee_energy/properties/face.py +274 -0
  114. honeybee_energy/properties/model.py +2640 -0
  115. honeybee_energy/properties/room.py +1747 -0
  116. honeybee_energy/properties/shade.py +314 -0
  117. honeybee_energy/properties/shademesh.py +262 -0
  118. honeybee_energy/reader.py +48 -0
  119. honeybee_energy/result/__init__.py +1 -0
  120. honeybee_energy/result/colorobj.py +648 -0
  121. honeybee_energy/result/emissions.py +290 -0
  122. honeybee_energy/result/err.py +101 -0
  123. honeybee_energy/result/eui.py +100 -0
  124. honeybee_energy/result/generation.py +160 -0
  125. honeybee_energy/result/loadbalance.py +890 -0
  126. honeybee_energy/result/match.py +202 -0
  127. honeybee_energy/result/osw.py +90 -0
  128. honeybee_energy/result/rdd.py +59 -0
  129. honeybee_energy/result/zsz.py +190 -0
  130. honeybee_energy/run.py +1577 -0
  131. honeybee_energy/schedule/__init__.py +1 -0
  132. honeybee_energy/schedule/day.py +626 -0
  133. honeybee_energy/schedule/dictutil.py +59 -0
  134. honeybee_energy/schedule/fixedinterval.py +1012 -0
  135. honeybee_energy/schedule/rule.py +619 -0
  136. honeybee_energy/schedule/ruleset.py +1867 -0
  137. honeybee_energy/schedule/typelimit.py +310 -0
  138. honeybee_energy/shw.py +315 -0
  139. honeybee_energy/simulation/__init__.py +1 -0
  140. honeybee_energy/simulation/control.py +214 -0
  141. honeybee_energy/simulation/daylightsaving.py +185 -0
  142. honeybee_energy/simulation/dictutil.py +51 -0
  143. honeybee_energy/simulation/output.py +646 -0
  144. honeybee_energy/simulation/parameter.py +606 -0
  145. honeybee_energy/simulation/runperiod.py +443 -0
  146. honeybee_energy/simulation/shadowcalculation.py +295 -0
  147. honeybee_energy/simulation/sizing.py +546 -0
  148. honeybee_energy/ventcool/__init__.py +5 -0
  149. honeybee_energy/ventcool/_crack_data.py +91 -0
  150. honeybee_energy/ventcool/afn.py +289 -0
  151. honeybee_energy/ventcool/control.py +269 -0
  152. honeybee_energy/ventcool/crack.py +126 -0
  153. honeybee_energy/ventcool/fan.py +493 -0
  154. honeybee_energy/ventcool/opening.py +365 -0
  155. honeybee_energy/ventcool/simulation.py +314 -0
  156. honeybee_energy/writer.py +1078 -0
  157. honeybee_energy-1.116.106.dist-info/METADATA +113 -0
  158. honeybee_energy-1.116.106.dist-info/RECORD +162 -0
  159. honeybee_energy-1.116.106.dist-info/WHEEL +5 -0
  160. honeybee_energy-1.116.106.dist-info/entry_points.txt +2 -0
  161. honeybee_energy-1.116.106.dist-info/licenses/LICENSE +661 -0
  162. honeybee_energy-1.116.106.dist-info/top_level.txt +1 -0
@@ -0,0 +1,270 @@
1
+ # coding=utf-8
2
+ """Base class for HVAC systems following a template from the OpenStudio standards gem."""
3
+ from __future__ import division
4
+
5
+ from ._base import _HVACSystem
6
+
7
+ from honeybee._lockable import lockable
8
+ from honeybee.typing import valid_ep_string
9
+
10
+ import os
11
+ import importlib
12
+
13
+
14
+ @lockable
15
+ class _TemplateSystem(_HVACSystem):
16
+ """Base class for HVAC systems following a standards template.
17
+
18
+ Args:
19
+ identifier: Text string for system identifier. Must be < 100 characters
20
+ and not contain any EnergyPlus special characters. This will be used to
21
+ identify the object across a model and in the exported IDF.
22
+ vintage: Text for the vintage of the template system. This will be used
23
+ to set efficiencies for various pieces of equipment within the system.
24
+ Choose from the following.
25
+
26
+ * DOE_Ref_Pre_1980
27
+ * DOE_Ref_1980_2004
28
+ * ASHRAE_2004
29
+ * ASHRAE_2007
30
+ * ASHRAE_2010
31
+ * ASHRAE_2013
32
+ * ASHRAE_2016
33
+ * ASHRAE_2019
34
+
35
+ equipment_type: Text for the specific type of the system and equipment.
36
+ For example, 'VAV chiller with gas boiler reheat'.
37
+
38
+ Properties:
39
+ * identifier
40
+ * display_name
41
+ * vintage
42
+ * equipment_type
43
+ * schedules
44
+ * has_district_heating
45
+ * has_district_cooling
46
+ * user_data
47
+ """
48
+ __slots__ = ('_vintage', '_equipment_type')
49
+
50
+ VINTAGES = ('DOE_Ref_Pre_1980', 'DOE_Ref_1980_2004', 'ASHRAE_2004', 'ASHRAE_2007',
51
+ 'ASHRAE_2010', 'ASHRAE_2013', 'ASHRAE_2016', 'ASHRAE_2019')
52
+ EQUIPMENT_TYPES = ('Inferred',)
53
+
54
+ def __init__(self, identifier, vintage='ASHRAE_2019', equipment_type=None):
55
+ """Initialize HVACSystem."""
56
+ # initialize base HVAC system properties
57
+ _HVACSystem.__init__(self, identifier)
58
+ self.vintage = vintage
59
+ self.equipment_type = equipment_type
60
+
61
+ @property
62
+ def vintage(self):
63
+ """Get or set text to indicate the vintage of the template system.
64
+
65
+ Choose from the following options:
66
+
67
+ * DOE_Ref_Pre_1980
68
+ * DOE_Ref_1980_2004
69
+ * ASHRAE_2004
70
+ * ASHRAE_2007
71
+ * ASHRAE_2010
72
+ * ASHRAE_2013
73
+ * ASHRAE_2016
74
+ * ASHRAE_2019
75
+ """
76
+ return self._vintage
77
+
78
+ @vintage.setter
79
+ def vintage(self, value):
80
+ clean_input = valid_ep_string(value).lower()
81
+ for key in self.VINTAGES:
82
+ if key.lower() == clean_input:
83
+ value = key
84
+ break
85
+ else:
86
+ raise ValueError(
87
+ 'Template HVAC vintage "{}" is not recognized.\nChoose from the '
88
+ 'following:\n{}'.format(value, self.VINTAGES))
89
+ self._vintage = value
90
+
91
+ @property
92
+ def equipment_type(self):
93
+ """Get or set text for the system's equipment specification.
94
+
95
+ For example, 'VAV chiller with gas boiler reheat'.
96
+ """
97
+ return self._equipment_type
98
+
99
+ @equipment_type.setter
100
+ def equipment_type(self, value):
101
+ if value is not None:
102
+ clean_input = valid_ep_string(value).lower()
103
+ for key in self.EQUIPMENT_TYPES:
104
+ if key.lower() == clean_input:
105
+ value = key
106
+ break
107
+ else:
108
+ raise ValueError(
109
+ 'HVAC equipment_type "{}" is not supported for {}.\n'
110
+ 'Choose from the following:\n{}'.format(
111
+ value, self.__class__.__name__, '\n'.join(self.EQUIPMENT_TYPES)))
112
+ self._equipment_type = value
113
+ else:
114
+ self._equipment_type = self.EQUIPMENT_TYPES[0]
115
+
116
+ @property
117
+ def has_district_heating(self):
118
+ """Get a boolean for whether the HVAC system has district heating."""
119
+ return self._equipment_type is not None and 'DHW' in self._equipment_type
120
+
121
+ @property
122
+ def has_district_cooling(self):
123
+ """Get a boolean for whether the HVAC system has district cooling."""
124
+ return self._equipment_type is not None and 'DCW' in self._equipment_type
125
+
126
+ @classmethod
127
+ def from_dict(cls, data):
128
+ """Create a HVAC object from a dictionary.
129
+
130
+ Args:
131
+ data: A HVAC dictionary in following the format below.
132
+
133
+ .. code-block:: python
134
+
135
+ {
136
+ "type": "", # text for the class name of the HVAC
137
+ "identifier": "Classroom1_System", # identifier for the HVAC
138
+ "display_name": "Standard System", # name for the HVAC
139
+ "vintage": "ASHRAE_2019", # text for the vintage of the template
140
+ "equipment_type": "" # text for the HVAC equipment type
141
+ }
142
+ """
143
+ assert data['type'] == cls.__name__, \
144
+ 'Expected {} dictionary. Got {}.'.format(cls.__name__, data['type'])
145
+ new_obj = cls(data['identifier'], data['vintage'], data['equipment_type'])
146
+ if 'display_name' in data and data['display_name'] is not None:
147
+ new_obj.display_name = data['display_name']
148
+ if 'user_data' in data and data['user_data'] is not None:
149
+ new_obj.user_data = data['user_data']
150
+ return new_obj
151
+
152
+ @classmethod
153
+ def from_dict_abridged(cls, data, schedule_dict):
154
+ """Create a HVAC object from an abridged dictionary.
155
+
156
+ Args:
157
+ data: An abridged dictionary in following the format below.
158
+ schedule_dict: A dictionary with schedule identifiers as keys and honeybee
159
+ schedule objects as values (either ScheduleRuleset or
160
+ ScheduleFixedInterval). These will be used to assign the schedules
161
+ to the Setpoint object.
162
+
163
+ .. code-block:: python
164
+
165
+ {
166
+ "type": "", # text for the class name of the HVAC
167
+ "identifier": "Classroom1_System", # identifier for the HVAC
168
+ "display_name": "Standard System", # name for the HVAC
169
+ "vintage": "ASHRAE_2019", # text for the vintage of the template
170
+ "equipment_type": "" # text for the HVAC equipment type
171
+ }
172
+ """
173
+ # this is the same as the from_dict method for as long as there are not schedules
174
+ return cls.from_dict(data)
175
+
176
+ def to_dict(self, abridged=False):
177
+ """All air system dictionary representation.
178
+
179
+ Args:
180
+ abridged: Boolean to note whether the full dictionary describing the
181
+ object should be returned (False) or just an abridged version (True).
182
+ This input currently has no effect but may eventually have one if
183
+ schedule-type properties are exposed on this template.
184
+ """
185
+ base = {'type': self.__class__.__name__}
186
+ base['identifier'] = self.identifier
187
+ if self._display_name is not None:
188
+ base['display_name'] = self.display_name
189
+ base['vintage'] = self.vintage
190
+ base['equipment_type'] = self.equipment_type
191
+ if self._user_data is not None:
192
+ base['user_data'] = self.user_data
193
+ return base
194
+
195
+ def __copy__(self):
196
+ new_obj = self.__class__(self.identifier, self.vintage, self.equipment_type)
197
+ new_obj._display_name = self._display_name
198
+ new_obj._user_data = None if self._user_data is None else self._user_data.copy()
199
+ return new_obj
200
+
201
+ def __key(self):
202
+ """A tuple based on the object properties, useful for hashing."""
203
+ return (self._identifier, self._vintage, self._equipment_type)
204
+
205
+ def __hash__(self):
206
+ return hash(self.__key())
207
+
208
+ def __eq__(self, other):
209
+ return isinstance(other, self.__class__) and self.__key() == other.__key()
210
+
211
+ def __ne__(self, other):
212
+ return not self.__eq__(other)
213
+
214
+ def __repr__(self):
215
+ return '{}: {} [type: {}] [vintage: {}]'.format(
216
+ self.__class__.__name__, self.display_name,
217
+ self.equipment_type, self.vintage)
218
+
219
+
220
+ class _EnumerationBase(object):
221
+ """Enumerates the systems that inherit from a given template class."""
222
+
223
+ def __init__(self):
224
+ pass # this class is only intended to be used in child objects
225
+
226
+ @property
227
+ def types(self):
228
+ """A tuple indicating the currently supported HVAC types."""
229
+ return tuple(sorted(self._HVAC_TYPES.keys()))
230
+
231
+ @property
232
+ def equipment_types(self):
233
+ """A tuple indicating the supported equipment types."""
234
+ return tuple(sorted(self._EQUIPMENT_TYPES.keys()))
235
+
236
+ @property
237
+ def types_dict(self):
238
+ """A dictionary containing pointers to the classes of each HVAC type.
239
+
240
+ The keys of this dictionary are the names of the HVAC classes (eg. 'FCU').
241
+ """
242
+ return self._HVAC_TYPES
243
+
244
+ @property
245
+ def equipment_types_dict(self):
246
+ """A dictionary containing pointers to the classes of each equipment type.
247
+
248
+ The keys of this dictionary are the names of the HVAC systems as they
249
+ appear in the OpenStudio standards gem and include the specific equipment
250
+ in the system (eg. 'DOAS with fan coil chiller with boiler').
251
+ """
252
+ return self._EQUIPMENT_TYPES
253
+
254
+ @staticmethod
255
+ def _import_modules(root_dir, base_package):
256
+ """Import all of the modules in the root_dir.
257
+
258
+ Args:
259
+ root_dir: The directory from which modules will be imported.
260
+ base_package: Text for the start of the import statement
261
+ (eg. 'honeybee_energy.hvac.heatcool').
262
+ """
263
+ exclude = ('__init__.py', '_base.py')
264
+ modules = [mod for mod in os.listdir(root_dir)
265
+ if mod not in exclude]
266
+ modules = [os.path.join(root_dir, mod) for mod in modules]
267
+ importable = ['.{}'.format(os.path.basename(f)[:-3]) for f in modules
268
+ if os.path.isfile(f) and f.endswith('.py')]
269
+ for mod in importable:
270
+ importlib.import_module(mod, base_package)
@@ -0,0 +1,22 @@
1
+ """Template All-air HVAC definitions.
2
+
3
+ All-air systems provide both ventilation and heating + cooling demand with
4
+ the same stream of warm/cool air. As such, they often grant tight control
5
+ over zone humidity. However, because such systems often involve the
6
+ cooling of air only to reheat it again, they are often more energy intensive
7
+ than systems that separate ventilation from the meeting of thermal loads.
8
+
9
+ Properties:
10
+ * HVAC_TYPES_DICT: A dictionary containing pointers to the classes of each
11
+ HVAC system. The keys of this dictionary are the names of the HVAC
12
+ classes (eg. 'VAV').
13
+ * EQUIPMENT_TYPES_DICT: A dictionary containing pointers to the classes of
14
+ the HVAC systems. The keys of this dictionary are the names of the HVAC
15
+ systems as they appear in the OpenStudio standards gem and include the
16
+ specific equipment in the system (eg. 'VAV chiller with gas boiler reheat').
17
+ """
18
+ from ._base import _AllAirEnumeration
19
+
20
+ _all_air_types = _AllAirEnumeration(import_modules=True)
21
+ HVAC_TYPES_DICT = _all_air_types.types_dict
22
+ EQUIPMENT_TYPES_DICT = _all_air_types.equipment_types_dict
@@ -0,0 +1,349 @@
1
+ # coding=utf-8
2
+ """Base class for All-Air HVAC systems."""
3
+ from __future__ import division
4
+ import os
5
+
6
+ from honeybee._lockable import lockable
7
+ from honeybee.typing import valid_string, float_in_range
8
+ from honeybee.altnumber import autosize
9
+
10
+ from .._template import _TemplateSystem, _EnumerationBase
11
+ from ..idealair import IdealAirSystem
12
+ from ...properties.extension import AllAirSystemProperties
13
+
14
+
15
+ @lockable
16
+ class _AllAirBase(_TemplateSystem):
17
+ """Base class for All-Air HVAC systems.
18
+
19
+ Args:
20
+ identifier: Text string for system identifier. Must be < 100 characters
21
+ and not contain any EnergyPlus special characters. This will be used to
22
+ identify the object across a model and in the exported IDF.
23
+ vintage: Text for the vintage of the template system. This will be used
24
+ to set efficiencies for various pieces of equipment within the system.
25
+ Choose from the following.
26
+
27
+ * DOE_Ref_Pre_1980
28
+ * DOE_Ref_1980_2004
29
+ * ASHRAE_2004
30
+ * ASHRAE_2007
31
+ * ASHRAE_2010
32
+ * ASHRAE_2013
33
+ * ASHRAE_2016
34
+ * ASHRAE_2019
35
+
36
+ equipment_type: Text for the specific type of the system and equipment.
37
+ For example, 'VAV chiller with gas boiler reheat'.
38
+ economizer_type: Text to indicate the type of air-side economizer used on
39
+ the system. (Default: NoEconomizer). Choose from the following.
40
+
41
+ * NoEconomizer
42
+ * DifferentialDryBulb
43
+ * DifferentialEnthalpy
44
+ * DifferentialDryBulbAndEnthalpy
45
+ * FixedDryBulb
46
+ * FixedEnthalpy
47
+ * ElectronicEnthalpy
48
+
49
+ sensible_heat_recovery: A number between 0 and 1 for the effectiveness
50
+ of sensible heat recovery within the system. (Default: 0).
51
+ latent_heat_recovery: A number between 0 and 1 for the effectiveness
52
+ of latent heat recovery within the system. (Default: 0).
53
+ demand_controlled_ventilation: Boolean to note whether demand controlled
54
+ ventilation should be used on the system, which will vary the amount
55
+ of ventilation air according to the occupancy schedule of the
56
+ Rooms. (Default: False).
57
+
58
+ Properties:
59
+ * identifier
60
+ * display_name
61
+ * vintage
62
+ * equipment_type
63
+ * economizer_type
64
+ * sensible_heat_recovery
65
+ * latent_heat_recovery
66
+ * demand_controlled_ventilation
67
+ * schedules
68
+ * has_district_heating
69
+ * has_district_cooling
70
+ * user_data
71
+ * properties
72
+ """
73
+ __slots__ = ('_economizer_type', '_sensible_heat_recovery', '_latent_heat_recovery',
74
+ '_demand_controlled_ventilation', '_properties')
75
+ ECONOMIZER_TYPES = ('NoEconomizer', 'DifferentialDryBulb', 'DifferentialEnthalpy',
76
+ 'DifferentialDryBulbAndEnthalpy', 'FixedDryBulb',
77
+ 'FixedEnthalpy', 'ElectronicEnthalpy')
78
+ COOL_ONLY_TYPES = ('PSZAC', 'PSZAC_DCW', 'PTAC')
79
+ HEAT_ONLY_TYPES = ('Furnace',)
80
+ _has_air_loop = True
81
+
82
+ def __init__(self, identifier, vintage='ASHRAE_2019', equipment_type=None,
83
+ economizer_type='NoEconomizer',
84
+ sensible_heat_recovery=0, latent_heat_recovery=0,
85
+ demand_controlled_ventilation=False):
86
+ """Initialize HVACSystem."""
87
+ # initialize base HVAC system properties
88
+ _TemplateSystem.__init__(self, identifier, vintage, equipment_type)
89
+
90
+ # set the main features of the HVAC system
91
+ self.economizer_type = economizer_type
92
+ self.sensible_heat_recovery = sensible_heat_recovery
93
+ self.latent_heat_recovery = latent_heat_recovery
94
+ self.demand_controlled_ventilation = demand_controlled_ventilation
95
+ self._properties = AllAirSystemProperties(self)
96
+
97
+ @property
98
+ def economizer_type(self):
99
+ """Get or set text to indicate the type of air-side economizer.
100
+
101
+ Choose from the following options.
102
+
103
+ * NoEconomizer
104
+ * DifferentialDryBulb
105
+ * DifferentialEnthalpy
106
+ * DifferentialDryBulbAndEnthalpy
107
+ * FixedDryBulb
108
+ * FixedEnthalpy
109
+ * ElectronicEnthalpy
110
+ """
111
+ return self._economizer_type
112
+
113
+ @economizer_type.setter
114
+ def economizer_type(self, value):
115
+ clean_input = valid_string(value).lower()
116
+ for key in self.ECONOMIZER_TYPES:
117
+ if key.lower() == clean_input:
118
+ value = key
119
+ break
120
+ else:
121
+ raise ValueError(
122
+ 'economizer_type {} is not recognized.\nChoose from the '
123
+ 'following:\n{}'.format(value, self.ECONOMIZER_TYPES))
124
+ if value != 'NoEconomizer':
125
+ self._air_loop_check('economizer')
126
+ self._economizer_type = value
127
+
128
+ @property
129
+ def sensible_heat_recovery(self):
130
+ """Get or set a number for the effectiveness of sensible heat recovery."""
131
+ return self._sensible_heat_recovery
132
+
133
+ @sensible_heat_recovery.setter
134
+ def sensible_heat_recovery(self, value):
135
+ if value is None or value == 0:
136
+ self._sensible_heat_recovery = 0
137
+ else:
138
+ self._air_loop_check('sensible_heat_recovery')
139
+ self._sensible_heat_recovery = \
140
+ float_in_range(value, 0.0, 1.0, 'hvac sensible heat recovery')
141
+
142
+ @property
143
+ def latent_heat_recovery(self):
144
+ """Get or set a number for the effectiveness of latent heat recovery."""
145
+ return self._latent_heat_recovery
146
+
147
+ @latent_heat_recovery.setter
148
+ def latent_heat_recovery(self, value):
149
+ if value is None or value == 0:
150
+ self._latent_heat_recovery = 0
151
+ else:
152
+ self._air_loop_check('latent_heat_recovery')
153
+ self._latent_heat_recovery = \
154
+ float_in_range(value, 0.0, 1.0, 'hvac latent heat recovery')
155
+
156
+ @property
157
+ def demand_controlled_ventilation(self):
158
+ """Get or set a boolean for whether demand controlled ventilation is present."""
159
+ return self._demand_controlled_ventilation
160
+
161
+ @demand_controlled_ventilation.setter
162
+ def demand_controlled_ventilation(self, value):
163
+ self._demand_controlled_ventilation = bool(value)
164
+ if self._demand_controlled_ventilation:
165
+ self._air_loop_check('demand_controlled_ventilation')
166
+
167
+ @property
168
+ def properties(self):
169
+ """Get properties for extensions."""
170
+ return self._properties
171
+
172
+ @classmethod
173
+ def from_dict(cls, data):
174
+ """Create a HVAC object from a dictionary.
175
+
176
+ Args:
177
+ data: An all-air dictionary in following the format below.
178
+
179
+ .. code-block:: python
180
+
181
+ {
182
+ "type": "", # text for the class name of the HVAC
183
+ "identifier": "Classroom1_System", # identifier for the HVAC
184
+ "display_name": "Standard System", # name for the HVAC
185
+ "vintage": "ASHRAE_2019", # text for the vintage of the template
186
+ "equipment_type": "", # text for the HVAC equipment type
187
+ "economizer_type": 'DifferentialDryBulb', # Economizer type
188
+ "sensible_heat_recovery": 0.75, # Sensible heat recovery effectiveness
189
+ "latent_heat_recovery": 0.7, # Latent heat recovery effectiveness
190
+ "demand_controlled_ventilation": False # Boolean for DCV
191
+ "properties": { ... } # AllAirSystemProperties as a dict
192
+ }
193
+ """
194
+ assert cls.__name__ in data['type'], \
195
+ 'Expected {} dictionary. Got {}.'.format(cls.__name__, data['type'])
196
+ # extract the key features and properties of the HVAC
197
+ econ, sensible, latent, dcv = cls._properties_from_dict(data)
198
+ new_obj = cls(data['identifier'], data['vintage'], data['equipment_type'],
199
+ econ, sensible, latent, dcv)
200
+ if 'display_name' in data and data['display_name'] is not None:
201
+ new_obj.display_name = data['display_name']
202
+ if 'user_data' in data and data['user_data'] is not None:
203
+ new_obj.user_data = data['user_data']
204
+ if 'properties' in data and data['properties'] is not None:
205
+ new_obj.properties._load_extension_attr_from_dict(data['properties'])
206
+ return new_obj
207
+
208
+ @classmethod
209
+ def from_dict_abridged(cls, data, schedule_dict):
210
+ """Create a HVAC object from an abridged dictionary.
211
+
212
+ Args:
213
+ data: An all-air abridged dictionary in following the format below.
214
+ schedule_dict: A dictionary with schedule identifiers as keys and honeybee
215
+ schedule objects as values (either ScheduleRuleset or
216
+ ScheduleFixedInterval). These will be used to assign the schedules
217
+ to the Setpoint object.
218
+
219
+ .. code-block:: python
220
+
221
+ {
222
+ "type": "", # text for the class name of the HVAC
223
+ "identifier": "Classroom1_System", # identifier for the HVAC
224
+ "display_name": "Standard System", # name for the HVAC
225
+ "vintage": "ASHRAE_2013", # text for the vintage of the template
226
+ "equipment_type": "", # text for the HVAC equipment type
227
+ "economizer_type": 'DifferentialDryBulb', # Economizer type
228
+ "sensible_heat_recovery": 0.75, # Sensible heat recovery effectiveness
229
+ "latent_heat_recovery": 0.7, # Latent heat recovery effectiveness
230
+ "demand_controlled_ventilation": False # Boolean for DCV
231
+ "properties": { ... } # dict of the AllAirSystemProperties
232
+ }
233
+ """
234
+ # this is the same as the from_dict method for as long as there are not schedules
235
+ return cls.from_dict(data)
236
+
237
+ def to_dict(self, abridged=False):
238
+ """All air system dictionary representation.
239
+
240
+ Args:
241
+ abridged: Boolean to note whether the full dictionary describing the
242
+ object should be returned (False) or just an abridged version (True).
243
+ This input currently has no effect but may eventually have one if
244
+ schedule-type properties are exposed on this template.
245
+ """
246
+ base = {'type': self.__class__.__name__}
247
+ base['identifier'] = self.identifier
248
+ if self._display_name is not None:
249
+ base['display_name'] = self.display_name
250
+ base['vintage'] = self.vintage
251
+ base['equipment_type'] = self.equipment_type
252
+ if self.economizer_type != 'NoEconomizer':
253
+ base['economizer_type'] = self.economizer_type
254
+ if self.sensible_heat_recovery != 0:
255
+ base['sensible_heat_recovery'] = self.sensible_heat_recovery
256
+ if self.latent_heat_recovery != 0:
257
+ base['latent_heat_recovery'] = self.latent_heat_recovery
258
+ base['demand_controlled_ventilation'] = self.demand_controlled_ventilation
259
+ if self._user_data is not None:
260
+ base['user_data'] = self.user_data
261
+ prop_dict = self.properties.to_dict()
262
+ if prop_dict is not None:
263
+ base['properties'] = prop_dict
264
+ return base
265
+
266
+ def to_ideal_air_equivalent(self):
267
+ """Get a version of this HVAC as an IdealAirSystem.
268
+
269
+ Relevant properties will be transferred to the resulting ideal air such as
270
+ economizer_type, sensible_heat_recovery, latent_heat_recovery, and
271
+ demand_controlled_ventilation.
272
+ """
273
+ econ_typ = self.economizer_type
274
+ if econ_typ not in self.ECONOMIZER_TYPES[:3]:
275
+ enth_types = ('FixedEnthalpy', 'ElectronicEnthalpy')
276
+ econ_typ = 'DifferentialEnthalpy' if econ_typ in enth_types \
277
+ else 'DifferentialDryBulb'
278
+ i_sys = IdealAirSystem(
279
+ self.identifier, economizer_type=econ_typ,
280
+ sensible_heat_recovery=self.sensible_heat_recovery,
281
+ latent_heat_recovery=self.latent_heat_recovery,
282
+ demand_controlled_ventilation=self.demand_controlled_ventilation)
283
+ if self.equipment_type in self.COOL_ONLY_TYPES:
284
+ i_sys.heating_limit = 0
285
+ if self.equipment_type in self.HEAT_ONLY_TYPES:
286
+ i_sys.cooling_limit = 0
287
+ i_sys._display_name = self._display_name
288
+ return i_sys
289
+
290
+ def _air_loop_check(self, prop_name):
291
+ """Check whether the system has an air loop and rase an error if not."""
292
+ assert self._has_air_loop, \
293
+ 'HVAC system must have an air loop to assign {}.'.format(prop_name)
294
+
295
+ @staticmethod
296
+ def _properties_from_dict(data):
297
+ """Extract basic properties from a dictionary and assign defaults."""
298
+ econ = data['economizer_type'] if 'economizer_type' in data and \
299
+ data['economizer_type'] is not None else 'NoEconomizer'
300
+ sensible = data['sensible_heat_recovery'] if \
301
+ 'sensible_heat_recovery' in data else 0
302
+ sensible = sensible if sensible != autosize.to_dict() else 0
303
+ latent = data['latent_heat_recovery'] if \
304
+ 'latent_heat_recovery' in data else 0
305
+ latent = latent if latent != autosize.to_dict() else 0
306
+ dcv = data['demand_controlled_ventilation'] \
307
+ if 'demand_controlled_ventilation' in data else False
308
+ return econ, sensible, latent, dcv
309
+
310
+ def __copy__(self):
311
+ new_obj = self.__class__(
312
+ self._identifier, self._vintage, self._equipment_type, self._economizer_type,
313
+ self._sensible_heat_recovery, self._latent_heat_recovery,
314
+ self._demand_controlled_ventilation)
315
+ new_obj._display_name = self._display_name
316
+ new_obj._user_data = None if self._user_data is None else self._user_data.copy()
317
+ new_obj._properties._duplicate_extension_attr(self._properties)
318
+ return new_obj
319
+
320
+ def __key(self):
321
+ """A tuple based on the object properties, useful for hashing."""
322
+ return (self._identifier, self._vintage, self._equipment_type,
323
+ self._economizer_type, self._sensible_heat_recovery,
324
+ self._latent_heat_recovery, self._demand_controlled_ventilation)
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
+
336
+ class _AllAirEnumeration(_EnumerationBase):
337
+ """Enumerates the systems that inherit from _AllAirBase."""
338
+
339
+ def __init__(self, import_modules=True):
340
+ if import_modules:
341
+ self._import_modules(
342
+ os.path.dirname(__file__), 'honeybee_energy.hvac.allair')
343
+
344
+ self._HVAC_TYPES = {}
345
+ self._EQUIPMENT_TYPES = {}
346
+ for clss in _AllAirBase.__subclasses__():
347
+ self._HVAC_TYPES[clss.__name__] = clss
348
+ for equip_type in clss.EQUIPMENT_TYPES:
349
+ self._EQUIPMENT_TYPES[equip_type] = clss