openstudio-standards 0.8.3 → 0.8.5.rc1

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 (330) hide show
  1. checksums.yaml +4 -4
  2. data/data/geometry/ASHRAECollege.osm +30 -30
  3. data/data/geometry/ASHRAECourthouse.osm +22 -22
  4. data/data/geometry/ASHRAESmallOfficeDetailed.osm +2 -2
  5. data/data/geometry/DEER_Asm.osm +1 -1
  6. data/data/geometry/DEER_ECC.osm +1 -1
  7. data/data/geometry/DEER_EPr.osm +1 -1
  8. data/data/geometry/DEER_ERC.osm +1 -1
  9. data/data/geometry/DEER_ESe.osm +1 -1
  10. data/data/geometry/DEER_EUn.osm +1 -1
  11. data/data/geometry/DEER_Hsp.osm +1 -1
  12. data/data/geometry/DEER_Htl.osm +1 -1
  13. data/data/geometry/DEER_MBT.osm +1 -1
  14. data/data/geometry/DEER_MFm.osm +1 -1
  15. data/data/geometry/DEER_Nrs.osm +1 -1
  16. data/data/geometry/DEER_OfL.osm +1 -1
  17. data/data/geometry/DEER_OfS.osm +1 -1
  18. data/data/geometry/DEER_RFF.osm +1 -1
  19. data/data/geometry/DEER_RSD.osm +1 -1
  20. data/data/geometry/DEER_Rt3.osm +1 -1
  21. data/data/geometry/DEER_RtS.osm +1 -1
  22. data/data/standards/export_OpenStudio_libraries.rb +2 -3
  23. data/data/standards/test_performance_expected_dd_results.csv +42 -42
  24. data/lib/openstudio-standards/btap/NECB_building_types.csv +35 -0
  25. data/lib/openstudio-standards/btap/NECB_space_types.csv +109 -0
  26. data/lib/openstudio-standards/btap/activity.rb +480 -0
  27. data/lib/openstudio-standards/btap/attributes.rb +166 -0
  28. data/lib/openstudio-standards/btap/bridging.rb +561 -1402
  29. data/lib/openstudio-standards/btap/btap.rb +4 -2
  30. data/lib/openstudio-standards/btap/btap_test_helper.rb +86 -0
  31. data/lib/openstudio-standards/btap/carbon/btap_carbon.rb +177 -0
  32. data/lib/openstudio-standards/btap/common_paths.rb +81 -0
  33. data/lib/openstudio-standards/btap/common_resources/ConstructionProperties.csv +52 -0
  34. data/lib/openstudio-standards/btap/common_resources/Constructions.csv +37 -0
  35. data/lib/openstudio-standards/btap/common_resources/carbon_frame.csv +35 -0
  36. data/lib/openstudio-standards/btap/common_resources/carbon_glazing.csv +35 -0
  37. data/lib/openstudio-standards/btap/common_resources/carbon_opaque.csv +164 -0
  38. data/lib/openstudio-standards/btap/common_resources/construction_sets.csv +1270 -0
  39. data/lib/openstudio-standards/btap/common_resources/constructions_glazing.csv +121 -0
  40. data/lib/openstudio-standards/btap/common_resources/constructions_opaque.csv +2256 -0
  41. data/lib/openstudio-standards/btap/common_resources/costs.csv +1897 -0
  42. data/lib/openstudio-standards/btap/common_resources/costs_local_factors.csv +2315 -0
  43. data/lib/openstudio-standards/btap/common_resources/hvac_vent_ahu.csv +925 -0
  44. data/lib/openstudio-standards/btap/common_resources/lighting.csv +364 -0
  45. data/lib/openstudio-standards/btap/common_resources/lighting_sets.csv +2667 -0
  46. data/lib/openstudio-standards/btap/common_resources/locations.csv +75 -0
  47. data/lib/openstudio-standards/btap/common_resources/materials_glazing.csv +35 -0
  48. data/lib/openstudio-standards/btap/common_resources/materials_hvac.csv +1686 -0
  49. data/lib/openstudio-standards/btap/common_resources/materials_lighting.csv +267 -0
  50. data/lib/openstudio-standards/btap/common_resources/materials_opaque.csv +164 -0
  51. data/lib/openstudio-standards/btap/costing/README.md +502 -0
  52. data/lib/openstudio-standards/btap/costing/btap_costing.rb +469 -0
  53. data/lib/openstudio-standards/btap/costing/btap_measure_helper.rb +359 -0
  54. data/lib/openstudio-standards/btap/costing/btap_workflow.rb +117 -0
  55. data/lib/openstudio-standards/btap/costing/copy_test_results_files_to_expected_results.rb +11 -0
  56. data/lib/openstudio-standards/btap/costing/cost_building_from_file.rb +136 -0
  57. data/lib/openstudio-standards/btap/costing/costing_database_wrapper.rb +173 -0
  58. data/lib/openstudio-standards/btap/costing/daylighting_sensor_control_costing.rb +354 -0
  59. data/lib/openstudio-standards/btap/costing/dcv_costing.rb +314 -0
  60. data/lib/openstudio-standards/btap/costing/dummy.epw +8768 -0
  61. data/lib/openstudio-standards/btap/costing/dummy.osm +5320 -0
  62. data/lib/openstudio-standards/btap/costing/envelope_costing.rb +215 -0
  63. data/lib/openstudio-standards/btap/costing/heating_cooling_costing.rb +2584 -0
  64. data/lib/openstudio-standards/btap/costing/led_lighting_costing.rb +156 -0
  65. data/lib/openstudio-standards/btap/costing/lighting_costing.rb +209 -0
  66. data/lib/openstudio-standards/btap/costing/mech_sizing.json +502 -0
  67. data/lib/openstudio-standards/btap/costing/neb_end_use_prices.csv +42 -0
  68. data/lib/openstudio-standards/btap/costing/necb_2011_spacetype_info.csv +225 -0
  69. data/lib/openstudio-standards/btap/costing/necb_reference_runs.csv +28705 -0
  70. data/lib/openstudio-standards/btap/costing/nv_costing.rb +547 -0
  71. data/lib/openstudio-standards/btap/costing/parallel_tests.rb +92 -0
  72. data/lib/openstudio-standards/btap/costing/pv_ground_costing.rb +687 -0
  73. data/lib/openstudio-standards/btap/costing/shw_costing.rb +705 -0
  74. data/lib/openstudio-standards/btap/costing/test_list.txt +15 -0
  75. data/lib/openstudio-standards/btap/costing/test_run_all_test_locally.rb +27 -0
  76. data/lib/openstudio-standards/btap/costing/test_run_costing_tests.rb +80 -0
  77. data/lib/openstudio-standards/btap/costing/ventilation_costing.rb +2616 -0
  78. data/lib/openstudio-standards/btap/geometry.rb +86 -6
  79. data/lib/openstudio-standards/btap/structure.rb +657 -0
  80. data/lib/openstudio-standards/constructions/modify.rb +2 -1
  81. data/lib/openstudio-standards/create_typical/create_typical.rb +17 -33
  82. data/lib/openstudio-standards/create_typical/space_type_ratios.rb +36 -36
  83. data/lib/openstudio-standards/equipment/create_transformer.rb +104 -0
  84. data/lib/openstudio-standards/equipment/create_typical_equipment.rb +117 -0
  85. data/lib/openstudio-standards/equipment/data/electric_equipment_space_types.json +1514 -0
  86. data/lib/openstudio-standards/equipment/data/gas_equipment_space_types.json +227 -0
  87. data/lib/openstudio-standards/exterior_lighting/create.rb +22 -22
  88. data/lib/openstudio-standards/exterior_lighting/information.rb +3 -2
  89. data/lib/openstudio-standards/hvac/components/air_conditioner_vrf.rb +482 -0
  90. data/lib/openstudio-standards/hvac/components/air_terminal.rb +31 -0
  91. data/lib/openstudio-standards/hvac/components/boiler_hot_water.rb +163 -0
  92. data/lib/openstudio-standards/hvac/components/central_air_source_heat_pump.rb +220 -0
  93. data/lib/openstudio-standards/hvac/components/chiller.rb +25 -0
  94. data/lib/openstudio-standards/hvac/components/coil.rb +276 -0
  95. data/lib/openstudio-standards/hvac/components/coil_cooling_dx_multi_speed.rb +40 -0
  96. data/lib/openstudio-standards/hvac/components/coil_cooling_dx_single_speed.rb +300 -0
  97. data/lib/openstudio-standards/hvac/components/coil_cooling_dx_two_speed.rb +187 -0
  98. data/lib/openstudio-standards/hvac/components/coil_cooling_water.rb +80 -0
  99. data/lib/openstudio-standards/hvac/components/coil_cooling_water_to_air_heat_pump_equation_fit.rb +182 -0
  100. data/lib/openstudio-standards/hvac/components/coil_heating_dx_single_speed.rb +220 -0
  101. data/lib/openstudio-standards/hvac/components/coil_heating_electric.rb +56 -0
  102. data/lib/openstudio-standards/hvac/components/coil_heating_gas.rb +90 -0
  103. data/lib/openstudio-standards/hvac/components/coil_heating_gas_multi_stage.rb +33 -0
  104. data/lib/openstudio-standards/hvac/components/coil_heating_water.rb +98 -0
  105. data/lib/openstudio-standards/hvac/components/coil_heating_water_to_air_heat_pump_equation_fit.rb +147 -0
  106. data/lib/openstudio-standards/hvac/components/component.rb +39 -0
  107. data/lib/openstudio-standards/{standards/ashrae_90_1/data/ashrae_90_1.fans.json → hvac/components/data/fans.json} +6 -6
  108. data/lib/openstudio-standards/hvac/components/fan.rb +363 -0
  109. data/lib/openstudio-standards/hvac/components/heat_exchanger_air_to_air.rb +203 -0
  110. data/lib/openstudio-standards/hvac/components/pump.rb +181 -0
  111. data/lib/openstudio-standards/hvac/controls/radiant_system_controls.rb +594 -0
  112. data/lib/openstudio-standards/hvac/conversions.rb +222 -0
  113. data/lib/openstudio-standards/hvac/curves.rb +192 -0
  114. data/lib/openstudio-standards/hvac/helpers.rb +357 -0
  115. data/lib/openstudio-standards/hvac/setpoint_managers/information.rb +4 -4
  116. data/lib/openstudio-standards/interior_lighting/create_lights.rb +52 -0
  117. data/lib/openstudio-standards/interior_lighting/create_typical_interior_lighting.rb +254 -0
  118. data/lib/openstudio-standards/interior_lighting/data/convert_lighting_data.rb +249 -0
  119. data/lib/openstudio-standards/interior_lighting/data/lighting_space_types.csv +96 -0
  120. data/lib/openstudio-standards/interior_lighting/data/lighting_space_types.json +1429 -0
  121. data/lib/openstudio-standards/interior_lighting/data/lighting_technology.csv +46 -0
  122. data/lib/openstudio-standards/interior_lighting/data/lighting_technology.json +859 -0
  123. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
  124. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
  125. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
  126. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +4 -4
  127. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
  128. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +4 -4
  129. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
  130. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
  131. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.HighRiseApartment.rb +6 -7
  132. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Hospital.rb +15 -15
  133. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeHotel.rb +4 -4
  134. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOffice.rb +5 -5
  135. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOffice.rb +6 -6
  136. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Outpatient.rb +7 -7
  137. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.PrimarySchool.rb +4 -4
  138. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SecondarySchool.rb +6 -6
  139. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOfficeDetailed.rb +5 -1
  140. data/lib/openstudio-standards/prototypes/common/data/prototype_space_type_map.json +2594 -0
  141. data/lib/openstudio-standards/prototypes/common/data/thermostat_schedule_lookup.json +2108 -0
  142. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirTerminalSingleDuctVAVReheat.rb +33 -0
  143. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +0 -140
  144. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanConstantVolume.rb +1 -73
  145. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanOnOff.rb +1 -69
  146. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanVariableVolume.rb +0 -116
  147. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanZoneExhaust.rb +0 -61
  148. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.hvac.rb +2 -2
  149. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +128 -13
  150. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +606 -607
  151. data/lib/openstudio-standards/prototypes/common/prototype_space_type_map.rb +41 -0
  152. data/lib/openstudio-standards/prototypes/common/space_type_equipment_map.rb +184 -0
  153. data/lib/openstudio-standards/prototypes/common/space_type_thermostat_schedule_map.rb +116 -0
  154. data/lib/openstudio-standards/qaqc/hvac.rb +12 -12
  155. data/lib/openstudio-standards/refrigeration/create_compressor.rb +2 -5
  156. data/lib/openstudio-standards/refrigeration/data/refrigeration_compressors.csv +4 -4
  157. data/lib/openstudio-standards/service_water_heating/create_water_heater.rb +1 -2
  158. data/lib/openstudio-standards/service_water_heating/create_water_use.rb +5 -5
  159. data/lib/openstudio-standards/space_type/data/level_1_space_types.json +612 -0
  160. data/lib/openstudio-standards/space_type/standards_space_type.rb +53 -0
  161. data/lib/openstudio-standards/standards/Standards.AirConditionerVariableRefrigerantFlow.rb +8 -26
  162. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +13 -13
  163. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctVAVReheat.rb +0 -24
  164. data/lib/openstudio-standards/standards/Standards.BoilerHotWater.rb +6 -43
  165. data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +7 -24
  166. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXMultiSpeed.rb +19 -44
  167. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +25 -50
  168. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXTwoSpeed.rb +25 -33
  169. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +9 -22
  170. data/lib/openstudio-standards/standards/Standards.CoilDX.rb +15 -157
  171. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXMultiSpeed.rb +2 -2
  172. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +18 -105
  173. data/lib/openstudio-standards/standards/Standards.CoilHeatingGas.rb +3 -23
  174. data/lib/openstudio-standards/standards/Standards.CoilHeatingGasMultiStage.rb +0 -24
  175. data/lib/openstudio-standards/standards/Standards.CoilHeatingWaterToAirHeatPumpEquationFit.rb +2 -86
  176. data/lib/openstudio-standards/standards/Standards.FanVariableVolume.rb +0 -107
  177. data/lib/openstudio-standards/standards/Standards.Model.rb +45 -20
  178. data/lib/openstudio-standards/standards/Standards.People.rb +113 -0
  179. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +11 -11
  180. data/lib/openstudio-standards/standards/Standards.Pump.rb +2 -147
  181. data/lib/openstudio-standards/standards/Standards.PumpVariableSpeed.rb +57 -41
  182. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +30 -153
  183. data/lib/openstudio-standards/standards/Standards.Ventilation.rb +74 -0
  184. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +1 -1
  185. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PlantLoop.rb +4 -4
  186. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.heat_pumps_heating.json +3 -3
  187. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.spc_typ.json +37 -112
  188. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/comstock_ashrae_90_1_2007.spc_typ.json +37 -102
  189. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.heat_pumps_heating.json +3 -3
  190. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.spc_typ.json +37 -112
  191. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
  192. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/comstock_ashrae_90_1_2010.spc_typ.json +37 -37
  193. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.heat_pumps_heating.json +6 -6
  194. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.spc_typ.json +37 -37
  195. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
  196. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.BoilerHotWater.rb +1 -1
  197. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/comstock_ashrae_90_1_2013.spc_typ.json +37 -102
  198. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.heat_pumps_heating.json +6 -6
  199. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.spc_typ.json +37 -37
  200. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
  201. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.BoilerHotWater.rb +1 -1
  202. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/comstock_ashrae_90_1_2016.spc_typ.json +45 -109
  203. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.heat_pumps_heating.json +6 -6
  204. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.spc_typ.json +37 -37
  205. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +1 -1
  206. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
  207. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.BoilerHotWater.rb +1 -1
  208. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoilHeatingGas.rb +1 -1
  209. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/comstock_ashrae_90_1_2019.spc_typ.json +45 -109
  210. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.heat_pumps_heating.json +6 -6
  211. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.spc_typ.json +37 -37
  212. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.curves.json +0 -200
  213. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/comstock_doe_ref_1980_2004.spc_typ.json +37 -37
  214. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.spc_typ.json +37 -37
  215. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/data/comstock_doe_ref_pre_1980.spc_typ.json +37 -37
  216. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.spc_typ.json +37 -37
  217. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
  218. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.PlantLoop.rb +5 -5
  219. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
  220. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.PlantLoop.rb +5 -5
  221. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +1 -1
  222. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +2 -2
  223. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +2 -68
  224. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +2 -35
  225. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +42 -0
  226. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +5 -2
  227. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +2 -2
  228. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +2 -2
  229. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +3 -3
  230. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +1 -1
  231. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +1 -0
  232. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019_WaterHeaterMixed.rb +2 -4
  233. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.curves.json +0 -200
  234. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.fans.json +5 -5
  235. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData.rb +7 -1
  236. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_enums.rb +0 -1
  237. data/lib/openstudio-standards/standards/cbes/data/cbes.curves.json +0 -200
  238. data/lib/openstudio-standards/standards/deer/data/deer.curves.json +0 -200
  239. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/btap_pre1980.rb +21 -37
  240. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/building_envelope.rb +12 -11
  241. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_3_and_8_single_speed.rb +68 -27
  242. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_4.rb +64 -25
  243. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +9 -14
  244. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_systems.rb +4 -4
  245. data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +1 -1
  246. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +115 -112
  247. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +637 -249
  248. data/lib/openstudio-standards/standards/necb/NECB2011/beps_compliance_path.rb +16 -12
  249. data/lib/openstudio-standards/standards/necb/NECB2011/building_envelope.rb +799 -46
  250. data/lib/openstudio-standards/standards/necb/NECB2011/data/chillers.json +33 -51
  251. data/lib/openstudio-standards/standards/necb/NECB2011/data/constants.json +75 -7
  252. data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +25 -1
  253. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/HighriseApartmentMult.osm +14272 -0
  254. data/lib/openstudio-standards/standards/necb/NECB2011/data/heat_pumps_heating.json +21 -15
  255. data/lib/openstudio-standards/standards/necb/NECB2011/data/necb_2015_table_c1.json +1 -1
  256. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +437 -437
  257. data/lib/openstudio-standards/standards/necb/NECB2011/data/systems.json +516 -0
  258. data/lib/openstudio-standards/standards/necb/NECB2011/data/systems_including_sys5.json +588 -0
  259. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_namer.rb +489 -0
  260. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_single_speed.rb +18 -6
  261. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_2_and_5.rb +48 -5
  262. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +2 -2
  263. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +35 -27
  264. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +34 -23
  265. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +8 -6
  266. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +68 -150
  267. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +444 -134
  268. data/lib/openstudio-standards/standards/necb/NECB2011/system_fuels.rb +61 -1
  269. data/lib/openstudio-standards/standards/necb/NECB2015/data/heat_pumps_heating.json +10 -2
  270. data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +636 -636
  271. data/lib/openstudio-standards/standards/necb/NECB2015/data/unitary_acs.json +38 -38
  272. data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +17 -8
  273. data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +636 -636
  274. data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +71 -71
  275. data/lib/openstudio-standards/standards/necb/NECB2020/data/heat_pumps_heating.json +16 -6
  276. data/lib/openstudio-standards/standards/necb/NECB2020/data/unitary_acs.json +60 -61
  277. data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +30 -30
  278. data/lib/openstudio-standards/standards/necb/README.md +343 -0
  279. data/lib/openstudio-standards/standards/necb/common/btap_analysis.rb +79 -0
  280. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +206 -32
  281. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +75 -43
  282. data/lib/openstudio-standards/standards/necb/common/eccc_electric_grid_intensity_20250311.csv +14 -0
  283. data/lib/openstudio-standards/standards/necb/common/nir_gas_grid_intensity_20250311.csv +14 -0
  284. data/lib/openstudio-standards/standards/necb/common/system_types.yaml +0 -0
  285. data/lib/openstudio-standards/thermal_zone/{thermal_zone.rb → information.rb} +12 -45
  286. data/lib/openstudio-standards/thermal_zone/thermostat_schedules.rb +152 -0
  287. data/lib/openstudio-standards/utilities/logging.rb +18 -14
  288. data/lib/openstudio-standards/version.rb +1 -1
  289. data/lib/openstudio-standards/weather/modify.rb +2 -2
  290. data/lib/openstudio-standards/weather/stat_file.rb +2 -2
  291. data/lib/openstudio-standards.rb +67 -38
  292. metadata +141 -50
  293. data/lib/openstudio-standards/hvac/components/create.rb +0 -169
  294. data/lib/openstudio-standards/hvac/components/modify.rb +0 -42
  295. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirConditionerVariableRefrigerantFlow.rb +0 -438
  296. data/lib/openstudio-standards/prototypes/common/objects/Prototype.BoilerHotWater.rb +0 -123
  297. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CentralAirSourceHeatPump.rb +0 -216
  298. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingDXSingleSpeed.rb +0 -273
  299. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingDXTwoSpeed.rb +0 -159
  300. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWater.rb +0 -77
  301. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWaterToAirHeatPumpEquationFit.rb +0 -154
  302. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingDXSingleSpeed.rb +0 -214
  303. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingElectric.rb +0 -53
  304. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingGas.rb +0 -72
  305. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWater.rb +0 -95
  306. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWaterToAirHeatPumpEquationFit.rb +0 -125
  307. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ControllerWaterCoil.rb +0 -17
  308. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.transformers.rb +0 -90
  309. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Pump.rb +0 -4
  310. data/lib/openstudio-standards/prototypes/common/objects/Prototype.PumpVariableSpeed.rb +0 -70
  311. data/lib/openstudio-standards/prototypes/common/objects/Prototype.radiant_system_controls.rb +0 -590
  312. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +0 -901
  313. data/lib/openstudio-standards/standards/Standards.FanConstantVolume.rb +0 -5
  314. data/lib/openstudio-standards/standards/Standards.FanOnOff.rb +0 -5
  315. data/lib/openstudio-standards/standards/Standards.FanZoneExhaust.rb +0 -5
  316. data/lib/openstudio-standards/standards/Standards.HeaderedPumpsConstantSpeed.rb +0 -5
  317. data/lib/openstudio-standards/standards/Standards.HeaderedPumpsVariableSpeed.rb +0 -55
  318. data/lib/openstudio-standards/standards/Standards.PumpConstantSpeed.rb +0 -5
  319. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +0 -5
  320. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +0 -5
  321. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanZoneExhaust.rb +0 -5
  322. data/lib/openstudio-standards/standards/cbes/data/cbes.fans.json +0 -328
  323. data/lib/openstudio-standards/standards/deer/data/deer.fans.json +0 -328
  324. /data/lib/openstudio-standards/{prototypes → standards}/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PumpVariableSpeed.rb +0 -0
  325. /data/lib/openstudio-standards/{prototypes → standards}/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.PumpVariableSpeed.rb +0 -0
  326. /data/lib/openstudio-standards/{prototypes → standards}/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.PumpVariableSpeed.rb +0 -0
  327. /data/lib/openstudio-standards/{prototypes → standards}/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.PumpVariableSpeed.rb +0 -0
  328. /data/lib/openstudio-standards/{prototypes → standards}/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.PumpVariableSpeed.rb +0 -0
  329. /data/lib/openstudio-standards/{prototypes → standards}/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Pump.rb +0 -0
  330. /data/lib/openstudio-standards/{prototypes → standards}/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.PumpVariableSpeed.rb +0 -0
@@ -1,5 +1,5 @@
1
1
  # **************************************************************************** /
2
- # * Copyright (c) 2008-2023, Natural Resources Canada
2
+ # * Copyright (c) 2008-2025, Natural Resources Canada
3
3
  # * All rights reserved.
4
4
  # *
5
5
  # * This library is free software; you can redistribute it and/or
@@ -29,54 +29,48 @@ module BTAP
29
29
  # @author: Denis Bourgeois
30
30
 
31
31
  # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
32
- # BTAP/TBD data extracted from the BTAP costing spreadsheet:
32
+ # BTAP/TBD data initially extracted from the BTAP costing spreadsheet:
33
33
  #
34
34
  # - range of clear-field Uo factors
35
35
  # - range of PSI factors (i.e. MAJOR thermal bridging), e.g. corners
36
- # - costing parameters
37
- #
38
- # NOTE: This module is to be replaced with roo-based spreadsheet parsing,
39
- # generating a BTAP costing JSON file. TO DO.
40
36
  #
41
37
  # Ref: EVOKE BTAP costing spreadsheet modifications (2022), synced with:
42
38
  # - Building Envelope Thermal Bridging Guide (BETBG)
43
39
  # - ASHRAE RP-1365, ISO-12011, etc.
40
+ #
41
+ # This module has been subsequently adapted following the adoption of new
42
+ # BTAP structure/envelope data model/classes.
44
43
 
45
44
  # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
46
- # BTAP costing data (both original BTAP constructions and EVOKE's
47
- # additions) hold sub-variants based on cladding/veneer, e.g.:
45
+ # BTAP costing data (both original BTAP envelope entries and EVOKE add-ons)
46
+ # hold sub-variants based on cladding/veneer, e.g.:
48
47
  #
49
48
  # - "BTAP-ExteriorWall-WoodFramed-5" ... brick veneer
50
49
  # - "BTAP-ExteriorWall-WoodFramed-1" ... wood siding
51
50
  #
52
51
  # Not all of these sub-variants are currently used within BTAP, e.g.
53
52
  # "BTAP-ExteriorWall-WoodFramed-1" is unused. BTAP/TBD data is limited
54
- # to the following wall constructions (paired LP & HP variants).
53
+ # to the following wall assemblies (paired LP & HP variants), which
54
+ # eventually should be located in a shared file (e.g. CSV, JSON).
55
55
  #
56
- # ---- (Basic) Low Performance (LP) assemblies
57
- #
58
- # ID : (layers)
56
+ # ----- Low Performance (LP) assemblies
57
+ # ID : layers
59
58
  # ----- ------------------------------------------
60
59
  # STEL1 : cladding | board | wool | frame | gypsum
61
60
  # WOOD5 : brick | board | wool | frame | gypsum
62
- # MTAL1 : panel | xps | wool | frame | gypsum
63
61
  # MASS2 : brick | xps | | cmu |
64
62
  # MASS4 : precast | xps | wool | frame | gypsum
65
- # MASS6 : brick | xps | | cmu |
66
- #
67
- # ---- High Performance (HP) variants
68
63
  #
69
- # ID : (layers)
64
+ # ----- High Performance (HP) variants
65
+ # ID : layers
70
66
  # ----- ------------------------------------------
71
67
  # STEL2 : cladding | board | wool | frame | gypsum ... switch from STEL1
72
68
  # WOOD7 : brick | mineral | wool | frame | gypsum ... switch from WOOD5
73
- # MTALD : panel | polyiso | foam | frame | gypsum ... switch from MTAL1
74
69
  # MASSB : brick | mineral | cmu | foam | gypsum ... switch from MASS2
75
70
  # MASS8 : precast | xps | wool | frame | gypsum ... switch from MASS4
76
- # MASSC : cladding | mineral | cmu | foam | gypsum ... switch from MASS6
77
71
  #
78
72
  # Paired LPs & HPs vall variants are critical for 'uprating' cases, e.g.
79
- # NECB2017. See below, and end of this document for additional NOTES.
73
+ # NECB2017/2020. See below, and end of this document for additional NOTES.
80
74
 
81
75
  MASS2 = "BTAP-ExteriorWall-Mass-2" # LP wall
82
76
  MASS2_BAD = "BTAP-ExteriorWall-Mass-2 bad" # LP "bad" PSI factors
@@ -92,20 +86,6 @@ module BTAP
92
86
  MASS8_BAD = "BTAP-ExteriorWall-Mass-8c bad"
93
87
  MASS8_GOOD = "BTAP-ExteriorWall-Mass-8c good"
94
88
 
95
- MASS6 = "BTAP-ExteriorWall-Mass-6"
96
- MASS6_BAD = "BTAP-ExteriorWall-Mass-6 bad"
97
- MASS6_GOOD = "BTAP-ExteriorWall-Mass-6 good"
98
- MASSC = "BTAP-ExteriorWall-Mass-10c" # HP, from @Uo < 0.247
99
- MASSC_BAD = "BTAP-ExteriorWall-Mass-10c bad"
100
- MASSC_GOOD = "BTAP-ExteriorWall-Mass-10c good"
101
-
102
- MTAL1 = "BTAP-ExteriorWall-Metal-1"
103
- MTAL1_BAD = "BTAP-ExteriorWall-Metal-1 bad"
104
- MTAL1_GOOD = "BTAP-ExteriorWall-Metal-1 good"
105
- MTALD = "BTAP-ExteriorWall-Metal-1d" # HP, from @Uo < 0.183
106
- MTALD_BAD = "BTAP-ExteriorWall-Metal-1d bad"
107
- MTALD_GOOD = "BTAP-ExteriorWall-Metal-1d good"
108
-
109
89
  WOOD5 = "BTAP-ExteriorWall-WoodFramed-5"
110
90
  WOOD5_BAD = "BTAP-ExteriorWall-WoodFramed-5 bad"
111
91
  WOOD5_GOOD = "BTAP-ExteriorWall-WoodFramed-5 good"
@@ -120,14 +100,11 @@ module BTAP
120
100
  STEL2_BAD = "BTAP-ExteriorWall-SteelFramed-2 bad"
121
101
  STEL2_GOOD = "BTAP-ExteriorWall-SteelFramed-2 good"
122
102
 
123
- ROOFS = "BTAP-ExteriorRoof-IEAD-4"
103
+ ROOF = "BTAP-ExteriorRoof-IEAD-4"
124
104
  FLOOR = "BTAP-ExteriorFloor-SteelFramed-1"
125
105
 
126
- UMIN = 0.010
127
- UMAX = 5.678
128
-
129
106
  # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
130
- # There are 3 distinct BTAP "building_envelope" classes to enrich with
107
+ # There are 2 distinct BTAP "building_envelope.rb" files to enrich with
131
108
  # TBD functionality (whether BTAP users choose to activate TBD or not):
132
109
  #
133
110
  # 1. BTAPPRE1980
@@ -135,10 +112,10 @@ module BTAP
135
112
  # 2. NECB2011
136
113
  # - superclass for NECB2015
137
114
  # - superclass for NECB2017 (inherits from NECB2015)
115
+ # - superclass for NECB2020 (inherits from NECB2017)
138
116
  # - superclass for ECMS
139
- # 3. NECB2020
140
117
  #
141
- # In all 3 classes, a BTAP/TBD option switch allows BTAP users to activate
118
+ # In both files, a BTAP/TBD option switch allows BTAP users to activate
142
119
  # or deactivate TBD functionality :
143
120
  # - "none" : TBD is deactivated, i.e. no up/de-rating
144
121
  # - "bad" or "good": (BTAP-costed) PSI factor sets, i.e. derating only
@@ -149,24 +126,24 @@ module BTAP
149
126
  # instead assess prescriptive Ut compliance for vintages NECB2017 and
150
127
  # NECB2020, the BTAP/TBD must be set to "uprate" so it can iteratively reset
151
128
  # combined Uo & PSI factors towards finding the least expensive, yet
152
- # compliant, combination. Why? Improved Uo construction variants are
153
- # necessarily required, given:
129
+ # compliant, combination. Why? Improved Uo assembly variants are necessarily
130
+ # required, given:
154
131
  #
155
- # Ut = Uo + ( ∑psi L )/A + ( ∑khi n )/A (ref: rd2.github.io/tbd)
132
+ # Ut = Uo + ( ∑psi x L )/A + ( ∑khi x n )/A (ref: rd2.github.io/tbd)
156
133
  #
157
- # If one ignores linear ("( ∑psi L )/A") and point ("( ∑khi n )/A")
134
+ # If one ignores linear ("( ∑psi x L )/A") and point ("( ∑khi x n )/A")
158
135
  # conductances, Ut simply equates to Uo. Yet for ANY added linear or
159
136
  # point conductance, Uo factors must necessarily be lower than required
160
137
  # NECB2017 or NECB2020 Ut factors. EVOKE's 2022 contribution extends
161
- # initial (pre-2022) BTAP wall construction variants, offering much
138
+ # initial (pre-2022) BTAP wall assembly variants, offering much
162
139
  # lower Uo factors (in some cases slightly below 0.1 W/m2.K or ~R70).
163
140
  # These BTAP upgrades provide more options for attaining required Ut
164
141
  # factors. For some variants, this simply implies a thicker insulation
165
- # layer. For others, it involves more radical construction changes, such
142
+ # layer. For others, it involves more radical assembly changes, such
166
143
  # as switching over to the latest commercially-available HP
167
144
  # thermally-broken cladding clips. While some solutions are simple
168
145
  # (free) detailing changes, most improvements increase construction
169
- # costs. Despite adding new HP constructions, it is unlikely that TBD
146
+ # costs. Despite adding new HP assemblies, it is unlikely that TBD
170
147
  # will find NECB2017 or NECB2020 compliant combinations (prescriptive
171
148
  # path) for EVERY OpenStudio model. Read here as to "why?":
172
149
  #
@@ -174,7 +151,7 @@ module BTAP
174
151
  # spec/tbd_tests_spec.rb#L9219
175
152
  #
176
153
  # For these reasons, BTAP's use of TBD rests on an ITERATIVE uprating
177
- # solution for e.g. NECB2017 and NECB2020:
154
+ # solution for NECB2017 and NECB2020:
178
155
  #
179
156
  # 1. TBD attempts to achieve NECB-required area-weighted Ut factors
180
157
  # for above-grade walls (then for roofs and exposed floors),
@@ -184,1090 +161,370 @@ module BTAP
184
161
  #
185
162
  # 2. If, for a given OpenStudio model, required area-weighted Ut
186
163
  # factors cannot be achieved, TBD then switches over to "good"
187
- # (HP) thermal bridging detailing for that same construction, and
164
+ # (HP) thermal bridging detailing for that same assembly, and
188
165
  # repeats the exercise.
189
166
  #
190
167
  # 3. A subsequent failed attempt triggers a switch over to EVOKE's
191
168
  # HP (improved Uo) assemblies. For instance:
192
169
  # - "BTAP-ExteriorWall-WoodFramed-5" ... switches over to:
193
- # - "BTAP-ExteriorWall-WoodFramed-7b"
170
+ # - "BTAP-ExteriorWall-WoodFramed-7"
194
171
  #
195
- # ... switching over to another construction this way also means
172
+ # ... switching over to another assembly this way also means
196
173
  # reverting back to "bad" (LP) thermal bridging PSI factors.
197
174
  #
198
175
  # 4. A final switch to "good" (HP) details is available (last resort).
199
176
  #
200
177
  # If NONE of the available combinations are sufficient:
201
- # - TBD red-flags a failed attempt at e.g. NECB2017 or NECB2020 compliance
178
+ # - TBD red-flags a failed attempt at NECB2017 or NECB2020 compliance
202
179
  # - TBD keeps iteration #4 Uo + PSI combo, then derates before a
203
180
  # BTAP simulation run (giving some performance gap indication)
204
181
 
205
182
  # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
206
- # There are 3x exceptions to the aforementioned iterative solution,
207
- # hopefully to correct (TO-DO):
183
+ # Notes:
208
184
  #
209
- # - Steel-framed construction: the selected HP variant has metal
185
+ # - Steel-framed assemblies: the selected HP variant has metal
210
186
  # cladding. The only LP steel-framed BTAP option is wood-clad -
211
187
  # something of an anomaly in commercial construction. By making the
212
188
  # switch earlier to metal cladding, everywhere in Canada except
213
189
  # (milder) SW BC and SW NS, it is hoped that a more consistent,
214
190
  # apples-to-apples comparison is ensured.
215
191
  #
216
- # - CMU-construction with lightweight cladding: The HP variant 10c
217
- # (CMU, gypsum-finished, metal-clad) doesn't have any obvious LP
218
- # construction counterpart. The proposed solution is to rely on
219
- # Mass-6 constructions (literal copies of Mass-2 constructions,
220
- # which are unfinished and brick-clad), as a starting point for
221
- # milder climate zones only, and switch as early as possible to
222
- # 10c constructions.
223
- #
224
- # - ROOF and (exposed) FLOOR surfaces refer to a single LP/HP selection
225
- # respectively. This is expected to change in the future ...
192
+ # - ROOF and (exposed) floor surfaces refer to a single LP/HP selection
193
+ # respectively. This is expected to change in the future @todo.
226
194
 
227
195
  # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
228
- # Preset BTAP/TBD wall construction parameters.
229
- # :sptypes : BTAP/TBD Hash of linked NECB SpaceTypes (symbols)
230
- # :uos : BTAP/TBD Hash of associated of Uo sub-variants
231
- # :lp or :hp : low- or high-performance attribute
196
+ # Preset BTAP/TBD wall assembly parameters.
232
197
  @@data = {}
233
198
 
234
- @@data[MASS2] = { sptypes: {}, uos: {}, lp: true }
235
- @@data[MASSB] = { sptypes: {}, uos: {}, hp: true }
236
- @@data[MASS4] = { sptypes: {}, uos: {}, lp: true }
237
- @@data[MASS8] = { sptypes: {}, uos: {}, hp: true }
238
- @@data[MASS6] = { sptypes: {}, uos: {}, lp: true }
239
- @@data[MASSC] = { sptypes: {}, uos: {}, hp: true }
240
- @@data[MTAL1] = { sptypes: {}, uos: {}, lp: true }
241
- @@data[MTALD] = { sptypes: {}, uos: {}, hp: true }
242
- @@data[WOOD5] = { sptypes: {}, uos: {}, lp: true }
243
- @@data[WOOD7] = { sptypes: {}, uos: {}, hp: true }
244
- @@data[STEL1] = { sptypes: {}, uos: {}, lp: true }
245
- @@data[STEL2] = { sptypes: {}, uos: {}, hp: true }
246
- @@data[FLOOR] = { sptypes: {}, uos: {} }
247
- @@data[ROOFS] = { sptypes: {}, uos: {} }
199
+ # Construction sub-variant identified strictly by Uo, e.g. 0.314 W/m2.K.
200
+ @@data[MASS2] = {uos: [0.314, 0.278, 0.247, 0.210, 0.183]}
201
+ @@data[MASSB] = {uos: [0.130, 0.100]}
248
202
 
249
- # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
250
- # A construction sub-variant is identified strictly by its Uo factor:
251
- #
252
- # e.g. "314" describes a Uo factor of 0.314 W/m2.K
253
- #
254
- # Listed items for each sub-variant are layer identifiers (for BTAP
255
- # costing only). For the moment, they are listed integers (but should
256
- # be expanded - e.g. as Hash keys - to hold additional costing metadata,
257
- # e.g. $/m2). This should be (soon) removed from BTAP/TBD data.
258
- #
259
- # NOTE: Missing gypsum finish for WOOD7 Uo 0.130?
260
-
261
- @@data[MASS2][:uos]["314"] = [ 24, 25, 26, 27, 28,134, 20, 21,139,141 ]
262
- @@data[MASS2][:uos]["278"] = [ 24, 25, 26, 27, 28, 42, 20, 21,139,141 ]
263
- @@data[MASS2][:uos]["247"] = [ 24, 25, 26, 27, 28, 58, 20, 21,139,141 ]
264
- @@data[MASS2][:uos]["210"] = [ 24, 25, 26, 27, 28, 55, 20, 21,139,141 ]
265
- @@data[MASS2][:uos]["183"] = [ 24, 25, 26, 27, 28, 68, 20, 21,139,141 ]
266
- @@data[MASSB][:uos]["130"] = [ 1, 11, 24,160,164,179,141 ]
267
- @@data[MASSB][:uos]["100"] = [ 1, 11, 24,160,165,179,141 ]
268
-
269
- @@data[MASS4][:uos]["314"] = [ 1, 11, 43, 6, 92, 41 ]
270
- @@data[MASS4][:uos]["278"] = [ 1, 11, 69, 6, 41,150 ]
271
- @@data[MASS4][:uos]["247"] = [ 1, 11, 43, 6, 58, 41 ]
272
- @@data[MASS4][:uos]["210"] = [ 1, 11, 43, 6,134, 41 ]
273
- @@data[MASS4][:uos]["183"] = [ 1, 11, 49, 80, 41 ]
274
- @@data[MASS8][:uos]["130"] = [ 1, 11,168,195 ]
275
- @@data[MASS8][:uos]["100"] = [ 1, 11,168,195 ]
276
-
277
- @@data[MASS6][:uos]["314"] = [ 24, 25, 26, 27, 28,134, 20, 21,139,141 ]
278
- @@data[MASS6][:uos]["278"] = [ 24, 25, 26, 27, 28, 42, 20, 21,139,141 ]
279
- @@data[MASS6][:uos]["247"] = [ 24, 25, 26, 27, 28, 58, 20, 21,139,141 ]
280
- @@data[MASSC][:uos]["210"] = [ 1, 11,160, 24, 25, 26, 27, 28,172,181,162,196,180,141 ]
281
- @@data[MASSC][:uos]["183"] = [ 1, 11,160, 24, 25, 26, 27, 28,172,182,163,196,180,141 ]
282
- @@data[MASSC][:uos]["130"] = [ 1, 11,160, 24, 25, 26, 27, 28,172,185,165,196,180,141 ]
283
- @@data[MASSC][:uos]["100"] = [ 1, 11,160, 24, 25, 26, 27, 28,172,186,163,165,196,180,141]
284
- @@data[MASSC][:uos]["080"] = [ 1, 11,160, 24, 25, 26, 27, 28,172,188,165,165,196,180,141]
285
-
286
- @@data[MTAL1][:uos]["314"] = [ 1, 11, 43, 6, 56,150, 48 ]
287
- @@data[MTAL1][:uos]["278"] = [ 1, 11, 43, 6, 48, 55 ]
288
- @@data[MTAL1][:uos]["247"] = [ 1, 11, 43, 56, 6, 48, 59 ]
289
- @@data[MTAL1][:uos]["210"] = [ 1, 11, 43, 63, 6, 48, 59 ]
290
- @@data[MTAL1][:uos]["183"] = [ 1, 11, 43, 58, 6, 48, 59 ]
291
- @@data[MTALD][:uos]["130"] = [ 11,160,204,203,205,204,174,173,180, 1 ]
292
- @@data[MTALD][:uos]["100"] = [ 11,160,204,203,205,204,174,174,180, 1 ]
293
-
294
- @@data[WOOD5][:uos]["314"] = [138, 3, 43, 5, 6,153, 20, 21,139,141, 1]
295
- @@data[WOOD5][:uos]["278"] = [138, 3, 53, 56, 5, 6, 20, 21,139,141, 1]
296
- @@data[WOOD5][:uos]["247"] = [138, 3, 4, 5, 56, 6, 20, 21,139,141, 1]
297
- @@data[WOOD5][:uos]["210"] = [138, 3, 53, 5, 56, 6, 20, 21,139,141, 1]
298
- @@data[WOOD5][:uos]["183"] = [138, 3, 53, 5, 67, 6, 20, 21,139,141, 1]
299
- @@data[WOOD7][:uos]["130"] = [138,160, 56,163,197, 20, 21,139,141, 1 ] # < added '1' for gypsum finish
300
-
301
- @@data[STEL1][:uos]["314"] = [ 11, 3, 43,153, 6, 7,141, 9, 10, 1 ]
302
- @@data[STEL1][:uos]["278"] = [ 11, 3, 53, 5, 56, 6, 7,141, 9, 10, 1 ]
303
- @@data[STEL2][:uos]["247"] = [ 11, 3, 53, 5, 63, 6, 7,141, 9, 10, 1 ]
304
- @@data[STEL2][:uos]["210"] = [ 11, 3, 53, 5, 67, 6, 7,141, 9, 10, 1 ]
305
- @@data[STEL2][:uos]["183"] = [ 11, 3, 53, 5, 56, 67, 6, 7,141, 9, 10, 1]
306
- @@data[STEL2][:uos]["130"] = [ 11, 3, 43,171,172,164,163,186,196,180,141, 1]
307
- @@data[STEL2][:uos]["100"] = [ 11, 3, 43,171,172,165,163,187,197,180,141, 1]
308
- @@data[STEL2][:uos]["080"] = [ 11, 3, 43,171,172,165,165,188,197,180,141, 1]
309
-
310
- @@data[FLOOR][:uos]["227"] = [117,145,118, 3, 99, 6,119 ]
311
- @@data[FLOOR][:uos]["183"] = [117,145,118, 3, 99, 56, 6,119]
312
- @@data[FLOOR][:uos]["162"] = [117,145,118, 3, 99, 67, 6,119]
313
- @@data[FLOOR][:uos]["142"] = [117,145,118, 3, 68, 56, 6,119]
314
- @@data[FLOOR][:uos]["116"] = [117,145,118, 3,157, 6,157, 6]
315
- @@data[FLOOR][:uos]["101"] = [117,145,118, 3,157,158, 6,119]
316
-
317
- @@data[ROOFS][:uos]["227"] = [ 94, 97, 71, 92, 93]
318
- @@data[ROOFS][:uos]["193"] = [ 94, 97, 80, 80, 93]
319
- @@data[ROOFS][:uos]["183"] = [ 94, 97,134,134, 93]
320
- @@data[ROOFS][:uos]["162"] = [ 94, 97,102,153, 93]
321
- @@data[ROOFS][:uos]["156"] = [ 94, 97,134, 91, 93]
322
- @@data[ROOFS][:uos]["142"] = [ 94, 97,106, 93 ]
323
- @@data[ROOFS][:uos]["138"] = [ 94, 97,106, 93 ] # same as :142 ?
324
- @@data[ROOFS][:uos]["121"] = [ 94, 97,106,150, 93]
325
- @@data[ROOFS][:uos]["100"] = [ 94, 97,106,106, 93]
203
+ @@data[MASS4] = {uos: [0.314, 0.278, 0.247, 0.210, 0.183]}
204
+ @@data[MASS8] = {uos: [0.130, 0.100]}
326
205
 
327
- # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
328
- # In BTAP costing, each NECB building/space type is linked to a default
329
- # construction set, which holds one of the preceding wall options. This
330
- # linkage is now extended to OpenStudio models (not just costing),
331
- # given the construction-specific nature of MAJOR thermal bridging.
332
- #
333
- # Each of these wall options holds NECB building (or space) type keywords
334
- # (see below). The default (fall back) keyword is :office. String pattern
335
- # recognition, e.g.:
336
- #
337
- # :gym from "Gymnasium/Fitness centre exercise area"
338
- #
339
- # ... is implemented elsewhere in the BTAP/TBD class. The default BTAP
340
- # wall construction for :office (fall back) is STEL1. Subsequent PSI
341
- # factor selection is based strictly on selected wall construction, i.e.
342
- # regardless of selected roof, fenestration, etc. The linkage remains valid
343
- # for both building and space types (regardless of NECB vintage).
344
- #
345
- # The implementation is likely to be revised in the future, yet would
346
- # remain conceptually similar.
347
-
348
- # "BTAP-ExteriorWall-Mass-2" & "BTAP-ExteriorWall-Mass-2b"
349
- @@data[MASS2][:sptypes][:exercise ] = {}
350
- @@data[MASS2][:sptypes][:firestation ] = {}
351
- @@data[MASS2][:sptypes][:gym ] = {}
352
- @@data[MASSB][:sptypes][:exercise ] = {}
353
- @@data[MASSB][:sptypes][:firestation ] = {}
354
- @@data[MASSB][:sptypes][:gym ] = {}
355
-
356
- # "BTAP-ExteriorWall-Mass-4" & "BTAP-ExteriorWall-Mass-8c"
357
- @@data[MASS4][:sptypes][:courthouse ] = {}
358
- @@data[MASS4][:sptypes][:museum ] = {}
359
- @@data[MASS4][:sptypes][:parking ] = {}
360
- @@data[MASS4][:sptypes][:post ] = {}
361
- @@data[MASS4][:sptypes][:transportation ] = {}
362
- @@data[MASS8][:sptypes][:courthouse ] = {}
363
- @@data[MASS8][:sptypes][:museum ] = {}
364
- @@data[MASS8][:sptypes][:parking ] = {}
365
- @@data[MASS8][:sptypes][:post ] = {}
366
- @@data[MASS8][:sptypes][:transportation ] = {}
367
-
368
- # "BTAP-ExteriorWall-Mass-6" & "BTAP-ExteriorWall-Mass-10c"
369
- @@data[MASS6][:sptypes][:automotive ] = {}
370
- @@data[MASS6][:sptypes][:penitentiary ] = {}
371
- @@data[MASS6][:sptypes][:arena ] = {}
372
- @@data[MASS6][:sptypes][:warehouse ] = {}
373
- @@data[MASS6][:sptypes][:storage ] = {}
374
- @@data[MASSC][:sptypes][:automotive ] = {}
375
- @@data[MASSC][:sptypes][:penitentiary ] = {}
376
- @@data[MASSC][:sptypes][:arena ] = {}
377
- @@data[MASSC][:sptypes][:warehouse ] = {}
378
- @@data[MASSC][:sptypes][:storage ] = {}
379
-
380
- # "BTAP-ExteriorWall-Metal-1" & "BTAP-ExteriorWall-Metal-1d"
381
- @@data[MTAL1][:sptypes][:mfg ] = {}
382
- @@data[MTAL1][:sptypes][:workshop ] = {}
383
- @@data[MTALD][:sptypes][:mfg ] = {}
384
- @@data[MTALD][:sptypes][:workshop ] = {}
385
-
386
- # "BTAP-ExteriorWall-WoodFramed-5" & "BTAP-ExteriorWall-WoodFramed-7"
387
- @@data[WOOD5][:sptypes][:religious ] = {}
388
- @@data[WOOD5][:sptypes][:dwelling ] = {} # if < 5 stories
389
- @@data[WOOD5][:sptypes][:library ] = {} # if < 3 stories
390
- @@data[WOOD5][:sptypes][:school ] = {} # if < 3 stories
391
- @@data[WOOD7][:sptypes][:religious ] = {}
392
- @@data[WOOD7][:sptypes][:dwelling ] = {} # if < 5 stories
393
- @@data[WOOD7][:sptypes][:library ] = {} # if < 3 stories
394
- @@data[WOOD7][:sptypes][:school ] = {} # if < 3 stories
395
-
396
- # "BTAP-ExteriorWall-SteelFramed-1" & "BTAP-ExteriorWall-SteelFramed-2"
397
- @@data[STEL1][:sptypes][:dwelling5 ] = {} # if > 4 stories
398
- @@data[STEL1][:sptypes][:library3 ] = {} # if > 2 stories
399
- @@data[STEL1][:sptypes][:school3 ] = {} # if > 2 stories
400
- @@data[STEL1][:sptypes][:convention ] = {}
401
- @@data[STEL1][:sptypes][:dining ] = {}
402
- @@data[STEL1][:sptypes][:health ] = {}
403
- @@data[STEL1][:sptypes][:hospital ] = {}
404
- @@data[STEL1][:sptypes][:motion ] = {}
405
- @@data[STEL1][:sptypes][:performance ] = {}
406
- @@data[STEL1][:sptypes][:police ] = {}
407
- @@data[STEL1][:sptypes][:retail ] = {}
408
- @@data[STEL1][:sptypes][:town ] = {}
409
- @@data[STEL1][:sptypes][:office ] = {}
410
- @@data[STEL2][:sptypes][:dwelling5 ] = {} # if > 4 stories
411
- @@data[STEL2][:sptypes][:library3 ] = {} # if > 2 stories
412
- @@data[STEL2][:sptypes][:school3 ] = {} # if > 2 stories
413
- @@data[STEL2][:sptypes][:convention ] = {}
414
- @@data[STEL2][:sptypes][:dining ] = {}
415
- @@data[STEL2][:sptypes][:health ] = {}
416
- @@data[STEL2][:sptypes][:hospital ] = {}
417
- @@data[STEL2][:sptypes][:motion ] = {}
418
- @@data[STEL2][:sptypes][:performance ] = {}
419
- @@data[STEL2][:sptypes][:police ] = {}
420
- @@data[STEL2][:sptypes][:retail ] = {}
421
- @@data[STEL2][:sptypes][:town ] = {}
422
- @@data[STEL2][:sptypes][:office ] = {}
206
+ @@data[WOOD5] = {uos: [0.314, 0.278, 0.247, 0.210, 0.183]}
207
+ @@data[WOOD7] = {uos: [0.130]}
208
+
209
+ @@data[STEL1] = {uos: [0.314, 0.278]}
210
+ @@data[STEL2] = {uos: [0.247, 0.210, 0.183, 0.130, 0.100, 0.080]}
211
+
212
+ @@data[FLOOR] = {uos: [0.227, 0.183, 0.162, 0.142, 0.116, 0.101]}
213
+ @@data[ROOF ] = {uos: [0.227, 0.193, 0.183, 0.162, 0.156, 0.142, 0.138, 0.121, 0.100]}
423
214
 
424
215
  # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
425
- # Initialize PSI factor qualities per wall construction.
216
+ # Initialize PSI factor qualities per wall assembly.
426
217
  @@data.values.each do |construction|
427
218
  construction[:bad ] = {}
428
219
  construction[:good] = {}
429
220
  end
430
221
 
431
222
  # Thermal bridge types :balcony, :party and :joint are NOT expected to
432
- # be processed within BTAP. They are not costed out either. At some
433
- # point, it may become wise to do so (notably for cantilevered balconies
434
- # in MURBs). Default, generic BETBG PSI factors are nonetheless provided
435
- # here (just in case):
436
- #
437
- # - for the "bad" BTAP cases, retained values are those of the
438
- # generic "bad" BETBG set
439
- # - while "good" BTAP values are those of the generic BETBG
440
- # "efficient" set
223
+ # be processed soon within BTAP. They are neither costed out, nor are carbon
224
+ # intensities (kg CO2eq/linear meter) associated to them. At some point, it
225
+ # may be wise to do so (notably cantilevered balconies in MURBs) - @todo.
226
+ # Default, generic BETBG PSI factors are nonetheless provided here:
227
+ # - for "bad" BTAP cases : generic BETBG set "bad"
228
+ # - for "good" BTAP cases: generic BETBG set "efficient"
441
229
 
230
+ @@data[MASS2][ :bad][:id ] = MASS2_BAD
442
231
  @@data[MASS2][ :bad][:rimjoist ] = { psi: 0.470 }
443
232
  @@data[MASS2][ :bad][:parapet ] = { psi: 0.500 }
444
- @@data[MASS2][ :bad][:head ] = { psi: 0.350 }
445
- @@data[MASS2][ :bad][:jamb ] = { psi: 0.350 }
446
- @@data[MASS2][ :bad][:sill ] = { psi: 0.350 }
233
+ @@data[MASS2][ :bad][:fenestration] = { psi: 0.350 }
234
+ @@data[MASS2][ :bad][:door ] = { psi: 0.000 }
447
235
  @@data[MASS2][ :bad][:corner ] = { psi: 0.150 }
448
236
  @@data[MASS2][ :bad][:balcony ] = { psi: 1.000 }
449
237
  @@data[MASS2][ :bad][:party ] = { psi: 0.850 }
450
238
  @@data[MASS2][ :bad][:grade ] = { psi: 0.520 }
451
239
  @@data[MASS2][ :bad][:joint ] = { psi: 0.300 }
452
- @@data[MASS2][ :bad][:transition ] = { psi: 0.000 }
453
240
 
241
+ @@data[MASS2][:good][:id ] = MASS2_GOOD
454
242
  @@data[MASS2][:good][:rimjoist ] = { psi: 0.100 }
455
243
  @@data[MASS2][:good][:parapet ] = { psi: 0.230 }
456
- @@data[MASS2][:good][:head ] = { psi: 0.078 }
457
- @@data[MASS2][:good][:jamb ] = { psi: 0.078 }
458
- @@data[MASS2][:good][:sill ] = { psi: 0.078 }
244
+ @@data[MASS2][:good][:fenestration] = { psi: 0.078 }
245
+ @@data[MASS2][:good][:door ] = { psi: 0.000 }
459
246
  @@data[MASS2][:good][:corner ] = { psi: 0.090 }
460
247
  @@data[MASS2][:good][:balcony ] = { psi: 0.200 }
461
248
  @@data[MASS2][:good][:party ] = { psi: 0.200 }
462
249
  @@data[MASS2][:good][:grade ] = { psi: 0.090 }
463
250
  @@data[MASS2][:good][:joint ] = { psi: 0.100 }
464
- @@data[MASS2][:good][:transition ] = { psi: 0.000 }
465
251
 
252
+ @@data[MASSB][ :bad][:id ] = MASSB_BAD
466
253
  @@data[MASSB][ :bad][:rimjoist ] = { psi: 0.470 }
467
254
  @@data[MASSB][ :bad][:parapet ] = { psi: 0.500 }
468
- @@data[MASSB][ :bad][:head ] = { psi: 0.350 }
469
- @@data[MASSB][ :bad][:jamb ] = { psi: 0.350 }
470
- @@data[MASSB][ :bad][:sill ] = { psi: 0.350 }
255
+ @@data[MASSB][ :bad][:fenestration] = { psi: 0.350 }
256
+ @@data[MASSB][ :bad][:door ] = { psi: 0.000 }
471
257
  @@data[MASSB][ :bad][:corner ] = { psi: 0.150 }
472
258
  @@data[MASSB][ :bad][:balcony ] = { psi: 1.000 }
473
259
  @@data[MASSB][ :bad][:party ] = { psi: 0.850 }
474
260
  @@data[MASSB][ :bad][:grade ] = { psi: 0.520 }
475
261
  @@data[MASSB][ :bad][:joint ] = { psi: 0.300 }
476
- @@data[MASSB][ :bad][:transition ] = { psi: 0.000 }
477
262
 
263
+ @@data[MASSB][:good][:id ] = MASSB_GOOD
478
264
  @@data[MASSB][:good][:rimjoist ] = { psi: 0.100 }
479
265
  @@data[MASSB][:good][:parapet ] = { psi: 0.230 }
480
- @@data[MASSB][:good][:head ] = { psi: 0.078 }
481
- @@data[MASSB][:good][:jamb ] = { psi: 0.078 }
482
- @@data[MASSB][:good][:sill ] = { psi: 0.078 }
266
+ @@data[MASSB][:good][:fenestration] = { psi: 0.078 }
267
+ @@data[MASSB][:good][:door ] = { psi: 0.000 }
483
268
  @@data[MASSB][:good][:corner ] = { psi: 0.090 }
484
269
  @@data[MASSB][:good][:balcony ] = { psi: 0.200 }
485
270
  @@data[MASSB][:good][:party ] = { psi: 0.200 }
486
271
  @@data[MASSB][:good][:grade ] = { psi: 0.090 }
487
272
  @@data[MASSB][:good][:joint ] = { psi: 0.100 }
488
- @@data[MASSB][:good][:transition ] = { psi: 0.000 }
489
273
 
274
+ @@data[MASS4][ :bad][:id ] = MASS4_BAD
490
275
  @@data[MASS4][ :bad][:rimjoist ] = { psi: 0.200 }
491
276
  @@data[MASS4][ :bad][:parapet ] = { psi: 0.650 }
492
- @@data[MASS4][ :bad][:head ] = { psi: 0.078 }
493
- @@data[MASS4][ :bad][:jamb ] = { psi: 0.078 }
494
- @@data[MASS4][ :bad][:sill ] = { psi: 0.078 }
277
+ @@data[MASS4][ :bad][:fenestration] = { psi: 0.078 }
278
+ @@data[MASS4][ :bad][:door ] = { psi: 0.000 }
495
279
  @@data[MASS4][ :bad][:corner ] = { psi: 0.370 }
496
280
  @@data[MASS4][ :bad][:balcony ] = { psi: 1.000 }
497
281
  @@data[MASS4][ :bad][:party ] = { psi: 0.850 }
498
282
  @@data[MASS4][ :bad][:grade ] = { psi: 0.800 }
499
283
  @@data[MASS4][ :bad][:joint ] = { psi: 0.300 }
500
- @@data[MASS4][ :bad][:transition ] = { psi: 0.000 }
501
284
 
285
+ @@data[MASS4][:good][:id ] = MASS4_GOOD
502
286
  @@data[MASS4][:good][:rimjoist ] = { psi: 0.020 }
503
287
  @@data[MASS4][:good][:parapet ] = { psi: 0.240 }
504
- @@data[MASS4][:good][:head ] = { psi: 0.078 }
505
- @@data[MASS4][:good][:jamb ] = { psi: 0.078 }
506
- @@data[MASS4][:good][:sill ] = { psi: 0.078 }
288
+ @@data[MASS4][:good][:fenestration] = { psi: 0.078 }
289
+ @@data[MASS4][:good][:door ] = { psi: 0.000 }
507
290
  @@data[MASS4][:good][:corner ] = { psi: 0.160 }
508
291
  @@data[MASS4][:good][:balcony ] = { psi: 0.200 }
509
292
  @@data[MASS4][:good][:party ] = { psi: 0.200 }
510
293
  @@data[MASS4][:good][:grade ] = { psi: 0.320 }
511
294
  @@data[MASS4][:good][:joint ] = { psi: 0.100 }
512
- @@data[MASS4][:good][:transition ] = { psi: 0.000 }
513
295
 
296
+ @@data[MASS8][ :bad][:id ] = MASS8_BAD
514
297
  @@data[MASS8][ :bad][:rimjoist ] = { psi: 0.200 }
515
298
  @@data[MASS8][ :bad][:parapet ] = { psi: 0.650 }
516
- @@data[MASS8][ :bad][:head ] = { psi: 0.078 }
517
- @@data[MASS8][ :bad][:jamb ] = { psi: 0.078 }
518
- @@data[MASS8][ :bad][:sill ] = { psi: 0.078 }
299
+ @@data[MASS8][ :bad][:fenestration] = { psi: 0.078 }
300
+ @@data[MASS8][ :bad][:door ] = { psi: 0.000 }
519
301
  @@data[MASS8][ :bad][:corner ] = { psi: 0.370 }
520
302
  @@data[MASS8][ :bad][:balcony ] = { psi: 1.000 }
521
303
  @@data[MASS8][ :bad][:party ] = { psi: 0.850 }
522
304
  @@data[MASS8][ :bad][:grade ] = { psi: 0.800 }
523
305
  @@data[MASS8][ :bad][:joint ] = { psi: 0.300 }
524
- @@data[MASS8][ :bad][:transition ] = { psi: 0.000 }
525
306
 
307
+ @@data[MASS8][:good][:id ] = MASS8_GOOD
526
308
  @@data[MASS8][:good][:rimjoist ] = { psi: 0.020 }
527
309
  @@data[MASS8][:good][:parapet ] = { psi: 0.240 }
528
- @@data[MASS8][:good][:head ] = { psi: 0.078 }
529
- @@data[MASS8][:good][:jamb ] = { psi: 0.078 }
530
- @@data[MASS8][:good][:sill ] = { psi: 0.078 }
310
+ @@data[MASS8][:good][:fenestration] = { psi: 0.078 }
311
+ @@data[MASS8][:good][:door ] = { psi: 0.000 }
531
312
  @@data[MASS8][:good][:corner ] = { psi: 0.160 }
532
313
  @@data[MASS8][:good][:balcony ] = { psi: 0.200 }
533
314
  @@data[MASS8][:good][:party ] = { psi: 0.200 }
534
315
  @@data[MASS8][:good][:grade ] = { psi: 0.320 }
535
316
  @@data[MASS8][:good][:joint ] = { psi: 0.100 }
536
- @@data[MASS8][:good][:transition ] = { psi: 0.000 }
537
-
538
- @@data[MASS6][ :bad][:rimjoist ] = { psi: 0.470 }
539
- @@data[MASS6][ :bad][:parapet ] = { psi: 0.500 }
540
- @@data[MASS6][ :bad][:head ] = { psi: 0.350 }
541
- @@data[MASS6][ :bad][:jamb ] = { psi: 0.350 }
542
- @@data[MASS6][ :bad][:sill ] = { psi: 0.350 }
543
- @@data[MASS6][ :bad][:corner ] = { psi: 0.150 }
544
- @@data[MASS6][ :bad][:balcony ] = { psi: 1.000 }
545
- @@data[MASS6][ :bad][:party ] = { psi: 0.850 }
546
- @@data[MASS6][ :bad][:grade ] = { psi: 0.520 }
547
- @@data[MASS6][ :bad][:joint ] = { psi: 0.300 }
548
- @@data[MASS6][ :bad][:transition ] = { psi: 0.000 }
549
-
550
- @@data[MASS6][:good][:rimjoist ] = { psi: 0.100 }
551
- @@data[MASS6][:good][:parapet ] = { psi: 0.230 }
552
- @@data[MASS6][:good][:head ] = { psi: 0.078 }
553
- @@data[MASS6][:good][:jamb ] = { psi: 0.078 }
554
- @@data[MASS6][:good][:sill ] = { psi: 0.078 }
555
- @@data[MASS6][:good][:corner ] = { psi: 0.090 }
556
- @@data[MASS6][:good][:balcony ] = { psi: 0.200 }
557
- @@data[MASS6][:good][:party ] = { psi: 0.200 }
558
- @@data[MASS6][:good][:grade ] = { psi: 0.090 }
559
- @@data[MASS6][:good][:joint ] = { psi: 0.100 }
560
- @@data[MASS6][:good][:transition ] = { psi: 0.000 }
561
-
562
- @@data[MASSC][ :bad][:rimjoist ] = { psi: 0.170 }
563
- @@data[MASSC][ :bad][:parapet ] = { psi: 0.500 }
564
- @@data[MASSC][ :bad][:head ] = { psi: 0.350 }
565
- @@data[MASSC][ :bad][:jamb ] = { psi: 0.350 }
566
- @@data[MASSC][ :bad][:sill ] = { psi: 0.350 }
567
- @@data[MASSC][ :bad][:corner ] = { psi: 0.150 }
568
- @@data[MASSC][ :bad][:balcony ] = { psi: 1.000 }
569
- @@data[MASSC][ :bad][:party ] = { psi: 0.850 }
570
- @@data[MASSC][ :bad][:grade ] = { psi: 0.720 }
571
- @@data[MASSC][ :bad][:joint ] = { psi: 0.300 }
572
- @@data[MASSC][ :bad][:transition ] = { psi: 0.000 }
573
-
574
- @@data[MASSC][:good][:rimjoist ] = { psi: 0.017 }
575
- @@data[MASSC][:good][:parapet ] = { psi: 0.230 }
576
- @@data[MASSC][:good][:head ] = { psi: 0.078 }
577
- @@data[MASSC][:good][:jamb ] = { psi: 0.078 }
578
- @@data[MASSC][:good][:sill ] = { psi: 0.078 }
579
- @@data[MASSC][:good][:corner ] = { psi: 0.090 }
580
- @@data[MASSC][:good][:balcony ] = { psi: 0.200 }
581
- @@data[MASSC][:good][:party ] = { psi: 0.200 }
582
- @@data[MASSC][:good][:grade ] = { psi: 0.470 }
583
- @@data[MASSC][:good][:joint ] = { psi: 0.100 }
584
- @@data[MASSC][:good][:transition ] = { psi: 0.000 }
585
-
586
- @@data[MTAL1][ :bad][:rimjoist ] = { psi: 0.320 }
587
- @@data[MTAL1][ :bad][:parapet ] = { psi: 0.420 }
588
- @@data[MTAL1][ :bad][:head ] = { psi: 0.520 }
589
- @@data[MTAL1][ :bad][:jamb ] = { psi: 0.520 }
590
- @@data[MTAL1][ :bad][:sill ] = { psi: 0.520 }
591
- @@data[MTAL1][ :bad][:corner ] = { psi: 0.150 }
592
- @@data[MTAL1][ :bad][:balcony ] = { psi: 1.000 }
593
- @@data[MTAL1][ :bad][:party ] = { psi: 0.850 }
594
- @@data[MTAL1][ :bad][:grade ] = { psi: 0.700 }
595
- @@data[MTAL1][ :bad][:joint ] = { psi: 0.300 }
596
- @@data[MTAL1][ :bad][:transition ] = { psi: 0.000 }
597
-
598
- @@data[MTAL1][:good][:rimjoist ] = { psi: 0.030 }
599
- @@data[MTAL1][:good][:parapet ] = { psi: 0.350 }
600
- @@data[MTAL1][:good][:head ] = { psi: 0.078 }
601
- @@data[MTAL1][:good][:jamb ] = { psi: 0.078 }
602
- @@data[MTAL1][:good][:sill ] = { psi: 0.078 }
603
- @@data[MTAL1][:good][:corner ] = { psi: 0.070 }
604
- @@data[MTAL1][:good][:balcony ] = { psi: 0.200 }
605
- @@data[MTAL1][:good][:party ] = { psi: 0.200 }
606
- @@data[MTAL1][:good][:grade ] = { psi: 0.500 }
607
- @@data[MTAL1][:good][:joint ] = { psi: 0.100 }
608
- @@data[MTAL1][:good][:transition ] = { psi: 0.000 }
609
-
610
- @@data[MTALD][ :bad][:rimjoist ] = { psi: 0.320 }
611
- @@data[MTALD][ :bad][:parapet ] = { psi: 0.420 }
612
- @@data[MTALD][ :bad][:head ] = { psi: 0.520 }
613
- @@data[MTALD][ :bad][:jamb ] = { psi: 0.520 }
614
- @@data[MTALD][ :bad][:sill ] = { psi: 0.520 }
615
- @@data[MTALD][ :bad][:corner ] = { psi: 0.150 }
616
- @@data[MTALD][ :bad][:balcony ] = { psi: 1.000 }
617
- @@data[MTALD][ :bad][:party ] = { psi: 0.850 }
618
- @@data[MTALD][ :bad][:grade ] = { psi: 0.700 }
619
- @@data[MTALD][ :bad][:joint ] = { psi: 0.300 }
620
- @@data[MTALD][ :bad][:transition ] = { psi: 0.000 }
621
-
622
- @@data[MTALD][:good][:rimjoist ] = { psi: 0.030 }
623
- @@data[MTALD][:good][:parapet ] = { psi: 0.350 }
624
- @@data[MTALD][:good][:head ] = { psi: 0.078 }
625
- @@data[MTALD][:good][:jamb ] = { psi: 0.078 }
626
- @@data[MTALD][:good][:sill ] = { psi: 0.078 }
627
- @@data[MTALD][:good][:corner ] = { psi: 0.070 }
628
- @@data[MTALD][:good][:balcony ] = { psi: 0.200 }
629
- @@data[MTALD][:good][:party ] = { psi: 0.200 }
630
- @@data[MTALD][:good][:grade ] = { psi: 0.500 }
631
- @@data[MTALD][:good][:joint ] = { psi: 0.100 }
632
- @@data[MTALD][:good][:transition ] = { psi: 0.000 }
633
317
 
318
+ @@data[WOOD5][ :bad][:id ] = WOOD5_BAD
634
319
  @@data[WOOD5][ :bad][:rimjoist ] = { psi: 0.050 }
635
320
  @@data[WOOD5][ :bad][:parapet ] = { psi: 0.050 }
636
- @@data[WOOD5][ :bad][:head ] = { psi: 0.270 }
637
- @@data[WOOD5][ :bad][:jamb ] = { psi: 0.270 }
638
- @@data[WOOD5][ :bad][:sill ] = { psi: 0.270 }
321
+ @@data[WOOD5][ :bad][:fenestration] = { psi: 0.270 }
322
+ @@data[WOOD5][ :bad][:door ] = { psi: 0.000 }
639
323
  @@data[WOOD5][ :bad][:corner ] = { psi: 0.040 }
640
324
  @@data[WOOD5][ :bad][:balcony ] = { psi: 1.000 }
641
325
  @@data[WOOD5][ :bad][:party ] = { psi: 0.850 }
642
326
  @@data[WOOD5][ :bad][:grade ] = { psi: 0.550 }
643
327
  @@data[WOOD5][ :bad][:joint ] = { psi: 0.300 }
644
- @@data[WOOD5][ :bad][:transition ] = { psi: 0.000 }
645
328
 
329
+ @@data[WOOD5][:good][:id ] = WOOD5_GOOD
646
330
  @@data[WOOD5][:good][:rimjoist ] = { psi: 0.030 }
647
331
  @@data[WOOD5][:good][:parapet ] = { psi: 0.050 }
648
- @@data[WOOD5][:good][:head ] = { psi: 0.078 }
649
- @@data[WOOD5][:good][:jamb ] = { psi: 0.078 }
650
- @@data[WOOD5][:good][:sill ] = { psi: 0.078 }
332
+ @@data[WOOD5][:good][:fenestration] = { psi: 0.078 }
333
+ @@data[WOOD5][:good][:door ] = { psi: 0.000 }
651
334
  @@data[WOOD5][:good][:corner ] = { psi: 0.040 }
652
335
  @@data[WOOD5][:good][:balcony ] = { psi: 0.200 }
653
336
  @@data[WOOD5][:good][:party ] = { psi: 0.200 }
654
337
  @@data[WOOD5][:good][:grade ] = { psi: 0.090 }
655
338
  @@data[WOOD5][:good][:joint ] = { psi: 0.100 }
656
- @@data[WOOD5][:good][:transition ] = { psi: 0.000 }
657
339
 
340
+ @@data[WOOD7][ :bad][:id ] = WOOD7_BAD
658
341
  @@data[WOOD7][ :bad][:rimjoist ] = { psi: 0.050 }
659
342
  @@data[WOOD7][ :bad][:parapet ] = { psi: 0.050 }
660
- @@data[WOOD7][ :bad][:head ] = { psi: 0.270 }
661
- @@data[WOOD7][ :bad][:jamb ] = { psi: 0.270 }
662
- @@data[WOOD7][ :bad][:sill ] = { psi: 0.270 }
343
+ @@data[WOOD7][ :bad][:fenestration] = { psi: 0.270 }
344
+ @@data[WOOD7][ :bad][:door ] = { psi: 0.000 }
663
345
  @@data[WOOD7][ :bad][:corner ] = { psi: 0.040 }
664
346
  @@data[WOOD7][ :bad][:balcony ] = { psi: 1.000 }
665
347
  @@data[WOOD7][ :bad][:party ] = { psi: 0.850 }
666
348
  @@data[WOOD7][ :bad][:grade ] = { psi: 0.550 }
667
349
  @@data[WOOD7][ :bad][:joint ] = { psi: 0.300 }
668
- @@data[WOOD7][ :bad][:transition ] = { psi: 0.000 }
669
350
 
351
+ @@data[WOOD7][:good][:id ] = WOOD7_GOOD
670
352
  @@data[WOOD7][:good][:rimjoist ] = { psi: 0.030 }
671
353
  @@data[WOOD7][:good][:parapet ] = { psi: 0.050 }
672
- @@data[WOOD7][:good][:head ] = { psi: 0.078 }
673
- @@data[WOOD7][:good][:jamb ] = { psi: 0.078 }
674
- @@data[WOOD7][:good][:sill ] = { psi: 0.078 }
354
+ @@data[WOOD7][:good][:fenestration] = { psi: 0.078 }
355
+ @@data[WOOD7][:good][:door ] = { psi: 0.000 }
675
356
  @@data[WOOD7][:good][:corner ] = { psi: 0.040 }
676
357
  @@data[WOOD7][:good][:balcony ] = { psi: 0.200 }
677
358
  @@data[WOOD7][:good][:party ] = { psi: 0.200 }
678
359
  @@data[WOOD7][:good][:grade ] = { psi: 0.090 }
679
360
  @@data[WOOD7][:good][:joint ] = { psi: 0.100 }
680
- @@data[WOOD7][:good][:transition ] = { psi: 0.000 }
681
361
 
362
+ @@data[STEL1][ :bad][:id ] = STEL1_BAD
682
363
  @@data[STEL1][ :bad][:rimjoist ] = { psi: 0.280 }
683
364
  @@data[STEL1][ :bad][:parapet ] = { psi: 0.650 }
684
- @@data[STEL1][ :bad][:head ] = { psi: 0.270 }
685
- @@data[STEL1][ :bad][:jamb ] = { psi: 0.270 }
686
- @@data[STEL1][ :bad][:sill ] = { psi: 0.270 }
365
+ @@data[STEL1][ :bad][:fenestration] = { psi: 0.270 }
366
+ @@data[STEL1][ :bad][:door ] = { psi: 0.000 }
687
367
  @@data[STEL1][ :bad][:corner ] = { psi: 0.150 }
688
368
  @@data[STEL1][ :bad][:balcony ] = { psi: 1.000 }
689
369
  @@data[STEL1][ :bad][:party ] = { psi: 0.850 }
690
370
  @@data[STEL1][ :bad][:grade ] = { psi: 0.720 }
691
371
  @@data[STEL1][ :bad][:joint ] = { psi: 0.300 }
692
- @@data[STEL1][ :bad][:transition ] = { psi: 0.000 }
693
372
 
373
+ @@data[STEL1][:good][:id ] = STEL1_GOOD
694
374
  @@data[STEL1][:good][:rimjoist ] = { psi: 0.090 }
695
375
  @@data[STEL1][:good][:parapet ] = { psi: 0.350 }
696
- @@data[STEL1][:good][:head ] = { psi: 0.078 }
697
- @@data[STEL1][:good][:jamb ] = { psi: 0.078 }
698
- @@data[STEL1][:good][:sill ] = { psi: 0.078 }
376
+ @@data[STEL1][:good][:fenestration] = { psi: 0.078 }
377
+ @@data[STEL1][:good][:door ] = { psi: 0.000 }
699
378
  @@data[STEL1][:good][:corner ] = { psi: 0.090 }
700
379
  @@data[STEL1][:good][:balcony ] = { psi: 0.200 }
701
380
  @@data[STEL1][:good][:party ] = { psi: 0.200 }
702
381
  @@data[STEL1][:good][:grade ] = { psi: 0.470 }
703
382
  @@data[STEL1][:good][:joint ] = { psi: 0.100 }
704
- @@data[STEL1][:good][:transition ] = { psi: 0.000 }
705
383
 
384
+ @@data[STEL2][ :bad][:id ] = STEL2_BAD
706
385
  @@data[STEL2][ :bad][:rimjoist ] = { psi: 0.280 }
707
386
  @@data[STEL2][ :bad][:parapet ] = { psi: 0.650 }
708
- @@data[STEL2][ :bad][:head ] = { psi: 0.270 }
709
- @@data[STEL2][ :bad][:jamb ] = { psi: 0.270 }
710
- @@data[STEL2][ :bad][:sill ] = { psi: 0.270 }
387
+ @@data[STEL2][ :bad][:fenestration] = { psi: 0.270 }
388
+ @@data[STEL2][ :bad][:door ] = { psi: 0.000 }
711
389
  @@data[STEL2][ :bad][:corner ] = { psi: 0.150 }
712
390
  @@data[STEL2][ :bad][:balcony ] = { psi: 1.000 }
713
391
  @@data[STEL2][ :bad][:party ] = { psi: 0.850 }
714
392
  @@data[STEL2][ :bad][:grade ] = { psi: 0.720 }
715
393
  @@data[STEL2][ :bad][:joint ] = { psi: 0.300 }
716
- @@data[STEL2][ :bad][:transition ] = { psi: 0.000 }
717
394
 
395
+ @@data[STEL2][:good][:id ] = STEL2_GOOD
718
396
  @@data[STEL2][:good][:rimjoist ] = { psi: 0.090 }
719
397
  @@data[STEL2][:good][:parapet ] = { psi: 0.100 }
720
- @@data[STEL2][:good][:head ] = { psi: 0.078 }
721
- @@data[STEL2][:good][:jamb ] = { psi: 0.078 }
722
- @@data[STEL2][:good][:sill ] = { psi: 0.078 }
398
+ @@data[STEL2][:good][:fenestration] = { psi: 0.078 }
399
+ @@data[STEL2][:good][:door ] = { psi: 0.000 }
723
400
  @@data[STEL2][:good][:corner ] = { psi: 0.090 }
724
401
  @@data[STEL2][:good][:balcony ] = { psi: 0.200 }
725
402
  @@data[STEL2][:good][:party ] = { psi: 0.200 }
726
403
  @@data[STEL2][:good][:grade ] = { psi: 0.470 }
727
404
  @@data[STEL2][:good][:joint ] = { psi: 0.100 }
728
- @@data[STEL2][:good][:transition ] = { psi: 0.000 }
729
-
730
405
  # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
731
- # Extend for BTAP costing.
732
- @@data.values.each do |construction|
733
- construction[:good].values.each { |bridge| bridge[:mat] = {} }
734
- construction[ :bad].values.each { |bridge| bridge[:mat] = {} }
735
- end
736
-
737
- # BTAP costed "materials" (Hash keywords in double quotations) for MAJOR
738
- # thermal bridges. Corresponding Hash values are multipliers.
739
- #
740
- # NOTE: "0" as a NIL placeholder (no cost associated to thermal bridge).
741
- @@data[MASS2][ :bad][:id ] = MASS2_BAD
742
- @@data[MASS2][ :bad][:rimjoist ][:mat][ "21"] = 1.000
743
- @@data[MASS2][ :bad][:rimjoist ][:mat]["172"] = 0.250
744
- @@data[MASS2][ :bad][:parapet ][:mat][ "0"] = 1.000
745
- @@data[MASS2][ :bad][:head ][:mat]["139"] = 0.750
746
- @@data[MASS2][ :bad][:jamb ][:mat]["139"] = 0.750
747
- @@data[MASS2][ :bad][:sill ][:mat]["139"] = 0.750
748
- @@data[MASS2][ :bad][:corner ][:mat][ "0"] = 1.000
749
- @@data[MASS2][ :bad][:balcony ][:mat][ ""] = 1.000
750
- @@data[MASS2][ :bad][:party ][:mat][ ""] = 1.000
751
- @@data[MASS2][ :bad][:grade ][:mat][ "21"] = 1.000
752
- @@data[MASS2][ :bad][:grade ][:mat]["139"] = 0.500
753
- @@data[MASS2][ :bad][:joint ][:mat][ ""] = 1.000
754
- @@data[MASS2][ :bad][:transition ][:mat][ ""] = 1.000
755
-
756
- @@data[MASS2][:good][:id ] = MASS2_GOOD
757
- @@data[MASS2][:good][:rimjoist ][:mat]["189"] = 1.000
758
- @@data[MASS2][:good][:rimjoist ][:mat]["172"] = 0.500
759
- @@data[MASS2][:good][:parapet ][:mat][ "57"] = 3.300
760
- @@data[MASS2][:good][:parapet ][:mat]["139"] = 1.000
761
- @@data[MASS2][:good][:head ][:mat]["139"] = 0.500
762
- @@data[MASS2][:good][:jamb ][:mat]["139"] = 0.500
763
- @@data[MASS2][:good][:sill ][:mat]["139"] = 0.500
764
- @@data[MASS2][:good][:corner ][:mat][ "0"] = 1.000
765
- @@data[MASS2][:good][:balcony ][:mat][ ""] = 1.000
766
- @@data[MASS2][:good][:party ][:mat][ ""] = 1.000
767
- @@data[MASS2][:good][:grade ][:mat]["189"] = 1.000
768
- @@data[MASS2][:good][:grade ][:mat]["139"] = 0.500
769
- @@data[MASS2][:good][:grade ][:mat]["192"] = 0.500
770
- @@data[MASS2][:good][:joint ][:mat][ ""] = 1.000
771
- @@data[MASS2][:good][:transition ][:mat][ ""] = 1.000
772
-
773
- @@data[MASSB][ :bad][:id ] = MASSB_BAD
774
- @@data[MASSB][ :bad][:rimjoist ][:mat][ "21"] = 1.000
775
- @@data[MASSB][ :bad][:rimjoist ][:mat]["172"] = 0.250
776
- @@data[MASSB][ :bad][:parapet ][:mat][ "0"] = 1.000
777
- @@data[MASSB][ :bad][:head ][:mat]["139"] = 0.750
778
- @@data[MASSB][ :bad][:jamb ][:mat]["139"] = 0.750
779
- @@data[MASSB][ :bad][:sill ][:mat]["139"] = 0.750
780
- @@data[MASSB][ :bad][:corner ][:mat][ "0"] = 1.000
781
- @@data[MASSB][ :bad][:balcony ][:mat][ ""] = 1.000
782
- @@data[MASSB][ :bad][:party ][:mat][ ""] = 1.000
783
- @@data[MASSB][ :bad][:grade ][:mat][ "21"] = 1.000
784
- @@data[MASSB][ :bad][:grade ][:mat]["139"] = 0.500
785
- @@data[MASSB][ :bad][:joint ][:mat][ ""] = 1.000
786
- @@data[MASSB][ :bad][:transition ][:mat][ ""] = 1.000
787
-
788
- @@data[MASSB][:good][:id ] = MASSB_GOOD
789
- @@data[MASSB][:good][:rimjoist ][:mat]["189"] = 1.000
790
- @@data[MASSB][:good][:rimjoist ][:mat]["172"] = 0.500
791
- @@data[MASSB][:good][:parapet ][:mat][ "57"] = 3.300
792
- @@data[MASSB][:good][:parapet ][:mat]["139"] = 1.000
793
- @@data[MASSB][:good][:head ][:mat]["139"] = 0.500
794
- @@data[MASSB][:good][:jamb ][:mat]["139"] = 0.500
795
- @@data[MASSB][:good][:sill ][:mat]["139"] = 0.500
796
- @@data[MASSB][:good][:corner ][:mat][ "0"] = 1.000
797
- @@data[MASSB][:good][:balcony ][:mat][ ""] = 1.000
798
- @@data[MASSB][:good][:party ][:mat][ ""] = 1.000
799
- @@data[MASSB][:good][:grade ][:mat]["189"] = 1.000
800
- @@data[MASSB][:good][:grade ][:mat]["139"] = 0.500
801
- @@data[MASSB][:good][:grade ][:mat]["192"] = 0.500
802
- @@data[MASSB][:good][:joint ][:mat][ ""] = 1.000
803
- @@data[MASSB][:good][:transition ][:mat][ ""] = 1.000
804
-
805
- @@data[MASS4][ :bad][:id ] = MASS4_BAD
806
- @@data[MASS4][ :bad][:rimjoist ][:mat][ "0"] = 1.000
807
- @@data[MASS4][ :bad][:parapet ][:mat][ "0"] = 1.000
808
- @@data[MASS4][ :bad][:head ][:mat]["139"] = 0.250
809
- @@data[MASS4][ :bad][:jamb ][:mat]["139"] = 0.250
810
- @@data[MASS4][ :bad][:sill ][:mat]["139"] = 0.250
811
- @@data[MASS4][ :bad][:corner ][:mat]["141"] = 1.000
812
- @@data[MASS4][ :bad][:balcony ][:mat][ ""] = 1.000
813
- @@data[MASS4][ :bad][:party ][:mat][ ""] = 1.000
814
- @@data[MASS4][ :bad][:grade ][:mat]["139"] = 0.500
815
- @@data[MASS4][ :bad][:joint ][:mat][ ""] = 1.000
816
- @@data[MASS4][ :bad][:transition ][:mat][ ""] = 1.000
817
-
818
- @@data[MASS4][:good][:id ] = MASS4_GOOD
819
- @@data[MASS4][:good][:rimjoist ][:mat][ "0"] = 1.000
820
- @@data[MASS4][:good][:parapet ][:mat][ "57"] = 3.300
821
- @@data[MASS4][:good][:parapet ][:mat]["139"] = 1.000
822
- @@data[MASS4][:good][:head ][:mat]["139"] = 0.250
823
- @@data[MASS4][:good][:head ][:mat]["150"] = 0.083
824
- @@data[MASS4][:good][:jamb ][:mat]["139"] = 0.250
825
- @@data[MASS4][:good][:jamb ][:mat]["150"] = 0.083
826
- @@data[MASS4][:good][:sill ][:mat]["139"] = 0.250
827
- @@data[MASS4][:good][:sill ][:mat]["150"] = 0.083
828
- @@data[MASS4][:good][:corner ][:mat]["141"] = 1.250
829
- @@data[MASS4][:good][:balcony ][:mat][ "0"] = 1.000
830
- @@data[MASS4][:good][:party ][:mat][ ""] = 1.000
831
- @@data[MASS4][:good][:grade ][:mat]["192"] = 0.500
832
- @@data[MASS4][:good][:grade ][:mat]["139"] = 0.500
833
- @@data[MASS4][:good][:joint ][:mat][ ""] = 1.000
834
- @@data[MASS4][:good][:transition ][:mat][ ""] = 1.000
835
-
836
- @@data[MASS8][ :bad][:id ] = MASS8_BAD
837
- @@data[MASS8][ :bad][:rimjoist ][:mat][ "0"] = 1.000
838
- @@data[MASS8][ :bad][:parapet ][:mat][ "0"] = 1.000
839
- @@data[MASS8][ :bad][:head ][:mat]["139"] = 0.250
840
- @@data[MASS8][ :bad][:jamb ][:mat]["139"] = 0.250
841
- @@data[MASS8][ :bad][:sill ][:mat]["139"] = 0.250
842
- @@data[MASS8][ :bad][:corner ][:mat]["141"] = 1.000
843
- @@data[MASS8][ :bad][:balcony ][:mat][ ""] = 1.000
844
- @@data[MASS8][ :bad][:party ][:mat][ ""] = 1.000
845
- @@data[MASS8][ :bad][:grade ][:mat]["139"] = 0.500
846
- @@data[MASS8][ :bad][:joint ][:mat][ ""] = 1.000
847
- @@data[MASS8][ :bad][:transition ][:mat][ ""] = 1.000
848
-
849
- @@data[MASS8][:good][:id ] = MASS8_GOOD
850
- @@data[MASS8][:good][:rimjoist ][:mat][ "0"] = 1.000
851
- @@data[MASS8][:good][:parapet ][:mat][ "57"] = 3.300
852
- @@data[MASS8][:good][:parapet ][:mat]["139"] = 1.000
853
- @@data[MASS8][:good][:head ][:mat]["139"] = 0.250
854
- @@data[MASS8][:good][:head ][:mat]["150"] = 0.083
855
- @@data[MASS8][:good][:jamb ][:mat]["139"] = 0.250
856
- @@data[MASS8][:good][:jamb ][:mat]["150"] = 0.083
857
- @@data[MASS8][:good][:sill ][:mat]["139"] = 0.250
858
- @@data[MASS8][:good][:sill ][:mat]["150"] = 0.083
859
- @@data[MASS8][:good][:corner ][:mat]["141"] = 1.250
860
- @@data[MASS8][:good][:balcony ][:mat][ "0"] = 1.000
861
- @@data[MASS8][:good][:party ][:mat][ ""] = 1.000
862
- @@data[MASS8][:good][:grade ][:mat]["192"] = 0.500
863
- @@data[MASS8][:good][:grade ][:mat]["139"] = 0.500
864
- @@data[MASS8][:good][:joint ][:mat][ ""] = 1.000
865
- @@data[MASS8][:good][:transition ][:mat][ ""] = 1.000
866
-
867
- @@data[MASS6][ :bad][:id ] = MASS6_BAD
868
- @@data[MASS6][ :bad][:rimjoist ][:mat][ "21"] = 1.000
869
- @@data[MASS6][ :bad][:rimjoist ][:mat]["172"] = 0.250
870
- @@data[MASS6][ :bad][:parapet ][:mat][ "0"] = 1.000
871
- @@data[MASS6][ :bad][:head ][:mat]["139"] = 0.750
872
- @@data[MASS6][ :bad][:jamb ][:mat]["139"] = 0.750
873
- @@data[MASS6][ :bad][:sill ][:mat]["139"] = 0.750
874
- @@data[MASS6][ :bad][:corner ][:mat][ "0"] = 1.000
875
- @@data[MASS6][ :bad][:balcony ][:mat][ ""] = 1.000
876
- @@data[MASS6][ :bad][:party ][:mat][ ""] = 1.000
877
- @@data[MASS6][ :bad][:grade ][:mat][ "21"] = 1.000
878
- @@data[MASS6][ :bad][:grade ][:mat]["139"] = 0.500
879
- @@data[MASS6][ :bad][:joint ][:mat][ ""] = 1.000
880
- @@data[MASS6][ :bad][:transition ][:mat][ ""] = 1.000
881
-
882
- @@data[MASS6][:good][:id ] = MASS6_GOOD
883
- @@data[MASS6][:good][:rimjoist ][:mat]["189"] = 1.000
884
- @@data[MASS6][:good][:rimjoist ][:mat]["172"] = 0.500
885
- @@data[MASS6][:good][:parapet ][:mat][ "57"] = 3.300
886
- @@data[MASS6][:good][:parapet ][:mat]["139"] = 1.000
887
- @@data[MASS6][:good][:head ][:mat]["139"] = 0.500
888
- @@data[MASS6][:good][:jamb ][:mat]["139"] = 0.500
889
- @@data[MASS6][:good][:sill ][:mat]["139"] = 0.500
890
- @@data[MASS6][:good][:corner ][:mat][ "0"] = 1.000
891
- @@data[MASS6][:good][:balcony ][:mat][ ""] = 1.000
892
- @@data[MASS6][:good][:party ][:mat][ ""] = 1.000
893
- @@data[MASS6][:good][:grade ][:mat]["189"] = 1.000
894
- @@data[MASS6][:good][:grade ][:mat]["139"] = 0.500
895
- @@data[MASS6][:good][:grade ][:mat]["192"] = 0.500
896
- @@data[MASS6][:good][:joint ][:mat][ ""] = 1.000
897
- @@data[MASS6][:good][:transition ][:mat][ ""] = 1.000
898
-
899
- @@data[MASSC][ :bad][:id ] = MASSC_BAD
900
- @@data[MASSC][ :bad][:rimjoist ][:mat]["139"] = 10.000
901
- @@data[MASSC][ :bad][:parapet ][:mat][ "0"] = 1.000
902
- @@data[MASSC][ :bad][:head ][:mat]["139"] = 0.750
903
- @@data[MASSC][ :bad][:jamb ][:mat]["139"] = 0.750
904
- @@data[MASSC][ :bad][:sill ][:mat]["139"] = 0.750
905
- @@data[MASSC][ :bad][:corner ][:mat][ "0"] = 1.000
906
- @@data[MASSC][ :bad][:balcony ][:mat][ ""] = 1.000
907
- @@data[MASSC][ :bad][:party ][:mat][ ""] = 1.000
908
- @@data[MASSC][ :bad][:grade ][:mat]["139"] = 0.000
909
- @@data[MASSC][ :bad][:joint ][:mat][ ""] = 1.000
910
- @@data[MASSC][ :bad][:transition ][:mat][ ""] = 1.000
911
-
912
- @@data[MASSC][:good][:id ] = MASSC_GOOD
913
- @@data[MASSC][:good][:rimjoist ][:mat]["172"] = 0.500
914
- @@data[MASSC][:good][:parapet ][:mat][ "57"] = 3.300
915
- @@data[MASSC][:good][:parapet ][:mat]["139"] = 1.000
916
- @@data[MASSC][:good][:head ][:mat]["139"] = 0.500
917
- @@data[MASSC][:good][:jamb ][:mat]["139"] = 0.500
918
- @@data[MASSC][:good][:sill ][:mat]["139"] = 0.500
919
- @@data[MASSC][:good][:corner ][:mat][ "0"] = 1.000
920
- @@data[MASSC][:good][:balcony ][:mat][ ""] = 1.000
921
- @@data[MASSC][:good][:party ][:mat][ ""] = 1.000
922
- @@data[MASSC][:good][:grade ][:mat]["192"] = 1.000
923
- @@data[MASSC][:good][:grade ][:mat]["139"] = 1.000
924
- @@data[MASSC][:good][:joint ][:mat][ ""] = 1.000
925
- @@data[MASSC][:good][:transition ][:mat][ ""] = 1.000
926
-
927
- @@data[MTAL1][ :bad][:id ] = MTAL1_BAD
928
- @@data[MTAL1][ :bad][:rimjoist ][:mat][ "0"] = 1.000
929
- @@data[MTAL1][ :bad][:parapet ][:mat][ "0"] = 1.000
930
- @@data[MTAL1][ :bad][:head ][:mat]["139"] = 1.000
931
- @@data[MTAL1][ :bad][:jamb ][:mat]["139"] = 1.000
932
- @@data[MTAL1][ :bad][:sill ][:mat]["139"] = 1.000
933
- @@data[MTAL1][ :bad][:corner ][:mat]["191"] = 1.000
934
- @@data[MTAL1][ :bad][:balcony ][:mat][ ""] = 1.000
935
- @@data[MTAL1][ :bad][:party ][:mat][ ""] = 1.000
936
- @@data[MTAL1][ :bad][:grade ][:mat]["139"] = 0.500
937
- @@data[MTAL1][ :bad][:joint ][:mat][ ""] = 1.000
938
- @@data[MTAL1][ :bad][:transition ][:mat][ ""] = 1.000
939
-
940
- @@data[MTAL1][:good][:id ] = MTAL1_GOOD
941
- @@data[MTAL1][:good][:rimjoist ][:mat][ "0"] = 1.000
942
- @@data[MTAL1][:good][:parapet ][:mat][ "57"] = 3.300
943
- @@data[MTAL1][:good][:parapet ][:mat]["139"] = 1.000
944
- @@data[MTAL1][:good][:head ][:mat]["139"] = 0.500
945
- @@data[MTAL1][:good][:jamb ][:mat]["139"] = 0.500
946
- @@data[MTAL1][:good][:sill ][:mat]["139"] = 0.500
947
- @@data[MTAL1][:good][:corner ][:mat]["191"] = 1.000
948
- @@data[MTAL1][:good][:balcony ][:mat][ ""] = 1.000
949
- @@data[MTAL1][:good][:party ][:mat][ ""] = 1.000
950
- @@data[MTAL1][:good][:grade ][:mat]["192"] = 0.500
951
- @@data[MTAL1][:good][:grade ][:mat]["139"] = 0.500
952
- @@data[MTAL1][:good][:joint ][:mat][ ""] = 1.000
953
- @@data[MTAL1][:good][:transition ][:mat][ ""] = 1.000
954
-
955
- @@data[MTALD][ :bad][:id ] = MTALD_BAD
956
- @@data[MTALD][ :bad][:rimjoist ][:mat][ "0"] = 1.000
957
- @@data[MTALD][ :bad][:parapet ][:mat][ "0"] = 1.000
958
- @@data[MTALD][ :bad][:head ][:mat]["139"] = 1.000
959
- @@data[MTALD][ :bad][:jamb ][:mat]["139"] = 1.000
960
- @@data[MTALD][ :bad][:sill ][:mat]["139"] = 1.000
961
- @@data[MTALD][ :bad][:corner ][:mat]["191"] = 1.000
962
- @@data[MTALD][ :bad][:balcony ][:mat][ ""] = 1.000
963
- @@data[MTALD][ :bad][:party ][:mat][ ""] = 1.000
964
- @@data[MTALD][ :bad][:grade ][:mat]["139"] = 0.500
965
- @@data[MTALD][ :bad][:joint ][:mat][ ""] = 1.000
966
- @@data[MTALD][ :bad][:transition ][:mat][ ""] = 1.000
967
-
968
- @@data[MTALD][:good][:id ] = MTALD_GOOD
969
- @@data[MTALD][:good][:rimjoist ][:mat][ "0"] = 1.000
970
- @@data[MTALD][:good][:parapet ][:mat][ "57"] = 3.300
971
- @@data[MTALD][:good][:parapet ][:mat]["139"] = 1.000
972
- @@data[MTALD][:good][:head ][:mat]["139"] = 0.500
973
- @@data[MTALD][:good][:jamb ][:mat]["139"] = 0.500
974
- @@data[MTALD][:good][:sill ][:mat]["139"] = 0.500
975
- @@data[MTALD][:good][:corner ][:mat]["191"] = 1.000
976
- @@data[MTALD][:good][:balcony ][:mat][ ""] = 1.000
977
- @@data[MTALD][:good][:party ][:mat][ ""] = 1.000
978
- @@data[MTALD][:good][:grade ][:mat]["192"] = 0.500
979
- @@data[MTALD][:good][:grade ][:mat]["139"] = 0.500
980
- @@data[MTALD][:good][:joint ][:mat][ ""] = 1.000
981
- @@data[MTALD][:good][:transition ][:mat][ ""] = 1.000
982
-
983
- @@data[WOOD5][ :bad][:id ] = WOOD5_BAD
984
- @@data[WOOD5][ :bad][:rimjoist ][:mat][ "21"] = 1.000
985
- @@data[WOOD5][ :bad][:rimjoist ][:mat]["172"] = 0.250
986
- @@data[WOOD5][ :bad][:parapet ][:mat][ "0"] = 1.000
987
- @@data[WOOD5][ :bad][:head ][:mat][ "0"] = 1.000
988
- @@data[WOOD5][ :bad][:jamb ][:mat][ "0"] = 1.000
989
- @@data[WOOD5][ :bad][:sill ][:mat][ "0"] = 1.000
990
- @@data[WOOD5][ :bad][:corner ][:mat][ "0"] = 1.000
991
- @@data[WOOD5][ :bad][:balcony ][:mat][ ""] = 1.000
992
- @@data[WOOD5][ :bad][:party ][:mat][ ""] = 1.000
993
- @@data[WOOD5][ :bad][:grade ][:mat][ "21"] = 1.000
994
- @@data[WOOD5][ :bad][:grade ][:mat]["139"] = 0.500
995
- @@data[WOOD5][ :bad][:joint ][:mat][ ""] = 1.000
996
- @@data[WOOD5][ :bad][:transition ][:mat][ ""] = 1.000
997
-
998
- @@data[WOOD5][:good][:id ] = WOOD5_GOOD
999
- @@data[WOOD5][:good][:rimjoist ][:mat]["189"] = 1.000
1000
- @@data[WOOD5][:good][:rimjoist ][:mat]["172"] = 0.500
1001
- @@data[WOOD5][:good][:parapet ][:mat]["190"] = 0.500
1002
- @@data[WOOD5][:good][:head ][:mat][ "0"] = 1.000
1003
- @@data[WOOD5][:good][:jamb ][:mat][ "0"] = 1.000
1004
- @@data[WOOD5][:good][:sill ][:mat][ "0"] = 1.000
1005
- @@data[WOOD5][:good][:corner ][:mat][ "0"] = 1.000
1006
- @@data[WOOD5][:good][:balcony ][:mat][ ""] = 1.000
1007
- @@data[WOOD5][:good][:party ][:mat][ ""] = 1.000
1008
- @@data[WOOD5][:good][:grade ][:mat]["189"] = 1.000
1009
- @@data[WOOD5][:good][:grade ][:mat]["139"] = 0.500
1010
- @@data[WOOD5][:good][:grade ][:mat]["192"] = 0.500
1011
- @@data[WOOD5][:good][:joint ][:mat][ ""] = 1.000
1012
- @@data[WOOD5][:good][:transition ][:mat][ ""] = 1.000
1013
-
1014
- @@data[WOOD7][ :bad][:id ] = WOOD7_BAD
1015
- @@data[WOOD7][ :bad][:rimjoist ][:mat][ "21"] = 1.000
1016
- @@data[WOOD7][ :bad][:rimjoist ][:mat]["172"] = 0.250
1017
- @@data[WOOD7][ :bad][:parapet ][:mat][ "0"] = 1.000
1018
- @@data[WOOD7][ :bad][:head ][:mat][ "0"] = 1.000
1019
- @@data[WOOD7][ :bad][:jamb ][:mat][ "0"] = 1.000
1020
- @@data[WOOD7][ :bad][:sill ][:mat][ "0"] = 1.000
1021
- @@data[WOOD7][ :bad][:corner ][:mat][ "0"] = 1.000
1022
- @@data[WOOD7][ :bad][:balcony ][:mat][ ""] = 1.000
1023
- @@data[WOOD7][ :bad][:party ][:mat][ ""] = 1.000
1024
- @@data[WOOD7][ :bad][:grade ][:mat][ "21"] = 1.000
1025
- @@data[WOOD7][ :bad][:grade ][:mat]["139"] = 0.500
1026
- @@data[WOOD7][ :bad][:joint ][:mat][ ""] = 1.000
1027
- @@data[WOOD7][ :bad][:transition ][:mat][ ""] = 1.000
1028
-
1029
- @@data[WOOD7][:good][:id ] = WOOD7_GOOD
1030
- @@data[WOOD7][:good][:rimjoist ][:mat]["189"] = 1.000
1031
- @@data[WOOD7][:good][:rimjoist ][:mat]["172"] = 0.500
1032
- @@data[WOOD7][:good][:parapet ][:mat]["190"] = 0.500
1033
- @@data[WOOD7][:good][:head ][:mat][ "0"] = 1.000
1034
- @@data[WOOD7][:good][:jamb ][:mat][ "0"] = 1.000
1035
- @@data[WOOD7][:good][:sill ][:mat][ "0"] = 1.000
1036
- @@data[WOOD7][:good][:corner ][:mat][ "0"] = 1.000
1037
- @@data[WOOD7][:good][:balcony ][:mat][ ""] = 1.000
1038
- @@data[WOOD7][:good][:party ][:mat][ ""] = 1.000
1039
- @@data[WOOD7][:good][:grade ][:mat]["189"] = 1.000
1040
- @@data[WOOD7][:good][:grade ][:mat]["139"] = 0.500
1041
- @@data[WOOD7][:good][:grade ][:mat]["192"] = 0.500
1042
- @@data[WOOD7][:good][:joint ][:mat][ ""] = 1.000
1043
- @@data[WOOD7][:good][:transition ][:mat][ ""] = 1.000
1044
-
1045
- @@data[STEL1][ :bad][:id ] = STEL1_BAD
1046
- @@data[STEL1][ :bad][:rimjoist ][:mat]["139"] = 10.000
1047
- @@data[STEL1][ :bad][:parapet ][:mat][ "0"] = 1.000
1048
- @@data[STEL1][ :bad][:head ][:mat]["139"] = 0.750
1049
- @@data[STEL1][ :bad][:jamb ][:mat]["139"] = 0.750
1050
- @@data[STEL1][ :bad][:sill ][:mat]["139"] = 0.750
1051
- @@data[STEL1][ :bad][:corner ][:mat][ "0"] = 1.000
1052
- @@data[STEL1][ :bad][:balcony ][:mat][ ""] = 1.000
1053
- @@data[STEL1][ :bad][:party ][:mat][ ""] = 1.000
1054
- @@data[STEL1][ :bad][:grade ][:mat]["139"] = 1.000
1055
- @@data[STEL1][ :bad][:joint ][:mat][ ""] = 1.000
1056
- @@data[STEL1][ :bad][:transition ][:mat][ ""] = 1.000
1057
-
1058
- @@data[STEL1][:good][:id ] = STEL1_GOOD
1059
- @@data[STEL1][:good][:rimjoist ][:mat]["172"] = 0.500
1060
- @@data[STEL1][:good][:parapet ][:mat][ "57"] = 3.300
1061
- @@data[STEL1][:good][:parapet ][:mat]["139"] = 1.000
1062
- @@data[STEL1][:good][:head ][:mat]["139"] = 0.500
1063
- @@data[STEL1][:good][:jamb ][:mat]["139"] = 0.500
1064
- @@data[STEL1][:good][:sill ][:mat]["139"] = 0.500
1065
- @@data[STEL1][:good][:corner ][:mat][ "0"] = 1.000
1066
- @@data[STEL1][:good][:balcony ][:mat][ ""] = 1.000
1067
- @@data[STEL1][:good][:party ][:mat][ ""] = 1.000
1068
- @@data[STEL1][:good][:grade ][:mat]["192"] = 1.000
1069
- @@data[STEL1][:good][:grade ][:mat]["139"] = 1.000
1070
- @@data[STEL1][:good][:joint ][:mat][ ""] = 1.000
1071
- @@data[STEL1][:good][:transition ][:mat][ ""] = 1.000
1072
-
1073
- @@data[STEL2][ :bad][:id ] = STEL2_BAD
1074
- @@data[STEL2][ :bad][:rimjoist ][:mat]["139"] = 10.000
1075
- @@data[STEL2][ :bad][:parapet ][:mat][ "0"] = 1.000
1076
- @@data[STEL2][ :bad][:head ][:mat]["139"] = 0.750
1077
- @@data[STEL2][ :bad][:jamb ][:mat]["139"] = 0.750
1078
- @@data[STEL2][ :bad][:sill ][:mat]["139"] = 0.750
1079
- @@data[STEL2][ :bad][:corner ][:mat][ "0"] = 1.000
1080
- @@data[STEL2][ :bad][:balcony ][:mat][ ""] = 1.000
1081
- @@data[STEL2][ :bad][:party ][:mat][ ""] = 1.000
1082
- @@data[STEL2][ :bad][:grade ][:mat]["139"] = 1.000
1083
- @@data[STEL2][ :bad][:joint ][:mat][ ""] = 1.000
1084
- @@data[STEL2][ :bad][:transition ][:mat][ ""] = 1.000
1085
-
1086
- @@data[STEL2][:good][:id ] = STEL2_GOOD
1087
- @@data[STEL2][:good][:rimjoist ][:mat]["172"] = 0.500
1088
- @@data[STEL2][:good][:parapet ][:mat]["206"] = 1.000
1089
- @@data[STEL2][:good][:head ][:mat]["139"] = 0.500
1090
- @@data[STEL2][:good][:jamb ][:mat]["139"] = 0.500
1091
- @@data[STEL2][:good][:sill ][:mat]["139"] = 0.500
1092
- @@data[STEL2][:good][:corner ][:mat][ "0"] = 1.000
1093
- @@data[STEL2][:good][:balcony ][:mat][ ""] = 1.000
1094
- @@data[STEL2][:good][:party ][:mat][ ""] = 1.000
1095
- @@data[STEL2][:good][:grade ][:mat]["192"] = 1.000
1096
- @@data[STEL2][:good][:grade ][:mat]["139"] = 1.000
1097
- @@data[STEL2][:good][:joint ][:mat][ ""] = 1.000
1098
- @@data[STEL2][:good][:transition ][:mat][ ""] = 1.000
1099
- # --- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --- #
1100
-
1101
- ##
1102
- # Retrieve TBD building/space type keyword.
1103
- #
1104
- # @param spacetype [String] NECB (or other) building/space type
1105
- # @param stories [Integer] number of building stories
1106
- #
1107
- # @return [Symbol] matching TBD keyword (:office if failure)
1108
- def spacetype(sptype = "", stories = 999)
1109
- tp = sptype.downcase
1110
- typ = :office
1111
-
1112
- return typ unless stories.is_a?(Integer) && stories.between?(1,999)
1113
-
1114
- typ = :exercise if tp.include?("exercise" )
1115
- typ = :firestation if tp.include?("fire" )
1116
- typ = :gym if tp.include?("gym" )
1117
- typ = :gym if tp.include?("locker" )
1118
- typ = :courthouse if tp.include?("courthouse" )
1119
- typ = :courtrhouse if tp.include?("courtroom" )
1120
- typ = :museum if tp.include?("museum" )
1121
- typ = :parking if tp.include?("parking" )
1122
- typ = :post if tp.include?("post" )
1123
- typ = :transportation if tp.include?("transp" )
1124
- typ = :transportation if tp.include?("maintenance" )
1125
- typ = :automotive if tp.include?("automotive" )
1126
- typ = :penitentiary if tp.include?("penitentiary" )
1127
- typ = :penitentiary if tp.include?("confinement" )
1128
- typ = :arena if tp.include?("arena" )
1129
- typ = :warehouse if tp.include?("warehouse" )
1130
- typ = :storage if tp.include?("storage" )
1131
- typ = :mfg if tp.include?("mfg" )
1132
- typ = :mfg if tp.include?("manufacturing")
1133
- typ = :mfg if tp.include?("loading" )
1134
- typ = :workshop if tp.include?("workshop" )
1135
- typ = :religious if tp.include?("religious" )
1136
- typ = :dwelling5 if tp.include?("dorm" )
1137
- typ = :dwelling5 if tp.include?("otel" )
1138
- typ = :dwelling5 if tp.include?("residential" )
1139
- typ = :dwelling5 if tp.include?("long-term" )
1140
- typ = :dwelling5 if tp.include?("dwelling" )
1141
- typ = :dwelling5 if tp.include?("lodging" )
1142
- typ = :dwelling5 if tp.include?("RP-28" )
1143
- typ = :dwelling5 if tp.include?("guest" )
1144
- typ = :dwelling if tp.include?("dorm" ) && stories < 5
1145
- typ = :dwelling if tp.include?("otel" ) && stories < 5
1146
- typ = :dwelling if tp.include?("residential" ) && stories < 5
1147
- typ = :dwelling if tp.include?("long-term" ) && stories < 5
1148
- typ = :dwelling if tp.include?("dwelling" ) && stories < 5
1149
- typ = :dwelling if tp.include?("lodging" ) && stories < 5
1150
- typ = :dwelling if tp.include?("RP-28" ) && stories < 5
1151
- typ = :dwelling if tp.include?("guest" ) && stories < 5
1152
- typ = :library3 if tp.include?("library" )
1153
- typ = :library if tp.include?("library" ) && stories < 3
1154
- typ = :school3 if tp.include?("school" )
1155
- typ = :school3 if tp.include?("classroom" )
1156
- typ = :school3 if tp.include?("lab" )
1157
- typ = :school3 if tp.include?("auditorium" )
1158
- typ = :school if tp.include?("school" ) && stories < 3
1159
- typ = :school if tp.include?("classroom" ) && stories < 3
1160
- typ = :school if tp.include?("lab" ) && stories < 3
1161
- typ = :school if tp.include?("auditorium" ) && stories < 3
1162
- typ = :convention if tp.include?("convention" )
1163
- typ = :dining if tp.include?("dining" )
1164
- typ = :dining if tp.include?("food" )
1165
- typ = :health if tp.include?("health" )
1166
- typ = :hospital if tp.include?("hospital" )
1167
- typ = :hospital if tp.include?("emergency" )
1168
- typ = :hospital if tp.include?("laundry" )
1169
- typ = :hospital if tp.include?("pharmacy" )
1170
- typ = :motion if tp.include?("motion" )
1171
- typ = :performance if tp.include?("perform" )
1172
- typ = :police if tp.include?("police" )
1173
- typ = :retail if tp.include?("retail" )
1174
- typ = :retail if tp.include?("sales" )
1175
- typ = :town if tp.include?("town" )
1176
-
1177
- typ
1178
- end
1179
406
 
1180
407
  ##
1181
- # Retrieve building/space type-specific assembly/construction.
408
+ # Retrieves BTAP-costed assembly.
1182
409
  #
1183
- # @param sptype [Symbol] BTAP/TBD spacetype
1184
- # @param stypes [Symbol] :walls, :floors or :roofs
1185
- # @param perform [Symbol] :lp (low-) or :hp (high-performance)
410
+ # @param structure [BTAP::Structure] BTAP Structure object
411
+ # @param stype [:walls, :floors or :roofs] surface type
412
+ # @param perform [:hp or :lp] high- or low-performance variant
1186
413
  #
1187
- # @return [String] corresponding BTAP construction (STEL2 if fail)
1188
- def assembly(sptype = :office, stypes = :walls, perform = :hp)
1189
- return FLOOR if stypes == :floors
1190
- return ROOFS if stypes == :roofs
1191
-
1192
- @@data.each do |id, construction|
1193
- next unless construction.key?(perform)
1194
- return id if construction[:sptypes].key?(sptype)
414
+ # @return [String] BTAP assembly identifier for costing
415
+ def costed_assembly(structure = nil, stype = :walls, perform = :lp)
416
+ stype = :walls unless [:roofs, :floors].include?(stype)
417
+ perform = :lp unless perform == :hp
418
+ return STEL1 unless structure.is_a?(BTAP::Structure)
419
+
420
+ # Select BTAP-costed assembly, matching:
421
+ # - BTAP::Structure generated construction parameters
422
+ # - requested high (HP) vs low-performance (LP) PSI-factor level
423
+ #
424
+ # Ideally, chosen PSI factor sets and matching OpenStudio constructions
425
+ # shouldn't strictly be based on selected BTAP assemblies (e.g.
426
+ # wood-framed vs steel-framed, cladding choice), but also on selected
427
+ # building 'structure', e.g.:
428
+ #
429
+ # - "wood-framed" MURB
430
+ # - "steel post/beam" office building
431
+ # - "reinforced concrete post/beam" public library
432
+ # - "metal(-building)" warehouse
433
+ # - "mass-timber (CLT)" university pavilion
434
+ #
435
+ # Major thermal bridges often consist of anchors or supports that transmit
436
+ # structural loads (and by the same token, 'heat') to a building's main
437
+ # structure. Examples include balconies, parapets and shelf angles.
438
+ # Highly conductive building structures (e.g. steel, aluminium) exacerbate
439
+ # thermal bridging effects - so building structural selection matters.
440
+ #
441
+ # The BTAP::Structure module generates such attributes, yet BTAP's costed
442
+ # thermal bridging database doesn't yet distinguish between building
443
+ # structures - @todo. For the moment, BTAP PSI set selection is strictly
444
+ # based on BTAP::Structure's :framing, :cladding and :finish attributes,
445
+ # which must be set prior to initiating BTAP's TBD's thermal bridging
446
+ # solution:
447
+
448
+ # Light gauge steel framing by default. Override if wood, cmu or precast.
449
+ case stype
450
+ when :roofs then return ROOF
451
+ when :floors then return FLOOR
452
+ else
453
+ case structure.framing
454
+ when :wood
455
+ c1 = WOOD5
456
+ c2 = WOOD7
457
+ when :cmu
458
+ c1 = MASS2
459
+ c2 = MASSB
460
+ else
461
+ if structure.cladding == :heavy && structure.finish == :heavy
462
+ c1 = MASS4
463
+ c2 = MASS8
464
+ else
465
+ c1 = STEL1
466
+ c2 = STEL2
467
+ end
468
+ end
1195
469
  end
1196
470
 
1197
- STEL2
471
+ perform == :lp ? c1 : c2
1198
472
  end
1199
473
 
1200
474
  ##
1201
- # Retrieve nearest building/space type-specific assembly Uo factor.
475
+ # Retrieves nearest assembly Uo factor.
1202
476
  #
1203
- # @param construction [String] BTAP construction identifier
477
+ # @param assembly [String] BTAP assembly identifier
1204
478
  # @param uo [Double] target Uo in W/m2.K
1205
479
  #
1206
- # @return [Double] costed BTAP construction Uo factor (nil if fail)
1207
- def costed_uo(construction = STEL2, uo = UMAX)
1208
- construction = STEL2 unless @@data.key?(construction)
1209
- uo = UMAX unless uo.is_a?(Numeric) && uo.between?(UMIN, UMAX)
1210
-
1211
- @@data[construction][:uos].keys.each do |u|
1212
- val = u.to_f / 1000
1213
- return nil unless val.is_a?(Numeric) && val.between?(UMIN, UMAX)
1214
- return val if val < uo || (val - uo).abs < 0.001
1215
- end
480
+ # @return [Double] costed BTAP assembly Uo factor (nil if fail)
481
+ def costed_uo(assembly = "", uo = nil)
482
+ return nil unless @@data.key?(assembly)
483
+ return nil unless uo.is_a?(Numeric)
484
+
485
+ uo = uo.clamp(TBD::UMIN, TBD::UMAX)
486
+
487
+ @@data[assembly][:uos].each { |u| return u if u.round(3) <= uo.round(3) }
1216
488
 
1217
489
  nil
1218
490
  end
1219
491
 
1220
492
  ##
1221
- # Retrieve lowest building/space type-specific assembly Uo factor.
493
+ # Retrieves lowest costed assembly Uo factor.
1222
494
  #
1223
- # @param construction [String] BTAP construction identifier
495
+ # @param assembly [String] BTAP assembly identifier
1224
496
  #
1225
- # @return [Double] lowest costed BTAP construction Uo factor (nil if fail)
1226
- def lowest_uo(construction = STEL2)
1227
- uos = []
1228
- construction = STEL2 unless @@data.key?(construction)
497
+ # @return [Double] lowest costed BTAP assembly Uo factor (nil if fail)
498
+ def lowest_uo(assembly = "")
499
+ return nil unless @@data.key?(assembly)
1229
500
 
1230
- @@data[construction][:uos].keys.each do |u|
1231
- val = u.to_f / 1000
1232
- return nil unless val.is_a?(Numeric) && val.between?(UMIN, UMAX)
1233
-
1234
- uos << val
1235
- end
1236
-
1237
- return uos.min unless uos.empty?
1238
-
1239
- nil
501
+ @@data[assembly][:uos].min
1240
502
  end
1241
503
 
1242
504
  ##
1243
- # Retrieve assembly-specific PSI factor set.
505
+ # Retrieves assembly-specific PSI factor set.
1244
506
  #
1245
- # @param assembly [String] BTAP/TBD wall construction
507
+ # @param assembly [String] BTAP/TBD wall construction identifier
1246
508
  # @param quality [Symbol] BTAP/TBD PSI quality (:bad or :good)
1247
509
  #
1248
510
  # @return [Hash] BTAP/TBD PSI factor set (defaults to STEL2, :good)
1249
511
  def set(assembly = STEL2, quality = :good)
1250
- psi = {}
1251
- chx = @@data[STEL2][:good ]
1252
- chx = @@data[STEL2][quality] if @@data[STEL2 ].key?(quality)
512
+ assembly = STEL2 unless @@data.key?(assembly)
513
+ quality = :good unless @@data[assembly].key?(quality)
1253
514
 
1254
- if @@data.key?(assembly)
1255
- chx = @@data[assembly][quality] if @@data[assembly].key?(quality)
1256
- chx = @@data[assembly][:good ] unless @@data[assembly].key?(quality)
1257
- end
515
+ chx = @@data[assembly][quality]
516
+ psi = {}
1258
517
 
1259
- psi[:id ] = chx[:id ]
1260
- psi[:rimjoist ] = chx[:rimjoist ][:psi]
1261
- psi[:parapet ] = chx[:parapet ][:psi]
1262
- psi[:head ] = chx[:head ][:psi]
1263
- psi[:jamb ] = chx[:jamb ][:psi]
1264
- psi[:sill ] = chx[:sill ][:psi]
1265
- psi[:corner ] = chx[:corner ][:psi]
1266
- psi[:balcony ] = chx[:balcony ][:psi]
1267
- psi[:party ] = chx[:party ][:psi]
1268
- psi[:grade ] = chx[:grade ][:psi]
1269
- psi[:joint ] = chx[:joint ][:psi]
1270
- psi[:transition] = chx[:transition][:psi]
518
+ psi[:id ] = chx[:id ]
519
+ psi[:rimjoist ] = chx[:rimjoist ][:psi]
520
+ psi[:parapet ] = chx[:parapet ][:psi]
521
+ psi[:fenestration] = chx[:fenestration][:psi]
522
+ psi[:door ] = chx[:door ][:psi]
523
+ psi[:corner ] = chx[:corner ][:psi]
524
+ psi[:balcony ] = chx[:balcony ][:psi]
525
+ psi[:party ] = chx[:party ][:psi]
526
+ psi[:grade ] = chx[:grade ][:psi]
527
+ psi[:joint ] = chx[:joint ][:psi]
1271
528
 
1272
529
  psi
1273
530
  end
@@ -1297,7 +554,7 @@ module BTAP
1297
554
  ERR = TBD::ERR
1298
555
  FTL = TBD::FTL
1299
556
 
1300
- # @return [Hash] BTAP/TBD Hash, specific to an OpenStudio model
557
+ # @return [Hash] BTAP/TBD hash, specific to an OpenStudio model
1301
558
  attr_reader :model
1302
559
 
1303
560
  # @return [Hash] logged messages TBD reports back to BTAP
@@ -1307,55 +564,40 @@ module BTAP
1307
564
  attr_reader :tally
1308
565
 
1309
566
  ##
1310
- # Initialize OpenStudio model-specific BTAP/TBD data - uprates/derates.
567
+ # Initializes OpenStudio model-specific BTAP/TBD data - uprates/derates.
1311
568
  #
1312
569
  # @param model [OpenStudio::Model::Model] a model
1313
- # @param argh [Hash] BTAP/TBD argument hash
570
+ # @param [Hash] argh BTAP/TBD argument hash
571
+ # @option argh [BTAP::Structure] structure a BTAP STRUCTURE object
572
+ # @option argh [Hash] walls exterior wall parameters e.g. :uo, :ut
573
+ # @option argh [Hash] floors exposed floor parameters e.g. :uo, :ut
574
+ # @option argh [Hash] roofs exterior roof parameters e.g. :uo, :ut
575
+ # @option argh [:good, :bad] quality derating option (if not uprating)
576
+ # @option argh [Boolean] interpolate if TBD interpolates among Uo (uprate)
1314
577
  def initialize(model = nil, argh = {})
578
+ btp = BTAP::Resources::Envelope::Constructions # alias
579
+ mth = "BTAP::Bridging::#{__callee__}"
1315
580
  @model = {}
1316
581
  @tally = {}
1317
- @feedback = { logs: [] }
582
+ @feedback = {logs: []}
1318
583
  lgs = @feedback[:logs]
1319
584
 
1320
- argh[:interpolate] = false unless argh.key?(:interpolate)
1321
-
1322
- # BTAP generates free-floating, unoccupied spaces (e.g. attics) as
1323
- # 'indirectly conditioned', rather than 'unconditioned' (e.g. vented
1324
- # attics). For instance, all outdoor-facing sloped roof surfaces of an
1325
- # attic in BTAP are insulated, while attic floors remain uninsulated. BTAP
1326
- # adds to the thermal zone of each unoccupied space a thermostat without
1327
- # referencing heating and/or cooling setpoint schedule objects. These
1328
- # conditions do not meet TBD's internal 'plenum' logic/check (which is
1329
- # based on OpenStudio-Standards), and so TBD ends up tagging such spaces
1330
- # as unconditioned. Consequently, TBD attempts to up/de-rate attic floors
1331
- # - not sloped roof surfaces. The upstream BTAP solution will undoubtedly
1332
- # need revision. In the meantime, and in an effort to harmonize TBD with
1333
- # BTAP's current approach, an OpenStudio model may be temporarily
1334
- # modified prior to TBD processes, ensuring that each attic space is
1335
- # temporarily mistaken as a conditioned plenum. The return variable of the
1336
- # following method is a Hash holding temporarily-modified spaces,
1337
- # i.e. buffer zones.
1338
- buffers = self.alter_buffers(model)
1339
-
1340
- # Populate BTAP/TBD inputs with BTAP & OpenStudio model parameters,
1341
- # which returns 'true' if successful. Check @feedback logs if failure to
1342
- # populate (e.g. invalid argument hash, invalid OpenStudio model).
585
+ # Populate and validate BTAP/TBD & OpenStudio model parameters. This does
586
+ # a safe TBD trial run, returning true if successful. If false, TBD leaves
587
+ # the model unaltered. Check @feedback logs.
1343
588
  return unless self.populate(model, argh)
1344
589
 
1345
590
  # Initialize loop controls and flags.
1346
591
  initial = true
1347
592
  complies = false
1348
- comply = {} # specific to :walls, :floors & :roofs
1349
- perform = :lp # Low-performance wall constructions (revise, TO-DO ...)
1350
- quality = :bad # default PSI factors - BTAP users can reset to :good
1351
- quality = :good if argh.key?(:quality) && argh[:quality] == :good
593
+ comply = {} # specific to :walls, :floors & :roofs (if uprating)
594
+ perform = :lp
595
+ quality = argh[:quality] == :good ? :good : :bad
1352
596
  combo = "#{perform.to_s}_#{quality.to_s}".to_sym # e.g. :lp_bad
1353
- args = {} # initialize native TBD arguments
597
+ args = {} # TBD's own argument hash
1354
598
 
1355
- # Initialize surface types & native TBD args (if uprating).
1356
- [:walls, :floors, :roofs].each do |stypes|
1357
- next if @model[stypes].empty?
1358
- next unless argh.key?(stypes)
599
+ # Initialize surface types & TBD arguments for iterative uprating runs.
600
+ @model[:stypes].each do |stypes|
1359
601
  next unless argh[stypes].key?(:ut)
1360
602
 
1361
603
  stype = stypes.to_s.chop
@@ -1363,52 +605,62 @@ module BTAP
1363
605
  option = "#{stype}_option".to_sym
1364
606
  ut = "#{stype}_ut".to_sym
1365
607
 
1366
- args[uprate ] = true
1367
- args[option ] = "ALL #{stype} constructions"
1368
- args[ut ] = argh[stypes][:ut]
608
+ args[uprate] = true
609
+ args[option] = "ALL #{stype} constructions"
610
+ args[ut ] = argh[stypes][:ut]
1369
611
 
1370
612
  comply[stypes] = false
613
+ end
1371
614
 
1372
- @model[:constructions] = {} unless @model.key?(:constructions)
615
+ # Building-wide PSI set.
616
+ @model[:constructions].values.each do |v|
617
+ args[:io_path] = v[combo] if v.key?(combo)
1373
618
  end
1374
619
 
1375
- args[:io_path] = @model[combo] # contents of a "tbd.json" file
1376
- args[:option ] = "" # safeguard
620
+ return false if args[:io_path].nil?
621
+
622
+ args[:option ] = ""
1377
623
 
1378
624
  loop do
1379
625
  if initial
1380
626
  initial = false
1381
627
  else
1382
- # Subsequent runs. Upgrade technologies. Reset TBD args.
628
+ # Subsequent uprating runs. Upgrade technologies. Reset TBD args.
1383
629
  if quality == :bad
1384
630
  quality = :good
1385
631
  combo = "#{perform.to_s}_#{quality.to_s}".to_sym
1386
- args[:io_path] = @model[combo]
632
+
633
+ @model[:constructions].values.each do |v|
634
+ args[:io_path] = v[combo] if v.key?(combo)
635
+ end
1387
636
  elsif perform == :lp
1388
637
  # Switch 'perform' from :lp to :hp - reset quality to :bad.
1389
638
  perform = :hp
1390
639
  quality = :bad
1391
640
  combo = "#{perform.to_s}_#{quality.to_s}".to_sym
1392
- args[:io_path] = @model[combo]
641
+
642
+ @model[:constructions].values.each do |v|
643
+ args[:io_path] = v[combo] if v.key?(combo)
644
+ end
1393
645
  end
1394
646
 
1395
647
  # Delete previously-generated TBD args Uo key/value pairs.
1396
- [:walls, :floors, :roofs].each do |stypes|
648
+ @model[:stypes].each do |stypes|
1397
649
  next unless comply.key?(stypes)
1398
650
 
1399
651
  uo = "#{stypes.to_s.chop}_uo".to_sym
1400
652
  args.delete(uo) if args.key?(uo)
1401
653
  end
1402
-
1403
- # Reset previous @model constructions.
1404
- @model.delete(:constructions) if @model.key?(:constructions)
1405
- @model[:constructions] = {}
1406
654
  end
1407
655
 
1408
656
  # Run TBD on cloned OpenStudio model - compliant combo?
1409
657
  mdl = OpenStudio::Model::Model.new
1410
658
  mdl.addObjects(model.toIdfFile.objects)
1411
659
  TBD.clean!
660
+
661
+ # fil = File.join("/Users/rd2/Desktop/test.osm")
662
+ # mdl.save(fil, true)
663
+
1412
664
  res = TBD.process(mdl, args)
1413
665
 
1414
666
  # Halt all processes if fatal errors raised by TBD (e.g. badly formatted
@@ -1419,69 +671,51 @@ module BTAP
1419
671
  end
1420
672
 
1421
673
  complies = true
1422
- # Check if TBD-uprated Uo factors are valid: TBD args Hash holds (new)
1423
- # uprated Uo keys/values for :walls, :floors AND/OR :roofs if uprating
674
+ # Check if TBD-uprated Uo factors are valid: TBD args hash holds (new)
675
+ # uprated Uo keys/values for :walls, :floors and/or :roofs if uprating
1424
676
  # is successful. In most cases, uprating tends to fail for wall
1425
677
  # constructions rather than roof or floor constructions, due to the
1426
- # typically larger density of linear thermal bridging per surface type
1427
- # area. Yet even if all constructions were successfully uprated by TBD,
1428
- # one must then determine if BTAP holds admissible (i.e. costed)
1429
- # assembly variants with corresponding Uo factors (see :uos key). If
1430
- # TBD-uprated Uo factors are lower than any of these admissible BTAP Uo
1431
- # factors, then no commercially available solution can been identified.
1432
- [:walls, :floors, :roofs].each do |stypes|
678
+ # typically larger density of linear thermal bridging per surface area
679
+ # Yet even if all constructions were successfully uprated by TBD, one
680
+ # must then determine if BTAP holds admissible (i.e. costed) assembly
681
+ # variants with corresponding Uo factors. If TBD-uprated Uo factors are
682
+ # lower than any of these admissible BTAP Uo factors, then no
683
+ # commercially available solution can been identified.
684
+ @model[:stypes].each do |stypes|
1433
685
  next unless comply.key?(stypes) # true only if uprating
1434
686
 
687
+ # TBD-estimated Uo target to meet NECB-required Ut - nil if invalid.
1435
688
  stype_uo = "#{stypes.to_s.chop}_uo".to_sym
1436
- target = nil # uprated Uo (if successful)
1437
- target = args[stype_uo] if args.key?(stype_uo) # ... may be nil
1438
-
1439
- comply[stypes] = true
1440
-
1441
- @model[stypes].each do |id, surface|
1442
- next unless surface.key?(:sptype)
1443
-
1444
- sptype = surface[:sptype] # e.g. :office
1445
- next unless @model[:sptypes].key?(sptype)
1446
- next unless @model[:sptypes][sptype].key?(stypes)
1447
- next unless @model[:sptypes][sptype][stypes].key?(perform)
1448
-
1449
- construction = @model[:sptypes][sptype][stypes][perform]
1450
- uo = nil
1451
- ok = true
1452
- uo = self.costed_uo(construction, target) if target
1453
- ok = false if uo.nil?
1454
- uo = target if ok && argh[:interpolate]
1455
- uo = self.lowest_uo(construction) unless ok # fallback
1456
- comply[stypes] = false unless ok
1457
-
1458
- unless @model[:constructions].key?(construction)
1459
- @model[:constructions][construction] = {}
1460
- @model[:constructions][construction][:stypes ] = stypes
1461
- @model[:constructions][construction][:uo ] = uo
1462
- @model[:constructions][construction][:compliant] = ok
1463
- @model[:constructions][construction][:surfaces ] = {}
1464
- end
689
+ target = args.key?(stype_uo) ? args[stype_uo] : nil
690
+ assembly = self.costed_assembly(argh[:structure], stypes, perform)
691
+
692
+ uo = target ? self.costed_uo(assembly, target) : nil
1465
693
 
1466
- face = model.getSurfaceByName(id)
1467
- next if face.empty?
694
+ if uo
695
+ uo = target if argh[:interpolate]
696
+ comply[stypes] = true
697
+ else
698
+ uo = self.lowest_uo(assembly)
699
+ comply[stypes] = false
700
+ end
701
+
702
+ @model[:constructions].each do |lc, v|
703
+ next unless v[:stypes] == stypes
1468
704
 
1469
- face = face.get
1470
- @model[:constructions][construction][:surfaces][id] = face
705
+ v[:uo] = uo
706
+ v[:compliant] = comply[stypes]
1471
707
  end
1472
708
 
1473
709
  complies = false unless comply[stypes]
1474
710
  end
1475
711
 
1476
- break if complies
1477
- # Final BTAP uprating option, yet non-compliant: TBD's uprating
1478
- # features are requested, yet unable to locate either a physically- or
1479
- # economically-plausible Uo + PSI combo for 1x or more surface types.
712
+ # Exit if successful or if final BTAP uprating option.
1480
713
  break if combo == :hp_good
1481
- end # of loop
714
+ break if complies
715
+ end
1482
716
 
1483
717
  # Post-loop steps (if uprating).
1484
- [:walls, :floors, :roofs].each do |stypes|
718
+ @model[:stypes].each do |stypes|
1485
719
  next unless comply.key?(stypes) # true only if uprating
1486
720
 
1487
721
  # Cancel uprating request before final derating.
@@ -1491,18 +725,13 @@ module BTAP
1491
725
  ut = "#{stype}_ut".to_sym
1492
726
  args.delete(uprate)
1493
727
  args.delete(option)
1494
- args.delete(ut )
1495
-
1496
- # Set uprated Uo factor for each BTAP 'deratable' construction.
1497
- @model[:constructions].each do |id, construction|
1498
- next unless construction.key?(:stypes )
1499
- next unless construction.key?(:uo )
1500
- next unless construction.key?(:compliant)
1501
- next unless construction.key?(:surfaces )
1502
- next unless construction[:stypes ] == stypes
1503
- next if construction[:surfaces].empty?
1504
-
1505
- construction[:surfaces].values.each { |surface| surface.setConstruction(construction[:uo]) }
728
+ args.delete(ut)
729
+
730
+ # Reset uprated Uo factor for each 'deratable' construction.
731
+ @model[:constructions].each do |lc, v|
732
+ next unless v[:stypes] == stypes
733
+
734
+ v[:r] = TBD.resetUo(lc, v[:filmRSI], v[:index], v[:uo])
1506
735
  end
1507
736
  end
1508
737
 
@@ -1518,336 +747,284 @@ module BTAP
1518
747
 
1519
748
  @model[:io ] = res[:io ] # TBD outputs (i.e. "tbd.out.json")
1520
749
  @model[:surfaces] = res[:surfaces] # TBD derated surface data
1521
- @model[:argh ] = argh # method argument Hash
750
+ @model[:argh ] = argh # method argument hash
1522
751
  @model[:args ] = args # last TBD inputs (i.e. "tbd.json")
1523
752
 
1524
753
  self.gen_tallies # tallies for BTAP costing
1525
754
  self.gen_feedback # log success messages for BTAP
1526
-
1527
- self.purge_buffer_schedules(model, buffers)
1528
755
  end
1529
756
 
1530
757
  ##
1531
- # Modify BTAP-generated 'buffer zones' (e.g. attics) to ensure TBD tags
1532
- # these as indirectly conditioned spaces (e.g. plenums).
758
+ # Populates and validates BTAP/TBD & OpenStudio model parameters for thermal
759
+ # bridging. This also does a safe TBD trial run, returning true if
760
+ # successful. Check @feedback logs if false.
1533
761
  #
1534
762
  # @param model [OpenStudio::Model::Model] a model
763
+ # @param [Hash] argh BTAP/TBD argument hash
764
+ # @option argh [BTAP::Structure] structure a BTAP STRUCTURE object
765
+ # @option argh [Hash] walls exterior wall parameters e.g. :uo, :ut
766
+ # @option argh [Hash] floors exposed floor parameters e.g. :uo, :ut
767
+ # @option argh [Hash] roofs exterior roof parameters e.g. :uo, :ut
768
+ # @option argh [Symbol] quality derating option (if not uprating)
769
+ # @option argh [Boolean] interpolate if TBD should pick between Uo values
1535
770
  #
1536
- # @return [Array] identifiers of modified buffer spaces in model
1537
- def alter_buffers(model = nil)
1538
- buffers = []
1539
- sched = nil
1540
- lgs = @feedback[:logs]
1541
- cl = OpenStudio::Model::Model
1542
- lgs << "Invalid OpenStudio model (buffers)" unless model.is_a?(cl)
1543
- return buffers unless model.is_a?(cl)
1544
-
1545
- model.getSpaces.each do |space|
1546
- next if space.partofTotalFloorArea
1547
- next if space.thermalZone.empty?
1548
-
1549
- id = space.nameString
1550
- zone = space.thermalZone.get
1551
- next if zone.isPlenum
1552
- next if zone.thermostat.empty?
1553
-
1554
- tstat = zone.thermostat.get
1555
- staged = tstat.respond_to?(:heatingTemperatureSetpointSchedule)
1556
- tstat = tstat.to_ZoneControlThermostatStagedDualSetpoint.get if staged
1557
- tstat = tstat.to_ThermostatSetpointDualSetpoint.get unless staged
1558
-
1559
- if sched.nil?
1560
- name = "TBD attic setpoint sched"
1561
- sched = OpenStudio::Model::ScheduleCompact.new(model)
1562
- sched.setName(name)
1563
- end
771
+ # @return [Boolean] true if valid (check @feedback logs if false)
772
+ def populate(model = nil, argh = {})
773
+ mth = "BTAP::Bridging::#{__callee__}"
774
+ args = { option: "(non thermal bridging)" } # for initial TBD dry run
775
+ lgs = @feedback[:logs]
776
+ cl = OpenStudio::Model::LayeredConstruction
777
+
778
+ unless model.is_a?(OpenStudio::Model::Model)
779
+ lgs << "Invalid OpenStudio model to de/up-rate (#{mth})"
780
+ return false
781
+ end
1564
782
 
1565
- tstat.setHeatingTemperatureSetpointSchedule(sched) if staged
1566
- tstat.setHeatingSetpointTemperatureSchedule(sched) unless staged
783
+ unless argh.is_a?(Hash)
784
+ lgs << "Invalid BTAP/TBD argument Hash (#{mth})"
785
+ return false
786
+ end
1567
787
 
1568
- buffers << id
788
+ if argh.key?(:structure)
789
+ unless argh[:structure].is_a?(BTAP::Structure)
790
+ lgs << "Invalid BTAP::Structure (#{mth})"
791
+ return false
792
+ end
793
+ else
794
+ lgs << "Missing STRUCTURE key (#{mth})"
795
+ return false
1569
796
  end
1570
797
 
1571
- buffers
1572
- end
798
+ # Building-wide envelope (e.g. assemblies, U-factors, PSI-factors) options
799
+ # depend on building structure-dependent features such as framing,
800
+ # cladding, etc. This will need to adapt to upcoming story/space
801
+ # construction/PSI customization - @todo.
802
+ strc = argh[:structure]
1573
803
 
1574
- ##
1575
- # Remove previously BTAP/TBD-added heating setpoint schedules for 'buffer
1576
- # zones' (e.g. attics).
1577
- #
1578
- # @param model [OpenStudio::Model::Model] a model
1579
- # @param buffers [Array] identifiers of modified buffer spaces in model
1580
- #
1581
- # @return [Boolean] true if successful
1582
- def purge_buffer_schedules(model = nil, buffers = [])
1583
- scheds = []
1584
- lgs = @feedback[:logs]
1585
- cl = OpenStudio::Model::Model
1586
- lgs << "Invalid OpenStudio model (purge)" unless model.is_a?(cl)
1587
- lgs << "Invalid BTAP/TBD buffers" unless buffers.is_a?(Array)
1588
- return false unless model.is_a?(cl)
1589
- return false unless buffers.is_a?(Array)
1590
-
1591
- buffers.each do |id|
1592
- space = model.getSpaceByName(id)
1593
- next if space.empty?
804
+ argh[:interpolate] = false unless argh.key?(:interpolate)
805
+ argh[:interpolate] = false unless [true, false].include?(argh[:interpolate])
1594
806
 
1595
- space = space.get
1596
- next if space.thermalZone.empty?
1597
-
1598
- zone = space.thermalZone.get
1599
- next if zone.thermostat.empty?
1600
-
1601
- tstat = zone.thermostat.get
1602
- staged = tstat.respond_to?(:heatingTemperatureSetpointSchedule)
1603
- tstat = tstat.to_ZoneControlThermostatStagedDualSetpoint.get if staged
1604
- tstat = tstat.to_ThermostatSetpointDualSetpoint.get unless staged
1605
- sched = tstat.heatingTemperatureSetpointSchedule if staged
1606
- sched = tstat.heatingSetpointTemperatureSchedule unless staged
1607
- next if sched.empty?
1608
-
1609
- sched = sched.get
1610
- scheds << sched.nameString
1611
- tstat.resetHeatingSetpointTemperatureSchedule unless staged
1612
- tstat.resetHeatingTemperatureSetpointSchedule if staged
1613
- end
807
+ [:walls, :floors, :roofs].each do |stypes|
808
+ unless argh.key?(stypes)
809
+ lgs << "Missing BTAP/TBD #{stypes} (#{mth})"
810
+ return false
811
+ end
1614
812
 
1615
- scheds.each do |sched|
1616
- schd = model.getScheduleByName(sched)
1617
- next if schd.empty?
1618
- schd = schd.get
1619
- schd.remove
1620
- end
813
+ unless argh[stypes].key?(:uo)
814
+ lgs << "Missing BTAP/TBD #{stypes} Uo (#{mth})"
815
+ return false
816
+ end
1621
817
 
1622
- true
1623
- end
818
+ uo = argh[stypes][:uo]
1624
819
 
1625
- ##
1626
- # Fetch min U-factor of outdoor-facing OpenStudio model surface types.
1627
- #
1628
- # @param model [OpenStudio::Model::Model] a model
1629
- # @param stype [Symbol] model surface type (e.g. :walls)
1630
- #
1631
- # @return [Float] min U factor (default 5.678 W/m2.K)
1632
- def minU(model = nil, stypes = :walls)
1633
- u = UMAX
1634
- lgs = @feedback[:logs]
1635
- cl = OpenStudio::Model::Model
1636
- stype = stypes.to_s.chop.downcase
1637
- ok = stype == "wall" || stype == "floor" || stype == "roof"
1638
- stype = "wall" unless ok
1639
- lgs << "Invalid OpenStudio model (#{stypes} minU)" unless model.is_a?(cl)
1640
- return u unless model.is_a?(cl)
1641
-
1642
- model.getSurfaces.each do |s|
1643
- next unless s.surfaceType.downcase.include?(stype)
1644
- next unless s.outsideBoundaryCondition.downcase == "outdoors"
1645
- next if s.construction.empty?
1646
- next if s.construction.get.to_LayeredConstruction.empty?
820
+ unless uo.is_a?(Numeric) && uo.between?(TBD::UMIN, TBD::UMAX)
821
+ lgs << "Invalid BTAP/TBD #{stypes} Uo (#{mth})"
822
+ return false
823
+ end
1647
824
 
1648
- lc = s.construction.get.to_LayeredConstruction.get
1649
- uo = 1 / TBD.rsi(lc, s.filmResistance)
825
+ next unless argh[stypes].key?(:ut)
1650
826
 
1651
- u = [uo, u].min
1652
- end
827
+ ut = argh[stypes][:ut]
1653
828
 
1654
- # u0 = format("%.3f", u) # TEMPORARY
1655
- # puts "~~ Extracted #{stypes} minU (#{u0}) W/m2.K from OpenStudio model"
829
+ unless ut.is_a?(Numeric) && ut.between?(TBD::UMIN, TBD::UMAX)
830
+ lgs << "Invalid BTAP/TBD #{stypes} Ut (#{mth})"
831
+ return false
832
+ end
833
+ end
1656
834
 
1657
- u
1658
- end
835
+ # Run TBD on a cloned OpenStudio model (dry run).
836
+ mdl = OpenStudio::Model::Model.new
837
+ mdl.addObjects(model.toIdfFile.objects)
838
+ TBD.clean!
839
+ res = TBD.process(mdl, args)
1659
840
 
1660
- ##
1661
- # Populate BTAP/TBD model with BTAP & OpenStudio model parameters.
1662
- #
1663
- # @param model [OpenStudio::Model::Model] a model
1664
- # @param argh [Hash] BTAP/TBD argument hash
1665
- #
1666
- # @return [Boolean] true if valid (check @feedback logs if false)
1667
- def populate(model = nil, argh = {})
1668
- cl = OpenStudio::Model::Model
1669
- args = { option: "(non thermal bridging)" } # for initial TBD dry run
1670
- lgs = @feedback[:logs]
841
+ # TBD validation of OpenStudio model.
842
+ if TBD.fatal? || TBD.error?
843
+ lgs << "TBD-identified FATAL error(s):" if TBD.fatal?
844
+ lgs << "TBD-identified non-FATAL error(s):" if TBD.error?
1671
845
 
1672
- lgs << "Invalid OpenStudio model to de/up-rate" unless model.is_a?(cl)
1673
- lgs << "Invalid BTAP/TBD argument Hash" unless argh.is_a?(Hash)
1674
- lgs << "Empty BTAP/TBD argument hash" if argh.empty?
1675
- return false unless model.is_a?(cl)
1676
- return false unless argh.is_a?(Hash)
1677
- return false if argh.empty?
846
+ TBD.logs.each { |log| lgs << log[:message] }
847
+ return false if TBD.fatal?
848
+ end
1678
849
 
1679
850
  # Fetch number of stories in OpenStudio model.
1680
851
  stories = model.getBuilding.standardsNumberOfAboveGroundStories
1681
852
  stories = stories.get unless stories.empty?
1682
853
  stories = model.getBuildingStorys.size unless stories.is_a?(Integer)
1683
854
 
1684
- @model[:stories] = stories
1685
- @model[:stories] = 1 if stories < 1
1686
- @model[:stories] = 999 if stories > 999
855
+ # Story/space construction/PSI customization is yet to be implemented.
856
+ # Keeping placeholders for now - @todo.
857
+ @model[:stories] = stories.clamp(1, 999)
1687
858
  @model[:spaces ] = {}
1688
- @model[:sptypes] = {}
1689
859
 
1690
- # Run TBD on a cloned OpenStudio model (dry run).
1691
- mdl = OpenStudio::Model::Model.new
1692
- mdl.addObjects(model.toIdfFile.objects)
1693
- TBD.clean!
1694
- res = TBD.process(mdl, args)
1695
- surfaces = res[:surfaces]
860
+ # Initialize deratable opaque, layered constructions & surface types.
861
+ @model[:constructions] = {}
862
+ @model[:stypes ] = []
1696
863
 
1697
- # TBD validation of OpenStudio model.
1698
- lgs << "TBD-identified FATAL error(s):" if TBD.fatal?
1699
- lgs << "TBD-identified non-FATAL error(s):" if TBD.error?
1700
- TBD.logs.each { |log| lgs << log[:message] } if TBD.fatal? || TBD.error?
1701
- return false if TBD.fatal?
1702
-
1703
- lgs << "TBD: no deratable surfaces in model" if surfaces.nil?
1704
- return false if surfaces.nil?
864
+ if res[:surfaces].nil?
865
+ lgs << "No deratable surfaces in model (#{mth})"
866
+ return false
867
+ end
1705
868
 
1706
- # Initialize deratable walls, exposed floors & roofs.
1707
- [:walls, :floors, :roofs].each { |stypes| @model[stypes] = {} }
869
+ # TBD surface objects hold certain attributes (keys) to signal if they're
870
+ # deratable. Concentrating only on those. Relying on reported strings
871
+ # (e.g. surface identifier) or integers (e.g. a layer :index) seems fine.
872
+ # Yet referecing TBD-cloned OpenStudio objects (e.g. key :construction)
873
+ # is a no-no (e.g. seg faults).
874
+ res[:surfaces].each do |id, surface|
875
+ next unless surface.key?(:type) # :wall, :ceiling or :floor
876
+ next unless surface.key?(:filmRSI) # sum of air film resistances
877
+ next unless surface.key?(:index) # deratable layer index
878
+ next unless surface.key?(:r) # deratable layer RSi
879
+ next unless surface.key?(:deratable) # true or false
1708
880
 
1709
- surfaces.each do |id, surface|
1710
- next unless surface.key?(:type ) # :wall, :floor, :ceiling
1711
- next unless surface.key?(:space ) # OpenStudio space object
1712
- next unless surface.key?(:deratable) # true/false
1713
881
  next unless surface[:deratable]
882
+ next unless surface[:index ]
883
+
884
+ stypes = case surface[:type]
885
+ when :wall then :walls
886
+ when :floor then :floors
887
+ when :ceiling then :roofs
888
+ else ""
889
+ end
890
+
891
+ next if stypes.empty?
892
+
893
+ # Track surface type.
894
+ @model[:stypes] << stypes unless @model[:stypes].include?(stypes)
895
+
896
+ # Track TBD-targeted constructions for uprating/derating.
897
+ srf = model.getSurfaceByName(id)
898
+
899
+ if srf.empty?
900
+ lgs << "Mismatched surface: #{id} (#{mth})?"
901
+ return false
902
+ end
903
+
904
+ srf = srf.get
905
+ space = srf.space
906
+
907
+ if space.empty?
908
+ lgs << "Missing space: #{id} (#{mth})?"
909
+ return false
910
+ end
911
+
912
+ space = space.get
913
+ lc = srf.construction
914
+
915
+ if lc.empty?
916
+ lgs << "Mismatched construction: #{id} (#{mth})?"
917
+ return false
918
+ end
919
+
920
+ lc = lc.get.to_LayeredConstruction
921
+
922
+ if lc.empty?
923
+ lgs << "Mismatched layered construction: #{id} (#{mth})?"
924
+ return false
925
+ end
926
+
927
+ lc = lc.get
928
+
929
+ unless @model[:constructions].key?(lc)
930
+ @model[:constructions][lc] = {}
931
+ @model[:constructions][lc][:index ] = surface[:index] # material
932
+ @model[:constructions][lc][:r ] = surface[:r] # material
933
+ @model[:constructions][lc][:filmRSI ] = surface[:filmRSI] # assembly
934
+ @model[:constructions][lc][:uo ] = nil # assembly
935
+ @model[:constructions][lc][:compliant] = nil # assembly
936
+ @model[:constructions][lc][:stypes ] = []
937
+ @model[:constructions][lc][:surfaces ] = []
938
+ @model[:constructions][lc][:spaces ] = []
939
+
940
+ # Generate TBD input hashes for both :good & :bad PSI factor sets.
941
+ # This depends solely on assigned wall constructions (e.g. steel- vs
942
+ # wood-framed) - not roof or floor constructions. Until space- and
943
+ # storey-specific structure/construction customization is enabled in
944
+ # BTAP, this is set for the entire building. In other words - for now
945
+ # - there should be a single assigned layered construction for all
946
+ # walls in a BTAP-altered OpenStudio model.
947
+ if stypes == :walls
948
+ @model[:constructions][lc][:lp_bad ] = self.inputs(strc, :lp, :bad )
949
+ @model[:constructions][lc][:lp_good] = self.inputs(strc, :lp, :good)
950
+ @model[:constructions][lc][:hp_bad ] = self.inputs(strc, :hp, :bad )
951
+ @model[:constructions][lc][:hp_good] = self.inputs(strc, :hp, :good)
952
+ end
953
+ end
1714
954
 
1715
- stypes = :walls if surface[:type] == :wall
1716
- stypes = :floors if surface[:type] == :floor
1717
- stypes = :roofs if surface[:type] == :ceiling
1718
- next unless stypes == :walls || stypes == :floors || stypes == :roofs
1719
-
1720
- space = surface[:space].nameString
1721
- sptype = surface[:stype].nameString if surface.key?(:stype)
1722
- sptype = "" unless surface.key?(:stype)
1723
- typ = self.spacetype(sptype, @model[:stories]) # e.g. :office
1724
-
1725
- # Keep track of individual surface's space and spacetype keyword.
1726
- @model[stypes][id] = {}
1727
- @model[stypes][id][:space ] = space
1728
- @model[stypes][id][:sptype] = typ
1729
-
1730
- # Keep track of individual spaces and spacetypes.
1731
- exists = @model[:spaces].key?(space)
1732
- @model[:spaces][space] = {} unless exists
1733
- @model[:spaces][space][:sptype] = typ unless exists
1734
-
1735
- exists = @model[:sptypes].key?(typ)
1736
- @model[:sptypes][typ ] = {} unless exists
1737
- @model[:sptypes][typ ][:sptype] = sptype unless exists
1738
- next if @model[:sptypes][typ].key?(stypes)
1739
-
1740
- # Low- vs Hi-Performance BTAP assemblies.
1741
- lo = self.assembly(typ, stypes, :lp)
1742
- hi = self.assembly(typ, stypes, :hp)
1743
- @model[:sptypes][typ][stypes] = {}
1744
- @model[:sptypes][typ][stypes][:lp] = lo
1745
- @model[:sptypes][typ][stypes][:hp] = hi
1746
- next unless stypes == :walls
1747
-
1748
- # Fetch bad vs good PSI factor sets - strictly a function of walls.
1749
- @model[:sptypes][typ][:lp_bad ] = self.set(lo, :bad )
1750
- @model[:sptypes][typ][:lp_good] = self.set(lo, :good)
1751
- @model[:sptypes][typ][:hp_bad ] = self.set(hi, :bad )
1752
- @model[:sptypes][typ][:hp_good] = self.set(hi, :good)
955
+ # Select lowest applicable air film resistances (given surface slope).
956
+ film = [@model[:constructions][lc][:filmRSI], surface[:filmRSI]].min
957
+
958
+ @model[:constructions][lc][:filmRSI ] = film
959
+ @model[:constructions][lc][:stypes ] << stypes # 1x
960
+ @model[:constructions][lc][:surfaces] << id # many
961
+ @model[:constructions][lc][:spaces ] << space.nameString # less
1753
962
  end
1754
963
 
1755
- # BTAP-fed Uo (+ optional Ut) factors.
1756
- [:walls, :floors, :roofs].each do |stypes|
1757
- lgs << "Missing BTAP/TBD #{stypes}" unless argh.key?(stypes)
1758
- lgs << "Missing BTAP/TBD #{stypes} Uo" unless argh[stypes].key?(:uo)
1759
- return false unless argh.key?(stypes)
1760
- return false unless argh[stypes].key?(:uo)
1761
- next if @model[stypes].empty?
964
+ # Loop through all tracked deratable constructions. Ensure a single
965
+ # surface type per construction. Ensure at least one wall construction.
966
+ @model[:constructions].values.each { |v| v[:stypes].uniq! }
967
+ nb = 0
1762
968
 
1763
- uo = argh[stypes][:uo]
1764
- ok = uo.is_a?(Numeric) && uo.between?(UMIN, UMAX)
1765
- next if ok
969
+ @model[:constructions].each do |lc, v|
970
+ if v[:stypes].size != 1
971
+ lgs << "Multiple surface types per construction (#{mth})?"
972
+ return false
973
+ else
974
+ v[:stypes] = v[:stypes].first
1766
975
 
1767
- uo = self.minU(model, stypes)
1768
- ok = uo.is_a?(Numeric) && uo.between?(UMIN, UMAX)
1769
- lgs << "Invalid BTAP/TBD #{stypes} Uo" unless ok
1770
- return false unless ok
976
+ # Assign construction for each deratable surface.
977
+ v[:surfaces].each do |id|
978
+ surface = model.getSurfaceByName(id)
979
+ next if surface.empty?
1771
980
 
1772
- argh[stypes][:uo] = uo
1773
- next unless argh[stypes].key?(:ut)
981
+ surface.get.setConstruction(lc)
982
+ end
983
+ end
984
+
985
+ nb += 1 if v[:stypes] == :walls
986
+ end
1774
987
 
1775
- argh[stypes][:ut] = uo
988
+ if nb < 1
989
+ lgs << "No deratable walls (#{mth})?"
990
+ return false
1776
991
  end
1777
992
 
1778
- # Generate native TBD input Hashes for the model, for both :good & :bad
1779
- # PSI factor sets. The typical TBD use case involves writing out the
1780
- # contents of either Hash (e.g. JSON::pretty_generate) as a "tbd.json"
1781
- # input file, to save under a standard OpenStudio "files" folder. At
1782
- # runtime, TBD then reopens the JSON file and populates its own data
1783
- # model in memory. Yet BTAP is not a typical use case. To avoid writing
1784
- # out (then re-reading) TBD JSON files/hashes (i.e. resource intensive),
1785
- # BTAP/TBD instead populates the TBD data model directly.
1786
- @model[:lp_bad ] = self.inputs(:lp, :bad )
1787
- @model[:lp_good] = self.inputs(:lp, :good)
1788
- @model[:hp_bad ] = self.inputs(:hp, :bad )
1789
- @model[:hp_good] = self.inputs(:hp, :good)
1790
-
1791
- @model[:osm ] = model
993
+ @model[:osm] = model
1792
994
 
1793
995
  true
1794
996
  end
1795
997
 
1796
998
  ##
1797
- # Generate (native) TBD input hash.
999
+ # Generate TBD input hash.
1798
1000
  #
1001
+ # @param structure [BTAP::Structure] a BTAP STRUCTURE object
1799
1002
  # @param perform [Symbol] :lp or :hp wall variant
1800
1003
  # @param quality [Symbol] :bad or :good PSI-factor
1801
1004
  #
1802
- # @return [Hash] native TBD inputs
1803
- def inputs(perform = :hp, quality = :good)
1005
+ # @return [Hash] TBD inputs
1006
+ def inputs(structure = nil, perform = :hp, quality = :good)
1804
1007
  input = {}
1805
1008
  psis = {} # construction-specific PSI sets
1806
- sptypes = {} # space type-specific references to previous PSI sets
1807
- perform = :hp unless perform == :lp || perform == :hp
1808
- quality = :good unless quality == :bad || quality == :good
1809
-
1810
- # Once building-type construction selection is introduced within BTAP,
1811
- # define default TBD "building" PSI set. In the meantime, this is added
1812
- # strictly as a backup solution (just in case).
1813
- building = self.set(STEL1, quality) if perform == :lp
1814
- building = self.set(STEL2, quality) if perform == :hp
1815
-
1816
- psis[ building[:id] ] = building
1817
-
1818
- # Collect unique BTAP/TBD instances.
1819
- combo = "#{perform.to_s}_#{quality.to_s}".to_sym
1009
+ perform = :hp unless [:lp, :hp].include?(perform)
1010
+ quality = :good unless [:bad, :good].include?(quality)
1820
1011
 
1821
- @model[:sptypes].values.each do |sptype|
1822
- next unless sptype.key?(combo)
1012
+ # A single PSI set for the entire building, based strictly on exterior
1013
+ # wall selection. Adapt once BTAP::Structure supports STRUCTURE
1014
+ # assignements per OpenStudio's building-to-space hierarchy, e.g. "cmu"
1015
+ # gymnasium walls in an otherwise "steel"post/frame school. @todo
1016
+ assembly = self.costed_assembly(structure, :walls, perform)
1017
+ building_psi = self.set(assembly, quality)
1823
1018
 
1824
- psi = sptype[combo]
1825
- next if psis.key?(psi[:id])
1826
-
1827
- psis[ psi[:id] ] = psi
1828
- end
1019
+ psis[ building_psi[:id] ] = building_psi
1829
1020
 
1830
1021
  # TBD JSON schema added as a reminder. No schema validation in BTAP.
1831
1022
  schema = "https://github.com/rd2/tbd/blob/master/tbd.schema.json"
1832
1023
 
1833
1024
  input[:schema ] = schema
1834
- input[:description] = "TBD input for BTAP" # append run # ?
1835
- input[:psis ] = psis.values
1836
-
1837
- @model[:sptypes].values.each do |sptype|
1838
- next unless sptype.key?(combo)
1839
- next unless sptype.key?(:sptype)
1840
- next if sptypes.key?(sptype[:sptype])
1841
-
1842
- sptypes[ sptype[:sptype] ] = { psi: sptype[combo][:id] }
1843
- end
1844
-
1845
- sptypes.each do |id, sptype|
1846
- input[:spacetypes] = [] unless input.key?(:spacetypes)
1847
- input[:spacetypes] << { id: id, psi: sptype[:psi] }
1848
- end
1849
-
1850
- input[:building] = { psi: building[:id] }
1025
+ input[:description] = "TBD input for BTAP" # append run # ?
1026
+ input[:psis ] = psis.values # maybe more than 1 in future
1027
+ input[:building ] = { psi: building_psi[:id] }
1851
1028
 
1852
1029
  input
1853
1030
  end
@@ -1857,8 +1034,9 @@ module BTAP
1857
1034
  #
1858
1035
  # @return [Boolean] true if BTAP/TBD tally is successful
1859
1036
  def gen_tallies
1860
- edges = {}
1037
+ edges = {}
1861
1038
  return false unless @model.key?(:io)
1039
+ return false unless @model.key?(:constructions)
1862
1040
  return false unless @model[:io].key?(:edges)
1863
1041
 
1864
1042
  @model[:io][:edges].each do |e|
@@ -1875,10 +1053,6 @@ module BTAP
1875
1053
  return false if edges.empty?
1876
1054
 
1877
1055
  @tally[:edges] = edges
1878
-
1879
- # Add final selection of (uprated) Uo factors per BTAP construction.
1880
- return true unless @model.key?(:constructions)
1881
-
1882
1056
  @tally[:constructions] = @model[:constructions]
1883
1057
 
1884
1058
  true
@@ -1891,34 +1065,33 @@ module BTAP
1891
1065
  def gen_feedback
1892
1066
  lgs = @feedback[:logs]
1893
1067
  return false unless @model.key?(:complies) # all model constructions
1894
- return false unless @model.key?(:comply ) # surface type specific ...
1895
- return false unless @model.key?(:argh ) # BTAP/TBD inputs + ouputs
1068
+ return false unless @model.key?(:comply) # surface type specific ...
1069
+ return false unless @model.key?(:argh) # BTAP/TBD inputs + ouputs
1070
+ return false unless @model.key?(:stypes) # :walls, :roofs, :floors
1896
1071
 
1897
1072
  argh = @model[:argh]
1898
1073
 
1899
1074
  # Uprating. Report first on surface types (compliant or not).
1900
- [:walls, :floors, :roofs].each do |stypes|
1075
+ @model[:stypes].each do |stypes|
1901
1076
  next unless @model[:comply].key?(stypes)
1902
1077
 
1903
1078
  ut = format("%.3f", argh[stypes][:ut])
1904
- lg = "Compliant " if @model[:comply][stypes]
1905
- lg = "Non-compliant " unless @model[:comply][stypes]
1079
+ lg = @model[:comply][stypes] ? "Compliant " : "Non-compliant "
1906
1080
  lg += "#{stypes}: Ut #{ut} W/m2.K"
1907
1081
  lgs << lg
1908
1082
 
1909
1083
  # Report then on required Uo factor per construction (compliant or not).
1910
- @model[:constructions].each do |id, construction|
1911
- next unless construction.key?(:stypes )
1912
- next unless construction.key?(:uo )
1913
- next unless construction.key?(:compliant)
1914
- next unless construction.key?(:surfaces )
1915
- next unless construction[:stypes ] == stypes
1916
- next if construction[:surfaces].empty?
1917
-
1918
- uo = format("%.3f", construction[:uo])
1919
- lg = " Compliant " if construction[:compliant]
1920
- lg = " Non-compliant " unless construction[:compliant]
1921
- lg += "#{id} Uo #{uo} (W/K.m2)"
1084
+ @model[:constructions].each do |lc, v|
1085
+ next unless v.key?(:stypes)
1086
+ next unless v.key?(:uo)
1087
+ next unless v.key?(:compliant)
1088
+ next unless v.key?(:surfaces)
1089
+ next unless v[:stypes ] == stypes
1090
+ next if v[:surfaces].empty?
1091
+
1092
+ uo = format("%.3f", v[:uo])
1093
+ lg = v[:compliant] ? " Compliant " : " Non-compliant "
1094
+ lg += "#{lc.nameString} Uo #{uo} (W/K.m2)"
1922
1095
  lgs << lg
1923
1096
  end
1924
1097
  end
@@ -1957,62 +1130,57 @@ module BTAP
1957
1130
  true
1958
1131
  end
1959
1132
 
1960
- def get_material_quantities()
1961
- material_quantities = {}
1962
- csv = CSV.read("#{File.dirname(__FILE__)}/../../../data/inventory/thermal_bridging.csv", headers: true)
1963
- tally_edges = @tally[:edges].transform_keys(&:to_s)
1964
-
1965
- #tally_edges = JSON.parse('{"edges":{"jamb":{"BTAP-ExteriorWall-SteelFramed-1 good":13.708557548340757},"sill":{"BTAP-ExteriorWall-SteelFramed-1 good":90.13000000000001},"head":{"BTAP-ExteriorWall-SteelFramed-1 good":90.13000000000001},"gradeconvex":{"BTAP-ExteriorWall-SteelFramed-1 good":90.4348},"parapetconvex":{"BTAP-ExteriorWall-SteelFramed-1 good":45.2174},"parapet":{"BTAP-ExteriorWall-SteelFramed-1 good":45.2174},"transition":{"BTAP-ExteriorWall-SteelFramed-1 good":71.16038874419307},"cornerconvex":{"BTAP-ExteriorWall-SteelFramed-1 good":12.1952}}}')['edges']
1966
- tally_edges.each do |edge_type_full, value|
1967
- edge_type = edge_type_full.delete_suffix('convex')
1968
- if ['head', 'jamb', 'sill'].include?(edge_type)
1969
- edge_type = 'fenestration'
1970
- end
1971
- value.each do |wall_ref_and_quality, quantity|
1972
- /(.*)\s(.*)/ =~ wall_ref_and_quality
1973
- wall_reference = $1
1974
- quality = $2
1975
-
1976
- if wall_reference =='BTAP-ExteriorWall-SteelFramed-1'
1977
- wall_reference = 'BTAP-ExteriorWall-SteelFramed-2'
1978
- end
1979
-
1980
- if edge_type == 'transition'
1981
- next
1982
- end
1983
-
1984
- result = csv.find { |row| row['edge_type'] == edge_type &&
1985
- row['quality'] == quality &&
1986
- row['wall_reference'] == wall_reference
1987
- }
1988
- if result.nil?
1989
- puts ("#{edge_type}-#{wall_reference}-#{quality}")
1990
- puts "not found in tb database"
1991
- next
1992
- end
1993
-
1994
- # Split
1995
- material_opaque_id_layers = result['material_opaque_id_layers'].split(",")
1996
- id_layers_quantity_multipliers = result['id_layers_quantity_multipliers'].split(",")
1997
-
1998
- material_opaque_id_layers.zip(id_layers_quantity_multipliers).each do |id, scale|
1999
- if material_quantities[id].nil? then material_quantities[id] = 0.0 end
2000
- material_quantities[id] = material_quantities[id] + scale.to_f * quantity.to_f
2001
- end
2002
- end
2003
- end
2004
- material_opaque_id_quantities = []
2005
- material_quantities.each do |id,quantity|
2006
- material_opaque_id_quantities << { 'materials_opaque_id' => id, 'quantity' => quantity, 'domain'=> 'thermal_bridging' }
2007
- end
2008
-
2009
- return material_opaque_id_quantities
2010
- end
2011
-
2012
-
1133
+ # def get_material_quantities()
1134
+ # material_quantities = {}
1135
+ # csv = CSV.read("#{File.dirname(__FILE__)}/../../../data/inventory/thermal_bridging.csv", headers: true)
1136
+ # tally_edges = @tally[:edges].transform_keys(&:to_s)
1137
+ #
1138
+ # tally_edges.each do |edge_type_full, value|
1139
+ # edge_type = edge_type_full.delete_suffix('convex')
1140
+ # edge_type = 'fenestration' if ['head', 'jamb', 'sill'].include?(edge_type)
1141
+ #
1142
+ # value.each do |wall_ref_and_quality, quantity|
1143
+ # /(.*)\s(.*)/ =~ wall_ref_and_quality
1144
+ # wall_reference = $1
1145
+ # quality = $2
1146
+ #
1147
+ # if wall_reference =='BTAP-ExteriorWall-SteelFramed-1'
1148
+ # wall_reference = 'BTAP-ExteriorWall-SteelFramed-2'
1149
+ # end
1150
+ #
1151
+ # next if edge_type == 'transition'
1152
+ #
1153
+ # result = csv.find { |row| row['edge_type'] == edge_type &&
1154
+ # row['quality'] == quality &&
1155
+ # row['wall_reference'] == wall_reference
1156
+ # }
1157
+ #
1158
+ # if result.nil?
1159
+ # puts ("#{edge_type}-#{wall_reference}-#{quality}")
1160
+ # puts "not found in tb database"
1161
+ # next
1162
+ # end
1163
+ #
1164
+ # # Split
1165
+ # material_opaque_id_layers = result['material_opaque_id_layers'].split(",")
1166
+ # id_layers_quantity_multipliers = result['id_layers_quantity_multipliers'].split(",")
1167
+ #
1168
+ # material_opaque_id_layers.zip(id_layers_quantity_multipliers).each do |id, scale|
1169
+ # material_quantities[id] = 0.0 if material_quantities[id].nil?
1170
+ # material_quantities[id] = material_quantities[id] + scale.to_f * quantity.to_f
1171
+ # end
1172
+ # end
1173
+ # end
1174
+ #
1175
+ # material_opaque_id_quantities = []
1176
+ #
1177
+ # material_quantities.each do |id,quantity|
1178
+ # material_opaque_id_quantities << { 'materials_opaque_id' => id, 'quantity' => quantity, 'domain'=> 'thermal_bridging' }
1179
+ # end
1180
+ #
1181
+ # return material_opaque_id_quantities
1182
+ # end
2013
1183
  end
2014
-
2015
-
2016
1184
  end
2017
1185
 
2018
1186
  # ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----- #
@@ -2097,7 +1265,7 @@ end
2097
1265
  # default fenestration layout. As a result, BTAP/TBD presumes continuous
2098
1266
  # shelf angles, offset by the height difference between slab edge and
2099
1267
  # window head. Loose lintels are however included in the clear field
2100
- # costing ($/m2), yet should be limited to doors (TO-DO). A more flexible,
1268
+ # costing ($/m2), yet should be limited to doors (@todo). A more flexible,
2101
1269
  # general solution would be required for 3rd-party OpenStudio models
2102
1270
  # (without strip windows as a basic fenestration layout).
2103
1271
  #
@@ -2106,13 +1274,4 @@ end
2106
1274
  # BTAP costing requires extending the areas (m2) of OpenStudio wall
2107
1275
  # surfaces (along parapet edges) by 3'-6" (1.1 m) x parapet lengths, to
2108
1276
  # account for the extra cost of completely wrapping the parapet in
2109
- # insulation for "good" (HP) details. See final TBD tally. TO-DO.
2110
- #
2111
- # NOTE: Overview of current BTAP building/space type construction link, e.g.:
2112
- #
2113
- # - ALL dwelling units/buildings < 5 stories are wood-framed
2114
- # - ALL dwelling units/buildings > 4 stories are steel-framed
2115
- #
2116
- # ... yet all (public) washrooms, corridors, stairwells, etc. are
2117
- # steel-framed (regardless of building type). Overview of possible fixes.
2118
- # TO-DO.
1277
+ # insulation for "good" (HP) details. See final TBD tally - @todo.