openstudio-extension 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +14 -0
  4. data/LICENSE.md +1 -1
  5. data/README.md +2 -0
  6. data/lib/openstudio/extension/runner.rb +12 -8
  7. data/lib/openstudio/extension/runner_config.rb +33 -6
  8. data/lib/openstudio/extension/version.rb +1 -1
  9. data/openstudio-extension.gemspec +6 -6
  10. metadata +18 -75
  11. data/lib/openstudio/extension/core/CreateResults.rb +0 -1033
  12. data/lib/openstudio/extension/core/check_air_sys_temps.rb +0 -160
  13. data/lib/openstudio/extension/core/check_calibration.rb +0 -125
  14. data/lib/openstudio/extension/core/check_cond_zns.rb +0 -54
  15. data/lib/openstudio/extension/core/check_domestic_hot_water.rb +0 -304
  16. data/lib/openstudio/extension/core/check_envelope_conductance.rb +0 -423
  17. data/lib/openstudio/extension/core/check_eui_by_end_use.rb +0 -132
  18. data/lib/openstudio/extension/core/check_eui_reasonableness.rb +0 -105
  19. data/lib/openstudio/extension/core/check_fan_pwr.rb +0 -68
  20. data/lib/openstudio/extension/core/check_internal_loads.rb +0 -363
  21. data/lib/openstudio/extension/core/check_mech_sys_capacity.rb +0 -196
  22. data/lib/openstudio/extension/core/check_mech_sys_efficiency.rb +0 -296
  23. data/lib/openstudio/extension/core/check_mech_sys_part_load_eff.rb +0 -434
  24. data/lib/openstudio/extension/core/check_mech_sys_type.rb +0 -109
  25. data/lib/openstudio/extension/core/check_part_loads.rb +0 -421
  26. data/lib/openstudio/extension/core/check_placeholder.rb +0 -45
  27. data/lib/openstudio/extension/core/check_plant_cap.rb +0 -93
  28. data/lib/openstudio/extension/core/check_plant_temps.rb +0 -129
  29. data/lib/openstudio/extension/core/check_plenum_loads.rb +0 -57
  30. data/lib/openstudio/extension/core/check_pump_pwr.rb +0 -78
  31. data/lib/openstudio/extension/core/check_sch_coord.rb +0 -211
  32. data/lib/openstudio/extension/core/check_schedules.rb +0 -281
  33. data/lib/openstudio/extension/core/check_simultaneous_heating_and_cooling.rb +0 -128
  34. data/lib/openstudio/extension/core/check_supply_air_and_thermostat_temp_difference.rb +0 -118
  35. data/lib/openstudio/extension/core/check_weather_files.rb +0 -102
  36. data/lib/openstudio/extension/core/deer_vintages.rb +0 -281
  37. data/lib/openstudio/extension/core/os_lib_aedg_measures.rb +0 -461
  38. data/lib/openstudio/extension/core/os_lib_constructions.rb +0 -353
  39. data/lib/openstudio/extension/core/os_lib_geometry.rb +0 -1169
  40. data/lib/openstudio/extension/core/os_lib_helper_methods.rb +0 -383
  41. data/lib/openstudio/extension/core/os_lib_hvac.rb +0 -2163
  42. data/lib/openstudio/extension/core/os_lib_lighting_and_equipment.rb +0 -184
  43. data/lib/openstudio/extension/core/os_lib_model_generation.rb +0 -3584
  44. data/lib/openstudio/extension/core/os_lib_model_simplification.rb +0 -1019
  45. data/lib/openstudio/extension/core/os_lib_outdoorair_and_infiltration.rb +0 -135
  46. data/lib/openstudio/extension/core/os_lib_reporting_qaqc.rb +0 -170
  47. data/lib/openstudio/extension/core/os_lib_schedules.rb +0 -933
@@ -1,196 +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_mech_sys_capacity(category, options, target_standard, name_only = false)
11
- # summary of the check
12
- check_elems = OpenStudio::AttributeVector.new
13
- check_elems << OpenStudio::Attribute.new('name', 'Mechanical System Capacity')
14
- check_elems << OpenStudio::Attribute.new('category', category)
15
- check_elems << OpenStudio::Attribute.new('description', 'Check HVAC capacity against ASHRAE rules of thumb for chiller max flow rate, air loop max flow rate, air loop cooling capciaty, and zone heating capcaity. Zone heating check will skip thermal zones without any exterior exposure, and thermal zones that are not conditioned.')
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
- # Versions of OpenStudio greater than 2.4.0 use a modified version of
27
- # openstudio-standards with different method calls. These methods
28
- # require a "Standard" object instead of the standard being passed into method calls.
29
- # This Standard object is used throughout the QAQC check.
30
- if OpenStudio::VersionString.new(OpenStudio.openStudioVersion) < OpenStudio::VersionString.new('2.4.3')
31
- use_old_gem_code = true
32
- else
33
- use_old_gem_code = false
34
- std = Standard.build(target_standard)
35
- end
36
-
37
- begin
38
- # check max flow rate of chillers in model
39
- @model.getPlantLoops.sort.each do |plant_loop|
40
- # next if no chiller on plant loop
41
- chillers = []
42
- plant_loop.supplyComponents.each do |sc|
43
- if sc.to_ChillerElectricEIR.is_initialized
44
- chillers << sc.to_ChillerElectricEIR.get
45
- end
46
- end
47
- next if chillers.empty?
48
-
49
- # gather targets for chiller capacity
50
- chiller_max_flow_rate_target = options['chiller_max_flow_rate']['target']
51
- chiller_max_flow_rate_fraction_min = options['chiller_max_flow_rate']['min']
52
- chiller_max_flow_rate_fraction_max = options['chiller_max_flow_rate']['max']
53
- chiller_max_flow_rate_units_ip = options['chiller_max_flow_rate']['units'] # gal/ton*min
54
- # string above or display only, for converstion 12000 Btu/h per ton
55
-
56
- # get capacity of loop (not individual chiller but entire loop)
57
- if use_old_gem_code
58
- total_cooling_capacity_w = plant_loop.total_cooling_capacity
59
- else
60
- total_cooling_capacity_w = std.plant_loop_total_cooling_capacity(plant_loop)
61
- end
62
- total_cooling_capacity_ton = OpenStudio.convert(total_cooling_capacity_w, 'W', 'Btu/h').get / 12000.0
63
-
64
- # get the max flow rate (through plant, not specific chiller)
65
- if use_old_gem_code
66
- maximum_loop_flow_rate = plant_loop.find_maximum_loop_flow_rate
67
- else
68
- maximum_loop_flow_rate = std.plant_loop_find_maximum_loop_flow_rate(plant_loop)
69
- end
70
- maximum_loop_flow_rate_ip = OpenStudio.convert(maximum_loop_flow_rate, 'm^3/s', 'gal/min').get
71
-
72
- # calculate the flow per tons of cooling
73
- model_flow_rate_per_ton_cooling_ip = maximum_loop_flow_rate_ip / total_cooling_capacity_ton
74
-
75
- # check flow rate per capacity
76
- if model_flow_rate_per_ton_cooling_ip < chiller_max_flow_rate_target * (1.0 - chiller_max_flow_rate_fraction_min)
77
- check_elems << OpenStudio::Attribute.new('flag', "Flow Rate of #{model_flow_rate_per_ton_cooling_ip.round(2)} #{chiller_max_flow_rate_units_ip} for #{plant_loop.name.get} is more than #{chiller_max_flow_rate_fraction_min * 100} % below the typical value of #{chiller_max_flow_rate_target.round(2)} #{chiller_max_flow_rate_units_ip}.")
78
- elsif model_flow_rate_per_ton_cooling_ip > chiller_max_flow_rate_target * (1.0 + chiller_max_flow_rate_fraction_max)
79
- check_elems << OpenStudio::Attribute.new('flag', "Flow Rate of #{model_flow_rate_per_ton_cooling_ip.round(2)} #{chiller_max_flow_rate_units_ip} for #{plant_loop.name.get} is more than #{chiller_max_flow_rate_fraction_max * 100} % above the typical value of #{chiller_max_flow_rate_target.round(2)} #{chiller_max_flow_rate_units_ip}.")
80
- end
81
- end
82
-
83
- # loop through air loops to get max flor rate and cooling capacity.
84
- @model.getAirLoopHVACs.sort.each do |air_loop|
85
- # TODO: - check if DOAS, don't check airflow or cooling capacity if it is (why not check OA for DOAS? would it be different target)
86
-
87
- # gather argument options for air_loop_max_flow_rate checks
88
- air_loop_max_flow_rate_target = options['air_loop_max_flow_rate']['target']
89
- air_loop_max_flow_rate_fraction_min = options['air_loop_max_flow_rate']['min']
90
- air_loop_max_flow_rate_fraction_max = options['air_loop_max_flow_rate']['max']
91
- air_loop_max_flow_rate_units_ip = options['air_loop_max_flow_rate']['units']
92
- air_loop_max_flow_rate_units_si = 'm^3/m^2*s'
93
-
94
- # get values from model for air loop checks
95
- if use_old_gem_code
96
- floor_area_served = air_loop.floor_area_served # m^2
97
- else
98
- floor_area_served = std.air_loop_hvac_floor_area_served(air_loop) # m^2
99
- end
100
-
101
- if use_old_gem_code
102
- design_supply_air_flow_rate = air_loop.find_design_supply_air_flow_rate # m^3/s
103
- else
104
- design_supply_air_flow_rate = std.air_loop_hvac_find_design_supply_air_flow_rate(air_loop) # m^3/s
105
- end
106
-
107
- # check max flow rate of air loops in the model
108
- model_normalized_flow_rate_si = design_supply_air_flow_rate / floor_area_served
109
- model_normalized_flow_rate_ip = OpenStudio.convert(model_normalized_flow_rate_si, air_loop_max_flow_rate_units_si, air_loop_max_flow_rate_units_ip).get
110
- if model_normalized_flow_rate_ip < air_loop_max_flow_rate_target * (1.0 - air_loop_max_flow_rate_fraction_min)
111
- check_elems << OpenStudio::Attribute.new('flag', "Flow Rate of #{model_normalized_flow_rate_ip.round(2)} #{air_loop_max_flow_rate_units_ip} for #{air_loop.name.get} is more than #{air_loop_max_flow_rate_fraction_min * 100} % below the typical value of #{air_loop_max_flow_rate_target.round(2)} #{air_loop_max_flow_rate_units_ip}.")
112
- elsif model_normalized_flow_rate_ip > air_loop_max_flow_rate_target * (1.0 + air_loop_max_flow_rate_fraction_max)
113
- check_elems << OpenStudio::Attribute.new('flag', "Flow Rate of #{model_normalized_flow_rate_ip.round(2)} #{air_loop_max_flow_rate_units_ip} for #{air_loop.name.get} is more than #{air_loop_max_flow_rate_fraction_max * 100} % above the typical value of #{air_loop_max_flow_rate_target.round(2)} #{air_loop_max_flow_rate_units_ip}.")
114
- end
115
- end
116
-
117
- # loop through air loops to get max flor rate and cooling capacity.
118
- @model.getAirLoopHVACs.sort.each do |air_loop|
119
- # check if DOAS, don't check airflow or cooling capacity if it is
120
- sizing_system = air_loop.sizingSystem
121
- next if sizing_system.typeofLoadtoSizeOn.to_s == 'VentilationRequirement'
122
-
123
- # gather argument options for air_loop_cooling_capacity checks
124
- air_loop_cooling_capacity_target = options['air_loop_cooling_capacity']['target']
125
- air_loop_cooling_capacity_fraction_min = options['air_loop_cooling_capacity']['min']
126
- air_loop_cooling_capacity_fraction_max = options['air_loop_cooling_capacity']['max']
127
- air_loop_cooling_capacity_units_ip = options['air_loop_cooling_capacity']['units'] # tons/ft^2
128
- # string above or display only, for converstion 12000 Btu/h per ton
129
- air_loop_cooling_capacity_units_si = 'W/m^2'
130
-
131
- # get values from model for air loop checks
132
- if use_old_gem_code
133
- floor_area_served = air_loop.floor_area_served # m^2
134
- else
135
- floor_area_served = std.air_loop_hvac_floor_area_served(air_loop) # m^2
136
- end
137
-
138
- if use_old_gem_code
139
- capacity = air_loop.total_cooling_capacity # W
140
- else
141
- capacity = std.air_loop_hvac_total_cooling_capacity(air_loop) # W
142
- end
143
-
144
- # check cooling capacity of air loops in the model
145
- model_normalized_capacity_si = capacity / floor_area_served
146
- model_normalized_capacity_ip = OpenStudio.convert(model_normalized_capacity_si, air_loop_cooling_capacity_units_si, 'Btu/ft^2*h').get / 12000.0 # hard coded to get tons from Btu/h
147
-
148
- # want to display in tons/ft^2 so invert number and display for checks
149
- model_tons_per_area_ip = 1.0 / model_normalized_capacity_ip
150
- target_tons_per_area_ip = 1.0 / air_loop_cooling_capacity_target
151
- inverted_units = 'ft^2/ton'
152
-
153
- if model_tons_per_area_ip < target_tons_per_area_ip * (1.0 - air_loop_cooling_capacity_fraction_max)
154
- check_elems << OpenStudio::Attribute.new('flag', "Cooling Capacity of #{model_tons_per_area_ip.round} #{inverted_units} for #{air_loop.name.get} is more than #{air_loop_cooling_capacity_fraction_max * 100} % below the typical value of #{target_tons_per_area_ip.round} #{inverted_units}.")
155
- elsif model_tons_per_area_ip > target_tons_per_area_ip * (1.0 + air_loop_cooling_capacity_fraction_min)
156
- check_elems << OpenStudio::Attribute.new('flag', "Cooling Capacity of #{model_tons_per_area_ip.round} #{inverted_units} for #{air_loop.name.get} is more than #{air_loop_cooling_capacity_fraction_min * 100} % above the typical value of #{target_tons_per_area_ip.round} #{inverted_units}.")
157
- end
158
- end
159
-
160
- # check heating capacity of thermal zones in the model with exterior exposure
161
- report_name = 'HVACSizingSummary'
162
- table_name = 'Zone Sensible Heating'
163
- column_name = 'User Design Load per Area'
164
- target = options['zone_heating_capacity']['target']
165
- fraction_min = options['zone_heating_capacity']['min']
166
- fraction_max = options['zone_heating_capacity']['max']
167
- units_ip = options['zone_heating_capacity']['units']
168
- units_si = 'W/m^2'
169
- @model.getThermalZones.sort.each do |thermal_zone|
170
- next if thermal_zone.canBePlenum
171
- next if thermal_zone.exteriorSurfaceArea == 0.0
172
- query = "SELECT Value FROM tabulardatawithstrings WHERE ReportName='#{report_name}' and TableName='#{table_name}' and RowName= '#{thermal_zone.name.get.upcase}' and ColumnName= '#{column_name}'"
173
- results = @sql.execAndReturnFirstDouble(query) # W/m^2
174
- model_zone_heating_capacity_ip = OpenStudio.convert(results.to_f, units_si, units_ip).get
175
- # check actual against target
176
- if model_zone_heating_capacity_ip < target * (1.0 - fraction_min)
177
- check_elems << OpenStudio::Attribute.new('flag', "Heating Capacity of #{model_zone_heating_capacity_ip.round(2)} Btu/ft^2*h for #{thermal_zone.name.get} is more than #{fraction_min * 100} % below the typical value of #{target.round(2)} Btu/ft^2*h.")
178
- elsif model_zone_heating_capacity_ip > target * (1.0 + fraction_max)
179
- check_elems << OpenStudio::Attribute.new('flag', "Heating Capacity of #{model_zone_heating_capacity_ip.round(2)} Btu/ft^2*h for #{thermal_zone.name.get} is more than #{fraction_max * 100} % above the typical value of #{target.round(2)} Btu/ft^2*h.")
180
- end
181
- end
182
- rescue StandardError => e
183
- # brief description of ruby error
184
- check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
185
-
186
- # backtrace of ruby error for diagnostic use
187
- if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
188
- end
189
-
190
- # add check_elms to new attribute
191
- check_elem = OpenStudio::Attribute.new('check', check_elems)
192
-
193
- return check_elem
194
- # note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
195
- end
196
- end
@@ -1,296 +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_mech_sys_efficiency(category, target_standard, min_pass, max_pass, name_only = false)
11
- component_type_array = ['ChillerElectricEIR', 'CoilCoolingDXSingleSpeed', 'CoilCoolingDXTwoSpeed', 'CoilHeatingDXSingleSpeed', 'BoilerHotWater', 'FanConstantVolume', 'FanVariableVolume', 'PumpConstantSpeed', 'PumpVariableSpeed']
12
-
13
- # summary of the check
14
- check_elems = OpenStudio::AttributeVector.new
15
- check_elems << OpenStudio::Attribute.new('name', 'Mechanical System Efficiency')
16
- check_elems << OpenStudio::Attribute.new('category', category)
17
-
18
- if target_standard.include?('90.1-2013')
19
- display_standard = "ASHRAE #{target_standard}"
20
- check_elems << OpenStudio::Attribute.new('description', "Check against #{display_standard} Tables 6.8.1 A-K for the following component types: #{component_type_array.join(', ')}.")
21
- else
22
- # TODO: - could add more elsifs if want to dsiplay tables and sections for additional 90.1 standards
23
- if target_standard.include?('90.1')
24
- display_standard = "ASHRAE #{target_standard}"
25
- else
26
- display_standard = target_standard
27
- end
28
- check_elems << OpenStudio::Attribute.new('description', "Check against #{display_standard} for the following component types: #{component_type_array.join(', ')}.")
29
- end
30
-
31
- # stop here if only name is requested this is used to populate display name for arguments
32
- if name_only == true
33
- results = []
34
- check_elems.each do |elem|
35
- results << elem.valueAsString
36
- end
37
- return results
38
- end
39
-
40
- # Versions of OpenStudio greater than 2.4.0 use a modified version of
41
- # openstudio-standards with different method calls. These methods
42
- # require a "Standard" object instead of the standard being passed into method calls.
43
- # This Standard object is used throughout the QAQC check.
44
- if OpenStudio::VersionString.new(OpenStudio.openStudioVersion) < OpenStudio::VersionString.new('2.4.3')
45
- use_old_gem_code = true
46
- else
47
- use_old_gem_code = false
48
- std = Standard.build(target_standard)
49
- end
50
-
51
- begin
52
- # check ChillerElectricEIR objects (will also have curve check in different script)
53
- @model.getChillerElectricEIRs.each do |component|
54
- # eff values from model
55
- reference_COP = component.referenceCOP
56
-
57
- # get eff values from standards (if name doesn't have expected strings find object returns first object of multiple)
58
-
59
- if use_old_gem_code
60
- standard_minimum_full_load_efficiency = component.standard_minimum_full_load_efficiency(target_standard)
61
- else
62
- standard_minimum_full_load_efficiency = std.chiller_electric_eir_standard_minimum_full_load_efficiency(component)
63
- end
64
-
65
- # check actual against target
66
- if standard_minimum_full_load_efficiency.nil?
67
- check_elems << OpenStudio::Attribute.new('flag', "Can't find target full load efficiency for #{component.name}.")
68
- elsif reference_COP < standard_minimum_full_load_efficiency * (1.0 - min_pass)
69
- check_elems << OpenStudio::Attribute.new('flag', "COP of #{reference_COP.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_full_load_efficiency.round(2)}.")
70
- elsif reference_COP > standard_minimum_full_load_efficiency * (1.0 + max_pass)
71
- check_elems << OpenStudio::Attribute.new('flag', "COP of #{reference_COP.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_full_load_efficiency.round(2)}.")
72
- end
73
- end
74
-
75
- # check CoilCoolingDXSingleSpeed objects (will also have curve check in different script)
76
- @model.getCoilCoolingDXSingleSpeeds.each do |component|
77
- # eff values from model
78
- rated_COP = component.ratedCOP.get
79
-
80
- # get eff values from standards
81
- if use_old_gem_code
82
- standard_minimum_cop = component.standard_minimum_cop(target_standard)
83
- else
84
- standard_minimum_cop = std.coil_cooling_dx_single_speed_standard_minimum_cop(component)
85
- end
86
-
87
- # check actual against target
88
- if standard_minimum_cop.nil?
89
- check_elems << OpenStudio::Attribute.new('flag', "Can't find target COP for #{component.name}.")
90
- elsif rated_COP < standard_minimum_cop * (1.0 - min_pass)
91
- check_elems << OpenStudio::Attribute.new('flag', "The COP of #{rated_COP.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_cop.round(2)} for #{display_standard}.")
92
- elsif rated_COP > standard_minimum_cop * (1.0 + max_pass)
93
- check_elems << OpenStudio::Attribute.new('flag', "The COP of #{rated_COP.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_cop.round(2)} for #{display_standard}.")
94
- end
95
- end
96
-
97
- # check CoilCoolingDXTwoSpeed objects (will also have curve check in different script)
98
- @model.getCoilCoolingDXTwoSpeeds.each do |component|
99
- # eff values from model
100
- rated_high_speed_COP = component.ratedHighSpeedCOP.get
101
- rated_low_speed_COP = component.ratedLowSpeedCOP.get
102
-
103
- # get eff values from standards
104
- if use_old_gem_code
105
- standard_minimum_cop = component.standard_minimum_cop(target_standard)
106
- else
107
- standard_minimum_cop = std.coil_cooling_dx_two_speed_standard_minimum_cop(component)
108
- end
109
-
110
- # check actual against target
111
- if standard_minimum_cop.nil?
112
- check_elems << OpenStudio::Attribute.new('flag', "Can't find target COP for #{component.name}.")
113
- elsif rated_high_speed_COP < standard_minimum_cop * (1.0 - min_pass)
114
- check_elems << OpenStudio::Attribute.new('flag', "The high speed COP of #{rated_high_speed_COP.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_cop.round(2)} for #{display_standard}.")
115
- elsif rated_high_speed_COP > standard_minimum_cop * (1.0 + max_pass)
116
- check_elems << OpenStudio::Attribute.new('flag', "The high speed COP of #{rated_high_speed_COP.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_cop.round(2)} for #{display_standard}.")
117
- end
118
- if standard_minimum_cop.nil?
119
- check_elems << OpenStudio::Attribute.new('flag', "Can't find target COP for #{component.name}.")
120
- elsif rated_low_speed_COP < standard_minimum_cop * (1.0 - min_pass)
121
- check_elems << OpenStudio::Attribute.new('flag', "The low speed COP of #{rated_low_speed_COP.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_cop.round(2)} for #{display_standard}.")
122
- elsif rated_low_speed_COP > standard_minimum_cop * (1.0 + max_pass)
123
- check_elems << OpenStudio::Attribute.new('flag', "The low speed COP of #{rated_low_speed_COP.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_cop.round(2)} for #{display_standard}.")
124
- end
125
- end
126
-
127
- # check CoilHeatingDXSingleSpeed objects
128
- # todo - need to test this once json file populated for this data
129
- @model.getCoilHeatingDXSingleSpeeds.each do |component|
130
- # eff values from model
131
- rated_COP = component.ratedCOP
132
-
133
- # get eff values from standards
134
- if use_old_gem_code
135
- standard_minimum_cop = component.standard_minimum_cop(target_standard)
136
- else
137
- standard_minimum_cop = std.coil_heating_dx_single_speed_standard_minimum_cop(component)
138
- end
139
-
140
- # check actual against target
141
- if standard_minimum_cop.nil?
142
- check_elems << OpenStudio::Attribute.new('flag', "Can't find target COP for #{component.name}.")
143
- elsif rated_COP < standard_minimum_cop * (1.0 - min_pass)
144
- check_elems << OpenStudio::Attribute.new('flag', "The COP of #{rated_COP.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_cop.round(2)} for #{display_standard}.")
145
- elsif rated_COP > standard_minimum_cop * (1.0 + max_pass)
146
- check_elems << OpenStudio::Attribute.new('flag', "The COP of #{rated_COP.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_cop.round(2)}. for #{display_standard}")
147
- end
148
- end
149
-
150
- # check BoilerHotWater
151
- @model.getBoilerHotWaters.each do |component|
152
- # eff values from model
153
- nominal_thermal_efficiency = component.nominalThermalEfficiency
154
-
155
- # get eff values from standards
156
- if use_old_gem_code
157
- standard_minimum_thermal_efficiency = component.standard_minimum_thermal_efficiency(target_standard)
158
- else
159
- standard_minimum_thermal_efficiency = std.boiler_hot_water_standard_minimum_thermal_efficiency(component)
160
- end
161
-
162
- # check actual against target
163
- if standard_minimum_thermal_efficiency.nil?
164
- check_elems << OpenStudio::Attribute.new('flag', "Can't find target thermal efficiency for #{component.name}.")
165
- elsif nominal_thermal_efficiency < standard_minimum_thermal_efficiency * (1.0 - min_pass)
166
- check_elems << OpenStudio::Attribute.new('flag', "Nominal thermal efficiency of #{nominal_thermal_efficiency.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_thermal_efficiency.round(2)} for #{display_standard}.")
167
- elsif nominal_thermal_efficiency > standard_minimum_thermal_efficiency * (1.0 + max_pass)
168
- check_elems << OpenStudio::Attribute.new('flag', "Nominal thermal efficiency of #{nominal_thermal_efficiency.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_thermal_efficiency.round(2)} for #{display_standard}.")
169
- end
170
- end
171
-
172
- # check FanConstantVolume
173
- @model.getFanConstantVolumes.each do |component|
174
- # eff values from model
175
- motor_eff = component.motorEfficiency
176
-
177
- # get eff values from standards
178
- if use_old_gem_code
179
- motor_bhp = component.brake_horsepower
180
- else
181
- motor_bhp = std.fan_brake_horsepower(component)
182
- end
183
-
184
- if use_old_gem_code
185
- standard_minimum_motor_efficiency_and_size = component.standard_minimum_motor_efficiency_and_size(target_standard, motor_bhp)[0]
186
- else
187
- standard_minimum_motor_efficiency_and_size = std.fan_standard_minimum_motor_efficiency_and_size(component, motor_bhp)[0]
188
- end
189
-
190
- # check actual against target
191
- if motor_eff < standard_minimum_motor_efficiency_and_size * (1.0 - min_pass)
192
- check_elems << OpenStudio::Attribute.new('flag', "Motor efficiency of #{motor_eff.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_motor_efficiency_and_size.round(2)} for #{display_standard}.")
193
- elsif motor_eff > standard_minimum_motor_efficiency_and_size * (1.0 + max_pass)
194
- check_elems << OpenStudio::Attribute.new('flag', "Motor efficiency of #{motor_eff.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_motor_efficiency_and_size.round(2)} for #{display_standard}.")
195
- end
196
- end
197
-
198
- # check FanVariableVolume
199
- @model.getFanVariableVolumes.each do |component|
200
- # eff values from model
201
- motor_eff = component.motorEfficiency
202
-
203
- # get eff values from standards
204
- if use_old_gem_code
205
- motor_bhp = component.brake_horsepower
206
- else
207
- motor_bhp = std.fan_brake_horsepower(component)
208
- end
209
- if use_old_gem_code
210
- standard_minimum_motor_efficiency_and_size = component.standard_minimum_motor_efficiency_and_size(target_standard, motor_bhp)[0]
211
- else
212
- standard_minimum_motor_efficiency_and_size = std.fan_standard_minimum_motor_efficiency_and_size(component, motor_bhp)[0]
213
- end
214
-
215
- # check actual against target
216
- if motor_eff < standard_minimum_motor_efficiency_and_size * (1.0 - min_pass)
217
- check_elems << OpenStudio::Attribute.new('flag', "Motor efficiency of #{motor_eff.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_motor_efficiency_and_size.round(2)} for #{display_standard}.")
218
- elsif motor_eff > standard_minimum_motor_efficiency_and_size * (1.0 + max_pass)
219
- check_elems << OpenStudio::Attribute.new('flag', "Motor efficiency of #{motor_eff.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_motor_efficiency_and_size.round(2)} for #{display_standard}.")
220
- end
221
- end
222
-
223
- # check PumpConstantSpeed
224
- @model.getPumpConstantSpeeds.each do |component|
225
- # eff values from model
226
- motor_eff = component.motorEfficiency
227
-
228
- # get eff values from standards
229
- if use_old_gem_code
230
- motor_bhp = component.brake_horsepower
231
- else
232
- motor_bhp = std.pump_brake_horsepower(component)
233
- end
234
- next if motor_bhp == 0.0
235
- if use_old_gem_code
236
- standard_minimum_motor_efficiency_and_size = component.standard_minimum_motor_efficiency_and_size(target_standard, motor_bhp)[0]
237
- else
238
- standard_minimum_motor_efficiency_and_size = std.pump_standard_minimum_motor_efficiency_and_size(component, motor_bhp)[0]
239
- end
240
-
241
- # check actual against target
242
- if motor_eff < standard_minimum_motor_efficiency_and_size * (1.0 - min_pass)
243
- check_elems << OpenStudio::Attribute.new('flag', "Motor efficiency of #{motor_eff.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_motor_efficiency_and_size.round(2)} for #{display_standard}.")
244
- elsif motor_eff > standard_minimum_motor_efficiency_and_size * (1.0 + max_pass)
245
- check_elems << OpenStudio::Attribute.new('flag', "Motor efficiency of #{motor_eff.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_motor_efficiency_and_size.round(2)} for #{display_standard}.")
246
- end
247
- end
248
-
249
- # check PumpVariableSpeed
250
- @model.getPumpVariableSpeeds.each do |component|
251
- # eff values from model
252
- motor_eff = component.motorEfficiency
253
-
254
- # get eff values from standards
255
- if use_old_gem_code
256
- motor_bhp = component.brake_horsepower
257
- else
258
- motor_bhp = std.pump_brake_horsepower(component)
259
- end
260
- next if motor_bhp == 0.0
261
- if use_old_gem_code
262
- standard_minimum_motor_efficiency_and_size = component.standard_minimum_motor_efficiency_and_size(target_standard, motor_bhp)[0]
263
- else
264
- standard_minimum_motor_efficiency_and_size = std.pump_standard_minimum_motor_efficiency_and_size(component, motor_bhp)[0]
265
- end
266
-
267
- # check actual against target
268
- if motor_eff < standard_minimum_motor_efficiency_and_size * (1.0 - min_pass)
269
- check_elems << OpenStudio::Attribute.new('flag', "Motor efficiency of #{motor_eff.round(2)} for #{component.name} is more than #{min_pass * 100} % below the expected value of #{standard_minimum_motor_efficiency_and_size.round(2)} for #{display_standard}.")
270
- elsif motor_eff > standard_minimum_motor_efficiency_and_size * (1.0 + max_pass)
271
- check_elems << OpenStudio::Attribute.new('flag', "Motor efficiency of #{motor_eff.round(2)} for #{component.name} is more than #{max_pass * 100} % above the expected value of #{standard_minimum_motor_efficiency_and_size.round(2)} for #{display_standard}.")
272
- end
273
- end
274
-
275
- # TODO: - should I throw flag if any other component types are in the model
276
-
277
- # BasicOfficeTest_Mueller.osm test model current exercises the following component types
278
- # (CoilCoolingDXTwoSpeed,FanVariableVolume,PumpConstantSpeed)
279
-
280
- # BasicOfficeTest_Mueller_altHVAC_a checks these component types
281
- # (ChillerElectricEIR,CoilCoolingDXSingleSpeed,CoilHeatingDXSingleSpeed,BoilerHotWater,FanConstantVolume,PumpVariableSpeed)
282
- rescue StandardError => e
283
- # brief description of ruby error
284
- check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")
285
-
286
- # backtrace of ruby error for diagnostic use
287
- if @error_backtrace then check_elems << OpenStudio::Attribute.new('flag', e.backtrace.join("\n").to_s) end
288
- end
289
-
290
- # add check_elms to new attribute
291
- check_elem = OpenStudio::Attribute.new('check', check_elems)
292
-
293
- return check_elem
294
- # note: registerWarning and registerValue will be added for checks downstream using os_lib_reporting_qaqc.rb
295
- end
296
- end