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,397 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
"""Room daylight controls, including sensor location and setpoint."""
|
|
3
|
+
from __future__ import division
|
|
4
|
+
import math
|
|
5
|
+
|
|
6
|
+
from ladybug_geometry.geometry3d.pointvector import Point3D
|
|
7
|
+
from honeybee.typing import float_in_range, float_positive
|
|
8
|
+
|
|
9
|
+
from ..reader import parse_idf_string
|
|
10
|
+
from ..writer import generate_idf_string
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DaylightingControl(object):
|
|
14
|
+
"""Room daylight controls, including sensor location and setpoint.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
sensor_position: A ladybug_geometry Point3D for the position of the daylight
|
|
18
|
+
sensor within the parent Room. This point should lie within the Room
|
|
19
|
+
volume in order for the results to be meaningful. The ladybug_geometry
|
|
20
|
+
Polyface.is_point_inside method can be used to check whether a given
|
|
21
|
+
point is inside the room volume.
|
|
22
|
+
illuminance_setpoint: A number for the illuminance setpoint in lux beyond
|
|
23
|
+
which electric lights are dimmed if there is sufficient daylight.
|
|
24
|
+
Some common setpoints are listed below. (Default: 300 lux).
|
|
25
|
+
|
|
26
|
+
* 50 lux - Corridors and hallways.
|
|
27
|
+
* 150 lux - Computer work spaces (screens provide illumination).
|
|
28
|
+
* 300 lux - Paper work spaces (reading from surfaces needing illumination).
|
|
29
|
+
* 500 lux - Retail spaces or museums illuminating merchandise/artifacts.
|
|
30
|
+
* 1000 lux - Operating rooms and workshops where light is needed for safety.
|
|
31
|
+
|
|
32
|
+
control_fraction: A number between 0 and 1 that represents the fraction of
|
|
33
|
+
the Room lights that are dimmed when the illuminance at the sensor
|
|
34
|
+
position is at the specified illuminance. 1 indicates that all lights are
|
|
35
|
+
dim-able while 0 indicates that no lights are dim-able. Deeper rooms
|
|
36
|
+
should have lower control fractions to account for the face that the
|
|
37
|
+
lights in the back of the space do not dim in response to suitable
|
|
38
|
+
daylight at the front of the room. (Default: 1).
|
|
39
|
+
min_power_input: A number between 0 and 1 for the the lowest power the
|
|
40
|
+
lighting system can dim down to, expressed as a fraction of maximum
|
|
41
|
+
input power. (Default: 0.3).
|
|
42
|
+
min_light_output: A number between 0 and 1 the lowest lighting output the
|
|
43
|
+
lighting system can dim down to, expressed as a fraction of maximum
|
|
44
|
+
light output. (Default: 0.2).
|
|
45
|
+
off_at_minimum: Boolean to note whether lights should switch off completely
|
|
46
|
+
when they get to the minimum power input. (Default: False).
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
Properties:
|
|
50
|
+
* sensor_position
|
|
51
|
+
* illuminance_setpoint
|
|
52
|
+
* control_fraction
|
|
53
|
+
* min_power_input
|
|
54
|
+
* min_light_output
|
|
55
|
+
* off_at_minimum
|
|
56
|
+
* parent
|
|
57
|
+
* has_parent
|
|
58
|
+
* is_sensor_inside_parent
|
|
59
|
+
"""
|
|
60
|
+
__slots__ = ('_sensor_position', '_illuminance_setpoint', '_control_fraction',
|
|
61
|
+
'_min_power_input', '_min_light_output', '_off_at_minimum', '_parent')
|
|
62
|
+
|
|
63
|
+
def __init__(self, sensor_position, illuminance_setpoint=300, control_fraction=1,
|
|
64
|
+
min_power_input=0.3, min_light_output=0.2, off_at_minimum=False):
|
|
65
|
+
self.sensor_position = sensor_position
|
|
66
|
+
self.illuminance_setpoint = illuminance_setpoint
|
|
67
|
+
self.control_fraction = control_fraction
|
|
68
|
+
self.min_power_input = min_power_input
|
|
69
|
+
self.min_light_output = min_light_output
|
|
70
|
+
self.off_at_minimum = off_at_minimum
|
|
71
|
+
self._parent = None # _parent will be set when the object is added to a Room
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def sensor_position(self):
|
|
75
|
+
"""Get or set a Point3D for the sensor position for the daylight sensor."""
|
|
76
|
+
return self._sensor_position
|
|
77
|
+
|
|
78
|
+
@sensor_position.setter
|
|
79
|
+
def sensor_position(self, value):
|
|
80
|
+
assert isinstance(value, Point3D), 'Expected Point3D for DaylightingControl ' \
|
|
81
|
+
'sensor_position. Got {}.'.format(type(value))
|
|
82
|
+
self._sensor_position = value
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def illuminance_setpoint(self):
|
|
86
|
+
"""Get or set a number for the illuminance setpoint in lux."""
|
|
87
|
+
return self._illuminance_setpoint
|
|
88
|
+
|
|
89
|
+
@illuminance_setpoint.setter
|
|
90
|
+
def illuminance_setpoint(self, value):
|
|
91
|
+
self._illuminance_setpoint = float_positive(value, 'illuminance setpoint')
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def control_fraction(self):
|
|
95
|
+
"""Get or set the fraction of the Room lights that are dimmed."""
|
|
96
|
+
return self._control_fraction
|
|
97
|
+
|
|
98
|
+
@control_fraction.setter
|
|
99
|
+
def control_fraction(self, value):
|
|
100
|
+
if value is not None:
|
|
101
|
+
self._control_fraction = float_in_range(
|
|
102
|
+
value, 0.0, 1.0, 'daylighting control fraction')
|
|
103
|
+
else:
|
|
104
|
+
self._control_fraction = 1
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def min_power_input(self):
|
|
108
|
+
"""Get or set the lowest power the lighting system can dim down to."""
|
|
109
|
+
return self._min_power_input
|
|
110
|
+
|
|
111
|
+
@min_power_input.setter
|
|
112
|
+
def min_power_input(self, value):
|
|
113
|
+
if value is not None:
|
|
114
|
+
self._min_power_input = float_in_range(
|
|
115
|
+
value, 0.0, 1.0, 'daylighting control min_power_input')
|
|
116
|
+
else:
|
|
117
|
+
self._min_power_input = 0.3
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def min_light_output(self):
|
|
121
|
+
"""Get or set the lowest lighting output the lighting system can dim down to."""
|
|
122
|
+
return self._min_light_output
|
|
123
|
+
|
|
124
|
+
@min_light_output.setter
|
|
125
|
+
def min_light_output(self, value):
|
|
126
|
+
if value is not None:
|
|
127
|
+
self._min_light_output = float_in_range(
|
|
128
|
+
value, 0.0, 1.0, 'daylighting control min_light_output')
|
|
129
|
+
else:
|
|
130
|
+
self._min_light_output = 0.2
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def off_at_minimum(self):
|
|
134
|
+
"""Get or set a boolean to indicate whether the lights switch off completely."""
|
|
135
|
+
return self._off_at_minimum
|
|
136
|
+
|
|
137
|
+
@off_at_minimum.setter
|
|
138
|
+
def off_at_minimum(self, value):
|
|
139
|
+
self._off_at_minimum = bool(value)
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def parent(self):
|
|
143
|
+
"""Get the parent Room if assigned. None if not assigned."""
|
|
144
|
+
return self._parent
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def has_parent(self):
|
|
148
|
+
"""Get a boolean noting whether this object has a parent Room."""
|
|
149
|
+
return self._parent is not None
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def is_sensor_inside_parent(self):
|
|
153
|
+
"""Get a boolean for whether the sensor position is inside the parent Room.
|
|
154
|
+
|
|
155
|
+
This will always be True if no parent is assigned.
|
|
156
|
+
"""
|
|
157
|
+
if self.parent is not None:
|
|
158
|
+
return self.parent.geometry.is_point_inside(self.sensor_position)
|
|
159
|
+
|
|
160
|
+
def move(self, moving_vec):
|
|
161
|
+
"""Move this object along a vector.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
moving_vec: A ladybug_geometry Vector3D with the direction and distance
|
|
165
|
+
to move the sensor.
|
|
166
|
+
"""
|
|
167
|
+
self.sensor_position = self.sensor_position.move(moving_vec)
|
|
168
|
+
|
|
169
|
+
def rotate(self, angle, axis, origin):
|
|
170
|
+
"""Rotate this object by a certain angle around an axis and origin.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
angle: An angle for rotation in degrees.
|
|
174
|
+
axis: Rotation axis as a Vector3D.
|
|
175
|
+
origin: A ladybug_geometry Point3D for the origin around which the
|
|
176
|
+
object will be rotated.
|
|
177
|
+
"""
|
|
178
|
+
rad_angle = math.radians(angle)
|
|
179
|
+
self.sensor_position = self.sensor_position.rotate(axis, rad_angle, origin)
|
|
180
|
+
|
|
181
|
+
def rotate_xy(self, angle, origin):
|
|
182
|
+
"""Rotate this object counterclockwise in the world XY plane by a certain angle.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
angle: An angle in degrees.
|
|
186
|
+
origin: A ladybug_geometry Point3D for the origin around which the
|
|
187
|
+
object will be rotated.
|
|
188
|
+
"""
|
|
189
|
+
rad_angle = math.radians(angle)
|
|
190
|
+
self.sensor_position = self.sensor_position.rotate_xy(rad_angle, origin)
|
|
191
|
+
|
|
192
|
+
def reflect(self, plane):
|
|
193
|
+
"""Reflect this object across a plane.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
plane: A ladybug_geometry Plane across which the object will
|
|
197
|
+
be reflected.
|
|
198
|
+
"""
|
|
199
|
+
self.sensor_position = self.sensor_position.reflect(plane.n, plane.o)
|
|
200
|
+
|
|
201
|
+
def scale(self, factor, origin=None):
|
|
202
|
+
"""Scale this object by a factor from an origin point.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
factor: A number representing how much the object should be scaled.
|
|
206
|
+
origin: A ladybug_geometry Point3D representing the origin from which
|
|
207
|
+
to scale. If None, it will be scaled from the World origin (0, 0, 0).
|
|
208
|
+
"""
|
|
209
|
+
self.sensor_position = self.sensor_position.scale(factor, origin)
|
|
210
|
+
|
|
211
|
+
@classmethod
|
|
212
|
+
def from_idf(cls, idf_string, idf_point_string):
|
|
213
|
+
"""Create a DaylightingControl object from an EnergyPlus IDF text string.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
idf_string: A text string fully describing an EnergyPlus
|
|
217
|
+
Daylighting:Controls definition.
|
|
218
|
+
idf_point_string: A text string fully describing an EnergyPlus
|
|
219
|
+
Daylighting:ReferencePoint definition.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
A DaylightingControl object loaded from the idf_string.
|
|
223
|
+
"""
|
|
224
|
+
# check the inputs
|
|
225
|
+
ep_strs = parse_idf_string(idf_string, 'Daylighting:Controls,')
|
|
226
|
+
ep_strs_pt = parse_idf_string(idf_point_string, 'Daylighting:ReferencePoint,')
|
|
227
|
+
assert ep_strs[1] == ep_strs_pt[1], 'Zone names do not match between ' \
|
|
228
|
+
'IDF daylight controls and reference point'
|
|
229
|
+
|
|
230
|
+
# extract the properties from the string
|
|
231
|
+
off_at_min = True if ep_strs[4].lower() == 'continuousoff' else False
|
|
232
|
+
min_power = ep_strs[5] if ep_strs[5] != '' else 0.3
|
|
233
|
+
min_output = ep_strs[6] if ep_strs[6] != '' else 0.2
|
|
234
|
+
cntrl_fract = 1
|
|
235
|
+
setpoint = 500
|
|
236
|
+
try:
|
|
237
|
+
cntrl_fract = ep_strs[14] if ep_strs[14] != '' else 1
|
|
238
|
+
setpoint = ep_strs[15] if ep_strs[15] != '' else 500
|
|
239
|
+
except IndexError:
|
|
240
|
+
pass # shorter daylight controls definition lacking certain fields
|
|
241
|
+
|
|
242
|
+
# extract the coordinates of the control point
|
|
243
|
+
ptx, pty = ep_strs_pt[2], ep_strs_pt[3]
|
|
244
|
+
try:
|
|
245
|
+
ptz = ep_strs_pt[4] if ep_strs_pt[4] != '' else 0.8
|
|
246
|
+
except IndexError:
|
|
247
|
+
pass # shorter definition lacking certain fields
|
|
248
|
+
|
|
249
|
+
# return the daylighting object
|
|
250
|
+
return cls(Point3D(ptx, pty, ptz), setpoint, cntrl_fract,
|
|
251
|
+
min_power, min_output, off_at_min)
|
|
252
|
+
|
|
253
|
+
@classmethod
|
|
254
|
+
def from_dict(cls, data):
|
|
255
|
+
"""Create a DaylightingControl object from a dictionary.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
data: A DaylightingControl dictionary in following the format below.
|
|
259
|
+
|
|
260
|
+
.. code-block:: python
|
|
261
|
+
|
|
262
|
+
{
|
|
263
|
+
"type": 'DaylightingControl',
|
|
264
|
+
"sensor_position": [5, 5, 0.8] # array of xyz coordinates for the sensor
|
|
265
|
+
"illuminance_setpoint": 300, # number for illuminance setpoint in lux
|
|
266
|
+
"control_fraction": 0.5, # fraction of the lights that are dim-able
|
|
267
|
+
"min_power_input": 0.3, # minimum fraction of lighting power
|
|
268
|
+
"min_light_output": 0.2, # minimum fraction of lighting output
|
|
269
|
+
"off_at_minimum": True # boolean for whether the lights switch off
|
|
270
|
+
}
|
|
271
|
+
"""
|
|
272
|
+
assert data['type'] == 'DaylightingControl', \
|
|
273
|
+
'Expected DaylightingControl dictionary. Got {}.'.format(data['type'])
|
|
274
|
+
sensor = Point3D.from_array(data['sensor_position'])
|
|
275
|
+
setpoint = data['illuminance_setpoint'] \
|
|
276
|
+
if 'illuminance_setpoint' in data else 300
|
|
277
|
+
cntrl_fract = data['control_fraction'] if 'control_fraction' in data else 1
|
|
278
|
+
min_pow = data['min_power_input'] if 'min_power_input' in data else 0.3
|
|
279
|
+
min_out = data['min_light_output'] if 'min_light_output' in data else 0.2
|
|
280
|
+
off_min = data['off_at_minimum'] if 'off_at_minimum' in data else False
|
|
281
|
+
return cls(sensor, setpoint, cntrl_fract, min_pow, min_out, off_min)
|
|
282
|
+
|
|
283
|
+
def to_idf(self):
|
|
284
|
+
"""IDF string representation of DaylightingControl object.
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
A tuple with two values.
|
|
288
|
+
|
|
289
|
+
- idf_control -- IDF string for the Daylighting:Controls object.
|
|
290
|
+
|
|
291
|
+
- idf_point -- IDF string for the Daylighting:ReferencePoint object.
|
|
292
|
+
|
|
293
|
+
.. code-block:: shell
|
|
294
|
+
|
|
295
|
+
Daylighting:Controls,
|
|
296
|
+
West Zone_DaylCtrl, !- Name
|
|
297
|
+
West Zone, !- Zone or Space Name
|
|
298
|
+
SplitFlux, !- Daylighting Method
|
|
299
|
+
, !- Availability Schedule Name
|
|
300
|
+
Continuous, !- Lighting Control Type
|
|
301
|
+
0.3, !- Minimum Input Power Fraction for Dimming
|
|
302
|
+
0.2, !- Minimum Light Output Fraction for Dimming
|
|
303
|
+
, !- Number of Stepped Control Steps
|
|
304
|
+
1.0, !- Probability Lighting Needs Reset
|
|
305
|
+
West Zone_DaylRefPt1, !- Glare Daylighting Reference Point Name
|
|
306
|
+
180.0, !- Glare Azimuth Angle of View Direction {deg}
|
|
307
|
+
20.0, !- Maximum Allowable Discomfort Glare Index
|
|
308
|
+
, !- DElight Gridding Resolution {m2}
|
|
309
|
+
West Zone_DaylRefPt1, !- Daylighting Reference Point 1 Name
|
|
310
|
+
1.0, !- Fraction of Lights Controlled by Point 1
|
|
311
|
+
500.; !- Illuminance Setpoint at Reference Point 1 {lux}
|
|
312
|
+
|
|
313
|
+
Daylighting:ReferencePoint,
|
|
314
|
+
West Zone_DaylRefPt1, !- Name
|
|
315
|
+
West Zone, !- Zone or Space Name
|
|
316
|
+
3.048, !- X-Coordinate of Reference Point {m}
|
|
317
|
+
3.048, !- Y-Coordinate of Reference Point {m}
|
|
318
|
+
0.9; !- Z-Coordinate of Reference Point {m}
|
|
319
|
+
"""
|
|
320
|
+
# create the identifiers
|
|
321
|
+
zone_id = self.parent.identifier if self.has_parent else 'Unknown_Room'
|
|
322
|
+
controls_name = '{}_Daylighting'.format(zone_id)
|
|
323
|
+
point_name = '{}_Sensor'.format(zone_id)
|
|
324
|
+
|
|
325
|
+
# create the IDF string for the Daylighting:Controls
|
|
326
|
+
cntrl_type = 'ContinuousOff' if self.off_at_minimum else 'Continuous'
|
|
327
|
+
cntrl_values = \
|
|
328
|
+
(controls_name, zone_id, 'SplitFlux', '', cntrl_type, self.min_power_input,
|
|
329
|
+
self.min_light_output, '', '', '', '', '', '', point_name,
|
|
330
|
+
self.control_fraction, self.illuminance_setpoint)
|
|
331
|
+
cntrl_comments = \
|
|
332
|
+
('name', 'zone name', 'daylight method', 'availability schedule',
|
|
333
|
+
'control type', 'min power input', 'min lighting input',
|
|
334
|
+
'control step count', 'reset probability', 'glare point', 'glare azimuth',
|
|
335
|
+
'max glare index', 'DElight grid res', 'reference point',
|
|
336
|
+
'control fraction', 'illuminance setpoint')
|
|
337
|
+
idf_control = generate_idf_string(
|
|
338
|
+
'Daylighting:Controls', cntrl_values, cntrl_comments)
|
|
339
|
+
|
|
340
|
+
# create the IDF string for the Daylighting:ReferencePoint
|
|
341
|
+
sensor = self.sensor_position
|
|
342
|
+
pt_values = (point_name, zone_id, sensor.x, sensor.y, sensor.z)
|
|
343
|
+
pt_comments = ('name', 'zone name', 'X', 'Y', 'Z')
|
|
344
|
+
idf_point = generate_idf_string(
|
|
345
|
+
'Daylighting:ReferencePoint', pt_values, pt_comments)
|
|
346
|
+
return idf_control, idf_point
|
|
347
|
+
|
|
348
|
+
def to_dict(self, abridged=False):
|
|
349
|
+
"""DaylightingControl dictionary representation.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
abridged: Boolean to note whether the full dictionary describing the
|
|
353
|
+
object should be returned (False) or just an abridged version (True),
|
|
354
|
+
which only specifies the identifiers of schedules. Default: False.
|
|
355
|
+
"""
|
|
356
|
+
return {
|
|
357
|
+
'type': 'DaylightingControl',
|
|
358
|
+
'sensor_position': self.sensor_position.to_array(),
|
|
359
|
+
'illuminance_setpoint': self.illuminance_setpoint,
|
|
360
|
+
'control_fraction': self.control_fraction,
|
|
361
|
+
'min_power_input': self.min_power_input,
|
|
362
|
+
'min_light_output': self.min_light_output,
|
|
363
|
+
'off_at_minimum': self.off_at_minimum
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
def duplicate(self):
|
|
367
|
+
"""Get a copy of this object."""
|
|
368
|
+
return self.__copy__()
|
|
369
|
+
|
|
370
|
+
def ToString(self):
|
|
371
|
+
"""Overwrite .NET ToString."""
|
|
372
|
+
return self.__repr__()
|
|
373
|
+
|
|
374
|
+
def __key(self):
|
|
375
|
+
"""A tuple based on the object properties, useful for hashing."""
|
|
376
|
+
return (hash(self.sensor_position), self.illuminance_setpoint,
|
|
377
|
+
self.control_fraction, self.min_power_input, self.min_light_output,
|
|
378
|
+
self.off_at_minimum)
|
|
379
|
+
|
|
380
|
+
def __hash__(self):
|
|
381
|
+
return hash(self.__key())
|
|
382
|
+
|
|
383
|
+
def __eq__(self, other):
|
|
384
|
+
return isinstance(other, DaylightingControl) and self.__key() == other.__key()
|
|
385
|
+
|
|
386
|
+
def __ne__(self, other):
|
|
387
|
+
return not self.__eq__(other)
|
|
388
|
+
|
|
389
|
+
def __copy__(self):
|
|
390
|
+
return DaylightingControl(
|
|
391
|
+
self.sensor_position, self.illuminance_setpoint, self.control_fraction,
|
|
392
|
+
self.min_power_input, self.min_light_output, self.off_at_minimum)
|
|
393
|
+
|
|
394
|
+
def __repr__(self):
|
|
395
|
+
pt = self.sensor_position
|
|
396
|
+
return 'DaylightingControl: [sensor: {}] [{} lux]'.format(
|
|
397
|
+
'(%.2f, %.2f, %.2f)' % (pt.x, pt.y, pt.z), self.illuminance_setpoint)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
"""Utilities to convert load dictionaries to Python objects."""
|
|
3
|
+
from honeybee_energy.load.people import People
|
|
4
|
+
from honeybee_energy.load.lighting import Lighting
|
|
5
|
+
from honeybee_energy.load.equipment import ElectricEquipment, GasEquipment
|
|
6
|
+
from honeybee_energy.load.infiltration import Infiltration
|
|
7
|
+
from honeybee_energy.load.ventilation import Ventilation
|
|
8
|
+
from honeybee_energy.load.setpoint import Setpoint
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
LOAD_TYPES = ('People', 'Lighting', 'ElectricEquipment', 'GasEquipment',
|
|
12
|
+
'Infiltration', 'Ventilation', 'Setpoint')
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def dict_to_load(load_dict, raise_exception=True):
|
|
16
|
+
"""Get a Python object of any Load from a dictionary.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
load_dict: A dictionary of any Honeybee energy load. Note
|
|
20
|
+
that this should be a non-abridged dictionary to be valid.
|
|
21
|
+
raise_exception: Boolean to note whether an excpetion should be raised
|
|
22
|
+
if the object is not identified as a load. Default: True.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
A Python object derived from the input load_dict.
|
|
26
|
+
"""
|
|
27
|
+
try: # get the type key from the dictionary
|
|
28
|
+
load_type = load_dict['type']
|
|
29
|
+
except KeyError:
|
|
30
|
+
raise ValueError('Load dictionary lacks required "type" key.')
|
|
31
|
+
|
|
32
|
+
if load_type == 'People':
|
|
33
|
+
return People.from_dict(load_dict)
|
|
34
|
+
elif load_type == 'Lighting':
|
|
35
|
+
return Lighting.from_dict(load_dict)
|
|
36
|
+
elif load_type == 'ElectricEquipment':
|
|
37
|
+
return ElectricEquipment.from_dict(load_dict)
|
|
38
|
+
elif load_type == 'GasEquipment':
|
|
39
|
+
return GasEquipment.from_dict(load_dict)
|
|
40
|
+
elif load_type == 'Infiltration':
|
|
41
|
+
return Infiltration.from_dict(load_dict)
|
|
42
|
+
elif load_type == 'Ventilation':
|
|
43
|
+
return Ventilation.from_dict(load_dict)
|
|
44
|
+
elif load_type == 'Setpoint':
|
|
45
|
+
return Setpoint.from_dict(load_dict)
|
|
46
|
+
elif raise_exception:
|
|
47
|
+
raise ValueError('{} is not a recognized energy Load type'.format(load_type))
|