buildingsync 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/continuous_integration.yml +146 -0
- data/.gitignore +33 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +50 -0
- data/Gemfile +31 -0
- data/Jenkinsfile +10 -0
- data/LICENSE.md +29 -0
- data/README.md +105 -0
- data/Rakefile +77 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/buildingsync.gemspec +37 -0
- data/config.rb.in +26 -0
- data/doc_templates/LICENSE.md +29 -0
- data/doc_templates/README.md.erb +42 -0
- data/doc_templates/copyright_erb.txt +38 -0
- data/doc_templates/copyright_js.txt +5 -0
- data/doc_templates/copyright_ruby.txt +36 -0
- data/lib/buildingsync.rb +43 -0
- data/lib/buildingsync/all_resource_total.rb +54 -0
- data/lib/buildingsync/audit_date.rb +54 -0
- data/lib/buildingsync/constants.rb +49 -0
- data/lib/buildingsync/contact.rb +54 -0
- data/lib/buildingsync/extension.rb +57 -0
- data/lib/buildingsync/generator.rb +584 -0
- data/lib/buildingsync/get_bcl_weather_file.rb +326 -0
- data/lib/buildingsync/helpers/Model.hvac.rb +216 -0
- data/lib/buildingsync/helpers/helper.rb +494 -0
- data/lib/buildingsync/helpers/xml_get_set.rb +215 -0
- data/lib/buildingsync/makers/phase_zero_base.osw +178 -0
- data/lib/buildingsync/makers/workflow_maker.json +811 -0
- data/lib/buildingsync/makers/workflow_maker.rb +581 -0
- data/lib/buildingsync/makers/workflow_maker_base.rb +167 -0
- data/lib/buildingsync/model_articulation/building.rb +1119 -0
- data/lib/buildingsync/model_articulation/building_and_system_types.json +121 -0
- data/lib/buildingsync/model_articulation/building_section.rb +190 -0
- data/lib/buildingsync/model_articulation/building_system.rb +49 -0
- data/lib/buildingsync/model_articulation/envelope_system.rb +102 -0
- data/lib/buildingsync/model_articulation/exterior_floor_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/facility.rb +439 -0
- data/lib/buildingsync/model_articulation/foundation_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/hvac_system.rb +395 -0
- data/lib/buildingsync/model_articulation/lighting_system.rb +102 -0
- data/lib/buildingsync/model_articulation/loads_system.rb +287 -0
- data/lib/buildingsync/model_articulation/location_element.rb +129 -0
- data/lib/buildingsync/model_articulation/measure.rb +57 -0
- data/lib/buildingsync/model_articulation/roof_system_type.rb +64 -0
- data/lib/buildingsync/model_articulation/service_hot_water_system.rb +87 -0
- data/lib/buildingsync/model_articulation/site.rb +242 -0
- data/lib/buildingsync/model_articulation/spatial_element.rb +343 -0
- data/lib/buildingsync/model_articulation/wall_system_type.rb +64 -0
- data/lib/buildingsync/report.rb +217 -0
- data/lib/buildingsync/resource_use.rb +55 -0
- data/lib/buildingsync/scenario.rb +622 -0
- data/lib/buildingsync/selection_tool.rb +98 -0
- data/lib/buildingsync/time_series.rb +85 -0
- data/lib/buildingsync/translator.rb +167 -0
- data/lib/buildingsync/utility.rb +67 -0
- data/lib/buildingsync/version.rb +45 -0
- metadata +223 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# *******************************************************************************
|
4
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
|
+
# BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
15
|
+
# this list of conditions and the following disclaimer in the documentation
|
16
|
+
# and/or other materials provided with the distribution.
|
17
|
+
#
|
18
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
19
|
+
# may be used to endorse or promote products derived from this software without
|
20
|
+
# specific prior written permission from the respective party.
|
21
|
+
#
|
22
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
23
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
24
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
25
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
28
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
31
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
32
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
33
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
34
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
37
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
|
+
# *******************************************************************************
|
39
|
+
|
40
|
+
module BuildingSync
|
41
|
+
# Foundation System Type
|
42
|
+
class FoundationSystemType
|
43
|
+
# initialize a foundation system type given a ref
|
44
|
+
# @param doc [REXML::Document]
|
45
|
+
# @param ns [String]
|
46
|
+
# @param ref [String]
|
47
|
+
def initialize(doc, ns, ref)
|
48
|
+
@id = nil
|
49
|
+
doc.elements.each("#{ns}:Systems/#{ns}:FoundationSystems/#{ns}:FoundationSystem") do |foundation_system|
|
50
|
+
if foundation_system.attributes['ID'] == ref
|
51
|
+
read(foundation_system, ns)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# read
|
57
|
+
# @param foundation_system [REXML:Element]
|
58
|
+
# @param ns [String]
|
59
|
+
def read(foundation_system, ns)
|
60
|
+
# ID
|
61
|
+
@id = foundation_system.attributes['ID'] if foundation_system.attributes['ID']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,395 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# *******************************************************************************
|
4
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
5
|
+
# BuildingSync(R), Copyright (c) 2015-2020, Alliance for Sustainable Energy, LLC.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
# Redistribution and use in source and binary forms, with or without
|
9
|
+
# modification, are permitted provided that the following conditions are met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
15
|
+
# this list of conditions and the following disclaimer in the documentation
|
16
|
+
# and/or other materials provided with the distribution.
|
17
|
+
#
|
18
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
19
|
+
# may be used to endorse or promote products derived from this software without
|
20
|
+
# specific prior written permission from the respective party.
|
21
|
+
#
|
22
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
23
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
24
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
25
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
28
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
29
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
31
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
32
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
33
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
34
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
35
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
36
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
37
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
|
+
# *******************************************************************************
|
39
|
+
require 'buildingsync/helpers/helper'
|
40
|
+
require 'buildingsync/helpers/xml_get_set'
|
41
|
+
|
42
|
+
module BuildingSync
|
43
|
+
# HVACSystem class
|
44
|
+
class HVACSystem < BuildingSystem
|
45
|
+
include BuildingSync::Helper
|
46
|
+
include BuildingSync::XmlGetSet
|
47
|
+
# initialize
|
48
|
+
# @param system_element [REXML::Element]
|
49
|
+
# @param ns [String]
|
50
|
+
def initialize(base_xml, ns = 'auc')
|
51
|
+
@base_xml = base_xml
|
52
|
+
@ns = ns
|
53
|
+
|
54
|
+
help_element_class_type_check(base_xml, 'HVACSystem')
|
55
|
+
|
56
|
+
# code to initialize
|
57
|
+
read_xml
|
58
|
+
end
|
59
|
+
|
60
|
+
# read xml
|
61
|
+
def read_xml; end
|
62
|
+
|
63
|
+
def get_linked_ids; end
|
64
|
+
|
65
|
+
# get principal hvac system type
|
66
|
+
# @return [String]
|
67
|
+
def get_principal_hvac_system_type
|
68
|
+
return xget_text('PrincipalHVACSystemType')
|
69
|
+
end
|
70
|
+
|
71
|
+
# adding the principal hvac system type to the hvac systems, overwrite existing values or create new elements if none are present
|
72
|
+
# @param id [String]
|
73
|
+
# @param principal_hvac_type [String]
|
74
|
+
def set_principal_hvac_system_type(principal_hvac_type)
|
75
|
+
xset_or_create('PrincipalHVACSystemType', principal_hvac_type)
|
76
|
+
end
|
77
|
+
|
78
|
+
# add exhaust
|
79
|
+
# @param model [OpenStudio::Model]
|
80
|
+
# @param standard [Standard]
|
81
|
+
# @param kitchen_makeup [String]
|
82
|
+
# @param remove_objects [Boolean]
|
83
|
+
def add_exhaust(model, standard, kitchen_makeup, remove_objects)
|
84
|
+
# remove exhaust objects
|
85
|
+
if remove_objects
|
86
|
+
model.getFanZoneExhausts.each(&:remove)
|
87
|
+
end
|
88
|
+
|
89
|
+
zone_exhaust_fans = standard.model_add_exhaust(model, kitchen_makeup) # second argument is strategy for finding makeup zones for exhaust zones
|
90
|
+
zone_exhaust_fans.each do |k, v|
|
91
|
+
max_flow_rate_ip = OpenStudio.convert(k.maximumFlowRate.get, 'm^3/s', 'cfm').get
|
92
|
+
if v.key?(:zone_mixing)
|
93
|
+
zone_mixing = v[:zone_mixing]
|
94
|
+
mixing_source_zone_name = zone_mixing.sourceZone.get.name
|
95
|
+
mixing_design_flow_rate_ip = OpenStudio.convert(zone_mixing.designFlowRate.get, 'm^3/s', 'cfm').get
|
96
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.HVACSystem.add_exhaust', "Adding #{OpenStudio.toNeatString(max_flow_rate_ip, 0, true)} (cfm) of exhaust to #{k.thermalZone.get.name}, with #{OpenStudio.toNeatString(mixing_design_flow_rate_ip, 0, true)} (cfm) of makeup air from #{mixing_source_zone_name}")
|
97
|
+
else
|
98
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.HVACSystem.add_exhaust', "Adding #{OpenStudio.toNeatString(max_flow_rate_ip, 0, true)} (cfm) of exhaust to #{k.thermalZone.get.name}")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
return true
|
102
|
+
end
|
103
|
+
|
104
|
+
# add thermostats
|
105
|
+
# @param model [OpenStudio::Model]
|
106
|
+
# @param standard [Standard]
|
107
|
+
# @param remove_objects [Boolean]
|
108
|
+
def add_thermostats(model, standard, remove_objects)
|
109
|
+
# remove thermostats
|
110
|
+
if remove_objects
|
111
|
+
model.getThermostatSetpointDualSetpoints.each(&:remove)
|
112
|
+
end
|
113
|
+
|
114
|
+
model.getSpaceTypes.each do |space_type|
|
115
|
+
# create thermostat schedules
|
116
|
+
# apply internal load schedules
|
117
|
+
# the last bool test it to make thermostat schedules. They are added to the model but not assigned
|
118
|
+
standard.space_type_apply_internal_load_schedules(space_type, false, false, false, false, false, false, true)
|
119
|
+
|
120
|
+
# identify thermal thermostat and apply to zones (apply_internal_load_schedules names )
|
121
|
+
model.getThermostatSetpointDualSetpoints.each do |thermostat|
|
122
|
+
next if !thermostat.name.to_s.include?(space_type.name.to_s)
|
123
|
+
if !thermostat.coolingSetpointTemperatureSchedule.is_initialized
|
124
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.HVACSystem.add_thermostats', "#{thermostat.name} has no cooling setpoint.")
|
125
|
+
end
|
126
|
+
if !thermostat.heatingSetpointTemperatureSchedule.is_initialized
|
127
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.HVACSystem.add_thermostats', "#{thermostat.name} has no heating setpoint.")
|
128
|
+
end
|
129
|
+
|
130
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.HVACSystem.add_thermostats', "Assigning #{thermostat.name} to thermal zones with #{space_type.name} assigned.")
|
131
|
+
puts "BuildingSync.HVACSystem.add_thermostats - Assigning #{thermostat.name} to thermal zones with #{space_type.name} assigned."
|
132
|
+
space_type.spaces.each do |space|
|
133
|
+
next if !space.thermalZone.is_initialized
|
134
|
+
|
135
|
+
space.thermalZone.get.setThermostatSetpointDualSetpoint(thermostat)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
puts "ThermalZones: #{model.getThermalZones.size}"
|
140
|
+
puts "ThermostatDSPs: #{model.getThermostatSetpointDualSetpoints.size}"
|
141
|
+
add_setpoints_to_thermostats_if_none(model)
|
142
|
+
return true
|
143
|
+
end
|
144
|
+
|
145
|
+
# @return [Boolean] true if ALL thermostats have heating and cooling setpoints
|
146
|
+
def add_setpoints_to_thermostats_if_none(model)
|
147
|
+
successful = true
|
148
|
+
|
149
|
+
# seperate out thermostats that need heating vs. cooling schedules
|
150
|
+
tstats_cooling = []
|
151
|
+
tstats_heating = []
|
152
|
+
model.getThermalZones.each do |tz|
|
153
|
+
if tz.thermostatSetpointDualSetpoint.is_initialized
|
154
|
+
tstat = tz.thermostatSetpointDualSetpoint.get
|
155
|
+
tstats_cooling << tstat if !tstat.coolingSetpointTemperatureSchedule.is_initialized
|
156
|
+
tstats_heating << tstat if !tstat.heatingSetpointTemperatureSchedule.is_initialized
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
puts "BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none - (#{tstats_cooling.size}) thermostats needing cooling schedule"
|
161
|
+
puts "BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none - (#{tstats_heating.size}) thermostats needing heating schedule"
|
162
|
+
|
163
|
+
htg_setpoints = [
|
164
|
+
# [Time.new(days, hours, mins seconds), temp_value_celsius]
|
165
|
+
[OpenStudio::Time.new(0, 9, 0, 0), 17],
|
166
|
+
[OpenStudio::Time.new(0, 17, 0, 0), 20],
|
167
|
+
[OpenStudio::Time.new(0, 24, 0, 0), 17]
|
168
|
+
]
|
169
|
+
clg_setpoints = [
|
170
|
+
# [Time.new(days, hours, mins seconds), temp_value_celsius]
|
171
|
+
[OpenStudio::Time.new(0, 9, 0, 0), 23],
|
172
|
+
[OpenStudio::Time.new(0, 17, 0, 0), 20],
|
173
|
+
[OpenStudio::Time.new(0, 24, 0, 0), 23]
|
174
|
+
]
|
175
|
+
|
176
|
+
heating_sp_schedule = create_schedule_ruleset(model, htg_setpoints, 'Thermostat Heating SP')
|
177
|
+
cooling_sp_schedule = create_schedule_ruleset(model, clg_setpoints, 'Thermostat Cooling SP')
|
178
|
+
|
179
|
+
tstats_cooling.each do |thermostat|
|
180
|
+
success = thermostat.setCoolingSetpointTemperatureSchedule(cooling_sp_schedule)
|
181
|
+
if success
|
182
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none', "Cooling Schedule (#{cooling_sp_schedule.nameString}) added to Thermostat: #{thermostat.nameString}")
|
183
|
+
puts "BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none - Cooling Schedule (#{cooling_sp_schedule.nameString}) added to Thermostat: #{thermostat.nameString}"
|
184
|
+
else
|
185
|
+
successful = false
|
186
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none', "No Cooling Schedule for Thermostat: #{thermostat.nameString}")
|
187
|
+
puts "BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none - No Cooling Schedule for Thermostat: #{thermostat.nameString}"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
tstats_heating.each do |thermostat|
|
192
|
+
success = thermostat.setHeatingSetpointTemperatureSchedule(heating_sp_schedule)
|
193
|
+
if success
|
194
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none', "Heating Schedule (#{heating_sp_schedule.nameString}) added to Thermostat: #{thermostat.nameString}")
|
195
|
+
puts "BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none - Heating Schedule (#{heating_sp_schedule.nameString}) added to Thermostat: #{thermostat.nameString}"
|
196
|
+
else
|
197
|
+
successful = false
|
198
|
+
OpenStudio.logFree(OpenStudio::Warn, 'BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none', "No Heating Schedule for Thermostat: #{thermostat.nameString}")
|
199
|
+
puts "BuildingSync.HVACSystem.add_setpoints_to_thermostats_if_none - No Heating Schedule for Thermostat: #{thermostat.nameString}"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
return successful
|
203
|
+
end
|
204
|
+
|
205
|
+
# @param model [OpenStudio::Model::Model]
|
206
|
+
# @param values [Array<Array<OpenStudio::Time, Float>>] [[cutoff_time, value_until_cutoff]]
|
207
|
+
# @return [OpenStudio::Model::ScheduleRuleset] a new schedule ruleset with values added to the default day
|
208
|
+
def create_schedule_ruleset(model, values, name)
|
209
|
+
ruleset = OpenStudio::Model::ScheduleRuleset.new(model)
|
210
|
+
ruleset.setName(name)
|
211
|
+
dd = ruleset.defaultDaySchedule
|
212
|
+
values.each do |v|
|
213
|
+
dd.addValue(v[0], v[1])
|
214
|
+
end
|
215
|
+
return ruleset
|
216
|
+
end
|
217
|
+
|
218
|
+
# map principal hvac system type to cbecs system type
|
219
|
+
# @param principal_hvac_system_type [String]
|
220
|
+
# @param fallback_system_type [String] the default system_type to use if the other is not found
|
221
|
+
# @return [String]
|
222
|
+
def map_to_cbecs(principal_hvac_system_type, fallback_system_type)
|
223
|
+
case principal_hvac_system_type
|
224
|
+
when 'Packaged Terminal Air Conditioner'
|
225
|
+
return 'PTAC with hot water heat'
|
226
|
+
when 'Packaged Terminal Heat Pump'
|
227
|
+
return 'PTHP'
|
228
|
+
when 'Packaged Rooftop Air Conditioner'
|
229
|
+
return 'PSZ-AC with gas coil heat'
|
230
|
+
when 'Packaged Rooftop Heat Pump'
|
231
|
+
return 'PSZ-HP'
|
232
|
+
when 'Packaged Rooftop VAV with Hot Water Reheat'
|
233
|
+
return 'PVAV with reheat'
|
234
|
+
when 'Packaged Rooftop VAV with Electric Reheat'
|
235
|
+
return 'PVAV with PFP boxes'
|
236
|
+
when 'VAV with Hot Water Reheat'
|
237
|
+
return 'VAV with reheat'
|
238
|
+
when 'VAV with Electric Reheat'
|
239
|
+
return 'VAV with PFP boxes'
|
240
|
+
else
|
241
|
+
OpenStudio.logFree(OpenStudio::Error, 'BuildingSync.HVACSystem.map_to_cbecs', "HVACSystem ID: #{xget_id}: No mapping for #{principal_hvac_system_type} to CBECS. Using the system type from standards: #{fallback_system_type}")
|
242
|
+
return fallback_system_type
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# add hvac
|
247
|
+
# @param model [OpenStudio::Model]
|
248
|
+
# @param zone_hash [hash]
|
249
|
+
# @param standard [Standard]
|
250
|
+
# @param system_type [String]
|
251
|
+
# @param hvac_delivery_type [String]
|
252
|
+
# @param htg_src [String]
|
253
|
+
# @param clg_src [String]
|
254
|
+
# @param remove_objects [Boolean]
|
255
|
+
# @return [Boolean]
|
256
|
+
def add_hvac(model, zone_hash, standard, system_type, hvac_delivery_type = 'Forced Air', htg_src = 'NaturalGas', clg_src = 'Electricity', remove_objects = false)
|
257
|
+
# remove HVAC objects
|
258
|
+
if remove_objects
|
259
|
+
standard.model_remove_prm_hvac(model)
|
260
|
+
end
|
261
|
+
|
262
|
+
puts "HVAC System ID: #{xget_id}. System_type derived from standards: #{system_type} and principal hvac system type override is: #{get_principal_hvac_system_type}"
|
263
|
+
temp = get_principal_hvac_system_type
|
264
|
+
if !temp.nil? && !temp.empty?
|
265
|
+
previous_system_type = system_type
|
266
|
+
system_type = map_to_cbecs(get_principal_hvac_system_type, previous_system_type)
|
267
|
+
OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.HVACSystem.add_hvac', "HVAC System ID: #{xget_id}. System type derived from standards: #{previous_system_type}, overriden to #{system_type}")
|
268
|
+
end
|
269
|
+
|
270
|
+
case system_type
|
271
|
+
when 'Inferred'
|
272
|
+
|
273
|
+
# Get the hvac delivery type enum
|
274
|
+
hvac_delivery = case hvac_delivery_type
|
275
|
+
when 'Forced Air'
|
276
|
+
'air'
|
277
|
+
when 'Hydronic'
|
278
|
+
'hydronic'
|
279
|
+
end
|
280
|
+
|
281
|
+
# Group the zones by occupancy type. Only split out
|
282
|
+
# non-dominant groups if their total area exceeds the limit.
|
283
|
+
sys_groups = standard.model_group_zones_by_type(model, OpenStudio.convert(20_000, 'ft^2', 'm^2').get)
|
284
|
+
|
285
|
+
# For each group, infer the HVAC system type.
|
286
|
+
sys_groups.each do |sys_group|
|
287
|
+
# Infer the principal system type
|
288
|
+
# OpenStudio.logFree(OpenStudio::Info, 'BuildingSync.Facility.create_building_system', "template = #{template}, climate_zone = #{climate_zone}, occ_type = #{sys_group['type']}, hvac_delivery = #{hvac_delivery}, htg_src = #{htg_src}, clg_src = #{clg_src}, area_ft2 = #{sys_group['area_ft2']}, num_stories = #{sys_group['stories']}")
|
289
|
+
sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel = standard.model_typical_hvac_system_type(model,
|
290
|
+
climate_zone,
|
291
|
+
sys_group['type'],
|
292
|
+
hvac_delivery,
|
293
|
+
htg_src,
|
294
|
+
clg_src,
|
295
|
+
OpenStudio.convert(sys_group['area_ft2'], 'ft^2', 'm^2').get,
|
296
|
+
sys_group['stories'])
|
297
|
+
|
298
|
+
# Infer the secondary system type for multizone systems
|
299
|
+
sec_sys_type = case sys_type
|
300
|
+
when 'PVAV Reheat', 'VAV Reheat'
|
301
|
+
'PSZ-AC'
|
302
|
+
when 'PVAV PFP Boxes', 'VAV PFP Boxes'
|
303
|
+
'PSZ-HP'
|
304
|
+
else
|
305
|
+
sys_type # same as primary system type
|
306
|
+
end
|
307
|
+
|
308
|
+
# Group zones by story
|
309
|
+
story_zone_lists = standard.model_group_zones_by_story(model, sys_group['zones'])
|
310
|
+
|
311
|
+
# On each story, add the primary system to the primary zones
|
312
|
+
# and add the secondary system to any zones that are different.
|
313
|
+
story_zone_lists.each do |story_group|
|
314
|
+
# Differentiate primary and secondary zones, based on
|
315
|
+
# operating hours and internal loads (same as 90.1 PRM)
|
316
|
+
pri_sec_zone_lists = standard.model_differentiate_primary_secondary_thermal_zones(model, story_group)
|
317
|
+
# Add the primary system to the primary zones
|
318
|
+
standard.model_add_hvac_system(model, sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, pri_sec_zone_lists['primary'])
|
319
|
+
# Add the secondary system to the secondary zones (if any)
|
320
|
+
if !pri_sec_zone_lists['secondary'].empty?
|
321
|
+
standard.model_add_hvac_system(model, sec_sys_type, central_htg_fuel, zone_htg_fuel, clg_fuel, pri_sec_zone_lists['secondary'])
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
else
|
326
|
+
# Group the zones by story
|
327
|
+
story_groups = standard.model_group_zones_by_story(model, model.getThermalZones)
|
328
|
+
|
329
|
+
# Add the user specified HVAC system for each story.
|
330
|
+
# Single-zone systems will get one per zone.
|
331
|
+
story_groups.each do |zones|
|
332
|
+
new_system_type = get_system_type_from_zone(zone_hash, zones, system_type)
|
333
|
+
puts "setting system: #{new_system_type} for zone names: #{help_get_zone_name_list(zones)}"
|
334
|
+
model.add_cbecs_hvac_system(standard, new_system_type, zones)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
return true
|
338
|
+
end
|
339
|
+
|
340
|
+
# get system type from zone
|
341
|
+
# @param zone_hash [hash]
|
342
|
+
# @param zones [array<OpenStudio::Model::ThermalZone>]
|
343
|
+
# @param system_type [String]
|
344
|
+
# @return [String]
|
345
|
+
def get_system_type_from_zone(zone_hash, zones, system_type)
|
346
|
+
zone_hash&.each do |id, zone_list|
|
347
|
+
zone_name_list = help_get_zone_name_list(zone_list)
|
348
|
+
zones.each do |zone|
|
349
|
+
if zone_name_list.include? zone.name.get
|
350
|
+
return map_to_cbecs(get_principal_hvac_system_type, system_type)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
return system_type
|
355
|
+
end
|
356
|
+
|
357
|
+
# apply sizing and assumptions
|
358
|
+
# @param model [OpenStudio::Model]
|
359
|
+
# @param output_path [String]
|
360
|
+
# @param standard [Standard]
|
361
|
+
# @param primary_bldg_type [String]
|
362
|
+
# @param system_type [String]
|
363
|
+
# @param climate_zone [String]
|
364
|
+
# @return [Boolean]
|
365
|
+
def apply_sizing_and_assumptions(model, output_path, standard, primary_bldg_type, system_type, climate_zone)
|
366
|
+
case system_type
|
367
|
+
when 'Ideal Air Loads'
|
368
|
+
|
369
|
+
else
|
370
|
+
# Set the heating and cooling sizing parameters
|
371
|
+
standard.model_apply_prm_sizing_parameters(model)
|
372
|
+
|
373
|
+
# Perform a sizing run
|
374
|
+
if standard.model_run_sizing_run(model, "#{output_path}/SR") == false
|
375
|
+
return false
|
376
|
+
end
|
377
|
+
|
378
|
+
# If there are any multizone systems, reset damper positions
|
379
|
+
# to achieve a 60% ventilation effectiveness minimum for the system
|
380
|
+
# following the ventilation rate procedure from 62.1
|
381
|
+
standard.model_apply_multizone_vav_outdoor_air_sizing(model)
|
382
|
+
|
383
|
+
# Apply the prototype HVAC assumptions
|
384
|
+
standard.model_apply_prototype_hvac_assumptions(model, primary_bldg_type, climate_zone)
|
385
|
+
|
386
|
+
# Apply the HVAC efficiency standard
|
387
|
+
standard.model_apply_hvac_efficiency_standard(model, climate_zone)
|
388
|
+
end
|
389
|
+
return true
|
390
|
+
end
|
391
|
+
|
392
|
+
# principal hvac system type
|
393
|
+
attr_reader :principal_hvac_system_type
|
394
|
+
end
|
395
|
+
end
|