honeybee-openstudio 2.0.3 → 2.1.0
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.
- checksums.yaml +4 -4
- data/honeybee-openstudio.gemspec +1 -1
- data/lib/from_honeybee.rb +1 -0
- data/lib/from_honeybee/_openapi/model.json +1417 -1176
- data/lib/from_honeybee/construction/window.rb +0 -1
- data/lib/from_honeybee/construction/windowshade.rb +207 -0
- data/lib/from_honeybee/model.rb +73 -36
- metadata +3 -2
@@ -0,0 +1,207 @@
|
|
1
|
+
# *******************************************************************************
|
2
|
+
# Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
|
3
|
+
# Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission from the respective party.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
20
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
21
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
23
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
24
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
25
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
26
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
28
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
29
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
# *******************************************************************************
|
31
|
+
|
32
|
+
require 'from_honeybee/model_object'
|
33
|
+
require 'from_honeybee/construction/window'
|
34
|
+
|
35
|
+
require 'openstudio'
|
36
|
+
|
37
|
+
module FromHoneybee
|
38
|
+
class WindowConstructionShadeAbridged < ModelObject
|
39
|
+
attr_reader :errors, :warnings
|
40
|
+
|
41
|
+
def initialize(hash = {})
|
42
|
+
super(hash)
|
43
|
+
@construction = nil
|
44
|
+
@shade_construction = nil
|
45
|
+
@shade_location = nil
|
46
|
+
@shade_material = nil
|
47
|
+
@control_type = nil
|
48
|
+
@setpoint = nil
|
49
|
+
@schedule = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def defaults
|
53
|
+
@@schema[:components][:schemas][:WindowConstructionShadeAbridged][:properties]
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_existing_openstudio_object(openstudio_model)
|
57
|
+
object = openstudio_model.getConstructionByName(@hash[:identifier])
|
58
|
+
return object.get if object.is_initialized
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_openstudio(openstudio_model)
|
63
|
+
# write the shaded and unsaded versions of the construciton into the model
|
64
|
+
# reverse the shaded and unshaded identifiers so unshaded one is assigned to apertures
|
65
|
+
unshd_id = @hash[:identifier]
|
66
|
+
shd_id = @hash[:window_construction][:identifier]
|
67
|
+
@hash[:window_construction][:identifier] = unshd_id
|
68
|
+
@hash[:identifier] = shd_id
|
69
|
+
|
70
|
+
# create the unshaded construction
|
71
|
+
unshd_constr_obj = WindowConstructionAbridged.new(@hash[:window_construction])
|
72
|
+
@construction = unshd_constr_obj.to_openstudio(openstudio_model)
|
73
|
+
|
74
|
+
# create the shaded construction
|
75
|
+
@shade_construction = OpenStudio::Model::Construction.new(openstudio_model)
|
76
|
+
@shade_construction.setName(shd_id)
|
77
|
+
|
78
|
+
# create the layers of the unshaded construction into which we will insert the shade
|
79
|
+
os_materials = []
|
80
|
+
@hash[:window_construction][:layers].each do |layer|
|
81
|
+
material_identifier = layer
|
82
|
+
material = openstudio_model.getMaterialByName(material_identifier)
|
83
|
+
unless material.empty?
|
84
|
+
os_material = material.get
|
85
|
+
os_materials << os_material
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# figure out where to insert the shade material and insert it
|
90
|
+
if @hash[:shade_location]
|
91
|
+
@shade_location = @hash[:shade_location]
|
92
|
+
else
|
93
|
+
@shade_location = defaults[:shade_location][:default]
|
94
|
+
end
|
95
|
+
|
96
|
+
# insert the shade material
|
97
|
+
shd_mat_name = openstudio_model.getMaterialByName(@hash[:shade_material])
|
98
|
+
unless shd_mat_name.empty?
|
99
|
+
@shade_material = shd_mat_name.get
|
100
|
+
end
|
101
|
+
unless @shade_material.nil?
|
102
|
+
if @shade_material.is_a? OpenStudio::Model::StandardGlazing
|
103
|
+
if @shade_location == 'Interior'
|
104
|
+
os_materials[-1] = @shade_material
|
105
|
+
elsif @shade_location == 'Exterior' | os_materials.length < 2
|
106
|
+
os_materials[0] = @shade_material
|
107
|
+
else # middle glass pane
|
108
|
+
os_materials[-3] = @shade_material
|
109
|
+
end
|
110
|
+
else
|
111
|
+
if @shade_location == 'Interior'
|
112
|
+
os_materials << @shade_material
|
113
|
+
elsif @shade_location == 'Exterior'
|
114
|
+
os_materials.unshift(@shade_material)
|
115
|
+
else # between glass shade/blind
|
116
|
+
split_gap = split_gas_gap(openstudio_model, os_materials[-2], @shade_material)
|
117
|
+
os_materials[-2] = split_gap
|
118
|
+
os_materials.insert(-2, @shade_material)
|
119
|
+
os_materials.insert(-2, split_gap)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# assign the layers to the shaded construction
|
125
|
+
os_materials_vec = OpenStudio::Model::MaterialVector.new
|
126
|
+
os_materials.each do |mat|
|
127
|
+
os_materials_vec << mat
|
128
|
+
end
|
129
|
+
@shade_construction.setLayers(os_materials)
|
130
|
+
|
131
|
+
# set defaults for control type, setpoint, and schedule
|
132
|
+
if @hash[:control_type]
|
133
|
+
@control_type = @hash[:control_type]
|
134
|
+
else
|
135
|
+
@control_type = defaults[:control_type][:default]
|
136
|
+
end
|
137
|
+
|
138
|
+
if @hash[:setpoint]
|
139
|
+
@setpoint = @hash[:setpoint]
|
140
|
+
else
|
141
|
+
@setpoint = defaults[:setpoint][:default]
|
142
|
+
end
|
143
|
+
|
144
|
+
unless @hash[:schedule].nil?
|
145
|
+
schedule_ref = openstudio_model.getScheduleByName(@hash[:schedule])
|
146
|
+
unless schedule_ref.empty?
|
147
|
+
@schedule = schedule_ref.get
|
148
|
+
if @control_type == 'AlwaysOn'
|
149
|
+
@control_type = 'OnIfScheduleAllows'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
@shade_construction
|
155
|
+
end
|
156
|
+
|
157
|
+
def to_openstudio_shading_control(openstudio_model)
|
158
|
+
# add a WindowShadingControl object to a model for a given aperture and room
|
159
|
+
os_shade_control = OpenStudio::Model::ShadingControl.new(@shade_construction)
|
160
|
+
|
161
|
+
# figure out the shading type
|
162
|
+
if @shade_material.is_a? OpenStudio::Model::StandardGlazing
|
163
|
+
shd_type = 'SwitchableGlazing'
|
164
|
+
elsif @shade_material.is_a? OpenStudio::Model::Blind
|
165
|
+
if @shade_location == 'Between'
|
166
|
+
shd_type = 'BetweenGlassBlind'
|
167
|
+
else
|
168
|
+
shd_type = @shade_location + 'Blind'
|
169
|
+
end
|
170
|
+
else
|
171
|
+
if @shade_location == 'Between'
|
172
|
+
shd_type = 'BetweenGlassShade'
|
173
|
+
else
|
174
|
+
shd_type = @shade_location + 'Shade'
|
175
|
+
end
|
176
|
+
end
|
177
|
+
os_shade_control.setShadingType(shd_type)
|
178
|
+
|
179
|
+
# set the shade control type and schedule
|
180
|
+
os_shade_control.setShadingControlType(@control_type)
|
181
|
+
unless @setpoint.nil?
|
182
|
+
os_shade_control.setSetpoint(@setpoint)
|
183
|
+
end
|
184
|
+
unless @schedule.nil?
|
185
|
+
os_shade_control.setSchedule(@schedule)
|
186
|
+
end
|
187
|
+
|
188
|
+
os_shade_control
|
189
|
+
end
|
190
|
+
|
191
|
+
def split_gas_gap(openstudio_model, original_gap, shade_material)
|
192
|
+
# split a gas gap material in two when it is interrupeted by a shade/blind
|
193
|
+
if shade_material.is_a? OpenStudio::Model::Blind
|
194
|
+
shd_thick = 0
|
195
|
+
else
|
196
|
+
shd_thick = shade_material.thickness
|
197
|
+
end
|
198
|
+
gap_thick = (original_gap.thickness - shd_thick) / 2
|
199
|
+
gap_obj = $gas_gap_hash[original_gap.name.get]
|
200
|
+
new_gap = gap_obj.to_openstudio(openstudio_model)
|
201
|
+
new_gap.setName(original_gap.name.get + gap_thick.to_s)
|
202
|
+
new_gap.setThickness(gap_thick)
|
203
|
+
new_gap
|
204
|
+
end
|
205
|
+
|
206
|
+
end #WindowConstructionShadeAbridged
|
207
|
+
end #FromHoneybee
|
data/lib/from_honeybee/model.rb
CHANGED
@@ -50,6 +50,7 @@ require 'from_honeybee/hvac/ideal_air'
|
|
50
50
|
# import the construction objects
|
51
51
|
require 'from_honeybee/construction/opaque'
|
52
52
|
require 'from_honeybee/construction/window'
|
53
|
+
require 'from_honeybee/construction/windowshade'
|
53
54
|
require 'from_honeybee/construction/shade'
|
54
55
|
require 'from_honeybee/construction/air'
|
55
56
|
|
@@ -184,12 +185,23 @@ module FromHoneybee
|
|
184
185
|
end
|
185
186
|
create_program_types
|
186
187
|
|
187
|
-
# create all of the model geometry
|
188
188
|
if log_report
|
189
189
|
puts 'Translating Room Geometry'
|
190
190
|
end
|
191
191
|
create_rooms
|
192
192
|
|
193
|
+
unless $window_shade_hash.empty?
|
194
|
+
if log_report
|
195
|
+
puts 'Translating Window Shading Control'
|
196
|
+
end
|
197
|
+
create_shading_control
|
198
|
+
end
|
199
|
+
|
200
|
+
if log_report
|
201
|
+
puts 'Translating HVAC Systems'
|
202
|
+
end
|
203
|
+
create_hvacs
|
204
|
+
|
193
205
|
if log_report
|
194
206
|
puts 'Translating Context Shade Geometry'
|
195
207
|
end
|
@@ -197,15 +209,11 @@ module FromHoneybee
|
|
197
209
|
create_orphaned_faces
|
198
210
|
create_orphaned_apertures
|
199
211
|
create_orphaned_doors
|
200
|
-
|
201
|
-
# create the hvac systems
|
202
|
-
if log_report
|
203
|
-
puts 'Translating HVAC Systems'
|
204
|
-
end
|
205
|
-
create_hvacs
|
206
212
|
end
|
207
213
|
|
208
214
|
def create_materials
|
215
|
+
$gas_gap_hash = Hash.new # hash to track gas gaps in case they are split by shades
|
216
|
+
|
209
217
|
@hash[:properties][:energy][:materials].each do |material|
|
210
218
|
material_type = material[:type]
|
211
219
|
|
@@ -216,8 +224,13 @@ module FromHoneybee
|
|
216
224
|
material_object = EnergyMaterialNoMass.new(material)
|
217
225
|
when 'EnergyWindowMaterialGas'
|
218
226
|
material_object = EnergyWindowMaterialGas.new(material)
|
227
|
+
$gas_gap_hash[material[:identifier]] = material_object
|
228
|
+
when 'EnergyWindowMaterialGasMixture'
|
229
|
+
material_object = EnergyWindowMaterialGasMixture.new(material)
|
230
|
+
$gas_gap_hash[material[:identifier]] = material_object
|
219
231
|
when 'EnergyWindowMaterialGasCustom'
|
220
232
|
material_object = EnergyWindowMaterialGasCustom.new(material)
|
233
|
+
$gas_gap_hash[material[:identifier]] = material_object
|
221
234
|
when 'EnergyWindowMaterialSimpleGlazSys'
|
222
235
|
material_object = EnergyWindowMaterialSimpleGlazSys.new(material)
|
223
236
|
when 'EnergyWindowMaterialBlind'
|
@@ -235,6 +248,7 @@ module FromHoneybee
|
|
235
248
|
|
236
249
|
def create_constructions
|
237
250
|
$air_boundary_hash = Hash.new # hash to track any air boundary constructions
|
251
|
+
$window_shade_hash = Hash.new # hash to track any window constructions with shade
|
238
252
|
|
239
253
|
@hash[:properties][:energy][:constructions].each do |construction|
|
240
254
|
identifier = construction[:identifier]
|
@@ -245,6 +259,9 @@ module FromHoneybee
|
|
245
259
|
construction_object = OpaqueConstructionAbridged.new(construction)
|
246
260
|
when 'WindowConstructionAbridged'
|
247
261
|
construction_object = WindowConstructionAbridged.new(construction)
|
262
|
+
when 'WindowConstructionShadeAbridged'
|
263
|
+
construction_object = WindowConstructionShadeAbridged.new(construction)
|
264
|
+
$window_shade_hash[construction[:identifier]] = construction_object
|
248
265
|
when 'ShadeConstruction'
|
249
266
|
construction_object = ShadeConstruction.new(construction)
|
250
267
|
when 'AirBoundaryConstructionAbridged'
|
@@ -344,7 +361,7 @@ module FromHoneybee
|
|
344
361
|
end
|
345
362
|
end
|
346
363
|
|
347
|
-
#
|
364
|
+
# create mixing objects between Rooms
|
348
365
|
$air_mxing_array.each do |air_mix_props|
|
349
366
|
zone_mixing = OpenStudio::Model::ZoneMixing.new(air_mix_props[0])
|
350
367
|
zone_mixing.setDesignFlowRate(air_mix_props[1])
|
@@ -361,35 +378,25 @@ module FromHoneybee
|
|
361
378
|
end
|
362
379
|
end
|
363
380
|
end
|
364
|
-
|
365
|
-
|
366
|
-
def create_orphaned_shades
|
367
|
-
if @hash[:orphaned_shades]
|
368
|
-
shading_surface_group = OpenStudio::Model::ShadingSurfaceGroup.new(@openstudio_model)
|
369
|
-
shading_surface_group.setShadingSurfaceType('Building')
|
370
|
-
@hash[:orphaned_shades].each do |shade|
|
371
|
-
shade_object = Shade.new(shade)
|
372
|
-
openstudio_shade = shade_object.to_openstudio(@openstudio_model)
|
373
|
-
openstudio_shade.setShadingSurfaceGroup(shading_surface_group)
|
374
|
-
end
|
375
|
-
end
|
376
|
-
end
|
377
381
|
|
378
|
-
def
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
382
|
+
def create_shading_control
|
383
|
+
# assign any shading control objects to windows with shades
|
384
|
+
# this is run as a separate step once all logic about construction sets is in place
|
385
|
+
sub_faces = @openstudio_model.getSubSurfaces()
|
386
|
+
sub_faces.each do |sub_face|
|
387
|
+
constr_ref = sub_face.construction
|
388
|
+
unless constr_ref.empty?
|
389
|
+
constr = constr_ref.get
|
390
|
+
constr_name_ref = constr.name
|
391
|
+
unless constr_name_ref.empty?
|
392
|
+
constr_name = constr_name_ref.get
|
393
|
+
unless $window_shade_hash[constr_name].nil?
|
394
|
+
window_shd_constr = $window_shade_hash[constr_name]
|
395
|
+
os_shd_control = window_shd_constr.to_openstudio_shading_control(@openstudio_model)
|
396
|
+
sub_face.setShadingControl(os_shd_control)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
393
400
|
end
|
394
401
|
end
|
395
402
|
|
@@ -428,6 +435,36 @@ module FromHoneybee
|
|
428
435
|
end
|
429
436
|
end
|
430
437
|
|
438
|
+
def create_orphaned_shades
|
439
|
+
if @hash[:orphaned_shades]
|
440
|
+
shading_surface_group = OpenStudio::Model::ShadingSurfaceGroup.new(@openstudio_model)
|
441
|
+
shading_surface_group.setShadingSurfaceType('Building')
|
442
|
+
@hash[:orphaned_shades].each do |shade|
|
443
|
+
shade_object = Shade.new(shade)
|
444
|
+
openstudio_shade = shade_object.to_openstudio(@openstudio_model)
|
445
|
+
openstudio_shade.setShadingSurfaceGroup(shading_surface_group)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
def create_orphaned_faces
|
451
|
+
if @hash[:orphaned_faces]
|
452
|
+
raise "Orphaned Faces are not translatable to OpenStudio."
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
def create_orphaned_apertures
|
457
|
+
if @hash[:orphaned_apertures]
|
458
|
+
raise "Orphaned Apertures are not translatable to OpenStudio."
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
def create_orphaned_doors
|
463
|
+
if @hash[:orphaned_doors]
|
464
|
+
raise "Orphaned Doors are not translatable to OpenStudio."
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
431
468
|
#TODO: create runlog for errors.
|
432
469
|
|
433
470
|
end # Model
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: honeybee-openstudio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tanushree Charan
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date: 2020-
|
14
|
+
date: 2020-06-02 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -171,6 +171,7 @@ files:
|
|
171
171
|
- lib/from_honeybee/construction/opaque.rb
|
172
172
|
- lib/from_honeybee/construction/shade.rb
|
173
173
|
- lib/from_honeybee/construction/window.rb
|
174
|
+
- lib/from_honeybee/construction/windowshade.rb
|
174
175
|
- lib/from_honeybee/construction_set.rb
|
175
176
|
- lib/from_honeybee/extension.rb
|
176
177
|
- lib/from_honeybee/geometry/aperture.rb
|