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,166 @@
1
+ # coding=utf-8
2
+ """Base energy material."""
3
+ from __future__ import division
4
+
5
+ from honeybee._lockable import lockable
6
+ from honeybee.typing import valid_ep_string
7
+
8
+
9
+ @lockable
10
+ class _EnergyMaterialBase(object):
11
+ """Base energy material.
12
+
13
+ Args:
14
+ identifier: Text string for a unique Material ID. Must be < 100 characters
15
+ and not contain any EnergyPlus special characters. This will be used to
16
+ identify the object across a model and in the exported IDF.
17
+
18
+ Properties:
19
+ * identifier
20
+ * display_name
21
+ * user_data
22
+ * properties
23
+ """
24
+ __slots__ = ('_identifier', '_display_name', '_locked', '_user_data', '_properties')
25
+
26
+ def __init__(self, identifier):
27
+ """Initialize energy material base."""
28
+ self._locked = False
29
+ self.identifier = identifier
30
+ self._display_name = None
31
+ self._user_data = None
32
+ self._properties = None
33
+
34
+ @property
35
+ def identifier(self):
36
+ """Get or set the text string for material identifier."""
37
+ return self._identifier
38
+
39
+ @identifier.setter
40
+ def identifier(self, identifier):
41
+ self._identifier = valid_ep_string(identifier, 'material identifier')
42
+
43
+ @property
44
+ def display_name(self):
45
+ """Get or set a string for the object name without any character restrictions.
46
+
47
+ If not set, this will be equal to the identifier.
48
+ """
49
+ if self._display_name is None:
50
+ return self._identifier
51
+ return self._display_name
52
+
53
+ @display_name.setter
54
+ def display_name(self, value):
55
+ if value is not None:
56
+ try:
57
+ value = str(value)
58
+ except UnicodeEncodeError: # Python 2 machine lacking the character set
59
+ pass # keep it as unicode
60
+ self._display_name = value
61
+
62
+ @property
63
+ def user_data(self):
64
+ """Get or set an optional dictionary for additional meta data for this object.
65
+
66
+ This will be None until it has been set. All keys and values of this
67
+ dictionary should be of a standard Python type to ensure correct
68
+ serialization of the object to/from JSON (eg. str, float, int, list, dict)
69
+ """
70
+ if self._user_data is not None:
71
+ return self._user_data
72
+
73
+ @user_data.setter
74
+ def user_data(self, value):
75
+ if value is not None:
76
+ assert isinstance(value, dict), 'Expected dictionary for honeybee_energy' \
77
+ 'object user_data. Got {}.'.format(type(value))
78
+ self._user_data = value
79
+
80
+ @property
81
+ def properties(self):
82
+ """Get properties for extensions."""
83
+ return self._properties
84
+
85
+ def duplicate(self):
86
+ """Get a copy of this construction."""
87
+ return self.__copy__()
88
+
89
+ def _compare_thickness_conductivity(self):
90
+ """Compare the thickness and conductivity to avoid CTF errors from EnergyPlus.
91
+
92
+ These CTF errors were common in EnergyPlus 9.5 and below but they have
93
+ been completely eliminated in more recent versions.
94
+ """
95
+ try:
96
+ assert self._conductivity / self._thickness <= 200000, \
97
+ 'Material layer "{}" does not have sufficient thermal resistance.\n'\
98
+ 'Either increase the thickness or remove it from the ' \
99
+ 'construction.'.format(self.identifier)
100
+ except ZeroDivisionError:
101
+ raise ValueError(
102
+ 'Material layer "{}" cannot have zero thickness.'.format(self.identifier)
103
+ )
104
+ except AttributeError:
105
+ pass # conductivity or thickness has not yet been set
106
+
107
+ def __copy__(self):
108
+ new_obj = self.__class__(self.identifier)
109
+ new_obj._display_name = self._display_name
110
+ new_obj._user_data = None if self._user_data is None else self._user_data.copy()
111
+ new_obj._properties._duplicate_extension_attr(self._properties)
112
+ return new_obj
113
+
114
+ def ToString(self):
115
+ """Overwrite .NET ToString."""
116
+ return self.__repr__()
117
+
118
+ def __repr__(self):
119
+ return 'Base Energy Material:\n{}'.format(self.display_name)
120
+
121
+
122
+ @lockable
123
+ class _EnergyMaterialOpaqueBase(_EnergyMaterialBase):
124
+ """Base energy material for all opaque material types."""
125
+ ROUGHTYPES = ('VeryRough', 'Rough', 'MediumRough',
126
+ 'MediumSmooth', 'Smooth', 'VerySmooth')
127
+ RADIANCEROUGHTYPES = {'VeryRough': 0.2, 'Rough': 0.2, 'MediumRough': 0.15,
128
+ 'MediumSmooth': 0.1, 'Smooth': 0.05, 'VerySmooth': 0}
129
+ __slots__ = ()
130
+
131
+ @property
132
+ def is_window_material(self):
133
+ """Boolean to note whether the material can be used for window surfaces."""
134
+ return False
135
+
136
+ def __repr__(self):
137
+ return 'Base Opaque Energy Material:\n{}'.format(self.display_name)
138
+
139
+
140
+ @lockable
141
+ class _EnergyMaterialWindowBase(_EnergyMaterialBase):
142
+ """Base energy material for all window material types."""
143
+ __slots__ = ()
144
+
145
+ @property
146
+ def is_window_material(self):
147
+ """Boolean to note whether the material can be used for window surfaces."""
148
+ return True
149
+
150
+ @property
151
+ def is_glazing_material(self):
152
+ """Boolean to note whether the material is a glazing layer."""
153
+ return False
154
+
155
+ @property
156
+ def is_gas_material(self):
157
+ """Boolean to note whether the material is a gas gap layer."""
158
+ return False
159
+
160
+ @property
161
+ def is_shade_material(self):
162
+ """Boolean to note whether the material is a shade layer."""
163
+ return False
164
+
165
+ def __repr__(self):
166
+ return 'Base Window Energy Material:\n{}'.format(self.display_name)
@@ -0,0 +1,59 @@
1
+ # coding=utf-8
2
+ """Utilities to convert material dictionaries to Python objects."""
3
+ from .opaque import EnergyMaterial, EnergyMaterialNoMass, EnergyMaterialVegetation
4
+ from .glazing import EnergyWindowMaterialGlazing, EnergyWindowMaterialSimpleGlazSys
5
+ from .gas import EnergyWindowMaterialGas, EnergyWindowMaterialGasMixture, \
6
+ EnergyWindowMaterialGasCustom
7
+ from .frame import EnergyWindowFrame
8
+ from .shade import EnergyWindowMaterialShade, EnergyWindowMaterialBlind
9
+
10
+
11
+ MATERIAL_TYPES = (
12
+ 'EnergyMaterial', 'EnergyMaterialNoMass', 'EnergyMaterialVegetation',
13
+ 'EnergyWindowMaterialGlazing', 'EnergyWindowMaterialSimpleGlazSys',
14
+ 'EnergyWindowMaterialGas', 'EnergyWindowMaterialGasMixture',
15
+ 'EnergyWindowMaterialGasCustom', 'EnergyWindowFrame',
16
+ 'EnergyWindowMaterialShade', 'EnergyWindowMaterialBlind'
17
+ )
18
+
19
+
20
+ def dict_to_material(mat_dict, raise_exception=True):
21
+ """Get a Python object of any Material from a dictionary.
22
+
23
+ Args:
24
+ mat_dict: A dictionary of any Honeybee energy material.
25
+ raise_exception: Boolean to note whether an exception should be raised
26
+ if the object is not identified as a material. Default: True.
27
+
28
+ Returns:
29
+ A Python object derived from the input mat_dict.
30
+ """
31
+ try: # get the type key from the dictionary
32
+ mat_type = mat_dict['type']
33
+ except KeyError:
34
+ raise ValueError('Material dictionary lacks required "type" key.')
35
+
36
+ if mat_type == 'EnergyMaterial':
37
+ return EnergyMaterial.from_dict(mat_dict)
38
+ elif mat_type == 'EnergyMaterialNoMass':
39
+ return EnergyMaterialNoMass.from_dict(mat_dict)
40
+ elif mat_type == 'EnergyMaterialVegetation':
41
+ return EnergyMaterialVegetation.from_dict(mat_dict)
42
+ elif mat_type == 'EnergyWindowMaterialGlazing':
43
+ return EnergyWindowMaterialGlazing.from_dict(mat_dict)
44
+ elif mat_type == 'EnergyWindowMaterialSimpleGlazSys':
45
+ return EnergyWindowMaterialSimpleGlazSys.from_dict(mat_dict)
46
+ elif mat_type == 'EnergyWindowMaterialGas':
47
+ return EnergyWindowMaterialGas.from_dict(mat_dict)
48
+ elif mat_type == 'EnergyWindowMaterialGasMixture':
49
+ return EnergyWindowMaterialGasMixture.from_dict(mat_dict)
50
+ elif mat_type == 'EnergyWindowMaterialGasCustom':
51
+ return EnergyWindowMaterialGasCustom.from_dict(mat_dict)
52
+ elif mat_type == 'EnergyWindowFrame':
53
+ return EnergyWindowFrame.from_dict(mat_dict)
54
+ elif mat_type == 'EnergyWindowMaterialShade':
55
+ return EnergyWindowMaterialShade.from_dict(mat_dict)
56
+ elif mat_type == 'EnergyWindowMaterialBlind':
57
+ return EnergyWindowMaterialBlind.from_dict(mat_dict)
58
+ elif raise_exception:
59
+ raise ValueError('{} is not a recognized Energy Material type'.format(mat_type))
@@ -0,0 +1,367 @@
1
+ # coding=utf-8
2
+ """Window frame materials.
3
+
4
+ The materials here can only be applied as frames to window constructions.
5
+ """
6
+ from __future__ import division
7
+
8
+ from honeybee._lockable import lockable
9
+ from honeybee.typing import float_in_range, float_in_range_excl_incl, float_positive
10
+
11
+ from ._base import _EnergyMaterialBase
12
+ from ..properties.extension import EnergyWindowFrameProperties
13
+ from ..reader import parse_idf_string
14
+ from ..writer import generate_idf_string
15
+
16
+
17
+ @lockable
18
+ class EnergyWindowFrame(_EnergyMaterialBase):
19
+ """A window frame assigned to a Window Construction.
20
+
21
+ Args:
22
+ identifier: Text string for a unique Material ID. Must be < 100 characters
23
+ and not contain any EnergyPlus special characters. This will be used to
24
+ identify the object across a model and in the exported IDF.
25
+ width: Number for the width of frame in plane of window [m]. The frame
26
+ width is assumed to be the same on all sides of window.
27
+ conductance: Number for the thermal conductance of the frame material measured
28
+ from inside to outside of the frame surface (no air films) and taking 2D
29
+ conduction effects into account [W/m2-K]. Values for typical frame
30
+ materials are as follows.
31
+
32
+ * Aluminum with Thermal Break - 56.4 W/m2-K
33
+ * Aluminum One-Sided (Flush) - 10.7 W/m2-K
34
+ * Wood - 3.5 W/m2-K
35
+ * Vinyl - 2.3 W/m2-K
36
+
37
+ edge_to_center_ratio: Number between 0 and 4 for the ratio of the glass
38
+ conductance near the frame (excluding air films) divided by the glass
39
+ conductance at the center of the glazing (excluding air films).
40
+ This is used only for multi-pane glazing constructions. This ratio should
41
+ usually be greater than 1.0 since the spacer material that separates
42
+ the glass panes is usually more conductive than the gap between panes.
43
+ A value of 1 effectively indicates no spacer. Values should usually be
44
+ obtained from the LBNL WINDOW program so that the unique characteristics
45
+ of the window construction can be accounted for. (Default: 1).
46
+ outside_projection: Number for the distance that the frame projects outward
47
+ from the outside face of the glazing [m]. This is used to calculate shadowing
48
+ of frame onto glass, solar absorbed by the frame, IR emitted and
49
+ absorbed by the frame, and convection from frame. (Default: 0).
50
+ inside_projection: Number for the distance that the frame projects inward
51
+ from the inside face of the glazing [m]. This is used to calculate solar
52
+ absorbed by the frame, IR emitted and absorbed by the frame, and
53
+ convection from frame. (Default: 0).
54
+ thermal_absorptance: A number between 0 and 1 for the fraction of incident long
55
+ wavelength radiation that is absorbed by the material. (Default: 0.9).
56
+ solar_absorptance: A number between 0 and 1 for the fraction of incident
57
+ solar radiation absorbed by the material. (Default: 0.7).
58
+ visible_absorptance: A number between 0 and 1 for the fraction of incident
59
+ visible wavelength radiation absorbed by the material.
60
+ Default is None, which will yield the same value as solar_absorptance.
61
+
62
+ Properties:
63
+ * identifier
64
+ * display_name
65
+ * width
66
+ * conductance
67
+ * edge_to_center_ratio
68
+ * outside_projection
69
+ * inside_projection
70
+ * thermal_absorptance
71
+ * solar_absorptance
72
+ * visible_absorptance
73
+ * solar_reflectance
74
+ * visible_reflectance
75
+ * u_value
76
+ * r_value
77
+ * user_data
78
+ * properties
79
+ """
80
+ __slots__ = ('_identifier', '_display_name', '_width', '_conductance',
81
+ '_edge_to_center_ratio', '_outside_projection', '_inside_projection',
82
+ '_thermal_absorptance', '_solar_absorptance', '_visible_absorptance')
83
+
84
+ def __init__(self, identifier, width, conductance, edge_to_center_ratio=1,
85
+ outside_projection=0, inside_projection=0, thermal_absorptance=0.9,
86
+ solar_absorptance=0.7, visible_absorptance=None):
87
+ """Initialize energy material."""
88
+ _EnergyMaterialBase.__init__(self, identifier)
89
+ self.width = width
90
+ self.conductance = conductance
91
+ self.edge_to_center_ratio = edge_to_center_ratio
92
+ self.outside_projection = outside_projection
93
+ self.inside_projection = inside_projection
94
+ self.thermal_absorptance = thermal_absorptance
95
+ self.solar_absorptance = solar_absorptance
96
+ self.visible_absorptance = visible_absorptance
97
+ self._locked = False
98
+ self._properties = EnergyWindowFrameProperties(self)
99
+
100
+ @property
101
+ def width(self):
102
+ """Get or set the width of frame in plane of window [m]."""
103
+ return self._width
104
+
105
+ @width.setter
106
+ def width(self, value):
107
+ self._width = float_in_range_excl_incl(value, 0.0, 1.0, 'window frame width')
108
+
109
+ @property
110
+ def conductance(self):
111
+ """Get or set the conductance of the frame material [W/m2-K]."""
112
+ return self._conductance
113
+
114
+ @conductance.setter
115
+ def conductance(self, cond):
116
+ self._conductance = float_positive(cond, 'window frame conductance')
117
+
118
+ @property
119
+ def edge_to_center_ratio(self):
120
+ """Get or set the ratio between the edge and center glass conductances."""
121
+ return self._edge_to_center_ratio
122
+
123
+ @edge_to_center_ratio.setter
124
+ def edge_to_center_ratio(self, value):
125
+ self._edge_to_center_ratio = float_in_range_excl_incl(
126
+ value, 0.0, 4.0, 'window frame edge-to-center ratio')
127
+
128
+ @property
129
+ def outside_projection(self):
130
+ """Get or set the distance the frame projects from the outside [m]."""
131
+ return self._outside_projection
132
+
133
+ @outside_projection.setter
134
+ def outside_projection(self, value):
135
+ self._outside_projection = float_in_range(
136
+ value, 0.0, 0.5, 'window frame outside projection')
137
+
138
+ @property
139
+ def inside_projection(self):
140
+ """Get or set the distance the frame projects from the inside [m]."""
141
+ return self._inside_projection
142
+
143
+ @inside_projection.setter
144
+ def inside_projection(self, value):
145
+ self._inside_projection = float_in_range(
146
+ value, 0.0, 0.5, 'window frame inside projection')
147
+
148
+ @property
149
+ def thermal_absorptance(self):
150
+ """Get or set the thermal absorptance of the frame material."""
151
+ return self._thermal_absorptance
152
+
153
+ @thermal_absorptance.setter
154
+ def thermal_absorptance(self, t_abs):
155
+ self._thermal_absorptance = float_in_range(
156
+ t_abs, 0.0, 1.0, 'window frame thermal absorptance')
157
+
158
+ @property
159
+ def solar_absorptance(self):
160
+ """Get or set the solar absorptance of the frame material."""
161
+ return self._solar_absorptance
162
+
163
+ @solar_absorptance.setter
164
+ def solar_absorptance(self, s_abs):
165
+ self._solar_absorptance = float_in_range(
166
+ s_abs, 0.0, 1.0, 'window frame solar absorptance')
167
+
168
+ @property
169
+ def visible_absorptance(self):
170
+ """Get or set the visible absorptance of the frame material."""
171
+ return self._visible_absorptance if self._visible_absorptance is not None \
172
+ else self._solar_absorptance
173
+
174
+ @visible_absorptance.setter
175
+ def visible_absorptance(self, v_abs):
176
+ self._visible_absorptance = float_in_range(
177
+ v_abs, 0.0, 1.0, 'window frame visible absorptance') if v_abs is not None \
178
+ else None
179
+
180
+ @property
181
+ def solar_reflectance(self):
182
+ """Get or set the front solar reflectance of the frame material."""
183
+ return 1 - self.solar_absorptance
184
+
185
+ @solar_reflectance.setter
186
+ def solar_reflectance(self, v_ref):
187
+ v_ref = float_in_range(v_ref, 0.0, 1.0, 'window frame solar reflectance')
188
+ self.solar_absorptance = 1 - v_ref
189
+
190
+ @property
191
+ def visible_reflectance(self):
192
+ """Get or set the front visible reflectance of the frame material."""
193
+ return 1 - self.visible_absorptance
194
+
195
+ @visible_reflectance.setter
196
+ def visible_reflectance(self, v_ref):
197
+ v_ref = float_in_range(v_ref, 0.0, 1.0, 'window frame visible reflectance')
198
+ self.visible_absorptance = 1 - v_ref
199
+
200
+ @property
201
+ def r_value(self):
202
+ """Get or set the R-value of the frame material in [m2-K/W] (excluding films).
203
+ """
204
+ return 1 / self.conductance
205
+
206
+ @r_value.setter
207
+ def r_value(self, r_val):
208
+ _new_conductance = 1 / float_positive(r_val, 'window frame r-value')
209
+ self._conductance = _new_conductance
210
+
211
+ @property
212
+ def u_value(self):
213
+ """Get or set the U-value of the frame material [W/m2-K] (excluding films).
214
+ """
215
+ return self.conductance
216
+
217
+ @u_value.setter
218
+ def u_value(self, u_val):
219
+ self.conductance = u_val
220
+
221
+ @classmethod
222
+ def from_idf(cls, idf_string):
223
+ """Create an EnergyWindowFrame from an EnergyPlus text string.
224
+
225
+ Args:
226
+ idf_string: A text string fully describing an EnergyPlus material.
227
+ """
228
+ ep_strs = parse_idf_string(idf_string, 'WindowProperty:FrameAndDivider,')
229
+ idf_defaults = ('unnamed', 0, 0, 0, 0, 1, 0.7, 0.7, 0.9)
230
+ for i, d_val in enumerate(idf_defaults): # fill in any default values
231
+ try:
232
+ if ep_strs[i] == '':
233
+ ep_strs[i] = d_val
234
+ except IndexError:
235
+ ep_strs.append(d_val)
236
+ if float(ep_strs[1]) == 0 or float(ep_strs[4]) == 0:
237
+ return None # no frame definition within WindowProperty:FrameAndDivider
238
+ return cls(
239
+ ep_strs[0], ep_strs[1], ep_strs[4], ep_strs[5], ep_strs[2], ep_strs[3],
240
+ ep_strs[6], ep_strs[7], ep_strs[8])
241
+
242
+ @classmethod
243
+ def from_dict(cls, data):
244
+ """Create a EnergyWindowFrame from a dictionary.
245
+
246
+ Args:
247
+ data: A python dictionary in the following format
248
+
249
+ .. code-block:: python
250
+
251
+ {
252
+ "type": 'EnergyWindowFrame',
253
+ "identifier": 'Wood_Frame_050_032',
254
+ "display_name": 'Pine Wooden Frame',
255
+ "width": 0.05,
256
+ "conductance": 3.2,
257
+ "edge_to_center_ratio": 2.6,
258
+ "outside_projection": 0.05,
259
+ "inside_projection": 0.1,
260
+ "thermal_absorptance": 0.9,
261
+ "solar_absorptance": 0.7,
262
+ "visible_absorptance": 0.7
263
+ }
264
+ """
265
+ assert data['type'] == 'EnergyWindowFrame', \
266
+ 'Expected EnergyWindowFrame. Got {}.'.format(data['type'])
267
+
268
+ ratio = data['edge_to_center_ratio'] if 'edge_to_center_ratio' in data and \
269
+ data['edge_to_center_ratio'] is not None else 1
270
+ out_pro = data['outside_projection'] if 'outside_projection' in data and \
271
+ data['outside_projection'] is not None else 0
272
+ in_pro = data['inside_projection'] if 'inside_projection' in data and \
273
+ data['inside_projection'] is not None else 0
274
+ t_abs = data['thermal_absorptance'] if 'thermal_absorptance' in data and \
275
+ data['thermal_absorptance'] is not None else 0.9
276
+ s_abs = data['solar_absorptance'] if 'solar_absorptance' in data and \
277
+ data['solar_absorptance'] is not None else 0.7
278
+ v_abs = data['visible_absorptance'] if 'visible_absorptance' in data else None
279
+
280
+ new_mat = cls(data['identifier'], data['width'], data['conductance'],
281
+ ratio, out_pro, in_pro, t_abs, s_abs, v_abs)
282
+ if 'display_name' in data and data['display_name'] is not None:
283
+ new_mat.display_name = data['display_name']
284
+ if 'user_data' in data and data['user_data'] is not None:
285
+ new_mat.user_data = data['user_data']
286
+ if 'properties' in data and data['properties'] is not None:
287
+ new_mat._properties._load_extension_attr_from_dict(data['properties'])
288
+
289
+ return new_mat
290
+
291
+ def to_idf(self):
292
+ """Get an EnergyPlus string representation of the window frame.
293
+
294
+ .. code-block:: shell
295
+
296
+ WindowProperty:FrameAndDivider,
297
+ TestFrameAndDivider, ! Frame/Divider Name
298
+ 0.05, ! Frame Width
299
+ 0.04, ! Frame Outside Projection
300
+ 0.03, ! Frame Inside Projection
301
+ 5.0, ! Frame Conductance
302
+ 1.3, ! Ratio of Frame-Edge Glass Conductance to Center-Of-Glass Conductance
303
+ 0.8, ! Frame Solar Absorptance
304
+ 0.8, ! Frame Visible Absorptance
305
+ """
306
+ values = (
307
+ self.identifier, self.width, self.outside_projection, self.inside_projection,
308
+ self.conductance, self.edge_to_center_ratio, self.solar_absorptance,
309
+ self.visible_absorptance, self.thermal_absorptance)
310
+ comments = (
311
+ 'name', 'width {m}', 'outside projection {m}', 'inside projection {m}',
312
+ 'conductance {W/m2-K}', 'edge-to-center-of-glass conductance ratio',
313
+ 'solar absorptance', 'visible absorptance', 'thermal absorptance')
314
+ return generate_idf_string('WindowProperty:FrameAndDivider', values, comments)
315
+
316
+ def to_dict(self):
317
+ """EnergyWindowFrame dictionary representation."""
318
+ base = {
319
+ 'type': 'EnergyWindowFrame',
320
+ 'identifier': self.identifier,
321
+ 'width': self.width,
322
+ 'conductance': self.conductance,
323
+ 'edge_to_center_ratio': self.edge_to_center_ratio,
324
+ 'outside_projection': self.outside_projection,
325
+ 'inside_projection': self.inside_projection,
326
+ 'thermal_absorptance': self.thermal_absorptance,
327
+ 'solar_absorptance': self.solar_absorptance,
328
+ 'visible_absorptance': self.visible_absorptance
329
+ }
330
+ if self._display_name is not None:
331
+ base['display_name'] = self.display_name
332
+ if self._user_data is not None:
333
+ base['user_data'] = self.user_data
334
+ prop_dict = self._properties.to_dict()
335
+ if prop_dict is not None:
336
+ base['properties'] = prop_dict
337
+ return base
338
+
339
+ def __key(self):
340
+ """A tuple based on the object properties, useful for hashing."""
341
+ return (
342
+ self.identifier, self.width, self.conductance, self.edge_to_center_ratio,
343
+ self.outside_projection, self.inside_projection,
344
+ self.thermal_absorptance, self.solar_absorptance, self.visible_absorptance)
345
+
346
+ def __hash__(self):
347
+ return hash(self.__key())
348
+
349
+ def __eq__(self, other):
350
+ return isinstance(other, EnergyWindowFrame) and self.__key() == other.__key()
351
+
352
+ def __ne__(self, other):
353
+ return not self.__eq__(other)
354
+
355
+ def __repr__(self):
356
+ return self.to_idf()
357
+
358
+ def __copy__(self):
359
+ new_material = self.__class__(
360
+ self.identifier, self.width, self.conductance, self.edge_to_center_ratio,
361
+ self.outside_projection, self.inside_projection, self.thermal_absorptance,
362
+ self.solar_absorptance, self._visible_absorptance)
363
+ new_material._display_name = self._display_name
364
+ new_material._user_data = None if self._user_data is None \
365
+ else self._user_data.copy()
366
+ new_material._properties._duplicate_extension_attr(self._properties)
367
+ return new_material