honeybee-openstudio 2.2.0 → 2.3.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.
@@ -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")
@@ -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
@@ -39,7 +39,7 @@ module FromHoneybee
39
39
  @@schema = nil
40
40
 
41
41
  def schema_file
42
- File.join(@lib_dir, 'from_honeybee', '_openapi', 'simulation-parameter.json')
42
+ File.join(@lib_dir, 'from_honeybee', '_defaults', 'simulation-parameter.json')
43
43
  end
44
44
 
45
45
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: honeybee-openstudio
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanushree Charan
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2020-06-19 00:00:00.000000000 Z
14
+ date: 2020-06-30 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -165,8 +165,9 @@ files:
165
165
  - lib/files/honeybee_workflow.osw
166
166
  - lib/files/urbanopt_Gemfile
167
167
  - lib/from_honeybee.rb
168
- - lib/from_honeybee/_openapi/model.json
169
- - lib/from_honeybee/_openapi/simulation-parameter.json
168
+ - lib/from_honeybee/_defaults/energy_default.json
169
+ - lib/from_honeybee/_defaults/model.json
170
+ - lib/from_honeybee/_defaults/simulation-parameter.json
170
171
  - lib/from_honeybee/construction/air.rb
171
172
  - lib/from_honeybee/construction/opaque.rb
172
173
  - lib/from_honeybee/construction/shade.rb