honeybee-energy 1.116.106__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- honeybee_energy/__init__.py +24 -0
- honeybee_energy/__main__.py +4 -0
- honeybee_energy/_extend_honeybee.py +145 -0
- honeybee_energy/altnumber.py +21 -0
- honeybee_energy/baseline/__init__.py +2 -0
- honeybee_energy/baseline/create.py +608 -0
- honeybee_energy/baseline/data/__init__.py +1 -0
- honeybee_energy/baseline/data/constructions.csv +64 -0
- honeybee_energy/baseline/data/fen_ratios.csv +15 -0
- honeybee_energy/baseline/data/lpd_building.csv +21 -0
- honeybee_energy/baseline/data/pci_2016.csv +22 -0
- honeybee_energy/baseline/data/pci_2019.csv +22 -0
- honeybee_energy/baseline/data/pci_2022.csv +22 -0
- honeybee_energy/baseline/data/shw.csv +21 -0
- honeybee_energy/baseline/pci.py +512 -0
- honeybee_energy/baseline/result.py +371 -0
- honeybee_energy/boundarycondition.py +128 -0
- honeybee_energy/cli/__init__.py +69 -0
- honeybee_energy/cli/baseline.py +475 -0
- honeybee_energy/cli/edit.py +327 -0
- honeybee_energy/cli/lib.py +1154 -0
- honeybee_energy/cli/result.py +810 -0
- honeybee_energy/cli/setconfig.py +124 -0
- honeybee_energy/cli/settings.py +569 -0
- honeybee_energy/cli/simulate.py +380 -0
- honeybee_energy/cli/translate.py +1714 -0
- honeybee_energy/cli/validate.py +224 -0
- honeybee_energy/config.json +11 -0
- honeybee_energy/config.py +842 -0
- honeybee_energy/construction/__init__.py +1 -0
- honeybee_energy/construction/_base.py +374 -0
- honeybee_energy/construction/air.py +325 -0
- honeybee_energy/construction/dictutil.py +89 -0
- honeybee_energy/construction/dynamic.py +607 -0
- honeybee_energy/construction/opaque.py +460 -0
- honeybee_energy/construction/shade.py +319 -0
- honeybee_energy/construction/window.py +1096 -0
- honeybee_energy/construction/windowshade.py +847 -0
- honeybee_energy/constructionset.py +1655 -0
- honeybee_energy/dictutil.py +56 -0
- honeybee_energy/generator/__init__.py +5 -0
- honeybee_energy/generator/loadcenter.py +204 -0
- honeybee_energy/generator/pv.py +535 -0
- honeybee_energy/hvac/__init__.py +21 -0
- honeybee_energy/hvac/_base.py +124 -0
- honeybee_energy/hvac/_template.py +270 -0
- honeybee_energy/hvac/allair/__init__.py +22 -0
- honeybee_energy/hvac/allair/_base.py +349 -0
- honeybee_energy/hvac/allair/furnace.py +168 -0
- honeybee_energy/hvac/allair/psz.py +131 -0
- honeybee_energy/hvac/allair/ptac.py +163 -0
- honeybee_energy/hvac/allair/pvav.py +109 -0
- honeybee_energy/hvac/allair/vav.py +128 -0
- honeybee_energy/hvac/detailed.py +337 -0
- honeybee_energy/hvac/doas/__init__.py +28 -0
- honeybee_energy/hvac/doas/_base.py +345 -0
- honeybee_energy/hvac/doas/fcu.py +127 -0
- honeybee_energy/hvac/doas/radiant.py +329 -0
- honeybee_energy/hvac/doas/vrf.py +81 -0
- honeybee_energy/hvac/doas/wshp.py +91 -0
- honeybee_energy/hvac/heatcool/__init__.py +23 -0
- honeybee_energy/hvac/heatcool/_base.py +177 -0
- honeybee_energy/hvac/heatcool/baseboard.py +61 -0
- honeybee_energy/hvac/heatcool/evapcool.py +72 -0
- honeybee_energy/hvac/heatcool/fcu.py +92 -0
- honeybee_energy/hvac/heatcool/gasunit.py +53 -0
- honeybee_energy/hvac/heatcool/radiant.py +269 -0
- honeybee_energy/hvac/heatcool/residential.py +77 -0
- honeybee_energy/hvac/heatcool/vrf.py +54 -0
- honeybee_energy/hvac/heatcool/windowac.py +70 -0
- honeybee_energy/hvac/heatcool/wshp.py +62 -0
- honeybee_energy/hvac/idealair.py +699 -0
- honeybee_energy/internalmass.py +310 -0
- honeybee_energy/lib/__init__.py +1 -0
- honeybee_energy/lib/_loadconstructions.py +194 -0
- honeybee_energy/lib/_loadconstructionsets.py +117 -0
- honeybee_energy/lib/_loadmaterials.py +83 -0
- honeybee_energy/lib/_loadprogramtypes.py +125 -0
- honeybee_energy/lib/_loadschedules.py +87 -0
- honeybee_energy/lib/_loadtypelimits.py +64 -0
- honeybee_energy/lib/constructions.py +207 -0
- honeybee_energy/lib/constructionsets.py +95 -0
- honeybee_energy/lib/materials.py +67 -0
- honeybee_energy/lib/programtypes.py +125 -0
- honeybee_energy/lib/schedules.py +61 -0
- honeybee_energy/lib/scheduletypelimits.py +31 -0
- honeybee_energy/load/__init__.py +1 -0
- honeybee_energy/load/_base.py +190 -0
- honeybee_energy/load/daylight.py +397 -0
- honeybee_energy/load/dictutil.py +47 -0
- honeybee_energy/load/equipment.py +771 -0
- honeybee_energy/load/hotwater.py +543 -0
- honeybee_energy/load/infiltration.py +460 -0
- honeybee_energy/load/lighting.py +480 -0
- honeybee_energy/load/people.py +497 -0
- honeybee_energy/load/process.py +472 -0
- honeybee_energy/load/setpoint.py +816 -0
- honeybee_energy/load/ventilation.py +550 -0
- honeybee_energy/material/__init__.py +1 -0
- honeybee_energy/material/_base.py +166 -0
- honeybee_energy/material/dictutil.py +59 -0
- honeybee_energy/material/frame.py +367 -0
- honeybee_energy/material/gas.py +1087 -0
- honeybee_energy/material/glazing.py +854 -0
- honeybee_energy/material/opaque.py +1351 -0
- honeybee_energy/material/shade.py +1360 -0
- honeybee_energy/measure.py +472 -0
- honeybee_energy/programtype.py +723 -0
- honeybee_energy/properties/__init__.py +1 -0
- honeybee_energy/properties/aperture.py +333 -0
- honeybee_energy/properties/door.py +342 -0
- honeybee_energy/properties/extension.py +244 -0
- honeybee_energy/properties/face.py +274 -0
- honeybee_energy/properties/model.py +2640 -0
- honeybee_energy/properties/room.py +1747 -0
- honeybee_energy/properties/shade.py +314 -0
- honeybee_energy/properties/shademesh.py +262 -0
- honeybee_energy/reader.py +48 -0
- honeybee_energy/result/__init__.py +1 -0
- honeybee_energy/result/colorobj.py +648 -0
- honeybee_energy/result/emissions.py +290 -0
- honeybee_energy/result/err.py +101 -0
- honeybee_energy/result/eui.py +100 -0
- honeybee_energy/result/generation.py +160 -0
- honeybee_energy/result/loadbalance.py +890 -0
- honeybee_energy/result/match.py +202 -0
- honeybee_energy/result/osw.py +90 -0
- honeybee_energy/result/rdd.py +59 -0
- honeybee_energy/result/zsz.py +190 -0
- honeybee_energy/run.py +1577 -0
- honeybee_energy/schedule/__init__.py +1 -0
- honeybee_energy/schedule/day.py +626 -0
- honeybee_energy/schedule/dictutil.py +59 -0
- honeybee_energy/schedule/fixedinterval.py +1012 -0
- honeybee_energy/schedule/rule.py +619 -0
- honeybee_energy/schedule/ruleset.py +1867 -0
- honeybee_energy/schedule/typelimit.py +310 -0
- honeybee_energy/shw.py +315 -0
- honeybee_energy/simulation/__init__.py +1 -0
- honeybee_energy/simulation/control.py +214 -0
- honeybee_energy/simulation/daylightsaving.py +185 -0
- honeybee_energy/simulation/dictutil.py +51 -0
- honeybee_energy/simulation/output.py +646 -0
- honeybee_energy/simulation/parameter.py +606 -0
- honeybee_energy/simulation/runperiod.py +443 -0
- honeybee_energy/simulation/shadowcalculation.py +295 -0
- honeybee_energy/simulation/sizing.py +546 -0
- honeybee_energy/ventcool/__init__.py +5 -0
- honeybee_energy/ventcool/_crack_data.py +91 -0
- honeybee_energy/ventcool/afn.py +289 -0
- honeybee_energy/ventcool/control.py +269 -0
- honeybee_energy/ventcool/crack.py +126 -0
- honeybee_energy/ventcool/fan.py +493 -0
- honeybee_energy/ventcool/opening.py +365 -0
- honeybee_energy/ventcool/simulation.py +314 -0
- honeybee_energy/writer.py +1078 -0
- honeybee_energy-1.116.106.dist-info/METADATA +113 -0
- honeybee_energy-1.116.106.dist-info/RECORD +162 -0
- honeybee_energy-1.116.106.dist-info/WHEEL +5 -0
- honeybee_energy-1.116.106.dist-info/entry_points.txt +2 -0
- honeybee_energy-1.116.106.dist-info/licenses/LICENSE +661 -0
- honeybee_energy-1.116.106.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,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
|