honeybee-openstudio 2.31.8 → 2.31.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cebfc1cf27c7e5d2e9bbfed6ece32096ec1cb0eb2a442783b9a7caeeddd136bc
4
- data.tar.gz: 8960a24e1240a7d5e5db87a09455343afde150294bdb5f3fccc7093a67c2d2cc
3
+ metadata.gz: f9cfa9e82e9efaedde24e6ccfe30c4d7fe6cbd4259a81d36de9b8a9936b8259b
4
+ data.tar.gz: 6c47a045cf0684fdc33521ca96b6bd1fe3f27a52658fe774a6f76165ab3c87b0
5
5
  SHA512:
6
- metadata.gz: 8ede21274b85d427693c6ca495ce6e100206dfd7af3fba82044f81309e5af160a61aae97ee476afa6bf4bfa3166ccde32ead3dbcbe7a448b9772c17c4b098311
7
- data.tar.gz: f408bfd525685fc1c1e61a7cdd0aa4d0646c6e34e3a68e565f2876b217d031e14cd47523ea5d58de595679ca7ed272631709706c459f3ce51496597fdff3f64e
6
+ metadata.gz: ceefaa71ad6fe18240c21b2738ddf5741fc9620dcf63088c67511a0fedb132f1ea063879527183624f88a196826f7a58bef62ac9211e605f815264ae3add17c4
7
+ data.tar.gz: 4b6e648afaa694daa0e2246f4f5f6cf6c5dadb714e4b4fa7681919447fa24a37cb9bba9e6edbbb77a216e04005a0d23b5da7c8f38df07c60ad2ed2543767ad7d
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'honeybee-openstudio'
7
- spec.version = '2.31.8'
7
+ spec.version = '2.31.9'
8
8
  spec.authors = ['Tanushree Charan', 'Dan Macumber', 'Chris Mackey', 'Mostapha Sadeghipour Roudsari']
9
9
  spec.email = ['tanushree.charan@nrel.gov', 'chris@ladybug.tools']
10
10
 
@@ -201,6 +201,17 @@ module Honeybee
201
201
  thermal_zone = space.thermalZone
202
202
  unless thermal_zone.empty?
203
203
  thermal_zone = space.thermalZone.get
204
+ # Create ideal_air_system if present
205
+ unless thermal_zone.equipment.nil?
206
+ thermal_zone.equipment.each do |equipment|
207
+ if equipment.to_ZoneHVACIdealLoadsAirSystem.is_initialized
208
+ ideal_air_hash = Honeybee::IdealAirSystemAbridged.from_hvac(
209
+ equipment.to_ZoneHVACIdealLoadsAirSystem.get)
210
+ $hvacs << ideal_air_hash
211
+ hash[:hvac] = ideal_air_hash[:identifier]
212
+ end
213
+ end
214
+ end
204
215
  unless thermal_zone.thermostatSetpointDualSetpoint.empty?
205
216
  hash[:setpoint] = {}
206
217
  hash[:setpoint][:type] = 'SetpointAbridged'
@@ -0,0 +1,75 @@
1
+ # *******************************************************************************
2
+ # 4ju0 d/zf 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 'honeybee/hvac/ideal_air'
33
+ require 'to_openstudio/model_object'
34
+
35
+ module Honeybee
36
+ class IdealAirSystemAbridged
37
+
38
+ def self.from_hvac(hvac)
39
+ # create an empty hash
40
+ hash = {}
41
+ hash[:type] = 'IdealAirSystemAbridged'
42
+ hash[:identifier] = clean_name(hvac.nameString)
43
+ unless hvac.displayName.empty?
44
+ hash[:display_name] = (hvac.displayName.get).force_encoding("UTF-8")
45
+ end
46
+ hash[:economizer_type] = hvac.outdoorAirEconomizerType
47
+ if hvac.demandControlledVentilationType.downcase == 'none'
48
+ hash[:demand_controlled_ventilation] = false
49
+ else
50
+ hash[:demand_controlled_ventilation] = true
51
+ end
52
+ hash[:sensible_heat_recovery] = hvac.sensibleHeatRecoveryEffectiveness
53
+ hash[:latent_heat_recovery] = hvac.latentHeatRecoveryEffectiveness
54
+ hash[:heating_air_temperature] = hvac.maximumHeatingSupplyAirTemperature
55
+ hash[:cooling_air_temperature] = hvac.minimumCoolingSupplyAirTemperature
56
+ if hvac.heatingLimit == 'NoLimit'
57
+ hash[:heating_limit] = hvac.heatingLimit
58
+ end
59
+ if hvac.coolingLimit == 'NoLimit'
60
+ hash[:cooling_limit] = hvac.coolingLimit
61
+ end
62
+ unless hvac.heatingAvailabilitySchedule.empty?
63
+ schedule = hvac.heatingAvailabilitySchedule.get
64
+ hash[:heating_availability] = schedule.nameString
65
+ end
66
+ unless hvac.coolingAvailabilitySchedule.empty?
67
+ schedule = hvac.coolingAvailabilitySchedule.get
68
+ hash[:coolingAvailabilitySchedule]
69
+ end
70
+
71
+ hash
72
+ end
73
+
74
+ end #IdealAirSystemAbridged
75
+ end #Honeybee
@@ -61,4 +61,4 @@ module Honeybee
61
61
 
62
62
 
63
63
  end #ElectricEquipmentAbridged
64
- end #Honeybee
64
+ end #Honeybee
@@ -51,6 +51,7 @@ module Honeybee
51
51
  $opaque_constructions = {}
52
52
  $window_constructions = {}
53
53
  $shade_constructions = {}
54
+ $hvacs = []
54
55
 
55
56
  hash[:properties] = properties_from_model(openstudio_model)
56
57
 
@@ -126,6 +127,7 @@ module Honeybee
126
127
  hash[:schedule_type_limits] = schedtypelimits_from_model(openstudio_model)
127
128
  hash[:schedules] = schedules_from_model(openstudio_model)
128
129
  hash[:program_types] = programtype_from_model(openstudio_model)
130
+ hash[:hvacs] = $hvacs
129
131
 
130
132
  hash
131
133
  end
@@ -81,6 +81,15 @@ module Honeybee
81
81
  hash[:day_schedules] << ScheduleRulesetAbridged.from_day_schedule(schedule_day)
82
82
  end
83
83
 
84
+ # remove the bogus default day schedule that OpenStudio adds upon import from IDF
85
+ if hash[:default_day_schedule].start_with?('Schedule Day ')
86
+ if hash[:day_schedules][0][:values] == [0] && hash[:schedule_rules].length() > 0
87
+ hash[:default_day_schedule] = hash[:schedule_rules][0][:schedule_day]
88
+ hash[:schedule_rules].pop(0)
89
+ hash[:day_schedules].pop(0)
90
+ end
91
+ end
92
+
84
93
  # assing any schedule type limits if they exist
85
94
  unless schedule_ruleset.scheduleTypeLimits.empty?
86
95
  typ_lim = schedule_ruleset.scheduleTypeLimits.get
@@ -44,6 +44,9 @@ require 'from_openstudio/geometry/face'
44
44
  require 'from_openstudio/geometry/room'
45
45
  require 'from_openstudio/geometry/shade'
46
46
 
47
+ # extend the hvac objects
48
+ require 'from_openstudio/hvac/ideal_air'
49
+
47
50
  # extend the construction objects
48
51
  require 'from_openstudio/construction/opaque'
49
52
  require 'from_openstudio/construction/window'
@@ -118,7 +118,7 @@ module Honeybee
118
118
  end
119
119
 
120
120
  # assign the construction if it exists
121
- if @hash[:properties][:energy][:construction]
121
+ if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
122
122
  construction_identifier = @hash[:properties][:energy][:construction]
123
123
  construction = openstudio_model.getConstructionByName(construction_identifier)
124
124
  if !construction.empty?
@@ -182,7 +182,7 @@ module Honeybee
182
182
 
183
183
  # get the approriate construction id
184
184
  construction_id = nil
185
- if @hash[:properties][:energy][:construction]
185
+ if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
186
186
  construction_id = @hash[:properties][:energy][:construction]
187
187
  else
188
188
  construction_id = 'Generic Double Pane'
@@ -118,7 +118,7 @@ module Honeybee
118
118
  end
119
119
 
120
120
  # assign the construction if it exists
121
- if @hash[:properties][:energy][:construction]
121
+ if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
122
122
  construction_identifier = @hash[:properties][:energy][:construction]
123
123
  construction = openstudio_model.getConstructionByName(construction_identifier)
124
124
  if !construction.empty?
@@ -176,7 +176,7 @@ module Honeybee
176
176
 
177
177
  # get the approriate construction id
178
178
  construction_id = nil
179
- if @hash[:properties][:energy][:construction]
179
+ if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
180
180
  construction_id = @hash[:properties][:energy][:construction]
181
181
  elsif @hash[:is_glass] == true
182
182
  construction_id = 'Generic Double Pane'
@@ -64,39 +64,41 @@ module Honeybee
64
64
  end
65
65
  os_surface.setSurfaceType(@hash[:face_type])
66
66
 
67
- # assign the construction if it is present
68
- if @hash[:properties][:energy][:construction]
69
- construction_identifier = @hash[:properties][:energy][:construction]
70
- construction = openstudio_model.getConstructionByName(construction_identifier)
71
- unless construction.empty?
72
- os_construction = construction.get
73
- os_surface.setConstruction(os_construction)
67
+ if @hash[:properties].key?(:energy)
68
+ # assign the construction if it is present
69
+ if @hash[:properties][:energy][:construction]
70
+ construction_identifier = @hash[:properties][:energy][:construction]
71
+ construction = openstudio_model.getConstructionByName(construction_identifier)
72
+ unless construction.empty?
73
+ os_construction = construction.get
74
+ os_surface.setConstruction(os_construction)
75
+ end
74
76
  end
75
- end
76
-
77
- # assign the AFN crack if it's specified and we are not using simple infiltration
78
- if !$use_simple_vent && @hash[:properties][:energy][:vent_crack]
79
- unless $interior_afn_srf_hash[@hash[:identifier]] # interior crack that's been accounted for
80
- vent_crack = @hash[:properties][:energy][:vent_crack]
81
- # create the crack object for using default values
82
- flow_exponent = crack_defaults[:flow_exponent][:default].to_f
83
- os_crack = OpenStudio::Model::AirflowNetworkCrack.new(
84
- openstudio_model, vent_crack[:flow_coefficient], flow_exponent,
85
- $afn_reference_crack)
86
77
 
87
- # assign the flow exponent if it's specified
88
- if vent_crack[:flow_exponent]
89
- os_crack.setAirMassFlowExponent(vent_crack[:flow_exponent])
90
- end
78
+ # assign the AFN crack if it's specified and we are not using simple infiltration
79
+ if !$use_simple_vent && @hash[:properties][:energy][:vent_crack]
80
+ unless $interior_afn_srf_hash[@hash[:identifier]] # interior crack that's been accounted for
81
+ vent_crack = @hash[:properties][:energy][:vent_crack]
82
+ # create the crack object for using default values
83
+ flow_exponent = crack_defaults[:flow_exponent][:default].to_f
84
+ os_crack = OpenStudio::Model::AirflowNetworkCrack.new(
85
+ openstudio_model, vent_crack[:flow_coefficient], flow_exponent,
86
+ $afn_reference_crack)
87
+
88
+ # assign the flow exponent if it's specified
89
+ if vent_crack[:flow_exponent]
90
+ os_crack.setAirMassFlowExponent(vent_crack[:flow_exponent])
91
+ end
91
92
 
92
- # if it's a Surface boundary condition ensure the neighbor is not written as a duplicate
93
- if @hash[:boundary_condition][:type] == 'Surface'
94
- $interior_afn_srf_hash[@hash[:boundary_condition][:boundary_condition_objects][0]] = true
95
- end
93
+ # if it's a Surface boundary condition ensure the neighbor is not written as a duplicate
94
+ if @hash[:boundary_condition][:type] == 'Surface'
95
+ $interior_afn_srf_hash[@hash[:boundary_condition][:boundary_condition_objects][0]] = true
96
+ end
96
97
 
97
- # create the AirflowNetworkSurface
98
- os_afn_srf = os_surface.getAirflowNetworkSurface(os_crack)
98
+ # create the AirflowNetworkSurface
99
+ os_afn_srf = os_surface.getAirflowNetworkSurface(os_crack)
99
100
 
101
+ end
100
102
  end
101
103
  end
102
104
 
@@ -206,7 +208,7 @@ module Honeybee
206
208
 
207
209
  # get the approriate construction id
208
210
  construction_id = nil
209
- if @hash[:properties][:energy][:construction]
211
+ if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
210
212
  construction_id = @hash[:properties][:energy][:construction]
211
213
  elsif @hash[:face_type] == 'Wall'
212
214
  construction_id = 'Generic Exterior Wall'
@@ -84,26 +84,6 @@ module Honeybee
84
84
  os_thermal_zone.setDisplayName(@hash[:display_name])
85
85
  end
86
86
 
87
- # assign the programtype
88
- if @hash[:properties][:energy][:program_type]
89
- space_type = openstudio_model.getSpaceTypeByName(@hash[:properties][:energy][:program_type])
90
- unless space_type.empty?
91
- space_type_object = space_type.get
92
- os_space.setSpaceType(space_type_object)
93
- end
94
- end
95
-
96
- # assign the constructionset
97
- if @hash[:properties][:energy][:construction_set]
98
- construction_set_identifier = @hash[:properties][:energy][:construction_set]
99
- # gets default construction set assigned to room from openstudio_model
100
- construction_set = openstudio_model.getDefaultConstructionSetByName(construction_set_identifier)
101
- unless construction_set.empty?
102
- default_construction_set = construction_set.get
103
- os_space.setDefaultConstructionSet(default_construction_set)
104
- end
105
- end
106
-
107
87
  # assign the multiplier
108
88
  if @hash[:multiplier] and @hash[:multiplier] != 1
109
89
  os_thermal_zone.setMultiplier(@hash[:multiplier])
@@ -142,6 +122,28 @@ module Honeybee
142
122
  end
143
123
  os_space.setBuildingStory(story)
144
124
 
125
+ if @hash[:properties].key?(:energy)
126
+ # assign the programtype
127
+ if @hash[:properties][:energy][:program_type]
128
+ space_type = openstudio_model.getSpaceTypeByName(@hash[:properties][:energy][:program_type])
129
+ unless space_type.empty?
130
+ space_type_object = space_type.get
131
+ os_space.setSpaceType(space_type_object)
132
+ end
133
+ end
134
+
135
+ # assign the constructionset
136
+ if @hash[:properties][:energy][:construction_set]
137
+ construction_set_identifier = @hash[:properties][:energy][:construction_set]
138
+ # gets default construction set assigned to room from openstudio_model
139
+ construction_set = openstudio_model.getDefaultConstructionSetByName(construction_set_identifier)
140
+ unless construction_set.empty?
141
+ default_construction_set = construction_set.get
142
+ os_space.setDefaultConstructionSet(default_construction_set)
143
+ end
144
+ end
145
+ end
146
+
145
147
  # keep track of all window ventilation objects
146
148
  window_vent = {}
147
149
 
@@ -162,9 +164,11 @@ module Honeybee
162
164
  # assign aperture-level shades if they exist
163
165
  if face[:apertures]
164
166
  face[:apertures].each do |aperture|
165
- if aperture[:properties][:energy][:vent_opening]
166
- window_vent[aperture[:identifier]] = \
167
- [aperture[:properties][:energy][:vent_opening], aperture[:boundary_condition][:type]]
167
+ if aperture[:properties].key?(:energy)
168
+ if aperture[:properties][:energy][:vent_opening]
169
+ window_vent[aperture[:identifier]] = \
170
+ [aperture[:properties][:energy][:vent_opening], aperture[:boundary_condition][:type]]
171
+ end
168
172
  end
169
173
  if aperture[:outdoor_shades]
170
174
  unless os_shd_group
@@ -180,9 +184,11 @@ module Honeybee
180
184
  # assign door-level shades if they exist
181
185
  if face[:doors]
182
186
  face[:doors].each do |door|
183
- if door[:properties][:energy][:vent_opening]
184
- window_vent[door[:identifier]] = \
185
- [door[:properties][:energy][:vent_opening], door[:boundary_condition][:type]]
187
+ if door[:properties].key?(:energy)
188
+ if door[:properties][:energy][:vent_opening]
189
+ window_vent[door[:identifier]] = \
190
+ [door[:properties][:energy][:vent_opening], door[:boundary_condition][:type]]
191
+ end
186
192
  end
187
193
  if door[:outdoor_shades]
188
194
  unless os_shd_group
@@ -196,7 +202,7 @@ module Honeybee
196
202
  end
197
203
 
198
204
  # assign interior constructions for adiabatic Faces
199
- if !face[:properties][:energy][:construction]
205
+ if face[:properties].key?(:energy) && !face[:properties][:energy][:construction]
200
206
  if face[:boundary_condition][:type] == 'Adiabatic'
201
207
  # assign default interior construction for Adiabatic Faces
202
208
  if face[:face_type] != 'Wall'
@@ -212,7 +218,7 @@ module Honeybee
212
218
  if face[:face_type] == 'AirBoundary'
213
219
  # assign default air boundary construction for AirBoundary face types
214
220
  air_construction = closest_air_construction(openstudio_model, os_space)
215
- if !face[:properties][:energy][:construction]
221
+ if face[:properties].key?(:energy) && !face[:properties][:energy][:construction]
216
222
  unless air_construction.nil?
217
223
  os_surface.setConstruction(air_construction)
218
224
  end
@@ -256,164 +262,166 @@ module Honeybee
256
262
  end
257
263
 
258
264
  #check whether there are any load objects on the room overriding the programtype
259
- if @hash[:properties][:energy][:people]
260
- unique_program = get_unique_space_type(openstudio_model, os_space)
261
- unique_program_ppl = unique_program.people
262
- unless unique_program_ppl.empty? # remove the previous load definition
263
- unique_program_ppl[0].remove()
265
+ if @hash[:properties].key?(:energy)
266
+ if @hash[:properties][:energy][:people]
267
+ unique_program = get_unique_space_type(openstudio_model, os_space)
268
+ unique_program_ppl = unique_program.people
269
+ unless unique_program_ppl.empty? # remove the previous load definition
270
+ unique_program_ppl[0].remove()
271
+ end
272
+ custom_people = PeopleAbridged.new(@hash[:properties][:energy][:people])
273
+ os_custom_people = custom_people.to_openstudio(openstudio_model)
274
+ os_custom_people.setSpaceType(unique_program) # assign the new load definition
264
275
  end
265
- custom_people = PeopleAbridged.new(@hash[:properties][:energy][:people])
266
- os_custom_people = custom_people.to_openstudio(openstudio_model)
267
- os_custom_people.setSpaceType(unique_program) # assign the new load definition
268
- end
269
276
 
270
- # assign lighting if it exists
271
- if @hash[:properties][:energy][:lighting]
272
- unique_program = get_unique_space_type(openstudio_model, os_space)
273
- unique_program_lght = unique_program.lights
274
- unless unique_program_lght.empty? # remove the previous load definition
275
- unique_program_lght[0].remove()
277
+ # assign lighting if it exists
278
+ if @hash[:properties][:energy][:lighting]
279
+ unique_program = get_unique_space_type(openstudio_model, os_space)
280
+ unique_program_lght = unique_program.lights
281
+ unless unique_program_lght.empty? # remove the previous load definition
282
+ unique_program_lght[0].remove()
283
+ end
284
+ custom_lighting = LightingAbridged.new(@hash[:properties][:energy][:lighting])
285
+ os_custom_lighting = custom_lighting.to_openstudio(openstudio_model)
286
+ os_custom_lighting.setSpaceType(unique_program) # assign the new load definition
276
287
  end
277
- custom_lighting = LightingAbridged.new(@hash[:properties][:energy][:lighting])
278
- os_custom_lighting = custom_lighting.to_openstudio(openstudio_model)
279
- os_custom_lighting.setSpaceType(unique_program) # assign the new load definition
280
- end
281
288
 
282
- # assign electric equipment if it exists
283
- if @hash[:properties][:energy][:electric_equipment]
284
- unique_program = get_unique_space_type(openstudio_model, os_space)
285
- unique_program_ele = unique_program.electricEquipment
286
- unless unique_program_ele.empty? # remove the previous load definition
287
- unique_program_ele[0].remove()
289
+ # assign electric equipment if it exists
290
+ if @hash[:properties][:energy][:electric_equipment]
291
+ unique_program = get_unique_space_type(openstudio_model, os_space)
292
+ unique_program_ele = unique_program.electricEquipment
293
+ unless unique_program_ele.empty? # remove the previous load definition
294
+ unique_program_ele[0].remove()
295
+ end
296
+ custom_electric_equipment = ElectricEquipmentAbridged.new(@hash[:properties][:energy][:electric_equipment])
297
+ os_custom_electric_equipment = custom_electric_equipment.to_openstudio(openstudio_model)
298
+ os_custom_electric_equipment.setSpaceType(unique_program) # assign the new load definition
288
299
  end
289
- custom_electric_equipment = ElectricEquipmentAbridged.new(@hash[:properties][:energy][:electric_equipment])
290
- os_custom_electric_equipment = custom_electric_equipment.to_openstudio(openstudio_model)
291
- os_custom_electric_equipment.setSpaceType(unique_program) # assign the new load definition
292
- end
293
300
 
294
- # assign gas equipment if it exists
295
- if @hash[:properties][:energy][:gas_equipment]
296
- unique_program = get_unique_space_type(openstudio_model, os_space)
297
- unique_program_gas = unique_program.gasEquipment
298
- unless unique_program_gas.empty? # remove the previous load definition
299
- unique_program_gas[0].remove()
301
+ # assign gas equipment if it exists
302
+ if @hash[:properties][:energy][:gas_equipment]
303
+ unique_program = get_unique_space_type(openstudio_model, os_space)
304
+ unique_program_gas = unique_program.gasEquipment
305
+ unless unique_program_gas.empty? # remove the previous load definition
306
+ unique_program_gas[0].remove()
307
+ end
308
+ custom_gas_equipment = GasEquipmentAbridged.new(@hash[:properties][:energy][:gas_equipment])
309
+ os_custom_gas_equipment = custom_gas_equipment.to_openstudio(openstudio_model)
310
+ os_custom_gas_equipment.setSpaceType(unique_program) # assign the new load definition
300
311
  end
301
- custom_gas_equipment = GasEquipmentAbridged.new(@hash[:properties][:energy][:gas_equipment])
302
- os_custom_gas_equipment = custom_gas_equipment.to_openstudio(openstudio_model)
303
- os_custom_gas_equipment.setSpaceType(unique_program) # assign the new load definition
304
- end
305
312
 
306
- # assign service hot water if it exists
307
- if @hash[:properties][:energy][:service_hot_water]
308
- shw_space = ServiceHotWaterAbridged.new(@hash[:properties][:energy][:service_hot_water])
309
- os_shw_space = shw_space.to_openstudio(
310
- openstudio_model, os_space, @hash[:properties][:energy][:shw])
311
- $shw_for_plant = shw_space
312
- end
313
+ # assign service hot water if it exists
314
+ if @hash[:properties][:energy][:service_hot_water]
315
+ shw_space = ServiceHotWaterAbridged.new(@hash[:properties][:energy][:service_hot_water])
316
+ os_shw_space = shw_space.to_openstudio(
317
+ openstudio_model, os_space, @hash[:properties][:energy][:shw])
318
+ $shw_for_plant = shw_space
319
+ end
313
320
 
314
- # assign infiltration if it exists
315
- if @hash[:properties][:energy][:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
316
- unique_program = get_unique_space_type(openstudio_model, os_space)
317
- unique_program_inf = unique_program.spaceInfiltrationDesignFlowRates
318
- unless unique_program_inf.empty? # remove the previous load definition
319
- unique_program_inf[0].remove()
321
+ # assign infiltration if it exists
322
+ if @hash[:properties][:energy][:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
323
+ unique_program = get_unique_space_type(openstudio_model, os_space)
324
+ unique_program_inf = unique_program.spaceInfiltrationDesignFlowRates
325
+ unless unique_program_inf.empty? # remove the previous load definition
326
+ unique_program_inf[0].remove()
327
+ end
328
+ custom_infiltration = InfiltrationAbridged.new(@hash[:properties][:energy][:infiltration])
329
+ os_custom_infiltration = custom_infiltration.to_openstudio(openstudio_model)
330
+ os_custom_infiltration.setSpaceType(unique_program) # assign the new load definition
320
331
  end
321
- custom_infiltration = InfiltrationAbridged.new(@hash[:properties][:energy][:infiltration])
322
- os_custom_infiltration = custom_infiltration.to_openstudio(openstudio_model)
323
- os_custom_infiltration.setSpaceType(unique_program) # assign the new load definition
324
- end
325
332
 
326
- # assign ventilation if it exists
327
- if @hash[:properties][:energy][:ventilation]
328
- unique_program = get_unique_space_type(openstudio_model, os_space)
329
- unique_program.resetDesignSpecificationOutdoorAir()
330
- custom_ventilation = VentilationAbridged.new(@hash[:properties][:energy][:ventilation])
331
- os_custom_ventilation = custom_ventilation.to_openstudio(openstudio_model)
332
- unique_program.setDesignSpecificationOutdoorAir(os_custom_ventilation)
333
- end
333
+ # assign ventilation if it exists
334
+ if @hash[:properties][:energy][:ventilation]
335
+ unique_program = get_unique_space_type(openstudio_model, os_space)
336
+ unique_program.resetDesignSpecificationOutdoorAir()
337
+ custom_ventilation = VentilationAbridged.new(@hash[:properties][:energy][:ventilation])
338
+ os_custom_ventilation = custom_ventilation.to_openstudio(openstudio_model)
339
+ unique_program.setDesignSpecificationOutdoorAir(os_custom_ventilation)
340
+ end
334
341
 
335
- # assign setpoint if it exists
336
- if @hash[:properties][:energy][:setpoint]
337
- # thermostat object is created because heating and cooling schedule are required
338
- setpoint_thermostat_space = SetpointThermostat.new(@hash[:properties][:energy][:setpoint])
339
- os_setpoint_thermostat_space = setpoint_thermostat_space.to_openstudio(openstudio_model)
340
- #set thermostat to thermal zone
341
- os_thermal_zone.setThermostatSetpointDualSetpoint(os_setpoint_thermostat_space)
342
- # humidistat object is created if humidifying or dehumidifying schedule is specified
343
- if @hash[:properties][:energy][:setpoint][:humidifying_schedule] or @hash[:properties][:energy][:setpoint][:dehumidifying_schedule]
344
- setpoint_humidistat_space = SetpointHumidistat.new(@hash[:properties][:energy][:setpoint])
345
- os_setpoint_humidistat_space = setpoint_humidistat_space.to_openstudio(openstudio_model)
346
- os_thermal_zone.setZoneControlHumidistat(os_setpoint_humidistat_space)
342
+ # assign setpoint if it exists
343
+ if @hash[:properties][:energy][:setpoint]
344
+ # thermostat object is created because heating and cooling schedule are required
345
+ setpoint_thermostat_space = SetpointThermostat.new(@hash[:properties][:energy][:setpoint])
346
+ os_setpoint_thermostat_space = setpoint_thermostat_space.to_openstudio(openstudio_model)
347
+ #set thermostat to thermal zone
348
+ os_thermal_zone.setThermostatSetpointDualSetpoint(os_setpoint_thermostat_space)
349
+ # humidistat object is created if humidifying or dehumidifying schedule is specified
350
+ if @hash[:properties][:energy][:setpoint][:humidifying_schedule] or @hash[:properties][:energy][:setpoint][:dehumidifying_schedule]
351
+ setpoint_humidistat_space = SetpointHumidistat.new(@hash[:properties][:energy][:setpoint])
352
+ os_setpoint_humidistat_space = setpoint_humidistat_space.to_openstudio(openstudio_model)
353
+ os_thermal_zone.setZoneControlHumidistat(os_setpoint_humidistat_space)
354
+ end
347
355
  end
348
- end
349
356
 
350
- # assign daylight control if it exists
351
- if @hash[:properties][:energy][:daylighting_control]
352
- dl_control = DaylightingControl.new(@hash[:properties][:energy][:daylighting_control])
353
- os_dl_control = dl_control.to_openstudio(openstudio_model, os_thermal_zone, os_space)
354
- end
357
+ # assign daylight control if it exists
358
+ if @hash[:properties][:energy][:daylighting_control]
359
+ dl_control = DaylightingControl.new(@hash[:properties][:energy][:daylighting_control])
360
+ os_dl_control = dl_control.to_openstudio(openstudio_model, os_thermal_zone, os_space)
361
+ end
355
362
 
356
- # assign window ventilation objects if they exist
357
- if $use_simple_vent && !window_vent.empty? # write simple WindAndStack ventilation
358
- window_vent.each do |sub_f_id, open_prop|
359
- opening = open_prop[0]
360
- bc = open_prop[1]
361
- if bc == 'Outdoors'
363
+ # assign window ventilation objects if they exist
364
+ if $use_simple_vent && !window_vent.empty? # write simple WindAndStack ventilation
365
+ window_vent.each do |sub_f_id, open_prop|
366
+ opening = open_prop[0]
367
+ bc = open_prop[1]
368
+ if bc == 'Outdoors'
369
+ opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
370
+ unless opt_sub_f.empty?
371
+ sub_f = opt_sub_f.get
372
+ vent_open = VentilationOpening.new(opening)
373
+ os_vent_open = vent_open.to_openstudio(
374
+ openstudio_model, sub_f, @hash[:properties][:energy][:window_vent_control])
375
+ os_vent_open.addToThermalZone(os_thermal_zone)
376
+ end
377
+ end
378
+ end
379
+ elsif !$use_simple_vent # we're using the AFN!
380
+ # write an AirflowNetworkZone object in for the Room
381
+ os_afn_room_node = os_thermal_zone.getAirflowNetworkZone
382
+ os_afn_room_node.setVentilationControlMode('NoVent')
383
+ # write the opening objects for each Aperture / Door
384
+ operable_subfs = [] # collect the sub-face objects for the EMS
385
+ opening_factors = [] # collect the maximum opening factors for the EMS
386
+ window_vent.each do |sub_f_id, open_prop|
387
+ opening = open_prop[0]
362
388
  opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
363
389
  unless opt_sub_f.empty?
364
390
  sub_f = opt_sub_f.get
365
- vent_open = VentilationOpening.new(opening)
366
- os_vent_open = vent_open.to_openstudio(
367
- openstudio_model, sub_f, @hash[:properties][:energy][:window_vent_control])
368
- os_vent_open.addToThermalZone(os_thermal_zone)
369
- end
370
- end
371
- end
372
- elsif !$use_simple_vent # we're using the AFN!
373
- # write an AirflowNetworkZone object in for the Room
374
- os_afn_room_node = os_thermal_zone.getAirflowNetworkZone
375
- os_afn_room_node.setVentilationControlMode('NoVent')
376
- # write the opening objects for each Aperture / Door
377
- operable_subfs = [] # collect the sub-face objects for the EMS
378
- opening_factors = [] # collect the maximum opening factors for the EMS
379
- window_vent.each do |sub_f_id, open_prop|
380
- opening = open_prop[0]
381
- opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
382
- unless opt_sub_f.empty?
383
- sub_f = opt_sub_f.get
384
- if sub_f.adjacentSubSurface.empty? # not an interior window that's already in the AFN
385
- vent_open = VentilationOpening.new(opening)
386
- open_fac = vent_open.to_openstudio_afn(openstudio_model, sub_f)
387
- unless open_fac.nil? # nil is used for horizontal exterior skylights
388
- operable_subfs << sub_f
389
- opening_factors << open_fac
391
+ if sub_f.adjacentSubSurface.empty? # not an interior window that's already in the AFN
392
+ vent_open = VentilationOpening.new(opening)
393
+ open_fac = vent_open.to_openstudio_afn(openstudio_model, sub_f)
394
+ unless open_fac.nil? # nil is used for horizontal exterior skylights
395
+ operable_subfs << sub_f
396
+ opening_factors << open_fac
397
+ end
390
398
  end
391
399
  end
392
400
  end
401
+ # add the control startegy of the ventilation openings using the EMS
402
+ if @hash[:properties][:energy][:window_vent_control]
403
+ vent_control = VentilationControlAbridged.new(@hash[:properties][:energy][:window_vent_control])
404
+ vent_control.to_openstudio(
405
+ openstudio_model, os_thermal_zone, operable_subfs, opening_factors)
406
+ end
393
407
  end
394
- # add the control startegy of the ventilation openings using the EMS
395
- if @hash[:properties][:energy][:window_vent_control]
396
- vent_control = VentilationControlAbridged.new(@hash[:properties][:energy][:window_vent_control])
397
- vent_control.to_openstudio(
398
- openstudio_model, os_thermal_zone, operable_subfs, opening_factors)
399
- end
400
- end
401
408
 
402
- # assign any internal masses if specified
403
- if @hash[:properties][:energy][:internal_masses]
404
- @hash[:properties][:energy][:internal_masses].each do |int_mass|
405
- hb_int_mass = InternalMassAbridged.new(int_mass)
406
- os_int_mass = hb_int_mass.to_openstudio(openstudio_model, os_space)
407
- os_int_mass.setSpace(os_space)
409
+ # assign any internal masses if specified
410
+ if @hash[:properties][:energy][:internal_masses]
411
+ @hash[:properties][:energy][:internal_masses].each do |int_mass|
412
+ hb_int_mass = InternalMassAbridged.new(int_mass)
413
+ os_int_mass = hb_int_mass.to_openstudio(openstudio_model, os_space)
414
+ os_int_mass.setSpace(os_space)
415
+ end
408
416
  end
409
- end
410
417
 
411
- # assign any process loads if specified
412
- if @hash[:properties][:energy][:process_loads]
413
- @hash[:properties][:energy][:process_loads].each do |p_load|
414
- hb_p_load = ProcessAbridged.new(p_load)
415
- os_p_load = hb_p_load.to_openstudio(openstudio_model)
416
- os_p_load.setSpace(os_space)
418
+ # assign any process loads if specified
419
+ if @hash[:properties][:energy][:process_loads]
420
+ @hash[:properties][:energy][:process_loads].each do |p_load|
421
+ hb_p_load = ProcessAbridged.new(p_load)
422
+ os_p_load = hb_p_load.to_openstudio(openstudio_model)
423
+ os_p_load.setSpace(os_space)
424
+ end
417
425
  end
418
426
  end
419
427
 
@@ -61,23 +61,26 @@ module Honeybee
61
61
  unless @hash[:display_name].nil?
62
62
  os_shading_surface.setDisplayName(@hash[:display_name])
63
63
  end
64
- # assign the construction if it exists
65
- if @hash[:properties][:energy][:construction]
66
- construction_identifier = @hash[:properties][:energy][:construction]
67
- construction = openstudio_model.getConstructionByName(construction_identifier)
68
- unless construction.empty?
69
- os_construction = construction.get
70
- os_shading_surface.setConstruction(os_construction)
64
+
65
+ if @hash[:properties].key?(:energy)
66
+ # assign the construction if it exists
67
+ if @hash[:properties][:energy][:construction]
68
+ construction_identifier = @hash[:properties][:energy][:construction]
69
+ construction = openstudio_model.getConstructionByName(construction_identifier)
70
+ unless construction.empty?
71
+ os_construction = construction.get
72
+ os_shading_surface.setConstruction(os_construction)
73
+ end
71
74
  end
72
- end
73
75
 
74
- # assign the transmittance schedule if it exists
75
- if @hash[:properties][:energy][:transmittance_schedule]
76
- schedule_identifier = @hash[:properties][:energy][:transmittance_schedule]
77
- schedule = openstudio_model.getScheduleByName(schedule_identifier)
78
- unless schedule.empty?
79
- os_schedule = schedule.get
80
- os_shading_surface.setTransmittanceSchedule(os_schedule)
76
+ # assign the transmittance schedule if it exists
77
+ if @hash[:properties][:energy][:transmittance_schedule]
78
+ schedule_identifier = @hash[:properties][:energy][:transmittance_schedule]
79
+ schedule = openstudio_model.getScheduleByName(schedule_identifier)
80
+ unless schedule.empty?
81
+ os_schedule = schedule.get
82
+ os_shading_surface.setTransmittanceSchedule(os_schedule)
83
+ end
81
84
  end
82
85
  end
83
86
 
@@ -109,7 +109,7 @@ module Honeybee
109
109
 
110
110
  # initialize a global variable for whether the AFN is used instead of simple ventilation
111
111
  $use_simple_vent = true
112
- if @hash[:properties][:energy][:ventilation_simulation_control]
112
+ if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:ventilation_simulation_control]
113
113
  vent_sim_control = @hash[:properties][:energy][:ventilation_simulation_control]
114
114
  if vent_sim_control[:vent_control_type] && vent_sim_control[:vent_control_type] != 'SingleZone'
115
115
  $use_simple_vent = false
@@ -129,42 +129,44 @@ module Honeybee
129
129
  $shw_for_plant = nil # track whether a hot water plant is needed
130
130
 
131
131
  # create all of the non-geometric model elements
132
- if log_report # schedules are used by all other objects and come first
133
- puts 'Translating Schedules'
134
- end
135
- if @hash[:properties][:energy][:schedule_type_limits]
136
- create_schedule_type_limits(@hash[:properties][:energy][:schedule_type_limits])
137
- end
138
- if @hash[:properties][:energy][:schedules]
139
- create_schedules(@hash[:properties][:energy][:schedules], false, true)
140
- end
132
+ if @hash[:properties].key?(:energy)
133
+ if log_report # schedules are used by all other objects and come first
134
+ puts 'Translating Schedules'
135
+ end
136
+ if @hash[:properties][:energy][:schedule_type_limits]
137
+ create_schedule_type_limits(@hash[:properties][:energy][:schedule_type_limits])
138
+ end
139
+ if @hash[:properties][:energy][:schedules]
140
+ create_schedules(@hash[:properties][:energy][:schedules], false, true)
141
+ end
141
142
 
142
- if log_report
143
- puts 'Translating Materials'
144
- end
145
- if @hash[:properties][:energy][:materials]
146
- create_materials(@hash[:properties][:energy][:materials])
147
- end
143
+ if log_report
144
+ puts 'Translating Materials'
145
+ end
146
+ if @hash[:properties][:energy][:materials]
147
+ create_materials(@hash[:properties][:energy][:materials])
148
+ end
148
149
 
149
- if log_report
150
- puts 'Translating Constructions'
151
- end
152
- if @hash[:properties][:energy][:constructions]
153
- create_constructions(@hash[:properties][:energy][:constructions])
154
- end
150
+ if log_report
151
+ puts 'Translating Constructions'
152
+ end
153
+ if @hash[:properties][:energy][:constructions]
154
+ create_constructions(@hash[:properties][:energy][:constructions])
155
+ end
155
156
 
156
- if log_report
157
- puts 'Translating ConstructionSets'
158
- end
159
- if @hash[:properties][:energy][:construction_sets]
160
- create_construction_sets(@hash[:properties][:energy][:construction_sets])
161
- end
157
+ if log_report
158
+ puts 'Translating ConstructionSets'
159
+ end
160
+ if @hash[:properties][:energy][:construction_sets]
161
+ create_construction_sets(@hash[:properties][:energy][:construction_sets])
162
+ end
162
163
 
163
- if log_report
164
- puts 'Translating ProgramTypes'
165
- end
166
- if @hash[:properties][:energy][:program_types]
167
- create_program_types(@hash[:properties][:energy][:program_types])
164
+ if log_report
165
+ puts 'Translating ProgramTypes'
166
+ end
167
+ if @hash[:properties][:energy][:program_types]
168
+ create_program_types(@hash[:properties][:energy][:program_types])
169
+ end
168
170
  end
169
171
 
170
172
  # create the default construction set to catch any cases of unassigned constructions
@@ -196,8 +198,10 @@ module Honeybee
196
198
  if log_report
197
199
  puts 'Translating HVAC Systems'
198
200
  end
199
- create_hvacs
200
- create_hot_water_plant
201
+ if @hash[:properties].key?(:energy)
202
+ create_hvacs
203
+ create_hot_water_plant
204
+ end
201
205
 
202
206
  if log_report
203
207
  puts 'Translating Context Shade Geometry'
@@ -445,32 +449,34 @@ module Honeybee
445
449
  openstudio_room = room_object.to_openstudio(@openstudio_model)
446
450
 
447
451
  # for rooms with hot water objects definied in the ProgramType, make a new WaterUse:Equipment
448
- if room[:properties][:energy][:program_type] && !room[:properties][:energy][:service_hot_water]
449
- program_type_id = room[:properties][:energy][:program_type]
450
- shw_hash = $programtype_shw_hash[program_type_id]
451
- unless shw_hash.nil?
452
- shw_object = ServiceHotWaterAbridged.new(shw_hash)
453
- openstudio_shw = shw_object.to_openstudio(
454
- @openstudio_model, openstudio_room, room[:properties][:energy][:shw])
455
- $shw_for_plant = shw_object
452
+ if room[:properties].key?(:energy)
453
+ if room[:properties][:energy][:program_type] && !room[:properties][:energy][:service_hot_water]
454
+ program_type_id = room[:properties][:energy][:program_type]
455
+ shw_hash = $programtype_shw_hash[program_type_id]
456
+ unless shw_hash.nil?
457
+ shw_object = ServiceHotWaterAbridged.new(shw_hash)
458
+ openstudio_shw = shw_object.to_openstudio(
459
+ @openstudio_model, openstudio_room, room[:properties][:energy][:shw])
460
+ $shw_for_plant = shw_object
461
+ end
456
462
  end
457
- end
458
463
 
459
- # for rooms with setpoint objects defined in the ProgramType, make a new thermostat
460
- if room[:properties][:energy][:program_type] && !room[:properties][:energy][:setpoint]
461
- thermal_zone = openstudio_room.thermalZone()
462
- unless thermal_zone.empty?
463
- thermal_zone_object = thermal_zone.get
464
- program_type_id = room[:properties][:energy][:program_type]
465
- setpoint_hash = $programtype_setpoint_hash[program_type_id]
466
- unless setpoint_hash.nil? # program type has no setpoint
467
- thermostat_object = SetpointThermostat.new(setpoint_hash)
468
- openstudio_thermostat = thermostat_object.to_openstudio(@openstudio_model)
469
- thermal_zone_object.setThermostatSetpointDualSetpoint(openstudio_thermostat)
470
- if setpoint_hash[:humidifying_schedule] or setpoint_hash[:dehumidifying_schedule]
471
- humidistat_object = SetpointHumidistat.new(setpoint_hash)
472
- openstudio_humidistat = humidistat_object.to_openstudio(@openstudio_model)
473
- thermal_zone_object.setZoneControlHumidistat(openstudio_humidistat)
464
+ # for rooms with setpoint objects defined in the ProgramType, make a new thermostat
465
+ if room[:properties][:energy][:program_type] && !room[:properties][:energy][:setpoint]
466
+ thermal_zone = openstudio_room.thermalZone()
467
+ unless thermal_zone.empty?
468
+ thermal_zone_object = thermal_zone.get
469
+ program_type_id = room[:properties][:energy][:program_type]
470
+ setpoint_hash = $programtype_setpoint_hash[program_type_id]
471
+ unless setpoint_hash.nil? # program type has no setpoint
472
+ thermostat_object = SetpointThermostat.new(setpoint_hash)
473
+ openstudio_thermostat = thermostat_object.to_openstudio(@openstudio_model)
474
+ thermal_zone_object.setThermostatSetpointDualSetpoint(openstudio_thermostat)
475
+ if setpoint_hash[:humidifying_schedule] or setpoint_hash[:dehumidifying_schedule]
476
+ humidistat_object = SetpointHumidistat.new(setpoint_hash)
477
+ openstudio_humidistat = humidistat_object.to_openstudio(@openstudio_model)
478
+ thermal_zone_object.setZoneControlHumidistat(openstudio_humidistat)
479
+ end
474
480
  end
475
481
  end
476
482
  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.31.8
4
+ version: 2.31.9
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: 2022-05-24 00:00:00.000000000 Z
14
+ date: 2022-05-26 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -177,6 +177,7 @@ files:
177
177
  - lib/from_openstudio/geometry/face.rb
178
178
  - lib/from_openstudio/geometry/room.rb
179
179
  - lib/from_openstudio/geometry/shade.rb
180
+ - lib/from_openstudio/hvac/ideal_air.rb
180
181
  - lib/from_openstudio/load/daylight.rb
181
182
  - lib/from_openstudio/load/electric_equipment.rb
182
183
  - lib/from_openstudio/load/gas_equipment.rb