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,327 @@
|
|
|
1
|
+
"""honeybee energy commands for editing model energy properties."""
|
|
2
|
+
import click
|
|
3
|
+
import sys
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from honeybee.model import Model
|
|
9
|
+
from honeybee.typing import clean_rad_string
|
|
10
|
+
|
|
11
|
+
from honeybee_energy.schedule.fixedinterval import ScheduleFixedInterval
|
|
12
|
+
from honeybee_energy.lib.scheduletypelimits import fractional
|
|
13
|
+
from honeybee_energy.properties.model import ModelEnergyProperties
|
|
14
|
+
|
|
15
|
+
_logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.group(help='Commands for editing model energy properties.')
|
|
19
|
+
def edit():
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@edit.command('reset-resource-ids')
|
|
24
|
+
@click.argument('model-file', type=click.Path(
|
|
25
|
+
exists=True, file_okay=True, dir_okay=False, resolve_path=True))
|
|
26
|
+
@click.option(
|
|
27
|
+
'--by-name/--by-name-and-uuid', ' /-uuid', help='Flag to note whether '
|
|
28
|
+
'newly-generated resource object IDs should be derived only from a '
|
|
29
|
+
'cleaned display_name or whether this new ID should also have a unique '
|
|
30
|
+
'set of 8 characters appended to it to guarantee uniqueness.', default=True
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
'--reset-materials/--keep-materials', ' /-m', help='Flag to note whether '
|
|
34
|
+
'the IDs of all materials in the model should be reset.',
|
|
35
|
+
default=True, show_default=True
|
|
36
|
+
)
|
|
37
|
+
@click.option(
|
|
38
|
+
'--reset-constructions/--keep-constructions', ' /-c', help='Flag to note whether '
|
|
39
|
+
'the IDs of all constructions in the model should be reset.',
|
|
40
|
+
default=True, show_default=True
|
|
41
|
+
)
|
|
42
|
+
@click.option(
|
|
43
|
+
'--reset-construction-sets/--keep-construction-sets', ' /-cs', help='Flag to '
|
|
44
|
+
'note whether the IDs of all construction sets in the model should be reset.',
|
|
45
|
+
default=True, show_default=True
|
|
46
|
+
)
|
|
47
|
+
@click.option(
|
|
48
|
+
'--reset-schedules/--keep-schedules', ' /-s', help='Flag to note whether '
|
|
49
|
+
'the IDs of all schedules in the model should be reset.',
|
|
50
|
+
default=True, show_default=True
|
|
51
|
+
)
|
|
52
|
+
@click.option(
|
|
53
|
+
'--reset-programs/--keep-programs', ' /-p', help='Flag to note whether '
|
|
54
|
+
'the IDs of all programs in the model should be reset. This will also include '
|
|
55
|
+
'resetting the IDs of all load objects in the program.',
|
|
56
|
+
default=True, show_default=True
|
|
57
|
+
)
|
|
58
|
+
@click.option(
|
|
59
|
+
'--output-file', '-f', help='Optional hbjson file to output the JSON '
|
|
60
|
+
'string of the converted model. By default this will be printed out to '
|
|
61
|
+
'stdout', type=click.File('w'), default='-', show_default=True
|
|
62
|
+
)
|
|
63
|
+
def reset_resource_ids(
|
|
64
|
+
model_file, by_name,
|
|
65
|
+
reset_materials, reset_constructions, reset_construction_sets,
|
|
66
|
+
reset_schedules, reset_programs, output_file
|
|
67
|
+
):
|
|
68
|
+
"""Reset the identifiers of resource objects in a Model file.
|
|
69
|
+
|
|
70
|
+
This is useful when human-readable names are needed when the model is
|
|
71
|
+
exported to other formats like IDF and OSM and the uniqueness of the
|
|
72
|
+
identifiers is less of a concern.
|
|
73
|
+
|
|
74
|
+
\b
|
|
75
|
+
Args:
|
|
76
|
+
model_file: Full path to a Honeybee Model (HBJSON) file.
|
|
77
|
+
"""
|
|
78
|
+
try:
|
|
79
|
+
# load the model file and separately load up the resource objects
|
|
80
|
+
if sys.version_info < (3, 0):
|
|
81
|
+
with open(model_file) as inf:
|
|
82
|
+
data = json.load(inf)
|
|
83
|
+
else:
|
|
84
|
+
with open(model_file, encoding='utf-8') as inf:
|
|
85
|
+
data = json.load(inf)
|
|
86
|
+
# reset the identifiers of resources in the dictionary
|
|
87
|
+
add_uuid = not by_name
|
|
88
|
+
model_dict = ModelEnergyProperties.reset_resource_ids_in_dict(
|
|
89
|
+
data, add_uuid, reset_materials, reset_constructions,
|
|
90
|
+
reset_construction_sets, reset_schedules, reset_programs)
|
|
91
|
+
# write the dictionary into a JSON
|
|
92
|
+
output_file.write(json.dumps(model_dict))
|
|
93
|
+
except Exception as e:
|
|
94
|
+
_logger.exception('Resetting resource identifiers failed.\n{}'.format(e))
|
|
95
|
+
sys.exit(1)
|
|
96
|
+
else:
|
|
97
|
+
sys.exit(0)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@edit.command('modifiers-from-constructions')
|
|
101
|
+
@click.argument('model-file', type=click.Path(
|
|
102
|
+
exists=True, file_okay=True, dir_okay=False, resolve_path=True))
|
|
103
|
+
@click.option('--solar/--visible', ' /-v', help='Flag to note whether the assigned '
|
|
104
|
+
'radiance modifiers should follow the solar properties of the '
|
|
105
|
+
'constructions or the visible properties.', default=True)
|
|
106
|
+
@click.option('--dynamic-groups/--static-groups', ' /-sg', help='Flag to note whether '
|
|
107
|
+
'dynamic window constructions and shaded window constructions should '
|
|
108
|
+
'be translated to dynamic aperture groups or just the static (bare) '
|
|
109
|
+
'construction should be used.', default=True)
|
|
110
|
+
@click.option('--dynamic-shade/--static-shade', ' /-ss', help='Flag to note whether '
|
|
111
|
+
'dynamic shade transmittance schedules should be translated to dynamic '
|
|
112
|
+
'shade groups or just a static, fully-opaque construction should '
|
|
113
|
+
'be used.', default=True)
|
|
114
|
+
@click.option('--exterior-offset', '-o', help='A number for the distance at which the '
|
|
115
|
+
'exterior Room faces should be offset in meters. This is used to account '
|
|
116
|
+
'for the fact that the exterior material layer of the construction '
|
|
117
|
+
'usually needs a different modifier from the interior. If set to 0, '
|
|
118
|
+
'no offset will occur and all assigned modifiers will be interior.',
|
|
119
|
+
type=float, default=0, show_default=True)
|
|
120
|
+
@click.option('--output-file', '-f', help='Optional hbjson file to output the JSON '
|
|
121
|
+
'string of the converted model. By default this will be printed out to '
|
|
122
|
+
'stdout', type=click.File('w'), default='-', show_default=True)
|
|
123
|
+
def modifiers_from_constructions(
|
|
124
|
+
model_file, solar, dynamic_groups, dynamic_shade, exterior_offset, output_file
|
|
125
|
+
):
|
|
126
|
+
"""Assign honeybee Radiance modifiers based on energy construction properties.
|
|
127
|
+
|
|
128
|
+
Note that the honeybee-radiance extension must be installed in order for this
|
|
129
|
+
command to be run successfully.
|
|
130
|
+
|
|
131
|
+
Also note that setting the --exterior-offset to a non-zero value will add the
|
|
132
|
+
offset faces as orphaned faces, which changes how the model simulates in EnergyPlus.
|
|
133
|
+
|
|
134
|
+
\b
|
|
135
|
+
Args:
|
|
136
|
+
model_file: Full path to a Honeybee Model (HBJSON or HBpkl) file.
|
|
137
|
+
"""
|
|
138
|
+
try:
|
|
139
|
+
# import dependencies and set up reused variables
|
|
140
|
+
try:
|
|
141
|
+
from honeybee_radiance.lib.modifiers import air_boundary
|
|
142
|
+
from honeybee_radiance.dynamic.state import RadianceShadeState
|
|
143
|
+
except ImportError as e:
|
|
144
|
+
raise ImportError('honeybee_radiance library must be installed to use '
|
|
145
|
+
'modifiers-from-constructions method. {}'.format(e))
|
|
146
|
+
# re-serialize the Model to Python
|
|
147
|
+
model = Model.from_file(model_file)
|
|
148
|
+
# assign the radiance properties based on the interior energy constructions
|
|
149
|
+
if solar:
|
|
150
|
+
model.properties.energy.assign_radiance_solar_interior()
|
|
151
|
+
else:
|
|
152
|
+
model.properties.energy.assign_radiance_visible_interior()
|
|
153
|
+
# offset the exterior faces and give them modifiers for the exterior
|
|
154
|
+
if exterior_offset is not None and exterior_offset > 0:
|
|
155
|
+
exterior_offset = exterior_offset if model.units == 'Meters' else \
|
|
156
|
+
exterior_offset / model.conversion_factor_to_meters(model.units)
|
|
157
|
+
ref_type = 'Solar' if solar else 'Visible'
|
|
158
|
+
model.properties.energy.offset_and_assign_exterior_face_modifiers(
|
|
159
|
+
reflectance_type=ref_type, offset=exterior_offset
|
|
160
|
+
)
|
|
161
|
+
# assign trans modifiers for any shades with constant transmittance schedules
|
|
162
|
+
tr_sch_dict = {}
|
|
163
|
+
for shade in model.shades:
|
|
164
|
+
t_sch = shade.properties.energy.transmittance_schedule
|
|
165
|
+
if t_sch is not None:
|
|
166
|
+
if t_sch.is_constant: # just use a trans modifier
|
|
167
|
+
if solar:
|
|
168
|
+
shade.properties.radiance.modifier = \
|
|
169
|
+
shade.properties.energy.radiance_modifier_solar()
|
|
170
|
+
else:
|
|
171
|
+
shade.properties.radiance.modifier = \
|
|
172
|
+
shade.properties.energy.radiance_modifier_visible()
|
|
173
|
+
else: # represent the shade as a dynamic group
|
|
174
|
+
try:
|
|
175
|
+
tr_sch_dict[t_sch.identifier].append(shade)
|
|
176
|
+
except KeyError:
|
|
177
|
+
tr_sch_dict[t_sch.identifier] = [shade]
|
|
178
|
+
# assign dynamic shade groups if requested
|
|
179
|
+
if dynamic_shade:
|
|
180
|
+
for grp_name, group in tr_sch_dict.items():
|
|
181
|
+
grp_name = clean_rad_string(grp_name)
|
|
182
|
+
for shd in group:
|
|
183
|
+
shd.properties.radiance.dynamic_group_identifier = grp_name
|
|
184
|
+
on_state = RadianceShadeState(shd.properties.radiance.modifier)
|
|
185
|
+
off_state = RadianceShadeState(air_boundary)
|
|
186
|
+
shd.properties.radiance.states = [on_state, off_state]
|
|
187
|
+
# assign dynamic aperture groups if requested
|
|
188
|
+
if dynamic_groups:
|
|
189
|
+
model.properties.energy.assign_dynamic_aperture_groups()
|
|
190
|
+
# write the Model JSON string
|
|
191
|
+
output_file.write(json.dumps(model.to_dict()))
|
|
192
|
+
except Exception as e:
|
|
193
|
+
_logger.exception(
|
|
194
|
+
'Assignment of model radiance modifiers from energy construction '
|
|
195
|
+
'failed.\n{}'.format(e)
|
|
196
|
+
)
|
|
197
|
+
sys.exit(1)
|
|
198
|
+
else:
|
|
199
|
+
sys.exit(0)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@edit.command('lighting-from-daylight')
|
|
203
|
+
@click.argument('model-file', type=click.Path(
|
|
204
|
+
exists=True, file_okay=True, dir_okay=False, resolve_path=True))
|
|
205
|
+
@click.argument(
|
|
206
|
+
'daylight-folder',
|
|
207
|
+
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True)
|
|
208
|
+
)
|
|
209
|
+
@click.option(
|
|
210
|
+
'--ill-setpoint', '-i', help='A number for the illuminance setpoint in lux beyond '
|
|
211
|
+
'which electric lights are dimmed if there is sufficient daylight.',
|
|
212
|
+
default=300, type=int, show_default=True
|
|
213
|
+
)
|
|
214
|
+
@click.option(
|
|
215
|
+
'--min-power-in', '-p',
|
|
216
|
+
help='A number between 0 and 1 for the the lowest power the lighting system can '
|
|
217
|
+
'dim down to, expressed as a fraction of maximum input power.', default=0.3,
|
|
218
|
+
type=float, show_default=True
|
|
219
|
+
)
|
|
220
|
+
@click.option(
|
|
221
|
+
'--min-light-out', '-l',
|
|
222
|
+
help='A number between 0 and 1 the lowest lighting output the lighting system can '
|
|
223
|
+
'dim down to, expressed as a fraction of maximum light output. Note that setting '
|
|
224
|
+
'this to 1 means lights are not dimmed at all until the illuminance setpoint is '
|
|
225
|
+
'reached. This can be used to approximate manual light-switching behavior when '
|
|
226
|
+
'used in conjunction with the --off_at_min output below.', default=0.2,
|
|
227
|
+
type=float, show_default=True
|
|
228
|
+
)
|
|
229
|
+
@click.option(
|
|
230
|
+
'--on-at-min/--off-at-min', ' /-oam', help='Flag to note whether lights should '
|
|
231
|
+
'switch off completely when they get to the minimum power input.',
|
|
232
|
+
default=True, show_default=True
|
|
233
|
+
)
|
|
234
|
+
@click.option(
|
|
235
|
+
'--output-file', '-f', help='Optional hbjson file to output the JSON '
|
|
236
|
+
'string of the converted model. By default this will be printed out to '
|
|
237
|
+
'stdout', type=click.File('w'), default='-', show_default=True
|
|
238
|
+
)
|
|
239
|
+
def lighting_from_daylight(
|
|
240
|
+
model_file, daylight_folder, ill_setpoint, min_power_in, min_light_out,
|
|
241
|
+
on_at_min, output_file
|
|
242
|
+
):
|
|
243
|
+
"""Assign HB-energy lighting schedules using Radiance annual-daylight results.
|
|
244
|
+
|
|
245
|
+
Note that the honeybee-radiance extension must be installed in order for this
|
|
246
|
+
command to be run successfully.
|
|
247
|
+
|
|
248
|
+
Also note that the Honeybee model must have sensor grids with room_identifiers
|
|
249
|
+
assigned to them for them to affect the HB-Energy lighting schedules. If such
|
|
250
|
+
grids are found, the lighting schedules of the Rooms will be adjusted according
|
|
251
|
+
to whether the illuminance values at the sensor locations are at a target
|
|
252
|
+
illuminance setpoint.
|
|
253
|
+
|
|
254
|
+
Each grid should have sensors at the locations in space where daylight dimming
|
|
255
|
+
sensors are located. Grids with two or more sensors can be used to model setups
|
|
256
|
+
where fractions of each room are controlled by different sensors. If the sensor
|
|
257
|
+
grids are distributed over the entire floor of the rooms, the resulting schedules
|
|
258
|
+
will be idealized, where light dimming has been optimized to supply the minimum
|
|
259
|
+
illuminance setpoint everywhere in the room.
|
|
260
|
+
|
|
261
|
+
\b
|
|
262
|
+
Args:
|
|
263
|
+
model_file: Full path to a Honeybee Model (HBJSON or HBpkl) file.
|
|
264
|
+
daylight_folder: Path to an annual-daylight results folder. This folder is
|
|
265
|
+
an output folder of the annual daylight recipe. The folder should
|
|
266
|
+
include grids_info.json and sun-up-hours.txt. The command uses the
|
|
267
|
+
list in grids_info.json to find the result files for each sensor grid.
|
|
268
|
+
"""
|
|
269
|
+
try:
|
|
270
|
+
# load up relevant honeybee-radiance dependencies
|
|
271
|
+
try:
|
|
272
|
+
from honeybee_radiance.postprocess.annualdaylight import \
|
|
273
|
+
_process_input_folder
|
|
274
|
+
from honeybee_radiance.postprocess.electriclight import \
|
|
275
|
+
_file_to_dimming_fraction
|
|
276
|
+
except ImportError as e:
|
|
277
|
+
raise ImportError('honeybee_radiance library must be installed to use '
|
|
278
|
+
'lighting-from-daylight. {}'.format(e))
|
|
279
|
+
|
|
280
|
+
# re-serialize the Model to Python and get a map from grids to room IDs
|
|
281
|
+
model = Model.from_file(model_file)
|
|
282
|
+
room_map = {}
|
|
283
|
+
for grid in model.properties.radiance.sensor_grids:
|
|
284
|
+
room_map[grid.room_identifier] = grid.full_identifier
|
|
285
|
+
|
|
286
|
+
# get the dimming fractions for each sensor grid from the .ill files
|
|
287
|
+
grids, sun_up_hours = _process_input_folder(daylight_folder, '*')
|
|
288
|
+
sun_up_hours = [int(h) for h in sun_up_hours]
|
|
289
|
+
off_at_min = not on_at_min
|
|
290
|
+
dim_fracts = {}
|
|
291
|
+
for grid_info in grids:
|
|
292
|
+
ill_file = os.path.join(daylight_folder, '%s.ill' % grid_info['full_id'])
|
|
293
|
+
fract_list = _file_to_dimming_fraction(
|
|
294
|
+
ill_file, sun_up_hours, ill_setpoint, min_power_in,
|
|
295
|
+
min_light_out, off_at_min
|
|
296
|
+
)
|
|
297
|
+
dim_fracts[grid_info['full_id']] = fract_list
|
|
298
|
+
|
|
299
|
+
# loop through the rooms of the model and assign the lighting dimming
|
|
300
|
+
for room in model.rooms:
|
|
301
|
+
light = room.properties.energy.lighting
|
|
302
|
+
if light is not None:
|
|
303
|
+
base_schedule = light.schedule.values_at_timestep(1) \
|
|
304
|
+
if isinstance(light.schedule, ScheduleFixedInterval) \
|
|
305
|
+
else light.schedule.values(1)
|
|
306
|
+
try:
|
|
307
|
+
dim_fract = dim_fracts[room_map[room.identifier]]
|
|
308
|
+
sch_vals = [b_val * d_val for b_val, d_val in
|
|
309
|
+
zip(base_schedule, dim_fract)]
|
|
310
|
+
sch_id = '{} Daylight Control'.format(room.identifier)
|
|
311
|
+
new_sch = ScheduleFixedInterval(sch_id, sch_vals, fractional)
|
|
312
|
+
new_light = light.duplicate()
|
|
313
|
+
new_light.schedule = new_sch
|
|
314
|
+
room.properties.energy.lighting = new_light
|
|
315
|
+
except KeyError:
|
|
316
|
+
pass # no grid is associated with the room
|
|
317
|
+
|
|
318
|
+
# write the Model JSON string
|
|
319
|
+
output_file.write(json.dumps(model.to_dict()))
|
|
320
|
+
except Exception as e:
|
|
321
|
+
_logger.exception(
|
|
322
|
+
'Assignment of model lighting schedules from annual-daylight results '
|
|
323
|
+
'failed.\n{}'.format(e)
|
|
324
|
+
)
|
|
325
|
+
sys.exit(1)
|
|
326
|
+
else:
|
|
327
|
+
sys.exit(0)
|