openstudio-extension 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +29 -26
- data/.rspec +3 -3
- data/.rubocop.yml +10 -9
- data/CHANGELOG.md +16 -0
- data/Gemfile +6 -6
- data/Jenkinsfile +10 -10
- data/README.md +251 -250
- data/Rakefile +119 -119
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/doc_templates/LICENSE.md +26 -26
- data/doc_templates/README.md.erb +41 -41
- data/doc_templates/copyright_erb.txt +35 -35
- data/doc_templates/copyright_js.txt +3 -3
- data/doc_templates/copyright_ruby.txt +33 -33
- data/init_templates/README.md +37 -37
- data/init_templates/gemspec.txt +32 -32
- data/init_templates/openstudio_module.rb +50 -50
- data/init_templates/spec.rb +47 -47
- data/init_templates/spec_helper.rb +49 -49
- data/init_templates/template_gemfile.txt +17 -17
- data/init_templates/template_rakefile.txt +15 -15
- data/init_templates/version.rb +40 -40
- data/lib/files/openstudio-extension-gem-test.ddy +536 -536
- data/lib/files/openstudio-extension-gem-test.epw +8768 -8768
- data/lib/files/openstudio-extension-gem-test.stat +554 -554
- data/lib/measures/openstudio_extension_test_measure/LICENSE.md +26 -26
- data/lib/measures/openstudio_extension_test_measure/README.md +26 -26
- data/lib/measures/openstudio_extension_test_measure/README.md.erb +41 -41
- data/lib/measures/openstudio_extension_test_measure/measure.rb +72 -72
- data/lib/measures/openstudio_extension_test_measure/measure.xml +83 -83
- data/lib/measures/openstudio_extension_test_measure/resources/os_lib_helper_methods.rb +399 -399
- data/lib/measures/openstudio_extension_test_measure/tests/{OpenStudioExtensionTestMeasure_Test.rb → openstudio_extension_test_measure_test.rb} +74 -75
- data/lib/openstudio-extension.rb +1 -1
- data/lib/openstudio/extension.rb +234 -229
- data/lib/openstudio/extension/core/CreateResults.rb +886 -886
- data/lib/openstudio/extension/core/check_air_sys_temps.rb +190 -190
- data/lib/openstudio/extension/core/check_calibration.rb +155 -155
- data/lib/openstudio/extension/core/check_cond_zns.rb +84 -84
- data/lib/openstudio/extension/core/check_domestic_hot_water.rb +334 -334
- data/lib/openstudio/extension/core/check_envelope_conductance.rb +453 -453
- data/lib/openstudio/extension/core/check_eui_by_end_use.rb +162 -162
- data/lib/openstudio/extension/core/check_eui_reasonableness.rb +135 -135
- data/lib/openstudio/extension/core/check_fan_pwr.rb +98 -98
- data/lib/openstudio/extension/core/check_internal_loads.rb +393 -393
- data/lib/openstudio/extension/core/check_mech_sys_capacity.rb +226 -226
- data/lib/openstudio/extension/core/check_mech_sys_efficiency.rb +326 -326
- data/lib/openstudio/extension/core/check_mech_sys_part_load_eff.rb +464 -464
- data/lib/openstudio/extension/core/check_mech_sys_type.rb +139 -139
- data/lib/openstudio/extension/core/check_part_loads.rb +451 -451
- data/lib/openstudio/extension/core/check_placeholder.rb +75 -75
- data/lib/openstudio/extension/core/check_plant_cap.rb +123 -123
- data/lib/openstudio/extension/core/check_plant_temps.rb +159 -159
- data/lib/openstudio/extension/core/check_plenum_loads.rb +87 -87
- data/lib/openstudio/extension/core/check_pump_pwr.rb +108 -108
- data/lib/openstudio/extension/core/check_sch_coord.rb +241 -241
- data/lib/openstudio/extension/core/check_schedules.rb +311 -311
- data/lib/openstudio/extension/core/check_simultaneous_heating_and_cooling.rb +158 -158
- data/lib/openstudio/extension/core/check_supply_air_and_thermostat_temp_difference.rb +148 -148
- data/lib/openstudio/extension/core/check_weather_files.rb +132 -132
- data/lib/openstudio/extension/core/deer_vintages.rb +311 -311
- data/lib/openstudio/extension/core/os_lib_aedg_measures.rb +491 -491
- data/lib/openstudio/extension/core/os_lib_cofee.rb +258 -258
- data/lib/openstudio/extension/core/os_lib_constructions.rb +378 -378
- data/lib/openstudio/extension/core/os_lib_geometry.rb +1022 -1022
- data/lib/openstudio/extension/core/os_lib_helper_methods.rb +399 -399
- data/lib/openstudio/extension/core/os_lib_hvac.rb +2171 -2171
- data/lib/openstudio/extension/core/os_lib_lighting_and_equipment.rb +214 -214
- data/lib/openstudio/extension/core/os_lib_model_generation.rb +817 -817
- data/lib/openstudio/extension/core/os_lib_model_simplification.rb +1049 -1049
- data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +165 -165
- data/lib/openstudio/extension/core/os_lib_reporting.rb +4651 -4651
- data/lib/openstudio/extension/core/os_lib_reporting_qaqc.rb +200 -200
- data/lib/openstudio/extension/core/os_lib_schedules.rb +963 -963
- data/lib/openstudio/extension/rake_task.rb +159 -149
- data/lib/openstudio/extension/runner.rb +667 -644
- data/lib/openstudio/extension/runner_config.rb +114 -0
- data/lib/openstudio/extension/version.rb +40 -40
- data/openstudio-extension.gemspec +34 -33
- metadata +39 -37
@@ -1,158 +1,158 @@
|
|
1
|
-
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
|
3
|
-
# All rights reserved.
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions are met:
|
6
|
-
#
|
7
|
-
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
-
# this list of conditions and the following disclaimer.
|
9
|
-
#
|
10
|
-
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
#
|
14
|
-
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
-
# may be used to endorse or promote products derived from this software without
|
16
|
-
# specific prior written permission from the respective party.
|
17
|
-
#
|
18
|
-
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
-
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
-
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
-
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
-
#
|
23
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
-
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
-
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
-
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
-
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
-
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
-
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
-
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
-
# *******************************************************************************
|
35
|
-
|
36
|
-
module OsLib_QAQC
|
37
|
-
# include any general notes about QAQC method here
|
38
|
-
|
39
|
-
# checks the number of unmet hours in the model
|
40
|
-
def check_simultaneous_heating_and_cooling(category, max_pass, name_only = false)
|
41
|
-
# summary of the check
|
42
|
-
check_elems = OpenStudio::AttributeVector.new
|
43
|
-
check_elems << OpenStudio::Attribute.new('name', 'Simultaneous Heating and Cooling')
|
44
|
-
check_elems << OpenStudio::Attribute.new('category', category)
|
45
|
-
check_elems << OpenStudio::Attribute.new('description', 'Check for simultaneous heating and cooling by looping through all Single Duct VAV Reheat Air Terminals and analyzing hourly data when there is a cooling load. ')
|
46
|
-
|
47
|
-
# stop here if only name is requested this is used to populate display name for arguments
|
48
|
-
if name_only == true
|
49
|
-
results = []
|
50
|
-
check_elems.each do |elem|
|
51
|
-
results << elem.valueAsString
|
52
|
-
end
|
53
|
-
return results
|
54
|
-
end
|
55
|
-
|
56
|
-
begin
|
57
|
-
# get the weather file run period (as opposed to design day run period)
|
58
|
-
ann_env_pd = nil
|
59
|
-
@sql.availableEnvPeriods.each do |env_pd|
|
60
|
-
env_type = @sql.environmentType(env_pd)
|
61
|
-
if env_type.is_initialized
|
62
|
-
if env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod')
|
63
|
-
ann_env_pd = env_pd
|
64
|
-
break
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# only try to get the annual timeseries if an annual simulation was run
|
70
|
-
if ann_env_pd.nil?
|
71
|
-
check_elems << OpenStudio::Attribute.new('flag', 'Cannot find the annual simulation run period, cannot determine simultaneous heating and cooling.')
|
72
|
-
return check_elem
|
73
|
-
end
|
74
|
-
|
75
|
-
# For each VAV reheat terminal, calculate
|
76
|
-
# the annual total % reheat hours.
|
77
|
-
@model.getAirTerminalSingleDuctVAVReheats.each do |term|
|
78
|
-
# Reheat coil heating rate
|
79
|
-
rht_coil = term.reheatCoil
|
80
|
-
key_value = rht_coil.name.get.to_s.upcase # must be in all caps.
|
81
|
-
time_step = 'Hourly' # "Zone Timestep", "Hourly", "HVAC System Timestep"
|
82
|
-
variable_name = 'Heating Coil Heating Rate'
|
83
|
-
variable_name_alt = 'Heating Coil Air Heating Rate'
|
84
|
-
rht_rate_ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value) # key value would go at the end if we used it.
|
85
|
-
|
86
|
-
# try and alternate variable name
|
87
|
-
if rht_rate_ts.empty?
|
88
|
-
rht_rate_ts = @sql.timeSeries(ann_env_pd, time_step, variable_name_alt, key_value) # key value would go at the end if we used it.
|
89
|
-
end
|
90
|
-
|
91
|
-
if rht_rate_ts.empty?
|
92
|
-
check_elems << OpenStudio::Attribute.new('flag', "Heating Coil (Air) Heating Rate Timeseries not found for #{key_value}.")
|
93
|
-
else
|
94
|
-
|
95
|
-
rht_rate_ts = rht_rate_ts.get.values
|
96
|
-
# Put timeseries into array
|
97
|
-
rht_rate_vals = []
|
98
|
-
for i in 0..(rht_rate_ts.size - 1)
|
99
|
-
rht_rate_vals << rht_rate_ts[i]
|
100
|
-
end
|
101
|
-
|
102
|
-
# Zone Air Terminal Sensible Heating Rate
|
103
|
-
key_value = "ADU #{term.name.get.to_s.upcase}" # must be in all caps.
|
104
|
-
time_step = 'Hourly' # "Zone Timestep", "Hourly", "HVAC System Timestep"
|
105
|
-
variable_name = 'Zone Air Terminal Sensible Cooling Rate'
|
106
|
-
clg_rate_ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value) # key value would go at the end if we used it.
|
107
|
-
if clg_rate_ts.empty?
|
108
|
-
check_elems << OpenStudio::Attribute.new('flag', "Zone Air Terminal Sensible Cooling Rate Timeseries not found for #{key_value}.")
|
109
|
-
else
|
110
|
-
|
111
|
-
clg_rate_ts = clg_rate_ts.get.values
|
112
|
-
# Put timeseries into array
|
113
|
-
clg_rate_vals = []
|
114
|
-
for i in 0..(clg_rate_ts.size - 1)
|
115
|
-
clg_rate_vals << clg_rate_ts[i]
|
116
|
-
end
|
117
|
-
|
118
|
-
# Loop through each timestep and calculate the hourly
|
119
|
-
# % reheat value.
|
120
|
-
ann_rht_hrs = 0
|
121
|
-
ann_clg_hrs = 0
|
122
|
-
ann_pcts = []
|
123
|
-
rht_rate_vals.zip(clg_rate_vals).each do |rht_w, clg_w|
|
124
|
-
# Skip hours with no cooling (in heating mode)
|
125
|
-
next if clg_w == 0
|
126
|
-
pct_overcool_rht = rht_w / (rht_w + clg_w)
|
127
|
-
ann_rht_hrs += pct_overcool_rht # implied * 1hr b/c hrly results
|
128
|
-
ann_clg_hrs += 1
|
129
|
-
ann_pcts << pct_overcool_rht.round(3)
|
130
|
-
end
|
131
|
-
|
132
|
-
# Calculate annual % reheat hours
|
133
|
-
ann_pct_reheat = ((ann_rht_hrs / ann_clg_hrs) * 100).round(1)
|
134
|
-
|
135
|
-
# Compare to limit
|
136
|
-
if ann_pct_reheat > max_pass * 100.0
|
137
|
-
check_elems << OpenStudio::Attribute.new('flag', "#{term.name} has #{ann_pct_reheat}% overcool-reheat, which is greater than the limit of #{max_pass * 100.0}%. This terminal is in cooling mode for #{ann_clg_hrs} hours of the year.")
|
138
|
-
end
|
139
|
-
|
140
|
-
end
|
141
|
-
|
142
|
-
end
|
143
|
-
end
|
144
|
-
rescue StandardError => e
|
145
|
-
# brief description of ruby error
|
146
|
-
check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
|
147
|
-
|
148
|
-
# backtrace of ruby error for diagnostic use
|
149
|
-
if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
|
150
|
-
end
|
151
|
-
|
152
|
-
# add check_elms to new attribute
|
153
|
-
check_elem = OpenStudio::Attribute.new('check', check_elems)
|
154
|
-
|
155
|
-
return check_elem
|
156
|
-
# note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
|
157
|
-
end
|
158
|
-
end
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
module OsLib_QAQC
|
37
|
+
# include any general notes about QAQC method here
|
38
|
+
|
39
|
+
# checks the number of unmet hours in the model
|
40
|
+
def check_simultaneous_heating_and_cooling(category, max_pass, name_only = false)
|
41
|
+
# summary of the check
|
42
|
+
check_elems = OpenStudio::AttributeVector.new
|
43
|
+
check_elems << OpenStudio::Attribute.new('name', 'Simultaneous Heating and Cooling')
|
44
|
+
check_elems << OpenStudio::Attribute.new('category', category)
|
45
|
+
check_elems << OpenStudio::Attribute.new('description', 'Check for simultaneous heating and cooling by looping through all Single Duct VAV Reheat Air Terminals and analyzing hourly data when there is a cooling load. ')
|
46
|
+
|
47
|
+
# stop here if only name is requested this is used to populate display name for arguments
|
48
|
+
if name_only == true
|
49
|
+
results = []
|
50
|
+
check_elems.each do |elem|
|
51
|
+
results << elem.valueAsString
|
52
|
+
end
|
53
|
+
return results
|
54
|
+
end
|
55
|
+
|
56
|
+
begin
|
57
|
+
# get the weather file run period (as opposed to design day run period)
|
58
|
+
ann_env_pd = nil
|
59
|
+
@sql.availableEnvPeriods.each do |env_pd|
|
60
|
+
env_type = @sql.environmentType(env_pd)
|
61
|
+
if env_type.is_initialized
|
62
|
+
if env_type.get == OpenStudio::EnvironmentType.new('WeatherRunPeriod')
|
63
|
+
ann_env_pd = env_pd
|
64
|
+
break
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# only try to get the annual timeseries if an annual simulation was run
|
70
|
+
if ann_env_pd.nil?
|
71
|
+
check_elems << OpenStudio::Attribute.new('flag', 'Cannot find the annual simulation run period, cannot determine simultaneous heating and cooling.')
|
72
|
+
return check_elem
|
73
|
+
end
|
74
|
+
|
75
|
+
# For each VAV reheat terminal, calculate
|
76
|
+
# the annual total % reheat hours.
|
77
|
+
@model.getAirTerminalSingleDuctVAVReheats.each do |term|
|
78
|
+
# Reheat coil heating rate
|
79
|
+
rht_coil = term.reheatCoil
|
80
|
+
key_value = rht_coil.name.get.to_s.upcase # must be in all caps.
|
81
|
+
time_step = 'Hourly' # "Zone Timestep", "Hourly", "HVAC System Timestep"
|
82
|
+
variable_name = 'Heating Coil Heating Rate'
|
83
|
+
variable_name_alt = 'Heating Coil Air Heating Rate'
|
84
|
+
rht_rate_ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value) # key value would go at the end if we used it.
|
85
|
+
|
86
|
+
# try and alternate variable name
|
87
|
+
if rht_rate_ts.empty?
|
88
|
+
rht_rate_ts = @sql.timeSeries(ann_env_pd, time_step, variable_name_alt, key_value) # key value would go at the end if we used it.
|
89
|
+
end
|
90
|
+
|
91
|
+
if rht_rate_ts.empty?
|
92
|
+
check_elems << OpenStudio::Attribute.new('flag', "Heating Coil (Air) Heating Rate Timeseries not found for #{key_value}.")
|
93
|
+
else
|
94
|
+
|
95
|
+
rht_rate_ts = rht_rate_ts.get.values
|
96
|
+
# Put timeseries into array
|
97
|
+
rht_rate_vals = []
|
98
|
+
for i in 0..(rht_rate_ts.size - 1)
|
99
|
+
rht_rate_vals << rht_rate_ts[i]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Zone Air Terminal Sensible Heating Rate
|
103
|
+
key_value = "ADU #{term.name.get.to_s.upcase}" # must be in all caps.
|
104
|
+
time_step = 'Hourly' # "Zone Timestep", "Hourly", "HVAC System Timestep"
|
105
|
+
variable_name = 'Zone Air Terminal Sensible Cooling Rate'
|
106
|
+
clg_rate_ts = @sql.timeSeries(ann_env_pd, time_step, variable_name, key_value) # key value would go at the end if we used it.
|
107
|
+
if clg_rate_ts.empty?
|
108
|
+
check_elems << OpenStudio::Attribute.new('flag', "Zone Air Terminal Sensible Cooling Rate Timeseries not found for #{key_value}.")
|
109
|
+
else
|
110
|
+
|
111
|
+
clg_rate_ts = clg_rate_ts.get.values
|
112
|
+
# Put timeseries into array
|
113
|
+
clg_rate_vals = []
|
114
|
+
for i in 0..(clg_rate_ts.size - 1)
|
115
|
+
clg_rate_vals << clg_rate_ts[i]
|
116
|
+
end
|
117
|
+
|
118
|
+
# Loop through each timestep and calculate the hourly
|
119
|
+
# % reheat value.
|
120
|
+
ann_rht_hrs = 0
|
121
|
+
ann_clg_hrs = 0
|
122
|
+
ann_pcts = []
|
123
|
+
rht_rate_vals.zip(clg_rate_vals).each do |rht_w, clg_w|
|
124
|
+
# Skip hours with no cooling (in heating mode)
|
125
|
+
next if clg_w == 0
|
126
|
+
pct_overcool_rht = rht_w / (rht_w + clg_w)
|
127
|
+
ann_rht_hrs += pct_overcool_rht # implied * 1hr b/c hrly results
|
128
|
+
ann_clg_hrs += 1
|
129
|
+
ann_pcts << pct_overcool_rht.round(3)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Calculate annual % reheat hours
|
133
|
+
ann_pct_reheat = ((ann_rht_hrs / ann_clg_hrs) * 100).round(1)
|
134
|
+
|
135
|
+
# Compare to limit
|
136
|
+
if ann_pct_reheat > max_pass * 100.0
|
137
|
+
check_elems << OpenStudio::Attribute.new('flag', "#{term.name} has #{ann_pct_reheat}% overcool-reheat, which is greater than the limit of #{max_pass * 100.0}%. This terminal is in cooling mode for #{ann_clg_hrs} hours of the year.")
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
rescue StandardError => e
|
145
|
+
# brief description of ruby error
|
146
|
+
check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
|
147
|
+
|
148
|
+
# backtrace of ruby error for diagnostic use
|
149
|
+
if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
|
150
|
+
end
|
151
|
+
|
152
|
+
# add check_elms to new attribute
|
153
|
+
check_elem = OpenStudio::Attribute.new('check', check_elems)
|
154
|
+
|
155
|
+
return check_elem
|
156
|
+
# note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
|
157
|
+
end
|
158
|
+
end
|
@@ -1,148 +1,148 @@
|
|
1
|
-
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
|
3
|
-
# All rights reserved.
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions are met:
|
6
|
-
#
|
7
|
-
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
-
# this list of conditions and the following disclaimer.
|
9
|
-
#
|
10
|
-
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
#
|
14
|
-
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
-
# may be used to endorse or promote products derived from this software without
|
16
|
-
# specific prior written permission from the respective party.
|
17
|
-
#
|
18
|
-
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
-
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
-
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
-
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
-
#
|
23
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
-
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
-
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
-
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
-
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
-
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
-
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
-
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
-
# *******************************************************************************
|
35
|
-
|
36
|
-
module OsLib_QAQC
|
37
|
-
# include any general notes about QAQC method here
|
38
|
-
|
39
|
-
# checks the number of unmet hours in the model
|
40
|
-
def check_supply_air_and_thermostat_temp_difference(category, target_standard, max_delta, name_only = false)
|
41
|
-
# G3.1.2.9 requires a 20 degree F delta between supply air temperature and zone temperature.
|
42
|
-
target_clg_delta = 20.0
|
43
|
-
|
44
|
-
# summary of the check
|
45
|
-
check_elems = OpenStudio::AttributeVector.new
|
46
|
-
check_elems << OpenStudio::Attribute.new('name', 'Supply and Zone Air Temperature')
|
47
|
-
check_elems << OpenStudio::Attribute.new('category', category)
|
48
|
-
if @utility_name.nil?
|
49
|
-
check_elems << OpenStudio::Attribute.new('description', "Check if fans modeled to ASHRAE 90.1 2013 Section G3.1.2.9 requirements. Compare the supply air temperature for each thermal zone against the thermostat setpoints. Throw flag if temperature difference excedes threshold of #{target_clg_delta}F plus the selected tolerance.")
|
50
|
-
else
|
51
|
-
check_elems << OpenStudio::Attribute.new('description', "Check if fans modeled to ASHRAE 90.1 2013 Section G3.1.2.9 requirements. Compare the supply air temperature for each thermal zone against the thermostat setpoints. Throw flag if temperature difference excedes threshold set by #{@utility_name}.")
|
52
|
-
end
|
53
|
-
|
54
|
-
# stop here if only name is requested this is used to populate display name for arguments
|
55
|
-
if name_only == true
|
56
|
-
results = []
|
57
|
-
check_elems.each do |elem|
|
58
|
-
results << elem.valueAsString
|
59
|
-
end
|
60
|
-
return results
|
61
|
-
end
|
62
|
-
|
63
|
-
# Versions of OpenStudio greater than 2.4.0 use a modified version of
|
64
|
-
# openstudio-standards with different method calls. These methods
|
65
|
-
# require a "Standard" object instead of the standard being passed into method calls.
|
66
|
-
# This Standard object is used throughout the QAQC check.
|
67
|
-
if OpenStudio::VersionString.new(OpenStudio.openStudioVersion) < OpenStudio::VersionString.new('2.4.3')
|
68
|
-
use_old_gem_code = true
|
69
|
-
else
|
70
|
-
use_old_gem_code = false
|
71
|
-
std = Standard.build(target_standard)
|
72
|
-
end
|
73
|
-
|
74
|
-
begin
|
75
|
-
# loop through thermal zones
|
76
|
-
@model.getThermalZones.sort.each do |thermal_zone|
|
77
|
-
model_clg_min = nil
|
78
|
-
|
79
|
-
# populate thermostat ranges
|
80
|
-
if thermal_zone.thermostatSetpointDualSetpoint.is_initialized
|
81
|
-
|
82
|
-
thermostat = thermal_zone.thermostatSetpointDualSetpoint.get
|
83
|
-
if thermostat.coolingSetpointTemperatureSchedule.is_initialized
|
84
|
-
|
85
|
-
clg_sch = thermostat.coolingSetpointTemperatureSchedule.get
|
86
|
-
schedule_values = nil
|
87
|
-
if clg_sch.to_ScheduleRuleset.is_initialized
|
88
|
-
if use_old_gem_code
|
89
|
-
schedule_values = clg_sch.to_ScheduleRuleset.get.annual_min_max_value
|
90
|
-
else
|
91
|
-
schedule_values = std.schedule_ruleset_annual_min_max_value(clg_sch.to_ScheduleRuleset.get)
|
92
|
-
end
|
93
|
-
elsif clg_sch.to_ScheduleConstant.is_initialized
|
94
|
-
if use_old_gem_code
|
95
|
-
schedule_values = clg_sch.to_ScheduleConstant.get.annual_min_max_value
|
96
|
-
else
|
97
|
-
schedule_values = std.schedule_constant_annual_min_max_value(clg_sch.to_ScheduleConstant.get)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
unless schedule_values.nil?
|
102
|
-
model_clg_min = schedule_values['min']
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
else
|
107
|
-
# go to next zone if not conditioned
|
108
|
-
next
|
109
|
-
|
110
|
-
end
|
111
|
-
|
112
|
-
# flag if there is setpoint schedule can't be inspected (isn't ruleset)
|
113
|
-
if model_clg_min.nil?
|
114
|
-
check_elems << OpenStudio::Attribute.new('flag', "Can't inspect thermostat schedules for #{thermal_zone.name}")
|
115
|
-
else
|
116
|
-
|
117
|
-
# get supply air temps from thermal zone sizing
|
118
|
-
sizing_zone = thermal_zone.sizingZone
|
119
|
-
clg_supply_air_temp = sizing_zone.zoneCoolingDesignSupplyAirTemperature
|
120
|
-
|
121
|
-
# convert model values to IP
|
122
|
-
model_clg_min_ip = OpenStudio.convert(model_clg_min, 'C', 'F').get
|
123
|
-
clg_supply_air_temp_ip = OpenStudio.convert(clg_supply_air_temp, 'C', 'F').get
|
124
|
-
|
125
|
-
# check supply air against zone temperature (only check against min setpoint, assume max is night setback)
|
126
|
-
if model_clg_min_ip - clg_supply_air_temp_ip > target_clg_delta + max_delta
|
127
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{thermal_zone.name} the delta temp between the cooling supply air temp of #{clg_supply_air_temp_ip.round(2)} (F) and the minimum thermostat cooling temp of #{model_clg_min_ip.round(2)} (F) is more than #{max_delta} (F) larger than the expected delta of #{target_clg_delta} (F)")
|
128
|
-
elsif model_clg_min_ip - clg_supply_air_temp_ip < target_clg_delta - max_delta
|
129
|
-
check_elems << OpenStudio::Attribute.new('flag', "For #{thermal_zone.name} the delta temp between the cooling supply air temp of #{clg_supply_air_temp_ip.round(2)} (F) and the minimum thermostat cooling temp of #{model_clg_min_ip.round(2)} (F) is more than #{max_delta} (F) smaller than the expected delta of #{target_clg_delta} (F)")
|
130
|
-
end
|
131
|
-
|
132
|
-
end
|
133
|
-
end
|
134
|
-
rescue StandardError => e
|
135
|
-
# brief description of ruby error
|
136
|
-
check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
|
137
|
-
|
138
|
-
# backtrace of ruby error for diagnostic use
|
139
|
-
if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
|
140
|
-
end
|
141
|
-
|
142
|
-
# add check_elms to new attribute
|
143
|
-
check_elem = OpenStudio::Attribute.new('check', check_elems)
|
144
|
-
|
145
|
-
return check_elem
|
146
|
-
# note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
|
147
|
-
end
|
148
|
-
end
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2019, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
module OsLib_QAQC
|
37
|
+
# include any general notes about QAQC method here
|
38
|
+
|
39
|
+
# checks the number of unmet hours in the model
|
40
|
+
def check_supply_air_and_thermostat_temp_difference(category, target_standard, max_delta, name_only = false)
|
41
|
+
# G3.1.2.9 requires a 20 degree F delta between supply air temperature and zone temperature.
|
42
|
+
target_clg_delta = 20.0
|
43
|
+
|
44
|
+
# summary of the check
|
45
|
+
check_elems = OpenStudio::AttributeVector.new
|
46
|
+
check_elems << OpenStudio::Attribute.new('name', 'Supply and Zone Air Temperature')
|
47
|
+
check_elems << OpenStudio::Attribute.new('category', category)
|
48
|
+
if @utility_name.nil?
|
49
|
+
check_elems << OpenStudio::Attribute.new('description', "Check if fans modeled to ASHRAE 90.1 2013 Section G3.1.2.9 requirements. Compare the supply air temperature for each thermal zone against the thermostat setpoints. Throw flag if temperature difference excedes threshold of #{target_clg_delta}F plus the selected tolerance.")
|
50
|
+
else
|
51
|
+
check_elems << OpenStudio::Attribute.new('description', "Check if fans modeled to ASHRAE 90.1 2013 Section G3.1.2.9 requirements. Compare the supply air temperature for each thermal zone against the thermostat setpoints. Throw flag if temperature difference excedes threshold set by #{@utility_name}.")
|
52
|
+
end
|
53
|
+
|
54
|
+
# stop here if only name is requested this is used to populate display name for arguments
|
55
|
+
if name_only == true
|
56
|
+
results = []
|
57
|
+
check_elems.each do |elem|
|
58
|
+
results << elem.valueAsString
|
59
|
+
end
|
60
|
+
return results
|
61
|
+
end
|
62
|
+
|
63
|
+
# Versions of OpenStudio greater than 2.4.0 use a modified version of
|
64
|
+
# openstudio-standards with different method calls. These methods
|
65
|
+
# require a "Standard" object instead of the standard being passed into method calls.
|
66
|
+
# This Standard object is used throughout the QAQC check.
|
67
|
+
if OpenStudio::VersionString.new(OpenStudio.openStudioVersion) < OpenStudio::VersionString.new('2.4.3')
|
68
|
+
use_old_gem_code = true
|
69
|
+
else
|
70
|
+
use_old_gem_code = false
|
71
|
+
std = Standard.build(target_standard)
|
72
|
+
end
|
73
|
+
|
74
|
+
begin
|
75
|
+
# loop through thermal zones
|
76
|
+
@model.getThermalZones.sort.each do |thermal_zone|
|
77
|
+
model_clg_min = nil
|
78
|
+
|
79
|
+
# populate thermostat ranges
|
80
|
+
if thermal_zone.thermostatSetpointDualSetpoint.is_initialized
|
81
|
+
|
82
|
+
thermostat = thermal_zone.thermostatSetpointDualSetpoint.get
|
83
|
+
if thermostat.coolingSetpointTemperatureSchedule.is_initialized
|
84
|
+
|
85
|
+
clg_sch = thermostat.coolingSetpointTemperatureSchedule.get
|
86
|
+
schedule_values = nil
|
87
|
+
if clg_sch.to_ScheduleRuleset.is_initialized
|
88
|
+
if use_old_gem_code
|
89
|
+
schedule_values = clg_sch.to_ScheduleRuleset.get.annual_min_max_value
|
90
|
+
else
|
91
|
+
schedule_values = std.schedule_ruleset_annual_min_max_value(clg_sch.to_ScheduleRuleset.get)
|
92
|
+
end
|
93
|
+
elsif clg_sch.to_ScheduleConstant.is_initialized
|
94
|
+
if use_old_gem_code
|
95
|
+
schedule_values = clg_sch.to_ScheduleConstant.get.annual_min_max_value
|
96
|
+
else
|
97
|
+
schedule_values = std.schedule_constant_annual_min_max_value(clg_sch.to_ScheduleConstant.get)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
unless schedule_values.nil?
|
102
|
+
model_clg_min = schedule_values['min']
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
else
|
107
|
+
# go to next zone if not conditioned
|
108
|
+
next
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# flag if there is setpoint schedule can't be inspected (isn't ruleset)
|
113
|
+
if model_clg_min.nil?
|
114
|
+
check_elems << OpenStudio::Attribute.new('flag', "Can't inspect thermostat schedules for #{thermal_zone.name}")
|
115
|
+
else
|
116
|
+
|
117
|
+
# get supply air temps from thermal zone sizing
|
118
|
+
sizing_zone = thermal_zone.sizingZone
|
119
|
+
clg_supply_air_temp = sizing_zone.zoneCoolingDesignSupplyAirTemperature
|
120
|
+
|
121
|
+
# convert model values to IP
|
122
|
+
model_clg_min_ip = OpenStudio.convert(model_clg_min, 'C', 'F').get
|
123
|
+
clg_supply_air_temp_ip = OpenStudio.convert(clg_supply_air_temp, 'C', 'F').get
|
124
|
+
|
125
|
+
# check supply air against zone temperature (only check against min setpoint, assume max is night setback)
|
126
|
+
if model_clg_min_ip - clg_supply_air_temp_ip > target_clg_delta + max_delta
|
127
|
+
check_elems << OpenStudio::Attribute.new('flag', "For #{thermal_zone.name} the delta temp between the cooling supply air temp of #{clg_supply_air_temp_ip.round(2)} (F) and the minimum thermostat cooling temp of #{model_clg_min_ip.round(2)} (F) is more than #{max_delta} (F) larger than the expected delta of #{target_clg_delta} (F)")
|
128
|
+
elsif model_clg_min_ip - clg_supply_air_temp_ip < target_clg_delta - max_delta
|
129
|
+
check_elems << OpenStudio::Attribute.new('flag', "For #{thermal_zone.name} the delta temp between the cooling supply air temp of #{clg_supply_air_temp_ip.round(2)} (F) and the minimum thermostat cooling temp of #{model_clg_min_ip.round(2)} (F) is more than #{max_delta} (F) smaller than the expected delta of #{target_clg_delta} (F)")
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
rescue StandardError => e
|
135
|
+
# brief description of ruby error
|
136
|
+
check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
|
137
|
+
|
138
|
+
# backtrace of ruby error for diagnostic use
|
139
|
+
if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
|
140
|
+
end
|
141
|
+
|
142
|
+
# add check_elms to new attribute
|
143
|
+
check_elem = OpenStudio::Attribute.new('check', check_elems)
|
144
|
+
|
145
|
+
return check_elem
|
146
|
+
# note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
|
147
|
+
end
|
148
|
+
end
|