honeybee-openstudio 2.1.0 → 2.4.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.
@@ -3,7 +3,7 @@
3
3
  "servers": [],
4
4
  "info": {
5
5
  "description": "This is the documentation for Honeybee model schema.",
6
- "version": "1.32.0",
6
+ "version": "1.34.3",
7
7
  "title": "Honeybee Model Schema",
8
8
  "contact": {
9
9
  "name": "Ladybug Tools",
@@ -4577,15 +4577,7 @@
4577
4577
  "description": "An optional schedule identifier to be applied on top of the control_type. If None, the control_type will govern all behavior of the construction.",
4578
4578
  "maxLength": 100,
4579
4579
  "minLength": 1,
4580
- "type": "string",
4581
- "anyOf": [
4582
- {
4583
- "$ref": "#/components/schemas/ScheduleRuleset"
4584
- },
4585
- {
4586
- "$ref": "#/components/schemas/ScheduleFixedInterval"
4587
- }
4588
- ]
4580
+ "type": "string"
4589
4581
  }
4590
4582
  },
4591
4583
  "required": [
@@ -6223,13 +6215,6 @@
6223
6215
  "type": "string",
6224
6216
  "readOnly": true
6225
6217
  },
6226
- "global_construction_set": {
6227
- "title": "Global Construction Set",
6228
- "description": "Identifier for the ConstructionSet to be used for all objects lacking their own construction or a parent Room construction_set. This ConstructionSet must appear under the Model construction_sets.",
6229
- "maxLength": 100,
6230
- "minLength": 1,
6231
- "type": "string"
6232
- },
6233
6218
  "construction_sets": {
6234
6219
  "title": "Construction Sets",
6235
6220
  "description": "List of all unique ConstructionSets in the Model.",
@@ -8662,11 +8647,6 @@
8662
8647
  }
8663
8648
  ]
8664
8649
  }
8665
- },
8666
- "global_modifier_set": {
8667
- "title": "Global Modifier Set",
8668
- "description": "Identifier of a ModifierSet or ModifierSetAbridged object to be used as as a default object for all unassigned objects in the Model (default: None).",
8669
- "type": "string"
8670
8650
  }
8671
8651
  },
8672
8652
  "additionalProperties": false
@@ -8729,6 +8709,13 @@
8729
8709
  "type": "string",
8730
8710
  "readOnly": true
8731
8711
  },
8712
+ "version": {
8713
+ "title": "Version",
8714
+ "description": "Text string for the current version of the schema.",
8715
+ "default": "0.0.0",
8716
+ "pattern": "([0-9]+)\\.([0-9]+)\\.([0-9]+)",
8717
+ "type": "string"
8718
+ },
8732
8719
  "rooms": {
8733
8720
  "title": "Rooms",
8734
8721
  "description": "A list of Rooms in the model.",
@@ -3,7 +3,7 @@
3
3
  "servers": [],
4
4
  "info": {
5
5
  "description": "This is the documentation for Honeybee energy simulation parameter schema.",
6
- "version": "0.0.1",
6
+ "version": "1.34.3",
7
7
  "title": "Honeybee Energy Simulation Parameter Schema",
8
8
  "contact": {
9
9
  "name": "Ladybug Tools",
@@ -469,7 +469,7 @@
469
469
  },
470
470
  "dry_bulb_range": {
471
471
  "title": "Dry Bulb Range",
472
- "description": "The difference between min and max temperatures on thedesign day [C].",
472
+ "description": "The difference between min and max temperatures on the design day [C].",
473
473
  "minimum": 0,
474
474
  "type": "number",
475
475
  "format": "double"
@@ -585,7 +585,7 @@
585
585
  "properties": {
586
586
  "date": {
587
587
  "title": "Date",
588
- "description": "A list of two integers for [month, day], representing the date for the day of the year on which the design day occurs.A third integer may be added to denote whether the date should be re-serialized for a leap year (it should be a 1 in this case).",
588
+ "description": "A list of two integers for [month, day], representing the date for the day of the year on which the design day occurs. A third integer may be added to denote whether the date should be re-serialized for a leap year (it should be a 1 in this case).",
589
589
  "type": "array",
590
590
  "items": {
591
591
  "type": "integer",
@@ -629,7 +629,7 @@
629
629
  "properties": {
630
630
  "date": {
631
631
  "title": "Date",
632
- "description": "A list of two integers for [month, day], representing the date for the day of the year on which the design day occurs.A third integer may be added to denote whether the date should be re-serialized for a leap year (it should be a 1 in this case).",
632
+ "description": "A list of two integers for [month, day], representing the date for the day of the year on which the design day occurs. A third integer may be added to denote whether the date should be re-serialized for a leap year (it should be a 1 in this case).",
633
633
  "type": "array",
634
634
  "items": {
635
635
  "type": "integer",
@@ -97,9 +97,10 @@ module FromHoneybee
97
97
  shd_mat_name = openstudio_model.getMaterialByName(@hash[:shade_material])
98
98
  unless shd_mat_name.empty?
99
99
  @shade_material = shd_mat_name.get
100
+ obj_type = @shade_material.iddObject.name
100
101
  end
101
102
  unless @shade_material.nil?
102
- if @shade_material.is_a? OpenStudio::Model::StandardGlazing
103
+ if obj_type == 'OS:WindowMaterial:StandardGlazing'
103
104
  if @shade_location == 'Interior'
104
105
  os_materials[-1] = @shade_material
105
106
  elsif @shade_location == 'Exterior' | os_materials.length < 2
@@ -159,9 +160,12 @@ module FromHoneybee
159
160
  os_shade_control = OpenStudio::Model::ShadingControl.new(@shade_construction)
160
161
 
161
162
  # figure out the shading type
162
- if @shade_material.is_a? OpenStudio::Model::StandardGlazing
163
+ unless @shade_material.nil?
164
+ obj_type = @shade_material.iddObject.name
165
+ end
166
+ if obj_type == 'OS:WindowMaterial:StandardGlazing'
163
167
  shd_type = 'SwitchableGlazing'
164
- elsif @shade_material.is_a? OpenStudio::Model::Blind
168
+ elsif obj_type == 'OS:WindowMaterial:Blind'
165
169
  if @shade_location == 'Between'
166
170
  shd_type = 'BetweenGlassBlind'
167
171
  else
@@ -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")
@@ -42,6 +42,7 @@ require 'from_honeybee/load/infiltration'
42
42
  require 'from_honeybee/load/ventilation'
43
43
  require 'from_honeybee/load/setpoint_thermostat'
44
44
  require 'from_honeybee/load/setpoint_humidistat'
45
+ require 'from_honeybee/ventcool/opening'
45
46
 
46
47
  require 'openstudio'
47
48
 
@@ -117,6 +118,9 @@ module FromHoneybee
117
118
  end
118
119
  os_space.setBuildingStory(story)
119
120
 
121
+ # keep track of all window ventilation objects
122
+ window_vent = {}
123
+
120
124
  # assign all of the faces to the room
121
125
  @hash[:faces].each do |face|
122
126
  ladybug_face = Face.new(face)
@@ -134,6 +138,9 @@ module FromHoneybee
134
138
  # assign aperture-level shades if they exist
135
139
  if face[:apertures]
136
140
  face[:apertures].each do |aperture|
141
+ if aperture[:properties][:energy][:vent_opening]
142
+ window_vent[aperture[:identifier]] = aperture[:properties][:energy][:vent_opening]
143
+ end
137
144
  if aperture[:outdoor_shades]
138
145
  unless os_shd_group
139
146
  os_shd_group = make_shade_group(openstudio_model, os_surface, os_space)
@@ -148,6 +155,9 @@ module FromHoneybee
148
155
  # assign door-level shades if they exist
149
156
  if face[:doors]
150
157
  face[:doors].each do |door|
158
+ if door[:properties][:energy][:vent_opening]
159
+ window_vent[door[:identifier]] = door[:properties][:energy][:vent_opening]
160
+ end
151
161
  if door[:outdoor_shades]
152
162
  unless os_shd_group
153
163
  os_shd_group = make_shade_group(openstudio_model, os_surface, os_space)
@@ -284,14 +294,12 @@ module FromHoneybee
284
294
 
285
295
  # assign setpoint if it exists
286
296
  if @hash[:properties][:energy][:setpoint]
287
- #thermostat object is created because heating and cooling schedule are required
288
- #fields.
297
+ # thermostat object is created because heating and cooling schedule are required
289
298
  setpoint_thermostat_space = SetpointThermostat.new(@hash[:properties][:energy][:setpoint])
290
299
  os_setpoint_thermostat_space = setpoint_thermostat_space.to_openstudio(openstudio_model)
291
300
  #set thermostat to thermal zone
292
301
  os_thermal_zone.setThermostatSetpointDualSetpoint(os_setpoint_thermostat_space)
293
- #humidistat object is created if humidifying or dehumidifying schedule is
294
- #specified.
302
+ # humidistat object is created if humidifying or dehumidifying schedule is specified
295
303
  if @hash[:properties][:energy][:setpoint][:humidifying_schedule] or @hash[:properties][:energy][:setpoint][:dehumidifying_schedule]
296
304
  setpoint_humidistat_space = SetpointHumidistat.new(@hash[:properties][:energy][:setpoint])
297
305
  os_setpoint_humidistat_space = setpoint_humidistat_space.to_openstudio(openstudio_model)
@@ -299,6 +307,20 @@ module FromHoneybee
299
307
  end
300
308
  end
301
309
 
310
+ # assign window ventilation objects if they exist
311
+ unless window_vent.empty?
312
+ window_vent.each do |sub_f_id, opening|
313
+ opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
314
+ unless opt_sub_f.empty?
315
+ sub_f = opt_sub_f.get
316
+ window_vent = VentilationOpening.new(opening)
317
+ os_window_vent = window_vent.to_openstudio(
318
+ openstudio_model, sub_f, @hash[:properties][:energy][:window_vent_control])
319
+ os_window_vent.addToThermalZone(os_thermal_zone)
320
+ end
321
+ end
322
+ end
323
+
302
324
  os_space
303
325
  end
304
326
 
@@ -95,12 +95,12 @@ module FromHoneybee
95
95
  # initialize class variable @@extension only once
96
96
  @@extension ||= Extension.new
97
97
  @@schema ||= @@extension.schema
98
+ @@standards ||= @@extension.standards
98
99
 
99
100
  @hash = hash
100
101
  @type = @hash[:type]
101
102
  raise 'Unknown model type' if @type.nil?
102
103
  raise "Incorrect model type '#{@type}'" unless @type == 'Model'
103
-
104
104
  end
105
105
 
106
106
  # check if the model is valid
@@ -157,34 +157,58 @@ module FromHoneybee
157
157
  building = @openstudio_model.getBuilding
158
158
  building.setStandardsBuildingType('MediumOffice')
159
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
+
160
166
  # create all of the non-geometric model elements
161
167
  if log_report
162
168
  puts 'Translating Materials'
163
169
  end
164
- create_materials
170
+ if @hash[:properties][:energy][:materials]
171
+ create_materials(@hash[:properties][:energy][:materials])
172
+ end
165
173
 
166
174
  if log_report
167
175
  puts 'Translating Constructions'
168
176
  end
169
- create_constructions
177
+ if @hash[:properties][:energy][:constructions]
178
+ create_constructions(@hash[:properties][:energy][:constructions])
179
+ end
170
180
 
171
181
  if log_report
172
182
  puts 'Translating ConstructionSets'
173
183
  end
174
- create_construction_set
175
- create_global_construction_set
184
+ if @hash[:properties][:energy][:construction_sets]
185
+ create_construction_sets(@hash[:properties][:energy][:construction_sets])
186
+ end
176
187
 
177
188
  if log_report
178
189
  puts 'Translating Schedules'
179
190
  end
180
- create_schedule_type_limits
181
- 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
182
197
 
183
198
  if log_report
184
199
  puts 'Translating ProgramTypes'
185
200
  end
186
- 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
187
210
 
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
@@ -211,103 +235,139 @@ module FromHoneybee
211
235
  create_orphaned_doors
212
236
  end
213
237
 
214
- def create_materials
215
- $gas_gap_hash = Hash.new # hash to track gas gaps in case they are split by shades
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
216
248
 
217
- @hash[:properties][:energy][:materials].each do |material|
218
- material_type = material[:type]
219
-
220
- case material_type
221
- when 'EnergyMaterial'
222
- material_object = EnergyMaterial.new(material)
223
- when 'EnergyMaterialNoMass'
224
- material_object = EnergyMaterialNoMass.new(material)
225
- when 'EnergyWindowMaterialGas'
226
- material_object = EnergyWindowMaterialGas.new(material)
227
- $gas_gap_hash[material[:identifier]] = material_object
228
- when 'EnergyWindowMaterialGasMixture'
229
- material_object = EnergyWindowMaterialGasMixture.new(material)
230
- $gas_gap_hash[material[:identifier]] = material_object
231
- when 'EnergyWindowMaterialGasCustom'
232
- material_object = EnergyWindowMaterialGasCustom.new(material)
233
- $gas_gap_hash[material[:identifier]] = material_object
234
- when 'EnergyWindowMaterialSimpleGlazSys'
235
- material_object = EnergyWindowMaterialSimpleGlazSys.new(material)
236
- when 'EnergyWindowMaterialBlind'
237
- material_object = EnergyWindowMaterialBlind.new(material)
238
- when 'EnergyWindowMaterialGlazing'
239
- material_object = EnergyWindowMaterialGlazing.new(material)
240
- when 'EnergyWindowMaterialShade'
241
- material_object = EnergyWindowMaterialShade.new(material)
242
- else
243
- raise "Unknown material type #{material_type}"
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)
244
278
  end
245
- material_object.to_openstudio(@openstudio_model)
246
279
  end
247
280
  end
248
281
 
249
- def create_constructions
250
- $air_boundary_hash = Hash.new # hash to track any air boundary constructions
251
- $window_shade_hash = Hash.new # hash to track any window constructions with shade
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
252
292
 
253
- @hash[:properties][:energy][:constructions].each do |construction|
254
- identifier = construction[:identifier]
255
- construction_type = construction[:type]
256
-
257
- case construction_type
258
- when 'OpaqueConstructionAbridged'
259
- construction_object = OpaqueConstructionAbridged.new(construction)
260
- when 'WindowConstructionAbridged'
261
- construction_object = WindowConstructionAbridged.new(construction)
262
- when 'WindowConstructionShadeAbridged'
263
- construction_object = WindowConstructionShadeAbridged.new(construction)
264
- $window_shade_hash[construction[:identifier]] = construction_object
265
- when 'ShadeConstruction'
266
- construction_object = ShadeConstruction.new(construction)
267
- when 'AirBoundaryConstructionAbridged'
268
- construction_object = AirBoundaryConstructionAbridged.new(construction)
269
- $air_boundary_hash[construction[:identifier]] = construction
270
- else
271
- 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)
272
313
  end
273
- construction_object.to_openstudio(@openstudio_model)
274
314
  end
275
315
  end
276
316
 
277
- def create_construction_set
278
- if @hash[:properties][:energy][:construction_sets]
279
- @hash[:properties][:energy][:construction_sets].each do |construction_set|
280
- construction_set_object = ConstructionSetAbridged.new(construction_set)
281
- 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
282
327
  end
283
- end
284
- end
285
328
 
286
- def create_global_construction_set
287
- if @hash[:properties][:energy][:global_construction_set]
288
- construction_id = @hash[:properties][:energy][:global_construction_set]
289
- construction = @openstudio_model.getDefaultConstructionSetByName(construction_id)
290
- unless construction.empty?
291
- 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)
292
333
  end
293
- @openstudio_model.getBuilding.setDefaultConstructionSet(openstudio_construction)
294
334
  end
295
335
  end
296
336
 
297
- def create_schedule_type_limits
298
- if @hash[:properties][:energy][:schedule_type_limits]
299
- @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
300
351
  schedule_type_limit_object = ScheduleTypeLimit.new(schedule_type_limit)
301
352
  schedule_type_limit_object.to_openstudio(@openstudio_model)
302
353
  end
303
354
  end
304
355
  end
305
356
 
306
- def create_schedules
307
- if @hash[:properties][:energy][:schedules]
308
- @hash[:properties][:energy][:schedules].each do |schedule|
309
- 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
310
367
 
368
+ # add the schedule object to the Model
369
+ if add_obj
370
+ schedule_type = schedule[:type]
311
371
  case schedule_type
312
372
  when 'ScheduleRulesetAbridged'
313
373
  schedule_object = ScheduleRulesetAbridged.new(schedule)
@@ -317,21 +377,56 @@ module FromHoneybee
317
377
  raise("Unknown schedule type #{schedule_type}.")
318
378
  end
319
379
  schedule_object.to_openstudio(@openstudio_model)
320
-
321
380
  end
322
381
  end
323
382
  end
324
383
 
325
- def create_program_types
326
- if @hash[:properties][:energy][:program_types]
327
- $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
328
- @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
329
397
  space_type_object = ProgramTypeAbridged.new(space_type)
330
398
  space_type_object.to_openstudio(@openstudio_model)
331
399
  end
332
400
  end
333
401
  end
334
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
+
335
430
  def create_rooms
336
431
  if @hash[:rooms]
337
432
  $air_mxing_array = [] # list to track any air mixing between Rooms