openstudio-common-measures 0.5.0 → 0.6.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -1
  3. data/README.md +7 -2
  4. data/doc_templates/copyright_erb.txt +1 -1
  5. data/lib/measures/AddCostPerFloorAreaUnusedToLights/measure.xml +2 -8
  6. data/lib/measures/AddCostToSupplySideHVACComponentByAirLoop/measure.xml +9 -3
  7. data/lib/measures/AddSimplePvToShadingSurfacesByType/measure.xml +2 -2
  8. data/lib/measures/RemoveUnusedDefaultProfiles/measure.xml +2 -2
  9. data/lib/measures/ReportModelChanges/measure.xml +2 -2
  10. data/lib/measures/SetCOPforSingleSpeedDXCoolingUnits/measure.xml +4 -4
  11. data/lib/measures/SetCOPforTwoSpeedDXCoolingUnits/measure.xml +4 -4
  12. data/lib/measures/SetGasBurnerEfficiency/measure.xml +4 -4
  13. data/lib/measures/ShiftScheduleProfileTime/measure.xml +4 -4
  14. data/lib/measures/SwapLightsDefinition/measure.xml +3 -5
  15. data/lib/measures/add_ems_emissions_reporting/measure.rb +236 -29
  16. data/lib/measures/add_ems_emissions_reporting/measure.xml +362 -10
  17. data/lib/measures/add_ev_load/measure.rb +51 -8
  18. data/lib/measures/add_ev_load/measure.xml +23 -5
  19. data/lib/measures/envelope_and_internal_load_breakdown/measure.xml +3 -3
  20. data/lib/measures/envelope_and_internal_load_breakdown/resources/report.html.erb +5 -1
  21. data/lib/measures/example_report/measure.xml +3 -3
  22. data/lib/measures/example_report/resources/report.html.erb +5 -1
  23. data/lib/measures/generic_qaqc/README.md +19 -4
  24. data/lib/measures/generic_qaqc/README.md.erb +7 -1
  25. data/lib/measures/generic_qaqc/docs/generic_qaqc_detailed.jpg +0 -0
  26. data/lib/measures/generic_qaqc/docs/generic_qaqc_summary.jpg +0 -0
  27. data/lib/measures/generic_qaqc/measure.rb +34 -29
  28. data/lib/measures/generic_qaqc/measure.xml +181 -82
  29. data/lib/measures/generic_qaqc/resources/check_cond_zns.rb +3 -1
  30. data/lib/measures/generic_qaqc/resources/check_domestic_hot_water.rb +13 -8
  31. data/lib/measures/generic_qaqc/resources/check_envelope_conductance.rb +330 -231
  32. data/lib/measures/generic_qaqc/resources/check_eui_by_end_use.rb +59 -20
  33. data/lib/measures/generic_qaqc/resources/check_eui_reasonableness.rb +58 -20
  34. data/lib/measures/generic_qaqc/resources/check_internal_loads.rb +57 -56
  35. data/lib/measures/generic_qaqc/resources/check_mech_sys_capacity.rb +4 -1
  36. data/lib/measures/generic_qaqc/resources/check_mech_sys_efficiency.rb +27 -22
  37. data/lib/measures/generic_qaqc/resources/check_mech_sys_part_load_eff.rb +4 -1
  38. data/lib/measures/generic_qaqc/resources/check_mech_sys_type.rb +3 -3
  39. data/lib/measures/generic_qaqc/resources/check_schedules.rb +65 -101
  40. data/lib/measures/generic_qaqc/resources/check_simultaneous_heating_and_cooling.rb +3 -1
  41. data/lib/measures/generic_qaqc/resources/check_supply_air_and_thermostat_temp_difference.rb +3 -1
  42. data/lib/measures/generic_qaqc/resources/os_lib_reporting_qaqc.rb +49 -15
  43. data/lib/measures/generic_qaqc/resources/report.html.erb +5 -1
  44. data/lib/measures/hvac_psychrometric_chart/measure.xml +3 -3
  45. data/lib/measures/hvac_psychrometric_chart/resources/report.html.erb +5 -1
  46. data/lib/measures/openstudio_results/measure.xml +3 -3
  47. data/lib/measures/openstudio_results/resources/report.html.erb +5 -1
  48. data/lib/measures/set_run_period/measure.xml +2 -2
  49. data/lib/measures/view_data/measure.xml +4 -4
  50. data/lib/measures/view_data/resources/report.html.in +189 -19
  51. data/lib/measures/view_data/resources/va3c.rb +1 -0
  52. data/lib/measures/view_model/measure.xml +9 -9
  53. data/lib/measures/view_model/resources/report.html.in +189 -19
  54. data/lib/measures/view_model/resources/va3c.rb +1 -0
  55. data/lib/openstudio/common_measures/version.rb +1 -1
  56. data/openstudio-common-measures.gemspec +1 -1
  57. metadata +7 -5
@@ -36,6 +36,86 @@
36
36
  module OsLib_QAQC
37
37
  # include any general notes about QAQC method here
38
38
 
39
+ # common methods
40
+ def map_surface_props(surface, check_elems, defaulted_const_type)
41
+
42
+ # see of standards info to get standard construction type if set
43
+ construction = surface.construction.get
44
+ const_standards = construction.standardsInformation
45
+ if const_standards.standardsConstructionType.is_initialized
46
+ const_type = const_standards.standardsConstructionType.get
47
+ if surface.surfaceType == "Wall"
48
+ ext_surf_type = "ExteriorWall"
49
+ elsif surface.surfaceType == "RoofCeiling"
50
+ ext_surf_type = "ExteriorRoof"
51
+ elsif surface.surfaceType == "Floor"
52
+ ext_surf_type = "ExteriorFloor"
53
+ else
54
+ ext_surf_type = nil # should not hit this
55
+ end
56
+ else
57
+ if surface.surfaceType == "Wall"
58
+ ext_surf_type = 'ExteriorWall'
59
+ const_type = 'SteelFramed'
60
+ elsif surface.surfaceType == "RoofCeiling"
61
+ ext_surf_type = 'ExteriorRoof'
62
+ const_type = 'IEAD'
63
+ elsif surface.surfaceType == "Floor"
64
+ ext_surf_type = 'ExteriorFloor'
65
+ const_type = 'Mass'
66
+ end
67
+ if !defaulted_const_type.include?(construction)
68
+ check_elems << OpenStudio::Attribute.new('flag', "#{construction.name} is not associated with a standards construction type, checking based on #{const_type} for #{ext_surf_type}.")
69
+ defaulted_const_type << construction
70
+ end
71
+ end
72
+
73
+ return {ext_surf_type: ext_surf_type, const_type: const_type, construction: construction}
74
+
75
+ end
76
+
77
+ def map_sub_surfaces_props(sub_surface, check_elems, defaulted_const_type)
78
+
79
+ construction = sub_surface.construction.get
80
+ const_standards = construction.standardsInformation
81
+ if const_standards.standardsConstructionType.is_initialized
82
+ sub_const_type = const_standards.standardsConstructionType.get
83
+
84
+ if sub_surface.subSurfaceType == "Door" || sub_surface.subSurfaceType == "OverheadDoor"
85
+ ext_sub_surf_type = "ExteriorDoor"
86
+ elsif sub_surface.subSurfaceType == "FixedWindow" || sub_surface.subSurfaceType == "OperableWindow"
87
+ ext_sub_surf_type = "ExteriorWindow"
88
+ elsif sub_surface.subSurfaceType == "Skylight"
89
+ ext_sub_surf_type = "Skylight"
90
+ else
91
+ # todo - add message about constructions not being checked
92
+ ext_sub_surf_type = sub_surface.surfaceType # address and test GlassDoor
93
+ end
94
+ else
95
+ if sub_surface.subSurfaceType == "Door"
96
+ ext_sub_surf_type = 'ExteriorDoor'
97
+ sub_const_type = 'Swinging'
98
+ elsif sub_surface.subSurfaceType == "OverheadDoor"
99
+ ext_sub_surf_type = 'ExteriorDoor'
100
+ sub_const_type = 'NonSwinging'
101
+ elsif sub_surface.subSurfaceType == "FixedWindow" || sub_surface.subSurfaceType == "OperableWindow"
102
+ ext_sub_surf_type = 'ExteriorWindow'
103
+ sub_const_type = 'Metal framing (all other)'
104
+ elsif sub_surface.subSurfaceType == "Skylight"
105
+ ext_sub_surf_type = 'Skylight'
106
+ sub_const_type = 'Glass with Curb'
107
+ else
108
+ check_elems << OpenStudio::Attribute.new('flag', "#{construction.name} is not associated with a standards construction type, this measure does not have default target mapping for #{sub_surface.surfaceType} sub-surface types.")
109
+ end
110
+ if !defaulted_const_type.include?(construction)
111
+ check_elems << OpenStudio::Attribute.new('flag', "#{construction.name} is not associated with a standards construction type, checking based on #{sub_const_type} for #{ext_sub_surf_type}.")
112
+ defaulted_const_type << construction
113
+ end
114
+ end
115
+
116
+ return {ext_sub_surf_type: ext_sub_surf_type, sub_const_type: sub_const_type, construction: construction}
117
+ end
118
+
39
119
  # checks the number of unmet hours in the model
40
120
  # todo - do I need unique tolerance ranges for conductance, reflectance, and shgc
41
121
  def check_envelope_conductance(category, target_standard, min_pass, max_pass, name_only = false)
@@ -58,79 +138,68 @@ module OsLib_QAQC
58
138
  end
59
139
  check_elems << OpenStudio::Attribute.new('description', "Check envelope against #{display_standard}. Roof reflectance of 55%, wall relfectance of 30%.")
60
140
  end
61
-
141
+ check_elems << OpenStudio::Attribute.new('min_pass', min_pass * 100)
142
+ check_elems << OpenStudio::Attribute.new('max_pass', max_pass * 100)
143
+
62
144
  # stop here if only name is requested this is used to populate display name for arguments
63
145
  if name_only == true
64
146
  results = []
65
147
  check_elems.each do |elem|
148
+ next if ['Double','Integer'].include? (elem.valueType.valueDescription)
66
149
  results << elem.valueAsString
67
150
  end
68
151
  return results
69
152
  end
70
153
 
71
- # list of surface types to identify for each space type for surfaces and sub-surfaces
72
- construction_type_array = []
73
- construction_type_array << ['ExteriorWall', 'SteelFramed']
74
- construction_type_array << ['ExteriorRoof', 'IEAD']
75
- construction_type_array << ['ExteriorFloor', 'Mass']
76
- construction_type_array << ['ExteriorDoor', 'Swinging']
77
- construction_type_array << ['ExteriorWindow', 'Metal framing (all other)']
78
- construction_type_array << ['Skylight', 'Glass with Curb']
79
- # overhead door doesn't show in list, or glass door
80
-
81
- # Versions of OpenStudio greater than 2.4.0 use a modified version of
82
- # openstudio-standards with different method calls. These methods
83
- # require a "Standard" object instead of the standard being passed into method calls.
84
- # This Standard object is used throughout the QAQC check.
85
- if OpenStudio::VersionString.new(OpenStudio.openStudioVersion) < OpenStudio::VersionString.new('2.4.3')
86
- use_old_gem_code = true
87
- else
88
- use_old_gem_code = false
154
+ begin
155
+
156
+ # setup standard
89
157
  std = Standard.build(target_standard)
90
- end
158
+
159
+ # gather building type for summary
160
+ bt_cz = std.model_get_building_climate_zone_and_building_type(@model)
161
+ building_type = bt_cz['building_type']
162
+ climate_zone = bt_cz['climate_zone']
163
+ prototype_prefix = "#{target_standard} #{building_type} #{climate_zone}"
164
+
165
+ # make array of construction details for surfaces
166
+ surface_details = []
167
+ missing_surface_constructions = []
168
+ sub_surface_details = []
169
+ missing_sub_surface_constructions = []
170
+ construction_type_array = []
171
+ space_type_const_properties = {}
172
+ defaulted_const_type = []
173
+ data_not_returned_for = []
91
174
 
92
- begin
93
175
  # loop through all space types used in the model
94
176
  @model.getSpaceTypes.each do |space_type|
95
177
  next if space_type.floorArea <= 0
96
- space_type_const_properties = {}
97
- construction_type_array.each do |const_type|
98
- # gather data for exterior wall
99
- intended_surface_type = const_type[0]
100
- standards_construction_type = const_type[1]
101
- space_type_const_properties[intended_surface_type] = {}
102
- if use_old_gem_code
103
- data = space_type.get_construction_properties(target_standard, intended_surface_type, standards_construction_type)
104
- else
105
- data = std.space_type_get_construction_properties(space_type, intended_surface_type, standards_construction_type)
106
- end
107
- if data.nil?
108
- puts "lookup for #{target_standard},#{intended_surface_type},#{standards_construction_type}"
109
- check_elems << OpenStudio::Attribute.new('flag', "Didn't find construction for #{standards_construction_type} #{intended_surface_type} for #{space_type.name}.")
110
- elsif intended_surface_type.include? 'ExteriorWall' || 'ExteriorFloor' || 'ExteriorDoor'
111
- space_type_const_properties[intended_surface_type]['u_value'] = data['assembly_maximum_u_value']
112
- space_type_const_properties[intended_surface_type]['reflectance'] = 0.30 # hard coded value
113
- elsif intended_surface_type.include? 'ExteriorRoof'
114
- space_type_const_properties[intended_surface_type]['u_value'] = data['assembly_maximum_u_value']
115
- space_type_const_properties[intended_surface_type]['reflectance'] = 0.55 # hard coded value
116
- else
117
- space_type_const_properties[intended_surface_type]['u_value'] = data['assembly_maximum_u_value']
118
- space_type_const_properties[intended_surface_type]['shgc'] = data['assembly_maximum_solar_heat_gain_coefficient']
119
- end
120
- end
121
-
122
- # make array of construction details for surfaces
123
- surface_details = []
124
- missing_surface_constructions = []
125
- sub_surface_details = []
126
- missing_sub_surface_constructions = []
127
178
 
128
179
  # loop through spaces
129
180
  space_type.spaces.each do |space|
130
181
  space.surfaces.each do |surface|
131
182
  next if surface.outsideBoundaryCondition != 'Outdoors'
132
183
  if surface.construction.is_initialized
133
- surface_details << { boundary_condition: surface.outsideBoundaryCondition, surface_type: surface.surfaceType, construction: surface.construction.get }
184
+ surf_props = self.map_surface_props(surface,check_elems,defaulted_const_type)
185
+ ext_surf_type = surf_props[:ext_surf_type]
186
+ const_type = surf_props[:const_type]
187
+ construction = surf_props[:construction]
188
+
189
+ # todo - need to get and add the building_category for this space/space type and add to surface_details. If can't identify then issue warning and assume it is nonresidential
190
+ data = std.space_type_get_construction_properties(space_type, ext_surf_type, const_type)
191
+ if !data.nil?
192
+ const_bldg_cat = data['building_category']
193
+ surface_details << { boundary_condition: surface.outsideBoundaryCondition, surface_type: ext_surf_type, construction: construction, construction_type: const_type, const_bldg_cat: const_bldg_cat }
194
+ if !construction_type_array.include? [ext_surf_type,const_type,const_bldg_cat]
195
+ construction_type_array << [ext_surf_type,const_type,const_bldg_cat]
196
+ end
197
+ else
198
+ if !data_not_returned_for.include?([space_type,ext_surf_type,const_type])
199
+ check_elems << OpenStudio::Attribute.new('flag', "Data not returned for #{space_type.name} on #{const_type} for #{ext_surf_type}.")
200
+ data_not_returned_for << [space_type,ext_surf_type,const_type]
201
+ end
202
+ end
134
203
  else
135
204
  missing_constructions << surface.name.get
136
205
  end
@@ -138,7 +207,24 @@ module OsLib_QAQC
138
207
  # make array of construction details for sub_surfaces
139
208
  surface.subSurfaces.each do |sub_surface|
140
209
  if sub_surface.construction.is_initialized
141
- sub_surface_details << { boundary_condition: sub_surface.outsideBoundaryCondition, surface_type: sub_surface.subSurfaceType, construction: sub_surface.construction.get }
210
+ sub_surf_props = self.map_sub_surfaces_props(sub_surface,check_elems,defaulted_const_type)
211
+ ext_sub_surf_type = sub_surf_props[:ext_sub_surf_type]
212
+ sub_const_type = sub_surf_props[:sub_const_type]
213
+ construction = sub_surf_props[:construction]
214
+
215
+ data = std.space_type_get_construction_properties(space_type, ext_sub_surf_type, sub_const_type)
216
+ if !data.nil?
217
+ const_bldg_cat = data['building_category']
218
+ sub_surface_details << {boundary_condition: sub_surface.outsideBoundaryCondition, surface_type: ext_sub_surf_type, construction: sub_surface.construction.get, construction_type: sub_const_type, const_bldg_cat: const_bldg_cat}
219
+ if !construction_type_array.include? [ext_sub_surf_type,sub_const_type,const_bldg_cat]
220
+ construction_type_array << [ext_sub_surf_type,sub_const_type,const_bldg_cat]
221
+ end
222
+ else
223
+ if !data_not_returned_for.include?([space_type,ext_sub_surf_type,sub_const_type])
224
+ check_elems << OpenStudio::Attribute.new('flag', "Data not returned for #{space_type.name} on #{sub_const_type} for #{ext_sub_surf_type}.")
225
+ data_not_returned_for << [space_type,ext_sub_surf_type,sub_const_type]
226
+ end
227
+ end
142
228
  else
143
229
  missing_constructions << sub_surface.name.get
144
230
  end
@@ -147,171 +233,193 @@ module OsLib_QAQC
147
233
  end
148
234
 
149
235
  if !missing_surface_constructions.empty?
150
- check_elems << OpenStudio::Attribute.new('flag', "#{missing_constructions.size} surfaces are missing constructions in #{space_type.name}. Spaces and can't be checked.")
236
+ check_elems << OpenStudio::Attribute.new('flag', "#{missing_constructions.size} surfaces are missing constructions in #{space_type.name}.")
151
237
  end
152
238
 
153
239
  if !missing_sub_surface_constructions.empty?
154
- check_elems << OpenStudio::Attribute.new('flag', "#{missing_constructions.size} sub surfaces are missing constructions in #{space_type.name}. Spaces and can't be checked.")
240
+ check_elems << OpenStudio::Attribute.new('flag', "#{missing_constructions.size} sub surfaces are missing constructions in #{space_type.name}.")
155
241
  end
156
242
 
157
- # gather targer values for this space type
158
- # todo - address support for other surface types e.g. overhead door glass door
159
- target_r_value_ip = {}
160
- target_reflectance = {}
161
- target_u_value_ip = {}
162
- target_shgc = {}
163
- target_r_value_ip['Wall'] = 1.0 / space_type_const_properties['ExteriorWall']['u_value'].to_f
164
- target_reflectance['Wall'] = space_type_const_properties['ExteriorWall']['reflectance'].to_f
165
- target_r_value_ip['RoofCeiling'] = 1.0 / space_type_const_properties['ExteriorRoof']['u_value'].to_f
166
- target_reflectance['RoofCeiling'] = space_type_const_properties['ExteriorRoof']['reflectance'].to_f
167
- target_r_value_ip['Floor'] = 1.0 / space_type_const_properties['ExteriorFloor']['u_value'].to_f
168
- target_reflectance['Floor'] = space_type_const_properties['ExteriorFloor']['reflectance'].to_f
169
- target_r_value_ip['Door'] = 1.0 / space_type_const_properties['ExteriorDoor']['u_value'].to_f
170
- target_reflectance['Door'] = space_type_const_properties['ExteriorDoor']['reflectance'].to_f
171
- target_u_value_ip['FixedWindow'] = space_type_const_properties['ExteriorWindow']['u_value'].to_f
172
- target_shgc['FixedWindow'] = space_type_const_properties['ExteriorWindow']['shgc'].to_f
173
- target_u_value_ip['OperableWindow'] = space_type_const_properties['ExteriorWindow']['u_value'].to_f
174
- target_shgc['OperableWindow'] = space_type_const_properties['ExteriorWindow']['shgc'].to_f
175
- target_u_value_ip['Skylight'] = space_type_const_properties['Skylight']['u_value'].to_f
176
- target_shgc['Skylight'] = space_type_const_properties['Skylight']['shgc'].to_f
177
-
178
- # loop through unique construction arary combinations
179
- surface_details.uniq.each do |surface_detail|
180
- if surface_detail[:construction].thermalConductance.is_initialized
243
+ construction_type_array.each do |const_attributes|
244
+ # gather data for exterior wall
245
+ intended_surface_type = const_attributes[0]
246
+ standards_construction_type = const_attributes[1]
247
+ if !space_type_const_properties.key?(intended_surface_type)
248
+ space_type_const_properties[intended_surface_type] = {}
249
+ end
250
+ if !space_type_const_properties[intended_surface_type].key?(standards_construction_type)
251
+ space_type_const_properties[intended_surface_type][standards_construction_type] = {}
252
+ end
181
253
 
182
- # don't use intened surface type of construction, look map based on surface type and boundary condition
183
- boundary_condition = surface_detail[:boundary_condition]
184
- surface_type = surface_detail[:surface_type]
185
- intended_surface_type = ''
186
- if boundary_condition.to_s == 'Outdoors'
187
- if surface_type.to_s == 'Wall' then intended_surface_type = 'ExteriorWall' end
188
- if surface_type == 'RoofCeiling' then intended_surface_type = 'ExteriorRoof' end
189
- if surface_type == 'Floor' then intended_surface_type = 'ExteriorFloor' end
190
- else
191
- # currently only used for surfaces with outdoor boundary condition
254
+ data = std.space_type_get_construction_properties(space_type, intended_surface_type, standards_construction_type)
255
+ if data.nil?
256
+ check_elems << OpenStudio::Attribute.new('flag', "Didn't find target construction values for #{target_standard} #{standards_construction_type} #{intended_surface_type} for #{space_type.name}.")
257
+ elsif ['ExteriorWall','ExteriorDoor'].include? intended_surface_type
258
+ const_bldg_cat = data['building_category']
259
+ if !space_type_const_properties[intended_surface_type][standards_construction_type].key?(const_bldg_cat)
260
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat] = {}
192
261
  end
193
- if use_old_gem_code
194
- film_coefficients_r_value = surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get.film_coefficients_r_value(intended_surface_type)
195
- else
196
- film_coefficients_r_value = std.film_coefficients_r_value(intended_surface_type, includes_int_film = true, includes_ext_film = true)
262
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat]['u_value'] = data['assembly_maximum_u_value']
263
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat]['reflectance'] = 0.30 # hard coded value
264
+ elsif intended_surface_type.include? 'ExteriorFloor'
265
+ const_bldg_cat = data['building_category']
266
+ if !space_type_const_properties[intended_surface_type][standards_construction_type].key?(const_bldg_cat)
267
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat] = {}
197
268
  end
198
- thermal_conductance = surface_detail[:construction].thermalConductance.get
199
- r_value_with_film = 1 / thermal_conductance + film_coefficients_r_value
200
- source_units = 'm^2*K/W'
201
- target_units = 'ft^2*h*R/Btu'
202
- r_value_ip = OpenStudio.convert(r_value_with_film, source_units, target_units).get
203
- solar_reflectance = surface_detail[:construction].to_LayeredConstruction.get.layers[0].to_OpaqueMaterial.get.solarReflectance .get # TODO: - check optional first does what happens with ext. air wall
204
-
205
- # stop if didn't find values (0 or infinity)
206
- next if target_r_value_ip[surface_detail[:surface_type]] == 0.0
207
- next if target_r_value_ip[surface_detail[:surface_type]] == Float::INFINITY
208
-
209
- # check r avlues
210
- if r_value_ip < target_r_value_ip[surface_detail[:surface_type]] * (1.0 - min_pass)
211
- check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{surface_detail[:construction].name} in #{space_type.name} is more than #{min_pass * 100} % below the expected value of #{target_r_value_ip[surface_detail[:surface_type]].round(2)} (#{target_units}) for #{display_standard}.")
212
- elsif r_value_ip > target_r_value_ip[surface_detail[:surface_type]] * (1.0 + max_pass)
213
- check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{surface_detail[:construction].name} in #{space_type.name} is more than #{max_pass * 100} % above the expected value of #{target_r_value_ip[surface_detail[:surface_type]].round(2)} (#{target_units}) for #{display_standard}.")
269
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat]['u_value'] = data['assembly_maximum_u_value']
270
+ elsif intended_surface_type.include? 'ExteriorRoof'
271
+ const_bldg_cat = data['building_category']
272
+ if !space_type_const_properties[intended_surface_type][standards_construction_type].key?(const_bldg_cat)
273
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat] = {}
214
274
  end
275
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat]['u_value'] = data['assembly_maximum_u_value']
276
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat]['reflectance'] = 0.55 # hard coded value
277
+ else # glazing
278
+ const_bldg_cat = data['building_category']
279
+ if !space_type_const_properties[intended_surface_type][standards_construction_type].key?(const_bldg_cat)
280
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat] = {}
281
+ end
282
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat]['u_value'] = data['assembly_maximum_u_value']
283
+ space_type_const_properties[intended_surface_type][standards_construction_type][const_bldg_cat]['shgc'] = data['assembly_maximum_solar_heat_gain_coefficient']
284
+ end
285
+ end
286
+ end
215
287
 
216
- # check solar reflectance
217
- if (solar_reflectance < target_reflectance[surface_detail[:surface_type]] * (1.0 - min_pass)) && (target_standard != 'ICC IECC 2015')
218
- check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{surface_detail[:construction].name} in #{space_type.name} is more than #{min_pass * 100} % below the expected value of #{(target_reflectance[surface_detail[:surface_type]] * 100).round} %.")
219
- elsif (solar_reflectance > target_reflectance[surface_detail[:surface_type]] * (1.0 + max_pass)) && (target_standard != 'ICC IECC 2015')
220
- check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{surface_detail[:construction].name} in #{space_type.name} is more than #{max_pass * 100} % above the expected value of #{(target_reflectance[surface_detail[:surface_type]] * 100).round} %.")
221
- end
288
+ # loop through unique construction arary combinations
289
+ surface_details.uniq.each do |surface_detail|
290
+ if surface_detail[:construction].thermalConductance.is_initialized
291
+
292
+ # don't use intened surface type of construction, look map based on surface type and boundary condition
293
+ boundary_condition = surface_detail[:boundary_condition]
294
+ intended_surface_type = surface_detail[:surface_type]
295
+ construction_type = surface_detail[:construction_type]
296
+ next if boundary_condition.to_s != 'Outdoors'
297
+
298
+ film_coefficients_r_value = std.film_coefficients_r_value(intended_surface_type, includes_int_film = true, includes_ext_film = true)
299
+ thermal_conductance = surface_detail[:construction].thermalConductance.get
300
+ r_value_with_film = 1 / thermal_conductance + film_coefficients_r_value
301
+ source_units = 'm^2*K/W'
302
+ target_units = 'ft^2*h*R/Btu'
303
+ r_value_ip = OpenStudio.convert(r_value_with_film, source_units, target_units).get
304
+ solar_reflectance = surface_detail[:construction].to_LayeredConstruction.get.layers[0].to_OpaqueMaterial.get.solarReflectance .get # TODO: - check optional first does what happens with ext. air wall
305
+ const_bldg_cat = surface_detail[:const_bldg_cat]
306
+
307
+ # lookup target_r_value_ip
308
+ target_r_value_ip = 1.0 / space_type_const_properties[intended_surface_type][construction_type][const_bldg_cat]['u_value'].to_f
309
+
310
+ # stop if didn't find values (0 or infinity)
311
+ next if construction_type == 0.0
312
+ next if construction_type == Float::INFINITY
313
+
314
+ # check r avlues
315
+ if r_value_ip < target_r_value_ip * (1.0 - min_pass)
316
+ check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{min_pass * 100} % below the value of #{target_r_value_ip.round(2)} (#{target_units}) for #{prototype_prefix} #{surface_detail[:construction_type]}.")
317
+ elsif r_value_ip > target_r_value_ip * (1.0 + max_pass)
318
+ check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{max_pass * 100} % above the value of #{target_r_value_ip.round(2)} (#{target_units}) for #{prototype_prefix} #{surface_detail[:construction_type]}.")
319
+ end
222
320
 
223
- else
224
- check_elems << OpenStudio::Attribute.new('flag', "Can't calculate R value for #{surface_detail[:construction].name}.")
321
+ # lookup target_reflectance
322
+ target_reflectance = space_type_const_properties[intended_surface_type][construction_type][const_bldg_cat]['reflectance'].to_f
323
+
324
+ # check solar reflectance
325
+ next if intended_surface_type == 'ExteriorFloor' # do not check reflectance exterior floors (overhang)
326
+ if (solar_reflectance < target_reflectance * (1.0 - min_pass)) && (target_standard != 'ICC IECC 2015')
327
+ check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{min_pass * 100} % below the value of #{(target_reflectance * 100).round} %.")
328
+ elsif (solar_reflectance > target_reflectance * (1.0 + max_pass)) && (target_standard != 'ICC IECC 2015')
329
+ check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{max_pass * 100} % above the value of #{(target_reflectance * 100).round} %.")
225
330
  end
331
+
332
+ else
333
+ check_elems << OpenStudio::Attribute.new('flag', "Can't calculate R value for #{surface_detail[:construction].name}.")
226
334
  end
335
+ end
227
336
 
228
- # loop through unique construction arary combinations
229
- sub_surface_details.uniq.each do |sub_surface_detail|
230
- if sub_surface_detail[:surface_type] == 'FixedWindow' || sub_surface_detail[:surface_type] == 'OperableWindow' || sub_surface_detail[:surface_type] == 'Skylight'
231
- # check for non opaque sub surfaces
232
- source_units = 'W/m^2*K'
233
- target_units = 'Btu/ft^2*h*R'
337
+ # loop through unique construction arary combinations
338
+ sub_surface_details.uniq.each do |sub_surface_detail|
339
+ if sub_surface_detail[:surface_type] == 'ExteriorWindow' || sub_surface_detail[:surface_type] == 'Skylight'
340
+ # check for non opaque sub surfaces
341
+ source_units = 'W/m^2*K'
342
+ target_units = 'Btu/ft^2*h*R'
343
+ u_factor_si = std.construction_calculated_u_factor(sub_surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get)
344
+ u_factor_ip = OpenStudio.convert(u_factor_si, source_units, target_units).get
345
+ shgc = std.construction_calculated_solar_heat_gain_coefficient(sub_surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get)
346
+ intended_surface_type = sub_surface_detail[:surface_type]
347
+ construction_type = sub_surface_detail[:construction_type]
348
+ const_bldg_cat = sub_surface_detail[:const_bldg_cat]
349
+ boundary_condition = sub_surface_detail[:boundary_condition]
350
+ next if boundary_condition.to_s != 'Outdoors'
351
+
352
+ # lookup target_u_value_ip
353
+ target_u_value_ip = space_type_const_properties[intended_surface_type][construction_type][const_bldg_cat]['u_value'].to_f
354
+
355
+ # stop if didn't find values (0 or infinity)
356
+ next if target_u_value_ip == 0.0
357
+ next if target_u_value_ip == Float::INFINITY
358
+
359
+ # check u avlues
360
+ if u_factor_ip < target_u_value_ip * (1.0 - min_pass)
361
+ check_elems << OpenStudio::Attribute.new('flag', "U value of #{u_factor_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{min_pass * 100} % below the value of #{target_u_value_ip.round(2)} (#{target_units}) for #{prototype_prefix} #{sub_surface_detail[:construction_type]}.")
362
+ elsif u_factor_ip > target_u_value_ip * (1.0 + max_pass)
363
+ check_elems << OpenStudio::Attribute.new('flag', "U value of #{u_factor_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{max_pass * 100} % above the value of #{target_u_value_ip.round(2)} (#{target_units}) for #{prototype_prefix} #{sub_surface_detail[:construction_type]}.")
364
+ end
234
365
 
235
- if use_old_gem_code
236
- u_factor_si = sub_surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get.calculated_u_factor
237
- else
238
- u_factor_si = std.construction_calculated_u_factor(sub_surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get)
239
- end
240
- u_factor_ip = OpenStudio.convert(u_factor_si, source_units, target_units).get
241
- if use_old_gem_code
242
- shgc = sub_surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get.calculated_solar_heat_gain_coefficient
243
- else
244
- shgc = std.construction_calculated_solar_heat_gain_coefficient(sub_surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get)
245
- end
366
+ # lookup target_shgc
367
+ target_shgc = space_type_const_properties[intended_surface_type][construction_type][const_bldg_cat]['shgc'].to_f
246
368
 
247
- # stop if didn't find values (0 or infinity)
248
- next if target_u_value_ip[sub_surface_detail[:surface_type]] == 0.0
249
- next if target_u_value_ip[sub_surface_detail[:surface_type]] == Float::INFINITY
250
-
251
- # check u avlues
252
- if u_factor_ip < target_u_value_ip[sub_surface_detail[:surface_type]] * (1.0 - min_pass)
253
- check_elems << OpenStudio::Attribute.new('flag', "U value of #{u_factor_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{min_pass * 100} % below the expected value of #{target_u_value_ip[sub_surface_detail[:surface_type]].round(2)} (#{target_units}) for #{display_standard}.")
254
- elsif u_factor_ip > target_u_value_ip[sub_surface_detail[:surface_type]] * (1.0 + max_pass)
255
- check_elems << OpenStudio::Attribute.new('flag', "U value of #{u_factor_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{max_pass * 100} % above the expected value of #{target_u_value_ip[sub_surface_detail[:surface_type]].round(2)} (#{target_units}) for #{display_standard}.")
256
- end
369
+ # check shgc
370
+ if shgc < target_shgc * (1.0 - min_pass)
371
+ check_elems << OpenStudio::Attribute.new('flag', "SHGC of #{shgc.round(2)} % for #{sub_surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{min_pass * 100} % below the value of #{target_shgc.round(2)} %.")
372
+ elsif shgc > target_shgc * (1.0 + max_pass)
373
+ check_elems << OpenStudio::Attribute.new('flag', "SHGC of #{shgc.round(2)} % for #{sub_surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{max_pass * 100} % above the value of #{target_shgc.round(2)} %.")
374
+ end
257
375
 
258
- # check shgc
259
- if shgc < target_shgc[sub_surface_detail[:surface_type]] * (1.0 - min_pass)
260
- check_elems << OpenStudio::Attribute.new('flag', "SHGC of #{shgc.round(2)} % for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{min_pass * 100} % below the expected value of #{target_shgc[sub_surface_detail[:surface_type]].round(2)} %.")
261
- elsif shgc > target_shgc[sub_surface_detail[:surface_type]] * (1.0 + max_pass)
262
- check_elems << OpenStudio::Attribute.new('flag', "SHGC of #{shgc.round(2)} % for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{max_pass * 100} % above the expected value of #{target_shgc[sub_surface_detail[:surface_type]].round(2)} %.")
263
- end
376
+ else
377
+ # check for opaque sub surfaces
378
+ if sub_surface_detail[:construction].thermalConductance.is_initialized
264
379
 
265
- else
266
- # check for opaque sub surfaces
267
- if sub_surface_detail[:construction].thermalConductance.is_initialized
380
+ # don't use intened surface type of construction, look map based on surface type and boundary condition
381
+ boundary_condition = sub_surface_detail[:boundary_condition]
382
+ intended_surface_type = sub_surface_detail[:surface_type]
383
+ construction_type = sub_surface_detail[:construction_type]
384
+ next if boundary_condition.to_s != 'Outdoors'
385
+ film_coefficients_r_value = std.film_coefficients_r_value(intended_surface_type, includes_int_film = true, includes_ext_film = true)
268
386
 
269
- # don't use intened surface type of construction, look map based on surface type and boundary condition
270
- boundary_condition = sub_surface_detail[:boundary_condition]
271
- surface_type = sub_surface_detail[:surface_type]
272
- intended_surface_type = ''
273
- if boundary_condition.to_s == 'Outdoors'
274
- # TODO: add additional intended surface types
275
- if surface_type.to_s == 'Door' then intended_surface_type = 'ExteriorDoor' end
276
- else
277
- # currently only used for surfaces with outdoor boundary condition
278
- end
279
- if use_old_gem_code
280
- film_coefficients_r_value = sub_surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get.film_coefficients_r_value(intended_surface_type)
281
- else
282
- film_coefficients_r_value = std.film_coefficients_r_value(intended_surface_type, includes_int_film = true, includes_ext_film = true)
283
- end
387
+ thermal_conductance = sub_surface_detail[:construction].thermalConductance.get
388
+ r_value_with_film = 1 / thermal_conductance + film_coefficients_r_value
389
+ source_units = 'm^2*K/W'
390
+ target_units = 'ft^2*h*R/Btu'
391
+ r_value_ip = OpenStudio.convert(r_value_with_film, source_units, target_units).get
392
+ solar_reflectance = sub_surface_detail[:construction].to_LayeredConstruction.get.layers[0].to_OpaqueMaterial.get.solarReflectance .get # TODO: - check optional first does what happens with ext. air wall
393
+ const_bldg_cat = sub_surface_detail[:const_bldg_cat]
284
394
 
285
- thermal_conductance = sub_surface_detail[:construction].thermalConductance.get
286
- r_value_with_film = 1 / thermal_conductance + film_coefficients_r_value
287
- source_units = 'm^2*K/W'
288
- target_units = 'ft^2*h*R/Btu'
289
- r_value_ip = OpenStudio.convert(r_value_with_film, source_units, target_units).get
290
- solar_reflectance = sub_surface_detail[:construction].to_LayeredConstruction.get.layers[0].to_OpaqueMaterial.get.solarReflectance .get # TODO: - check optional first does what happens with ext. air wall
395
+ # lookup target_r_value_ip
396
+ target_r_value_ip = 1.0 / space_type_const_properties[intended_surface_type][construction_type][const_bldg_cat]['u_value'].to_f
291
397
 
292
- # stop if didn't find values (0 or infinity)
293
- next if target_r_value_ip[sub_surface_detail[:surface_type]] == 0.0
294
- next if target_r_value_ip[sub_surface_detail[:surface_type]] == Float::INFINITY
398
+ # stop if didn't find values (0 or infinity)
399
+ next if target_r_value_ip == 0.0
400
+ next if target_r_value_ip == Float::INFINITY
295
401
 
296
- # check r avlues
297
- if r_value_ip < target_r_value_ip[sub_surface_detail[:surface_type]] * (1.0 - min_pass)
298
- check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{min_pass * 100} % below the expected value of #{target_r_value_ip[sub_surface_detail[:surface_type]].round(2)} (#{target_units}) for #{display_standard}.")
299
- elsif r_value_ip > target_r_value_ip[sub_surface_detail[:surface_type]] * (1.0 + max_pass)
300
- check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{max_pass * 100} % above the expected value of #{target_r_value_ip[sub_surface_detail[:surface_type]].round(2)} (#{target_units}) for #{display_standard}.")
301
- end
402
+ # check r avlues
403
+ if r_value_ip < target_r_value_ip * (1.0 - min_pass)
404
+ check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{min_pass * 100} % below the value of #{target_r_value_ip.round(2)} % (#{target_units}) for #{prototype_prefix} #{sub_surface_detail[:construction_type]} #{sub_surface_detail[:surface_type]}.")
405
+ elsif r_value_ip > target_r_value_ip * (1.0 + max_pass)
406
+ check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{max_pass * 100} % above the value of #{target_r_value_ip.round(2)} % (#{target_units}) for #{prototype_prefix} #{sub_surface_detail[:construction_type]} #{sub_surface_detail[:surface_type]}.")
407
+ end
302
408
 
303
- # check solar reflectance
304
- if (solar_reflectance < target_reflectance[sub_surface_detail[:surface_type]] * (1.0 - min_pass)) && (target_standard != 'ICC IECC 2015')
305
- check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{min_pass * 100} % below the expected value of #{(target_reflectance[sub_surface_detail[:surface_type]] * 100).round} %.")
306
- elsif (solar_reflectance > target_reflectance[sub_surface_detail[:surface_type]] * (1.0 + max_pass)) && (target_standard != 'ICC IECC 2015')
307
- check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{max_pass * 100} % above the expected value of #{(target_reflectance[sub_surface_detail[:surface_type]] * 100).round} %.")
308
- end
409
+ # lookup target_reflectance
410
+ target_reflectance = space_type_const_properties[intended_surface_type][construction_type][const_bldg_cat]['reflectance'].to_f
309
411
 
310
- else
311
- check_elems << OpenStudio::Attribute.new('flag', "Can't calculate R value for #{sub_surface_detail[:construction].name}.")
412
+ # check solar reflectance
413
+ if (solar_reflectance < target_reflectance* (1.0 - min_pass)) && (target_standard != 'ICC IECC 2015')
414
+ check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{sub_surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{min_pass * 100} % below the value of #{(target_reflectance * 100).round} % for #{prototype_prefix} #{sub_surface_detail[:construction_type]} #{sub_surface_detail[:surface_type]}.")
415
+ elsif (solar_reflectance > target_reflectance * (1.0 + max_pass)) && (target_standard != 'ICC IECC 2015')
416
+ check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{sub_surface_detail[:construction].name} in #{const_bldg_cat} space type is more than #{max_pass * 100} % above the value of #{(target_reflectance * 100).round} % for #{prototype_prefix} #{sub_surface_detail[:construction_type]} #{sub_surface_detail[:surface_type]}.")
312
417
  end
313
418
 
419
+ else
420
+ check_elems << OpenStudio::Attribute.new('flag', "Can't calculate R value for #{sub_surface_detail[:construction].name}.")
314
421
  end
422
+
315
423
  end
316
424
  end
317
425
 
@@ -324,11 +432,18 @@ module OsLib_QAQC
324
432
  missing_surface_constructions = []
325
433
  sub_surface_details = []
326
434
  missing_sub_surface_constructions = []
435
+ const_bldg_cat = 'Nonresidential'
436
+ check_elems << OpenStudio::Attribute.new('flag', "Treating surfaces and sub-surfaces in space #{space.name} as Nonresidential since no space type is assigned.")
327
437
 
328
438
  space.surfaces.each do |surface|
329
439
  next if surface.outsideBoundaryCondition != 'Outdoors'
330
440
  if surface.construction.is_initialized
331
- surface_details << { boundary_condition: surface.outsideBoundaryCondition, surface_type: surface.surfaceType, construction: surface.construction.get }
441
+ surf_props = self.map_surface_props(surface,check_elems,defaulted_const_type)
442
+ ext_surf_type = surf_props[:ext_surf_type]
443
+ const_type = surf_props[:const_type]
444
+ construction = surf_props[:construction]
445
+
446
+ surface_details << { boundary_condition: surface.outsideBoundaryCondition, surface_type: ext_surf_type, construction: surface.construction.get,construction_type: const_type, const_bldg_cat: const_bldg_cat}
332
447
  else
333
448
  missing_constructions << surface.name.get
334
449
  end
@@ -336,7 +451,12 @@ module OsLib_QAQC
336
451
  # make array of construction details for sub_surfaces
337
452
  surface.subSurfaces.each do |sub_surface|
338
453
  if sub_surface.construction.is_initialized
339
- sub_surface_details << { boundary_condition: sub_surface.outsideBoundaryCondition, surface_type: sub_surface.subSurfaceType, construction: sub_surface.construction.get }
454
+ sub_surf_props = self.map_sub_surfaces_props(sub_surface,check_elems,defaulted_const_type)
455
+ ext_sub_surf_type = sub_surf_props[:ext_sub_surf_type]
456
+ sub_const_type = sub_surf_props[:sub_const_type]
457
+ construction = sub_surf_props[:construction]
458
+
459
+ sub_surface_details << {boundary_condition: sub_surface.outsideBoundaryCondition, surface_type: ext_sub_surf_type, construction: sub_surface.construction.get, construction_type: sub_const_type, const_bldg_cat: const_bldg_cat}
340
460
  else
341
461
  missing_constructions << sub_surface.name.get
342
462
  end
@@ -355,27 +475,9 @@ module OsLib_QAQC
355
475
  if surface_detail[:construction].thermalConductance.is_initialized
356
476
  # don't use intened surface type of construction, look map based on surface type and boundary condition
357
477
  boundary_condition = surface_detail[:boundary_condition]
358
- surface_type = surface_detail[:surface_type]
359
- intended_surface_type = ''
360
- if boundary_condition.to_s == 'Outdoors'
361
- if surface_type.to_s == 'Wall'
362
- intended_surface_type = 'ExteriorWall'
363
- standards_construction_type = 'SteelFramed'
364
- elsif surface_type == 'RoofCeiling'
365
- intended_surface_type = 'ExteriorRoof'
366
- standards_construction_type = 'IEAD'
367
- else surface_type == 'Floor'
368
- intended_surface_type = 'ExteriorFloor'
369
- standards_construction_type = 'Mass'
370
- end
371
- else
372
- # currently only used for surfaces with outdoor boundary condition
373
- end
374
- if use_old_gem_code
375
- film_coefficients_r_value = surface_detail[:construction].to_LayeredConstruction.get.to_Construction.get.film_coefficients_r_value(intended_surface_type)
376
- else
377
- film_coefficients_r_value = std.film_coefficients_r_value(intended_surface_type, includes_int_film = true, includes_ext_film = true)
378
- end
478
+ intended_surface_type = surface_detail[:surface_type]
479
+ construction_type = surface_detail[:construction_type]
480
+ film_coefficients_r_value = std.film_coefficients_r_value(intended_surface_type, includes_int_film = true, includes_ext_film = true)
379
481
 
380
482
  thermal_conductance = surface_detail[:construction].thermalConductance.get
381
483
  r_value_with_film = 1 / thermal_conductance + film_coefficients_r_value
@@ -386,24 +488,17 @@ module OsLib_QAQC
386
488
 
387
489
  # calculate target_r_value_ip
388
490
  target_reflectance = nil
389
- if use_old_gem_code
390
- data = @model.get_construction_properties(target_standard, intended_surface_type, standards_construction_type)
391
- else
392
491
 
393
- # model_get_construction_properties takes additional arguments now, maybe standard should update to add default
394
- building_type = std.model_get_standards_building_type(@model)
395
- construction_set_data = std.model_get_construction_set(building_type)
396
- building_type_category = construction_set_data['exterior_wall_building_category']
397
-
398
- data = std.model_get_construction_properties(@model, intended_surface_type, standards_construction_type, building_type_category)
399
- end
492
+ data = std.model_get_construction_properties(@model, intended_surface_type, construction_type, const_bldg_cat)
400
493
 
401
494
  if data.nil?
402
- check_elems << OpenStudio::Attribute.new('flag', "Didn't find construction for #{standards_construction_type} #{intended_surface_type} for #{space.name}.")
495
+ check_elems << OpenStudio::Attribute.new('flag', "Didn't find construction for #{construction_type} #{intended_surface_type} for #{space.name}.")
403
496
  next
404
- elsif intended_surface_type.include? 'ExteriorWall' || 'ExteriorFloor' || 'ExteriorDoor'
497
+ elsif ['ExteriorWall','ExteriorDoor'].include? intended_surface_type
405
498
  assembly_maximum_u_value = data['assembly_maximum_u_value']
406
499
  target_reflectance = 0.30
500
+ elsif intended_surface_type.include? 'ExteriorFloor'
501
+ assembly_maximum_u_value = data['assembly_maximum_u_value']
407
502
  elsif intended_surface_type.include? 'ExteriorRoof'
408
503
  assembly_maximum_u_value = data['assembly_maximum_u_value']
409
504
  target_reflectance = 0.55
@@ -419,16 +514,19 @@ module OsLib_QAQC
419
514
 
420
515
  # check r avlues
421
516
  if r_value_ip < assembly_maximum_r_value_ip * (1.0 - min_pass)
422
- check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{surface_detail[:construction].name} in #{space.name} is more than #{min_pass * 100} % below the expected value of #{assembly_maximum_r_value_ip.round(2)} (#{target_units}) for #{display_standard}.")
517
+ check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{surface_detail[:construction].name} in #{space.name} is more than #{min_pass * 100} % below the value of #{assembly_maximum_r_value_ip.round(2)} (#{target_units}) for #{prototype_prefix} #{surface_detail[:construction_type]} #{surface_detail[:const_bldg_cat]}.")
518
+ elsif r_value_ip > assembly_maximum_r_value_ip * (1.0 + max_pass)
519
+ check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{sub_surface_detail[:construction].name} in #{space_type.name} is more than #{max_pass * 100} % above the value of #{target_r_value_ip.round(2)} (#{target_units}) for #{prototype_prefix} #{surface_detail[:construction_type]} #{surface_detail[:const_bldg_cat]}")
423
520
  elsif r_value_ip > assembly_maximum_r_value_ip * (1.0 + max_pass)
424
- check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{surface_detail[:construction].name} in #{space.name} is more than #{max_pass * 100} % above the expected value of #{assembly_maximum_r_value_ip.round(2)} (#{target_units}) for #{display_standard}.")
521
+ check_elems << OpenStudio::Attribute.new('flag', "R value of #{r_value_ip.round(2)} (#{target_units}) for #{surface_detail[:construction].name} in #{space.name} is more than #{max_pass * 100} % above the value of #{assembly_maximum_r_value_ip.round(2)} (#{target_units}) for #{prototype_prefix} #{surface_detail[:construction_type]} #{surface_detail[:building_type_category]}.")
425
522
  end
426
523
 
427
524
  # check solar reflectance
525
+ next if intended_surface_type == 'ExteriorFloor' # do not check reflectance exterior floors (overhang)
428
526
  if (solar_reflectance < target_reflectance * (1.0 - min_pass)) && (target_standard != 'ICC IECC 2015')
429
- check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{surface_detail[:construction].name} in #{space.name} is more than #{min_pass * 100} % below the expected value of #{(target_reflectance * 100).round} %.")
527
+ check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{surface_detail[:construction].name} in #{space.name} is more than #{min_pass * 100} % below the value of #{(target_reflectance * 100).round} %.")
430
528
  elsif (solar_reflectance > target_reflectance * (1.0 + max_pass)) && (target_standard != 'ICC IECC 2015')
431
- check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{surface_detail[:construction].name} in #{space.name} is more than #{max_pass * 100} % above the expected value of #{(target_reflectance * 100).round} %.")
529
+ check_elems << OpenStudio::Attribute.new('flag', "Solar Reflectance of #{(solar_reflectance * 100).round} % for #{surface_detail[:construction].name} in #{space.name} is more than #{max_pass * 100} % above the value of #{(target_reflectance * 100).round} %.")
432
530
  end
433
531
  else
434
532
  check_elems << OpenStudio::Attribute.new('flag', "Can't calculate R value for #{surface_detail[:construction].name}.")
@@ -442,6 +540,7 @@ module OsLib_QAQC
442
540
 
443
541
  end
444
542
  end
543
+
445
544
  rescue StandardError => e
446
545
  # brief description of ruby error
447
546
  check_elems << OpenStudio::Attribute.new('flag', "Error prevented QAQC check from running (#{e}).")