openstudio-common-measures 0.4.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +3 -1
  4. data/CHANGELOG.md +25 -0
  5. data/README.md +21 -2
  6. data/doc_templates/copyright_erb.txt +1 -1
  7. data/lib/measures/AddCostPerFloorAreaUnusedToLights/measure.xml +2 -8
  8. data/lib/measures/AddCostToSupplySideHVACComponentByAirLoop/measure.xml +9 -3
  9. data/lib/measures/AddSimplePvToShadingSurfacesByType/measure.xml +2 -2
  10. data/lib/measures/RemoveUnusedDefaultProfiles/measure.xml +2 -2
  11. data/lib/measures/ReportModelChanges/measure.xml +2 -2
  12. data/lib/measures/SetCOPforSingleSpeedDXCoolingUnits/measure.xml +4 -4
  13. data/lib/measures/SetCOPforTwoSpeedDXCoolingUnits/measure.xml +4 -4
  14. data/lib/measures/SetGasBurnerEfficiency/measure.xml +4 -4
  15. data/lib/measures/ShiftScheduleProfileTime/measure.xml +4 -4
  16. data/lib/measures/SwapLightsDefinition/measure.xml +3 -5
  17. data/lib/measures/add_ems_emissions_reporting/LICENSE.MD.txt +15 -0
  18. data/lib/measures/add_ems_emissions_reporting/LICENSE.md +27 -0
  19. data/lib/measures/add_ems_emissions_reporting/README.md +17 -0
  20. data/lib/measures/add_ems_emissions_reporting/measure.rb +474 -0
  21. data/lib/measures/add_ems_emissions_reporting/measure.xml +599 -0
  22. data/lib/measures/add_ems_emissions_reporting/resources/future_annual_co2e.csv +17 -0
  23. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2020.csv +8761 -0
  24. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2022.csv +8761 -0
  25. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2024.csv +8761 -0
  26. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2026.csv +8761 -0
  27. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2028.csv +8761 -0
  28. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2030.csv +8761 -0
  29. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2032.csv +8761 -0
  30. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2034.csv +8761 -0
  31. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2036.csv +8761 -0
  32. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2038.csv +8761 -0
  33. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2040.csv +8761 -0
  34. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2042.csv +8761 -0
  35. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2044.csv +8761 -0
  36. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2046.csv +8761 -0
  37. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2048.csv +8761 -0
  38. data/lib/measures/add_ems_emissions_reporting/resources/future_hourly_co2e_2050.csv +8761 -0
  39. data/lib/measures/add_ems_emissions_reporting/resources/historical_annual_co2e.csv +9 -0
  40. data/lib/measures/add_ems_emissions_reporting/resources/historical_hourly_co2e_2019.csv +8761 -0
  41. data/lib/measures/add_ev_load/measure.rb +51 -8
  42. data/lib/measures/add_ev_load/measure.xml +23 -5
  43. data/lib/measures/envelope_and_internal_load_breakdown/measure.xml +3 -3
  44. data/lib/measures/envelope_and_internal_load_breakdown/resources/report.html.erb +6 -1
  45. data/lib/measures/example_report/measure.xml +3 -3
  46. data/lib/measures/example_report/resources/report.html.erb +6 -1
  47. data/lib/measures/generic_qaqc/README.md +19 -4
  48. data/lib/measures/generic_qaqc/README.md.erb +7 -1
  49. data/lib/measures/generic_qaqc/docs/generic_qaqc_detailed.jpg +0 -0
  50. data/lib/measures/generic_qaqc/docs/generic_qaqc_summary.jpg +0 -0
  51. data/lib/measures/generic_qaqc/measure.rb +34 -29
  52. data/lib/measures/generic_qaqc/measure.xml +181 -82
  53. data/lib/measures/generic_qaqc/resources/check_cond_zns.rb +3 -1
  54. data/lib/measures/generic_qaqc/resources/check_domestic_hot_water.rb +13 -8
  55. data/lib/measures/generic_qaqc/resources/check_envelope_conductance.rb +330 -231
  56. data/lib/measures/generic_qaqc/resources/check_eui_by_end_use.rb +59 -20
  57. data/lib/measures/generic_qaqc/resources/check_eui_reasonableness.rb +58 -20
  58. data/lib/measures/generic_qaqc/resources/check_internal_loads.rb +57 -56
  59. data/lib/measures/generic_qaqc/resources/check_mech_sys_capacity.rb +4 -1
  60. data/lib/measures/generic_qaqc/resources/check_mech_sys_efficiency.rb +27 -22
  61. data/lib/measures/generic_qaqc/resources/check_mech_sys_part_load_eff.rb +4 -1
  62. data/lib/measures/generic_qaqc/resources/check_mech_sys_type.rb +3 -3
  63. data/lib/measures/generic_qaqc/resources/check_schedules.rb +65 -101
  64. data/lib/measures/generic_qaqc/resources/check_simultaneous_heating_and_cooling.rb +3 -1
  65. data/lib/measures/generic_qaqc/resources/check_supply_air_and_thermostat_temp_difference.rb +3 -1
  66. data/lib/measures/generic_qaqc/resources/os_lib_reporting_qaqc.rb +49 -15
  67. data/lib/measures/generic_qaqc/resources/report.html.erb +6 -1
  68. data/lib/measures/hvac_psychrometric_chart/measure.xml +4 -3
  69. data/lib/measures/hvac_psychrometric_chart/resources/report.html.erb +6 -1
  70. data/lib/measures/openstudio_results/measure.xml +3 -3
  71. data/lib/measures/openstudio_results/resources/report.html.erb +6 -1
  72. data/lib/measures/set_run_period/measure.xml +2 -2
  73. data/lib/measures/view_data/measure.xml +9 -9
  74. data/lib/measures/view_data/resources/report.html.in +1336 -973
  75. data/lib/measures/view_data/resources/va3c.rb +1 -0
  76. data/lib/measures/view_model/measure.xml +33 -64
  77. data/lib/measures/view_model/resources/report.html.in +1339 -976
  78. data/lib/measures/view_model/resources/va3c.rb +1 -0
  79. data/lib/openstudio/common_measures/version.rb +1 -1
  80. data/openstudio-common-measures.gemspec +2 -2
  81. metadata +33 -7
@@ -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}).")