honeybee-openstudio 2.0.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -74,7 +74,6 @@ module FromHoneybee
74
74
 
75
75
  end #WindowConstructionAbridged
76
76
  end #FromHoneybee
77
-
78
77
 
79
78
 
80
79
 
@@ -0,0 +1,207 @@
1
+ # *******************************************************************************
2
+ # Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
3
+ # Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # (1) Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # (3) Neither the name of the copyright holder nor the names of any contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission from the respective party.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
23
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
24
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # *******************************************************************************
31
+
32
+ require 'from_honeybee/model_object'
33
+ require 'from_honeybee/construction/window'
34
+
35
+ require 'openstudio'
36
+
37
+ module FromHoneybee
38
+ class WindowConstructionShadeAbridged < ModelObject
39
+ attr_reader :errors, :warnings
40
+
41
+ def initialize(hash = {})
42
+ super(hash)
43
+ @construction = nil
44
+ @shade_construction = nil
45
+ @shade_location = nil
46
+ @shade_material = nil
47
+ @control_type = nil
48
+ @setpoint = nil
49
+ @schedule = nil
50
+ end
51
+
52
+ def defaults
53
+ @@schema[:components][:schemas][:WindowConstructionShadeAbridged][:properties]
54
+ end
55
+
56
+ def find_existing_openstudio_object(openstudio_model)
57
+ object = openstudio_model.getConstructionByName(@hash[:identifier])
58
+ return object.get if object.is_initialized
59
+ nil
60
+ end
61
+
62
+ def to_openstudio(openstudio_model)
63
+ # write the shaded and unsaded versions of the construciton into the model
64
+ # reverse the shaded and unshaded identifiers so unshaded one is assigned to apertures
65
+ unshd_id = @hash[:identifier]
66
+ shd_id = @hash[:window_construction][:identifier]
67
+ @hash[:window_construction][:identifier] = unshd_id
68
+ @hash[:identifier] = shd_id
69
+
70
+ # create the unshaded construction
71
+ unshd_constr_obj = WindowConstructionAbridged.new(@hash[:window_construction])
72
+ @construction = unshd_constr_obj.to_openstudio(openstudio_model)
73
+
74
+ # create the shaded construction
75
+ @shade_construction = OpenStudio::Model::Construction.new(openstudio_model)
76
+ @shade_construction.setName(shd_id)
77
+
78
+ # create the layers of the unshaded construction into which we will insert the shade
79
+ os_materials = []
80
+ @hash[:window_construction][:layers].each do |layer|
81
+ material_identifier = layer
82
+ material = openstudio_model.getMaterialByName(material_identifier)
83
+ unless material.empty?
84
+ os_material = material.get
85
+ os_materials << os_material
86
+ end
87
+ end
88
+
89
+ # figure out where to insert the shade material and insert it
90
+ if @hash[:shade_location]
91
+ @shade_location = @hash[:shade_location]
92
+ else
93
+ @shade_location = defaults[:shade_location][:default]
94
+ end
95
+
96
+ # insert the shade material
97
+ shd_mat_name = openstudio_model.getMaterialByName(@hash[:shade_material])
98
+ unless shd_mat_name.empty?
99
+ @shade_material = shd_mat_name.get
100
+ end
101
+ unless @shade_material.nil?
102
+ if @shade_material.is_a? OpenStudio::Model::StandardGlazing
103
+ if @shade_location == 'Interior'
104
+ os_materials[-1] = @shade_material
105
+ elsif @shade_location == 'Exterior' | os_materials.length < 2
106
+ os_materials[0] = @shade_material
107
+ else # middle glass pane
108
+ os_materials[-3] = @shade_material
109
+ end
110
+ else
111
+ if @shade_location == 'Interior'
112
+ os_materials << @shade_material
113
+ elsif @shade_location == 'Exterior'
114
+ os_materials.unshift(@shade_material)
115
+ else # between glass shade/blind
116
+ split_gap = split_gas_gap(openstudio_model, os_materials[-2], @shade_material)
117
+ os_materials[-2] = split_gap
118
+ os_materials.insert(-2, @shade_material)
119
+ os_materials.insert(-2, split_gap)
120
+ end
121
+ end
122
+ end
123
+
124
+ # assign the layers to the shaded construction
125
+ os_materials_vec = OpenStudio::Model::MaterialVector.new
126
+ os_materials.each do |mat|
127
+ os_materials_vec << mat
128
+ end
129
+ @shade_construction.setLayers(os_materials)
130
+
131
+ # set defaults for control type, setpoint, and schedule
132
+ if @hash[:control_type]
133
+ @control_type = @hash[:control_type]
134
+ else
135
+ @control_type = defaults[:control_type][:default]
136
+ end
137
+
138
+ if @hash[:setpoint]
139
+ @setpoint = @hash[:setpoint]
140
+ else
141
+ @setpoint = defaults[:setpoint][:default]
142
+ end
143
+
144
+ unless @hash[:schedule].nil?
145
+ schedule_ref = openstudio_model.getScheduleByName(@hash[:schedule])
146
+ unless schedule_ref.empty?
147
+ @schedule = schedule_ref.get
148
+ if @control_type == 'AlwaysOn'
149
+ @control_type = 'OnIfScheduleAllows'
150
+ end
151
+ end
152
+ end
153
+
154
+ @shade_construction
155
+ end
156
+
157
+ def to_openstudio_shading_control(openstudio_model)
158
+ # add a WindowShadingControl object to a model for a given aperture and room
159
+ os_shade_control = OpenStudio::Model::ShadingControl.new(@shade_construction)
160
+
161
+ # figure out the shading type
162
+ if @shade_material.is_a? OpenStudio::Model::StandardGlazing
163
+ shd_type = 'SwitchableGlazing'
164
+ elsif @shade_material.is_a? OpenStudio::Model::Blind
165
+ if @shade_location == 'Between'
166
+ shd_type = 'BetweenGlassBlind'
167
+ else
168
+ shd_type = @shade_location + 'Blind'
169
+ end
170
+ else
171
+ if @shade_location == 'Between'
172
+ shd_type = 'BetweenGlassShade'
173
+ else
174
+ shd_type = @shade_location + 'Shade'
175
+ end
176
+ end
177
+ os_shade_control.setShadingType(shd_type)
178
+
179
+ # set the shade control type and schedule
180
+ os_shade_control.setShadingControlType(@control_type)
181
+ unless @setpoint.nil?
182
+ os_shade_control.setSetpoint(@setpoint)
183
+ end
184
+ unless @schedule.nil?
185
+ os_shade_control.setSchedule(@schedule)
186
+ end
187
+
188
+ os_shade_control
189
+ end
190
+
191
+ def split_gas_gap(openstudio_model, original_gap, shade_material)
192
+ # split a gas gap material in two when it is interrupeted by a shade/blind
193
+ if shade_material.is_a? OpenStudio::Model::Blind
194
+ shd_thick = 0
195
+ else
196
+ shd_thick = shade_material.thickness
197
+ end
198
+ gap_thick = (original_gap.thickness - shd_thick) / 2
199
+ gap_obj = $gas_gap_hash[original_gap.name.get]
200
+ new_gap = gap_obj.to_openstudio(openstudio_model)
201
+ new_gap.setName(original_gap.name.get + gap_thick.to_s)
202
+ new_gap.setThickness(gap_thick)
203
+ new_gap
204
+ end
205
+
206
+ end #WindowConstructionShadeAbridged
207
+ end #FromHoneybee
@@ -37,6 +37,7 @@ require 'openstudio/extension'
37
37
  module FromHoneybee
38
38
  class Extension < OpenStudio::Extension::Extension
39
39
  @@schema = nil
40
+ @@standards = nil
40
41
 
41
42
  # Override parent class
42
43
  def initialize
@@ -49,6 +50,7 @@ module FromHoneybee
49
50
 
50
51
  @instance_lock = Mutex.new
51
52
  @@schema ||= schema
53
+ @@standards ||= standards
52
54
  end
53
55
 
54
56
  # Return the absolute path of the measures or nil if there is none.
@@ -73,7 +75,12 @@ module FromHoneybee
73
75
 
74
76
  # return path to the model schema file
75
77
  def schema_file
76
- File.join(@lib_dir, 'from_honeybee', '_openapi', 'model.json')
78
+ File.join(@lib_dir, 'from_honeybee', '_defaults', 'model.json')
79
+ end
80
+
81
+ # return path to the model standards file
82
+ def standards_file
83
+ File.join(@lib_dir, 'from_honeybee', '_defaults', 'energy_default.json')
77
84
  end
78
85
 
79
86
  # return the model schema
@@ -89,6 +96,19 @@ module FromHoneybee
89
96
  @@schema
90
97
  end
91
98
 
99
+ # return the JSON of default standards
100
+ def standards
101
+ @instance_lock.synchronize do
102
+ if @@standards.nil?
103
+ File.open(standards_file, 'r') do |f|
104
+ @@standards = JSON.parse(f.read, symbolize_names: true)
105
+ end
106
+ end
107
+ end
108
+
109
+ @@standards
110
+ end
111
+
92
112
  # check if the model schema is valid
93
113
  def schema_valid?
94
114
  if Gem.loaded_specs.has_key?("json-schema")
@@ -50,6 +50,7 @@ require 'from_honeybee/hvac/ideal_air'
50
50
  # import the construction objects
51
51
  require 'from_honeybee/construction/opaque'
52
52
  require 'from_honeybee/construction/window'
53
+ require 'from_honeybee/construction/windowshade'
53
54
  require 'from_honeybee/construction/shade'
54
55
  require 'from_honeybee/construction/air'
55
56
 
@@ -94,12 +95,12 @@ module FromHoneybee
94
95
  # initialize class variable @@extension only once
95
96
  @@extension ||= Extension.new
96
97
  @@schema ||= @@extension.schema
98
+ @@standards ||= @@extension.standards
97
99
 
98
100
  @hash = hash
99
101
  @type = @hash[:type]
100
102
  raise 'Unknown model type' if @type.nil?
101
103
  raise "Incorrect model type '#{@type}'" unless @type == 'Model'
102
-
103
104
  end
104
105
 
105
106
  # check if the model is valid
@@ -156,40 +157,75 @@ module FromHoneybee
156
157
  building = @openstudio_model.getBuilding
157
158
  building.setStandardsBuildingType('MediumOffice')
158
159
 
160
+ # initialize global hashes for various model properties
161
+ $gas_gap_hash = Hash.new # hash to track gas gaps in case they are split by shades
162
+ $air_boundary_hash = Hash.new # hash to track any air boundary constructions
163
+ $window_shade_hash = Hash.new # hash to track any window constructions with shade
164
+ $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
165
+
159
166
  # create all of the non-geometric model elements
160
167
  if log_report
161
168
  puts 'Translating Materials'
162
169
  end
163
- create_materials
170
+ if @hash[:properties][:energy][:materials]
171
+ create_materials(@hash[:properties][:energy][:materials])
172
+ end
164
173
 
165
174
  if log_report
166
175
  puts 'Translating Constructions'
167
176
  end
168
- create_constructions
177
+ if @hash[:properties][:energy][:constructions]
178
+ create_constructions(@hash[:properties][:energy][:constructions])
179
+ end
169
180
 
170
181
  if log_report
171
182
  puts 'Translating ConstructionSets'
172
183
  end
173
- create_construction_set
174
- create_global_construction_set
184
+ if @hash[:properties][:energy][:construction_sets]
185
+ create_construction_sets(@hash[:properties][:energy][:construction_sets])
186
+ end
175
187
 
176
188
  if log_report
177
189
  puts 'Translating Schedules'
178
190
  end
179
- create_schedule_type_limits
180
- create_schedules
191
+ if @hash[:properties][:energy][:schedule_type_limits]
192
+ create_schedule_type_limits(@hash[:properties][:energy][:schedule_type_limits])
193
+ end
194
+ if @hash[:properties][:energy][:schedules]
195
+ create_schedules(@hash[:properties][:energy][:schedules])
196
+ end
181
197
 
182
198
  if log_report
183
199
  puts 'Translating ProgramTypes'
184
200
  end
185
- create_program_types
201
+ if @hash[:properties][:energy][:program_types]
202
+ create_program_types(@hash[:properties][:energy][:program_types])
203
+ end
204
+
205
+ # create the default construction set to catch any cases of unassigned constructions
206
+ if log_report
207
+ puts 'Translating Default ConstructionSet'
208
+ end
209
+ create_default_construction_set
186
210
 
187
- # create all of the model geometry
211
+ # create the geometry and add any extra properties to it
188
212
  if log_report
189
213
  puts 'Translating Room Geometry'
190
214
  end
191
215
  create_rooms
192
216
 
217
+ unless $window_shade_hash.empty?
218
+ if log_report
219
+ puts 'Translating Window Shading Control'
220
+ end
221
+ create_shading_control
222
+ end
223
+
224
+ if log_report
225
+ puts 'Translating HVAC Systems'
226
+ end
227
+ create_hvacs
228
+
193
229
  if log_report
194
230
  puts 'Translating Context Shade Geometry'
195
231
  end
@@ -197,100 +233,141 @@ module FromHoneybee
197
233
  create_orphaned_faces
198
234
  create_orphaned_apertures
199
235
  create_orphaned_doors
200
-
201
- # create the hvac systems
202
- if log_report
203
- puts 'Translating HVAC Systems'
204
- end
205
- create_hvacs
206
236
  end
207
237
 
208
- def create_materials
209
- @hash[:properties][:energy][:materials].each do |material|
210
- material_type = material[:type]
211
-
212
- case material_type
213
- when 'EnergyMaterial'
214
- material_object = EnergyMaterial.new(material)
215
- when 'EnergyMaterialNoMass'
216
- material_object = EnergyMaterialNoMass.new(material)
217
- when 'EnergyWindowMaterialGas'
218
- material_object = EnergyWindowMaterialGas.new(material)
219
- when 'EnergyWindowMaterialGasCustom'
220
- material_object = EnergyWindowMaterialGasCustom.new(material)
221
- when 'EnergyWindowMaterialSimpleGlazSys'
222
- material_object = EnergyWindowMaterialSimpleGlazSys.new(material)
223
- when 'EnergyWindowMaterialBlind'
224
- material_object = EnergyWindowMaterialBlind.new(material)
225
- when 'EnergyWindowMaterialGlazing'
226
- material_object = EnergyWindowMaterialGlazing.new(material)
227
- when 'EnergyWindowMaterialShade'
228
- material_object = EnergyWindowMaterialShade.new(material)
229
- else
230
- raise "Unknown material type #{material_type}"
238
+ def create_materials(material_dicts, check_existing=false)
239
+ material_dicts.each do |material|
240
+ # check if there's already a material in the model with the identifier
241
+ add_obj = true
242
+ if check_existing
243
+ object = @openstudio_model.getMaterialByName(material[:identifier])
244
+ if object.is_initialized
245
+ add_obj = false
246
+ end
247
+ end
248
+
249
+ # add the material object to the Model
250
+ if add_obj
251
+ material_type = material[:type]
252
+ case material_type
253
+ when 'EnergyMaterial'
254
+ material_object = EnergyMaterial.new(material)
255
+ when 'EnergyMaterialNoMass'
256
+ material_object = EnergyMaterialNoMass.new(material)
257
+ when 'EnergyWindowMaterialGas'
258
+ material_object = EnergyWindowMaterialGas.new(material)
259
+ $gas_gap_hash[material[:identifier]] = material_object
260
+ when 'EnergyWindowMaterialGasMixture'
261
+ material_object = EnergyWindowMaterialGasMixture.new(material)
262
+ $gas_gap_hash[material[:identifier]] = material_object
263
+ when 'EnergyWindowMaterialGasCustom'
264
+ material_object = EnergyWindowMaterialGasCustom.new(material)
265
+ $gas_gap_hash[material[:identifier]] = material_object
266
+ when 'EnergyWindowMaterialSimpleGlazSys'
267
+ material_object = EnergyWindowMaterialSimpleGlazSys.new(material)
268
+ when 'EnergyWindowMaterialBlind'
269
+ material_object = EnergyWindowMaterialBlind.new(material)
270
+ when 'EnergyWindowMaterialGlazing'
271
+ material_object = EnergyWindowMaterialGlazing.new(material)
272
+ when 'EnergyWindowMaterialShade'
273
+ material_object = EnergyWindowMaterialShade.new(material)
274
+ else
275
+ raise "Unknown material type #{material_type}"
276
+ end
277
+ material_object.to_openstudio(@openstudio_model)
231
278
  end
232
- material_object.to_openstudio(@openstudio_model)
233
279
  end
234
280
  end
235
281
 
236
- def create_constructions
237
- $air_boundary_hash = Hash.new # hash to track any air boundary constructions
282
+ def create_constructions(construction_dicts, check_existing=false)
283
+ construction_dicts.each do |construction|
284
+ # check if there's already a construction in the model with the identifier
285
+ add_obj = true
286
+ if check_existing
287
+ object = @openstudio_model.getConstructionByName(construction[:identifier])
288
+ if object.is_initialized
289
+ add_obj = false
290
+ end
291
+ end
238
292
 
239
- @hash[:properties][:energy][:constructions].each do |construction|
240
- identifier = construction[:identifier]
241
- construction_type = construction[:type]
242
-
243
- case construction_type
244
- when 'OpaqueConstructionAbridged'
245
- construction_object = OpaqueConstructionAbridged.new(construction)
246
- when 'WindowConstructionAbridged'
247
- construction_object = WindowConstructionAbridged.new(construction)
248
- when 'ShadeConstruction'
249
- construction_object = ShadeConstruction.new(construction)
250
- when 'AirBoundaryConstructionAbridged'
251
- construction_object = AirBoundaryConstructionAbridged.new(construction)
252
- $air_boundary_hash[construction[:identifier]] = construction
253
- else
254
- raise "Unknown construction type #{construction_type}."
293
+ # add the construction object to the Model
294
+ if add_obj
295
+ construction_type = construction[:type]
296
+ case construction_type
297
+ when 'OpaqueConstructionAbridged'
298
+ construction_object = OpaqueConstructionAbridged.new(construction)
299
+ when 'WindowConstructionAbridged'
300
+ construction_object = WindowConstructionAbridged.new(construction)
301
+ when 'WindowConstructionShadeAbridged'
302
+ construction_object = WindowConstructionShadeAbridged.new(construction)
303
+ $window_shade_hash[construction[:identifier]] = construction_object
304
+ when 'ShadeConstruction'
305
+ construction_object = ShadeConstruction.new(construction)
306
+ when 'AirBoundaryConstructionAbridged'
307
+ construction_object = AirBoundaryConstructionAbridged.new(construction)
308
+ $air_boundary_hash[construction[:identifier]] = construction
309
+ else
310
+ raise "Unknown construction type #{construction_type}."
311
+ end
312
+ construction_object.to_openstudio(@openstudio_model)
255
313
  end
256
- construction_object.to_openstudio(@openstudio_model)
257
314
  end
258
315
  end
259
316
 
260
- def create_construction_set
261
- if @hash[:properties][:energy][:construction_sets]
262
- @hash[:properties][:energy][:construction_sets].each do |construction_set|
263
- construction_set_object = ConstructionSetAbridged.new(construction_set)
264
- construction_set_object.to_openstudio(@openstudio_model)
317
+ def create_construction_sets(construction_set_dicts, check_existing=false)
318
+ construction_set_dicts.each do |construction_set|
319
+ # check if there's already a construction set in the model with the identifier
320
+ add_obj = true
321
+ if check_existing
322
+ object = @openstudio_model.getDefaultConstructionSetByName(
323
+ construction_set[:identifier])
324
+ if object.is_initialized
325
+ add_obj = false
326
+ end
265
327
  end
266
- end
267
- end
268
328
 
269
- def create_global_construction_set
270
- if @hash[:properties][:energy][:global_construction_set]
271
- construction_id = @hash[:properties][:energy][:global_construction_set]
272
- construction = @openstudio_model.getDefaultConstructionSetByName(construction_id)
273
- unless construction.empty?
274
- openstudio_construction = construction.get
329
+ # add the construction set object to the Model
330
+ if add_obj
331
+ construction_set_object = ConstructionSetAbridged.new(construction_set)
332
+ construction_set_object.to_openstudio(@openstudio_model)
275
333
  end
276
- @openstudio_model.getBuilding.setDefaultConstructionSet(openstudio_construction)
277
334
  end
278
335
  end
279
336
 
280
- def create_schedule_type_limits
281
- if @hash[:properties][:energy][:schedule_type_limits]
282
- @hash[:properties][:energy][:schedule_type_limits].each do |schedule_type_limit|
337
+ def create_schedule_type_limits(stl_dicts, check_existing=false)
338
+ stl_dicts.each do |schedule_type_limit|
339
+ # check if there's already a schedule type limit in the model with the identifier
340
+ add_obj = true
341
+ if check_existing
342
+ object = @openstudio_model.getScheduleTypeLimitsByName(
343
+ schedule_type_limit[:identifier])
344
+ if object.is_initialized
345
+ add_obj = false
346
+ end
347
+ end
348
+
349
+ # add the schedule type limit object to the Model
350
+ if add_obj
283
351
  schedule_type_limit_object = ScheduleTypeLimit.new(schedule_type_limit)
284
352
  schedule_type_limit_object.to_openstudio(@openstudio_model)
285
353
  end
286
354
  end
287
355
  end
288
356
 
289
- def create_schedules
290
- if @hash[:properties][:energy][:schedules]
291
- @hash[:properties][:energy][:schedules].each do |schedule|
292
- schedule_type = schedule[:type]
357
+ def create_schedules(schedule_dicts, check_existing=false)
358
+ schedule_dicts.each do |schedule|
359
+ # check if there's already a schedule in the model with the identifier
360
+ add_obj = true
361
+ if check_existing
362
+ object = @openstudio_model.getScheduleByName(schedule[:identifier])
363
+ if object.is_initialized
364
+ add_obj = false
365
+ end
366
+ end
293
367
 
368
+ # add the schedule object to the Model
369
+ if add_obj
370
+ schedule_type = schedule[:type]
294
371
  case schedule_type
295
372
  when 'ScheduleRulesetAbridged'
296
373
  schedule_object = ScheduleRulesetAbridged.new(schedule)
@@ -300,21 +377,56 @@ module FromHoneybee
300
377
  raise("Unknown schedule type #{schedule_type}.")
301
378
  end
302
379
  schedule_object.to_openstudio(@openstudio_model)
303
-
304
380
  end
305
381
  end
306
382
  end
307
383
 
308
- def create_program_types
309
- if @hash[:properties][:energy][:program_types]
310
- $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
311
- @hash[:properties][:energy][:program_types].each do |space_type|
384
+ def create_program_types(program_dicts, check_existing=false)
385
+ program_dicts.each do |space_type|
386
+ # check if there's already a space type in the model with the identifier
387
+ add_obj = true
388
+ if check_existing
389
+ object = @openstudio_model.getSpaceTypeByName(space_type[:identifier])
390
+ if object.is_initialized
391
+ add_obj = false
392
+ end
393
+ end
394
+
395
+ # add the space type object to the Model
396
+ if add_obj
312
397
  space_type_object = ProgramTypeAbridged.new(space_type)
313
398
  space_type_object.to_openstudio(@openstudio_model)
314
399
  end
315
400
  end
316
401
  end
317
402
 
403
+ def create_default_construction_set
404
+ # create the materials, constructions and construction set
405
+ create_materials(@@standards[:materials], true)
406
+ create_constructions(@@standards[:constructions], true)
407
+ create_construction_sets(@@standards[:construction_sets], true)
408
+
409
+ # write the fractional schedule type and always on schedule if they are not there
410
+ @@standards[:schedule_type_limits].each do |sch_type_limit|
411
+ if sch_type_limit[:identifier] == 'Fractional'
412
+ create_schedule_type_limits([sch_type_limit], true)
413
+ end
414
+ end
415
+ @@standards[:schedules].each do |schedule|
416
+ if schedule[:identifier] == 'Always On'
417
+ create_schedules([schedule], true)
418
+ end
419
+ end
420
+
421
+ # set the default construction set to the building level of the Model
422
+ construction_id = 'Default Generic Construction Set'
423
+ construction = @openstudio_model.getDefaultConstructionSetByName(construction_id)
424
+ unless construction.empty?
425
+ os_constructionset = construction.get
426
+ @openstudio_model.getBuilding.setDefaultConstructionSet(os_constructionset)
427
+ end
428
+ end
429
+
318
430
  def create_rooms
319
431
  if @hash[:rooms]
320
432
  $air_mxing_array = [] # list to track any air mixing between Rooms
@@ -344,7 +456,7 @@ module FromHoneybee
344
456
  end
345
457
  end
346
458
 
347
- # Create mixing objects between Rooms
459
+ # create mixing objects between Rooms
348
460
  $air_mxing_array.each do |air_mix_props|
349
461
  zone_mixing = OpenStudio::Model::ZoneMixing.new(air_mix_props[0])
350
462
  zone_mixing.setDesignFlowRate(air_mix_props[1])
@@ -361,35 +473,25 @@ module FromHoneybee
361
473
  end
362
474
  end
363
475
  end
364
-
365
-
366
- def create_orphaned_shades
367
- if @hash[:orphaned_shades]
368
- shading_surface_group = OpenStudio::Model::ShadingSurfaceGroup.new(@openstudio_model)
369
- shading_surface_group.setShadingSurfaceType('Building')
370
- @hash[:orphaned_shades].each do |shade|
371
- shade_object = Shade.new(shade)
372
- openstudio_shade = shade_object.to_openstudio(@openstudio_model)
373
- openstudio_shade.setShadingSurfaceGroup(shading_surface_group)
374
- end
375
- end
376
- end
377
-
378
- def create_orphaned_faces
379
- if @hash[:orphaned_faces]
380
- raise "Orphaned Faces are not translatable to OpenStudio."
381
- end
382
- end
383
476
 
384
- def create_orphaned_apertures
385
- if @hash[:orphaned_apertures]
386
- raise "Orphaned Apertures are not translatable to OpenStudio."
387
- end
388
- end
389
-
390
- def create_orphaned_doors
391
- if @hash[:orphaned_doors]
392
- raise "Orphaned Doors are not translatable to OpenStudio."
477
+ def create_shading_control
478
+ # assign any shading control objects to windows with shades
479
+ # this is run as a separate step once all logic about construction sets is in place
480
+ sub_faces = @openstudio_model.getSubSurfaces()
481
+ sub_faces.each do |sub_face|
482
+ constr_ref = sub_face.construction
483
+ unless constr_ref.empty?
484
+ constr = constr_ref.get
485
+ constr_name_ref = constr.name
486
+ unless constr_name_ref.empty?
487
+ constr_name = constr_name_ref.get
488
+ unless $window_shade_hash[constr_name].nil?
489
+ window_shd_constr = $window_shade_hash[constr_name]
490
+ os_shd_control = window_shd_constr.to_openstudio_shading_control(@openstudio_model)
491
+ sub_face.setShadingControl(os_shd_control)
492
+ end
493
+ end
494
+ end
393
495
  end
394
496
  end
395
497
 
@@ -428,6 +530,36 @@ module FromHoneybee
428
530
  end
429
531
  end
430
532
 
533
+ def create_orphaned_shades
534
+ if @hash[:orphaned_shades]
535
+ shading_surface_group = OpenStudio::Model::ShadingSurfaceGroup.new(@openstudio_model)
536
+ shading_surface_group.setShadingSurfaceType('Building')
537
+ @hash[:orphaned_shades].each do |shade|
538
+ shade_object = Shade.new(shade)
539
+ openstudio_shade = shade_object.to_openstudio(@openstudio_model)
540
+ openstudio_shade.setShadingSurfaceGroup(shading_surface_group)
541
+ end
542
+ end
543
+ end
544
+
545
+ def create_orphaned_faces
546
+ if @hash[:orphaned_faces]
547
+ raise "Orphaned Faces are not translatable to OpenStudio."
548
+ end
549
+ end
550
+
551
+ def create_orphaned_apertures
552
+ if @hash[:orphaned_apertures]
553
+ raise "Orphaned Apertures are not translatable to OpenStudio."
554
+ end
555
+ end
556
+
557
+ def create_orphaned_doors
558
+ if @hash[:orphaned_doors]
559
+ raise "Orphaned Doors are not translatable to OpenStudio."
560
+ end
561
+ end
562
+
431
563
  #TODO: create runlog for errors.
432
564
 
433
565
  end # Model