honeybee-openstudio 2.2.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -100,7 +100,7 @@ module FromHoneybee
100
100
  end
101
101
 
102
102
  # assign limits to the system's heating capacity
103
- if @hash[:heating_limit] == {'type': 'NoLimit'}
103
+ if @hash[:heating_limit] == {:type => 'NoLimit'}
104
104
  os_ideal_air.setHeatingLimit('NoLimit')
105
105
  else
106
106
  os_ideal_air.setHeatingLimit('LimitCapacity')
@@ -112,7 +112,7 @@ module FromHoneybee
112
112
  end
113
113
 
114
114
  # assign limits to the system's cooling capacity
115
- if @hash[:cooling_limit] == {'type': 'NoLimit'}
115
+ if @hash[:cooling_limit] == {:type => 'NoLimit'}
116
116
  os_ideal_air.setCoolingLimit('NoLimit')
117
117
  else
118
118
  os_ideal_air.setCoolingLimit('LimitFlowRateAndCapacity')
@@ -0,0 +1,198 @@
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 'openstudio-standards'
33
+ require_relative 'Model.hvac'
34
+
35
+ require 'from_honeybee/extension'
36
+ require 'from_honeybee/model_object'
37
+
38
+ module FromHoneybee
39
+ class TemplateHVAC < ModelObject
40
+ attr_reader :errors, :warnings
41
+
42
+ @@all_air_types = ['VAV', 'PVAV', 'PSZ', 'PTAC', 'ForcedAirFurnace']
43
+ @@doas_types = ['FCUwithDOAS', 'WSHPwithDOAS', 'VRFwithDOAS']
44
+ @@heat_cool_types = ['FCU', 'WSHP', 'VRF', 'Baseboard', 'EvaporativeCooler',
45
+ 'Residential', 'WindowAC', 'GasUnitHeater']
46
+ @@types = @@all_air_types + @@doas_types + @@heat_cool_types
47
+
48
+ def initialize(hash = {})
49
+ super(hash)
50
+ end
51
+
52
+ def self.types
53
+ # array of all supported template HVAC systems
54
+ @@types
55
+ end
56
+
57
+ def self.all_air_types
58
+ # array of the All Air HVAC types
59
+ @@all_air_types
60
+ end
61
+
62
+ def self.doas_types
63
+ # array of the DOAS HVAC types
64
+ @@doas_types
65
+ end
66
+
67
+ def self.heat_cool_types
68
+ # array of the system types providing heating and cooling only
69
+ @@heat_cool_types
70
+ end
71
+
72
+ def defaults(system_type)
73
+ @@schema[:components][:schemas][system_type.to_sym][:properties]
74
+ end
75
+
76
+ def to_openstudio(openstudio_model, room_ids)
77
+ # get the defaults for the specific system type
78
+ hvac_defaults = defaults(@hash[:type])
79
+
80
+ # make the standard applier
81
+ if @hash[:vintage]
82
+ standard = Standard.build(@hash[:vintage])
83
+ else
84
+ standard = Standard.build(hvac_defaults[:vintage][:default])
85
+ end
86
+
87
+ # get the default equipment type
88
+ if @hash[:equipment_type]
89
+ equipment_type = @hash[:equipment_type]
90
+ else
91
+ equipment_type = hvac_defaults[:equipment_type][:default]
92
+ end
93
+
94
+ # get all of the thermal zones from the Model using the room identifiers
95
+ zones = []
96
+ room_ids.each do |room_id|
97
+ zone_get = openstudio_model.getThermalZoneByName(room_id)
98
+ unless zone_get.empty?
99
+ os_thermal_zone = zone_get.get
100
+ zones << os_thermal_zone
101
+ end
102
+ end
103
+
104
+ # create the HVAC system and assign the identifier to the air loop name if it exists
105
+ os_hvac = openstudio_model.add_cbecs_hvac_system(standard, equipment_type, zones)
106
+ os_air_loop = nil
107
+ air_loops = openstudio_model.getAirLoopHVACs
108
+ unless air_loops.length == 0
109
+ os_air_loop = air_loops[-1]
110
+ loop_name = os_air_loop.name
111
+ unless loop_name.empty?
112
+ os_air_loop.setName(@hash[:identifier] + ' - ' + loop_name.get)
113
+ end
114
+ end
115
+
116
+ # TODO: consider adding the ability to decentralize the plant by changing loop names
117
+ #os_hvac.each do |hvac_loop|
118
+ # loop_name = hvac_loop.name
119
+ # unless loop_name.empty?
120
+ # hvac_loop.setName(@hash[:identifier] + ' - ' + loop_name.get)
121
+ # end
122
+ #end
123
+
124
+ # assign the economizer type if there's an air loop and the economizer is specified
125
+ if @hash[:economizer_type] && @hash[:economizer_type] != 'Inferred' && os_air_loop
126
+ oasys = os_air_loop.airLoopHVACOutdoorAirSystem
127
+ unless oasys.empty?
128
+ os_oasys = oasys.get
129
+ oactrl = os_oasys.getControllerOutdoorAir
130
+ oactrl.setEconomizerControlType(@hash[:economizer_type])
131
+ end
132
+ end
133
+
134
+ # set the sensible heat recovery if there's an air loop and the heat recovery is specified
135
+ if @hash[:sensible_heat_recovery] && @hash[:sensible_heat_recovery] != {:type => 'Autosize'} && os_air_loop
136
+ erv = get_existing_erv(os_air_loop)
137
+ unless erv
138
+ erv = create_erv(openstudio_model, os_air_loop)
139
+ end
140
+ eff_at_max = @hash[:sensible_heat_recovery] * (0.76 / 0.81) # taken from OpenStudio defaults
141
+ erv.setSensibleEffectivenessat100CoolingAirFlow(eff_at_max)
142
+ erv.setSensibleEffectivenessat100HeatingAirFlow(eff_at_max)
143
+ erv.setSensibleEffectivenessat75CoolingAirFlow(@hash[:sensible_heat_recovery])
144
+ erv.setSensibleEffectivenessat75HeatingAirFlow(@hash[:sensible_heat_recovery])
145
+ end
146
+
147
+ # set the latent heat recovery if there's an air loop and the heat recovery is specified
148
+ if @hash[:latent_heat_recovery] && @hash[:latent_heat_recovery] != {:type => 'Autosize'} && os_air_loop
149
+ erv = get_existing_erv(os_air_loop)
150
+ unless erv
151
+ erv = create_erv(openstudio_model, os_air_loop)
152
+ end
153
+ eff_at_max = @hash[:latent_heat_recovery] * (0.68 / 0.73) # taken from OpenStudio defaults
154
+ erv.setLatentEffectivenessat100CoolingAirFlow(eff_at_max)
155
+ erv.setLatentEffectivenessat100HeatingAirFlow(eff_at_max)
156
+ erv.setLatentEffectivenessat75CoolingAirFlow(@hash[:latent_heat_recovery])
157
+ erv.setLatentEffectivenessat75HeatingAirFlow(@hash[:latent_heat_recovery])
158
+ end
159
+
160
+ os_hvac
161
+ end
162
+
163
+ def get_existing_erv(os_air_loop)
164
+ # get an existing heat ecovery unit from an air loop; will be nil if there is none
165
+ os_air_loop.oaComponents.each do |supply_component|
166
+ if not supply_component.to_HeatExchangerAirToAirSensibleAndLatent.empty?
167
+ erv = supply_component.to_HeatExchangerAirToAirSensibleAndLatent.get
168
+ return erv
169
+ end
170
+ end
171
+ nil
172
+ end
173
+
174
+ def create_erv(model, os_air_loop)
175
+ # create a heat recovery unit with default zero efficiencies
176
+ heat_ex = OpenStudio::Model::HeatExchangerAirToAirSensibleAndLatent.new(model)
177
+ heat_ex.setEconomizerLockout(false)
178
+ heat_ex.setName(@hash[:identifier] + '_Heat Recovery Unit')
179
+ heat_ex.setSensibleEffectivenessat100CoolingAirFlow(0)
180
+ heat_ex.setSensibleEffectivenessat100HeatingAirFlow(0)
181
+ heat_ex.setSensibleEffectivenessat75CoolingAirFlow(0)
182
+ heat_ex.setSensibleEffectivenessat75HeatingAirFlow(0)
183
+ heat_ex.setLatentEffectivenessat100CoolingAirFlow(0)
184
+ heat_ex.setLatentEffectivenessat100HeatingAirFlow(0)
185
+ heat_ex.setLatentEffectivenessat75CoolingAirFlow(0)
186
+ heat_ex.setLatentEffectivenessat75HeatingAirFlow(0)
187
+
188
+ # add the heat exchanger to the air loop
189
+ outdoor_node = os_air_loop.reliefAirNode
190
+ unless outdoor_node.empty?
191
+ os_outdoor_node = outdoor_node.get
192
+ heat_ex.addToNode(os_outdoor_node)
193
+ end
194
+ heat_ex
195
+ end
196
+
197
+ end #TemplateHVAC
198
+ end #FromHoneybee
@@ -46,6 +46,7 @@ require 'from_honeybee/geometry/room'
46
46
 
47
47
  # import the HVAC objects
48
48
  require 'from_honeybee/hvac/ideal_air'
49
+ require 'from_honeybee/hvac/template'
49
50
 
50
51
  # import the construction objects
51
52
  require 'from_honeybee/construction/opaque'
@@ -95,12 +96,12 @@ module FromHoneybee
95
96
  # initialize class variable @@extension only once
96
97
  @@extension ||= Extension.new
97
98
  @@schema ||= @@extension.schema
99
+ @@standards ||= @@extension.standards
98
100
 
99
101
  @hash = hash
100
102
  @type = @hash[:type]
101
103
  raise 'Unknown model type' if @type.nil?
102
104
  raise "Incorrect model type '#{@type}'" unless @type == 'Model'
103
-
104
105
  end
105
106
 
106
107
  # check if the model is valid
@@ -157,34 +158,58 @@ module FromHoneybee
157
158
  building = @openstudio_model.getBuilding
158
159
  building.setStandardsBuildingType('MediumOffice')
159
160
 
161
+ # initialize global hashes for various model properties
162
+ $gas_gap_hash = Hash.new # hash to track gas gaps in case they are split by shades
163
+ $air_boundary_hash = Hash.new # hash to track any air boundary constructions
164
+ $window_shade_hash = Hash.new # hash to track any window constructions with shade
165
+ $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
166
+
160
167
  # create all of the non-geometric model elements
161
168
  if log_report
162
169
  puts 'Translating Materials'
163
170
  end
164
- create_materials
171
+ if @hash[:properties][:energy][:materials]
172
+ create_materials(@hash[:properties][:energy][:materials])
173
+ end
165
174
 
166
175
  if log_report
167
176
  puts 'Translating Constructions'
168
177
  end
169
- create_constructions
178
+ if @hash[:properties][:energy][:constructions]
179
+ create_constructions(@hash[:properties][:energy][:constructions])
180
+ end
170
181
 
171
182
  if log_report
172
183
  puts 'Translating ConstructionSets'
173
184
  end
174
- create_construction_set
175
- create_global_construction_set
185
+ if @hash[:properties][:energy][:construction_sets]
186
+ create_construction_sets(@hash[:properties][:energy][:construction_sets])
187
+ end
176
188
 
177
189
  if log_report
178
190
  puts 'Translating Schedules'
179
191
  end
180
- create_schedule_type_limits
181
- create_schedules
192
+ if @hash[:properties][:energy][:schedule_type_limits]
193
+ create_schedule_type_limits(@hash[:properties][:energy][:schedule_type_limits])
194
+ end
195
+ if @hash[:properties][:energy][:schedules]
196
+ create_schedules(@hash[:properties][:energy][:schedules])
197
+ end
182
198
 
183
199
  if log_report
184
200
  puts 'Translating ProgramTypes'
185
201
  end
186
- create_program_types
202
+ if @hash[:properties][:energy][:program_types]
203
+ create_program_types(@hash[:properties][:energy][:program_types])
204
+ end
205
+
206
+ # create the default construction set to catch any cases of unassigned constructions
207
+ if log_report
208
+ puts 'Translating Default ConstructionSet'
209
+ end
210
+ create_default_construction_set
187
211
 
212
+ # create the geometry and add any extra properties to it
188
213
  if log_report
189
214
  puts 'Translating Room Geometry'
190
215
  end
@@ -211,103 +236,139 @@ module FromHoneybee
211
236
  create_orphaned_doors
212
237
  end
213
238
 
214
- def create_materials
215
- $gas_gap_hash = Hash.new # hash to track gas gaps in case they are split by shades
239
+ def create_materials(material_dicts, check_existing=false)
240
+ material_dicts.each do |material|
241
+ # check if there's already a material in the model with the identifier
242
+ add_obj = true
243
+ if check_existing
244
+ object = @openstudio_model.getMaterialByName(material[:identifier])
245
+ if object.is_initialized
246
+ add_obj = false
247
+ end
248
+ end
216
249
 
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}"
250
+ # add the material object to the Model
251
+ if add_obj
252
+ material_type = material[:type]
253
+ case material_type
254
+ when 'EnergyMaterial'
255
+ material_object = EnergyMaterial.new(material)
256
+ when 'EnergyMaterialNoMass'
257
+ material_object = EnergyMaterialNoMass.new(material)
258
+ when 'EnergyWindowMaterialGas'
259
+ material_object = EnergyWindowMaterialGas.new(material)
260
+ $gas_gap_hash[material[:identifier]] = material_object
261
+ when 'EnergyWindowMaterialGasMixture'
262
+ material_object = EnergyWindowMaterialGasMixture.new(material)
263
+ $gas_gap_hash[material[:identifier]] = material_object
264
+ when 'EnergyWindowMaterialGasCustom'
265
+ material_object = EnergyWindowMaterialGasCustom.new(material)
266
+ $gas_gap_hash[material[:identifier]] = material_object
267
+ when 'EnergyWindowMaterialSimpleGlazSys'
268
+ material_object = EnergyWindowMaterialSimpleGlazSys.new(material)
269
+ when 'EnergyWindowMaterialBlind'
270
+ material_object = EnergyWindowMaterialBlind.new(material)
271
+ when 'EnergyWindowMaterialGlazing'
272
+ material_object = EnergyWindowMaterialGlazing.new(material)
273
+ when 'EnergyWindowMaterialShade'
274
+ material_object = EnergyWindowMaterialShade.new(material)
275
+ else
276
+ raise "Unknown material type #{material_type}"
277
+ end
278
+ material_object.to_openstudio(@openstudio_model)
244
279
  end
245
- material_object.to_openstudio(@openstudio_model)
246
280
  end
247
281
  end
248
282
 
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
283
+ def create_constructions(construction_dicts, check_existing=false)
284
+ construction_dicts.each do |construction|
285
+ # check if there's already a construction in the model with the identifier
286
+ add_obj = true
287
+ if check_existing
288
+ object = @openstudio_model.getConstructionByName(construction[:identifier])
289
+ if object.is_initialized
290
+ add_obj = false
291
+ end
292
+ end
252
293
 
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}."
294
+ # add the construction object to the Model
295
+ if add_obj
296
+ construction_type = construction[:type]
297
+ case construction_type
298
+ when 'OpaqueConstructionAbridged'
299
+ construction_object = OpaqueConstructionAbridged.new(construction)
300
+ when 'WindowConstructionAbridged'
301
+ construction_object = WindowConstructionAbridged.new(construction)
302
+ when 'WindowConstructionShadeAbridged'
303
+ construction_object = WindowConstructionShadeAbridged.new(construction)
304
+ $window_shade_hash[construction[:identifier]] = construction_object
305
+ when 'ShadeConstruction'
306
+ construction_object = ShadeConstruction.new(construction)
307
+ when 'AirBoundaryConstructionAbridged'
308
+ construction_object = AirBoundaryConstructionAbridged.new(construction)
309
+ $air_boundary_hash[construction[:identifier]] = construction
310
+ else
311
+ raise "Unknown construction type #{construction_type}."
312
+ end
313
+ construction_object.to_openstudio(@openstudio_model)
272
314
  end
273
- construction_object.to_openstudio(@openstudio_model)
274
315
  end
275
316
  end
276
317
 
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)
318
+ def create_construction_sets(construction_set_dicts, check_existing=false)
319
+ construction_set_dicts.each do |construction_set|
320
+ # check if there's already a construction set in the model with the identifier
321
+ add_obj = true
322
+ if check_existing
323
+ object = @openstudio_model.getDefaultConstructionSetByName(
324
+ construction_set[:identifier])
325
+ if object.is_initialized
326
+ add_obj = false
327
+ end
282
328
  end
283
- end
284
- end
285
329
 
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
330
+ # add the construction set object to the Model
331
+ if add_obj
332
+ construction_set_object = ConstructionSetAbridged.new(construction_set)
333
+ construction_set_object.to_openstudio(@openstudio_model)
292
334
  end
293
- @openstudio_model.getBuilding.setDefaultConstructionSet(openstudio_construction)
294
335
  end
295
336
  end
296
337
 
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|
338
+ def create_schedule_type_limits(stl_dicts, check_existing=false)
339
+ stl_dicts.each do |schedule_type_limit|
340
+ # check if there's already a schedule type limit in the model with the identifier
341
+ add_obj = true
342
+ if check_existing
343
+ object = @openstudio_model.getScheduleTypeLimitsByName(
344
+ schedule_type_limit[:identifier])
345
+ if object.is_initialized
346
+ add_obj = false
347
+ end
348
+ end
349
+
350
+ # add the schedule type limit object to the Model
351
+ if add_obj
300
352
  schedule_type_limit_object = ScheduleTypeLimit.new(schedule_type_limit)
301
353
  schedule_type_limit_object.to_openstudio(@openstudio_model)
302
354
  end
303
355
  end
304
356
  end
305
357
 
306
- def create_schedules
307
- if @hash[:properties][:energy][:schedules]
308
- @hash[:properties][:energy][:schedules].each do |schedule|
309
- schedule_type = schedule[:type]
358
+ def create_schedules(schedule_dicts, check_existing=false)
359
+ schedule_dicts.each do |schedule|
360
+ # check if there's already a schedule in the model with the identifier
361
+ add_obj = true
362
+ if check_existing
363
+ object = @openstudio_model.getScheduleByName(schedule[:identifier])
364
+ if object.is_initialized
365
+ add_obj = false
366
+ end
367
+ end
310
368
 
369
+ # add the schedule object to the Model
370
+ if add_obj
371
+ schedule_type = schedule[:type]
311
372
  case schedule_type
312
373
  when 'ScheduleRulesetAbridged'
313
374
  schedule_object = ScheduleRulesetAbridged.new(schedule)
@@ -317,21 +378,56 @@ module FromHoneybee
317
378
  raise("Unknown schedule type #{schedule_type}.")
318
379
  end
319
380
  schedule_object.to_openstudio(@openstudio_model)
320
-
321
381
  end
322
382
  end
323
383
  end
324
384
 
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|
385
+ def create_program_types(program_dicts, check_existing=false)
386
+ program_dicts.each do |space_type|
387
+ # check if there's already a space type in the model with the identifier
388
+ add_obj = true
389
+ if check_existing
390
+ object = @openstudio_model.getSpaceTypeByName(space_type[:identifier])
391
+ if object.is_initialized
392
+ add_obj = false
393
+ end
394
+ end
395
+
396
+ # add the space type object to the Model
397
+ if add_obj
329
398
  space_type_object = ProgramTypeAbridged.new(space_type)
330
399
  space_type_object.to_openstudio(@openstudio_model)
331
400
  end
332
401
  end
333
402
  end
334
403
 
404
+ def create_default_construction_set
405
+ # create the materials, constructions and construction set
406
+ create_materials(@@standards[:materials], true)
407
+ create_constructions(@@standards[:constructions], true)
408
+ create_construction_sets(@@standards[:construction_sets], true)
409
+
410
+ # write the fractional schedule type and always on schedule if they are not there
411
+ @@standards[:schedule_type_limits].each do |sch_type_limit|
412
+ if sch_type_limit[:identifier] == 'Fractional'
413
+ create_schedule_type_limits([sch_type_limit], true)
414
+ end
415
+ end
416
+ @@standards[:schedules].each do |schedule|
417
+ if schedule[:identifier] == 'Always On'
418
+ create_schedules([schedule], true)
419
+ end
420
+ end
421
+
422
+ # set the default construction set to the building level of the Model
423
+ construction_id = 'Default Generic Construction Set'
424
+ construction = @openstudio_model.getDefaultConstructionSetByName(construction_id)
425
+ unless construction.empty?
426
+ os_constructionset = construction.get
427
+ @openstudio_model.getBuilding.setDefaultConstructionSet(os_constructionset)
428
+ end
429
+ end
430
+
335
431
  def create_rooms
336
432
  if @hash[:rooms]
337
433
  $air_mxing_array = [] # list to track any air mixing between Rooms
@@ -408,7 +504,7 @@ module FromHoneybee
408
504
  hvac_hashes[hvac[:identifier]] = hvac
409
505
  hvac_hashes[hvac[:identifier]]['rooms'] = []
410
506
  end
411
- # loop through the rooms and trach which are assigned to each HVAC
507
+ # loop through the rooms and track which are assigned to each HVAC
412
508
  if @hash[:rooms]
413
509
  @hash[:rooms].each do |room|
414
510
  if room[:properties][:energy][:hvac]
@@ -419,8 +515,7 @@ module FromHoneybee
419
515
 
420
516
  hvac_hashes.each_value do |hvac|
421
517
  system_type = hvac[:type]
422
- case system_type
423
- when 'IdealAirSystemAbridged'
518
+ if system_type == 'IdealAirSystemAbridged'
424
519
  ideal_air_system = IdealAirSystemAbridged.new(hvac)
425
520
  os_ideal_air_system = ideal_air_system.to_openstudio(@openstudio_model)
426
521
  hvac['rooms'].each do |room_id|
@@ -430,6 +525,9 @@ module FromHoneybee
430
525
  os_ideal_air_system.addToThermalZone(os_thermal_zone)
431
526
  end
432
527
  end
528
+ elsif TemplateHVAC.types.include?(system_type)
529
+ template_system = TemplateHVAC.new(hvac)
530
+ os_template_system = template_system.to_openstudio(@openstudio_model, hvac['rooms'])
433
531
  end
434
532
  end
435
533
  end