honeybee-openstudio 2.0.2 → 2.3.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.
@@ -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