honeybee-openstudio 2.4.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'
@@ -503,7 +504,7 @@ module FromHoneybee
503
504
  hvac_hashes[hvac[:identifier]] = hvac
504
505
  hvac_hashes[hvac[:identifier]]['rooms'] = []
505
506
  end
506
- # 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
507
508
  if @hash[:rooms]
508
509
  @hash[:rooms].each do |room|
509
510
  if room[:properties][:energy][:hvac]
@@ -514,8 +515,7 @@ module FromHoneybee
514
515
 
515
516
  hvac_hashes.each_value do |hvac|
516
517
  system_type = hvac[:type]
517
- case system_type
518
- when 'IdealAirSystemAbridged'
518
+ if system_type == 'IdealAirSystemAbridged'
519
519
  ideal_air_system = IdealAirSystemAbridged.new(hvac)
520
520
  os_ideal_air_system = ideal_air_system.to_openstudio(@openstudio_model)
521
521
  hvac['rooms'].each do |room_id|
@@ -525,6 +525,9 @@ module FromHoneybee
525
525
  os_ideal_air_system.addToThermalZone(os_thermal_zone)
526
526
  end
527
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'])
528
531
  end
529
532
  end
530
533
  end
@@ -59,11 +59,11 @@ module FromHoneybee
59
59
  os_type_limit = OpenStudio::Model::ScheduleTypeLimits.new(openstudio_model)
60
60
  os_type_limit.setName(@hash[:identifier])
61
61
 
62
- if @hash[:lower_limit] != nil and @hash[:lower_limit] != {'type': 'NoLimit'}
62
+ if @hash[:lower_limit] != nil and @hash[:lower_limit] != {:type => 'NoLimit'}
63
63
  os_type_limit.setLowerLimitValue(@hash[:lower_limit])
64
64
  end
65
65
 
66
- if @hash[:upper_limit] != nil and @hash[:upper_limit] != {'type': 'NoLimit'}
66
+ if @hash[:upper_limit] != nil and @hash[:upper_limit] != {:type => 'NoLimit'}
67
67
  os_type_limit.setUpperLimitValue(@hash[:upper_limit])
68
68
  end
69
69
 
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.4.0
4
+ version: 2.5.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-07-20 00:00:00.000000000 Z
14
+ date: 2020-08-07 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -181,7 +181,9 @@ files:
181
181
  - lib/from_honeybee/geometry/face.rb
182
182
  - lib/from_honeybee/geometry/room.rb
183
183
  - lib/from_honeybee/geometry/shade.rb
184
+ - lib/from_honeybee/hvac/Model.hvac.rb
184
185
  - lib/from_honeybee/hvac/ideal_air.rb
186
+ - lib/from_honeybee/hvac/template.rb
185
187
  - lib/from_honeybee/load/electric_equipment.rb
186
188
  - lib/from_honeybee/load/gas_equipment.rb
187
189
  - lib/from_honeybee/load/infiltration.rb