honeybee-openstudio 2.6.2 → 2.6.7

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: 58a653751b8089a138bf8801ec4b364cc80ac8b32ea2a92e07baa138b3a800e5
4
- data.tar.gz: fbc8b5a03386731492f61feb8728e45a8658002f6a92ff785b2714d6f24ce9ea
3
+ metadata.gz: 0b0da04a58221bdf1cd64089755dadb753e9c45feb2966a983a7aa9574dea77a
4
+ data.tar.gz: ef763660f47e53e7336f0b48cbaf99b89c924dbee72bef048977485d483db49e
5
5
  SHA512:
6
- metadata.gz: 95f905265f9aa6c3765dc39cff0e0654b058f66d7e75070b80c52ffeb27c708e7859a9ced7290c6aa2dcbaa6af4df50afd4047a5c54e2fdf723a012e60c9b600
7
- data.tar.gz: 85621370e9d5a0e3a4f120cbde34fc1187791d2c8fb4283d3cfca9272894e1ae2fac73feb03eabd300db282b2e33193acff242625b95fb83e8afa06d155ced32
6
+ metadata.gz: 862f2c7fa88498e78141a6293797e39e96f9b25d2e10ef8231c0899530917373774f4c4c26bfe674a7f9accc6d2e639dd0c3baab25bd543029b4740034a8ad75
7
+ data.tar.gz: 15bb34106c90a0f72f3e05fa5075636f2e4e28839b8a1820695087c3c2c1707e3aad9c6c2825f630f5db8e18753f8780484af2fa5005ce50a46ab67224aae114
@@ -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.6.2'
7
+ spec.version = '2.6.7'
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
 
@@ -21,4 +21,4 @@ else
21
21
  end
22
22
 
23
23
  # include the honeybee-openstudio-gem
24
- gem 'honeybee-openstudio', '2.5.3'
24
+ gem 'honeybee-openstudio', '2.6.4'
@@ -55,7 +55,12 @@ module FromHoneybee
55
55
  os_construction = OpenStudio::Model::ConstructionAirBoundary.new(openstudio_model)
56
56
  os_construction.setName(@hash[:identifier])
57
57
  os_construction.setSolarAndDaylightingMethod('GroupedZones')
58
- os_construction.setRadiantExchangeMethod('GroupedZones')
58
+ # REMOVE: Remove the use of IRTSurface once the AFN works with GroupedZone air walls
59
+ if !$use_simple_vent # we're using the AFN!
60
+ os_construction.setRadiantExchangeMethod('IRTSurface')
61
+ else
62
+ os_construction.setRadiantExchangeMethod('GroupedZones')
63
+ end
59
64
  os_construction.setAirExchangeMethod('None')
60
65
 
61
66
  os_construction
@@ -54,6 +54,7 @@ module FromHoneybee
54
54
  def initialize(hash = {})
55
55
  super(hash)
56
56
  raise "Incorrect model type '#{@type}'" unless @type == 'Room'
57
+ @unique_space_type = nil
57
58
  end
58
59
 
59
60
  def defaults
@@ -66,6 +67,33 @@ module FromHoneybee
66
67
  nil
67
68
  end
68
69
 
70
+ def get_unique_space_type(openstudio_model, os_space)
71
+ # get a space type that is unique to the room
72
+ if @unique_space_type.nil?
73
+ space_type = os_space.spaceType
74
+ unless space_type.empty?
75
+ # copy the space type that is already assigned to the room
76
+ space_type_object = space_type.get
77
+ space_type_mod_obj = space_type_object.clone(openstudio_model)
78
+ new_space_type = space_type_mod_obj.to_SpaceType.get
79
+ else
80
+ # create a new space type as there is currently none assigned to the room
81
+ new_space_type = OpenStudio::Model::SpaceType.new(openstudio_model)
82
+ end
83
+ # give the space type a new unique name and assign it to the room
84
+ st_name = space_type_object.name
85
+ unless space_type.empty?
86
+ st_name = st_name.get
87
+ else
88
+ st_name = 'CustomSpaceType'
89
+ end
90
+ new_space_type.setName(st_name + '_' + @hash[:identifier])
91
+ os_space.setSpaceType(new_space_type)
92
+ @unique_space_type = new_space_type
93
+ end
94
+ @unique_space_type
95
+ end
96
+
69
97
  def to_openstudio(openstudio_model)
70
98
  # create the space and thermal zone
71
99
  os_space = OpenStudio::Model::Space.new(openstudio_model)
@@ -213,88 +241,75 @@ module FromHoneybee
213
241
  @hash[:outdoor_shades].each do |outdoor_shade|
214
242
  add_shade_to_group(openstudio_model, os_shd_group, outdoor_shade)
215
243
  end
216
- end
244
+ end
217
245
 
218
246
  #check whether there are any load objects on the room overriding the programtype
219
247
  if @hash[:properties][:energy][:people]
220
- people = openstudio_model.getPeopleByName(@hash[:properties][:energy][:people][:identifier])
221
- unless people.empty?
222
- people_object = people.get
223
- people_object.setSpace(os_space)
224
- else
225
- people_space = PeopleAbridged.new(@hash[:properties][:energy][:people])
226
- os_people_space = people_space.to_openstudio(openstudio_model)
227
- os_people_space.setSpace(os_space)
248
+ unique_program = get_unique_space_type(openstudio_model, os_space)
249
+ unique_program_ppl = unique_program.people
250
+ unless unique_program_ppl.empty? # remove the previous load definition
251
+ unique_program_ppl[0].remove()
228
252
  end
253
+ custom_people = PeopleAbridged.new(@hash[:properties][:energy][:people])
254
+ os_custom_people = custom_people.to_openstudio(openstudio_model)
255
+ os_custom_people.setSpaceType(unique_program) # assign the new load definition
229
256
  end
230
257
 
231
258
  # assign lighting if it exists
232
259
  if @hash[:properties][:energy][:lighting]
233
- lighting = openstudio_model.getLightsByName(@hash[:properties][:energy][:lighting][:identifier])
234
- unless lighting.empty?
235
- lighting_object = lighting.get
236
- lighting_object.setSpace(os_space)
237
- else
238
- lighting_space = LightingAbridged.new(@hash[:properties][:energy][:lighting])
239
- os_lighting_space = lighting_space.to_openstudio(openstudio_model)
240
- os_lighting_space.setSpace(os_space)
260
+ unique_program = get_unique_space_type(openstudio_model, os_space)
261
+ unique_program_lght = unique_program.lights
262
+ unless unique_program_lght.empty? # remove the previous load definition
263
+ unique_program_lght[0].remove()
241
264
  end
265
+ custom_lighting = LightingAbridged.new(@hash[:properties][:energy][:lighting])
266
+ os_custom_lighting = custom_lighting.to_openstudio(openstudio_model)
267
+ os_custom_lighting.setSpaceType(unique_program) # assign the new load definition
242
268
  end
243
269
 
244
270
  # assign electric equipment if it exists
245
271
  if @hash[:properties][:energy][:electric_equipment]
246
- electric_equipment = openstudio_model.getElectricEquipmentByName(
247
- @hash[:properties][:energy][:electric_equipment][:identifier])
248
- unless electric_equipment.empty?
249
- electric_equipment_object = electric_equipment.get
250
- electric_equipment_object.setSpace(os_space)
251
- else
252
- electric_equipment_space = ElectricEquipmentAbridged.new(@hash[:properties][:energy][:electric_equipment])
253
- os_electric_equipment_space = electric_equipment_space.to_openstudio(openstudio_model)
254
- os_electric_equipment_space.setSpace(os_space)
272
+ unique_program = get_unique_space_type(openstudio_model, os_space)
273
+ unique_program_ele = unique_program.electricEquipment
274
+ unless unique_program_ele.empty? # remove the previous load definition
275
+ unique_program_ele[0].remove()
255
276
  end
277
+ custom_electric_equipment = ElectricEquipmentAbridged.new(@hash[:properties][:energy][:electric_equipment])
278
+ os_custom_electric_equipment = custom_electric_equipment.to_openstudio(openstudio_model)
279
+ os_custom_electric_equipment.setSpaceType(unique_program) # assign the new load definition
256
280
  end
257
-
281
+
258
282
  # assign gas equipment if it exists
259
283
  if @hash[:properties][:energy][:gas_equipment]
260
- gas_equipment = openstudio_model.getGasEquipmentByName(
261
- @hash[:properties][:energy][:gas_equipment][:identifier])
262
- unless gas_equipment.empty?
263
- gas_equipment_object = gas_equipment.get
264
- gas_equipment_object.setSpace(os_space)
265
- else
266
- gas_equipment_space = GasEquipmentAbridged.new(@hash[:properties][:energy][:gas_equipment])
267
- os_gas_equipment_space = gas_equipment_space.to_openstudio(openstudio_model)
268
- os_gas_equipment_space.setSpace(os_space)
284
+ unique_program = get_unique_space_type(openstudio_model, os_space)
285
+ unique_program_gas = unique_program.gasEquipment
286
+ unless unique_program_gas.empty? # remove the previous load definition
287
+ unique_program_gas[0].remove()
269
288
  end
289
+ custom_gas_equipment = GasEquipmentAbridged.new(@hash[:properties][:energy][:gas_equipment])
290
+ os_custom_gas_equipment = custom_gas_equipment.to_openstudio(openstudio_model)
291
+ os_custom_gas_equipment.setSpaceType(unique_program) # assign the new load definition
270
292
  end
271
293
 
272
294
  # assign infiltration if it exists
273
295
  if @hash[:properties][:energy][:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
274
- infiltration = openstudio_model.getSpaceInfiltrationDesignFlowRateByName(
275
- @hash[:properties][:energy][:infiltration][:identifier])
276
- unless infiltration.empty?
277
- infiltration_object = infiltration.get
278
- infiltration_object.setSpace(os_space)
279
- else
280
- infiltration_space = InfiltrationAbridged.new(@hash[:properties][:energy][:infiltration])
281
- os_infiltration_space = infiltration_space.to_openstudio(openstudio_model)
282
- os_infiltration_space.setSpace(os_space)
296
+ unique_program = get_unique_space_type(openstudio_model, os_space)
297
+ unique_program_inf = unique_program.spaceInfiltrationDesignFlowRates
298
+ unless unique_program_inf.empty? # remove the previous load definition
299
+ unique_program_inf[0].remove()
283
300
  end
301
+ custom_infiltration = InfiltrationAbridged.new(@hash[:properties][:energy][:infiltration])
302
+ os_custom_infiltration = custom_infiltration.to_openstudio(openstudio_model)
303
+ os_custom_infiltration.setSpaceType(unique_program) # assign the new load definition
284
304
  end
285
-
305
+
286
306
  # assign ventilation if it exists
287
307
  if @hash[:properties][:energy][:ventilation]
288
- ventilation = openstudio_model.getDesignSpecificationOutdoorAirByName(
289
- @hash[:properties][:energy][:ventilation][:identifier])
290
- unless ventilation.empty?
291
- ventilation_object = ventilation.get
292
- ventilation_object.setSpace(os_space)
293
- else
294
- ventilation_space = VentilationAbridged.new(@hash[:properties][:energy][:ventilation])
295
- os_ventilation_space = ventilation_space.to_openstudio(openstudio_model)
296
- os_space.setDesignSpecificationOutdoorAir(os_ventilation_space)
297
- end
308
+ unique_program = get_unique_space_type(openstudio_model, os_space)
309
+ unique_program.resetDesignSpecificationOutdoorAir()
310
+ custom_ventilation = VentilationAbridged.new(@hash[:properties][:energy][:ventilation])
311
+ os_custom_ventilation = custom_ventilation.to_openstudio(openstudio_model)
312
+ unique_program.setDesignSpecificationOutdoorAir(os_custom_ventilation)
298
313
  end
299
314
 
300
315
  # assign setpoint if it exists
@@ -533,12 +533,14 @@ module FromHoneybee
533
533
  system_type = hvac[:type]
534
534
  if system_type == 'IdealAirSystemAbridged'
535
535
  ideal_air_system = IdealAirSystemAbridged.new(hvac)
536
- os_ideal_air_system = ideal_air_system.to_openstudio(@openstudio_model)
537
536
  hvac['rooms'].each do |room_id|
537
+ os_ideal_air = ideal_air_system.to_openstudio(@openstudio_model)
538
+ # enforce a strict naming system for each zone so results can be matched
539
+ os_ideal_air.setName(room_id + ' Ideal Loads Air System')
538
540
  zone_get = @openstudio_model.getThermalZoneByName(room_id)
539
541
  unless zone_get.empty?
540
542
  os_thermal_zone = zone_get.get
541
- os_ideal_air_system.addToThermalZone(os_thermal_zone)
543
+ os_ideal_air.addToThermalZone(os_thermal_zone)
542
544
  end
543
545
  end
544
546
  elsif TemplateHVAC.types.include?(system_type)
@@ -138,7 +138,7 @@ module FromHoneybee
138
138
  openstudio_schedule_rule.setApplyFriday(rule[:apply_friday])
139
139
  openstudio_schedule_rule.setApplySaturday(rule[:apply_saturday])
140
140
  year_description = openstudio_model.getYearDescription
141
- start_date = year_description.makeDate(rule[:start_date][0], rule[:start_date][1])
141
+ start_date = year_description.makeDate(rule[:start_date][0], rule[:start_date][1])
142
142
  end_date = year_description.makeDate(rule[:end_date][0], rule[:end_date][1])
143
143
  openstudio_schedule_rule.setStartDate(start_date)
144
144
  openstudio_schedule_rule.setEndDate(end_date)
@@ -288,7 +288,18 @@ module FromHoneybee
288
288
  @hash[:run_period][:daylight_saving_time][:end_date][1])
289
289
  end
290
290
 
291
- # TODO: set the holidays once they are available in OpenStudio SDK
291
+ # Set the holidays
292
+ if @hash[:run_period][:holidays]
293
+ @hash[:run_period][:holidays].each do |hol|
294
+ begin
295
+ os_hol = OpenStudio::Model::RunPeriodControlSpecialDays.new(
296
+ OpenStudio::MonthOfYear.new(hol[0]), hol[1], @openstudio_model)
297
+ os_hol.setDuration(1)
298
+ os_hol.setSpecialDayType('Holiday')
299
+ rescue NoMethodError # REMOVE: Once the upgrade to OpenStudio 3.0 is official
300
+ end
301
+ end
302
+ end
292
303
  end
293
304
 
294
305
  # set the simulation timestep
@@ -98,6 +98,20 @@ module FromHoneybee
98
98
  @@sensor_count = @@sensor_count + 1
99
99
  in_air_temp.setName(in_sensor_name)
100
100
 
101
+ # set up a schedule sensor if there's a schedule specified
102
+ if @hash[:schedule]
103
+ vent_sch = openstudio_model.getScheduleByName(@hash[:schedule])
104
+ unless vent_sch.empty? # schedule not specified
105
+ sch_var = OpenStudio::Model::OutputVariable.new('Schedule Value', openstudio_model)
106
+ sch_var.setReportingFrequency('Timestep')
107
+ sch_var.setKeyValue(@hash[:schedule])
108
+ sch_sens = OpenStudio::Model::EnergyManagementSystemSensor.new(openstudio_model, sch_var)
109
+ sch_sensor_name = replace_ems_special_characters(os_zone_name) + '_Sensor' + @@sensor_count.to_s
110
+ @@sensor_count = @@sensor_count + 1
111
+ sch_sens.setName(sch_sensor_name)
112
+ end
113
+ end
114
+
101
115
  # create the actuators for each of the operaable windows
102
116
  actuator_names = []
103
117
  vent_opening_surfaces.each do |vent_srf|
@@ -140,6 +154,10 @@ module FromHoneybee
140
154
  if delta_in_out && delta_in_out != defaults[:delta_temperature][:default]
141
155
  logic_statements << '((' + in_sensor_name + ' - Outdoor_Sensor) > ' + delta_in_out.to_s + ')'
142
156
  end
157
+ # check the schedule for ventilation
158
+ if sch_sensor_name
159
+ logic_statements << '(' + sch_sensor_name + ' > 0)'
160
+ end
143
161
  # create the complete logic statement for opening windows
144
162
  if logic_statements.empty?
145
163
  complete_logic = 'IF (Outdoor_Sensor < 100)' # no logic has been provided; always open windows
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.6.2
4
+ version: 2.6.7
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-09-02 00:00:00.000000000 Z
14
+ date: 2020-10-23 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler