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,244 @@
1
+ # coding: utf-8
2
+ """Extension properties for Honeybee-Energy objects like constructions and schedules.
3
+
4
+ These properties classes can be used to extend the honeybee-energy for
5
+ other purposes. For example, extending the capabilities of constructions for
6
+ embodied carbon or extending schedules and loads for creation of compliance
7
+ reports for certain standards (eg. passive house).
8
+ """
9
+
10
+
11
+ class _EnergyProperties(object):
12
+ """Base class for all Honeybee-Energy Properties classes.
13
+
14
+ Args:
15
+ host: A honeybee-energy object that hosts these properties
16
+ (ie. ScheduleRuleset, OpaqueConstruction, WindowConstruction).
17
+ """
18
+ _exclude = {'host', 'to_dict', 'ToString'}
19
+
20
+ def __init__(self, host):
21
+ """Initialize properties."""
22
+ self._host = host
23
+
24
+ @property
25
+ def host(self):
26
+ """Get the object hosting these properties."""
27
+ return self._host
28
+
29
+ @property
30
+ def _extension_attributes(self):
31
+ return (atr for atr in dir(self) if not atr.startswith('_')
32
+ and atr not in self._exclude)
33
+
34
+ def to_dict(self):
35
+ """Convert properties to dictionary.
36
+
37
+ Will be None if no extension attributes exist.
38
+ """
39
+ base = {'type': self.__class__.__name__}
40
+ for atr in self._extension_attributes:
41
+ var = getattr(self, atr)
42
+ if not hasattr(var, 'to_dict'):
43
+ continue
44
+ try:
45
+ base.update(var.to_dict())
46
+ except Exception as e:
47
+ import traceback
48
+ traceback.print_exc()
49
+ raise Exception('Failed to convert {} to a dict: {}'.format(var, e))
50
+ return base if len(base) != 1 else None
51
+
52
+ def _load_extension_attr_from_dict(self, property_dict):
53
+ """Get attributes for extensions from a dictionary of the properties.
54
+
55
+ This method should be called within the from_dict method of each
56
+ honeybee-energy object. Specifically, this method should be called on
57
+ the host object after it has been created from a dictionary but lacks
58
+ any of the extension attributes in the dictionary.
59
+
60
+ Args:
61
+ property_dict: A dictionary of properties for the object (ie.
62
+ ScheduleRulesetProperties, OpaqueConstructionProperties).
63
+ These will be used to load attributes from the dictionary and
64
+ assign them to the object on which this method is called.
65
+ """
66
+ for atr in self._extension_attributes:
67
+ var = getattr(self, atr)
68
+ if not hasattr(var, 'from_dict'):
69
+ continue
70
+
71
+ atr_prop_dict = property_dict.get(atr, None)
72
+ if not atr_prop_dict:
73
+ # the property_dict possesses no properties for that extension
74
+ continue
75
+ setattr(self, '_' + atr, var.__class__.from_dict(atr_prop_dict, self.host))
76
+
77
+
78
+ def _duplicate_extension_attr(self, original_properties):
79
+ """Duplicate the attributes added by extensions.
80
+
81
+ This method should be called within the duplicate or __copy__ methods of
82
+ each honeybee-energy object after the host object has been duplicated.
83
+ This method only needs to be called on the new (duplicated) host object and
84
+ the extension properties of the original host object should be passed to
85
+ this method as the original_properties.
86
+
87
+ Args:
88
+ original_properties: The properties object of the original host
89
+ object from which the duplicate was derived.
90
+ """
91
+ for atr in self._extension_attributes:
92
+ var = getattr(original_properties, atr)
93
+ if not hasattr(var, 'duplicate'):
94
+ continue
95
+ try:
96
+ setattr(self, '_' + atr, var.duplicate(self.host))
97
+ except Exception as e:
98
+ import traceback
99
+ traceback.print_exc()
100
+ raise Exception('Failed to duplicate {}: {}'.format(var, e))
101
+
102
+ def ToString(self):
103
+ """Overwrite .NET ToString method."""
104
+ return self.__repr__()
105
+
106
+ def __repr__(self):
107
+ """Properties representation."""
108
+ return '{}: {}'.format(self.__class__.__name__, self.host.display_name)
109
+
110
+
111
+ class ScheduleRulesetProperties(_EnergyProperties):
112
+ """ScheduleRuleset properties to be extended by extensions."""
113
+
114
+
115
+ class ScheduleFixedIntervalProperties(_EnergyProperties):
116
+ """ScheduleFixedInterval properties to be extended by extensions."""
117
+
118
+
119
+ class OpaqueConstructionProperties(_EnergyProperties):
120
+ """OpaqueConstruction properties to be extended by extensions."""
121
+
122
+
123
+ class AirBoundaryConstructionProperties(_EnergyProperties):
124
+ """AirBoundaryConstruction properties to be extended by extensions."""
125
+
126
+
127
+ class ShadeConstructionProperties(_EnergyProperties):
128
+ """ShadeConstruction properties to be extended by extensions."""
129
+
130
+
131
+ class WindowConstructionProperties(_EnergyProperties):
132
+ """WindowConstruction properties to be extended by extensions."""
133
+
134
+
135
+ class WindowConstructionShadeProperties(_EnergyProperties):
136
+ """WindowConstructionShade properties to be extended by extensions."""
137
+
138
+
139
+ class ElectricEquipmentProperties(_EnergyProperties):
140
+ """ElectricEquipment properties to be extended by extensions."""
141
+
142
+
143
+ class GasEquipmentProperties(_EnergyProperties):
144
+ """GasEquipment properties to be extended by extensions."""
145
+
146
+
147
+ class ServiceHotWaterProperties(_EnergyProperties):
148
+ """ServiceHotWater properties to be extended by extensions."""
149
+
150
+
151
+ class SHWSystemProperties(_EnergyProperties):
152
+ """SHWSystem (Equipment) properties to be extended by extensions."""
153
+
154
+
155
+ class InfiltrationProperties(_EnergyProperties):
156
+ """Infiltration properties to be extended by extensions."""
157
+
158
+
159
+ class LightingProperties(_EnergyProperties):
160
+ """Lighting properties to be extended by extensions."""
161
+
162
+
163
+ class PeopleProperties(_EnergyProperties):
164
+ """People properties to be extended by extensions."""
165
+
166
+
167
+ class ProcessProperties(_EnergyProperties):
168
+ """Process properties to be extended by extensions."""
169
+
170
+
171
+ class SetpointProperties(_EnergyProperties):
172
+ """Setpoint properties to be extended by extensions."""
173
+
174
+
175
+ class VentilationProperties(_EnergyProperties):
176
+ """Ventilation properties to be extended by extensions."""
177
+
178
+
179
+ class IdealAirSystemProperties(_EnergyProperties):
180
+ """IdealAirSystem properties to be extended by extensions."""
181
+
182
+
183
+ class AllAirSystemProperties(_EnergyProperties):
184
+ """AllAirSystem HVAC properties to be extended by extensions."""
185
+
186
+
187
+ class DOASSystemProperties(_EnergyProperties):
188
+ """DOASSystem HVAC properties to be extended by extensions."""
189
+
190
+
191
+ class HeatCoolSystemProperties(_EnergyProperties):
192
+ """HeatCoolSystem HVAC properties to be extended by extensions."""
193
+
194
+
195
+ class EnergyMaterialProperties(_EnergyProperties):
196
+ """EnergyMaterial properties to be extended by extensions."""
197
+
198
+
199
+ class EnergyMaterialNoMassProperties(_EnergyProperties):
200
+ """EnergyMaterialNoMass properties to be extended by extensions."""
201
+
202
+
203
+ class EnergyMaterialVegetationProperties(_EnergyProperties):
204
+ """EnergyMaterialVegetation properties to be extended by extensions."""
205
+
206
+
207
+ class EnergyWindowMaterialGlazingsProperties(_EnergyProperties):
208
+ """EnergyWindowMaterialGlazing properties to be extended by extensions."""
209
+
210
+
211
+ class EnergyWindowMaterialSimpleGlazSysProperties(_EnergyProperties):
212
+ """EnergyWindowMaterialSimpleGlazSys properties to be extended by extensions."""
213
+
214
+
215
+ class EnergyWindowMaterialGasProperties(_EnergyProperties):
216
+ """EnergyWindowMaterialGas properties to be extended by extensions."""
217
+
218
+
219
+ class EnergyWindowMaterialGasMixtureProperties(_EnergyProperties):
220
+ """EnergyWindowMaterialGasMixture properties to be extended by extensions."""
221
+
222
+
223
+ class EnergyWindowMaterialGasCustomProperties(_EnergyProperties):
224
+ """EnergyWindowMaterialGasCustom properties to be extended by extensions."""
225
+
226
+
227
+ class EnergyWindowFrameProperties(_EnergyProperties):
228
+ """EnergyWindowFrame properties to be extended by extensions."""
229
+
230
+
231
+ class EnergyWindowMaterialShadeProperties(_EnergyProperties):
232
+ """EnergyWindowMaterialShade properties to be extended by extensions."""
233
+
234
+
235
+ class EnergyWindowMaterialBlindProperties(_EnergyProperties):
236
+ """EnergyWindowMaterialBlind properties to be extended by extensions."""
237
+
238
+
239
+ class ElectricLoadCenterProperties(_EnergyProperties):
240
+ """ElectricLoadCenter properties to be extended by extensions."""
241
+
242
+
243
+ class PVPropertiesProperties(_EnergyProperties):
244
+ """PVProperties to be extended by extensions."""
@@ -0,0 +1,274 @@
1
+ # coding=utf-8
2
+ """Face Energy Properties."""
3
+ from honeybee.facetype import AirBoundary
4
+ from honeybee.checkdup import is_equivalent
5
+ from honeybee.units import conversion_factor_to_meters
6
+
7
+ from ..construction.opaque import OpaqueConstruction
8
+ from ..construction.air import AirBoundaryConstruction
9
+ from ..lib.constructionsets import generic_construction_set
10
+ from ..ventcool.crack import AFNCrack
11
+
12
+
13
+ class FaceEnergyProperties(object):
14
+ """Energy Properties for Honeybee Face.
15
+
16
+ Args:
17
+ host: A honeybee_core Face object that hosts these properties.
18
+ construction: An optional Honeybee OpaqueConstruction object for
19
+ the face. If None, it will be set by the parent Room ConstructionSet
20
+ or the the Honeybee default generic ConstructionSet.
21
+ vent_crack: An optional AFNCrack to specify the air leakage crack for
22
+ the Face. (Default: None).
23
+
24
+ Properties:
25
+ * host
26
+ * construction
27
+ * vent_crack
28
+ * is_construction_set_on_object
29
+ """
30
+
31
+ __slots__ = ('_host', '_construction', '_vent_crack')
32
+
33
+ def __init__(self, host, construction=None, vent_crack=None):
34
+ """Initialize Face energy properties."""
35
+ self._host = host
36
+ self.construction = construction
37
+ self.vent_crack = vent_crack
38
+
39
+ @property
40
+ def host(self):
41
+ """Get the Face object hosting these properties."""
42
+ return self._host
43
+
44
+ @property
45
+ def construction(self):
46
+ """Get or set Face Construction.
47
+
48
+ If the Construction is not set on the face-level, then it will be assigned
49
+ based on the ConstructionSet assigned to the parent Room. If there is no
50
+ parent Room or the parent Room's ConstructionSet has no construction for
51
+ the Face type and boundary_condition, it will be assigned using the honeybee
52
+ default generic construction set.
53
+ """
54
+ if self._construction: # set by user
55
+ return self._construction
56
+ elif self._host.has_parent: # set by parent room
57
+ constr_set = self._host.parent.properties.energy.construction_set
58
+ return constr_set.get_face_construction(
59
+ self._host.type.name, self._host.boundary_condition.name)
60
+ else:
61
+ return generic_construction_set.get_face_construction(
62
+ self._host.type.name, self._host.boundary_condition.name)
63
+
64
+ @construction.setter
65
+ def construction(self, value):
66
+ if value is not None:
67
+ if isinstance(self.host.type, AirBoundary):
68
+ accept_cons = (AirBoundaryConstruction, OpaqueConstruction)
69
+ assert isinstance(value, accept_cons), \
70
+ 'Expected Air Boundary or Opaque Construction for face with ' \
71
+ 'AirBoundary type. Got {}'.format(type(value))
72
+ else:
73
+ assert isinstance(value, OpaqueConstruction), \
74
+ 'Expected Opaque Construction for face. Got {}'.format(type(value))
75
+ value.lock() # lock editing in case construction has multiple references
76
+ self._construction = value
77
+
78
+ @property
79
+ def vent_crack(self):
80
+ """Get or set a AFNCrack object to specify Airflow Network air leakage.
81
+
82
+ Note that anything assigned here has no bearing on the simulation unless
83
+ the Model that the Face is a part of has its ventilation_simulation_control
84
+ set for MultiZone air flow, thereby triggering the use of the AirflowNetwork.
85
+ """
86
+ return self._vent_crack
87
+
88
+ @vent_crack.setter
89
+ def vent_crack(self, value):
90
+ if value is not None:
91
+ assert isinstance(value, AFNCrack), 'Expected AFNCrack ' \
92
+ 'for Face vent_crack. Got {}'.format(type(value))
93
+ value.lock() # lock because we don't duplicate the object
94
+ self._vent_crack = value
95
+
96
+ @property
97
+ def is_construction_set_on_object(self):
98
+ """Boolean noting if construction is assigned on the level of this Face.
99
+
100
+ This is opposed to having the construction assigned by a ConstructionSet.
101
+ """
102
+ return self._construction is not None
103
+
104
+ def r_factor(self, units='Meters'):
105
+ """Get the Face R-factor [m2-K/W] (including air film resistance).
106
+
107
+ The air film resistances are computed using the orientation and height
108
+ of the Face geometry.
109
+
110
+ Args:
111
+ units: Text for the units in which the Face geometry exists. These
112
+ will be used to correctly interpret the dimensions of the
113
+ geometry for heat flow calculation. (Default: Meters).
114
+ """
115
+ constr = self.construction
116
+ if isinstance(constr, AirBoundaryConstruction):
117
+ return 0
118
+ u_conv = conversion_factor_to_meters(units)
119
+ height = (self.host.max.z - self.host.min.z) * u_conv
120
+ height = 1 if height < 1 else height
121
+ temps, r_vals = constr.temperature_profile(
122
+ height=height, angle=abs(self.host.altitude - 90))
123
+ return sum(r_vals)
124
+
125
+ def u_factor(self, units='Meters'):
126
+ """Get the Face U-factor [W/m2-K] (including resistances for air films).
127
+
128
+ The air film resistances are computed using the orientation and height
129
+ of the Face geometry.
130
+
131
+ Args:
132
+ units: Text for the units in which the Face geometry exists. These
133
+ will be used to correctly interpret the dimensions of the
134
+ geometry for heat flow calculation. (Default: Meters).
135
+ """
136
+ try:
137
+ return 1 / self.r_factor(units)
138
+ except ZeroDivisionError:
139
+ return 0 # AirBoundary construction
140
+
141
+ def shgc(self, units='Meters'):
142
+ """Get the Face solar heat gain coefficient (SHGC).
143
+
144
+ This value is computed by summing the conducted portions of solar irradiance
145
+ under the NFRC summer conditions. The air film resistances are computed using
146
+ the orientation and height of the Face geometry.
147
+
148
+ Args:
149
+ units: Text for the units in which the Face geometry exists. These
150
+ will be used to correctly interpret the dimensions of the
151
+ geometry for heat flow calculation. (Default: Meters).
152
+ """
153
+ constr = self.construction
154
+ if isinstance(constr, AirBoundaryConstruction):
155
+ return 1
156
+ # compute the temperature profile
157
+ t_out, t_in, sol_irr = 32, 24, 783 # NFRC 2010 summer conditions
158
+ u_conv = conversion_factor_to_meters(units)
159
+ height = (self.host.max.z - self.host.min.z) * u_conv
160
+ height = 1 if height < 1 else height
161
+ _, r_vals = constr.temperature_profile(
162
+ t_out, t_in, height=height, angle=abs(self.host.altitude - 90),
163
+ solar_irradiance=sol_irr)
164
+ heat_gen = sol_irr * (1 - constr.outside_solar_reflectance)
165
+ r_factor = sum(r_vals)
166
+ conducted = heat_gen * (1 - (sum(r_vals[1:]) / r_factor))
167
+ return conducted / sol_irr
168
+
169
+ def reset_construction_to_set(self):
170
+ """Reset the construction assigned to this Face and its children to the default.
171
+
172
+ This means that the Face's construction and its child Aperture/Door
173
+ constructions will be assigned by a ConstructionSet.
174
+ """
175
+ self._construction = None
176
+ for sf in self.host.sub_faces:
177
+ sf.properties.energy.reset_construction_to_set()
178
+ for shade in self.host.shades:
179
+ shade.properties.energy.reset_construction_to_set()
180
+
181
+ @classmethod
182
+ def from_dict(cls, data, host):
183
+ """Create FaceEnergyProperties from a dictionary.
184
+
185
+ Note that the dictionary must be a non-abridged version for this
186
+ classmethod to work.
187
+
188
+ Args:
189
+ data: A dictionary representation of FaceEnergyProperties with the
190
+ format below.
191
+ host: A Face object that hosts these properties.
192
+
193
+ .. code-block:: python
194
+
195
+ {
196
+ "type": 'FaceEnergyProperties',
197
+ "construction": {}, # opaque construction
198
+ "vent_crack": {} # AFN crack
199
+ }
200
+ """
201
+ assert data['type'] == 'FaceEnergyProperties', \
202
+ 'Expected FaceEnergyProperties. Got {}.'.format(data['type'])
203
+
204
+ new_prop = cls(host)
205
+ if 'construction' in data and data['construction'] is not None:
206
+ new_prop.construction = OpaqueConstruction.from_dict(data['construction'])
207
+ if 'vent_crack' in data and data['vent_crack'] is not None:
208
+ new_prop.vent_crack = AFNCrack.from_dict(data['vent_crack'])
209
+ return new_prop
210
+
211
+ def apply_properties_from_dict(self, abridged_data, constructions):
212
+ """Apply properties from a FaceEnergyPropertiesAbridged dictionary.
213
+
214
+ Args:
215
+ abridged_data: A FaceEnergyPropertiesAbridged dictionary (typically
216
+ coming from a Model).
217
+ constructions: A dictionary of constructions with constructions identifiers
218
+ as keys, which will be used to re-assign constructions.
219
+ """
220
+ if 'construction' in abridged_data and abridged_data['construction'] is not None:
221
+ try:
222
+ self.construction = constructions[abridged_data['construction']]
223
+ except KeyError:
224
+ raise ValueError('Face construction "{}" was not found in '
225
+ 'constructions.'.format(abridged_data['construction']))
226
+ if 'vent_crack' in abridged_data and abridged_data['vent_crack'] is not None:
227
+ self.vent_crack = AFNCrack.from_dict(abridged_data['vent_crack'])
228
+
229
+ def to_dict(self, abridged=False):
230
+ """Return energy properties as a dictionary.
231
+
232
+ Args:
233
+ abridged: Boolean to note whether the full dictionary describing the
234
+ object should be returned (False) or just an abridged version (True).
235
+ Default: False.
236
+ """
237
+ base = {'energy': {}}
238
+ base['energy']['type'] = 'FaceEnergyProperties' if not \
239
+ abridged else 'FaceEnergyPropertiesAbridged'
240
+ if self._construction is not None:
241
+ base['energy']['construction'] = \
242
+ self._construction.identifier if abridged else \
243
+ self._construction.to_dict()
244
+ if self._vent_crack is not None:
245
+ base['energy']['vent_crack'] = self._vent_crack.to_dict()
246
+ return base
247
+
248
+ def duplicate(self, new_host=None):
249
+ """Get a copy of this object.
250
+
251
+ Args:
252
+ new_host: A new Face object that hosts these properties.
253
+ If None, the properties will be duplicated with the same host.
254
+ """
255
+ _host = new_host or self._host
256
+ return FaceEnergyProperties(_host, self._construction, self._vent_crack)
257
+
258
+ def is_equivalent(self, other):
259
+ """Check to see if these energy properties are equivalent to another object.
260
+
261
+ This will only be True if all properties match (except for the host) and
262
+ will otherwise be False.
263
+ """
264
+ if not is_equivalent(self._construction, other._construction):
265
+ return False
266
+ if not is_equivalent(self._vent_crack, other._vent_crack):
267
+ return False
268
+ return True
269
+
270
+ def ToString(self):
271
+ return self.__repr__()
272
+
273
+ def __repr__(self):
274
+ return 'Face Energy Properties: [host: {}]'.format(self.host.display_name)