honeybee-openstudio 0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +5 -5
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +32 -33
  4. data/.releaserc.json +7 -7
  5. data/.travis.yml +41 -0
  6. data/Gemfile +18 -14
  7. data/LICENSE.md +23 -23
  8. data/README.md +95 -95
  9. data/Rakefile +21 -16
  10. data/doc_templates/LICENSE.md +23 -23
  11. data/doc_templates/copyright_erb.txt +31 -31
  12. data/doc_templates/copyright_js.txt +4 -4
  13. data/doc_templates/copyright_ruby.txt +29 -29
  14. data/honeybee-openstudio.gemspec +35 -38
  15. data/lib/files/Honeybee.rb +112 -112
  16. data/lib/files/honeybee_workflow.osw +47 -47
  17. data/lib/files/urbanopt_Gemfile +32 -32
  18. data/lib/{honeybee/_defaults → from_honeybee/_openapi}/model.json +8126 -11310
  19. data/lib/{honeybee/_defaults → from_honeybee/_openapi}/simulation-parameter.json +842 -972
  20. data/lib/{to_openstudio → from_honeybee}/construction/air.rb +65 -56
  21. data/lib/{to_openstudio → from_honeybee}/construction/opaque.rb +77 -67
  22. data/lib/{to_openstudio → from_honeybee}/construction/shade.rb +108 -99
  23. data/lib/{to_openstudio → from_honeybee}/construction/window.rb +80 -70
  24. data/lib/{to_openstudio → from_honeybee}/construction_set.rb +278 -266
  25. data/lib/{honeybee → from_honeybee}/extension.rb +109 -129
  26. data/lib/{to_openstudio → from_honeybee}/geometry/aperture.rb +167 -157
  27. data/lib/{to_openstudio → from_honeybee}/geometry/door.rb +160 -150
  28. data/lib/{to_openstudio → from_honeybee}/geometry/face.rb +163 -178
  29. data/lib/{to_openstudio → from_honeybee}/geometry/room.rb +392 -442
  30. data/lib/{to_openstudio → from_honeybee}/geometry/shade.rb +89 -79
  31. data/lib/{to_openstudio → from_honeybee}/hvac/ideal_air.rb +150 -141
  32. data/lib/{to_openstudio → from_honeybee}/load/electric_equipment.rb +96 -87
  33. data/lib/{to_openstudio → from_honeybee}/load/gas_equipment.rb +97 -88
  34. data/lib/{to_openstudio → from_honeybee}/load/infiltration.rb +94 -85
  35. data/lib/{to_openstudio → from_honeybee}/load/lighting.rb +98 -89
  36. data/lib/{to_openstudio → from_honeybee}/load/people.rb +100 -91
  37. data/lib/{to_openstudio → from_honeybee}/load/setpoint_humidistat.rb +75 -66
  38. data/lib/{to_openstudio → from_honeybee}/load/setpoint_thermostat.rb +71 -62
  39. data/lib/{to_openstudio → from_honeybee}/load/ventilation.rb +96 -87
  40. data/lib/{to_openstudio → from_honeybee}/material/opaque.rb +94 -85
  41. data/lib/{to_openstudio → from_honeybee}/material/opaque_no_mass.rb +94 -85
  42. data/lib/{to_openstudio → from_honeybee}/material/window_blind.rb +238 -229
  43. data/lib/{to_openstudio → from_honeybee}/material/window_gas.rb +76 -67
  44. data/lib/{to_openstudio → from_honeybee}/material/window_gas_custom.rb +118 -108
  45. data/lib/{to_openstudio → from_honeybee}/material/window_gas_mixture.rb +79 -70
  46. data/lib/{to_openstudio → from_honeybee}/material/window_glazing.rb +166 -157
  47. data/lib/{to_openstudio → from_honeybee}/material/window_shade.rb +160 -151
  48. data/lib/{to_openstudio → from_honeybee}/material/window_simpleglazsys.rb +73 -64
  49. data/lib/from_honeybee/model.rb +434 -0
  50. data/lib/{honeybee → from_honeybee}/model_object.rb +110 -108
  51. data/lib/{to_openstudio → from_honeybee}/program_type.rb +124 -104
  52. data/lib/{to_openstudio → from_honeybee}/schedule/fixed_interval.rb +115 -105
  53. data/lib/{to_openstudio → from_honeybee}/schedule/ruleset.rb +164 -164
  54. data/lib/{to_openstudio → from_honeybee}/schedule/type_limit.rb +88 -76
  55. data/lib/{to_openstudio/simulation/design_day.rb → from_honeybee/simulation/designday.rb} +105 -96
  56. data/lib/{honeybee/load/lighting.rb → from_honeybee/simulation/extension.rb} +46 -43
  57. data/lib/{to_openstudio/simulation/parameter_model.rb → from_honeybee/simulation/parameter.rb} +277 -243
  58. data/lib/{honeybee/simulation/design_day.rb → from_honeybee/version.rb} +34 -42
  59. data/lib/{honeybee.rb → from_honeybee.rb} +86 -93
  60. data/lib/measures/from_honeybee_model/LICENSE.md +27 -23
  61. data/lib/measures/from_honeybee_model/README.md +32 -32
  62. data/lib/measures/from_honeybee_model/measure.rb +91 -91
  63. data/lib/measures/from_honeybee_model/measure.xml +103 -80
  64. data/lib/measures/from_honeybee_model/tests/from_honeybee_model_test.rb +126 -126
  65. data/lib/measures/from_honeybee_simulation_parameter/LICENSE.md +27 -23
  66. data/lib/measures/from_honeybee_simulation_parameter/README.md +32 -32
  67. data/lib/measures/from_honeybee_simulation_parameter/measure.rb +95 -95
  68. data/lib/measures/from_honeybee_simulation_parameter/measure.xml +91 -86
  69. data/lib/measures/from_honeybee_simulation_parameter/tests/from_honeybee_simulation_parameter_test.rb +109 -109
  70. metadata +89 -147
  71. data/.github/workflows/ci.yaml +0 -88
  72. data/doc_templates/README.md.erb +0 -42
  73. data/lib/from_openstudio/geometry/aperture.rb +0 -136
  74. data/lib/from_openstudio/geometry/door.rb +0 -136
  75. data/lib/from_openstudio/geometry/face.rb +0 -174
  76. data/lib/from_openstudio/geometry/room.rb +0 -121
  77. data/lib/from_openstudio/geometry/shade.rb +0 -87
  78. data/lib/from_openstudio/model.rb +0 -123
  79. data/lib/from_openstudio/model_object.rb +0 -43
  80. data/lib/from_openstudio/simulation/design_day.rb +0 -123
  81. data/lib/from_openstudio/simulation/parameter_model.rb +0 -93
  82. data/lib/from_openstudio/simulation/simulation_output.rb +0 -67
  83. data/lib/from_openstudio.rb +0 -49
  84. data/lib/honeybee/_defaults/energy_default.json +0 -1682
  85. data/lib/honeybee/construction/air.rb +0 -42
  86. data/lib/honeybee/construction/opaque.rb +0 -42
  87. data/lib/honeybee/construction/shade.rb +0 -42
  88. data/lib/honeybee/construction/window.rb +0 -51
  89. data/lib/honeybee/construction/windowshade.rb +0 -43
  90. data/lib/honeybee/construction_set.rb +0 -42
  91. data/lib/honeybee/geometry/aperture.rb +0 -42
  92. data/lib/honeybee/geometry/door.rb +0 -42
  93. data/lib/honeybee/geometry/face.rb +0 -48
  94. data/lib/honeybee/geometry/room.rb +0 -56
  95. data/lib/honeybee/geometry/shade.rb +0 -42
  96. data/lib/honeybee/hvac/ideal_air.rb +0 -42
  97. data/lib/honeybee/hvac/template.rb +0 -73
  98. data/lib/honeybee/load/electric_equipment.rb +0 -42
  99. data/lib/honeybee/load/gas_equipment.rb +0 -42
  100. data/lib/honeybee/load/infiltration.rb +0 -42
  101. data/lib/honeybee/load/people.rb +0 -42
  102. data/lib/honeybee/load/setpoint_humidistat.rb +0 -46
  103. data/lib/honeybee/load/setpoint_thermostat.rb +0 -46
  104. data/lib/honeybee/load/ventilation.rb +0 -42
  105. data/lib/honeybee/material/opaque.rb +0 -42
  106. data/lib/honeybee/material/opaque_no_mass.rb +0 -42
  107. data/lib/honeybee/material/window_blind.rb +0 -42
  108. data/lib/honeybee/material/window_gas.rb +0 -42
  109. data/lib/honeybee/material/window_gas_custom.rb +0 -42
  110. data/lib/honeybee/material/window_gas_mixture.rb +0 -42
  111. data/lib/honeybee/material/window_glazing.rb +0 -42
  112. data/lib/honeybee/material/window_shade.rb +0 -42
  113. data/lib/honeybee/material/window_simpleglazsys.rb +0 -42
  114. data/lib/honeybee/model.rb +0 -87
  115. data/lib/honeybee/program_type.rb +0 -56
  116. data/lib/honeybee/schedule/fixed_interval.rb +0 -42
  117. data/lib/honeybee/schedule/ruleset.rb +0 -42
  118. data/lib/honeybee/schedule/type_limit.rb +0 -42
  119. data/lib/honeybee/simulation/parameter_model.rb +0 -86
  120. data/lib/honeybee/simulation/simulation_output.rb +0 -42
  121. data/lib/honeybee/ventcool/control.rb +0 -42
  122. data/lib/honeybee/ventcool/opening.rb +0 -46
  123. data/lib/honeybee/ventcool/simulation.rb +0 -42
  124. data/lib/to_openstudio/construction/windowshade.rb +0 -196
  125. data/lib/to_openstudio/hvac/Model.hvac.rb +0 -641
  126. data/lib/to_openstudio/hvac/template.rb +0 -169
  127. data/lib/to_openstudio/model.rb +0 -497
  128. data/lib/to_openstudio/model_object.rb +0 -52
  129. data/lib/to_openstudio/ventcool/control.rb +0 -185
  130. data/lib/to_openstudio/ventcool/opening.rb +0 -189
  131. data/lib/to_openstudio/ventcool/simulation.rb +0 -101
  132. data/lib/to_openstudio.rb +0 -92
@@ -1,442 +1,392 @@
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 'honeybee/geometry/room'
33
-
34
- require 'to_openstudio/model_object'
35
-
36
- module Honeybee
37
- class Room
38
-
39
- attr_reader :unique_space_type
40
-
41
- def find_existing_openstudio_object(openstudio_model)
42
- model_space = openstudio_model.getSpaceByName(@hash[:identifier])
43
- return model_space.get unless model_space.empty?
44
- nil
45
- end
46
-
47
- def get_unique_space_type(openstudio_model, os_space)
48
- # get a space type that is unique to the room
49
- if @unique_space_type.nil?
50
- space_type = os_space.spaceType
51
- unless space_type.empty?
52
- # copy the space type that is already assigned to the room
53
- space_type_object = space_type.get
54
- space_type_mod_obj = space_type_object.clone(openstudio_model)
55
- new_space_type = space_type_mod_obj.to_SpaceType.get
56
- # give the space type a new unique name and assign it to the room
57
- st_name = space_type_object.name
58
- unless space_type.empty?
59
- st_name = st_name.get
60
- else
61
- st_name = 'CustomSpaceType'
62
- end
63
- else
64
- # create a new space type as there is currently none assigned to the room
65
- new_space_type = OpenStudio::Model::SpaceType.new(openstudio_model)
66
- st_name = 'CustomSpaceType'
67
- end
68
- new_space_type.setName(st_name + '_' + @hash[:identifier])
69
- os_space.setSpaceType(new_space_type)
70
- @unique_space_type = new_space_type
71
- end
72
- @unique_space_type
73
- end
74
-
75
- def to_openstudio(openstudio_model)
76
- # create the space and thermal zone
77
- os_space = OpenStudio::Model::Space.new(openstudio_model)
78
- os_space.setName(@hash[:identifier])
79
- os_thermal_zone = OpenStudio::Model::ThermalZone.new(openstudio_model)
80
- os_thermal_zone.setName(@hash[:identifier])
81
- os_space.setThermalZone(os_thermal_zone)
82
-
83
- # assign the programtype
84
- if @hash[:properties][:energy][:program_type]
85
- space_type = openstudio_model.getSpaceTypeByName(@hash[:properties][:energy][:program_type])
86
- unless space_type.empty?
87
- space_type_object = space_type.get
88
- os_space.setSpaceType(space_type_object)
89
- end
90
- end
91
-
92
- # assign the constructionset
93
- if @hash[:properties][:energy][:construction_set]
94
- construction_set_identifier = @hash[:properties][:energy][:construction_set]
95
- # gets default construction set assigned to room from openstudio_model
96
- construction_set = openstudio_model.getDefaultConstructionSetByName(construction_set_identifier)
97
- unless construction_set.empty?
98
- default_construction_set = construction_set.get
99
- os_space.setDefaultConstructionSet(default_construction_set)
100
- end
101
- end
102
-
103
- # assign the multiplier
104
- if @hash[:multiplier] and @hash[:multiplier] != 1
105
- os_thermal_zone.setMultiplier(@hash[:multiplier])
106
- end
107
-
108
- # assign the story
109
- if @hash[:story] # the users has specified the name of the story
110
- story = openstudio_model.getBuildingStoryByName(@hash[:story])
111
- if story.empty? # first time that this story has been referenced
112
- story = OpenStudio::Model::BuildingStory.new(openstudio_model)
113
- story.setName(@hash[:story])
114
- else
115
- story = story.get
116
- end
117
- else # give the room a dummy story so that it works with David's measures
118
- story = openstudio_model.getBuildingStoryByName('UndefiniedStory')
119
- if story.empty? # first time that this story has been referenced
120
- story = OpenStudio::Model::BuildingStory.new(openstudio_model)
121
- story.setName('UndefiniedStory')
122
- else
123
- story = story.get
124
- end
125
- end
126
- os_space.setBuildingStory(story)
127
-
128
- # keep track of all window ventilation objects
129
- window_vent = {}
130
-
131
- # assign all of the faces to the room
132
- @hash[:faces].each do |face|
133
- ladybug_face = Face.new(face)
134
- os_surface = ladybug_face.to_openstudio(openstudio_model)
135
- os_surface.setSpace(os_space)
136
-
137
- # assign face-level shades if they exist
138
- if face[:outdoor_shades]
139
- os_shd_group = make_shade_group(openstudio_model, os_surface, os_space)
140
- face[:outdoor_shades].each do |outdoor_shade|
141
- add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
142
- end
143
- end
144
-
145
- # assign aperture-level shades if they exist
146
- if face[:apertures]
147
- face[:apertures].each do |aperture|
148
- if aperture[:properties][:energy][:vent_opening]
149
- window_vent[aperture[:identifier]] = \
150
- [aperture[:properties][:energy][:vent_opening], aperture[:boundary_condition][:type]]
151
- end
152
- if aperture[:outdoor_shades]
153
- unless os_shd_group
154
- os_shd_group = make_shade_group(openstudio_model, os_surface, os_space)
155
- end
156
- aperture[:outdoor_shades].each do |outdoor_shade|
157
- add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
158
- end
159
- end
160
- end
161
- end
162
-
163
- # assign door-level shades if they exist
164
- if face[:doors]
165
- face[:doors].each do |door|
166
- if door[:properties][:energy][:vent_opening]
167
- window_vent[door[:identifier]] = \
168
- [door[:properties][:energy][:vent_opening], door[:boundary_condition][:type]]
169
- end
170
- if door[:outdoor_shades]
171
- unless os_shd_group
172
- os_shd_group = make_shade_group(openstudio_model, os_surface, os_space)
173
- end
174
- door[:outdoor_shades].each do |outdoor_shade|
175
- add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
176
- end
177
- end
178
- end
179
- end
180
-
181
- if !face[:properties][:energy][:construction]
182
- if face[:boundary_condition][:type] == 'Adiabatic'
183
- # assign default interior construciton for Adiabatic Faces
184
- if face[:face_type] != 'Wall'
185
- interior_construction = closest_interior_construction(openstudio_model, os_space, face[:face_type])
186
- unless interior_construction.nil?
187
- os_surface.setConstruction(interior_construction)
188
- end
189
- end
190
- elsif face[:face_type] == 'AirBoundary'
191
- # assign default air boundary construciton for AirBoundary face types
192
- air_construction = closest_air_construction(openstudio_model, os_space)
193
- unless air_construction.nil?
194
- os_surface.setConstruction(air_construction)
195
- end
196
- # add air mixing properties to the global list that tracks them
197
- if $use_simple_vent # only use air mixing objects when simple ventilation is requested
198
- air_hash = $air_boundary_hash[air_construction.name.to_s]
199
- if air_hash[:air_mixing_per_area]
200
- air_mix_area = air_hash[:air_mixing_per_area]
201
- else
202
- air_default = @@schema[:components][:schemas][:AirBoundaryConstructionAbridged]
203
- air_mix_area = air_default[:properties][:air_mixing_per_area][:default]
204
- end
205
- flow_rate = os_surface.netArea * air_mix_area
206
- flow_sch_id = air_hash[:air_mixing_schedule]
207
- adj_zone_id = face[:boundary_condition][:boundary_condition_objects][-1]
208
- $air_mxing_array << [os_thermal_zone, flow_rate, flow_sch_id, adj_zone_id]
209
- end
210
- end
211
- end
212
- end
213
-
214
- # assign any room-level outdoor shades if they exist
215
- if @hash[:outdoor_shades]
216
- os_shd_group = OpenStudio::Model::ShadingSurfaceGroup.new(openstudio_model)
217
- os_shd_group.setSpace(os_space)
218
- os_shd_group.setShadingSurfaceType("Space")
219
- @hash[:outdoor_shades].each do |outdoor_shade|
220
- add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
221
- end
222
- end
223
-
224
- #check whether there are any load objects on the room overriding the programtype
225
- if @hash[:properties][:energy][:people]
226
- unique_program = get_unique_space_type(openstudio_model, os_space)
227
- unique_program_ppl = unique_program.people
228
- unless unique_program_ppl.empty? # remove the previous load definition
229
- unique_program_ppl[0].remove()
230
- end
231
- custom_people = PeopleAbridged.new(@hash[:properties][:energy][:people])
232
- os_custom_people = custom_people.to_openstudio(openstudio_model)
233
- os_custom_people.setSpaceType(unique_program) # assign the new load definition
234
- end
235
-
236
- # assign lighting if it exists
237
- if @hash[:properties][:energy][:lighting]
238
- unique_program = get_unique_space_type(openstudio_model, os_space)
239
- unique_program_lght = unique_program.lights
240
- unless unique_program_lght.empty? # remove the previous load definition
241
- unique_program_lght[0].remove()
242
- end
243
- custom_lighting = LightingAbridged.new(@hash[:properties][:energy][:lighting])
244
- os_custom_lighting = custom_lighting.to_openstudio(openstudio_model)
245
- os_custom_lighting.setSpaceType(unique_program) # assign the new load definition
246
- end
247
-
248
- # assign electric equipment if it exists
249
- if @hash[:properties][:energy][:electric_equipment]
250
- unique_program = get_unique_space_type(openstudio_model, os_space)
251
- unique_program_ele = unique_program.electricEquipment
252
- unless unique_program_ele.empty? # remove the previous load definition
253
- unique_program_ele[0].remove()
254
- end
255
- custom_electric_equipment = ElectricEquipmentAbridged.new(@hash[:properties][:energy][:electric_equipment])
256
- os_custom_electric_equipment = custom_electric_equipment.to_openstudio(openstudio_model)
257
- os_custom_electric_equipment.setSpaceType(unique_program) # assign the new load definition
258
- end
259
-
260
- # assign gas equipment if it exists
261
- if @hash[:properties][:energy][:gas_equipment]
262
- unique_program = get_unique_space_type(openstudio_model, os_space)
263
- unique_program_gas = unique_program.gasEquipment
264
- unless unique_program_gas.empty? # remove the previous load definition
265
- unique_program_gas[0].remove()
266
- end
267
- custom_gas_equipment = GasEquipmentAbridged.new(@hash[:properties][:energy][:gas_equipment])
268
- os_custom_gas_equipment = custom_gas_equipment.to_openstudio(openstudio_model)
269
- os_custom_gas_equipment.setSpaceType(unique_program) # assign the new load definition
270
- end
271
-
272
- # assign infiltration if it exists
273
- if @hash[:properties][:energy][:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
274
- unique_program = get_unique_space_type(openstudio_model, os_space)
275
- unique_program_inf = unique_program.spaceInfiltrationDesignFlowRates
276
- unless unique_program_inf.empty? # remove the previous load definition
277
- unique_program_inf[0].remove()
278
- end
279
- custom_infiltration = InfiltrationAbridged.new(@hash[:properties][:energy][:infiltration])
280
- os_custom_infiltration = custom_infiltration.to_openstudio(openstudio_model)
281
- os_custom_infiltration.setSpaceType(unique_program) # assign the new load definition
282
- end
283
-
284
- # assign ventilation if it exists
285
- if @hash[:properties][:energy][:ventilation]
286
- unique_program = get_unique_space_type(openstudio_model, os_space)
287
- unique_program.resetDesignSpecificationOutdoorAir()
288
- custom_ventilation = VentilationAbridged.new(@hash[:properties][:energy][:ventilation])
289
- os_custom_ventilation = custom_ventilation.to_openstudio(openstudio_model)
290
- unique_program.setDesignSpecificationOutdoorAir(os_custom_ventilation)
291
- end
292
-
293
- # assign setpoint if it exists
294
- if @hash[:properties][:energy][:setpoint]
295
- # thermostat object is created because heating and cooling schedule are required
296
- setpoint_thermostat_space = SetpointThermostat.new(@hash[:properties][:energy][:setpoint])
297
- os_setpoint_thermostat_space = setpoint_thermostat_space.to_openstudio(openstudio_model)
298
- #set thermostat to thermal zone
299
- os_thermal_zone.setThermostatSetpointDualSetpoint(os_setpoint_thermostat_space)
300
- # humidistat object is created if humidifying or dehumidifying schedule is specified
301
- if @hash[:properties][:energy][:setpoint][:humidifying_schedule] or @hash[:properties][:energy][:setpoint][:dehumidifying_schedule]
302
- setpoint_humidistat_space = SetpointHumidistat.new(@hash[:properties][:energy][:setpoint])
303
- os_setpoint_humidistat_space = setpoint_humidistat_space.to_openstudio(openstudio_model)
304
- os_thermal_zone.setZoneControlHumidistat(os_setpoint_humidistat_space)
305
- end
306
- end
307
-
308
- # assign window ventilation objects if they exist
309
- if $use_simple_vent && !window_vent.empty? # write simple WindAndStack ventilation
310
- window_vent.each do |sub_f_id, open_prop|
311
- opening = open_prop[0]
312
- bc = open_prop[1]
313
- if bc == 'Outdoors'
314
- opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
315
- unless opt_sub_f.empty?
316
- sub_f = opt_sub_f.get
317
- vent_open = VentilationOpening.new(opening)
318
- os_vent_open = vent_open.to_openstudio(
319
- openstudio_model, sub_f, @hash[:properties][:energy][:window_vent_control])
320
- os_vent_open.addToThermalZone(os_thermal_zone)
321
- end
322
- end
323
- end
324
- elsif !$use_simple_vent # we're using the AFN!
325
- # write an AirflowNetworkZone object in for the Room
326
- os_afn_room_node = os_thermal_zone.getAirflowNetworkZone
327
- os_afn_room_node.setVentilationControlMode('NoVent')
328
- # write the opening objects for each Aperture / Door
329
- operable_subfs = [] # collect the sub-face objects for the EMS
330
- opening_factors = [] # collect the maximum opening factors for the EMS
331
- window_vent.each do |sub_f_id, open_prop|
332
- opening = open_prop[0]
333
- opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
334
- unless opt_sub_f.empty?
335
- sub_f = opt_sub_f.get
336
- if sub_f.adjacentSubSurface.empty? # not an interior window that's already in the AFN
337
- vent_open = VentilationOpening.new(opening)
338
- open_fac = vent_open.to_openstudio_afn(openstudio_model, sub_f)
339
- operable_subfs << sub_f
340
- opening_factors << open_fac
341
- end
342
- end
343
- end
344
- # add the control startegy of the ventilation openings using the EMS
345
- if @hash[:properties][:energy][:window_vent_control]
346
- vent_control = VentilationControlAbridged.new(@hash[:properties][:energy][:window_vent_control])
347
- vent_control.to_openstudio(
348
- openstudio_model, os_thermal_zone, operable_subfs, opening_factors)
349
- end
350
- end
351
-
352
- os_space
353
- end
354
-
355
- # method to make a space-assigned Shade group for shades assigned to parent objects
356
- def make_shade_group(openstudio_model, os_surface, os_space)
357
- os_shd_group = OpenStudio::Model::ShadingSurfaceGroup.new(openstudio_model)
358
- os_shd_group.setShadedSurface(os_surface)
359
- os_shd_group.setSpace(os_space)
360
- os_shd_group.setShadingSurfaceType("Space")
361
-
362
- os_shd_group
363
- end
364
-
365
- # method to create a Shade and add it to a shade group
366
- def add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
367
- hb_outdoor_shade = Shade.new(outdoor_shade)
368
- os_outdoor_shade = hb_outdoor_shade.to_openstudio(openstudio_model)
369
- os_outdoor_shade.setShadingSurfaceGroup(os_shd_group)
370
- end
371
-
372
- # method to check for the closest-assigned interior ceiling or floor construction
373
- def closest_interior_construction(openstudio_model, os_space, surface_type)
374
- # first check the space-assigned construction set
375
- constr_set_space = os_space.defaultConstructionSet
376
- unless constr_set_space.empty?
377
- constr_set_space_object = constr_set_space.get
378
- default_interior_srf_set = constr_set_space_object.defaultInteriorSurfaceConstructions
379
- unless default_interior_srf_set.empty?
380
- default_interior_srf_set = default_interior_srf_set.get
381
- if surface_type == 'RoofCeiling'
382
- interior_construction = default_interior_srf_set.roofCeilingConstruction
383
- else
384
- interior_construction = default_interior_srf_set.floorConstruction
385
- end
386
- unless interior_construction.empty?
387
- return interior_construction.get
388
- end
389
- end
390
- end
391
- # if no construction was found, check the building-assigned construction set
392
- building = openstudio_model.building
393
- unless building.empty?
394
- building = building.get
395
- construction_set_bldg = building.defaultConstructionSet
396
- unless construction_set_bldg.empty?
397
- construction_set_bldg_object = construction_set_bldg.get
398
- default_interior_srf_set = construction_set_bldg_object.defaultInteriorSurfaceConstructions
399
- unless default_interior_srf_set.empty?
400
- default_interior_srf_set = default_interior_srf_set.get
401
- if surface_type == 'RoofCeiling'
402
- interior_construction = default_interior_srf_set.roofCeilingConstruction
403
- else
404
- interior_construction = default_interior_srf_set.floorConstruction
405
- end
406
- unless interior_construction.empty?
407
- return interior_construction.get
408
- end
409
- end
410
- end
411
- end
412
- nil # no construction was found
413
- end
414
-
415
- # method to check for the closest-assigned air boundary construction
416
- def closest_air_construction(openstudio_model, os_space)
417
- # first check the space-assigned construction set
418
- constr_set_ref = os_space.defaultConstructionSet
419
- unless constr_set_ref.empty?
420
- constr_set_space = constr_set_ref.get
421
- air_constr_ref = constr_set_space.interiorPartitionConstruction
422
- unless air_constr_ref.empty?
423
- return air_constr_ref.get
424
- end
425
- end
426
- # if no construction was found, check the building-assigned construction set
427
- building_ref = openstudio_model.building
428
- unless building_ref.empty?
429
- building = building_ref.get
430
- constr_set_bldg_ref = building.defaultConstructionSet
431
- unless constr_set_bldg_ref.empty?
432
- constr_set_bldg = constr_set_bldg_ref.get
433
- air_constr_ref = constr_set_bldg.interiorPartitionConstruction
434
- unless air_constr_ref.empty?
435
- return air_constr_ref.get
436
- end
437
- end
438
- end
439
- end
440
-
441
- end #Room
442
- end #Honeybee
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
+
34
+ require 'from_honeybee/geometry/face'
35
+ require 'from_honeybee/geometry/shade'
36
+
37
+ require 'from_honeybee/load/people'
38
+ require 'from_honeybee/load/lighting'
39
+ require 'from_honeybee/load/electric_equipment'
40
+ require 'from_honeybee/load/gas_equipment'
41
+ require 'from_honeybee/load/infiltration'
42
+ require 'from_honeybee/load/ventilation'
43
+ require 'from_honeybee/load/setpoint_thermostat'
44
+ require 'from_honeybee/load/setpoint_humidistat'
45
+
46
+ require 'openstudio'
47
+
48
+ module FromHoneybee
49
+ class Room < ModelObject
50
+ attr_reader :errors, :warnings
51
+
52
+ def initialize(hash = {})
53
+ super(hash)
54
+ raise "Incorrect model type '#{@type}'" unless @type == 'Room'
55
+ end
56
+
57
+ def defaults
58
+ @@schema[:components][:schemas][:RoomEnergyPropertiesAbridged][:properties]
59
+ end
60
+
61
+ def find_existing_openstudio_object(openstudio_model)
62
+ model_space = openstudio_model.getSpaceByName(@hash[:identifier])
63
+ return model_space.get unless model_space.empty?
64
+ nil
65
+ end
66
+
67
+ def to_openstudio(openstudio_model)
68
+ # create the space and thermal zone
69
+ os_space = OpenStudio::Model::Space.new(openstudio_model)
70
+ os_space.setName(@hash[:identifier])
71
+ os_thermal_zone = OpenStudio::Model::ThermalZone.new(openstudio_model)
72
+ os_thermal_zone.setName(@hash[:identifier])
73
+ os_space.setThermalZone(os_thermal_zone)
74
+
75
+ # assign the programtype
76
+ if @hash[:properties][:energy][:program_type]
77
+ space_type = openstudio_model.getSpaceTypeByName(@hash[:properties][:energy][:program_type])
78
+ unless space_type.empty?
79
+ space_type_object = space_type.get
80
+ os_space.setSpaceType(space_type_object)
81
+ end
82
+ end
83
+
84
+ # assign the constructionset
85
+ if @hash[:properties][:energy][:construction_set]
86
+ construction_set_identifier = @hash[:properties][:energy][:construction_set]
87
+ # gets default construction set assigned to room from openstudio_model
88
+ construction_set = openstudio_model.getDefaultConstructionSetByName(construction_set_identifier)
89
+ unless construction_set.empty?
90
+ default_construction_set = construction_set.get
91
+ os_space.setDefaultConstructionSet(default_construction_set)
92
+ end
93
+ end
94
+
95
+ # assign the multiplier
96
+ if @hash[:multiplier] and @hash[:multiplier] != 1
97
+ os_thermal_zone.setMultiplier(@hash[:multiplier])
98
+ end
99
+
100
+ # assign the story
101
+ if @hash[:story] # the users has specified the name of the story
102
+ story = openstudio_model.getBuildingStoryByName(@hash[:story])
103
+ if story.empty? # first time that this story has been referenced
104
+ story = OpenStudio::Model::BuildingStory.new(openstudio_model)
105
+ story.setName(@hash[:story])
106
+ else
107
+ story = story.get
108
+ end
109
+ else # give the room a dummy story so that it works with David's measures
110
+ story = openstudio_model.getBuildingStoryByName('UndefiniedStory')
111
+ if story.empty? # first time that this story has been referenced
112
+ story = OpenStudio::Model::BuildingStory.new(openstudio_model)
113
+ story.setName('UndefiniedStory')
114
+ else
115
+ story = story.get
116
+ end
117
+ end
118
+ os_space.setBuildingStory(story)
119
+
120
+ # assign all of the faces to the room
121
+ @hash[:faces].each do |face|
122
+ ladybug_face = Face.new(face)
123
+ os_surface = ladybug_face.to_openstudio(openstudio_model)
124
+ os_surface.setSpace(os_space)
125
+
126
+ # assign face-level shades if they exist
127
+ if face[:outdoor_shades]
128
+ os_shd_group = make_shade_group(openstudio_model, os_surface, os_space)
129
+ face[:outdoor_shades].each do |outdoor_shade|
130
+ add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
131
+ end
132
+ end
133
+
134
+ # assign aperture-level shades if they exist
135
+ if face[:apertures]
136
+ face[:apertures].each do |aperture|
137
+ if aperture[:outdoor_shades]
138
+ unless os_shd_group
139
+ os_shd_group = make_shade_group(openstudio_model, os_surface, os_space)
140
+ end
141
+ aperture[:outdoor_shades].each do |outdoor_shade|
142
+ add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ # assign door-level shades if they exist
149
+ if face[:doors]
150
+ face[:doors].each do |door|
151
+ if door[:outdoor_shades]
152
+ unless os_shd_group
153
+ os_shd_group = make_shade_group(openstudio_model, os_surface, os_space)
154
+ end
155
+ door[:outdoor_shades].each do |outdoor_shade|
156
+ add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ if !face[:properties][:energy][:construction]
163
+ if face[:boundary_condition][:type] == 'Adiabatic'
164
+ # assign default interior construciton for Adiabatic Faces
165
+ if face[:face_type] != 'Wall'
166
+ interior_construction = closest_interior_construction(openstudio_model, os_space, face[:face_type])
167
+ unless interior_construction.nil?
168
+ os_surface.setConstruction(interior_construction)
169
+ end
170
+ end
171
+ elsif face[:face_type] == 'AirBoundary'
172
+ # assign default air boundary construciton for AirBoundary face types
173
+ air_construction = closest_air_construction(openstudio_model, os_space)
174
+ unless air_construction.nil?
175
+ os_surface.setConstruction(air_construction)
176
+ end
177
+ # add air mixing properties to the global list that tracks them
178
+ air_hash = $air_boundary_hash[air_construction.name.to_s]
179
+ if air_hash[:air_mixing_per_area]
180
+ air_mix_area = air_hash[:air_mixing_per_area]
181
+ else
182
+ air_default = @@schema[:components][:schemas][:AirBoundaryConstructionAbridged]
183
+ air_mix_area = air_default[:properties][:air_mixing_per_area][:default]
184
+ end
185
+ flow_rate = os_surface.netArea * air_mix_area
186
+ flow_sch_id = air_hash[:air_mixing_schedule]
187
+ adj_zone_id = face[:boundary_condition][:boundary_condition_objects][-1]
188
+ $air_mxing_array << [os_thermal_zone, flow_rate, flow_sch_id, adj_zone_id]
189
+ end
190
+ end
191
+ end
192
+
193
+ # assign any room-level outdoor shades if they exist
194
+ if @hash[:outdoor_shades]
195
+ os_shd_group = OpenStudio::Model::ShadingSurfaceGroup.new(openstudio_model)
196
+ os_shd_group.setSpace(os_space)
197
+ os_shd_group.setShadingSurfaceType("Space")
198
+ @hash[:outdoor_shades].each do |outdoor_shade|
199
+ add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
200
+ end
201
+ end
202
+
203
+ #check whether there are any load objects on the room overriding the programtype
204
+ if @hash[:properties][:energy][:people]
205
+ people = openstudio_model.getPeopleByName(@hash[:properties][:energy][:people][:identifier])
206
+ unless people.empty?
207
+ people_object = people.get
208
+ people_object.setSpace(os_space)
209
+ else
210
+ people_space = PeopleAbridged.new(@hash[:properties][:energy][:people])
211
+ os_people_space = people_space.to_openstudio(openstudio_model)
212
+ os_people_space.setSpace(os_space)
213
+ end
214
+ end
215
+
216
+ # assign lighting if it exists
217
+ if @hash[:properties][:energy][:lighting]
218
+ lighting = openstudio_model.getLightsByName(@hash[:properties][:energy][:lighting][:identifier])
219
+ unless lighting.empty?
220
+ lighting_object = lighting.get
221
+ lighting_object.setSpace(os_space)
222
+ else
223
+ lighting_space = LightingAbridged.new(@hash[:properties][:energy][:lighting])
224
+ os_lighting_space = lighting_space.to_openstudio(openstudio_model)
225
+ os_lighting_space.setSpace(os_space)
226
+ end
227
+ end
228
+
229
+ # assign electric equipment if it exists
230
+ if @hash[:properties][:energy][:electric_equipment]
231
+ electric_equipment = openstudio_model.getElectricEquipmentByName(
232
+ @hash[:properties][:energy][:electric_equipment][:identifier])
233
+ unless electric_equipment.empty?
234
+ electric_equipment_object = electric_equipment.get
235
+ electric_equipment_object.setSpace(os_space)
236
+ else
237
+ electric_equipment_space = ElectricEquipmentAbridged.new(@hash[:properties][:energy][:electric_equipment])
238
+ os_electric_equipment_space = electric_equipment_space.to_openstudio(openstudio_model)
239
+ os_electric_equipment_space.setSpace(os_space)
240
+ end
241
+ end
242
+
243
+ # assign gas equipment if it exists
244
+ if @hash[:properties][:energy][:gas_equipment]
245
+ gas_equipment = openstudio_model.getGasEquipmentByName(
246
+ @hash[:properties][:energy][:gas_equipment][:identifier])
247
+ unless gas_equipment.empty?
248
+ gas_equipment_object = gas_equipment.get
249
+ gas_equipment_object.setSpace(os_space)
250
+ else
251
+ gas_equipment_space = GasEquipmentAbridged.new(@hash[:properties][:energy][:gas_equipment])
252
+ os_gas_equipment_space = gas_equipment_space.to_openstudio(openstudio_model)
253
+ os_gas_equipment_space.setSpace(os_space)
254
+ end
255
+ end
256
+
257
+ # assign infiltration if it exists
258
+ if @hash[:properties][:energy][:infiltration]
259
+ infiltration = openstudio_model.getSpaceInfiltrationDesignFlowRateByName(
260
+ @hash[:properties][:energy][:infiltration][:identifier])
261
+ unless infiltration.empty?
262
+ infiltration_object = infiltration.get
263
+ infiltration_object.setSpace(os_space)
264
+ else
265
+ infiltration_space = InfiltrationAbridged.new(@hash[:properties][:energy][:infiltration])
266
+ os_infiltration_space = infiltration_space.to_openstudio(openstudio_model)
267
+ os_infiltration_space.setSpace(os_space)
268
+ end
269
+ end
270
+
271
+ # assign ventilation if it exists
272
+ if @hash[:properties][:energy][:ventilation]
273
+ ventilation = openstudio_model.getDesignSpecificationOutdoorAirByName(
274
+ @hash[:properties][:energy][:ventilation][:identifier])
275
+ unless ventilation.empty?
276
+ ventilation_object = ventilation.get
277
+ ventilation_object.setSpace(os_space)
278
+ else
279
+ ventilation_space = VentilationAbridged.new(@hash[:properties][:energy][:ventilation])
280
+ os_ventilation_space = ventilation_space.to_openstudio(openstudio_model)
281
+ os_space.setDesignSpecificationOutdoorAir(os_ventilation_space)
282
+ end
283
+ end
284
+
285
+ # assign setpoint if it exists
286
+ if @hash[:properties][:energy][:setpoint]
287
+ #thermostat object is created because heating and cooling schedule are required
288
+ #fields.
289
+ setpoint_thermostat_space = SetpointThermostat.new(@hash[:properties][:energy][:setpoint])
290
+ os_setpoint_thermostat_space = setpoint_thermostat_space.to_openstudio(openstudio_model)
291
+ #set thermostat to thermal zone
292
+ os_thermal_zone.setThermostatSetpointDualSetpoint(os_setpoint_thermostat_space)
293
+ #humidistat object is created if humidifying or dehumidifying schedule is
294
+ #specified.
295
+ if @hash[:properties][:energy][:setpoint][:humidifying_schedule] or @hash[:properties][:energy][:setpoint][:dehumidifying_schedule]
296
+ setpoint_humidistat_space = SetpointHumidistat.new(@hash[:properties][:energy][:setpoint])
297
+ os_setpoint_humidistat_space = setpoint_humidistat_space.to_openstudio(openstudio_model)
298
+ os_thermal_zone.setZoneControlHumidistat(os_setpoint_humidistat_space)
299
+ end
300
+ end
301
+
302
+ os_space
303
+ end
304
+
305
+ # method to make a space-assigned Shade group for shades assigned to parent objects
306
+ def make_shade_group(openstudio_model, os_surface, os_space)
307
+ os_shd_group = OpenStudio::Model::ShadingSurfaceGroup.new(openstudio_model)
308
+ os_shd_group.setShadedSurface(os_surface)
309
+ os_shd_group.setSpace(os_space)
310
+ os_shd_group.setShadingSurfaceType("Space")
311
+
312
+ os_shd_group
313
+ end
314
+
315
+ # method to create a Shade and add it to a shade group
316
+ def add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
317
+ hb_outdoor_shade = Shade.new(outdoor_shade)
318
+ os_outdoor_shade = hb_outdoor_shade.to_openstudio(openstudio_model)
319
+ os_outdoor_shade.setShadingSurfaceGroup(os_shd_group)
320
+ end
321
+
322
+ # method to check for the closest-assigned interior ceiling or floor construction
323
+ def closest_interior_construction(openstudio_model, os_space, surface_type)
324
+ # first check the space-assigned construction set
325
+ constr_set_space = os_space.defaultConstructionSet
326
+ unless constr_set_space.empty?
327
+ constr_set_space_object = constr_set_space.get
328
+ default_interior_srf_set = constr_set_space_object.defaultInteriorSurfaceConstructions
329
+ unless default_interior_srf_set.empty?
330
+ default_interior_srf_set = default_interior_srf_set.get
331
+ if surface_type == 'RoofCeiling'
332
+ interior_construction = default_interior_srf_set.roofCeilingConstruction
333
+ else
334
+ interior_construction = default_interior_srf_set.floorConstruction
335
+ end
336
+ unless interior_construction.empty?
337
+ return interior_construction.get
338
+ end
339
+ end
340
+ end
341
+ # if no construction was found, check the building-assigned construction set
342
+ building = openstudio_model.building
343
+ unless building.empty?
344
+ building = building.get
345
+ construction_set_bldg = building.defaultConstructionSet
346
+ unless construction_set_bldg.empty?
347
+ construction_set_bldg_object = construction_set_bldg.get
348
+ default_interior_srf_set = construction_set_bldg_object.defaultInteriorSurfaceConstructions
349
+ unless default_interior_srf_set.empty?
350
+ default_interior_srf_set = default_interior_srf_set.get
351
+ if surface_type == 'RoofCeiling'
352
+ interior_construction = default_interior_srf_set.roofCeilingConstruction
353
+ else
354
+ interior_construction = default_interior_srf_set.floorConstruction
355
+ end
356
+ unless interior_construction.empty?
357
+ return interior_construction.get
358
+ end
359
+ end
360
+ end
361
+ end
362
+ nil # no construction was found
363
+ end
364
+
365
+ # method to check for the closest-assigned air boundary construction
366
+ def closest_air_construction(openstudio_model, os_space)
367
+ # first check the space-assigned construction set
368
+ constr_set_ref = os_space.defaultConstructionSet
369
+ unless constr_set_ref.empty?
370
+ constr_set_space = constr_set_ref.get
371
+ air_constr_ref = constr_set_space.interiorPartitionConstruction
372
+ unless air_constr_ref.empty?
373
+ return air_constr_ref.get
374
+ end
375
+ end
376
+ # if no construction was found, check the building-assigned construction set
377
+ building_ref = openstudio_model.building
378
+ unless building_ref.empty?
379
+ building = building_ref.get
380
+ constr_set_bldg_ref = building.defaultConstructionSet
381
+ unless constr_set_bldg_ref.empty?
382
+ constr_set_bldg = constr_set_bldg_ref.get
383
+ air_constr_ref = constr_set_bldg.interiorPartitionConstruction
384
+ unless air_constr_ref.empty?
385
+ return air_constr_ref.get
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ end #Room
392
+ end #FromHoneybee