honeybee-openstudio 1.8.1

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.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +32 -0
  4. data/.releaserc.json +7 -0
  5. data/.travis.yml +41 -0
  6. data/Gemfile +18 -0
  7. data/LICENSE.md +23 -0
  8. data/README.md +95 -0
  9. data/Rakefile +21 -0
  10. data/doc_templates/LICENSE.md +23 -0
  11. data/doc_templates/copyright_erb.txt +32 -0
  12. data/doc_templates/copyright_js.txt +5 -0
  13. data/doc_templates/copyright_ruby.txt +30 -0
  14. data/honeybee-openstudio.gemspec +35 -0
  15. data/lib/files/Honeybee.rb +113 -0
  16. data/lib/files/honeybee_workflow.osw +48 -0
  17. data/lib/files/urbanopt_Gemfile +32 -0
  18. data/lib/from_honeybee.rb +86 -0
  19. data/lib/from_honeybee/_openapi/model.json +8127 -0
  20. data/lib/from_honeybee/_openapi/simulation-parameter.json +843 -0
  21. data/lib/from_honeybee/construction/air.rb +65 -0
  22. data/lib/from_honeybee/construction/opaque.rb +77 -0
  23. data/lib/from_honeybee/construction/shade.rb +108 -0
  24. data/lib/from_honeybee/construction/window.rb +80 -0
  25. data/lib/from_honeybee/construction_set.rb +278 -0
  26. data/lib/from_honeybee/extension.rb +109 -0
  27. data/lib/from_honeybee/geometry/aperture.rb +167 -0
  28. data/lib/from_honeybee/geometry/door.rb +160 -0
  29. data/lib/from_honeybee/geometry/face.rb +163 -0
  30. data/lib/from_honeybee/geometry/room.rb +392 -0
  31. data/lib/from_honeybee/geometry/shade.rb +89 -0
  32. data/lib/from_honeybee/hvac/ideal_air.rb +150 -0
  33. data/lib/from_honeybee/load/electric_equipment.rb +96 -0
  34. data/lib/from_honeybee/load/gas_equipment.rb +97 -0
  35. data/lib/from_honeybee/load/infiltration.rb +95 -0
  36. data/lib/from_honeybee/load/lighting.rb +98 -0
  37. data/lib/from_honeybee/load/people.rb +100 -0
  38. data/lib/from_honeybee/load/setpoint_humidistat.rb +75 -0
  39. data/lib/from_honeybee/load/setpoint_thermostat.rb +71 -0
  40. data/lib/from_honeybee/load/ventilation.rb +96 -0
  41. data/lib/from_honeybee/material/opaque.rb +94 -0
  42. data/lib/from_honeybee/material/opaque_no_mass.rb +94 -0
  43. data/lib/from_honeybee/material/window_blind.rb +238 -0
  44. data/lib/from_honeybee/material/window_gas.rb +76 -0
  45. data/lib/from_honeybee/material/window_gas_custom.rb +118 -0
  46. data/lib/from_honeybee/material/window_gas_mixture.rb +79 -0
  47. data/lib/from_honeybee/material/window_glazing.rb +166 -0
  48. data/lib/from_honeybee/material/window_shade.rb +160 -0
  49. data/lib/from_honeybee/material/window_simpleglazsys.rb +73 -0
  50. data/lib/from_honeybee/model.rb +434 -0
  51. data/lib/from_honeybee/model_object.rb +110 -0
  52. data/lib/from_honeybee/program_type.rb +124 -0
  53. data/lib/from_honeybee/schedule/fixed_interval.rb +115 -0
  54. data/lib/from_honeybee/schedule/ruleset.rb +164 -0
  55. data/lib/from_honeybee/schedule/type_limit.rb +88 -0
  56. data/lib/from_honeybee/simulation/designday.rb +105 -0
  57. data/lib/from_honeybee/simulation/extension.rb +46 -0
  58. data/lib/from_honeybee/simulation/parameter.rb +277 -0
  59. data/lib/from_honeybee/version.rb +34 -0
  60. data/lib/measures/.gitkeep +0 -0
  61. data/lib/measures/from_honeybee_model/LICENSE.md +27 -0
  62. data/lib/measures/from_honeybee_model/README.md +32 -0
  63. data/lib/measures/from_honeybee_model/measure.rb +91 -0
  64. data/lib/measures/from_honeybee_model/measure.xml +103 -0
  65. data/lib/measures/from_honeybee_model/tests/from_honeybee_model_test.rb +126 -0
  66. data/lib/measures/from_honeybee_simulation_parameter/LICENSE.md +27 -0
  67. data/lib/measures/from_honeybee_simulation_parameter/README.md +32 -0
  68. data/lib/measures/from_honeybee_simulation_parameter/measure.rb +95 -0
  69. data/lib/measures/from_honeybee_simulation_parameter/measure.xml +91 -0
  70. data/lib/measures/from_honeybee_simulation_parameter/tests/from_honeybee_simulation_parameter_test.rb +109 -0
  71. metadata +243 -0
@@ -0,0 +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 '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
@@ -0,0 +1,89 @@
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 'openstudio'
35
+
36
+ module FromHoneybee
37
+ class Shade < ModelObject
38
+ attr_reader :errors, :warnings
39
+
40
+ def initialize(hash)
41
+ super(hash)
42
+ raise "Incorrect model type '#{@type}'" unless @type == 'Shade'
43
+ end
44
+
45
+ def defaults
46
+ @@schema[:components][:schemas][:ShadeEnergyPropertiesAbridged][:properties]
47
+ end
48
+
49
+ def find_existing_openstudio_object(openstudio_model)
50
+ object = openstudio_model.getSurfaceByName(@hash[:identifier])
51
+ return object.get if object.is_initialized
52
+ nil
53
+ end
54
+
55
+ def to_openstudio(openstudio_model)
56
+ # create the openstudio shading surface
57
+ os_vertices = OpenStudio::Point3dVector.new
58
+ @hash[:geometry][:boundary].each do |vertex|
59
+ os_vertices << OpenStudio::Point3d.new(vertex[0], vertex[1], vertex[2])
60
+ end
61
+ reordered_vertices = OpenStudio.reorderULC(os_vertices)
62
+
63
+ os_shading_surface = OpenStudio::Model::ShadingSurface.new(reordered_vertices, openstudio_model)
64
+ os_shading_surface.setName(@hash[:identifier])
65
+
66
+ # assign the construction if it exists
67
+ if @hash[:properties][:energy][:construction]
68
+ construction_identifier = @hash[:properties][:energy][:construction]
69
+ construction = openstudio_model.getConstructionByName(construction_identifier)
70
+ unless construction.empty?
71
+ os_construction = construction.get
72
+ os_shading_surface.setConstruction(os_construction)
73
+ end
74
+ end
75
+
76
+ # assign the transmittance schedule if it exists
77
+ if @hash[:properties][:energy][:transmittance_schedule]
78
+ schedule_identifier = @hash[:properties][:energy][:transmittance_schedule]
79
+ schedule = openstudio_model.getScheduleByName(schedule_identifier)
80
+ unless schedule.empty?
81
+ os_schedule = schedule.get
82
+ os_shading_surface.setTransmittanceSchedule(os_schedule)
83
+ end
84
+ end
85
+
86
+ os_shading_surface
87
+ end
88
+ end #Shade
89
+ end #FromHoneybee