honeybee-openstudio 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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