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,472 @@
1
+ # coding=utf-8
2
+ """Load object used to represent various types of specific processes."""
3
+ from __future__ import division
4
+
5
+ from honeybee._lockable import lockable
6
+ from honeybee.typing import float_in_range, float_positive, valid_string, \
7
+ valid_ep_string
8
+
9
+ from ._base import _LoadBase
10
+ from ..schedule.ruleset import ScheduleRuleset
11
+ from ..schedule.fixedinterval import ScheduleFixedInterval
12
+ from ..reader import parse_idf_string
13
+ from ..writer import generate_idf_string
14
+ from ..properties.extension import ProcessProperties
15
+
16
+
17
+ @lockable
18
+ class Process(_LoadBase):
19
+ """Load object used to represent various types of specific processes.
20
+
21
+ Examples include kilns, manufacturing equipment, and various industrial
22
+ processes. They can also be used to represent wood burning fireplaces
23
+ or certain pieces of equipment to be separated from the other end uses.
24
+
25
+ Args:
26
+ identifier: Text string for a unique Process ID. Must be < 100 characters
27
+ and not contain any EnergyPlus special characters. This will be used to
28
+ identify the object across a model and in the exported IDF.
29
+ watts: A numerical value for the process load power in Watts.
30
+ schedule: A ScheduleRuleset or ScheduleFixedInterval for the use of process
31
+ over the course of the year. The type of this schedule should be
32
+ Fractional and the fractional values will get multiplied by the
33
+ watts to yield a complete process load profile.
34
+ fuel_type: Text to denote the type of fuel consumed by the process.
35
+ Using the "None" type indicates that no end uses will be associated
36
+ with the process, only the zone gains. Choose from the following.
37
+
38
+ * Electricity
39
+ * NaturalGas
40
+ * Propane
41
+ * FuelOilNo1
42
+ * FuelOilNo2
43
+ * Diesel
44
+ * Gasoline
45
+ * Coal
46
+ * Steam
47
+ * DistrictHeating
48
+ * DistrictCooling
49
+ * OtherFuel1
50
+ * OtherFuel2
51
+ * None
52
+
53
+ end_use_category: Text to indicate the end-use subcategory, which will identify
54
+ the process load in the output end use table. Examples include
55
+ “Cooking”, “Clothes Drying”, etc. Setting this to "General" will
56
+ result in the process load being reported as part of the other Interior
57
+ Equipment. (Default: Process).
58
+ radiant_fraction: A number between 0 and 1 for the fraction of the total
59
+ load given off as long wave radiant heat. (Default: 0).
60
+ latent_fraction: A number between 0 and 1 for the fraction of the total
61
+ load that is latent (as opposed to sensible). (Default: 0).
62
+ lost_fraction: A number between 0 and 1 for the fraction of the total
63
+ load that is lost outside of the zone and the HVAC system.
64
+ Typically, this is used to represent heat that is exhausted directly
65
+ out of a zone (as you would for a stove). (Default: 0).
66
+
67
+ Properties:
68
+ * identifier
69
+ * display_name
70
+ * watts
71
+ * schedule
72
+ * fuel_type
73
+ * end_use_category
74
+ * radiant_fraction
75
+ * latent_fraction
76
+ * lost_fraction
77
+ * convected_fraction
78
+ * user_data
79
+ """
80
+ __slots__ = ('_watts', '_schedule', '_fuel_type', '_end_use_category',
81
+ '_radiant_fraction', '_latent_fraction', '_lost_fraction')
82
+ FUEL_TYPES = (
83
+ 'Electricity',
84
+ 'NaturalGas',
85
+ 'Propane',
86
+ 'FuelOilNo1',
87
+ 'FuelOilNo2',
88
+ 'Diesel',
89
+ 'Gasoline',
90
+ 'Coal',
91
+ 'Steam',
92
+ 'DistrictHeating',
93
+ 'DistrictCooling',
94
+ 'OtherFuel1',
95
+ 'OtherFuel2',
96
+ 'None'
97
+ )
98
+
99
+ def __init__(self, identifier, watts, schedule, fuel_type,
100
+ end_use_category='Process', radiant_fraction=0,
101
+ latent_fraction=0, lost_fraction=0):
102
+ """Initialize Process."""
103
+ _LoadBase.__init__(self, identifier)
104
+ self._latent_fraction = 0 # starting value so that check runs correctly
105
+ self._lost_fraction = 0 # starting value so that check runs correctly
106
+
107
+ self.watts = watts
108
+ self.schedule = schedule
109
+ self.fuel_type = fuel_type
110
+ self.end_use_category = end_use_category
111
+ self.radiant_fraction = radiant_fraction
112
+ self.latent_fraction = latent_fraction
113
+ self.lost_fraction = lost_fraction
114
+ self._properties = ProcessProperties(self)
115
+
116
+ @property
117
+ def watts(self):
118
+ """Get or set the process total power in Watts."""
119
+ return self._watts
120
+
121
+ @watts.setter
122
+ def watts(self, value):
123
+ self._watts = float_positive(value, 'process watts')
124
+
125
+ @property
126
+ def schedule(self):
127
+ """Get or set a ScheduleRuleset or ScheduleFixedInterval for process usage."""
128
+ return self._schedule
129
+
130
+ @schedule.setter
131
+ def schedule(self, value):
132
+ assert isinstance(value, (ScheduleRuleset, ScheduleFixedInterval)), \
133
+ 'Expected ScheduleRuleset or ScheduleFixedInterval for process ' \
134
+ 'schedule. Got {}.'.format(type(value))
135
+ self._check_fractional_schedule_type(value, 'Equipment')
136
+ value.lock() # lock editing in case schedule has multiple references
137
+ self._schedule = value
138
+
139
+ @property
140
+ def fuel_type(self):
141
+ """Get or set text to denote the type of fuel consumed by the process.
142
+
143
+ Choose from the following options.
144
+
145
+ * Electricity
146
+ * NaturalGas
147
+ * Propane
148
+ * FuelOilNo1
149
+ * FuelOilNo2
150
+ * Diesel
151
+ * Gasoline
152
+ * Coal
153
+ * Steam
154
+ * DistrictHeating
155
+ * DistrictCooling
156
+ * OtherFuel1
157
+ * OtherFuel2
158
+ * None
159
+ """
160
+ return self._fuel_type
161
+
162
+ @fuel_type.setter
163
+ def fuel_type(self, value):
164
+ clean_input = valid_string(value).lower()
165
+ for key in self.FUEL_TYPES:
166
+ if key.lower() == clean_input:
167
+ value = key
168
+ break
169
+ else:
170
+ raise ValueError(
171
+ 'fuel_type {} is not recognized.\nChoose from the '
172
+ 'following:\n{}'.format(value, '\n'.join(self.FUEL_TYPES)))
173
+ self._fuel_type = value
174
+
175
+ @property
176
+ def end_use_category(self):
177
+ """Get or set text to indicate the end-use subcategory."""
178
+ return self._end_use_category
179
+
180
+ @end_use_category.setter
181
+ def end_use_category(self, value):
182
+ self._end_use_category = valid_ep_string(value)
183
+
184
+ @property
185
+ def radiant_fraction(self):
186
+ """Get or set the fraction of process heat given off as long wave radiation."""
187
+ return self._radiant_fraction
188
+
189
+ @radiant_fraction.setter
190
+ def radiant_fraction(self, value):
191
+ self._radiant_fraction = float_in_range(
192
+ value, 0.0, 1.0, 'process radiant fraction')
193
+ self._check_fractions()
194
+
195
+ @property
196
+ def latent_fraction(self):
197
+ """Get or set the fraction of process heat that is latent."""
198
+ return self._latent_fraction
199
+
200
+ @latent_fraction.setter
201
+ def latent_fraction(self, value):
202
+ self._latent_fraction = float_in_range(
203
+ value, 0.0, 1.0, 'process latent fraction')
204
+ self._check_fractions()
205
+
206
+ @property
207
+ def lost_fraction(self):
208
+ """Get or set the fraction of process heat that is lost out of the zone."""
209
+ return self._lost_fraction
210
+
211
+ @lost_fraction.setter
212
+ def lost_fraction(self, value):
213
+ self._lost_fraction = float_in_range(
214
+ value, 0.0, 1.0, 'process lost fraction')
215
+ self._check_fractions()
216
+
217
+ @property
218
+ def convected_fraction(self):
219
+ """Get the fraction of process heat that convects to the zone air."""
220
+ return 1 - sum((self._radiant_fraction, self._latent_fraction,
221
+ self._lost_fraction))
222
+
223
+ @classmethod
224
+ def from_idf(cls, idf_string, schedule_dict):
225
+ """Create a Process object from an EnergyPlus OtherEquipment IDF text string.
226
+
227
+ Note that the OtherEquipment idf_string must use the 'equipment level'
228
+ method in order to be successfully imported.
229
+
230
+ Args:
231
+ idf_string: A text string fully describing an EnergyPlus
232
+ OtherEquipment definition.
233
+ schedule_dict: A dictionary with schedule identifiers as keys and honeybee
234
+ schedule objects as values (either ScheduleRuleset or
235
+ ScheduleFixedInterval). These will be used to assign the schedules to
236
+ the OtherEquipment object.
237
+
238
+ Returns:
239
+ A tuple with two elements
240
+
241
+ - process: An Process object loaded from the idf_string.
242
+
243
+ - zone_identifier: The identifier of the zone to which the
244
+ Process object should be assigned.
245
+ """
246
+ # check the inputs
247
+ ep_strs = parse_idf_string(idf_string, 'OtherEquipment,')
248
+ # check the inputs
249
+ if len(ep_strs) > 4:
250
+ assert ep_strs[4].lower() == 'equipmentlevel', 'Equipment must use ' \
251
+ 'Watts/Area method to be loaded from IDF to honeybee.'
252
+ # extract the properties from the string
253
+ watts = 0
254
+ rad_fract = 0
255
+ lat_fract = 0
256
+ lost_fract = 0
257
+ cat = 'General'
258
+ try:
259
+ watts = ep_strs[5] if ep_strs[5] != '' else 0
260
+ lat_fract = ep_strs[8] if ep_strs[8] != '' else 0
261
+ rad_fract = ep_strs[9] if ep_strs[9] != '' else 0
262
+ lost_fract = ep_strs[10] if ep_strs[10] != '' else 0
263
+ cat = ep_strs[12] if ep_strs[12] != '' else 'General'
264
+ except IndexError:
265
+ pass # shorter equipment definition lacking fractions
266
+ # extract the schedules from the string
267
+ try:
268
+ sched = schedule_dict[ep_strs[3]]
269
+ except KeyError as e:
270
+ raise ValueError('Failed to find {} in the schedule_dict.'.format(e))
271
+
272
+ # return the equipment object and the zone identifier for the equip object
273
+ obj_id = ep_strs[0].split('..')[0]
274
+ fuel = ep_strs[1] if ep_strs[1] != '' else 'None'
275
+ zone_id = ep_strs[2]
276
+ equipment = cls(obj_id, watts, sched, fuel, cat,
277
+ rad_fract, lat_fract, lost_fract)
278
+ return equipment, zone_id
279
+
280
+ @classmethod
281
+ def from_dict(cls, data):
282
+ """Create a Process object from a dictionary.
283
+
284
+ Note that the dictionary must be a non-abridged version for this classmethod
285
+ to work.
286
+
287
+ Args:
288
+ data: A Process dictionary in following the format below.
289
+
290
+ .. code-block:: python
291
+
292
+ {
293
+ "type": 'Process',
294
+ "identifier": 'Wood_Burning_Fireplace_500_03',
295
+ "display_name": 'Hearth',
296
+ "watts": 500, # watts consumed by the process
297
+ "schedule": {}, # ScheduleRuleset/ScheduleFixedInterval dictionary
298
+ "fuel_type": 'OtherFuel1', # Text for the fuel type
299
+ "end_use_category": "Fireplaces", # Text for the end use category
300
+ "radiant_fraction": 0.4, # fraction of heat that is long wave radiant
301
+ "latent_fraction": 0, # fraction of heat that is latent
302
+ "lost_fraction": 0.5 # fraction of heat that is lost
303
+ }
304
+ """
305
+ cat, rad_f, lat_f, lost_f = cls._extract_dict_props(data, 'Process')
306
+ sched = cls._get_schedule_from_dict(data['schedule'])
307
+ new_obj = cls(data['identifier'], data['watts'], sched, data['fuel_type'],
308
+ cat, rad_f, lat_f, lost_f)
309
+ if 'display_name' in data and data['display_name'] is not None:
310
+ new_obj.display_name = data['display_name']
311
+ if 'user_data' in data and data['user_data'] is not None:
312
+ new_obj.user_data = data['user_data']
313
+ if 'properties' in data and data['properties'] is not None:
314
+ new_obj.properties._load_extension_attr_from_dict(data['properties'])
315
+ return new_obj
316
+
317
+ @classmethod
318
+ def from_dict_abridged(cls, data, schedule_dict):
319
+ """Create a Process object from an abridged dictionary.
320
+
321
+ Args:
322
+ data: A ProcessAbridged dictionary in following the format below.
323
+ schedule_dict: A dictionary with schedule identifiers as keys and honeybee
324
+ schedule objects as values (either ScheduleRuleset or
325
+ ScheduleFixedInterval). These will be used to assign the schedules
326
+ to the equipment object.
327
+
328
+ .. code-block:: python
329
+
330
+ {
331
+ "type": 'ProcessAbridged',
332
+ "identifier": 'Wood_Burning_Fireplace_500_03',
333
+ "display_name": 'Hearth',
334
+ "watts": 500, # watts consumed by the process
335
+ "schedule": "Fireplace Usage Schedule", # Schedule identifier
336
+ "fuel_type": 'OtherFuel1', # Text for the fuel type
337
+ "end_use_category": "Fireplaces", # Text for the end use category
338
+ "radiant_fraction": 0.4, # fraction of heat that is long wave radiant
339
+ "latent_fraction": 0, # fraction of heat that is latent
340
+ "lost_fraction": 0.5 # fraction of heat that is lost
341
+ }
342
+ """
343
+ cat, rad_f, lat_f, lost_f = cls._extract_dict_props(data, 'ProcessAbridged')
344
+ try:
345
+ sched = schedule_dict[data['schedule']]
346
+ except KeyError as e:
347
+ raise ValueError('Failed to find {} in the schedule_dict.'.format(e))
348
+ new_obj = cls(data['identifier'], data['watts'], sched, data['fuel_type'],
349
+ cat, rad_f, lat_f, lost_f)
350
+ if 'display_name' in data and data['display_name'] is not None:
351
+ new_obj.display_name = data['display_name']
352
+ if 'user_data' in data and data['user_data'] is not None:
353
+ new_obj.user_data = data['user_data']
354
+ if 'properties' in data and data['properties'] is not None:
355
+ new_obj.properties._load_extension_attr_from_dict(data['properties'])
356
+ return new_obj
357
+
358
+ def to_idf(self, zone_identifier):
359
+ """IDF string representation of Process object.
360
+
361
+ Note that this method only outputs a single string for the Process
362
+ object and, to write everything needed to describe the object into an IDF,
363
+ this object's schedule must also be written.
364
+
365
+ Args:
366
+ zone_identifier: Text for the zone identifier that the Process
367
+ object is assigned to.
368
+
369
+ .. code-block:: shell
370
+
371
+ OtherEquipment,
372
+ BASE-1 OthEq 1, !- Name
373
+ Propane, !- Fuel Use Type
374
+ BASE-1, !- Zone or ZoneList or Space or SpaceList Name
375
+ ALWAYSON, !- SCHEDULE Name
376
+ EquipmentLevel, !- Design Level calculation method
377
+ 6766., !- Design Level {W}
378
+ , !- Power per Zone Floor Area {watts/m2}
379
+ , !- Power per Person {watts/person}
380
+ 0, !- Fraction Latent
381
+ 0.3, !- Fraction Radiant
382
+ 0, !- Fraction Lost
383
+ 1.2E-7, !- Carbon Dioxide Generation Rate
384
+ SubCategory1; !- End-Use Subcategory
385
+ """
386
+ _idf_comments = (
387
+ 'name', 'fuel type', 'zone name', 'schedule name', 'level method',
388
+ 'power level {W}', 'power per floor area {W/m2}',
389
+ 'power per person {W/ppl}', 'latent fraction', 'radiant fraction',
390
+ 'lost fraction', 'co2 generation {m3/s-W', 'end use subcategory'
391
+ )
392
+ _idf_values = (
393
+ '{}..{}'.format(self.identifier, zone_identifier), self.fuel_type,
394
+ zone_identifier, self.schedule.identifier, 'EquipmentLevel', self.watts,
395
+ '', '', self.latent_fraction, self.radiant_fraction, self.lost_fraction,
396
+ '', self.end_use_category
397
+ )
398
+ return generate_idf_string('OtherEquipment', _idf_values, _idf_comments)
399
+
400
+ def to_dict(self, abridged=False):
401
+ """Process dictionary representation.
402
+
403
+ Args:
404
+ abridged: Boolean to note whether the full dictionary describing the
405
+ object should be returned (False) or just an abridged version (True),
406
+ which only specifies the identifiers of schedules. (Default: False).
407
+ """
408
+ base = {'type': 'Process'} if not abridged else {'type': 'ProcessAbridged'}
409
+ base['identifier'] = self.identifier
410
+ base['watts'] = self.watts
411
+ base['schedule'] = self.schedule.to_dict() if not \
412
+ abridged else self.schedule.identifier
413
+ base['fuel_type'] = self.fuel_type
414
+ base['end_use_category'] = self.end_use_category
415
+ base['radiant_fraction'] = self.radiant_fraction
416
+ base['radiant_fraction'] = self.radiant_fraction
417
+ base['latent_fraction'] = self.latent_fraction
418
+ base['lost_fraction'] = self.lost_fraction
419
+ if self._display_name is not None:
420
+ base['display_name'] = self.display_name
421
+ if self._user_data is not None:
422
+ base['user_data'] = self.user_data
423
+ prop_dict = self.properties.to_dict()
424
+ if prop_dict is not None:
425
+ base['properties'] = prop_dict
426
+ return base
427
+
428
+ def _check_fractions(self):
429
+ tot = (self._radiant_fraction, self._latent_fraction, self._lost_fraction)
430
+ assert sum(tot) <= 1 + 1e-9, 'Sum of process radiant_fraction, ' \
431
+ 'latent_fraction and lost_fraction ({}) is greater than 1.'.format(sum(tot))
432
+
433
+ @staticmethod
434
+ def _extract_dict_props(data, expected_type):
435
+ """Extract relevant properties from an equipment dictionary."""
436
+ assert data['type'] == expected_type, \
437
+ 'Expected {} dictionary. Got {}.'.format(expected_type, data['type'])
438
+ category = data['end_use_category'] if 'end_use_category' in data else 'Process'
439
+ rad_fract = data['radiant_fraction'] if 'radiant_fraction' in data else 0
440
+ lat_fract = data['latent_fraction'] if 'latent_fraction' in data else 0
441
+ lost_fract = data['lost_fraction'] if 'lost_fraction' in data else 0
442
+ return category, rad_fract, lat_fract, lost_fract
443
+
444
+ def __key(self):
445
+ """A tuple based on the object properties, useful for hashing."""
446
+ return (self.identifier, self.watts, hash(self.schedule), self.fuel_type,
447
+ self.end_use_category, self.radiant_fraction, self.latent_fraction,
448
+ self.lost_fraction)
449
+
450
+ def __hash__(self):
451
+ return hash(self.__key())
452
+
453
+ def __eq__(self, other):
454
+ return isinstance(other, Process) and self.__key() == other.__key()
455
+
456
+ def __ne__(self, other):
457
+ return not self.__eq__(other)
458
+
459
+ def __copy__(self):
460
+ new_obj = Process(
461
+ self.identifier, self.watts, self.schedule, self.fuel_type,
462
+ self.end_use_category, self.radiant_fraction, self.latent_fraction,
463
+ self.lost_fraction)
464
+ new_obj._display_name = self._display_name
465
+ new_obj._user_data = None if self._user_data is None else self._user_data.copy()
466
+ new_obj._properties._duplicate_extension_attr(self._properties)
467
+ return new_obj
468
+
469
+ def __repr__(self):
470
+ return 'Process: {} [{} W] [schedule: {}] [fuel: {}]'.format(
471
+ self.display_name, round(self.watts, 1), self.schedule.display_name,
472
+ self.fuel_type)