honeybee-openstudio 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.
Files changed (130) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yaml +88 -0
  3. data/.gitignore +33 -0
  4. data/.releaserc.json +7 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE.md +23 -0
  7. data/README.md +95 -0
  8. data/Rakefile +16 -0
  9. data/doc_templates/LICENSE.md +23 -0
  10. data/doc_templates/README.md.erb +42 -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 +38 -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_openstudio.rb +49 -0
  19. data/lib/from_openstudio/geometry/aperture.rb +136 -0
  20. data/lib/from_openstudio/geometry/door.rb +136 -0
  21. data/lib/from_openstudio/geometry/face.rb +174 -0
  22. data/lib/from_openstudio/geometry/room.rb +121 -0
  23. data/lib/from_openstudio/geometry/shade.rb +87 -0
  24. data/lib/from_openstudio/model.rb +123 -0
  25. data/lib/from_openstudio/model_object.rb +43 -0
  26. data/lib/from_openstudio/simulation/design_day.rb +123 -0
  27. data/lib/from_openstudio/simulation/parameter_model.rb +93 -0
  28. data/lib/from_openstudio/simulation/simulation_output.rb +67 -0
  29. data/lib/honeybee.rb +93 -0
  30. data/lib/honeybee/_defaults/energy_default.json +1682 -0
  31. data/lib/honeybee/_defaults/model.json +11311 -0
  32. data/lib/honeybee/_defaults/simulation-parameter.json +973 -0
  33. data/lib/honeybee/construction/air.rb +42 -0
  34. data/lib/honeybee/construction/opaque.rb +42 -0
  35. data/lib/honeybee/construction/shade.rb +42 -0
  36. data/lib/honeybee/construction/window.rb +51 -0
  37. data/lib/honeybee/construction/windowshade.rb +43 -0
  38. data/lib/honeybee/construction_set.rb +42 -0
  39. data/lib/honeybee/extension.rb +129 -0
  40. data/lib/honeybee/geometry/aperture.rb +42 -0
  41. data/lib/honeybee/geometry/door.rb +42 -0
  42. data/lib/honeybee/geometry/face.rb +48 -0
  43. data/lib/honeybee/geometry/room.rb +56 -0
  44. data/lib/honeybee/geometry/shade.rb +42 -0
  45. data/lib/honeybee/hvac/ideal_air.rb +42 -0
  46. data/lib/honeybee/hvac/template.rb +73 -0
  47. data/lib/honeybee/load/electric_equipment.rb +42 -0
  48. data/lib/honeybee/load/gas_equipment.rb +42 -0
  49. data/lib/honeybee/load/infiltration.rb +42 -0
  50. data/lib/honeybee/load/lighting.rb +43 -0
  51. data/lib/honeybee/load/people.rb +42 -0
  52. data/lib/honeybee/load/setpoint_humidistat.rb +46 -0
  53. data/lib/honeybee/load/setpoint_thermostat.rb +46 -0
  54. data/lib/honeybee/load/ventilation.rb +42 -0
  55. data/lib/honeybee/material/opaque.rb +42 -0
  56. data/lib/honeybee/material/opaque_no_mass.rb +42 -0
  57. data/lib/honeybee/material/window_blind.rb +42 -0
  58. data/lib/honeybee/material/window_gas.rb +42 -0
  59. data/lib/honeybee/material/window_gas_custom.rb +42 -0
  60. data/lib/honeybee/material/window_gas_mixture.rb +42 -0
  61. data/lib/honeybee/material/window_glazing.rb +42 -0
  62. data/lib/honeybee/material/window_shade.rb +42 -0
  63. data/lib/honeybee/material/window_simpleglazsys.rb +42 -0
  64. data/lib/honeybee/model.rb +87 -0
  65. data/lib/honeybee/model_object.rb +108 -0
  66. data/lib/honeybee/program_type.rb +56 -0
  67. data/lib/honeybee/schedule/fixed_interval.rb +42 -0
  68. data/lib/honeybee/schedule/ruleset.rb +42 -0
  69. data/lib/honeybee/schedule/type_limit.rb +42 -0
  70. data/lib/honeybee/simulation/design_day.rb +42 -0
  71. data/lib/honeybee/simulation/parameter_model.rb +86 -0
  72. data/lib/honeybee/simulation/simulation_output.rb +42 -0
  73. data/lib/honeybee/ventcool/control.rb +42 -0
  74. data/lib/honeybee/ventcool/opening.rb +46 -0
  75. data/lib/honeybee/ventcool/simulation.rb +42 -0
  76. data/lib/measures/.gitkeep +0 -0
  77. data/lib/measures/from_honeybee_model/LICENSE.md +23 -0
  78. data/lib/measures/from_honeybee_model/README.md +32 -0
  79. data/lib/measures/from_honeybee_model/measure.rb +91 -0
  80. data/lib/measures/from_honeybee_model/measure.xml +80 -0
  81. data/lib/measures/from_honeybee_model/tests/from_honeybee_model_test.rb +126 -0
  82. data/lib/measures/from_honeybee_simulation_parameter/LICENSE.md +23 -0
  83. data/lib/measures/from_honeybee_simulation_parameter/README.md +32 -0
  84. data/lib/measures/from_honeybee_simulation_parameter/measure.rb +95 -0
  85. data/lib/measures/from_honeybee_simulation_parameter/measure.xml +86 -0
  86. data/lib/measures/from_honeybee_simulation_parameter/tests/from_honeybee_simulation_parameter_test.rb +109 -0
  87. data/lib/to_openstudio.rb +92 -0
  88. data/lib/to_openstudio/construction/air.rb +56 -0
  89. data/lib/to_openstudio/construction/opaque.rb +67 -0
  90. data/lib/to_openstudio/construction/shade.rb +99 -0
  91. data/lib/to_openstudio/construction/window.rb +70 -0
  92. data/lib/to_openstudio/construction/windowshade.rb +196 -0
  93. data/lib/to_openstudio/construction_set.rb +266 -0
  94. data/lib/to_openstudio/geometry/aperture.rb +157 -0
  95. data/lib/to_openstudio/geometry/door.rb +150 -0
  96. data/lib/to_openstudio/geometry/face.rb +178 -0
  97. data/lib/to_openstudio/geometry/room.rb +442 -0
  98. data/lib/to_openstudio/geometry/shade.rb +79 -0
  99. data/lib/to_openstudio/hvac/Model.hvac.rb +641 -0
  100. data/lib/to_openstudio/hvac/ideal_air.rb +141 -0
  101. data/lib/to_openstudio/hvac/template.rb +169 -0
  102. data/lib/to_openstudio/load/electric_equipment.rb +87 -0
  103. data/lib/to_openstudio/load/gas_equipment.rb +88 -0
  104. data/lib/to_openstudio/load/infiltration.rb +86 -0
  105. data/lib/to_openstudio/load/lighting.rb +89 -0
  106. data/lib/to_openstudio/load/people.rb +91 -0
  107. data/lib/to_openstudio/load/setpoint_humidistat.rb +66 -0
  108. data/lib/to_openstudio/load/setpoint_thermostat.rb +62 -0
  109. data/lib/to_openstudio/load/ventilation.rb +87 -0
  110. data/lib/to_openstudio/material/opaque.rb +85 -0
  111. data/lib/to_openstudio/material/opaque_no_mass.rb +85 -0
  112. data/lib/to_openstudio/material/window_blind.rb +229 -0
  113. data/lib/to_openstudio/material/window_gas.rb +67 -0
  114. data/lib/to_openstudio/material/window_gas_custom.rb +108 -0
  115. data/lib/to_openstudio/material/window_gas_mixture.rb +70 -0
  116. data/lib/to_openstudio/material/window_glazing.rb +157 -0
  117. data/lib/to_openstudio/material/window_shade.rb +151 -0
  118. data/lib/to_openstudio/material/window_simpleglazsys.rb +64 -0
  119. data/lib/to_openstudio/model.rb +497 -0
  120. data/lib/to_openstudio/model_object.rb +52 -0
  121. data/lib/to_openstudio/program_type.rb +104 -0
  122. data/lib/to_openstudio/schedule/fixed_interval.rb +105 -0
  123. data/lib/to_openstudio/schedule/ruleset.rb +164 -0
  124. data/lib/to_openstudio/schedule/type_limit.rb +76 -0
  125. data/lib/to_openstudio/simulation/design_day.rb +96 -0
  126. data/lib/to_openstudio/simulation/parameter_model.rb +243 -0
  127. data/lib/to_openstudio/ventcool/control.rb +185 -0
  128. data/lib/to_openstudio/ventcool/opening.rb +189 -0
  129. data/lib/to_openstudio/ventcool/simulation.rb +101 -0
  130. metadata +301 -0
@@ -0,0 +1,266 @@
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/construction_set'
33
+
34
+ require 'to_openstudio/model_object'
35
+
36
+ module Honeybee
37
+ class ConstructionSetAbridged
38
+
39
+ def find_existing_openstudio_object(openstudio_model)
40
+ object = openstudio_model.getDefaultConstructionSetByName(@hash[:identifier])
41
+ return object.get if object.is_initialized
42
+ nil
43
+ end
44
+
45
+ def to_openstudio(openstudio_model)
46
+ # create the constructionset object
47
+ os_constr_set = OpenStudio::Model::DefaultConstructionSet.new(openstudio_model)
48
+ os_constr_set.setName(@hash[:identifier])
49
+
50
+ int_surf_const = OpenStudio::Model::DefaultSurfaceConstructions.new(openstudio_model)
51
+ ext_surf_const = OpenStudio::Model::DefaultSurfaceConstructions.new(openstudio_model)
52
+ grnd_surf_const = OpenStudio::Model::DefaultSurfaceConstructions.new(openstudio_model)
53
+ int_subsurf_const = OpenStudio::Model::DefaultSubSurfaceConstructions.new(openstudio_model)
54
+ ext_subsurf_const = OpenStudio::Model::DefaultSubSurfaceConstructions.new(openstudio_model)
55
+
56
+ os_constr_set.setDefaultInteriorSurfaceConstructions(int_surf_const)
57
+ os_constr_set.setDefaultExteriorSurfaceConstructions(ext_surf_const)
58
+ os_constr_set.setDefaultGroundContactSurfaceConstructions(grnd_surf_const)
59
+ os_constr_set.setDefaultInteriorSubSurfaceConstructions(int_subsurf_const)
60
+ os_constr_set.setDefaultExteriorSubSurfaceConstructions(ext_subsurf_const)
61
+
62
+ # assign any constructions in the wall set
63
+ if @hash[:wall_set]
64
+ if @hash[:wall_set][:interior_construction]
65
+ int_wall_ref = openstudio_model.getConstructionByName(@hash[:wall_set][:interior_construction])
66
+ unless int_wall_ref.empty?
67
+ interior_wall = int_wall_ref.get
68
+ int_surf_const.setWallConstruction(interior_wall)
69
+ os_constr_set.setAdiabaticSurfaceConstruction(interior_wall)
70
+ end
71
+ end
72
+ if @hash[:wall_set][:exterior_construction]
73
+ ext_wall_ref = openstudio_model.getConstructionByName(@hash[:wall_set][:exterior_construction])
74
+ unless ext_wall_ref.empty?
75
+ exterior_wall = ext_wall_ref.get
76
+ ext_surf_const.setWallConstruction(exterior_wall)
77
+ end
78
+ end
79
+ if @hash[:wall_set][:ground_construction]
80
+ grd_wall_ref = openstudio_model.getConstructionByName(@hash[:wall_set][:ground_construction])
81
+ unless grd_wall_ref.empty?
82
+ ground_wall = grd_wall_ref.get
83
+ grnd_surf_const.setWallConstruction(ground_wall)
84
+ end
85
+ end
86
+ end
87
+
88
+ # assign any constructions in the floor set
89
+ if @hash[:floor_set]
90
+ if @hash[:floor_set][:interior_construction]
91
+ constr_id_int = openstudio_model.getConstructionByName(@hash[:floor_set][:interior_construction])
92
+ assign_constr_to_set_int(openstudio_model, int_surf_const, 'Floor',
93
+ constr_id_int)
94
+ end
95
+ if @hash[:floor_set][:exterior_construction]
96
+ constr_id_ext = openstudio_model.getConstructionByName(@hash[:floor_set][:exterior_construction])
97
+ assign_constr_to_set_ext(openstudio_model, ext_surf_const, 'Floor',
98
+ constr_id_ext
99
+ )
100
+ end
101
+ if @hash[:floor_set][:ground_construction]
102
+ constr_id_grd = openstudio_model.getConstructionByName(@hash[:floor_set][:ground_construction])
103
+ assign_constr_to_set_grd(openstudio_model, grnd_surf_const, 'Floor',
104
+ constr_id_grd)
105
+ end
106
+ end
107
+
108
+ # assign any constructions in the roof ceiling set
109
+ if @hash[:roof_ceiling_set]
110
+ if @hash[:roof_ceiling_set][:interior_construction]
111
+ constr_id_int = openstudio_model.getConstructionByName(@hash[:roof_ceiling_set][:interior_construction])
112
+ assign_constr_to_set_int(openstudio_model, int_surf_const, 'Roof',
113
+ constr_id_int)
114
+ end
115
+ if @hash[:roof_ceiling_set][:exterior_construction]
116
+ constr_id_ext = openstudio_model.getConstructionByName(@hash[:roof_ceiling_set][:exterior_construction])
117
+ assign_constr_to_set_ext(openstudio_model, ext_surf_const, 'Roof',
118
+ constr_id_ext)
119
+ end
120
+ if @hash[:roof_ceiling_set][:ground_construction]
121
+ constr_id_grd = openstudio_model.getConstructionByName(@hash[:roof_ceiling_set][:ground_construction])
122
+ assign_constr_to_set_grd(openstudio_model, grnd_surf_const, 'Roof',
123
+ constr_id_grd)
124
+ end
125
+ end
126
+
127
+ # assign any constructions in the aperture set
128
+ if @hash[:aperture_set]
129
+ if @hash[:aperture_set][:interior_construction]
130
+ int_ap_ref = openstudio_model.getConstructionByName(
131
+ @hash[:aperture_set][:interior_construction])
132
+ unless int_ap_ref.empty?
133
+ interior_aperture = int_ap_ref.get
134
+ int_subsurf_const.setFixedWindowConstruction(interior_aperture)
135
+ int_subsurf_const.setOperableWindowConstruction(interior_aperture)
136
+ end
137
+ end
138
+ if @hash[:aperture_set][:window_construction]
139
+ window_ref = openstudio_model.getConstructionByName(
140
+ @hash[:aperture_set][:window_construction])
141
+ unless window_ref.empty?
142
+ window_aperture = window_ref.get
143
+ ext_subsurf_const.setFixedWindowConstruction(window_aperture)
144
+ end
145
+ end
146
+ if @hash[:aperture_set][:skylight_construction]
147
+ skylight_ref = openstudio_model.getConstructionByName(
148
+ @hash[:aperture_set][:skylight_construction])
149
+ unless skylight_ref.empty?
150
+ skylight_aperture = skylight_ref.get
151
+ ext_subsurf_const.setSkylightConstruction(skylight_aperture)
152
+ end
153
+ end
154
+ if @hash[:aperture_set][:operable_construction]
155
+ operable_ref = openstudio_model.getConstructionByName(
156
+ @hash[:aperture_set][:operable_construction])
157
+ unless operable_ref.empty?
158
+ operable_aperture = operable_ref.get
159
+ ext_subsurf_const.setOperableWindowConstruction(operable_aperture)
160
+ end
161
+ end
162
+ end
163
+
164
+ # assign any constructions in the door set
165
+ if @hash[:door_set]
166
+ if @hash[:door_set][:interior_construction]
167
+ int_door_ref = openstudio_model.getConstructionByName(
168
+ @hash[:door_set][:interior_construction])
169
+ unless int_door_ref.empty?
170
+ interior_door = int_door_ref.get
171
+ int_subsurf_const.setDoorConstruction(interior_door)
172
+ end
173
+ end
174
+ if @hash[:door_set][:exterior_construction]
175
+ ext_door_ref = openstudio_model.getConstructionByName(
176
+ @hash[:door_set][:exterior_construction])
177
+ unless ext_door_ref.empty?
178
+ exterior_door = ext_door_ref.get
179
+ ext_subsurf_const.setDoorConstruction(exterior_door)
180
+ end
181
+ end
182
+ if @hash[:door_set][:overhead_construction]
183
+ overhead_door_ref = openstudio_model.getConstructionByName(
184
+ @hash[:door_set][:overhead_construction])
185
+ unless overhead_door_ref.empty?
186
+ overhead_door = overhead_door_ref.get
187
+ ext_subsurf_const.setOverheadDoorConstruction(overhead_door)
188
+ end
189
+ end
190
+ if @hash[:door_set][:exterior_glass_construction]
191
+ ext_glz_door_ref = openstudio_model.getConstructionByName(
192
+ @hash[:door_set][:exterior_glass_construction])
193
+ unless ext_glz_door_ref.empty?
194
+ exterior_glass_door = ext_glz_door_ref.get
195
+ ext_subsurf_const.setGlassDoorConstruction(exterior_glass_door)
196
+ end
197
+ end
198
+ if @hash[:door_set][:interior_glass_construction]
199
+ int_glz_door_ref = openstudio_model.getConstructionByName(
200
+ @hash[:door_set][:interior_glass_construction])
201
+ unless int_glz_door_ref.empty?
202
+ interior_glass_door = int_glz_door_ref.get
203
+ int_subsurf_const.setGlassDoorConstruction(interior_glass_door)
204
+ end
205
+ end
206
+ end
207
+
208
+ # assign any shading constructions to construction set
209
+ if @hash[:shade_construction]
210
+ shade_ref = openstudio_model.getConstructionByName(@hash[:shade_construction])
211
+ unless shade_ref.empty?
212
+ shade_construction = shade_ref.get
213
+ os_constr_set.setSpaceShadingConstruction(shade_construction)
214
+ end
215
+ end
216
+
217
+ # assign any air boundary constructions to construction set
218
+ if @hash[:air_boundary_construction]
219
+ air_ref = openstudio_model.getConstructionAirBoundaryByName(
220
+ @hash[:air_boundary_construction])
221
+ unless air_ref.empty?
222
+ air_construction = air_ref.get
223
+ os_constr_set.setInteriorPartitionConstruction(air_construction)
224
+ end
225
+ end
226
+
227
+ os_constr_set
228
+ end
229
+
230
+ # get interior construction subset
231
+ def assign_constr_to_set_int(openstudio_model, constr_subset, face_type, constr_id_int)
232
+ unless constr_id_int.empty?
233
+ constr_id = constr_id_int.get
234
+ check_constr_type(constr_id, face_type, constr_subset)
235
+ end
236
+ end
237
+
238
+ # get exterior construction subset
239
+ def assign_constr_to_set_ext(openstudio_model, constr_subset, face_type, constr_id_ext)
240
+ unless constr_id_ext.empty?
241
+ constr_id = constr_id_ext.get
242
+ check_constr_type(constr_id, face_type, constr_subset)
243
+ end
244
+ end
245
+
246
+ # get ground construction subset
247
+ def assign_constr_to_set_grd(openstudio_model, constr_subset, face_type, constr_id_grd)
248
+ unless constr_id_grd.empty?
249
+ constr_id = constr_id_grd.get
250
+ check_constr_type(constr_id, face_type, constr_subset)
251
+ end
252
+ end
253
+
254
+ # check face type and assign to construction subset
255
+ def check_constr_type(constr_id, face_type, constr_subset)
256
+ if face_type == 'Wall'
257
+ constr_subset.setWallConstruction(constr_id)
258
+ elsif face_type == 'Floor'
259
+ constr_subset.setFloorConstruction(constr_id)
260
+ else
261
+ constr_subset.setRoofCeilingConstruction(constr_id)
262
+ end
263
+ end
264
+
265
+ end #ConstructionSetAbridged
266
+ end #Honeybee
@@ -0,0 +1,157 @@
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/aperture'
33
+
34
+ require 'to_openstudio/model_object'
35
+
36
+ module Honeybee
37
+ class Aperture < ModelObject
38
+
39
+ def find_existing_openstudio_object(openstudio_model)
40
+ object = openstudio_model.getSubSurfaceByName(@hash[:identifier])
41
+ return object.get if object.is_initialized
42
+ nil
43
+ end
44
+
45
+ def to_openstudio(openstudio_model)
46
+ # create the OpenStudio aperture object
47
+ os_vertices = OpenStudio::Point3dVector.new
48
+ @hash[:geometry][:boundary].each do |vertex|
49
+ os_vertices << OpenStudio::Point3d.new(vertex[0], vertex[1], vertex[2])
50
+ end
51
+ reordered_vertices = OpenStudio.reorderULC(os_vertices)
52
+
53
+ # triangulate subsurface if neccesary
54
+ triangulated = false
55
+ final_vertices_list = []
56
+ matching_os_subsurfaces = []
57
+ matching_os_subsurface_indices = []
58
+ if reordered_vertices.size > 4
59
+
60
+ # if this apeture has a matched apeture, see if the other one has already been created
61
+ # the matched apeture should have been converted to multiple subsurfaces
62
+ if @hash[:boundary_condition][:type] == 'Surface'
63
+ adj_srf_identifier = @hash[:boundary_condition][:boundary_condition_objects][0]
64
+ regex = Regexp.new("#{adj_srf_identifier}\.\.(\\d+)")
65
+ openstudio_model.getSubSurfaces.each do |subsurface|
66
+ if md = regex.match(subsurface.nameString)
67
+ final_vertices_list << OpenStudio.reorderULC(OpenStudio::reverse(subsurface.vertices))
68
+ matching_os_subsurfaces << subsurface
69
+ matching_os_subsurface_indices << md[1]
70
+ end
71
+ end
72
+ end
73
+
74
+ # if other apeture is not already created, do the triangulation
75
+ if final_vertices_list.empty?
76
+
77
+ # transform to face coordinates
78
+ t = OpenStudio::Transformation::alignFace(reordered_vertices)
79
+ tInv = t.inverse
80
+ face_vertices = OpenStudio::reverse(tInv*reordered_vertices)
81
+
82
+ # no holes in the subsurface
83
+ holes = OpenStudio::Point3dVectorVector.new
84
+
85
+ # triangulate surface
86
+ triangles = OpenStudio::computeTriangulation(face_vertices, holes)
87
+ if triangles.empty?
88
+ raise "Failed to triangulate aperture #{@hash[:identifier]} with #{reordered_vertices.size} vertices"
89
+ end
90
+
91
+ # create new list of surfaces
92
+ triangles.each do |vertices|
93
+ final_vertices_list << OpenStudio.reorderULC(OpenStudio::reverse(t*vertices))
94
+ end
95
+
96
+ triangulated = true
97
+
98
+ end
99
+
100
+ else
101
+ # reordered_vertices are good as is
102
+ final_vertices_list << reordered_vertices
103
+ end
104
+
105
+ result = []
106
+ final_vertices_list.each_with_index do |reordered_vertices, index|
107
+ os_subsurface = OpenStudio::Model::SubSurface.new(reordered_vertices, openstudio_model)
108
+
109
+ if !matching_os_subsurfaces.empty?
110
+ os_subsurface.setName(@hash[:identifier] + "..#{matching_os_subsurface_indices[index]}")
111
+ elsif triangulated
112
+ os_subsurface.setName(@hash[:identifier] + "..#{index}")
113
+ else
114
+ os_subsurface.setName(@hash[:identifier])
115
+ end
116
+
117
+ # assign the construction if it exists
118
+ if @hash[:properties][:energy][:construction]
119
+ construction_identifier = @hash[:properties][:energy][:construction]
120
+ construction = openstudio_model.getConstructionByName(construction_identifier)
121
+ unless construction.empty?
122
+ os_construction = construction.get
123
+ os_subsurface.setConstruction(os_construction)
124
+ end
125
+ end
126
+
127
+ # assign the boundary condition object if it's a Surface
128
+ if @hash[:boundary_condition][:type] == 'Surface'
129
+ if !matching_os_subsurfaces.empty?
130
+ # we already have the match because this was created from the matching_os_subsurfaces
131
+ # setAdjacentSubSurface will fail at this point because sub surface is not assigned to surface yet, store data for later
132
+ adj_srf_identifier = matching_os_subsurfaces[index].nameString
133
+ os_subsurface.additionalProperties.setFeature("AdjacentSubSurfaceName", adj_srf_identifier)
134
+ elsif triangulated
135
+ # other subsurfaces haven't been created yet, no-op
136
+ else
137
+ # get adjacent sub surface by identifier from openstudio model
138
+ # setAdjacentSubSurface will fail at this point because sub surface is not assigned to surface yet, store data for later
139
+ adj_srf_identifier = @hash[:boundary_condition][:boundary_condition_objects][0]
140
+ os_subsurface.additionalProperties.setFeature("AdjacentSubSurfaceName", adj_srf_identifier)
141
+ end
142
+ end
143
+
144
+ # assign the operable property
145
+ if @hash[:is_operable] == false
146
+ os_subsurface.setSubSurfaceType('FixedWindow')
147
+ else
148
+ os_subsurface.setSubSurfaceType('OperableWindow')
149
+ end
150
+
151
+ result << os_subsurface
152
+ end
153
+
154
+ return result
155
+ end
156
+ end # Aperture
157
+ end # Honeybee
@@ -0,0 +1,150 @@
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/door'
33
+
34
+ require 'to_openstudio/model_object'
35
+
36
+ module Honeybee
37
+ class Door
38
+
39
+ def find_existing_openstudio_object(openstudio_model)
40
+ object = openstudio_model.getSubSurfaceByName(@hash[:identifier])
41
+ return object.get if object.is_initialized
42
+ nil
43
+ end
44
+
45
+ def to_openstudio(openstudio_model)
46
+ # create the OpenStudio door object
47
+ os_vertices = OpenStudio::Point3dVector.new
48
+ @hash[:geometry][:boundary].each do |vertex|
49
+ os_vertices << OpenStudio::Point3d.new(vertex[0], vertex[1], vertex[2])
50
+ end
51
+ reordered_vertices = OpenStudio.reorderULC(os_vertices)
52
+
53
+ # triangulate subsurface if neccesary
54
+ triangulated = false
55
+ final_vertices_list = []
56
+ matching_os_subsurfaces = []
57
+ matching_os_subsurface_indices = []
58
+ if reordered_vertices.size > 4
59
+
60
+ # if this door has a matched door, see if the other one has already been created
61
+ # the matched door should have been converted to multiple subsurfaces
62
+ if @hash[:boundary_condition][:type] == 'Surface'
63
+ adj_srf_identifier = @hash[:boundary_condition][:boundary_condition_objects][0]
64
+ regex = Regexp.new("#{adj_srf_identifier}\.\.(\\d+)")
65
+ openstudio_model.getSubSurfaces.each do |subsurface|
66
+ if md = regex.match(subsurface.nameString)
67
+ final_vertices_list << OpenStudio.reorderULC(OpenStudio::reverse(subsurface.vertices))
68
+ matching_os_subsurfaces << subsurface
69
+ matching_os_subsurface_indices << md[1]
70
+ end
71
+ end
72
+ end
73
+
74
+ # if other door is not already created, do the triangulation
75
+ if final_vertices_list.empty?
76
+
77
+ # transform to face coordinates
78
+ t = OpenStudio::Transformation::alignFace(reordered_vertices)
79
+ tInv = t.inverse
80
+ face_vertices = OpenStudio::reverse(tInv*reordered_vertices)
81
+
82
+ # no holes in the subsurface
83
+ holes = OpenStudio::Point3dVectorVector.new
84
+
85
+ # triangulate surface
86
+ triangles = OpenStudio::computeTriangulation(face_vertices, holes)
87
+ if triangles.empty?
88
+ raise "Failed to triangulate door #{@hash[:identifier]} with #{reordered_vertices.size} vertices"
89
+ end
90
+
91
+ # create new list of surfaces
92
+ triangles.each do |vertices|
93
+ final_vertices_list << OpenStudio.reorderULC(OpenStudio::reverse(t*vertices))
94
+ end
95
+
96
+ triangulated = true
97
+
98
+ end
99
+
100
+ else
101
+ # reordered_vertices are good as is
102
+ final_vertices_list << reordered_vertices
103
+ end
104
+
105
+ result = []
106
+ final_vertices_list.each_with_index do |reordered_vertices, index|
107
+ os_subsurface = OpenStudio::Model::SubSurface.new(reordered_vertices, openstudio_model)
108
+
109
+ if !matching_os_subsurfaces.empty?
110
+ os_subsurface.setName(@hash[:identifier] + "..#{matching_os_subsurface_indices[index]}")
111
+ elsif triangulated
112
+ os_subsurface.setName(@hash[:identifier] + "..#{index}")
113
+ else
114
+ os_subsurface.setName(@hash[:identifier])
115
+ end
116
+
117
+ # assign the construction if it exists
118
+ if @hash[:properties][:energy][:construction]
119
+ construction_identifier = @hash[:properties][:energy][:construction]
120
+ construction = openstudio_model.getConstructionByName(construction_identifier)
121
+ unless construction.empty?
122
+ os_construction = construction.get
123
+ os_subsurface.setConstruction(os_construction)
124
+ end
125
+ end
126
+
127
+ # assign the boundary condition object if it's a Surface
128
+ if @hash[:boundary_condition][:type] == 'Surface'
129
+ if !matching_os_subsurfaces.empty?
130
+ # we already have the match because this was created from the matching_os_subsurfaces
131
+ # setAdjacentSubSurface will fail at this point because sub surface is not assigned to surface yet, store data for later
132
+ adj_srf_identifier = matching_os_subsurfaces[index].nameString
133
+ os_subsurface.additionalProperties.setFeature("AdjacentSubSurfaceName", adj_srf_identifier)
134
+ elsif triangulated
135
+ # other subsurfaces haven't been created yet, no-op
136
+ else
137
+ # get adjacent sub surface by identifier from openstudio model
138
+ # setAdjacentSubSurface will fail at this point because sub surface is not assigned to surface yet, store data for later
139
+ adj_srf_identifier = @hash[:boundary_condition][:boundary_condition_objects][0]
140
+ os_subsurface.additionalProperties.setFeature("AdjacentSubSurfaceName", adj_srf_identifier)
141
+ end
142
+ end
143
+
144
+ result << os_subsurface
145
+ end
146
+
147
+ return result
148
+ end
149
+ end # Door
150
+ end # Honeybee