openstudio-extension 0.7.1 → 0.8.0
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 +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +14 -0
- data/LICENSE.md +1 -1
- data/README.md +2 -0
- data/lib/openstudio/extension/runner.rb +12 -8
- data/lib/openstudio/extension/runner_config.rb +33 -6
- data/lib/openstudio/extension/version.rb +1 -1
- data/openstudio-extension.gemspec +6 -6
- metadata +15 -66
- data/lib/openstudio/extension/core/CreateResults.rb +0 -1033
- data/lib/openstudio/extension/core/check_air_sys_temps.rb +0 -160
- data/lib/openstudio/extension/core/check_calibration.rb +0 -125
- data/lib/openstudio/extension/core/check_cond_zns.rb +0 -54
- data/lib/openstudio/extension/core/check_domestic_hot_water.rb +0 -304
- data/lib/openstudio/extension/core/check_envelope_conductance.rb +0 -423
- data/lib/openstudio/extension/core/check_eui_by_end_use.rb +0 -132
- data/lib/openstudio/extension/core/check_eui_reasonableness.rb +0 -105
- data/lib/openstudio/extension/core/check_fan_pwr.rb +0 -68
- data/lib/openstudio/extension/core/check_internal_loads.rb +0 -363
- data/lib/openstudio/extension/core/check_mech_sys_capacity.rb +0 -196
- data/lib/openstudio/extension/core/check_mech_sys_efficiency.rb +0 -296
- data/lib/openstudio/extension/core/check_mech_sys_part_load_eff.rb +0 -434
- data/lib/openstudio/extension/core/check_mech_sys_type.rb +0 -109
- data/lib/openstudio/extension/core/check_part_loads.rb +0 -421
- data/lib/openstudio/extension/core/check_placeholder.rb +0 -45
- data/lib/openstudio/extension/core/check_plant_cap.rb +0 -93
- data/lib/openstudio/extension/core/check_plant_temps.rb +0 -129
- data/lib/openstudio/extension/core/check_plenum_loads.rb +0 -57
- data/lib/openstudio/extension/core/check_pump_pwr.rb +0 -78
- data/lib/openstudio/extension/core/check_sch_coord.rb +0 -211
- data/lib/openstudio/extension/core/check_schedules.rb +0 -281
- data/lib/openstudio/extension/core/check_simultaneous_heating_and_cooling.rb +0 -128
- data/lib/openstudio/extension/core/check_supply_air_and_thermostat_temp_difference.rb +0 -118
- data/lib/openstudio/extension/core/check_weather_files.rb +0 -102
- data/lib/openstudio/extension/core/deer_vintages.rb +0 -281
- data/lib/openstudio/extension/core/os_lib_aedg_measures.rb +0 -461
- data/lib/openstudio/extension/core/os_lib_constructions.rb +0 -353
- data/lib/openstudio/extension/core/os_lib_geometry.rb +0 -1169
- data/lib/openstudio/extension/core/os_lib_helper_methods.rb +0 -383
- data/lib/openstudio/extension/core/os_lib_hvac.rb +0 -2163
- data/lib/openstudio/extension/core/os_lib_lighting_and_equipment.rb +0 -184
- data/lib/openstudio/extension/core/os_lib_model_generation.rb +0 -3584
- data/lib/openstudio/extension/core/os_lib_model_simplification.rb +0 -1019
- data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +0 -135
- data/lib/openstudio/extension/core/os_lib_reporting_qaqc.rb +0 -170
- data/lib/openstudio/extension/core/os_lib_schedules.rb +0 -933
@@ -1,421 +0,0 @@
|
|
1
|
-
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
-
# See also https://openstudio.net/license
|
4
|
-
# *******************************************************************************
|
5
|
-
|
6
|
-
module OsLib_QAQC
|
7
|
-
# Bin the hourly part load ratios into 10% bins
|
8
|
-
def bin_part_loads_by_ten_pcts(hrly_plrs)
|
9
|
-
bins = Array.new(10, 0)
|
10
|
-
op_hrs = 0.0
|
11
|
-
hrly_plrs.each do |plr|
|
12
|
-
op_hrs += 1.0 if plr > 0
|
13
|
-
if plr <= 0.1 # add below-zero % PLRs to final bin
|
14
|
-
bins[0] += 1
|
15
|
-
elsif plr > 0.1 && plr <= 0.2
|
16
|
-
bins[1] += 1
|
17
|
-
elsif plr > 0.2 && plr <= 0.3
|
18
|
-
bins[2] += 1
|
19
|
-
elsif plr > 0.3 && plr <= 0.4
|
20
|
-
bins[3] += 1
|
21
|
-
elsif plr > 0.4 && plr <= 0.5
|
22
|
-
bins[4] += 1
|
23
|
-
elsif plr > 0.5 && plr <= 0.6
|
24
|
-
bins[5] += 1
|
25
|
-
elsif plr > 0.6 && plr <= 0.7
|
26
|
-
bins[6] += 1
|
27
|
-
elsif plr > 0.7 && plr <= 0.8
|
28
|
-
bins[7] += 1
|
29
|
-
elsif plr > 0.8 && plr <= 0.9
|
30
|
-
bins[8] += 1
|
31
|
-
elsif plr > 0.9 # add over-100% PLRs to final bin
|
32
|
-
bins[9] += 1
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Convert bins from hour counts to % of operating hours.
|
37
|
-
bins.each_with_index do |bin, i|
|
38
|
-
bins[i] = bins[i] / op_hrs
|
39
|
-
end
|
40
|
-
|
41
|
-
return bins
|
42
|
-
end
|
43
|
-
|
44
|
-
# Check primary heating and cooling equipment part load ratios
|
45
|
-
# to find equipment that is significantly oversized or undersized.
|
46
|
-
def check_part_loads(category, target_standard, max_pct_delta = 0.1, name_only = false)
|
47
|
-
# summary of the check
|
48
|
-
check_elems = OpenStudio::AttributeVector.new
|
49
|
-
check_elems << OpenStudio::Attribute.new('name', 'Part Load')
|
50
|
-
check_elems << OpenStudio::Attribute.new('category', category)
|
51
|
-
check_elems << OpenStudio::Attribute.new('description', 'Check that equipment operates at reasonable part load ranges.')
|
52
|
-
|
53
|
-
# stop here if only name is requested this is used to populate display name for arguments
|
54
|
-
if name_only == true
|
55
|
-
results = []
|
56
|
-
check_elems.each do |elem|
|
57
|
-
results << elem.valueAsString
|
58
|
-
end
|
59
|
-
return results
|
60
|
-
end
|
61
|
-
|
62
|
-
std = Standard.build(target_standard)
|
63
|
-
|
64
|
-
begin
|
65
|
-
# Establish limits for % of operating hrs expected above 90% part load
|
66
|
-
expected_pct_hrs_above_90 = 0.1
|
67
|
-
|
68
|
-
# get the weather file run period (as opposed to design day run period)
|
69
|
-
ann_env_pd = nil
|
70
|
-
@sql.availableEnvPeriods.each do |env_pd|
|
71
|
-
env_type = @sql.environmentType(env_pd)
|
72
|
-
if env_type.is_initialized
|
73
|
-
if env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod')
|
74
|
-
ann_env_pd = env_pd
|
75
|
-
break
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# only try to get the annual timeseries if an annual simulation was run
|
81
|
-
if ann_env_pd.nil?
|
82
|
-
check_elems << OpenStudio::Attribute.new('flag', 'Cannot find the annual simulation run period, cannot check equipment part load ratios.')
|
83
|
-
return check_elem
|
84
|
-
end
|
85
|
-
|
86
|
-
# Boilers
|
87
|
-
@model.getBoilerHotWaters.each do |equip|
|
88
|
-
# Get the timeseries part load ratio data
|
89
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
90
|
-
time_step = 'Hourly'
|
91
|
-
variable_name = 'Boiler Part Load Ratio'
|
92
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
93
|
-
if ts.empty?
|
94
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
95
|
-
next
|
96
|
-
end
|
97
|
-
|
98
|
-
# Convert to array
|
99
|
-
ts = ts.get.values
|
100
|
-
plrs = []
|
101
|
-
for i in 0..(ts.size - 1)
|
102
|
-
plrs << ts[i]
|
103
|
-
end
|
104
|
-
|
105
|
-
# Bin part load ratios
|
106
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
107
|
-
|
108
|
-
# Check top-end part load ratio bins
|
109
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
110
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# Chillers
|
115
|
-
@model.getChillerElectricEIRs.each do |equip|
|
116
|
-
# Get the timeseries part load ratio data
|
117
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
118
|
-
time_step = 'Hourly'
|
119
|
-
variable_name = 'Chiller Part Load Ratio'
|
120
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
121
|
-
if ts.empty?
|
122
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
123
|
-
next
|
124
|
-
end
|
125
|
-
|
126
|
-
# Convert to array
|
127
|
-
ts = ts.get.values
|
128
|
-
plrs = []
|
129
|
-
for i in 0..(ts.size - 1)
|
130
|
-
plrs << ts[i]
|
131
|
-
end
|
132
|
-
|
133
|
-
# Bin part load ratios
|
134
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
135
|
-
|
136
|
-
# Check top-end part load ratio bins
|
137
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
138
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# Cooling Towers (Single Speed)
|
143
|
-
@model.getCoolingTowerSingleSpeeds.each do |equip|
|
144
|
-
# Get the design fan power
|
145
|
-
if equip.fanPoweratDesignAirFlowRate.is_initialized
|
146
|
-
dsn_pwr = equip.fanPoweratDesignAirFlowRate.get
|
147
|
-
elsif equip.autosizedFanPoweratDesignAirFlowRate.is_initialized
|
148
|
-
dsn_pwr = equip.autosizedFanPoweratDesignAirFlowRate.get
|
149
|
-
else
|
150
|
-
check_elems << OpenStudio::Attribute.new('flag', "Could not determine peak power for #{equip.name}, cannot check part load ratios.")
|
151
|
-
next
|
152
|
-
end
|
153
|
-
|
154
|
-
# Get the timeseries fan power
|
155
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
156
|
-
time_step = 'Hourly'
|
157
|
-
variable_name = 'Cooling Tower Fan Electric Power'
|
158
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
159
|
-
if ts.empty?
|
160
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
161
|
-
next
|
162
|
-
end
|
163
|
-
|
164
|
-
# Convert to array
|
165
|
-
ts = ts.get.values
|
166
|
-
plrs = []
|
167
|
-
for i in 0..(ts.size - 1)
|
168
|
-
plrs << ts[i] / dsn_pwr.to_f
|
169
|
-
end
|
170
|
-
|
171
|
-
# Bin part load ratios
|
172
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
173
|
-
|
174
|
-
# Check top-end part load ratio bins
|
175
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
176
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
# Cooling Towers (Two Speed)
|
181
|
-
@model.getCoolingTowerTwoSpeeds.each do |equip|
|
182
|
-
# Get the design fan power
|
183
|
-
if equip.highFanSpeedFanPower.is_initialized
|
184
|
-
dsn_pwr = equip.highFanSpeedFanPower.get
|
185
|
-
elsif equip.autosizedHighFanSpeedFanPower.is_initialized
|
186
|
-
dsn_pwr = equip.autosizedHighFanSpeedFanPower.get
|
187
|
-
else
|
188
|
-
check_elems << OpenStudio::Attribute.new('flag', "Could not determine peak power for #{equip.name}, cannot check part load ratios.")
|
189
|
-
next
|
190
|
-
end
|
191
|
-
|
192
|
-
# Get the timeseries fan power
|
193
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
194
|
-
time_step = 'Hourly'
|
195
|
-
variable_name = 'Cooling Tower Fan Electric Power'
|
196
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
197
|
-
if ts.empty?
|
198
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
199
|
-
next
|
200
|
-
end
|
201
|
-
|
202
|
-
# Convert to array
|
203
|
-
ts = ts.get.values
|
204
|
-
plrs = []
|
205
|
-
for i in 0..(ts.size - 1)
|
206
|
-
plrs << ts[i] / dsn_pwr.to_f
|
207
|
-
end
|
208
|
-
|
209
|
-
# Bin part load ratios
|
210
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
211
|
-
|
212
|
-
# Check top-end part load ratio bins
|
213
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
214
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
# Cooling Towers (Variable Speed)
|
219
|
-
@model.getCoolingTowerVariableSpeeds.each do |equip|
|
220
|
-
# Get the design fan power
|
221
|
-
if equip.designFanPower.is_initialized
|
222
|
-
dsn_pwr = equip.designFanPower.get
|
223
|
-
elsif equip.autosizedDesignFanPower.is_initialized
|
224
|
-
dsn_pwr = equip.autosizedDesignFanPower.get
|
225
|
-
else
|
226
|
-
check_elems << OpenStudio::Attribute.new('flag', "Could not determine peak power for #{equip.name}, cannot check part load ratios.")
|
227
|
-
next
|
228
|
-
end
|
229
|
-
|
230
|
-
# Get the timeseries fan power
|
231
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
232
|
-
time_step = 'Hourly'
|
233
|
-
variable_name = 'Cooling Tower Fan Electric Power'
|
234
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
235
|
-
if ts.empty?
|
236
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
237
|
-
next
|
238
|
-
end
|
239
|
-
|
240
|
-
# Convert to array
|
241
|
-
ts = ts.get.values
|
242
|
-
plrs = []
|
243
|
-
for i in 0..(ts.size - 1)
|
244
|
-
plrs << ts[i] / dsn_pwr.to_f
|
245
|
-
end
|
246
|
-
|
247
|
-
# Bin part load ratios
|
248
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
249
|
-
|
250
|
-
# Check top-end part load ratio bins
|
251
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
252
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
# DX Cooling Coils (Single Speed)
|
257
|
-
@model.getCoilCoolingDXSingleSpeeds.each do |equip|
|
258
|
-
# Get the design coil capacity
|
259
|
-
if equip.grossRatedTotalCoolingCapacity.is_initialized
|
260
|
-
dsn_pwr = equip.grossRatedTotalCoolingCapacity.get
|
261
|
-
elsif equip.autosizedGrossRatedTotalCoolingCapacity.is_initialized
|
262
|
-
dsn_pwr = equip.autosizedGrossRatedTotalCoolingCapacity.get
|
263
|
-
else
|
264
|
-
check_elems << OpenStudio::Attribute.new('flag', "Could not determine capacity for #{equip.name}, cannot check part load ratios.")
|
265
|
-
next
|
266
|
-
end
|
267
|
-
|
268
|
-
# Get the timeseries coil capacity
|
269
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
270
|
-
time_step = 'Hourly'
|
271
|
-
variable_name = 'Cooling Coil Total Cooling Rate'
|
272
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
273
|
-
if ts.empty?
|
274
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
275
|
-
next
|
276
|
-
end
|
277
|
-
|
278
|
-
# Convert to array
|
279
|
-
ts = ts.get.values
|
280
|
-
plrs = []
|
281
|
-
for i in 0..(ts.size - 1)
|
282
|
-
plrs << ts[i] / dsn_pwr.to_f
|
283
|
-
end
|
284
|
-
|
285
|
-
# Bin part load ratios
|
286
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
287
|
-
|
288
|
-
# Check top-end part load ratio bins
|
289
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
290
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
# DX Cooling Coils (Two Speed)
|
295
|
-
@model.getCoilCoolingDXTwoSpeeds.each do |equip|
|
296
|
-
# Get the design coil capacity
|
297
|
-
if equip.ratedHighSpeedTotalCoolingCapacity.is_initialized
|
298
|
-
dsn_pwr = equip.ratedHighSpeedTotalCoolingCapacity.get
|
299
|
-
elsif equip.autosizedRatedHighSpeedTotalCoolingCapacity.is_initialized
|
300
|
-
dsn_pwr = equip.autosizedRatedHighSpeedTotalCoolingCapacity.get
|
301
|
-
else
|
302
|
-
check_elems << OpenStudio::Attribute.new('flag', "Could not determine capacity for #{equip.name}, cannot check part load ratios.")
|
303
|
-
next
|
304
|
-
end
|
305
|
-
|
306
|
-
# Get the timeseries coil capacity
|
307
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
308
|
-
time_step = 'Hourly'
|
309
|
-
variable_name = 'Cooling Coil Total Cooling Rate'
|
310
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
311
|
-
if ts.empty?
|
312
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
313
|
-
next
|
314
|
-
end
|
315
|
-
|
316
|
-
# Convert to array
|
317
|
-
ts = ts.get.values
|
318
|
-
plrs = []
|
319
|
-
for i in 0..(ts.size - 1)
|
320
|
-
plrs << ts[i] / dsn_pwr.to_f
|
321
|
-
end
|
322
|
-
|
323
|
-
# Bin part load ratios
|
324
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
325
|
-
|
326
|
-
# Check top-end part load ratio bins
|
327
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
328
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
# DX Cooling Coils (Variable Speed)
|
333
|
-
@model.getCoilCoolingDXVariableSpeeds.each do |equip|
|
334
|
-
# Get the design coil capacity
|
335
|
-
if equip.grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel.is_initialized
|
336
|
-
dsn_pwr = equip.grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel.get
|
337
|
-
elsif equip.autosizedGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel.is_initialized
|
338
|
-
dsn_pwr = equip.autosizedGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel.get
|
339
|
-
else
|
340
|
-
check_elems << OpenStudio::Attribute.new('flag', "Could not determine capacity for #{equip.name}, cannot check part load ratios.")
|
341
|
-
next
|
342
|
-
end
|
343
|
-
|
344
|
-
# Get the timeseries coil capacity
|
345
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
346
|
-
time_step = 'Hourly'
|
347
|
-
variable_name = 'Cooling Coil Total Cooling Rate'
|
348
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
349
|
-
if ts.empty?
|
350
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
351
|
-
next
|
352
|
-
end
|
353
|
-
|
354
|
-
# Convert to array
|
355
|
-
ts = ts.get.values
|
356
|
-
plrs = []
|
357
|
-
for i in 0..(ts.size - 1)
|
358
|
-
plrs << ts[i] / dsn_pwr.to_f
|
359
|
-
end
|
360
|
-
|
361
|
-
# Bin part load ratios
|
362
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
363
|
-
|
364
|
-
# Check top-end part load ratio bins
|
365
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
366
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
# Gas Heating Coils
|
371
|
-
@model.getCoilHeatingGass.each do |equip|
|
372
|
-
# Get the design coil capacity
|
373
|
-
if equip.nominalCapacity.is_initialized
|
374
|
-
dsn_pwr = equip.nominalCapacity.get
|
375
|
-
elsif equip.autosizedNominalCapacity.is_initialized
|
376
|
-
dsn_pwr = equip.autosizedNominalCapacity.get
|
377
|
-
else
|
378
|
-
check_elems << OpenStudio::Attribute.new('flag', "Could not determine capacity for #{equip.name}, cannot check part load ratios.")
|
379
|
-
next
|
380
|
-
end
|
381
|
-
|
382
|
-
# Get the timeseries coil capacity
|
383
|
-
key_value = equip.name.get.to_s.upcase # must be in all caps.
|
384
|
-
time_step = 'Hourly'
|
385
|
-
variable_name = 'Heating Coil Air Heating Rate'
|
386
|
-
ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value)
|
387
|
-
if ts.empty?
|
388
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{variable_name} Timeseries not found for #{key_value}.")
|
389
|
-
next
|
390
|
-
end
|
391
|
-
|
392
|
-
# Convert to array
|
393
|
-
ts = ts.get.values
|
394
|
-
plrs = []
|
395
|
-
for i in 0..(ts.size - 1)
|
396
|
-
plrs << ts[i] / dsn_pwr.to_f
|
397
|
-
end
|
398
|
-
|
399
|
-
# Bin part load ratios
|
400
|
-
pct_hrs_above_90 = bin_part_loads_by_ten_pcts(plrs)[9]
|
401
|
-
|
402
|
-
# Check top-end part load ratio bins
|
403
|
-
if ((pct_hrs_above_90 - expected_pct_hrs_above_90) / pct_hrs_above_90).abs > max_pct_delta
|
404
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{equip.name}, the actual hrs above 90% part load of #{(pct_hrs_above_90 * 100).round(2)}% is more than #{(max_pct_delta * 100.0).round(2)}% different from the expected #{(expected_pct_hrs_above_90 * 100).round(2)}% of hrs above 90% part load. This could indicate significantly oversized or undersized equipment.")
|
405
|
-
end
|
406
|
-
end
|
407
|
-
rescue StandardError => e
|
408
|
-
# brief description of ruby error
|
409
|
-
check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
|
410
|
-
|
411
|
-
# backtrace of ruby error for diagnostic use
|
412
|
-
if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
|
413
|
-
end
|
414
|
-
|
415
|
-
# add check_elms to new attribute
|
416
|
-
check_elem = OpenStudio::Attribute.new('check', check_elems)
|
417
|
-
|
418
|
-
return check_elem
|
419
|
-
# note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
|
420
|
-
end
|
421
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
-
# See also https://openstudio.net/license
|
4
|
-
# *******************************************************************************
|
5
|
-
|
6
|
-
module OsLib_QAQC
|
7
|
-
# include any general notes about QAQC method here
|
8
|
-
|
9
|
-
# checks the number of unmet hours in the model
|
10
|
-
def check_placeholder(category, name_only = false)
|
11
|
-
# summary of the check
|
12
|
-
check_elems = OpenStudio::AttributeVector.new
|
13
|
-
check_elems << OpenStudio::Attribute.new('name', 'Place Holder Check')
|
14
|
-
check_elems << OpenStudio::Attribute.new('category', category)
|
15
|
-
check_elems << OpenStudio::Attribute.new('description', 'This does nothing, it will just throw a flag until I add real check code to the method.')
|
16
|
-
|
17
|
-
# stop here if only name is requested this is used to populate display name for arguments
|
18
|
-
if name_only == true
|
19
|
-
results = []
|
20
|
-
check_elems.each do |elem|
|
21
|
-
results << elem.valueAsString
|
22
|
-
end
|
23
|
-
return results
|
24
|
-
end
|
25
|
-
|
26
|
-
begin
|
27
|
-
# TODO: - implement QAQC check code here
|
28
|
-
|
29
|
-
# remove this once code is written to do real checks
|
30
|
-
check_elems << OpenStudio::Attribute.new('flag', 'Code has not been implemented yet for this QAQC check')
|
31
|
-
rescue StandardError => e
|
32
|
-
# brief description of ruby error
|
33
|
-
check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
|
34
|
-
|
35
|
-
# backtrace of ruby error for diagnostic use
|
36
|
-
if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
|
37
|
-
end
|
38
|
-
|
39
|
-
# add check_elms to new attribute
|
40
|
-
check_elem = OpenStudio::Attribute.new('check', check_elems)
|
41
|
-
|
42
|
-
return check_elem
|
43
|
-
# note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
|
44
|
-
end
|
45
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
-
# See also https://openstudio.net/license
|
4
|
-
# *******************************************************************************
|
5
|
-
|
6
|
-
module OsLib_QAQC
|
7
|
-
# Check primary plant loop heating and cooling equipment capacity against
|
8
|
-
# coil loads to find equipment that is significantly oversized or undersized.
|
9
|
-
def check_plant_cap(category, target_standard, max_pct_delta = 0.1, name_only = false)
|
10
|
-
# summary of the check
|
11
|
-
check_elems = OpenStudio::AttributeVector.new
|
12
|
-
check_elems << OpenStudio::Attribute.new('name', 'Plant Capacity')
|
13
|
-
check_elems << OpenStudio::Attribute.new('category', category)
|
14
|
-
check_elems << OpenStudio::Attribute.new('description', 'Check that plant equipment capacity matches loads.')
|
15
|
-
|
16
|
-
# stop here if only name is requested this is used to populate display name for arguments
|
17
|
-
if name_only == true
|
18
|
-
results = []
|
19
|
-
check_elems.each do |elem|
|
20
|
-
results << elem.valueAsString
|
21
|
-
end
|
22
|
-
return results
|
23
|
-
end
|
24
|
-
|
25
|
-
std = Standard.build(target_standard)
|
26
|
-
|
27
|
-
begin
|
28
|
-
# Check the heating and cooling capacity of the plant loops against their coil loads
|
29
|
-
@model.getPlantLoops.each do |plant_loop|
|
30
|
-
# Heating capacity
|
31
|
-
htg_cap_w = std.plant_loop_total_heating_capacity(plant_loop)
|
32
|
-
|
33
|
-
# Cooling capacity
|
34
|
-
clg_cap_w = std.plant_loop_total_cooling_capacity(plant_loop)
|
35
|
-
|
36
|
-
# Heating and cooling loads
|
37
|
-
plant_loop.demandComponents.each do |dc|
|
38
|
-
# Get the load for each coil
|
39
|
-
htg_load_w = 0.0
|
40
|
-
clg_load_w = 0.0
|
41
|
-
obj_type = sc.iddObjectType.valueName.to_s
|
42
|
-
case obj_type
|
43
|
-
when 'OS_Coil_Heating_Water'
|
44
|
-
coil = sc.to_CoilHeatingWater.get
|
45
|
-
if coil.ratedCapacity.is_initialized
|
46
|
-
clg_load_w += coil.ratedCapacity.get
|
47
|
-
elsif coil.autosizedRatedCapacity.is_initialized
|
48
|
-
clg_load_w += coil.autosizedRatedCapacity.get
|
49
|
-
end
|
50
|
-
when 'OS_Coil_Cooling_Water'
|
51
|
-
coil = sc.to_CoilCoolingWater.get
|
52
|
-
if coil.autosizedDesignCoilLoad.is_initialized
|
53
|
-
clg_load_w += coil.autosizedDesignCoilLoad.get
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Don't check loops with no loads. These are probably
|
59
|
-
# SWH or non-typical loops that can't be checked by simple methods.
|
60
|
-
|
61
|
-
# Heating
|
62
|
-
if htg_load_w > 0
|
63
|
-
htg_cap_kbtu_per_hr = OpenStudio.convert(htg_cap_w, 'W', 'kBtu/hr').get.round(1)
|
64
|
-
htg_load_kbtu_per_hr = OpenStudio.convert(htg_load_w, 'W', 'kBtu/hr').get.round(1)
|
65
|
-
if ((htg_cap_w - htg_load_w) / htg_cap_w).abs > max_pct_delta
|
66
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{plant_loop.name}, the total heating capacity of #{htg_cap_kbtu_per_hr} kBtu/hr is more than #{(max_pct_delta * 100.0).round(2)}% different from the combined coil load of #{htg_load_kbtu_per_hr} kBtu/hr. This could indicate significantly oversized or undersized equipment.")
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# Cooling
|
71
|
-
if clg_load_w > 0
|
72
|
-
clg_cap_tons = OpenStudio.convert(clg_cap_w, 'W', 'ton').get.round(1)
|
73
|
-
clg_load_tons = OpenStudio.convert(clg_load_w, 'W', 'ton').get.round(1)
|
74
|
-
if ((clg_cap_w - clg_load_w) / clg_cap_w).abs > max_pct_delta
|
75
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{plant_loop.name}, the total cooling capacity of #{clg_cap_kbtu_per_hr} tons is more than #{(max_pct_delta * 100.0).round(2)}% different from the combined coil load of #{clg_load_kbtu_per_hr} tons. This could indicate significantly oversized or undersized equipment.")
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
rescue StandardError => e
|
80
|
-
# brief description of ruby error
|
81
|
-
check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
|
82
|
-
|
83
|
-
# backtrace of ruby error for diagnostic use
|
84
|
-
if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
|
85
|
-
end
|
86
|
-
|
87
|
-
# add check_elms to new attribute
|
88
|
-
check_elem = OpenStudio::Attribute.new('check', check_elems)
|
89
|
-
|
90
|
-
return check_elem
|
91
|
-
# note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
|
92
|
-
end
|
93
|
-
end
|