openstudio-standards 0.2.14 → 0.2.15.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (642) hide show
  1. checksums.yaml +4 -4
  2. data/data/geometry/ASHRAECollege.json +0 -19
  3. data/data/geometry/ASHRAEMidriseApartment.json +47 -47
  4. data/data/geometry/ASHRAESecondarySchool.osm +2 -2
  5. data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
  6. data/data/standards/export_OpenStudio_libraries.rb +1 -1
  7. data/data/standards/manage_OpenStudio_Standards.rb +43 -87
  8. data/data/standards/metadata_units_OpenStudio_Standards-ashrae_90_1.csv +9 -0
  9. data/data/standards/openstudio_standards_duplicates_log.csv +142 -27
  10. data/data/standards/test_performance_expected_dd_results.csv +2016 -2016
  11. data/data/weather/CAN_NU_Iqaluit.AP.719090_CWEC2016.ddy +2316 -0
  12. data/data/weather/CAN_NU_Iqaluit.AP.719090_CWEC2016.epw +8768 -0
  13. data/data/weather/CAN_NU_Iqaluit.AP.719090_CWEC2016.stat +697 -0
  14. data/lib/openstudio-standards/btap/WeatherData1.json +54 -0
  15. data/lib/openstudio-standards/btap/WeatherData1.xlsx +0 -0
  16. data/lib/openstudio-standards/btap/btap_result.rb +12 -10
  17. data/lib/openstudio-standards/btap/envelope.rb +2 -2
  18. data/lib/openstudio-standards/btap/geometry.rb +96 -49
  19. data/lib/openstudio-standards/{utilities → btap/utilities}/Add_template_field_to_json.rb +0 -0
  20. data/lib/openstudio-standards/{utilities → btap/utilities}/convert_surfaces_to_adiabatic_necb_8426.rb +0 -0
  21. data/lib/openstudio-standards/{utilities → btap/utilities}/generate_space_types.rb +0 -0
  22. data/lib/openstudio-standards/{utilities → btap/utilities}/necb_to_epw_map.rb +0 -0
  23. data/lib/openstudio-standards/{utilities → btap/utilities}/os_sim_extract.rb +0 -0
  24. data/lib/openstudio-standards/{utilities → btap/utilities}/rename_surfaces.rb +0 -0
  25. data/lib/openstudio-standards/{utilities → btap/utilities}/round_surf_coords.rb +0 -0
  26. data/lib/openstudio-standards/{utilities → btap/utilities}/sched_create.rb +0 -0
  27. data/lib/openstudio-standards/{utilities → btap/utilities}/set_mult_to_adiabatic.rb +0 -0
  28. data/lib/openstudio-standards/btap/utilities/space_type.rb +78 -0
  29. data/lib/openstudio-standards/{utilities → btap/utilities}/weatherData1_xlsx_to_json.rb +0 -0
  30. data/lib/openstudio-standards/hvac_sizing/Siz.AirConditionerVariableRefrigerantFlow.rb +1 -1
  31. data/lib/openstudio-standards/hvac_sizing/Siz.HVACComponent.rb +1 -1
  32. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +20 -6
  33. data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +6 -6
  34. data/lib/openstudio-standards/hvac_sizing/Siz.WaterHeaterMixed.rb +2 -2
  35. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACTerminalUnitVariableRefrigerantFlow.rb +1 -1
  36. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirTerminalSingleDuctVAVReheat.rb +2 -1
  37. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PumpVariableSpeed.rb +6 -7
  38. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.AirTerminalSingleDuctVAVReheat.rb +2 -1
  39. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.FanConstantVolume.rb +5 -4
  40. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.FanOnOff.rb +5 -5
  41. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.FanVariableVolume.rb +5 -4
  42. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.PumpVariableSpeed.rb +6 -7
  43. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +2 -1
  44. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.FanConstantVolume.rb +5 -4
  45. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.FanOnOff.rb +5 -5
  46. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.FanVariableVolume.rb +5 -4
  47. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Model.elevators.rb +6 -4
  48. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Model.rb +10 -9
  49. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.PumpVariableSpeed.rb +9 -11
  50. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +2 -1
  51. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.FanConstantVolume.rb +5 -4
  52. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.FanOnOff.rb +5 -5
  53. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.FanVariableVolume.rb +5 -4
  54. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.elevators.rb +11 -7
  55. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +17 -16
  56. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.PumpVariableSpeed.rb +9 -11
  57. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.hvac_systems.rb +4 -2
  58. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +2 -1
  59. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.FanConstantVolume.rb +5 -4
  60. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.FanOnOff.rb +5 -5
  61. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.FanVariableVolume.rb +5 -4
  62. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.elevators.rb +11 -7
  63. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +23 -22
  64. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.PumpVariableSpeed.rb +9 -10
  65. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.hvac_systems.rb +4 -2
  66. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +2 -1
  67. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanConstantVolume.rb +5 -4
  68. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanOnOff.rb +5 -5
  69. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanVariableVolume.rb +5 -4
  70. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.elevators.rb +11 -7
  71. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +23 -22
  72. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Pump.rb +89 -0
  73. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.PumpVariableSpeed.rb +9 -10
  74. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +76 -0
  75. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb +22 -2
  76. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirTerminalSingleDuctVAVReheat.rb +2 -1
  77. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.elevators.rb +11 -11
  78. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.refrigeration.rb +5 -4
  79. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirTerminalSingleDuctVAVReheat.rb +2 -1
  80. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.CoilHeatingGas.rb +5 -4
  81. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.elevators.rb +11 -11
  82. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.refrigeration.rb +5 -4
  83. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +2 -1
  84. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.FanConstantVolume.rb +5 -4
  85. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.FanOnOff.rb +5 -5
  86. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.FanVariableVolume.rb +5 -4
  87. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.HeatExchangerAirToAirSensibleAndLatent.rb +2 -0
  88. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.Model.elevators.rb +11 -7
  89. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.Model.rb +10 -10
  90. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.hvac_systems.rb +4 -2
  91. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +2 -1
  92. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.FanConstantVolume.rb +5 -4
  93. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.FanOnOff.rb +5 -5
  94. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.FanVariableVolume.rb +5 -4
  95. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.HeatExchangerAirToAirSensibleAndLatent.rb +2 -0
  96. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.Model.elevators.rb +11 -7
  97. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.Model.rb +10 -10
  98. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.hvac_systems.rb +4 -2
  99. data/lib/openstudio-standards/prototypes/cbes/cbes.Model.elevators.rb +3 -6
  100. data/lib/openstudio-standards/prototypes/cbes/cbes.refrigeration.rb +5 -4
  101. data/lib/openstudio-standards/prototypes/cbes/cbes_t24_2008/cbes_t24_2008.FanConstantVolume.rb +5 -3
  102. data/lib/openstudio-standards/prototypes/cbes/cbes_t24_2008/cbes_t24_2008.FanOnOff.rb +5 -4
  103. data/lib/openstudio-standards/prototypes/cbes/cbes_t24_2008/cbes_t24_2008.FanVariableVolume.rb +5 -3
  104. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +65 -30
  105. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Courthouse.rb +54 -23
  106. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.FullServiceRestaurant.rb +135 -147
  107. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.HighRiseApartment.rb +42 -7
  108. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Hospital.rb +85 -12
  109. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +42 -30
  110. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterHighITE.rb +39 -8
  111. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterLowITE.rb +39 -8
  112. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeHotel.rb +60 -12
  113. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOffice.rb +33 -265
  114. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOfficeDetailed.rb +41 -3
  115. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOffice.rb +69 -297
  116. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOfficeDetailed.rb +68 -25
  117. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MidriseApartment.rb +88 -59
  118. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Outpatient.rb +88 -9
  119. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.PrimarySchool.rb +48 -10
  120. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.QuickServiceRestaurant.rb +130 -145
  121. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStandalone.rb +29 -101
  122. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStripmall.rb +24 -7
  123. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SecondarySchool.rb +48 -589
  124. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterHighITE.rb +38 -7
  125. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterLowITE.rb +38 -8
  126. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallHotel.rb +40 -7
  127. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOffice.rb +85 -171
  128. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOfficeDetailed.rb +87 -44
  129. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperMarket.rb +46 -5
  130. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperTallBuilding.rb +105 -17
  131. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.TallBuilding.rb +97 -15
  132. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Warehouse.rb +26 -167
  133. data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +3828 -1131
  134. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirConditionerVariableRefrigerantFlow.rb +3 -0
  135. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirTerminalSingleDuctVAVReheat.rb +2 -1
  136. data/lib/openstudio-standards/prototypes/common/objects/Prototype.BoilerHotWater.rb +2 -0
  137. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CentralAirSourceHeatPump.rb +2 -0
  138. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingDXSingleSpeed.rb +4 -1
  139. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingDXTwoSpeed.rb +3 -0
  140. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWater.rb +4 -1
  141. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWaterToAirHeatPumpEquationFit.rb +3 -0
  142. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingDXSingleSpeed.rb +9 -0
  143. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingElectric.rb +3 -0
  144. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingGas.rb +9 -4
  145. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWater.rb +4 -1
  146. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWaterToAirHeatPumpEquationFit.rb +3 -0
  147. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ControllerWaterCoil.rb +2 -2
  148. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoolingTower.rb +4 -1
  149. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +23 -2
  150. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanConstantVolume.rb +29 -4
  151. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanOnOff.rb +29 -5
  152. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanVariableVolume.rb +43 -4
  153. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanZoneExhaust.rb +22 -0
  154. data/lib/openstudio-standards/prototypes/common/objects/Prototype.HeatExchangerAirToAirSensibleAndLatent.rb +46 -3
  155. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.elevators.rb +27 -22
  156. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.exterior_lights.rb +15 -8
  157. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.hvac.rb +22 -4
  158. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +429 -59
  159. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.swh.rb +18 -11
  160. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.transformers.rb +11 -2
  161. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Pump.rb +1 -0
  162. data/lib/openstudio-standards/prototypes/common/objects/Prototype.PumpVariableSpeed.rb +8 -10
  163. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +37 -28
  164. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +24 -6
  165. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +251 -65
  166. data/lib/openstudio-standards/prototypes/common/objects/Prototype.radiant_system_controls.rb +1 -1
  167. data/lib/openstudio-standards/prototypes/common/objects/Prototype.refrigeration.rb +46 -31
  168. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +62 -10
  169. data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +76 -33
  170. data/lib/openstudio-standards/prototypes/deer/deer.Model.rb +1 -1
  171. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +445 -275
  172. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +3 -3
  173. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctVAVReheat.rb +26 -21
  174. data/lib/openstudio-standards/standards/Standards.BoilerHotWater.rb +5 -2
  175. data/lib/openstudio-standards/standards/Standards.BuildingStory.rb +7 -9
  176. data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +8 -2
  177. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXMultiSpeed.rb +10 -6
  178. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +5 -1
  179. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXTwoSpeed.rb +6 -1
  180. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +45 -4
  181. data/lib/openstudio-standards/standards/Standards.CoilDX.rb +18 -8
  182. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXMultiSpeed.rb +9 -7
  183. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +8 -4
  184. data/lib/openstudio-standards/standards/Standards.CoilHeatingGas.rb +86 -3
  185. data/lib/openstudio-standards/standards/Standards.CoilHeatingGasMultiStage.rb +5 -2
  186. data/lib/openstudio-standards/standards/Standards.CoilHeatingWaterToAirHeatPumpEquationFit.rb +6 -2
  187. data/lib/openstudio-standards/standards/Standards.Construction.rb +66 -35
  188. data/lib/openstudio-standards/standards/Standards.CoolingTower.rb +7 -7
  189. data/lib/openstudio-standards/standards/Standards.CoolingTowerSingleSpeed.rb +2 -2
  190. data/lib/openstudio-standards/standards/Standards.CoolingTowerTwoSpeed.rb +2 -1
  191. data/lib/openstudio-standards/standards/Standards.CoolingTowerVariableSpeed.rb +2 -1
  192. data/lib/openstudio-standards/standards/Standards.Fan.rb +53 -35
  193. data/lib/openstudio-standards/standards/Standards.FanVariableVolume.rb +22 -16
  194. data/lib/openstudio-standards/standards/Standards.FluidCooler.rb +2 -2
  195. data/lib/openstudio-standards/standards/Standards.HeaderedPumpsVariableSpeed.rb +4 -4
  196. data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +77 -19
  197. data/lib/openstudio-standards/standards/Standards.Model.rb +387 -245
  198. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +13 -15
  199. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +94 -48
  200. data/lib/openstudio-standards/standards/Standards.Pump.rb +28 -20
  201. data/lib/openstudio-standards/standards/Standards.PumpVariableSpeed.rb +3 -4
  202. data/lib/openstudio-standards/standards/Standards.ScheduleCompact.rb +2 -1
  203. data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +2 -0
  204. data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +34 -24
  205. data/lib/openstudio-standards/standards/Standards.Space.rb +179 -116
  206. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +23 -12
  207. data/lib/openstudio-standards/standards/Standards.SubSurface.rb +55 -25
  208. data/lib/openstudio-standards/standards/Standards.Surface.rb +57 -32
  209. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +157 -107
  210. data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +9 -6
  211. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +52 -1
  212. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1.Standards.FanVariableVolume.rb +2 -2
  213. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1.rb +4 -0
  214. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb +28 -18
  215. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.FanVariableVolume.rb +1 -1
  216. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PlantLoop.rb +4 -2
  217. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.rb +4 -0
  218. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/comstock_ashrae_90_1_2004.rb +4 -0
  219. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/ashrae_90_1.schedules.json +696 -2938
  220. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/comstock_ashrae_90_1_2004.ext_ltg.json +1 -1
  221. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/comstock_ashrae_90_1_2004.spc_typ.json +123 -123
  222. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.furnaces.json +26 -0
  223. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.prototype_inputs.json +11 -11
  224. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.refrigeration_system.json +0 -8
  225. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.spc_typ.json +395 -384
  226. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.unitary_acs.json +69 -0
  227. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.AirLoopHVAC.rb +20 -13
  228. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.FanVariableVolume.rb +1 -1
  229. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.Model.rb +1 -1
  230. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.rb +4 -0
  231. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/comstock_ashrae_90_1_2007.rb +4 -0
  232. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/ashrae_90_1.schedules.json +696 -2938
  233. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/comstock_ashrae_90_1_2007.ext_ltg.json +1 -1
  234. 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 +122 -122
  235. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.furnaces.json +26 -0
  236. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.prototype_inputs.json +11 -11
  237. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.refrigeration_system.json +0 -8
  238. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.spc_typ.json +413 -401
  239. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.unitary_acs.json +69 -0
  240. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirLoopHVAC.rb +42 -53
  241. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +3 -2
  242. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.CoolingTower.rb +5 -8
  243. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.FanVariableVolume.rb +1 -1
  244. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Space.rb +6 -4
  245. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.rb +4 -0
  246. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/comstock_ashrae_90_1_2010.rb +4 -0
  247. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/ashrae_90_1.schedules.json +696 -2938
  248. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/comstock_ashrae_90_1_2010.ext_ltg.json +1 -1
  249. 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 +129 -129
  250. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.energy_recovery.json +210 -42
  251. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.furnaces.json +26 -0
  252. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.prototype_inputs.json +11 -11
  253. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.refrigeration_system.json +0 -8
  254. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.spc_typ.json +460 -320
  255. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.unitary_acs.json +69 -0
  256. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirLoopHVAC.rb +45 -51
  257. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +3 -2
  258. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.CoolingTower.rb +5 -8
  259. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.CoolingTowerVariableSpeed.rb +2 -3
  260. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.FanVariableVolume.rb +2 -2
  261. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Space.rb +8 -5
  262. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.ThermalZone.rb +2 -1
  263. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.WaterHeaterMixed.rb +1 -1
  264. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.ZoneHVACComponent.rb +1 -0
  265. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.rb +4 -0
  266. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/comstock_ashrae_90_1_2013.rb +4 -0
  267. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/ashrae_90_1.schedules.json +696 -2938
  268. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/comstock_ashrae_90_1_2013.ext_ltg.json +1 -1
  269. 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 +121 -121
  270. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.energy_recovery.json +420 -84
  271. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.furnaces.json +26 -0
  272. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.prototype_inputs.json +12 -12
  273. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.refrigeration_system.json +0 -8
  274. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.spc_typ.json +475 -335
  275. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.unitary_acs.json +69 -0
  276. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirLoopHVAC.rb +40 -50
  277. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +3 -2
  278. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.CoolingTower.rb +5 -8
  279. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.CoolingTowerVariableSpeed.rb +2 -3
  280. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.FanVariableVolume.rb +2 -2
  281. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Space.rb +8 -5
  282. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.ThermalZone.rb +2 -1
  283. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.ZoneHVACComponent.rb +1 -0
  284. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.rb +4 -0
  285. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/comstock_ashrae_90_1_2016.rb +4 -0
  286. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/ashrae_90_1.schedules.json +696 -2938
  287. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/comstock_ashrae_90_1_2016.ext_ltg.json +1 -1
  288. 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 +152 -128
  289. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.energy_recovery.json +488 -84
  290. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.furnaces.json +26 -0
  291. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.spc_typ.json +47 -47
  292. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.unitary_acs.json +69 -0
  293. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +342 -56
  294. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +3 -2
  295. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTower.rb +5 -8
  296. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerVariableSpeed.rb +2 -3
  297. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.FanVariableVolume.rb +2 -2
  298. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +25 -5
  299. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ThermalZone.rb +2 -1
  300. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb +30 -0
  301. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.rb +4 -0
  302. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/comstock_ashrae_90_1_2019.rb +4 -0
  303. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/ashrae_90_1.schedules.json +696 -2938
  304. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/comstock_ashrae_90_1_2019.ext_ltg.json +1 -1
  305. 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 +151 -127
  306. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.boilers.json +1 -1
  307. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.energy_recovery.json +2307 -101
  308. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.furnaces.json +26 -0
  309. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.refrigeration_compressors.json +1 -1
  310. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.spc_typ.json +47 -47
  311. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.unitary_acs.json +69 -0
  312. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.curves.json +25 -0
  313. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.schedules.json +286 -224
  314. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/comstock_doe_ref_1980_2004.rb +4 -0
  315. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/ashrae_90_1.schedules.json +696 -2938
  316. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/comstock_doe_ref_1980_2004.ext_ltg.json +1 -1
  317. 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 +126 -126
  318. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.furnaces.json +26 -0
  319. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.prototype_inputs.json +11 -11
  320. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.refrigeration_system.json +0 -8
  321. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.spc_typ.json +405 -393
  322. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirLoopHVAC.rb +15 -11
  323. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.rb +1 -1
  324. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.PlantLoop.rb +3 -0
  325. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.rb +4 -0
  326. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/comstock_doe_ref_pre_1980.rb +4 -0
  327. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/data/ashrae_90_1.schedules.json +696 -2938
  328. 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 +121 -121
  329. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.furnaces.json +37 -0
  330. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.prototype_inputs.json +11 -11
  331. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.refrigeration_system.json +0 -8
  332. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.spc_typ.json +403 -391
  333. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirLoopHVAC.rb +15 -11
  334. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.rb +1 -1
  335. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.PlantLoop.rb +3 -0
  336. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.rb +4 -0
  337. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/data/nrel_zne_ready_2017.furnaces.json +15 -0
  338. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +64 -42
  339. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +3 -2
  340. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.CoolingTower.rb +5 -8
  341. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.CoolingTowerVariableSpeed.rb +2 -3
  342. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.FanVariableVolume.rb +2 -2
  343. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.HeatExchangerSensLat.rb +1 -1
  344. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.Model.rb +1 -1
  345. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.PlantLoop.rb +4 -1
  346. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.Space.rb +5 -3
  347. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.ZoneHVACComponent.rb +3 -0
  348. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.rb +4 -0
  349. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/data/ze_aedg_multifamily.furnaces.json +15 -0
  350. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirLoopHVAC.rb +61 -36
  351. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +3 -2
  352. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.CoolingTower.rb +5 -8
  353. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.CoolingTowerVariableSpeed.rb +2 -3
  354. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.FanVariableVolume.rb +2 -2
  355. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.HeatExchangerSensLat.rb +1 -1
  356. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.Model.rb +1 -1
  357. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.PlantLoop.rb +4 -1
  358. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.Space.rb +6 -4
  359. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.ZoneHVACComponent.rb +3 -0
  360. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.rb +4 -0
  361. data/lib/openstudio-standards/standards/cbes/cbes.AirLoopHVAC.rb +20 -14
  362. data/lib/openstudio-standards/standards/cbes/cbes.PlantLoop.rb +3 -0
  363. data/lib/openstudio-standards/standards/cbes/cbes.rb +4 -0
  364. data/lib/openstudio-standards/standards/cbes/cbes_pre_1978/cbes_pre_1978.rb +4 -0
  365. data/lib/openstudio-standards/standards/cbes/cbes_t24_1978/cbes_t24_1978.rb +4 -0
  366. data/lib/openstudio-standards/standards/cbes/cbes_t24_1992/cbes_t24_1992.rb +4 -0
  367. data/lib/openstudio-standards/standards/cbes/cbes_t24_2001/cbes_t24_2001.rb +4 -0
  368. data/lib/openstudio-standards/standards/cbes/cbes_t24_2005/cbes_t24_2005.rb +4 -0
  369. data/lib/openstudio-standards/standards/cbes/cbes_t24_2008/cbes_t24_2008.rb +4 -0
  370. data/lib/openstudio-standards/standards/deer/deer.AirLoopHVAC.rb +10 -5
  371. data/lib/openstudio-standards/standards/deer/deer.PlanarSurface.rb +1 -1
  372. data/lib/openstudio-standards/standards/deer/deer.rb +4 -0
  373. data/lib/openstudio-standards/standards/deer/deer_1985/comstock_deer_1985/comstock_deer_1985.rb +4 -0
  374. data/lib/openstudio-standards/standards/deer/deer_1985/comstock_deer_1985/data/comstock_deer_1985.ext_ltg.json +2 -2
  375. data/lib/openstudio-standards/standards/deer/deer_1985/deer_1985.rb +4 -0
  376. data/lib/openstudio-standards/standards/deer/deer_1996/comstock_deer_1996/comstock_deer_1996.rb +4 -0
  377. data/lib/openstudio-standards/standards/deer/deer_1996/comstock_deer_1996/data/comstock_deer_1996.ext_ltg.json +2 -2
  378. data/lib/openstudio-standards/standards/deer/deer_1996/deer_1996.rb +4 -0
  379. data/lib/openstudio-standards/standards/deer/deer_2003/comstock_deer_2003/comstock_deer_2003.rb +4 -0
  380. data/lib/openstudio-standards/standards/deer/deer_2003/comstock_deer_2003/data/comstock_deer_2003.ext_ltg.json +2 -2
  381. data/lib/openstudio-standards/standards/deer/deer_2003/deer_2003.rb +4 -0
  382. data/lib/openstudio-standards/standards/deer/deer_2007/comstock_deer_2007/comstock_deer_2007.rb +4 -0
  383. data/lib/openstudio-standards/standards/deer/deer_2007/comstock_deer_2007/data/comstock_deer_2007.ext_ltg.json +2 -2
  384. data/lib/openstudio-standards/standards/deer/deer_2007/deer_2007.rb +4 -0
  385. data/lib/openstudio-standards/standards/deer/deer_2011/comstock_deer_2011/comstock_deer_2011.rb +4 -0
  386. data/lib/openstudio-standards/standards/deer/deer_2011/comstock_deer_2011/data/comstock_deer_2011.ext_ltg.json +2 -2
  387. data/lib/openstudio-standards/standards/deer/deer_2011/deer_2011.rb +4 -0
  388. data/lib/openstudio-standards/standards/deer/deer_2014/comstock_deer_2014/comstock_deer_2014.rb +4 -0
  389. data/lib/openstudio-standards/standards/deer/deer_2014/comstock_deer_2014/data/comstock_deer_2014.ext_ltg.json +2 -2
  390. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.Space.rb +5 -3
  391. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.rb +4 -0
  392. data/lib/openstudio-standards/standards/deer/deer_2015/comstock_deer_2015/comstock_deer_2015.rb +4 -0
  393. data/lib/openstudio-standards/standards/deer/deer_2015/comstock_deer_2015/data/comstock_deer_2015.ext_ltg.json +2 -2
  394. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.Space.rb +5 -3
  395. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.rb +4 -0
  396. data/lib/openstudio-standards/standards/deer/deer_2017/comstock_deer_2017/comstock_deer_2017.rb +4 -0
  397. data/lib/openstudio-standards/standards/deer/deer_2017/comstock_deer_2017/data/comstock_deer_2017.ext_ltg.json +2 -2
  398. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.Space.rb +5 -3
  399. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.rb +4 -0
  400. data/lib/openstudio-standards/standards/deer/deer_2020/comstock_deer_2020/comstock_deer_2020.rb +4 -0
  401. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.AirLoopHVAC.rb +9 -5
  402. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.FanVariableVolume.rb +3 -0
  403. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.Space.rb +5 -3
  404. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.rb +4 -0
  405. data/lib/openstudio-standards/standards/deer/deer_2025/comstock_deer_2025/comstock_deer_2025.rb +4 -0
  406. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.AirLoopHVAC.rb +9 -5
  407. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.FanVariableVolume.rb +3 -0
  408. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.Space.rb +5 -3
  409. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.rb +4 -0
  410. data/lib/openstudio-standards/standards/deer/deer_2030/comstock_deer_2030/comstock_deer_2030.rb +4 -0
  411. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.AirLoopHVAC.rb +9 -5
  412. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.FanVariableVolume.rb +3 -0
  413. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.Space.rb +5 -3
  414. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.rb +4 -0
  415. data/lib/openstudio-standards/standards/deer/deer_2035/comstock_deer_2035/comstock_deer_2035.rb +4 -0
  416. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.AirLoopHVAC.rb +9 -5
  417. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.FanVariableVolume.rb +3 -0
  418. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.Space.rb +5 -3
  419. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.rb +4 -0
  420. data/lib/openstudio-standards/standards/deer/deer_2040/comstock_deer_2040/comstock_deer_2040.rb +4 -0
  421. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.AirLoopHVAC.rb +9 -5
  422. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.FanVariableVolume.rb +3 -0
  423. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.Space.rb +5 -3
  424. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.rb +4 -0
  425. data/lib/openstudio-standards/standards/deer/deer_2045/comstock_deer_2045/comstock_deer_2045.rb +4 -0
  426. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.AirLoopHVAC.rb +9 -5
  427. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.FanVariableVolume.rb +3 -0
  428. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.Space.rb +5 -3
  429. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.rb +4 -0
  430. data/lib/openstudio-standards/standards/deer/deer_2050/comstock_deer_2050/comstock_deer_2050.rb +4 -0
  431. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.AirLoopHVAC.rb +9 -5
  432. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.FanVariableVolume.rb +3 -0
  433. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.Space.rb +5 -3
  434. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.rb +4 -0
  435. data/lib/openstudio-standards/standards/deer/deer_2055/comstock_deer_2055/comstock_deer_2055.rb +4 -0
  436. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.AirLoopHVAC.rb +9 -5
  437. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.FanVariableVolume.rb +3 -0
  438. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.Space.rb +5 -3
  439. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.rb +4 -0
  440. data/lib/openstudio-standards/standards/deer/deer_2060/comstock_deer_2060/comstock_deer_2060.rb +4 -0
  441. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.AirLoopHVAC.rb +9 -5
  442. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.FanVariableVolume.rb +3 -0
  443. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.Space.rb +5 -3
  444. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.rb +4 -0
  445. data/lib/openstudio-standards/standards/deer/deer_2065/comstock_deer_2065/comstock_deer_2065.rb +4 -0
  446. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.AirLoopHVAC.rb +9 -5
  447. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.FanVariableVolume.rb +3 -0
  448. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.Space.rb +5 -3
  449. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.rb +4 -0
  450. data/lib/openstudio-standards/standards/deer/deer_2070/comstock_deer_2070/comstock_deer_2070.rb +4 -0
  451. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.AirLoopHVAC.rb +9 -5
  452. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.FanVariableVolume.rb +3 -0
  453. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.Space.rb +5 -3
  454. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.rb +4 -0
  455. data/lib/openstudio-standards/standards/deer/deer_2075/comstock_deer_2075/comstock_deer_2075.rb +4 -0
  456. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.AirLoopHVAC.rb +9 -5
  457. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.FanVariableVolume.rb +3 -0
  458. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.Space.rb +5 -3
  459. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.rb +4 -0
  460. data/lib/openstudio-standards/standards/deer/deer_pre_1975/comstock_deer_pre_1975/comstock_deer_pre_1975.rb +4 -0
  461. data/lib/openstudio-standards/standards/deer/deer_pre_1975/comstock_deer_pre_1975/data/comstock_deer_pre_1975.ext_ltg.json +2 -2
  462. data/lib/openstudio-standards/standards/deer/deer_pre_1975/deer_pre_1975.rb +4 -0
  463. data/lib/openstudio-standards/standards/icc_iecc/icc_iecc_2015/icc_iecc_2015.rb +4 -0
  464. data/lib/openstudio-standards/standards/necb/BTAP1980TO2010/btap_1980to2010.rb +6 -28
  465. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/btap_pre1980.rb +25 -110
  466. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/building_envelope.rb +45 -60
  467. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_3_and_8_single_speed.rb +19 -23
  468. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_4.rb +84 -83
  469. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +52 -47
  470. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_systems.rb +43 -40
  471. data/lib/openstudio-standards/standards/necb/ECMS/data/boiler_set.json +18 -0
  472. data/lib/openstudio-standards/standards/necb/ECMS/data/chiller_set.json +211 -0
  473. data/lib/openstudio-standards/standards/necb/ECMS/data/curves.json +1195 -20
  474. data/lib/openstudio-standards/standards/necb/ECMS/data/furnace_set.json +18 -0
  475. data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps.json +244 -182
  476. data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps_heating.json +232 -185
  477. data/lib/openstudio-standards/standards/necb/ECMS/data/shw_set.json +20 -2
  478. data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +18 -25
  479. data/lib/openstudio-standards/standards/necb/ECMS/erv.rb +12 -13
  480. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +1647 -466
  481. data/lib/openstudio-standards/standards/necb/ECMS/loads.rb +93 -0
  482. data/lib/openstudio-standards/standards/necb/ECMS/nv.rb +40 -47
  483. data/lib/openstudio-standards/standards/necb/ECMS/pv_ground.rb +26 -25
  484. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +303 -305
  485. data/lib/openstudio-standards/standards/necb/NECB2011/beps_compliance_path.rb +45 -45
  486. data/lib/openstudio-standards/standards/necb/NECB2011/building_envelope.rb +90 -120
  487. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Hospital.osm +1176 -1115
  488. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LowriseApartment.osm +8279 -28923
  489. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +1173 -1173
  490. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_multi_speed.rb +15 -13
  491. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_single_speed.rb +32 -29
  492. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_2_and_5.rb +25 -26
  493. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +14 -14
  494. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +24 -29
  495. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +85 -84
  496. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +41 -42
  497. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +209 -197
  498. data/lib/openstudio-standards/standards/necb/NECB2011/lighting.rb +87 -82
  499. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +510 -406
  500. data/lib/openstudio-standards/standards/necb/NECB2011/nv.md +3 -3
  501. data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +686 -683
  502. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +129 -82
  503. data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +1608 -1608
  504. data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +25 -18
  505. data/lib/openstudio-standards/standards/necb/NECB2015/lighting.rb +73 -67
  506. data/lib/openstudio-standards/standards/necb/NECB2015/necb_2015.rb +18 -22
  507. data/lib/openstudio-standards/standards/necb/NECB2015/qaqc/necb_2015_qaqc.rb +59 -63
  508. data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +1608 -1608
  509. data/lib/openstudio-standards/standards/necb/NECB2017/hvac_systems.rb +1 -4
  510. data/lib/openstudio-standards/standards/necb/NECB2017/necb_2017.rb +10 -14
  511. data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +779 -0
  512. data/lib/openstudio-standards/standards/necb/NECB2020/data/boilers.json +122 -0
  513. data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +335 -0
  514. data/lib/openstudio-standards/standards/necb/NECB2020/data/constants.json +13 -0
  515. data/lib/openstudio-standards/standards/necb/NECB2020/data/furnaces.json +41 -0
  516. data/lib/openstudio-standards/standards/necb/NECB2020/data/heat_pumps.json +452 -0
  517. data/lib/openstudio-standards/standards/necb/NECB2020/data/heat_pumps_heating.json +164 -0
  518. data/lib/openstudio-standards/standards/necb/NECB2020/data/heat_rejection.json +228 -0
  519. data/lib/openstudio-standards/standards/necb/NECB2020/data/led_lighting_data.json +2883 -0
  520. data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +25851 -0
  521. data/lib/openstudio-standards/standards/necb/NECB2020/data/surface_thermal_transmittance.json +60 -0
  522. data/lib/openstudio-standards/standards/necb/NECB2020/data/unitary_acs.json +585 -0
  523. data/lib/openstudio-standards/standards/necb/NECB2020/necb_2020.rb +175 -0
  524. data/lib/openstudio-standards/standards/necb/common/bc_step_code_indicators.md +10 -0
  525. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +1963 -0
  526. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +410 -0
  527. data/lib/openstudio-standards/standards/necb/common/neb_end_use_prices.csv +42 -0
  528. data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +28705 -0
  529. data/lib/openstudio-standards/standards/necb/common/phius.md +23 -0
  530. data/lib/openstudio-standards/standards/necb/common/space_type_upgrade_map.json +1158 -386
  531. data/lib/openstudio-standards/standards/oeesc/oeesc_2014/oeesc_2014.rb +4 -0
  532. data/lib/openstudio-standards/standards/standard.rb +2 -1
  533. data/lib/openstudio-standards/utilities/define_thermal_zone_and_mulitpliers.rb +1 -1
  534. data/lib/openstudio-standards/utilities/logging.rb +6 -0
  535. data/lib/openstudio-standards/utilities/simulation.rb +30 -14
  536. data/lib/openstudio-standards/utilities/{speacetype_map_converter.rb → spacetype_map_converter.rb} +0 -0
  537. data/lib/openstudio-standards/utilities/sqlfile.rb +112 -71
  538. data/lib/openstudio-standards/version.rb +2 -2
  539. data/lib/openstudio-standards/weather/Weather.Model.rb +209 -9
  540. data/lib/openstudio-standards/weather/Weather.stat_file.rb +1 -1
  541. data/lib/openstudio-standards.rb +9 -0
  542. metadata +106 -205
  543. data/data/standards/OpenStudio_Standards-ashrae_90_1-ALL-comstock(space_types).xlsx +0 -0
  544. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.boilers.json +0 -49
  545. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.chillers.json +0 -293
  546. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_properties.json +0 -25426
  547. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_sets.json +0 -1600
  548. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.economizers.json +0 -564
  549. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.elevators.json +0 -349
  550. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.ext_ltg.json +0 -164
  551. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.ground_temperatures.json +0 -10663
  552. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.heat_pumps.json +0 -508
  553. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.heat_pumps_heating.json +0 -156
  554. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.heat_rejection.json +0 -44
  555. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.motors.json +0 -184
  556. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.prototype_inputs.json +0 -3094
  557. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.ref_cases.json +0 -829
  558. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.ref_lnup.json +0 -562
  559. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.refrigeration_compressors.json +0 -52
  560. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.refrigeration_condenser.json +0 -220
  561. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.refrigeration_system.json +0 -156
  562. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.refrigeration_walkins.json +0 -1316
  563. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.spc_typ.json +0 -21446
  564. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.unitary_acs.json +0 -554
  565. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.water_heaters.json +0 -68
  566. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.water_source_heat_pumps.json +0 -28
  567. data/data/standards/export/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.water_source_heat_pumps_heating.json +0 -12
  568. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.boilers.json +0 -49
  569. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.chillers.json +0 -293
  570. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.construction_properties.json +0 -12487
  571. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.construction_sets.json +0 -1600
  572. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.economizers.json +0 -564
  573. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.elevators.json +0 -349
  574. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.ext_ltg.json +0 -164
  575. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.ground_temperatures.json +0 -10663
  576. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.heat_pumps.json +0 -466
  577. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.heat_pumps_heating.json +0 -137
  578. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.heat_rejection.json +0 -44
  579. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.motors.json +0 -184
  580. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.prototype_inputs.json +0 -3094
  581. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.ref_cases.json +0 -829
  582. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.ref_lnup.json +0 -562
  583. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.refrigeration_compressors.json +0 -52
  584. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.refrigeration_condenser.json +0 -220
  585. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.refrigeration_system.json +0 -156
  586. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.refrigeration_walkins.json +0 -1316
  587. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.spc_typ.json +0 -21380
  588. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.unitary_acs.json +0 -554
  589. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.water_heaters.json +0 -68
  590. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.water_source_heat_pumps.json +0 -28
  591. data/data/standards/export/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.water_source_heat_pumps_heating.json +0 -12
  592. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.boilers.json +0 -49
  593. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.chillers.json +0 -395
  594. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.construction_properties.json +0 -12487
  595. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.construction_sets.json +0 -1600
  596. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.economizers.json +0 -592
  597. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.elevators.json +0 -349
  598. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.energy_recovery.json +0 -550
  599. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.ext_ltg.json +0 -164
  600. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.ground_temperatures.json +0 -10663
  601. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.heat_pumps.json +0 -466
  602. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.heat_pumps_heating.json +0 -137
  603. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.heat_rejection.json +0 -44
  604. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.motors.json +0 -238
  605. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.prototype_inputs.json +0 -3094
  606. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.ref_cases.json +0 -829
  607. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.ref_lnup.json +0 -562
  608. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.refrigeration_compressors.json +0 -52
  609. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.refrigeration_condenser.json +0 -220
  610. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.refrigeration_system.json +0 -156
  611. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.refrigeration_walkins.json +0 -1316
  612. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.spc_typ.json +0 -21548
  613. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.unitary_acs.json +0 -554
  614. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.water_heaters.json +0 -68
  615. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.water_source_heat_pumps.json +0 -28
  616. data/data/standards/export/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.water_source_heat_pumps_heating.json +0 -12
  617. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.boilers.json +0 -64
  618. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.chillers.json +0 -871
  619. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_properties.json +0 -12487
  620. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_sets.json +0 -1600
  621. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.economizers.json +0 -592
  622. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.elevators.json +0 -349
  623. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.energy_recovery.json +0 -1096
  624. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.ext_ltg.json +0 -164
  625. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.ground_temperatures.json +0 -10663
  626. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.heat_pumps.json +0 -886
  627. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.heat_pumps_heating.json +0 -194
  628. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.heat_rejection.json +0 -44
  629. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.motors.json +0 -247
  630. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.prototype_inputs.json +0 -3094
  631. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.ref_cases.json +0 -829
  632. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.ref_lnup.json +0 -562
  633. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.refrigeration_compressors.json +0 -52
  634. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.refrigeration_condenser.json +0 -220
  635. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.refrigeration_system.json +0 -156
  636. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.refrigeration_walkins.json +0 -1316
  637. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.spc_typ.json +0 -22079
  638. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.unitary_acs.json +0 -994
  639. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.water_heaters.json +0 -68
  640. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.water_source_heat_pumps.json +0 -28
  641. data/data/standards/export/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.water_source_heat_pumps_heating.json +0 -12
  642. data/lib/openstudio-standards/utilities/convert_costing_constructions.rb +0 -105
@@ -0,0 +1,1963 @@
1
+ class BTAPData
2
+ attr_accessor :osa_file
3
+ attr_accessor :osw_file
4
+ attr_accessor :osm_file
5
+ attr_accessor :sqlite_file
6
+ attr_accessor :btap_data
7
+
8
+ def initialize(model:, runner: nil, cost_result:, baseline_cost_equipment_total_cost_per_m_sq: -1.0,
9
+ baseline_cost_utility_neb_total_cost_per_m_sq: -1.0, baseline_energy_eui_total_gj_per_m_sq: -1.0, qaqc:)
10
+ @model = model
11
+ @error_warning = []
12
+ # sets sql file.
13
+ set_sql_file(model.sqlFile)
14
+ @standard = Standard.build('NECB2011')
15
+ @btap_data = {}
16
+ @btap_results_version = 1.00
17
+ @neb_prices_csv_file_name = File.join(__dir__, 'neb_end_use_prices.csv')
18
+ @necb_reference_runs_csv_file_name = File.join(__dir__, 'necb_reference_runs.csv')
19
+
20
+ # Conditioned floor area is used so much. May as well make it a object variable.
21
+ # setup the queries
22
+ command = "SELECT Value
23
+ FROM TabularDataWithStrings
24
+ WHERE ReportName='AnnualBuildingUtilityPerformanceSummary'
25
+ AND ReportForString='Entire Facility'
26
+ AND TableName='Building Area'
27
+ AND RowName = 'Net Conditioned Building Area'
28
+ AND ColumnName='Area'"
29
+ area = @sqlite_file.get.execAndReturnFirstDouble(command)
30
+ # make sure all the data are available
31
+ if area.empty?
32
+ @conditioned_floor_area_m_sq = 0.0
33
+ else
34
+ @conditioned_floor_area_m_sq = area.get
35
+ end
36
+
37
+
38
+ @btap_data['simulation_btap_data_version'] = '0.1'
39
+ # @btap_data["simulation_openstudio_version"] = open("| \"#{OpenStudio.getOpenStudioCLI}\" openstudio_version").read().strip
40
+ # @btap_data["simulation_energyplus_version"] = open("| \"#{OpenStudio.getOpenStudioCLI}\" energyplus_version").read().strip
41
+ @btap_data['simulation_os_standards_revision'] = OpenstudioStandards.git_revision
42
+ @btap_data['simulation_os_standards_version'] = OpenstudioStandards::VERSION
43
+ @btap_data['simulation_date'] = Time.now
44
+ @btap_data.merge!(building_data)
45
+ @btap_data.merge!(building_costing_data(cost_result)) unless cost_result.nil?
46
+ @btap_data.merge!(climate_data)
47
+ @btap_data.merge!(service_water_heating_data)
48
+ @btap_data.merge!(energy_eui_data)
49
+ @btap_data.merge!(energy_peak_data)
50
+ @btap_data.merge!(utility(model))
51
+ @btap_data.merge!(unmet_hours(model))
52
+
53
+ # Data in tables...
54
+ @btap_data.merge!('measures_data_table' => measures_data_table(runner)) unless runner.nil?
55
+ @btap_data.merge!('envelope_exterior_surface_table' => envelope_exterior_surface_table)
56
+ @btap_data.merge!('space_table' => space_table(model, cost_result))
57
+ @btap_data.merge!('space_type_table' => space_type_table(model))
58
+ # This does not work with the new VRF or CCASHP systems. Commenting it for now.
59
+ # @btap_data.merge!({'zone_table' => thermal_zones_table(model, cost_result)['table']})
60
+ @btap_data.merge!('zone_equip_table' => thermal_zones_equipment_table(model))
61
+ # This does not work with the new VRF or CCASHP systems. Commenting it for now.
62
+ # @btap_data.merge!({'air_loop_table' => air_loops_table(model, cost_result)})
63
+ # @btap_data.merge!({'sql_raw_data' => sql_data_tables(model)})
64
+ @btap_data.merge!('eplusout_err_table' => eplusout_err_table(model))
65
+
66
+ # Remainder of costing data in separate tables:
67
+ @btap_data.merge!('envelope_construction_cost_table' => cost_result['envelope']['construction_costs']) unless cost_result.nil?
68
+ @btap_data.merge!('lighting_fixture_cost_table' => cost_result['lighting']['fixture_report']) unless cost_result.nil?
69
+ ideal_air = true
70
+ model.getThermalZones.each do |zone|
71
+ ideal_air = false if zone.useIdealAirLoads == false
72
+ end
73
+ unless ideal_air
74
+ @btap_data.merge!('h_and_c_plant_equipment_cost_table' => cost_result['heating_and_cooling']['plant_equipment']) unless cost_result.nil?
75
+ @btap_data.merge!('h_and_c_plant_zonal_systems_cost_table' => cost_result['heating_and_cooling']['zonal_systems']) unless cost_result.nil?
76
+ # This does not work with the new VRF or CCASHP systems. Commenting it for now.
77
+ # @btap_data.merge!('system_coils_cost_table' => coil_cost_table(cost_result))
78
+ # This does not work with the new VRF or CCASHP systems. Commenting it for now.
79
+ # @btap_data.merge!('terminal_VAV_cost_table' => terminal_VAV_cost_table(cost_result))
80
+ # This does not work with the new VRF or CCASHP systems. Commenting it for now.
81
+ # @btap_data.merge!('trunk_ducts_cost_table' => trunk_ducts_cost_table(cost_result))
82
+ end
83
+ # calculate energy demands and peak loads calculations as per PHIUS and NECB and compare them
84
+ phius_performance_indicators(model)
85
+ # The below method calculates energy performance indicators (i.e. TEDI and MEUI) as per BC Energy Step Code
86
+ bc_energy_step_code_performance_indicators
87
+
88
+ measure_metrics(qaqc)
89
+ @btap_data
90
+ end
91
+
92
+ # Oct-2019 JTB: This function must be passed a hash and will flatten mixtures of hashes
93
+ # and arrays of hashes. Embedded arrays are enumerated (starting at 1).
94
+ def flatten_mix(hash)
95
+ hash.each_with_object({}) do |(k, v), h|
96
+ if v.is_a?(Hash)
97
+ flatten_mix(v).map do |h_k, h_v|
98
+ h["#{k}.#{h_k}".to_sym] = h_v
99
+ end
100
+ elsif v.is_a?(Array)
101
+ v.map.with_index do |e, ndx|
102
+ if e.is_a?(Hash)
103
+ flatten_mix(e).map do |e_k, e_v|
104
+ h["#{k}.#{e_k}.#{ndx + 1}".to_sym] = e_v
105
+ end
106
+ # if there is another array within the array v, flatten more
107
+ # but this is as deep as we go with embedded arrays!
108
+ elsif e.is_a?(Array)
109
+ e.map.with_index do |e1, ndx1|
110
+ if e1.is_a?(Hash)
111
+ flatten_mix(e1).map do |e1_k, e1_v|
112
+ h["#{k}.#{e1_k}.#{ndx1 + 1}".to_sym] = e1_v
113
+ end
114
+ else
115
+ # Stop flattening here!
116
+ h[k] = v
117
+ end
118
+ end
119
+ else
120
+ h[k] = v
121
+ end
122
+ end
123
+ else
124
+ h[k] = v
125
+ end
126
+ end
127
+ end
128
+
129
+ # General Building Data that there is alway either zero of 1 of.
130
+ def building_data
131
+ # Store Building data.
132
+ building_data = {}
133
+ building_data['bldg_name'] = @model.building.get.name.get
134
+ building_data['bldg_conditioned_floor_area_m_sq'] = @conditioned_floor_area_m_sq
135
+ building_data['bldg_exterior_area_m_sq'] = @model.building.get.exteriorSurfaceArea # m_sq
136
+ building_data['bldg_volume_m_cu'] = @model.building.get.airVolume # m_cu
137
+ building_data['bldg_standards_template'] = @model.building.get.standardsTemplate.empty? ? nil : @model.building.get.standardsTemplate.get
138
+ building_data['bldg_standards_building_type'] = @model.building.get.standardsBuildingType.empty? ? nil : @model.building.get.standardsBuildingType.get
139
+ building_data['bldg_standards_number_of_stories'] = @model.building.get.standardsNumberOfStories.empty? ? nil : @model.building.get.standardsNumberOfStories.get
140
+ building_data['bldg_standards_number_of_above_ground_stories'] = @model.building.get.standardsNumberOfAboveGroundStories.empty? ? nil : @model.building.get.standardsNumberOfAboveGroundStories.get
141
+ building_data['bldg_standards_number_of_living_units'] = @model.building.get.standardsNumberOfLivingUnits.empty? ? nil : @model.building.get.standardsNumberOfAboveGroundStories.get
142
+ building_data['bldg_nominal_floor_to_ceiling_height'] = @model.building.get.nominalFloortoCeilingHeight.empty? ? nil : @model.building.get.nominalFloortoCeilingHeight.get
143
+ building_data['bldg_nominal_floor_to_floor_height'] = @model.building.get.nominalFloortoFloorHeight.empty? ? nil : @model.building.get.nominalFloortoFloorHeight.get
144
+ building_data['bldg_surface_to_volume_ratio'] = @model.building.get.exteriorSurfaceArea / @model.building.get.airVolume
145
+ building_data['bldg_fdwr'] = (BTAP::Geometry.get_fwdr(@model) * 100.0).round(1)
146
+ building_data['bldg_srr'] = (BTAP::Geometry.get_srr(@model) * 100.0).round(1)
147
+
148
+ return building_data
149
+ end
150
+
151
+ def building_costing_data(cost_result)
152
+ building_data = {}
153
+ building_data['cost_rs_means_prov'] = cost_result['rs_means_prov']
154
+ building_data['cost_rs_means_city'] = cost_result['rs_means_city']
155
+ building_data['cost_equipment_envelope_total_cost_per_m_sq'] = (cost_result['totals']['envelope']) / @conditioned_floor_area_m_sq
156
+ building_data['cost_equipment_lighting_total_cost_per_m_sq'] = (cost_result['totals']['lighting']) / @conditioned_floor_area_m_sq
157
+ building_data['cost_equipment_heating_and_cooling_total_cost_per_m_sq'] = (cost_result['totals']['heating_and_cooling']) / @conditioned_floor_area_m_sq
158
+ building_data['cost_equipment_shw_total_cost_per_m_sq'] = (cost_result['totals']['shw']) / @conditioned_floor_area_m_sq
159
+ building_data['cost_equipment_ventilation_total_cost_per_m_sq'] = (cost_result['totals']['ventilation']) / @conditioned_floor_area_m_sq
160
+ building_data['cost_equipment_total_cost_per_m_sq'] = (cost_result['totals']['grand_total']) / @conditioned_floor_area_m_sq
161
+ # building_data.merge!(cost_result['envelope'].select{|k,v| k!='construction_costs' && k!='total_envelope_cost'})
162
+ # building_data.merge!(cost_result['shw'].select{|k,v| k!='shw_total'})
163
+ # building_data.merge!(flatten_mix(cost_result['ventilation'].select{|k,v| k=='mech_to_roof'.to_sym}))
164
+ return building_data
165
+ end
166
+
167
+ def envelope(model)
168
+ data = {}
169
+ # Get OSM surface information
170
+ surfaces = model.getSurfaces.sort
171
+ interior_surfaces = BTAP::Geometry::Surfaces.filter_by_boundary_condition(surfaces, ['Surface', 'Adiabatic'])
172
+ interior_floors = BTAP::Geometry::Surfaces.filter_by_surface_types(interior_surfaces, 'Floor')
173
+ outdoor_surfaces = BTAP::Geometry::Surfaces.filter_by_boundary_condition(surfaces, 'Outdoors')
174
+ outdoor_walls = BTAP::Geometry::Surfaces.filter_by_surface_types(outdoor_surfaces, 'Wall')
175
+ outdoor_roofs = BTAP::Geometry::Surfaces.filter_by_surface_types(outdoor_surfaces, 'RoofCeiling')
176
+ outdoor_floors = BTAP::Geometry::Surfaces.filter_by_surface_types(outdoor_surfaces, 'Floor')
177
+ outdoor_subsurfaces = BTAP::Geometry::Surfaces.get_subsurfaces_from_surfaces(outdoor_surfaces)
178
+ ground_surfaces = BTAP::Geometry::Surfaces.filter_by_boundary_condition(surfaces, 'Ground')
179
+ ground_walls = BTAP::Geometry::Surfaces.filter_by_surface_types(ground_surfaces, 'Wall')
180
+ ground_roofs = BTAP::Geometry::Surfaces.filter_by_surface_types(ground_surfaces, 'RoofCeiling')
181
+ ground_floors = BTAP::Geometry::Surfaces.filter_by_surface_types(ground_surfaces, 'Floor')
182
+ windows = BTAP::Geometry::Surfaces.filter_subsurfaces_by_types(outdoor_subsurfaces, ['FixedWindow', 'OperableWindow'])
183
+ skylights = BTAP::Geometry::Surfaces.filter_subsurfaces_by_types(outdoor_subsurfaces, ['Skylight', 'TubularDaylightDiffuser', 'TubularDaylightDome'])
184
+ doors = BTAP::Geometry::Surfaces.filter_subsurfaces_by_types(outdoor_subsurfaces, ['Door', 'GlassDoor'])
185
+ overhead_doors = BTAP::Geometry::Surfaces.filter_subsurfaces_by_types(outdoor_subsurfaces, ['OverheadDoor'])
186
+
187
+ # Get Areas
188
+ data['outdoor_walls_area_m_sq'] = outdoor_walls.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier }
189
+ data['outdoor_roofs_area_m_sq'] = outdoor_roofs.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier }
190
+ data['outdoor_floors_area_m_sq'] = outdoor_floors.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier }
191
+ data['ground_walls_area_m_sq'] = ground_walls.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier }
192
+ data['ground_roofs_area_m_sq'] = ground_roofs.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier }
193
+ data['ground_floors_area_m_sq'] = ground_floors.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier }
194
+ data['interior_floors_area_m_sq'] = interior_floors.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier }
195
+
196
+ # Subsurface areas
197
+ data['windows_area_m_sq'] = windows.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier * e.multiplier }
198
+ data['skylights_area_m_sq'] = skylights.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier * e.multiplier }
199
+ data['doors_area_m_sq'] = doors.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier * e.multiplier }
200
+ data['overhead_doors_area_m_sq'] = overhead_doors.inject(0) { |sum, e| sum + e.netArea * e.space.get.multiplier * e.multiplier }
201
+
202
+ # Total Building Ground Surface Area.
203
+ data['total_ground_area_m_sq'] = data['ground_walls_area_m_sq'] +
204
+ data['ground_roofs_area_m_sq'] +
205
+ data['ground_floors_area_m_sq']
206
+ # Total Building Outdoor Surface Area.
207
+ data['total_outdoor_area_m_sq'] = data['outdoor_walls_area_m_sq'] +
208
+ data['outdoor_roofs_area_m_sq'] +
209
+ data['outdoor_floors_area_m_sq'] +
210
+ data['windows_area_m_sq'] +
211
+ data['skylights_area_m_sq'] +
212
+ data['doors_area_m_sq'] +
213
+ data['overhead_doors_area_m_sq']
214
+
215
+ # Average Conductances by surface Type
216
+ data['outdoor_walls_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(outdoor_walls).round(4) if !outdoor_walls.empty?
217
+ data['outdoor_roofs_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(outdoor_roofs).round(4) if !outdoor_roofs.empty?
218
+ data['outdoor_floors_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(outdoor_floors).round(4) if !outdoor_floors.empty?
219
+ data['ground_walls_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(ground_walls).round(4) if !ground_walls.empty?
220
+ data['ground_roofs_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(ground_roofs).round(4) if !ground_roofs.empty?
221
+ data['ground_floors_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(ground_floors).round(4) if !ground_floors.empty?
222
+ data['windows_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(windows).round(4) if !windows.empty?
223
+ data['skylights_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(skylights).round(4) if !skylights.empty?
224
+ data['doors_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(doors).round(4) if !doors.empty?
225
+ data['overhead_doors_average_conductance_w_per_m_sq_k'] = BTAP::Geometry::Surfaces.get_weighted_average_surface_conductance(overhead_doors).round(4) if !overhead_doors.empty?
226
+
227
+ # #Average Conductances for building whole weight factors
228
+ !outdoor_walls.empty? ? o_wall_cond_weight = data['outdoor_walls_average_conductance_w_per_m_sq_k'] * data['outdoor_walls_area_m_sq'] : o_wall_cond_weight = 0
229
+ !outdoor_roofs.empty? ? o_roof_cond_weight = data['outdoor_roofs_average_conductance_w_per_m_sq_k'] * data['outdoor_roofs_area_m_sq'] : o_roof_cond_weight = 0
230
+ !outdoor_floors.empty? ? o_floor_cond_weight = data['outdoor_floors_average_conductance_w_per_m_sq_k'] * data['outdoor_floors_area_m_sq'] : o_floor_cond_weight = 0
231
+ !ground_walls.empty? ? g_wall_cond_weight = data['ground_walls_average_conductance_w_per_m_sq_k'] * data['ground_walls_area_m_sq'] : g_wall_cond_weight = 0
232
+ !ground_roofs.empty? ? g_roof_cond_weight = data['ground_roofs_average_conductance_w_per_m_sq_k'] * data['ground_roofs_area_m_sq'] : g_roof_cond_weight = 0
233
+ !ground_floors.empty? ? g_floor_cond_weight = data['ground_floors_average_conductance_w_per_m_sq_k'] * data['ground_floors_area_m_sq'] : g_floor_cond_weight = 0
234
+ !windows.empty? ? win_cond_weight = data['windows_average_conductance_w_per_m_sq_k'] * data['windows_area_m_sq'] : win_cond_weight = 0
235
+ # doors.size > 0 ? sky_cond_weight = data["skylights_average_conductance_w_per_m_sq_k"] * data["skylights_area_m_sq"] : sky_cond_weight = 0
236
+ if !doors.empty? && !data['skylights_average_conductance_w_per_m_sq_k'].nil? && !data['skylights_area_m_sq'].nil?
237
+ sky_cond_weight = data['skylights_average_conductance_w_per_m_sq_k'] * data['skylights_area_m_sq']
238
+ else
239
+ sky_cond_weight = 0
240
+ end
241
+ !overhead_doors.empty? ? door_cond_weight = data['doors_average_conductance_w_per_m_sq_k'] * data['doors_area_m_sq'] : door_cond_weight = 0
242
+ !overhead_doors.empty? ? overhead_door_cond_weight = data['overhead_doors_average_conductance_w_per_m_sq_k'] * data['overhead_doors_area_m_sq'] : overhead_door_cond_weight = 0
243
+
244
+ # Building Average Conductance
245
+ data['outdoor_average_conductance_w_per_m_sq_k'] = (
246
+ o_floor_cond_weight +
247
+ o_roof_cond_weight +
248
+ o_wall_cond_weight +
249
+ win_cond_weight +
250
+ sky_cond_weight +
251
+ door_cond_weight +
252
+ overhead_door_cond_weight) / data['total_outdoor_area_m_sq']
253
+
254
+ # Building Average Ground Conductance
255
+ data['ground_average_conductance_w_per_m_sq_k'] = (
256
+ g_floor_cond_weight +
257
+ g_roof_cond_weight +
258
+ g_wall_cond_weight) / data['total_ground_area_m_sq']
259
+
260
+ # Building Average Conductance
261
+ data['average_conductance_w_per_m_sq_k'] = (
262
+ (data['average_conductance_w_per_m_sq_k'] * data['total_ground_area_m_sq']) +
263
+ (data['outdoor_average_conductance_w_per_m_sq_k'] * data['total_outdoor_area_m_sq'])
264
+ ) /
265
+ (data['total_ground_area_m_sq'] + data['total_outdoor_area_m_sq'])
266
+ prefix = 'envel_'
267
+ return Hash[data.map { |k, v| ["#{prefix}_#{k}", v] }]
268
+ end
269
+
270
+ def envelope_summary(qaqc)
271
+ @btap_data['envelope-outdoor_walls_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:outdoor_walls_average_conductance_w_per_m2_k]
272
+ @btap_data['envelope-outdoor_roofs_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:outdoor_roofs_average_conductance_w_per_m2_k]
273
+ @btap_data['envelope-outdoor_floors_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:outdoor_floors_average_conductance_w_per_m2_k]
274
+ @btap_data['envelope-ground_walls_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:ground_walls_average_conductance_w_per_m2_k]
275
+ @btap_data['envelope-ground_roofs_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:ground_roofs_average_conductance_w_per_m2_k]
276
+ @btap_data['envelope-ground_floors_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:ground_floors_average_conductance_w_per_m2_k]
277
+ @btap_data['envelope-outdoor_windows_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:windows_average_conductance_w_per_m2_k]
278
+ @btap_data['envelope-outdoor_doors_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:doors_average_conductance_w_per_m2_k]
279
+ @btap_data['envelope-outdoor_overhead_doors_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:overhead_doors_average_conductance_w_per_m2_k]
280
+ @btap_data['envelope-skylights_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:skylights_average_conductance_w_per_m2_k]
281
+ end
282
+
283
+ def envelope_exterior_surface_table
284
+ surfaces = @model.getSurfaces.sort
285
+ outdoor_surfaces = BTAP::Geometry::Surfaces.filter_by_boundary_condition(surfaces, 'Outdoors')
286
+ ground_surfaces = BTAP::Geometry::Surfaces.filter_by_boundary_condition(surfaces, 'Ground')
287
+ exterior_opaque_surfaces = outdoor_surfaces + ground_surfaces
288
+ # outdoor_surfaces.each { |surface| puts surface.name}
289
+ # get surface table from sql
290
+ table = get_sql_table_to_json(@model, 'EnvelopeSummary', 'Entire Facility', 'Opaque Exterior')
291
+ raise('Could not get opaque surface table from E+ sql') if table.empty?
292
+
293
+ # add space name to table.
294
+ table['table'].each do |row|
295
+ surface = exterior_opaque_surfaces.detect { |curr_surface| curr_surface.name.get.downcase == row['name'].downcase }
296
+ raise("Could not find surface #{row['name'].downcase} in #{outdoor_surfaces.map { |curr_surface| curr_surface.name.get.downcase }}") if surface.nil?
297
+
298
+ row['os_type'] = surface.surfaceType
299
+ row['boundary_condition'] = surface.outsideBoundaryCondition
300
+ space_includes_surface = @model.getSpaces.detect { |space| space.surfaces.include?(surface) }
301
+ row['space_name'] = space_includes_surface.nil? || !space_includes_surface.name.is_initialized ? 'NA' : space_includes_surface.name.get
302
+ end
303
+ opaque = table
304
+
305
+ # Fenestrations
306
+ fenestrations = BTAP::Geometry::Surfaces.filter_subsurfaces_by_types(@model.getSubSurfaces.sort, ['GlassDoor', 'FixedWindow', 'OperableWindow', 'Skylight', 'TubularDaylightDiffuser', 'TubularDaylightDome'])
307
+ # get surface table from sql
308
+ table = get_sql_table_to_json(@model, 'EnvelopeSummary', 'Entire Facility', 'Exterior Fenestration')
309
+ # Exclude totals and averages by deleting row with that in their name.
310
+ table['table'].delete_if { |row| !!(row['name'] =~ /Total|Average/) }
311
+ raise('Could not get fenestration surface table from E+ sql') if table.empty?
312
+
313
+ # add space name to table.
314
+ table['table'].each do |row|
315
+ subsurface = fenestrations.detect { |surface| surface.name.get.downcase == row['name'].downcase }
316
+ raise("Could not find surface #{row['name'].downcase} in #{fenestrations.map { |surface| surface.name.get.downcase }}") if subsurface.nil?
317
+
318
+ row['os_type'] = subsurface.subSurfaceType
319
+ row['boundary_condition'] = subsurface.outsideBoundaryCondition
320
+ parent_surface = subsurface.surface.get
321
+ space_includes_surface = @model.getSpaces.detect { |space| space.surfaces.include?(parent_surface) }
322
+ row['space_name'] = space_includes_surface.nil? || !space_includes_surface.name.is_initialized ? 'NA' : space_includes_surface.name.get
323
+ end
324
+ glazing = table
325
+
326
+ # return as a single table.
327
+
328
+ return glazing['table'] + opaque['table']
329
+ end
330
+
331
+ def space_table(model, cost_result)
332
+ # Store Space data.
333
+ table = []
334
+ model.getSpaces.sort.each do |space|
335
+ spaceinfo = {}
336
+ table << spaceinfo
337
+ spaceinfo['thermal_zone_name'] = space.thermalZone.empty? ? 'None' : space.thermalZone.get.name.get # should be assigned a thermalzone name.
338
+ spaceinfo['space_name'] = space.name.get # name should be defined test
339
+ spaceinfo['multiplier'] = space.multiplier
340
+ spaceinfo['volume'] = space.volume # should be greater than zero
341
+ spaceinfo['exterior_wall_area'] = space.exteriorWallArea # just for information.
342
+ spaceinfo['space_type_name'] = space.spaceType.get.name.get unless space.spaceType.empty? # should have a space types name defined.
343
+ spaceinfo['breathing_zone_outdoor_airflow_vbz'] = -1
344
+ spaceinfo['infiltration_flow_per_m_sq'] = space.infiltrationDesignFlowPerExteriorSurfaceArea
345
+ spaceinfo['floor_area_m2'] = space.floorArea
346
+ spaceinfo['building_type'] = space.spaceType.get.standardsBuildingType.empty? ? 'None' : space.spaceType.get.standardsBuildingType.get
347
+ spaceinfo['is_conditioned'] = space.thermalZone.get.isConditioned.get unless space.thermalZone.empty? or space.thermalZone.get.isConditioned.empty?
348
+ # shw
349
+ spaceinfo['shw_peak_flow_rate_m_cu_per_s'] = 0
350
+ spaceinfo['shw_peak_flow_rate_per_floor_area_m_cu_per_s_per_m_sq'] = 0
351
+ space.waterUseEquipment.each do |equipment|
352
+ spaceinfo['shw_peak_flow_rate_m_cu_per_s'] += equipment.waterUseEquipmentDefinition.peakFlowRate
353
+ spaceinfo['shw_peak_flow_rate_per_floor_area_m_cu_per_s_per_m_sq'] += equipment.waterUseEquipmentDefinition.peakFlowRate / space.floorArea
354
+ area_per_occ = space.spaceType.get.getFloorAreaPerPerson(space.floorArea)
355
+ # Watt per person = m_cu/s/m_cu * 1000W/kW * (specific heat * dT) * m_sq/person
356
+ spaceinfo['shw_watts_per_person'] = spaceinfo['shw_peak_flow_rate_per_floor_area_m_cu_per_s_per_m_sq'] * 1000 * (4.19 * 44.4) * 1000 * area_per_occ
357
+ end
358
+ unless cost_result.nil?
359
+ # Including space level lighting costs in the existing space table...
360
+ spaceLgtInfo = cost_result['lighting']['space_report'].detect { |curr_spaceLgtInfo| curr_spaceLgtInfo['zone'].downcase == spaceinfo['thermal_zone_name'].downcase }
361
+ raise("Could not find zone name \"#{spaceinfo['thermal_zone_name']}\" in lighting space_report") if spaceLgtInfo.nil?
362
+
363
+ spaceinfo['space_type'] = spaceLgtInfo['space_type']
364
+ spaceinfo['fixture_type'] = spaceLgtInfo['fixture_type']
365
+ # Note spelling mistake of "description" in cost_result hash fixed below in copy
366
+ spaceinfo['fixture_description'] = spaceLgtInfo['fixture_desciption']
367
+ spaceinfo['height_avg_ft'] = spaceLgtInfo['height_avg_ft']
368
+ spaceinfo['floor_area_ft2'] = spaceLgtInfo['floor_area_ft2']
369
+ spaceinfo['lighting_cost'] = spaceLgtInfo['cost']
370
+ spaceinfo['lighting_cost_per_ft2'] = spaceLgtInfo['cost_per_ft2']
371
+ spaceinfo['lighting_note'] = spaceLgtInfo['note']
372
+ end
373
+ end
374
+ table.sort_by! { |spaceinfo| [spaceinfo['thermal_zone_name'], spaceinfo['space_name']] }
375
+ return table
376
+ end
377
+
378
+ def climate_data
379
+ # Store Geography Data
380
+ geography_data = {}
381
+ geography_data['location_necb_hdd'] = @standard.get_necb_hdd18(@model)
382
+ geography_data['location_weather_file'] = File.basename(@model.getWeatherFile.path.get.to_s)
383
+ geography_data['location_epw_cdd'] = BTAP::Environment::WeatherFile.new(@model.getWeatherFile.path.get.to_s).cdd18
384
+ geography_data['location_epw_hdd'] = BTAP::Environment::WeatherFile.new(@model.getWeatherFile.path.get.to_s).hdd18
385
+ geography_data['location_necb_climate_zone'] = @standard.get_climate_zone_name(geography_data['location_necb_hdd'])
386
+ geography_data['location_city'] = @model.getWeatherFile.city
387
+ geography_data['location_state_province_region'] = @model.getWeatherFile.stateProvinceRegion
388
+ geography_data['location_country'] = @model.getWeatherFile.country
389
+ geography_data['location_latitude'] = @model.getWeatherFile.latitude
390
+ geography_data['location_longitude'] = @model.getWeatherFile.longitude
391
+ return geography_data
392
+ end
393
+
394
+ def utility(model)
395
+ economics_data = {}
396
+ provinces_names_map = { 'QC' => 'Quebec',
397
+ 'NL' => 'Newfoundland and Labrador',
398
+ 'NS' => 'Nova Scotia',
399
+ 'PE' => 'Prince Edward Island',
400
+ 'ON' => 'Ontario',
401
+ 'MB' => 'Manitoba',
402
+ 'SK' => 'Saskatchewan',
403
+ 'AB' => 'Alberta',
404
+ 'BC' => 'British Columbia',
405
+ 'YT' => 'Yukon',
406
+ 'NT' => 'Northwest Territories',
407
+ 'NB' => 'New Brunswick',
408
+ 'NU' => 'Nunavut' }
409
+ building_type = 'Commercial'
410
+ province = provinces_names_map[model.getWeatherFile.stateProvinceRegion]
411
+ neb_eplus_fuel_map = { 'Electricity' => 'Electricity',
412
+ 'Natural Gas' => 'Gas',
413
+ 'Oil' => 'FuelOilNo2' }
414
+ economics_data['cost_utility_neb_total_cost_per_m_sq'] = 0.0
415
+ economics_data['cost_utility_ghg_total_kg_per_m_sq'] = 0.0
416
+ # Create a hash of the neb data.
417
+ neb_data = CSV.parse(File.read(@neb_prices_csv_file_name), headers: true, converters: :numeric).map(&:to_h)
418
+
419
+ neb_eplus_fuel_map.each do |neb_fuel, ep_fuel|
420
+ row = neb_data.detect do |data|
421
+ (data['building_type'] == building_type) &&
422
+ (data['province'] == province) &&
423
+ (data['fuel_type'] == neb_fuel)
424
+ end
425
+ neb_fuel_cost = row['2020']
426
+ fuel_consumption_gj = 0.0
427
+ if neb_fuel == 'Electricity' || neb_fuel == 'Natural Gas'
428
+ sql_command = "SELECT Value FROM tabulardatawithstrings
429
+ WHERE ReportName='EnergyMeters'
430
+ AND ReportForString='Entire Facility'
431
+ AND TableName='Annual and Peak Values - #{ep_fuel}'
432
+ AND RowName='#{ep_fuel}:Facility'
433
+ AND ColumnName='#{ep_fuel} Annual Value'
434
+ AND Units='GJ'"
435
+ fuel_consumption_gj = model.sqlFile.get.execAndReturnFirstDouble(sql_command).is_initialized ? model.sqlFile.get.execAndReturnFirstDouble(sql_command).get : 0.0
436
+ else
437
+ sql_command = " SELECT Value FROM tabulardatawithstrings
438
+ WHERE ReportName='EnergyMeters'
439
+ AND ReportForString='Entire Facility'
440
+ AND TableName='Annual and Peak Values - Other'
441
+ AND RowName='#{ep_fuel}:Facility'
442
+ AND ColumnName='Annual Value'
443
+ AND Units='GJ'"
444
+
445
+ fuel_consumption_gj = model.sqlFile.get.execAndReturnFirstDouble(sql_command).is_initialized ? model.sqlFile.get.execAndReturnFirstDouble(sql_command).get : 0.0
446
+ end
447
+
448
+ # Determine costs in $$
449
+ economics_data["cost_utility_neb_#{neb_fuel.downcase}_cost_per_m_sq"] = fuel_consumption_gj * neb_fuel_cost.to_f / @conditioned_floor_area_m_sq
450
+ economics_data['cost_utility_neb_total_cost_per_m_sq'] += economics_data["cost_utility_neb_#{neb_fuel.downcase}_cost_per_m_sq"]
451
+ # Determine cost in GHG kg of CO2
452
+ economics_data["cost_utility_ghg_#{neb_fuel.downcase}_kg_per_m_sq"] = fuel_consumption_gj * get_utility_ghg_kg_per_gj(province: model.getWeatherFile.stateProvinceRegion, fuel_type: ep_fuel) / @conditioned_floor_area_m_sq
453
+ economics_data['cost_utility_ghg_total_kg_per_m_sq'] += economics_data["cost_utility_ghg_#{neb_fuel.downcase}_kg_per_m_sq"]
454
+ end
455
+ # Commenting out block charge rates for now....
456
+
457
+ # Fuel cost based local utility rates
458
+ # sql_command = "SELECT RowName FROM TabularDataWithStrings
459
+ # WHERE ReportName='LEEDsummary'
460
+ # AND ReportForString='Entire Facility'
461
+ # AND TableName='EAp2-7. Energy Cost Summary'
462
+ # AND ColumnName='Total Energy Cost'"
463
+ # costing_rownames = model.sqlFile().get().execAndReturnVectorOfString(sql_command)
464
+
465
+ #==> ["Electricity", "Natural Gas", "Additional", "Total"]
466
+ # costing_rownames = validate_optional(costing_rownames, model, "N/A")
467
+ # unless costing_rownames == "N/A"
468
+ # costing_rownames.each do |rowname|
469
+ # sql_command = "SELECT Value FROM TabularDataWithStrings
470
+ # WHERE ReportName='LEEDsummary'
471
+ # AND ReportForString='Entire Facility'
472
+ # AND TableName='EAp2-7. Energy Cost Summary'
473
+ # AND ColumnName='Total Energy Cost'
474
+ # AND RowName='#{rowname}'"
475
+ # case rowname
476
+ # when "Electricity"
477
+ # economics_data["cost_utility_block_electricity_cost_per_m_sq"] = model.sqlFile().get().execAndReturnFirstDouble(sql_command).get / @conditioned_floor_area_m_sq
478
+ # when "Natural Gas"
479
+ # economics_data["cost_utility_block_natural_gas_cost_per_m_sq"] = model.sqlFile().get().execAndReturnFirstDouble(sql_command).get / @conditioned_floor_area_m_sq
480
+ # when "Additional"
481
+ # economics_data["cost_utility_block_additional_cost_per_m_sq"] = model.sqlFile().get().execAndReturnFirstDouble(sql_command).get / @conditioned_floor_area_m_sq
482
+ # when "Total"
483
+ # economics_data["cost_utility_block_total_cost_per_m_sq"] = model.sqlFile().get().execAndReturnFirstDouble(sql_command).get / @conditioned_floor_area_m_sq
484
+ # end
485
+ # end
486
+ # else
487
+ # @error_warning << "costing is unavailable because the sql statement is nil RowName FROM TabularDataWithStrings WHERE ReportName='LEEDsummary' AND ReportForString='Entire Facility' AND TableName='EAp2-7. Energy Cost Summary' AND ColumnName='Total Energy Cost'"
488
+ # end
489
+ return economics_data
490
+ end
491
+
492
+ def space_type_table(model)
493
+ table = []
494
+ model.getSpaceTypes.sort.each do |spaceType|
495
+ next if spaceType.floorArea == 0
496
+
497
+ # data for space type breakdown
498
+ display = spaceType.name.get
499
+ floor_area_si = 0
500
+ # loop through spaces so I can skip if not included in floor area
501
+ spaceType.spaces.sort.each do |space|
502
+ next if !space.partofTotalFloorArea
503
+
504
+ floor_area_si += space.floorArea * space.multiplier
505
+ end
506
+ space_type_info = {}
507
+ space_type_info['name'] = spaceType.name.get
508
+ space_type_info['floor_m_sq'] = floor_area_si
509
+ space_type_info['percent_area'] = (floor_area_si / @conditioned_floor_area_m_sq * 100.0).round(2)
510
+ space_type_info['occ_per_m_sq'] = !spaceType.peoplePerFloorArea.empty? ? spaceType.peoplePerFloorArea.get : nil
511
+ space_type_info['occ_schedule'] = !spaceType.defaultScheduleSet.empty? && !spaceType.defaultScheduleSet.get.numberofPeopleSchedule.empty? ? spaceType.defaultScheduleSet.get.numberofPeopleSchedule.get.name.get : nil
512
+ space_type_info['lighting_w_per_m_sq'] = !spaceType.lightingPowerPerFloorArea.empty? ? spaceType.lightingPowerPerFloorArea.get : nil
513
+ space_type_info['electric_w_per_m_sq'] = !spaceType.electricEquipmentPowerPerFloorArea.empty? ? spaceType.electricEquipmentPowerPerFloorArea.get : nil
514
+ space_type_info['gas_w_per_m_sq'] = !spaceType.gasEquipmentPowerPerFloorArea.empty? ? spaceType.gasEquipmentPowerPerFloorArea.get : nil
515
+ table << space_type_info
516
+ end
517
+ return table
518
+ end
519
+
520
+ def thermal_zones_table(model, cost_result)
521
+ # Get E+ zone table.
522
+ zones = @model.getThermalZones
523
+ # get surface table from sql
524
+ table = get_sql_table_to_json(@model, 'InputVerificationandResultsSummary', 'Entire Facility', 'Zone Summary')
525
+ # Get rid of totals and averages.
526
+ table['table'].delete_if { |row| !!(row['name'] =~ /Total|Average/) }
527
+ raise('Could not get zone table from E+ sql') if table.empty?
528
+
529
+ # Go through zone objects
530
+ zones.each do |zone|
531
+ # get E+ zone row
532
+ row = table['table'].detect { |curr_row| zone.name.get.downcase == curr_row['name'].downcase }
533
+ raise("Could not find zone #{row['name']} in #{zones.map { |curr_zone| curr_zone.name.get }}") if row.nil?
534
+
535
+ row['is_ideal_air_loads'] = zone.useIdealAirLoads
536
+ row['heating_sizing_factor'] = zone.sizingZone.zoneHeatingSizingFactor.empty? ? -1.0 : zone.sizingZone.zoneHeatingSizingFactor.get
537
+ row['cooling_sizing_factor'] = zone.sizingZone.zoneCoolingSizingFactor.empty? ? -1.0 : zone.sizingZone.zoneCoolingSizingFactor.get
538
+ row['zone_heating_design_supply_air_temperature'] = zone.sizingZone.zoneHeatingDesignSupplyAirTemperature
539
+ row['zone_cooling_design_supply_air_temperature'] = zone.sizingZone.zoneCoolingDesignSupplyAirTemperature
540
+ # Get Air loop that it is connected to if possible
541
+ row['air_loop_name'] = nil
542
+ model.getAirLoopHVACs.sort.each do |air_loop|
543
+ row['air_loop_name'] = air_loop.name.get if air_loop.thermalZones.include?(zone)
544
+ end
545
+ # Get Breathing zone outdoor air flow.
546
+ sql_command = "
547
+ SELECT Value FROM TabularDataWithStrings
548
+ WHERE ReportName='Standard62.1Summary'
549
+ AND ReportForString='Entire Facility'
550
+ AND TableName='Zone Ventilation Parameters'
551
+ AND ColumnName='Breathing Zone Outdoor Airflow - Vbz'
552
+ AND Units='m3/s'
553
+ AND RowName='#{row['name']}'
554
+ "
555
+ breathing_zone_outdoor_airflow_vbz = model.sqlFile.get.execAndReturnFirstDouble(sql_command)
556
+ row['breathing_zone_outdoor_airflow_vbz'] = breathing_zone_outdoor_airflow_vbz.empty? ? nil : breathing_zone_outdoor_airflow_vbz.get
557
+
558
+ if zone.useIdealAirLoads == false
559
+ # Including ventilation tz_distribution cost data into zone_table
560
+ zoneName = row['name'].downcase
561
+ storyHash = cost_result['ventilation']['tz_distribution'.to_sym][0].detect { |currstoryHash| zoneName.include?(currstoryHash[:Story].to_s.downcase) }
562
+ if storyHash
563
+ tzHash = storyHash[:thermal_zones].detect { |currtzHash| zoneName == currtzHash[:ThermalZone].to_s.downcase && tzHash[:ducting_direction].to_s.downcase == 'supply' }
564
+ if tzHash
565
+ row['ducting_direction'] = tzHash[:ducting_direction]
566
+ row['tz_mult'] = tzHash[:tz_mult]
567
+ row['airflow_m3ps'] = tzHash[:airflow_m3ps]
568
+ row['num_diff'] = tzHash[:num_diff]
569
+ row['ducting_lbs'] = tzHash[:ducting_lbs]
570
+ row['duct_insulation_ft2'] = tzHash[:duct_insulation_ft2]
571
+ row['flex_duct_sz_in'] = tzHash[:flex_duct_sz_in]
572
+ row['flex_duct_length_ft'] = tzHash[:flex_duct_length_ft]
573
+ row['duct_cost'] = tzHash[:cost]
574
+ # Check if there is a return duct hash and, if so, modify ducting direction & cost to include
575
+ # Return duct. Note that all other return duct costing values are identical to Supply duct
576
+ tzHash1 = storyHash[:thermal_zones].detect { |currtzHash1| zoneName == currtzHash1[:ThermalZone].to_s.downcase && currtzHash1[:ducting_direction].to_s.downcase == 'return' }
577
+ if !tzHash1.nil?
578
+ row['ducting_direction'] = 'Supply & Return'
579
+ row['duct_cost'] += tzHash1[:cost]
580
+ end
581
+ end
582
+ end
583
+
584
+ # Including thermal zone HRV return ducting distribution cost information
585
+ floorHash = cost_result['ventilation']['hrv_return_ducting'.to_sym].detect { |currfloorHash| zoneName.include?(currfloorHash[:floor].to_s.downcase) }
586
+ if floorHash
587
+ airSysArr = floorHash[:air_systems].select { |airSys| airSys[:air_system].to_s.downcase == row['air_loop_name'].downcase }
588
+ if !airSysArr.empty?
589
+ airSysArr.each do |airSysHash|
590
+ airSys_tz_hash = airSysHash[:tz_dist].detect { |curr_airSys_tz_hash| curr_airSys_tz_hash[:tz].to_s.downcase == zoneName }
591
+ if airSys_tz_hash
592
+ row['hrv_ret_dist_m'] = airSys_tz_hash[:hrv_ret_dist_m]
593
+ row['hrv_ret_size_in'] = airSys_tz_hash[:hrv_ret_size_in]
594
+ row['hrv_ret_duct_cost'] = airSys_tz_hash[:cost]
595
+ end
596
+ end
597
+ end
598
+ end
599
+ end
600
+ end
601
+
602
+ return table
603
+ end
604
+
605
+ def thermal_zones_equipment_table(model)
606
+ # Store Thermal zone data
607
+ table = []
608
+ model.getThermalZones.sort.each do |zone|
609
+ zone.equipmentInHeatingOrder.each do |equipment|
610
+ item = {}
611
+ item['air_loop_name'] = nil
612
+ model.getAirLoopHVACs.sort.each do |air_loop|
613
+ if air_loop.thermalZones.include?(zone)
614
+ item['air_loop_name'] = air_loop.name.empty? ? 'None' : air_loop.name.get
615
+ else
616
+ item['air_loop_name'] = 'None'
617
+ end
618
+ end
619
+ item['thermal_zone_name'] = zone.name.empty? ? 'None' : zone.name.get
620
+ item['zone_equipment_name'] = equipment.name.empty? ? 'None' : equipment.name.get
621
+ item['type'] = get_actual_child_object(equipment).class.name
622
+ table << item
623
+ end
624
+ end
625
+
626
+ table.sort_by! { |item| [item['air_loop_name'], item['thermal_zone_name'], item['zone_equipment_name']] }
627
+ return table
628
+ end
629
+
630
+ def air_loops_table(model, cost_result)
631
+ # Store Air Loop Information
632
+ table = []
633
+ model.getAirLoopHVACs.sort.each do |air_loop|
634
+ air_loop_info = {}
635
+ air_loop_info['name'] = air_loop.name.get
636
+ sql_command = " SELECT Value FROM TabularDataWithStrings
637
+ WHERE ReportName='Standard62.1Summary'
638
+ AND ReportForString='Entire Facility'
639
+ AND TableName='System Ventilation Parameters'
640
+ AND ColumnName='Area Outdoor Air Rate - Ra'
641
+ AND Units='m3/s-m2'
642
+ AND RowName='#{air_loop.name.get.to_s.upcase}' "
643
+ air_loop_info['area_outdoor_air_rate_m_cu_per_s_m_sq'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
644
+
645
+ air_loop_info['total_floor_area_served'] = 0.0
646
+ air_loop_info['total_breathing_zone_outdoor_airflow_vbz'] = 0.0
647
+ air_loop.thermalZones.sort.each do |zone|
648
+ sql_command = " SELECT Value FROM TabularDataWithStrings
649
+ WHERE ReportName='Standard62.1Summary'
650
+ AND ReportForString='Entire Facility'
651
+ AND TableName='Zone Ventilation Parameters'
652
+ AND ColumnName='Breathing Zone Outdoor Airflow - Vbz'
653
+ AND Units='m3/s'
654
+ AND RowName='#{zone.name.get.to_s.upcase}' "
655
+ vbz = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, 0)
656
+ air_loop_info['total_breathing_zone_outdoor_airflow_vbz'] += vbz
657
+ air_loop_info['total_floor_area_served'] += zone.floorArea
658
+ end
659
+ air_loop_info['outdoor_air_l_per_s'] = -1.0
660
+ unless air_loop_info['area_outdoor_air_rate_m_cu_per_s_m_sq'] == -1.0
661
+ air_loop_info['outdoor_air_l_per_s'] = air_loop_info['area_outdoor_air_rate_m_cu_per_s_m_sq'] * air_loop_info['total_floor_area_served'] * 1000
662
+ end
663
+
664
+ # SUpply Fan
665
+ unless air_loop.supplyFan.empty?
666
+ if air_loop.supplyFan.get.to_FanConstantVolume.is_initialized
667
+ air_loop_info['supply_fan_type'] = 'CV'
668
+ fan = air_loop.supplyFan.get.to_FanConstantVolume.get
669
+ elsif air_loop.supplyFan.get.to_FanVariableVolume.is_initialized
670
+ air_loop_info['supply_fan_type'] = 'VV'
671
+ fan = air_loop.supplyFan.get.to_FanVariableVolume.get
672
+ end
673
+ air_loop_info['supply_fan_name'] = fan.name.get
674
+ air_loop_info['supply_fan_efficiency'] = fan.fanEfficiency
675
+ air_loop_info['supply_fan_motor_efficiency'] = fan.motorEfficiency
676
+ air_loop_info['supply_fan_pressure_rise'] = fan.pressureRise
677
+ air_loop_info['supply_fan_max_air_flow_rate_m_cu_per_s'] = -1.0
678
+ sql_command = " SELECT RowName FROM TabularDataWithStrings
679
+ WHERE ReportName='EquipmentSummary'
680
+ AND ReportForString='Entire Facility'
681
+ AND TableName='Fans'
682
+ AND ColumnName='Max Air Flow Rate'
683
+ AND Units='m3/s' "
684
+ max_air_flow_info = model.sqlFile.get.execAndReturnVectorOfString(sql_command)
685
+ max_air_flow_info = validate_optional(max_air_flow_info, model, 'N/A')
686
+ if max_air_flow_info != 'N/A'
687
+ if max_air_flow_info.include?(air_loop_info['supply_fan_name'].to_s.upcase)
688
+ sql_command = " SELECT Value FROM TabularDataWithStrings
689
+ WHERE ReportName='EquipmentSummary'
690
+ AND ReportForString='Entire Facility'
691
+ AND TableName='Fans'
692
+ AND ColumnName='Max Air Flow Rate'
693
+ AND Units='m3/s'
694
+ AND RowName='#{air_loop_info['supply_fan_name'].upcase}' "
695
+ air_loop_info['supply_fan_max_air_flow_rate_m_cu_per_s'] = model.sqlFile.get.execAndReturnFirstDouble(sql_command).get
696
+ sql_coommand = " SELECT Value FROM TabularDataWithStrings
697
+ WHERE ReportName='EquipmentSummary'
698
+ AND ReportForString='Entire Facility'
699
+ AND TableName='Fans'
700
+ AND ColumnName='Rated Electric Power'
701
+ AND Units='W'
702
+ AND RowName='#{air_loop_info['supply_fan_name'].upcase}' "
703
+ air_loop_info['supply_fan_rated_electric_power_w'] = model.sqlFile.get.execAndReturnFirstDouble(sql_coommand).get
704
+ else
705
+ @error_warning << "#{air_loop_info['supply_fan_name']} does not exist in sql file WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Max Air Flow Rate' AND Units='m3/s'"
706
+ end
707
+ else
708
+ @error_warning << "max_air_flow_info is nil because the following sql statement returned nil: RowName FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Max Air Flow Rate' AND Units='m3/s' "
709
+ end
710
+ end
711
+
712
+ # Fan
713
+ unless air_loop.returnFan.empty?
714
+ air_loop_info['return_fan'] = {}
715
+ if air_loop.returnFan.get.to_FanConstantVolume.is_initialized
716
+ air_loop_info['return_fan_type'] = 'CV'
717
+ fan = air_loop.returnFan.get.to_FanConstantVolume.get
718
+ elsif air_loop.returnFan.get.to_FanVariableVolume.is_initialized
719
+ air_loop_info['return_fan_type'] = 'VV'
720
+ fan = air_loop.returnFan.get.to_FanVariableVolume.get
721
+ end
722
+ air_loop_info['return_fan_name'] = fan.name.get
723
+ air_loop_info['return_fan_efficiency'] = fan.fanEfficiency
724
+ air_loop_info['return_fan_motor_efficiency'] = fan.motorEfficiency
725
+ air_loop_info['return_fan_pressure_rise'] = fan.pressureRise
726
+ air_loop_info['return_fan_max_air_flow_rate_m_cu_per_s'] = -1.0
727
+ sql_command = " SELECT RowName FROM TabularDataWithStrings
728
+ WHERE ReportName='EquipmentSummary'
729
+ AND ReportForString='Entire Facility'
730
+ AND TableName='Fans'
731
+ AND ColumnName='Max Air Flow Rate'
732
+ AND Units='m3/s' "
733
+ max_air_flow_info = model.sqlFile.get.execAndReturnVectorOfString(sql_command)
734
+ max_air_flow_info = validate_optional(max_air_flow_info, model, 'N/A')
735
+ if max_air_flow_info != 'N/A'
736
+ if max_air_flow_info.include?(air_loop_info['return_fan_name'].to_s.upcase.to_s)
737
+ sql_command = " SELECT Value FROM TabularDataWithStrings
738
+ WHERE ReportName='EquipmentSummary'
739
+ AND ReportForString='Entire Facility'
740
+ AND TableName='Fans'
741
+ AND ColumnName='Max Air Flow Rate'
742
+ AND Units='m3/s'
743
+ AND RowName='#{air_loop_info['return_fan_name'].upcase}' "
744
+ air_loop_info['return_fan_max_air_flow_rate_m_cu_per_s'] = model.sqlFile.get.execAndReturnFirstDouble(sql_command).get
745
+ sql_coommand = " SELECT Value FROM TabularDataWithStrings
746
+ WHERE ReportName='EquipmentSummary'
747
+ AND ReportForString='Entire Facility'
748
+ AND TableName='Fans'
749
+ AND ColumnName='Rated Electric Power'
750
+ AND Units='W'
751
+ AND RowName='#{air_loop_info['return_fan_name'].upcase}' "
752
+ air_loop_info['return_fan_rated_electric_power_w'] = model.sqlFile.get.execAndReturnFirstDouble(sql_coommand).get
753
+ else
754
+ @error_warning << "#{air_loop_info['return_fan_name']} does not exist in sql file WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Max Air Flow Rate' AND Units='m3/s'"
755
+ end
756
+ else
757
+ @error_warning << "max_air_flow_info is nil because the following sql statement returned nil: RowName FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Max Air Flow Rate' AND Units='m3/s' "
758
+ end
759
+ end
760
+
761
+ # economizer
762
+ air_loop_info['economizer_name'] = air_loop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.name.get
763
+ air_loop_info['economizer_control_type'] = air_loop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.getEconomizerControlType
764
+
765
+ # Include air system costs from ventilation costs
766
+ sysNum = air_loop_info['name'][4].to_i
767
+ sysCostInfo = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym].detect { |currsysCostInfo| currsysCostInfo[:name].to_s.downcase == air_loop_info['name'].downcase }
768
+ if sysCostInfo.nil? && sysNum == 4
769
+ # 04-Nov-2019 JTB: CK says that system_4 is handled the same way as system_1 so may see "Sys_4" substrings in the name of a system_1 airloop!
770
+ sysCostInfo = cost_result['ventilation']['system_1'.to_s.to_sym].detect { |currsysCostInfo| currsysCostInfo[:name].to_s.downcase == air_loop_info['name'].downcase }
771
+ raise("System name \"#{air_loop_info['name']}\" not found in ventilation cost info for system_1") if sysCostInfo.nil?
772
+ else
773
+ raise("System name \"#{air_loop_info['name']}\" not found in ventilation cost info for System_#{sysNum}") if sysCostInfo.nil?
774
+ end
775
+ if !sysCostInfo.nil?
776
+ air_loop_info['airloop_flow_m3_per_s'] = sysCostInfo[:airloop_flow_m3_per_s]
777
+ air_loop_info['num_rooftop_units'] = sysCostInfo[:num_rooftop_units]
778
+ # air_loop_info['ahu_counter'] = sysCostInfo[:ahu_counter]
779
+ # air_loop_info['ahu_l_per_s'] = sysCostInfo[:ahu_l_per_s]
780
+ air_loop_info['base_ahu_cost'] = sysCostInfo[:base_ahu_cost]
781
+ air_loop_info['revised_base_ahu_cost'] = sysCostInfo[:revised_base_ahu_cost]
782
+ # Promote hrv data from it's own hash, if it isn't empty!
783
+ if sysCostInfo[:hrv].empty?
784
+ air_loop_info['hrv_type'] = sysCostInfo[:hrv]
785
+ else
786
+ air_loop_info['hrv_type'] = sysCostInfo[:hrv][:hrv_type]
787
+ air_loop_info['hrv_name'] = sysCostInfo[:hrv][:hrv_name]
788
+ air_loop_info['hrv_size_m3ps'] = sysCostInfo[:hrv][:hrv_size_m3ps]
789
+ air_loop_info['hrv_return_fan_size_m3ps'] = sysCostInfo[:hrv][:hrv_return_fan_size_m3ps]
790
+ air_loop_info['hrv_cost'] = sysCostInfo[:hrv][:hrv_cost]
791
+ air_loop_info['revised_hrv_cost'] = sysCostInfo[:hrv][:revised_hrv_cost]
792
+ end
793
+ end
794
+
795
+ # Also include hrv_return_ducting information from ventilation costs.
796
+ # Note that there can be multiple hrv return duct runs for the same air loop name
797
+ # (on different floors) plus a system level trunk return duct section.
798
+ hrv_retduct_byflr = cost_result['ventilation']['hrv_return_ducting'.to_sym].reject { |arr| arr[:floor].nil? }
799
+ hrv_retduct_bysys = cost_result['ventilation']['hrv_return_ducting'.to_sym].reject { |arr| arr[:air_system].nil? }
800
+
801
+ # Floor level hrv return ducts...
802
+ hrv_retduct_byflr.each do |arr1|
803
+ flrNum = arr1[:floor].to_s[15].to_i
804
+ airsys_byflr = arr1[:air_systems].select { |arr2| arr2[:air_system].to_s.downcase == air_loop_info['name'].to_s.downcase }
805
+ airsys_byflr.each do |arr3|
806
+ air_loop_info["flr#{flrNum}_floor_mult".to_sym] = arr3[:floor_mult]
807
+ if !arr3[:hrv_ret_trunk].empty?
808
+ # The hrv_ret_trunk embedded hash is not empty -- promote it
809
+ air_loop_info["flr#{flrNum}_hrv_ret_trunk_len_m".to_sym] = arr3[:hrv_ret_trunk][:duct_length_m]
810
+ air_loop_info["flr#{flrNum}_hrv_ret_trunk_dia_in".to_sym] = arr3[:hrv_ret_trunk][:dia_in]
811
+ air_loop_info["flr#{flrNum}_hrv_ret_trunk_cost".to_sym] = arr3[:hrv_ret_trunk][:cost]
812
+ # If not don't include anything!
813
+ end
814
+ # The individual thermal zone (by floor) ret duct distribution (tz_dist) added to zone_table
815
+ end
816
+ end
817
+ # System level trunk hrv return ducts...
818
+ hrv_retduct_bysys.each do |arr1|
819
+ if arr1[:air_system].to_s.downcase == air_loop_info['name'].to_s.downcase
820
+ air_loop_info[:hrv_building_trunk_length_m] = arr1[:hrv_building_trunk_length_m]
821
+ air_loop_info[:hrv_building_trunk_dia_in] = arr1[:hrv_building_trunk_dia_in]
822
+ air_loop_info["sys#{sysNum}_hrv_ret_duct_cost".to_sym] = arr1[:cost]
823
+ end
824
+ end
825
+
826
+ table << air_loop_info
827
+ end
828
+
829
+ return table
830
+ end
831
+
832
+ def coil_table
833
+ table = get_sql_table_to_json(model, 'CoilSizingDetails', 'Entire Facility', 'Coils')['table']
834
+ model.getAirLoopHVACs.sort.each do |air_loop|
835
+ air_loop.supplyComponents.each do |supply_comp|
836
+ object = get_actual_child_object(supply_comp)
837
+ coil_types = [
838
+ 'openstudio::model::CoilCoolingCooledBeam',
839
+ 'openstudio::model::CoilCoolingDXMultiSpeed',
840
+ 'openstudio::model::CoilCoolingDXSingleSpeed',
841
+ 'openstudio::model::CoilCoolingDXTwoSpeed',
842
+ 'openstudio::model::CoilCoolingDXTwoStageWithHumidityControlMode',
843
+ 'openstudio::model::CoilCoolingDXVariableSpeed',
844
+ 'openstudio::model::CoilCoolingFourPipeBeam',
845
+ 'openstudio::model::CoilCoolingLowTempRadiantConstFlow',
846
+ 'openstudio::model::CoilCoolingLowTempRadiantVarFlow',
847
+ 'openstudio::model::CoilHeatingDesuperheater',
848
+ 'openstudio::model::CoilHeatingDXMultiSpeed',
849
+ 'openstudio::model::CoilHeatingDXSingleSpeed',
850
+ 'openstudio::model::CoilHeatingDXVariableSpeed',
851
+ 'openstudio::model::CoilHeatingElectric',
852
+ 'openstudio::model::CoilHeatingFourPipeBeam',
853
+ 'openstudio::model::CoilHeatingGas',
854
+ 'openstudio::model::CoilHeatingGasMultiStage',
855
+ 'openstudio::model::CoilHeatingLowTempRadiantConstFlow',
856
+ 'openstudio::model::CoilHeatingLowTempRadiantVarFlow',
857
+ 'openstudio::model::CoilHeatingWaterBaseboard',
858
+ 'openstudio::model::CoilHeatingWaterBaseboardRadiant',
859
+ 'openstudio::model::CoilSystemCoolingDXHeatExchangerAssisted',
860
+ 'openstudio::model::CoilSystemCoolingWaterHeatExchangerAssisted',
861
+ 'openstudio::model::CoilWaterHeatingDesuperheater'
862
+ ]
863
+ # Is it a heating coil?
864
+ if coil_types.include?(object.class.name) && object.class.name.include?('Heating')
865
+
866
+ case object.class.name
867
+ when 'CoilHeatingGas'
868
+ coil = {}
869
+ coil['name'] = object.get.name
870
+ coil['type'] = 'Gas'
871
+ coil['efficency'] = gas.gasBurnerEfficiency
872
+ sql_command = "SELECT Value FROM TabularDataWithStrings
873
+ WHERE ReportName='EquipmentSummary'
874
+ AND ReportForString='Entire Facility'
875
+ AND TableName='Heating Coils'
876
+ AND ColumnName='Nominal Total Capacity'
877
+ AND RowName='#{coil['name'].to_s.upcase}'"
878
+ coil['nominal_total_capacity_w'] = validate_optional(@model.sqlFile.get.execAndReturnFirstDouble(sql_command), @model, -1.0)
879
+
880
+ when 'CoilHeatingElectric'
881
+ when 'CoilHeatingWater'
882
+ end
883
+
884
+ if supply_comp.to_CoilHeatingGas.is_initialized
885
+ coil = {}
886
+ air_loop_info['heating_coils']['coil_heating_gas'] << coil
887
+ gas = supply_comp.to_CoilHeatingGas.get
888
+ coil['name'] = gas.name.get
889
+ coil['type'] = 'Gas'
890
+ coil['efficency'] = gas.gasBurnerEfficiency
891
+ sql_command = "SELECT Value FROM TabularDataWithStrings
892
+ WHERE ReportName='EquipmentSummary'
893
+ AND ReportForString='Entire Facility'
894
+ AND TableName='Heating Coils'
895
+ AND ColumnName='Nominal Total Capacity'
896
+ AND RowName='#{coil['name'].to_s.upcase}'"
897
+ coil['nominal_total_capacity_w'] = validate_optional(@model.sqlFile.get.execAndReturnFirstDouble(sql_command), @model, -1.0)
898
+ end
899
+ if supply_comp.to_CoilHeatingElectric.is_initialized
900
+ coil = {}
901
+ air_loop_info['heating_coils']['coil_heating_electric'] << coil
902
+ electric = supply_comp.to_CoilHeatingElectric.get
903
+ coil['name'] = electric.name.get
904
+ coil['type'] = 'Electric'
905
+ sql_command = "SELECT Value FROM TabularDataWithStrings
906
+ WHERE ReportName='EquipmentSummary'
907
+ AND ReportForString='Entire Facility'
908
+ AND TableName='Heating Coils'
909
+ AND ColumnName='Nominal Total Capacity'
910
+ AND RowName='#{coil['name'].to_s.upcase}'"
911
+ coil['nominal_total_capacity_w'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
912
+ end
913
+ if supply_comp.to_CoilHeatingWater.is_initialized
914
+ coil = {}
915
+ air_loop_info['heating_coils']['coil_heating_water'] << coil
916
+ water = supply_comp.to_CoilHeatingWater.get
917
+ coil['name'] = water.name.get
918
+ coil['type'] = 'Water'
919
+ sql_command = "SELECT Value FROM TabularDataWithStrings
920
+ WHERE ReportName='EquipmentSummary'
921
+ AND ReportForString='Entire Facility'
922
+ AND TableName='Heating Coils'
923
+ AND ColumnName='Nominal Total Capacity'
924
+ AND RowName='#{coil['name'].to_s.upcase}'"
925
+ coil['nominal_total_capacity_w'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
926
+ end
927
+ end
928
+
929
+ # I dont think i need to get the type of heating coil from the sql file, because the coils are differentiated by class, and I have hard coded the information
930
+ # model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName= 'Heating Coils' AND ColumnName='Type' ").get #padmussen to complete #AND RowName='#{air_loop_info["heating_coils"]["name"].upcase}'
931
+ #
932
+ # Collect all the fans into the the array.
933
+ air_loop.supplyComponents.each do |curr_supply_comp|
934
+ if curr_supply_comp.to_CoilCoolingDXSingleSpeed.is_initialized
935
+ coil = {}
936
+ air_loop_info['cooling_coils']['dx_single_speed'] << coil
937
+ single_speed = curr_supply_comp.to_CoilCoolingDXSingleSpeed.get
938
+ coil['name'] = single_speed.name.get
939
+ coil['cop'] = single_speed.getRatedCOP.get
940
+ sql_command = "SELECT Value FROM TabularDataWithStrings
941
+ WHERE ReportName='EquipmentSummary'
942
+ AND ReportForString='Entire Facility'
943
+ AND TableName='Cooling Coils'
944
+ AND ColumnName='Nominal Total Capacity'
945
+ AND RowName='#{coil['name'].to_s.upcase}'"
946
+ coil['nominal_total_capacity_w'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
947
+ end
948
+ if curr_supply_comp.to_CoilCoolingDXTwoSpeed.is_initialized
949
+ coil = {}
950
+ air_loop_info['cooling_coils']['dx_two_speed'] << coil
951
+ two_speed = curr_supply_comp.to_CoilCoolingDXTwoSpeed.get
952
+ coil['name'] = two_speed.name.get
953
+ coil['cop_low'] = two_speed.getRatedLowSpeedCOP.get
954
+ coil['cop_high'] = two_speed.getRatedHighSpeedCOP.get
955
+ sql_command = "SELECT Value FROM TabularDataWithStrings
956
+ WHERE ReportName='EquipmentSummary'
957
+ AND ReportForString='Entire Facility'
958
+ AND TableName='Cooling Coils'
959
+ AND ColumnName='Nominal Total Capacity'
960
+ AND RowName='#{coil['name'].to_s.upcase}'"
961
+ coil['nominal_total_capacity_w'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
962
+ end
963
+ if curr_supply_comp.to_CoilCoolingWater.is_initialized
964
+ coil = {}
965
+ air_loop_info['cooling_coils']['coil_cooling_water'] << coil
966
+ coil_cooling_water = curr_supply_comp.to_CoilCoolingWater.get
967
+ coil['name'] = coil_cooling_water.name.get
968
+ sql_command = "SELECT Value FROM TabularDataWithStrings
969
+ WHERE ReportName='EquipmentSummary'
970
+ AND ReportForString='Entire Facility'
971
+ AND TableName='Cooling Coils'
972
+ AND ColumnName='Nominal Total Capacity'
973
+ AND RowName='#{coil['name'].to_s.upcase}'"
974
+ coil['nominal_total_capacity_w'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
975
+ sql_command = "SELECT Value FROM TabularDataWithStrings
976
+ WHERE ReportName='EquipmentSummary'
977
+ AND ReportForString='Entire Facility'
978
+ AND TableName='Cooling Coils'
979
+ AND ColumnName='Nominal Sensible Heat Ratio'
980
+ AND RowName='#{coil['name'].upcase}' "
981
+ coil['nominal_sensible_heat_ratio'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
982
+ end
983
+ end
984
+ end
985
+ end
986
+ end
987
+
988
+ def coil_cost_table(cost_result)
989
+ sys_coils_table = []
990
+ (1..7).each do |sysNum|
991
+ sys_table = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym].reject(&:empty?)
992
+ sys_table.each do |sysHash|
993
+ equip_info_table = sysHash[:equipment_info].reject(&:empty?)
994
+ equip_info_table.each do |equipHash|
995
+ sysCoilsInfo = {}
996
+ sys_coils_table << sysCoilsInfo
997
+ sysCoilsInfo[:sys_type] = sysNum
998
+ sysCoilsInfo[:sys_name] = equipHash[:name]
999
+ sysCoilsInfo[:eq_category] = equipHash[:eq_category]
1000
+ sysCoilsInfo[:heating_fuel] = equipHash[:heating_fuel]
1001
+ sysCoilsInfo[:cooling_type] = equipHash[:cooling_type]
1002
+ sysCoilsInfo[:capacity_kw] = equipHash[:capacity_kw]
1003
+ sysCoilsInfo[:coil_cost] = equipHash[:cost]
1004
+ end
1005
+ end
1006
+ end
1007
+ return sys_coils_table
1008
+ end
1009
+
1010
+ def terminal_VAV_cost_table(cost_result)
1011
+ terminal_VAV_table = []
1012
+ (1..7).each do |sysNum|
1013
+ ndx = 0
1014
+ until cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx].nil?
1015
+ ndx1 = 0
1016
+ until cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1].nil?
1017
+ sysTerminalInfo = {}
1018
+ terminal_VAV_table << sysTerminalInfo
1019
+ sysTerminalInfo[:sys_type] = sysNum
1020
+ sysTerminalInfo[:sys_name] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:name]
1021
+ sysTerminalInfo[:terminal] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:terminal]
1022
+ sysTerminalInfo[:zone_mult] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:zone_mult]
1023
+ sysTerminalInfo[:box_type] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:box_type]
1024
+ sysTerminalInfo[:box_name] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:box_name]
1025
+ sysTerminalInfo[:unit_size_kw] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:unit_info][:size_kw]
1026
+ sysTerminalInfo[:unit_air_flow_m3_per_s] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:unit_info][:air_flow_m3_per_s]
1027
+ sysTerminalInfo[:unit_pipe_dist_m] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:unit_info][:pipe_dist_m]
1028
+ sysTerminalInfo[:unit_elect_dist_m] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:unit_info][:elect_dist_m]
1029
+ sysTerminalInfo[:unit_num_units] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:unit_info][:num_units]
1030
+ sysTerminalInfo[:cost] = cost_result['ventilation']["system_#{sysNum}".to_s.to_sym][ndx][:reheat_recool][ndx1][:cost]
1031
+ ndx1 += 1
1032
+ end
1033
+ ndx += 1
1034
+ end
1035
+ end
1036
+ return terminal_VAV_table
1037
+ end
1038
+
1039
+ def trunk_ducts_cost_table(cost_result)
1040
+ # Create a trunk ducts cost table that combines the building trunk duct with the floor trunk ducts
1041
+ trunk_ducts_table = []
1042
+ ndx = 0
1043
+ insert_bld_trunk_duct = true
1044
+ until cost_result['ventilation']['floor_trunk_ducts'.to_sym][0][ndx].nil?
1045
+ if insert_bld_trunk_duct
1046
+ trunkDuctsInfo = {}
1047
+ trunk_ducts_table << trunkDuctsInfo
1048
+ trunkDuctsInfo[:Floor] = 'building_trunk'
1049
+ trunkDuctsInfo[:Predominant_space_type] = 'n/a'
1050
+ trunkDuctsInfo[:SupplyDuctSize_in] = cost_result['ventilation']['trunk_duct'.to_sym][ndx][:DuctSize_in]
1051
+ trunkDuctsInfo[:SupplyDuctLength_m] = cost_result['ventilation']['trunk_duct'.to_sym][ndx][:DuctLength_m]
1052
+ if cost_result['ventilation']['trunk_duct'.to_sym][ndx][:NumberRuns] == 2
1053
+ trunkDuctsInfo[:ReturnDuctSize_in] = cost_result['ventilation']['trunk_duct'.to_sym][ndx][:DuctSize_in]
1054
+ trunkDuctsInfo[:ReturnDuctLength_m] = cost_result['ventilation']['trunk_duct'.to_sym][ndx][:DuctLength_m]
1055
+ else
1056
+ trunkDuctsInfo[:ReturnDuctSize_in] = 0
1057
+ trunkDuctsInfo[:ReturnDuctLength_m] = 0
1058
+ end
1059
+ trunkDuctsInfo[:TotalDuctCost] = cost_result['ventilation']['trunk_duct'.to_sym][ndx][:DuctCost]
1060
+ trunkDuctsInfo[:Multiplier] = 1.0
1061
+ insert_bld_trunk_duct = false
1062
+ else
1063
+ trunkDuctsInfo = {}
1064
+ trunk_ducts_table << trunkDuctsInfo
1065
+ cost_result['ventilation']['floor_trunk_ducts'.to_sym][0][ndx].each do |k, v|
1066
+ trunkDuctsInfo[k] = v
1067
+ end
1068
+ ndx += 1
1069
+ end
1070
+ end
1071
+ return trunk_ducts_table
1072
+ end
1073
+
1074
+ def plant_loop_table(model)
1075
+ table = []
1076
+ model.getPlantLoops.sort.each do |plant_loop|
1077
+ plant_loop_info = {}
1078
+ table << plant_loop_info
1079
+ plant_loop_info['name'] = plant_loop.name.get
1080
+
1081
+ sizing = plant_loop.sizingPlant
1082
+ plant_loop_info['design_loop_exit_temperature'] = sizing.getDesignLoopExitTemperature.value
1083
+ plant_loop_info['loop_design_temperature_difference'] = sizing.getLoopDesignTemperatureDifference.value
1084
+
1085
+ # Create Container for plant equipment arrays.
1086
+ plant_loop_info['pumps'] = []
1087
+ plant_loop_info['boilers'] = []
1088
+ plant_loop_info['chiller_electric_eir'] = []
1089
+ plant_loop_info['cooling_tower_single_speed'] = []
1090
+ plant_loop_info['water_heater_mixed'] = []
1091
+ plant_loop.supplyComponents.each do |supply_comp|
1092
+ # Collect Constant Speed
1093
+ if supply_comp.to_PumpConstantSpeed.is_initialized
1094
+ pump = supply_comp.to_PumpConstantSpeed.get
1095
+ pump_info = {}
1096
+ plant_loop_info['pumps'] << pump_info
1097
+ pump_info['name'] = pump.name.get
1098
+ pump_info['type'] = 'Pump:ConstantSpeed'
1099
+ sql_command = " SELECT Value FROM TabularDataWithStrings
1100
+ WHERE ReportName='EquipmentSummary'
1101
+ AND ReportForString='Entire Facility'
1102
+ AND TableName='Pumps'
1103
+ AND ColumnName='Head'
1104
+ AND RowName='#{pump_info['name'].upcase}' "
1105
+ pump_info['head_pa'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
1106
+ sql_command = " SELECT Value FROM TabularDataWithStrings
1107
+ WHERE ReportName='EquipmentSummary'
1108
+ AND ReportForString='Entire Facility'
1109
+ AND TableName='Pumps'
1110
+ AND ColumnName='Water Flow'
1111
+ AND RowName='#{pump_info['name'].upcase}' "
1112
+ pump_info['water_flow_m_cu_per_s'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
1113
+ sql_command = " SELECT Value FROM TabularDataWithStrings
1114
+ WHERE ReportName='EquipmentSummary'
1115
+ AND ReportForString='Entire Facility'
1116
+ AND TableName='Pumps'
1117
+ AND ColumnName='Electric Power'
1118
+ AND RowName='#{pump_info['name'].upcase}' "
1119
+ pump_info['electric_power_w'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
1120
+ pump_info['motor_efficency'] = pump.getMotorEfficiency.value
1121
+ end
1122
+
1123
+ # Collect Variable Speed
1124
+ if supply_comp.to_PumpVariableSpeed.is_initialized
1125
+ pump = supply_comp.to_PumpVariableSpeed.get
1126
+ pump_info = {}
1127
+ plant_loop_info['pumps'] << pump_info
1128
+ pump_info['name'] = pump.name.get
1129
+ pump_info['type'] = 'Pump:VariableSpeed'
1130
+ sql_command = " SELECT Value FROM TabularDataWithStrings
1131
+ WHERE ReportName='EquipmentSummary'
1132
+ AND ReportForString='Entire Facility'
1133
+ AND TableName='Pumps'
1134
+ AND ColumnName='Head'
1135
+ AND RowName='#{pump_info['name'].upcase}' "
1136
+ pump_info['head_pa'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
1137
+ sql_command = " SELECT Value FROM TabularDataWithStrings
1138
+ WHERE ReportName='EquipmentSummary'
1139
+ AND ReportForString='Entire Facility'
1140
+ AND TableName='Pumps'
1141
+ AND ColumnName='Water Flow'
1142
+ AND RowName='#{pump_info['name'].upcase}' "
1143
+ pump_info['water_flow_m_cu_per_s'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
1144
+ sql_command = " SELECT Value FROM TabularDataWithStrings
1145
+ WHERE ReportName='EquipmentSummary'
1146
+ AND ReportForString='Entire Facility'
1147
+ AND TableName='Pumps'
1148
+ AND ColumnName='Electric Power'
1149
+ AND RowName='#{pump_info['name'].upcase}' "
1150
+ pump_info['electric_power_w'] = validate_optional(model.sqlFile.get.execAndReturnFirstDouble(sql_command), model, -1.0)
1151
+ pump_info['motor_efficency'] = pump.getMotorEfficiency.value
1152
+ end
1153
+
1154
+ # Collect HotWaterBoilers
1155
+ if supply_comp.to_BoilerHotWater.is_initialized
1156
+ boiler = supply_comp.to_BoilerHotWater.get
1157
+ boiler_info = {}
1158
+ plant_loop_info['boilers'] << boiler_info
1159
+ boiler_info['name'] = boiler.name.get
1160
+ boiler_info['type'] = 'Boiler:HotWater'
1161
+ boiler_info['fueltype'] = boiler.fuelType
1162
+ boiler_info['nominal_capacity'] = validate_optional(boiler.nominalCapacity, model, -1.0)
1163
+ end
1164
+
1165
+ # Collect ChillerElectricEIR
1166
+ if supply_comp.to_ChillerElectricEIR.is_initialized
1167
+ chiller = supply_comp.to_ChillerElectricEIR.get
1168
+ chiller_info = {}
1169
+ plant_loop_info['chiller_electric_eir'] << chiller_info
1170
+ chiller_info['name'] = chiller.name.get
1171
+ chiller_info['type'] = 'Chiller:Electric:EIR'
1172
+ chiller_info['reference_capacity'] = validate_optional(chiller.referenceCapacity, model, -1.0)
1173
+ chiller_info['reference_leaving_chilled_water_temperature'] = chiller.referenceLeavingChilledWaterTemperature
1174
+ end
1175
+
1176
+ # Collect CoolingTowerSingleSpeed
1177
+ if supply_comp.to_CoolingTowerSingleSpeed.is_initialized
1178
+ coolingTower = supply_comp.to_CoolingTowerSingleSpeed.get
1179
+ coolingTower_info = {}
1180
+ plant_loop_info['cooling_tower_single_speed'] << coolingTower_info
1181
+ coolingTower_info['name'] = coolingTower.name.get
1182
+ coolingTower_info['type'] = 'CoolingTower:SingleSpeed'
1183
+ coolingTower_info['fan_power_at_design_air_flow_rate'] = validate_optional(coolingTower.fanPoweratDesignAirFlowRate, model, -1.0)
1184
+ end
1185
+
1186
+ # Collect WaterHeaterMixed
1187
+ if supply_comp.to_WaterHeaterMixed.is_initialized
1188
+ waterHeaterMixed = supply_comp.to_WaterHeaterMixed.get
1189
+ waterHeaterMixed_info = {}
1190
+ plant_loop_info['water_heater_mixed'] << waterHeaterMixed_info
1191
+ waterHeaterMixed_info['name'] = waterHeaterMixed.name.get
1192
+ waterHeaterMixed_info['type'] = 'WaterHeater:Mixed'
1193
+ waterHeaterMixed_info['heater_thermal_efficiency'] = waterHeaterMixed.heaterThermalEfficiency.get unless waterHeaterMixed.heaterThermalEfficiency.empty?
1194
+ waterHeaterMixed_info['heater_fuel_type'] = waterHeaterMixed.heaterFuelType
1195
+ end
1196
+ end
1197
+ end
1198
+ return table
1199
+ end
1200
+
1201
+ def eplusout_err_table(model)
1202
+ table = []
1203
+ warnings = model.sqlFile.get.execAndReturnVectorOfString("SELECT ErrorMessage FROM Errors WHERE ErrorType='0' ")
1204
+ warnings = validate_optional(warnings, model, 'N/A')
1205
+ unless warnings == 'N/A'
1206
+ messages = model.sqlFile.get.execAndReturnVectorOfString("SELECT ErrorMessage FROM Errors WHERE ErrorType='0' ").get
1207
+ messages.each do |message|
1208
+ table << { 'error_type' => 'warning', 'message' => message }
1209
+ end
1210
+ messages = model.sqlFile.get.execAndReturnVectorOfString("SELECT ErrorMessage FROM Errors WHERE ErrorType='1' ").get
1211
+ messages.each do |message|
1212
+ table << { 'error_type' => 'severe', 'message' => message }
1213
+ end
1214
+ messages = model.sqlFile.get.execAndReturnVectorOfString("SELECT ErrorMessage FROM Errors WHERE ErrorType='2' ").get
1215
+ messages.each do |message|
1216
+ table << { 'error_type' => 'fatal', 'message' => message }
1217
+ end
1218
+ end
1219
+ return table
1220
+ end
1221
+
1222
+ def energy_peak_data
1223
+ # Primary heaing source
1224
+ data = {}
1225
+ command = "SELECT Value
1226
+ FROM TabularDataWithStrings
1227
+ WHERE ReportName='LEEDsummary'
1228
+ AND ReportForString='Entire Facility'
1229
+ AND TableName='Sec1.1A-General Information'
1230
+ AND RowName = 'Principal Heating Source'
1231
+ AND ColumnName='Data'"
1232
+ value = @sqlite_file.get.execAndReturnFirstString(command)
1233
+ # make sure all the data are availalbe
1234
+
1235
+ data['energy_principal_heating_source'] = 'unknown'
1236
+ unless value.empty?
1237
+ data['energy_principal_heating_source'] = value.get
1238
+ end
1239
+
1240
+ # Peaks
1241
+ electric_peak = @model.sqlFile.get.execAndReturnFirstDouble("SELECT Value FROM tabulardatawithstrings WHERE ReportName='EnergyMeters'" \
1242
+ " AND ReportForString='Entire Facility' AND TableName='Annual and Peak Values - Electricity' AND RowName='Electricity:Facility'" \
1243
+ " AND ColumnName='Electricity Maximum Value' AND Units='W'")
1244
+ natural_gas_peak = @model.sqlFile.get.execAndReturnFirstDouble("SELECT Value FROM tabulardatawithstrings WHERE ReportName='EnergyMeters'" \
1245
+ " AND ReportForString='Entire Facility' AND TableName='Annual and Peak Values - Gas' AND RowName='Gas:Facility'" \
1246
+ " AND ColumnName='Gas Maximum Value' AND Units='W'")
1247
+ data['energy_peak_electric_w_per_m_sq'] = electric_peak.empty? ? 0.0 : electric_peak.get / @conditioned_floor_area_m_sq
1248
+ data['energy_peak_natural_gas_w_per_m_sq'] = natural_gas_peak.empty? ? 0.0 : natural_gas_peak.get / @conditioned_floor_area_m_sq
1249
+
1250
+ # Peak heating load #TODO: IMPORTANT NOTE: Peak heating load must be updated if a combination of fuel types is used in a building model.
1251
+ command = "SELECT Value
1252
+ FROM TabularDataWithStrings
1253
+ WHERE ReportName='EnergyMeters'
1254
+ AND ReportForString='Entire Facility'
1255
+ AND TableName='Annual and Peak Values - Electricity'
1256
+ AND RowName='Heating:Electricity'
1257
+ AND ColumnName='Electricity Maximum Value'
1258
+ AND Units='W'"
1259
+ heating_peak_w_electricity = @sqlite_file.get.execAndReturnFirstDouble(command)
1260
+ command = "SELECT Value
1261
+ FROM TabularDataWithStrings
1262
+ WHERE ReportName='EnergyMeters'
1263
+ AND ReportForString='Entire Facility'
1264
+ AND TableName='Annual and Peak Values - Gas'
1265
+ AND RowName='Heating:Gas'
1266
+ AND ColumnName='Gas Maximum Value'
1267
+ AND Units='W'"
1268
+ heating_peak_w_gas = @sqlite_file.get.execAndReturnFirstDouble(command)
1269
+ heating_peak_w = [heating_peak_w_electricity.to_f, heating_peak_w_gas.to_f].max
1270
+ data['heating_peak_w_per_m_sq'] = heating_peak_w / @conditioned_floor_area_m_sq
1271
+
1272
+ # Peak cooling load #TODO: IMPORTANT NOTE: Peak cooling load must be updated if a combination of fuel types is used in a building model.
1273
+ command = "SELECT Value
1274
+ FROM TabularDataWithStrings
1275
+ WHERE ReportName='EnergyMeters'
1276
+ AND ReportForString='Entire Facility'
1277
+ AND TableName='Annual and Peak Values - Electricity'
1278
+ AND RowName='Cooling:Electricity'
1279
+ AND ColumnName='Electricity Maximum Value'
1280
+ AND Units='W'"
1281
+ cooling_peak_w_electricity = @sqlite_file.get.execAndReturnFirstDouble(command)
1282
+ command = "SELECT Value
1283
+ FROM TabularDataWithStrings
1284
+ WHERE ReportName='EnergyMeters'
1285
+ AND ReportForString='Entire Facility'
1286
+ AND TableName='Annual and Peak Values - Gas'
1287
+ AND RowName='Cooling:Electricity'
1288
+ AND ColumnName='Electricity Maximum Value'
1289
+ AND Units='W'"
1290
+ cooling_peak_w_gas = @sqlite_file.get.execAndReturnFirstDouble(command)
1291
+ cooling_peak_w = [cooling_peak_w_electricity.to_f, cooling_peak_w_gas.to_f].max
1292
+ data['cooling_peak_w_per_m_sq'] = cooling_peak_w / @conditioned_floor_area_m_sq
1293
+
1294
+ return data
1295
+ end
1296
+
1297
+ def energy_eui_data
1298
+ data = {}
1299
+ # default to zero to start.
1300
+ ['energy_eui_fans_gj_per_m_sq',
1301
+ 'energy_eui_heating_gj_per_m_sq',
1302
+ 'energy_eui_cooling_gj_per_m_sq',
1303
+ 'energy_eui_interior equipment_gj_per_m_sq',
1304
+ 'energy_eui_natural_gas_gj_per_m_sq',
1305
+ 'energy_eui_pumps_gj_per_m_sq',
1306
+ 'energy_eui_total_gj_per_m_sq',
1307
+ 'energy_eui_water systems_gj_per_m_sq'].each { |end_use| data[end_use] = 0.0 }
1308
+ # Get E+ End use table from sql
1309
+ table = get_sql_table_to_json(@model, 'AnnualBuildingUtilityPerformanceSummary', 'Entire Facility', 'End Uses')['table']
1310
+ # Get rid of totals and averages rows.. I want just the
1311
+ table.delete_if { |row| !!(row['name'] =~ /Total|Average/) }
1312
+ table.each do |row|
1313
+ # skip name and water_m3 columns
1314
+ energy_columns = row.select { |k, v| (k != 'name') && (k != 'water_m3') }
1315
+ # Store eui by use name.
1316
+ data["energy_eui_#{row['name'].downcase}_gj_per_m_sq"] = energy_columns.inject(0) { |sum, tuple| sum += tuple[1] } / @conditioned_floor_area_m_sq
1317
+ end
1318
+ data['energy_eui_total_gj_per_m_sq'] = 0.0
1319
+ ['natural_gas_GJ', 'electricity_GJ', 'district_cooling_GJ', 'district_heating_GJ', 'additional_fuel_GJ'].each do |column|
1320
+ data["energy_eui_#{column.downcase}_per_m_sq"] = table.inject(0) { |sum, row| sum + (row[column].nil? ? 0.0 : row[column]) } / @conditioned_floor_area_m_sq
1321
+ data['energy_eui_total_gj_per_m_sq'] += data["energy_eui_#{column.downcase}_per_m_sq"] unless data["energy_eui_#{column.downcase}_per_m_sq"].nil?
1322
+ end
1323
+ # Get total and net site energy use intensity
1324
+ # Note: 'Total Site Energy' is the "gross" energy used by a building.
1325
+ # Note: 'Net Site Energy' is the final energy used by the building after considering any on-site energy generation (e.g. PV).
1326
+ # Reference: https://unmethours.com/question/25416/what-is-the-difference-between-site-energy-and-source-energy/
1327
+ # Reference: https://designbuilder.co.uk/helpv6.0/Content/KPIs.htm
1328
+ data['total_site_eui_gj_per_m_sq'] = data['energy_eui_total_gj_per_m_sq'].to_f
1329
+ command = "SELECT Value
1330
+ FROM TabularDataWithStrings
1331
+ WHERE ReportName='AnnualBuildingUtilityPerformanceSummary'
1332
+ AND ReportForString='Entire Facility'
1333
+ AND TableName='Site and Source Energy'
1334
+ AND RowName='Net Site Energy'
1335
+ AND ColumnName='Energy Per Conditioned Building Area'
1336
+ AND Units='MJ/m2'"
1337
+ net_site_eui_mj_per_m_sq = @sqlite_file.get.execAndReturnFirstDouble(command)
1338
+ data['net_site_eui_gj_per_m_sq'] = OpenStudio.convert(net_site_eui_mj_per_m_sq.to_f, 'MJ', 'GJ').get
1339
+ return data
1340
+ end
1341
+
1342
+ def unmet_hours(model)
1343
+ # Store unmet hour data
1344
+ unmet_hours = {}
1345
+ unmet_hours['unmet_hours_cooling'] = model.getFacility.hoursCoolingSetpointNotMet.get unless model.getFacility.hoursCoolingSetpointNotMet.empty?
1346
+ unmet_hours['unmet_hours_heating'] = model.getFacility.hoursHeatingSetpointNotMet.get unless model.getFacility.hoursHeatingSetpointNotMet.empty?
1347
+ command = "SELECT Value
1348
+ FROM TabularDataWithStrings
1349
+ WHERE ReportName='AnnualBuildingUtilityPerformanceSummary'
1350
+ AND ReportForString='Entire Facility'
1351
+ AND TableName='Comfort and Setpoint Not Met Summary'
1352
+ AND RowName='Time Setpoint Not Met During Occupied Cooling'
1353
+ AND ColumnName='Facility'
1354
+ AND Units='Hours'"
1355
+ unmet_hours['unmet_hours_cooling_during_occupied'] = @sqlite_file.get.execAndReturnFirstDouble(command).to_f
1356
+ command = "SELECT Value
1357
+ FROM TabularDataWithStrings
1358
+ WHERE ReportName='AnnualBuildingUtilityPerformanceSummary'
1359
+ AND ReportForString='Entire Facility'
1360
+ AND TableName='Comfort and Setpoint Not Met Summary'
1361
+ AND RowName='Time Setpoint Not Met During Occupied Heating'
1362
+ AND ColumnName='Facility'
1363
+ AND Units='Hours'"
1364
+ unmet_hours['unmet_hours_heating_during_occupied'] = @sqlite_file.get.execAndReturnFirstDouble(command).to_f
1365
+ return unmet_hours
1366
+ end
1367
+
1368
+ def service_water_heating_data
1369
+ service_water_heating = {}
1370
+ service_water_heating['shw_total_nominal_occupancy'] = -1
1371
+ # service_water_heating["total_nominal_occupancy"]=@model.sqlFile().get().execAndReturnVectorOfDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='OutdoorAirSummary' AND ReportForString='Entire Facility' AND TableName='Average Outdoor Air During Occupied Hours' AND ColumnName='Nominal Number of Occupants'").get.inject(0, :+)
1372
+ service_water_heating['shw_total_nominal_occupancy'] = get_total_nominal_capacity(@model)
1373
+
1374
+ service_water_heating['shw_electricity_per_year'] = @model.sqlFile.get.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND ColumnName='Electricity' AND RowName='Water Systems'")
1375
+ service_water_heating['shw_electricity_per_year'] = validate_optional(service_water_heating['shw_electricity_per_year'], @model, -1)
1376
+
1377
+ service_water_heating['shw_electricity_per_day'] = service_water_heating['shw_electricity_per_year'] / 365.5
1378
+ service_water_heating['shw_electricity_per_day_per_occupant'] = service_water_heating['shw_electricity_per_day'] / service_water_heating['shw_total_nominal_occupancy']
1379
+
1380
+ service_water_heating['shw_natural_gas_per_year'] = @model.sqlFile.get.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND ColumnName='Natural Gas' AND RowName='Water Systems'")
1381
+ service_water_heating['shw_natural_gas_per_year'] = validate_optional(service_water_heating['shw_natural_gas_per_year'], @model, -1)
1382
+
1383
+ service_water_heating['shw_additional_fuel_per_year'] = @model.sqlFile.get.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND ColumnName='Additional Fuel' AND RowName='Water Systems'")
1384
+ service_water_heating['shw_additional_fuel_per_year'] = validate_optional(service_water_heating['shw_additional_fuel_per_year'], @model, -1)
1385
+
1386
+ service_water_heating['shw_water_m_cu_per_year'] = @model.sqlFile.get.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND ColumnName='Water' AND RowName='Water Systems'")
1387
+ service_water_heating['shw_water_m_cu_per_year'] = validate_optional(service_water_heating['shw_water_m_cu_per_year'], @model, -1)
1388
+
1389
+ service_water_heating['shw_water_m_cu_per_day'] = service_water_heating['shw_water_m_cu_per_year'] / 365.5
1390
+ service_water_heating['shw_water_m_cu_per_day_per_occupant'] = service_water_heating['shw_water_m_cu_per_day'] / service_water_heating['shw_total_nominal_occupancy']
1391
+ return service_water_heating
1392
+ end
1393
+
1394
+ def sql_data_tables(model)
1395
+ puts 'Getting SQL Data into json...'
1396
+ start = Time.now
1397
+ sql_data = []
1398
+
1399
+ [
1400
+ ['AnnualBuildingUtilityPerformanceSummary', 'Entire Facility', 'End Uses']
1401
+ # ["AnnualBuildingUtilityPerformanceSummary", "Entire Facility", "Site and Source Energy"],
1402
+ # ["AnnualBuildingUtilityPerformanceSummary", "Entire Facility", "On-Site Thermal Sources"],
1403
+ # ["AnnualBuildingUtilityPerformanceSummary", "Entire Facility", "Comfort and Setpoint Not Met Summary"],
1404
+ # ["InputVerificationandResultsSummary", "Entire Facility", "Window-Wall Ratio"],
1405
+ # ["InputVerificationandResultsSummary", "Entire Facility", "Conditioned Window-Wall Ratio"],
1406
+ # ["InputVerificationandResultsSummary", "Entire Facility", "Skylight-Roof Ratio"],
1407
+ # ["DemandEndUseComponentsSummary", "Entire Facility", "End Uses"],
1408
+ # ["ComponentSizingSummary", "Entire Facility", "AirLoopHVAC"],
1409
+ # ["EnergyMeters", "Entire Facility", 'Annual and Peak Values - Gas'],
1410
+ # ["EnergyMeters", "Entire Facility", 'Annual and Peak Values - Electricity'],
1411
+ # ["EnergyMeters", "Entire Facility", 'Annual and Peak Values - FuelOilNo2'],
1412
+ # ["EnergyMeters", "Entire Facility", 'Annual and Peak Values - Other'],
1413
+ # ["LEEDsummary", "Entire Facility", "EAp2-7. Energy Cost Summary"],
1414
+ # ["Standard62.1Summary", "Entire Facility", "Zone Ventilation Parameters"],
1415
+ # ["EquipmentSummary", "Entire Facility", "Fans"],
1416
+ # ["EquipmentSummary", "Entire Facility", "Heating Coils"],
1417
+ # ["EquipmentSummary", "Entire Facility", "Cooling Coils"],
1418
+ # ["EquipmentSummary", "Entire Facility", "Pumps"],
1419
+ # ["CoilSizingDetails", "Entire Facility", "Coils"] # Do not use! Takes very long to parse.
1420
+ ].each do |table|
1421
+ start = Time.now
1422
+ puts "Parsing #{table[0]}-#{table[1]}-#{table[2]}"
1423
+ sql_data << get_sql_table_to_json(model, table[0], table[1], table[2])
1424
+ finish = Time.now
1425
+ puts "....finish parsing in #{finish - start} seconds and stored in sql_data_tables hash."
1426
+ end
1427
+ end
1428
+
1429
+ # This measure will return an array of hashes with the varialbles used in the previous measures.
1430
+ def measures_data_table(runner)
1431
+ # Array to store hash row data.
1432
+ measure_variables_table = []
1433
+ # Go through each workstep.
1434
+ runner.workflow.workflowSteps.each do |step|
1435
+ # Check if the ws is a measure.
1436
+ if step.to_MeasureStep.is_initialized
1437
+ measure_step = step.to_MeasureStep.get
1438
+ # Set measure name using either the folder name or the measureStep name if possible.
1439
+ measure_name = measure_step.name.is_initialized ? measure_step.name.get : measure_step.measureDirName
1440
+ measures_to_skip = ['openstudio_results']
1441
+ unless measures_to_skip.include?(measure_name.to_s)
1442
+ # Check if the 'result' (?) is initialized?
1443
+ if measure_step.result.is_initialized
1444
+ result = measure_step.result.get
1445
+ # Iterate through the result object stepValues to obtain the arg values. I am assuming this is for arg, var. pivot, continous...
1446
+ result.stepValues.each do |arg|
1447
+ # Store the row /hash for the table.
1448
+ units = arg.units.empty? ? nil : arg.units
1449
+ value = nil
1450
+ case arg.variantType.value
1451
+ when 0
1452
+ value = arg.valueAsBoolean
1453
+ when 1..2
1454
+ value = arg.valueAsDouble
1455
+ when 3
1456
+ value = arg.valueAsString
1457
+ end
1458
+ measure_variables_table << { 'measure_name' => measure_name, 'arg_name' => arg.name, 'value' => value, 'units' => units, 'type' => arg.variantType.value }
1459
+ end
1460
+ end
1461
+ end
1462
+ end
1463
+ end
1464
+ return measure_variables_table
1465
+ end
1466
+
1467
+ # This should be done last.
1468
+
1469
+ def get_sql_table_to_json(model, report_name, report_for_string, table_name)
1470
+ table = []
1471
+ query_row_names = "
1472
+ SELECT DISTINCT
1473
+ RowName
1474
+ FROM
1475
+ tabulardatawithstrings
1476
+ WHERE
1477
+ ReportName='#{report_name}'
1478
+ AND
1479
+ ReportForString='#{report_for_string}'
1480
+ AND
1481
+ TableName='#{table_name}'"
1482
+ row_names = model.sqlFile.get.execAndReturnVectorOfString(query_row_names).get
1483
+
1484
+ # get Columns
1485
+ query_col_names = "
1486
+ SELECT DISTINCT
1487
+ ColumnName
1488
+ FROM tabulardatawithstrings
1489
+ WHERE ReportName='#{report_name}'
1490
+ AND ReportForString='#{report_for_string}'
1491
+ AND TableName='#{table_name}'"
1492
+ col_names = model.sqlFile.get.execAndReturnVectorOfString(query_col_names).get
1493
+
1494
+ # get units
1495
+ query_unit_names = "
1496
+ SELECT DISTINCT
1497
+ Units
1498
+ FROM tabulardatawithstrings
1499
+ WHERE ReportName='#{report_name}'
1500
+ AND ReportForString='#{report_for_string}'
1501
+ AND TableName='#{table_name}'"
1502
+ unit_names = model.sqlFile.get.execAndReturnVectorOfString(query_unit_names).get
1503
+
1504
+ row_names.each do |row|
1505
+ next if row.nil? || row == ''
1506
+
1507
+ row_hash = {}
1508
+ row_hash['name'] = row
1509
+ col_names.each do |col|
1510
+ unit_names.each do |unit|
1511
+ query = "
1512
+ SELECT
1513
+ Value
1514
+ FROM
1515
+ tabulardatawithstrings
1516
+ WHERE
1517
+ ReportName='#{report_name}'
1518
+ AND
1519
+ ReportForString='#{report_for_string}'
1520
+ AND
1521
+ TableName='#{table_name}'
1522
+ AND
1523
+ RowName='#{row}'
1524
+ AND
1525
+ ColumnName='#{col}'
1526
+ AND
1527
+ Units='#{unit}'
1528
+ "
1529
+ column_name = col.to_s.gsub(/\s+/, '_').downcase
1530
+ column_name += "_#{unit}" if unit != ''
1531
+ value = model.sqlFile.get.execAndReturnFirstString(query)
1532
+ next if value.empty? || value.get.nil?
1533
+
1534
+ value = value.get.strip
1535
+ # check is value is a number. The last chunk checks if the string includes an E, if not return true since it
1536
+ # is a regular number, if not it checks if it is in the E+ exponent format and returns the bool result of that.
1537
+ if (begin
1538
+ Float(value)
1539
+ rescue StandardError
1540
+ false
1541
+ end) && value.to_f != 0 && (value.include?('E') || value.include?('e') ? value =~ /\d*\.\d*E[+|-]\d*/ : true)
1542
+ row_hash[column_name] = value.to_f
1543
+ # Check if value is a date
1544
+ elsif unit == '' && value =~ /\d\d-\D\D\D-\d\d:\d\d/
1545
+ row_hash[column_name] = DateTime.parse(value)
1546
+ # skip if value in an empty string or a zero value
1547
+ elsif value != '' && value != '0.00'
1548
+ row_hash[column_name] = value
1549
+ end
1550
+ end
1551
+ end
1552
+ if row_hash.size > 1
1553
+ table << row_hash
1554
+ end
1555
+ end
1556
+ result = { 'report_name' => report_name, 'report_for_string' => report_for_string, 'table_name' => table_name, 'table' => table }
1557
+ return result
1558
+ end
1559
+
1560
+ def merge_recursively(a, b)
1561
+ a.merge(b) { |key, a_item, b_item| merge_recursively(a_item, b_item) }
1562
+ end
1563
+
1564
+ def validate_optional(var, model, return_value = 'N/A')
1565
+ return return_value if var.nil? || var.empty?
1566
+
1567
+ return var.get
1568
+ end
1569
+
1570
+ # TODO: SQL command units may have been converted wrong.
1571
+
1572
+ def get_actual_child_object(object)
1573
+ # monkey patch class to have a decendants static method to return all possible subclasses of the object.
1574
+ object.class.class_eval do
1575
+ def self.descendants
1576
+ ObjectSpace.each_object(Class).select { |k| k < self } << self
1577
+ end
1578
+ end
1579
+ # Dont try and match the class that the object is already in! So get decendants that are not of the current object class
1580
+ subclass_array = object.class.descendants.map { |classtype| classtype if classtype != object.class }.reject(&:nil?)
1581
+ subclass_array.each do |class_type|
1582
+ # convert class name to not have prefix.
1583
+ matches = class_type.name.match(/OpenStudio::Model::(?<object_name>.*)/)
1584
+ new_object = nil
1585
+ # Use eval (I know this is the devil) to try to cast to a subclass.
1586
+ eval_info = "new_object = object.to_#{matches['object_name']}"
1587
+ eval(eval_info)
1588
+ # if it does then clean it up and return it.
1589
+ if new_object.is_initialized
1590
+ new_object = new_object.get
1591
+ return get_actual_child_object(new_object)
1592
+ end
1593
+ end
1594
+ # It is not cast-able to any subclass.. so returning original object.
1595
+ return object
1596
+ end
1597
+
1598
+ def set_sql_file(file)
1599
+ @sqlite_file = file
1600
+ end
1601
+
1602
+ def measure_metrics(qaqc)
1603
+ # Store mesure metric data that will be used in analysis tools.
1604
+ @btap_data['env_outdoor_walls_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:outdoor_walls_average_conductance_w_per_m2_k]
1605
+ @btap_data['env_outdoor_roofs_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:outdoor_roofs_average_conductance_w_per_m2_k]
1606
+ @btap_data['env_outdoor_floors_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:outdoor_floors_average_conductance_w_per_m2_k]
1607
+ @btap_data['env_ground_walls_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:ground_walls_average_conductance_w_per_m2_k]
1608
+ @btap_data['env_ground_roofs_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:ground_roofs_average_conductance_w_per_m2_k]
1609
+ @btap_data['env_ground_floors_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:ground_floors_average_conductance_w_per_m2_k]
1610
+ @btap_data['env_outdoor_windows_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:windows_average_conductance_w_per_m2_k]
1611
+ @btap_data['env_outdoor_doors_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:doors_average_conductance_w_per_m2_k]
1612
+ @btap_data['env_outdoor_overhead_doors_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:overhead_doors_average_conductance_w_per_m2_k]
1613
+ @btap_data['env_skylights_average_conductance-w_per_m_sq_k'] = qaqc[:envelope][:skylights_average_conductance_w_per_m2_k]
1614
+ @btap_data['env_fdwr'] = (BTAP::Geometry.get_fwdr(@model) * 100.0).round(1)
1615
+ @btap_data['env_srr'] = (BTAP::Geometry.get_srr(@model) * 100.0).round(1)
1616
+ unless @btap_data['measures_data_table'].nil?
1617
+ if @btap_data['measures_data_table'].detect { |item| item['measure_name'] == 'btap_standard_building_type_geometry' }.nil?
1618
+ @btap_data['env_x_scale'] = 1.0
1619
+ @btap_data['env_y_scale'] = 1.0
1620
+ @btap_data['env_z_scale'] = 1.0
1621
+ @btap_data['env_rotation'] = 0.0
1622
+ else
1623
+ @btap_data['env_x_scale'] = @btap_data['measures_data_table'].detect { |item| item['measure_name'] == 'btap_standard_building_type_geometry' && item['arg_name'] == 'x_scale' }['value']
1624
+ @btap_data['env_y_scale'] = @btap_data['measures_data_table'].detect { |item| item['measure_name'] == 'btap_standard_building_type_geometry' && item['arg_name'] == 'y_scale' }['value']
1625
+ @btap_data['env_z_scale'] = @btap_data['measures_data_table'].detect { |item| item['measure_name'] == 'btap_standard_building_type_geometry' && item['arg_name'] == 'z_scale' }['value']
1626
+ @btap_data['env_rotation'] = @btap_data['measures_data_table'].detect { |item| item['measure_name'] == 'btap_standard_building_type_geometry' && item['arg_name'] == 'relative_building_rotation' }['value']
1627
+ end
1628
+ end
1629
+
1630
+ # This does not work with the new VRF or CCASHP systems. Commenting it for now.
1631
+ # Determine dominant system type by air loop
1632
+
1633
+ # systems = {}
1634
+ # @btap_data["air_loop_table"].each do |loop|
1635
+ # Get system name part from regex
1636
+ # system_name = loop["name"].match(/(^.{0,6}).*/)[1]
1637
+ # systems[system_name] = 0.0 if systems[system_name] == nil
1638
+ # systems[system_name] += loop["total_floor_area_served"]
1639
+ # end
1640
+ # if systems.empty?
1641
+ # @btap_data["mm_hvac_dominant_system_type"] = "Unknown/IdealHVAC"
1642
+ # else
1643
+ # @btap_data["mm_hvac_dominant_system_type"] = systems.key(systems.values.max)
1644
+ # end
1645
+ return @btap_data
1646
+ end
1647
+
1648
+ def get_utility_ghg_kg_per_gj(province:, fuel_type:)
1649
+ ghg_data = [
1650
+ # Obtained from Portfolio Manager https://portfoliomanager.energystar.gov/pdf/reference/Emissions.pdf 10/10/2020
1651
+ { "province": 'AB', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 53.24, "CO2eq Emissions (g/m3)": 1939.0 },
1652
+ { "province": 'BC', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 53.19, "CO2eq Emissions (g/m3)": 1937.0 },
1653
+ { "province": 'MB', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.09, "CO2eq Emissions (g/m3)": 1897.0 },
1654
+ { "province": 'NB', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.50, "CO2eq Emissions (g/m3)": 1912.0 },
1655
+ { "province": 'NL', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.50, "CO2eq Emissions (g/m3)": 1912.0 },
1656
+ { "province": 'NT', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.50, "CO2eq Emissions (g/m3)": 1912.0 },
1657
+ { "province": 'NS', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.50, "CO2eq Emissions (g/m3)": 1912.0 },
1658
+ { "province": 'NU', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.50, "CO2eq Emissions (g/m3)": 1912.0 },
1659
+ { "province": 'ON', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.14, "CO2eq Emissions (g/m3)": 1912.0 },
1660
+ { "province": 'PE', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.50, "CO2eq Emissions (g/m3)": 1912.0 },
1661
+ { "province": 'QC', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.12, "CO2eq Emissions (g/m3)": 1898.0 },
1662
+ { "province": 'SK', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 50.53, "CO2eq Emissions (g/m3)": 1840.0 },
1663
+ { "province": 'YT', "fuel_type": 'Gas', "CO2eq Emissions (kg/MBtu)": 52.50, "CO2eq Emissions (g/m3)": 1912.0 },
1664
+
1665
+ { "province": 'AB', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1666
+ { "province": 'BC', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1667
+ { "province": 'MB', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1668
+ { "province": 'NB', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1669
+ { "province": 'NL', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1670
+ { "province": 'NT', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1671
+ { "province": 'NS', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1672
+ { "province": 'NU', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1673
+ { "province": 'ON', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1674
+ { "province": 'PE', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1675
+ { "province": 'QC', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1676
+ { "province": 'SK', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1677
+ { "province": 'YT', "fuel_type": 'FuelOilNo2', "CO2eq Emissions (kg/MBtu)": 75.13, "CO2eq Emissions (g/m3)": 2763.0 },
1678
+
1679
+ { "province": 'AB', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1680
+ { "province": 'BC', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1681
+ { "province": 'MB', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1682
+ { "province": 'NB', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1683
+ { "province": 'NL', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1684
+ { "province": 'NT', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1685
+ { "province": 'NS', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1686
+ { "province": 'NU', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1687
+ { "province": 'ON', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1688
+ { "province": 'PE', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1689
+ { "province": 'QC', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1690
+ { "province": 'SK', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1691
+ { "province": 'YT', "fuel_type": 'Propane', "CO2eq Emissions (kg/MBtu)": 64.25, "CO2eq Emissions (g/m3)": 1548.00 },
1692
+
1693
+ { "province": 'AB', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 231.54, "CO2eq Emissions (g/m3)": 790.0 },
1694
+ { "province": 'BC', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 2.99, "CO2eq Emissions (g/m3)": 10.2 },
1695
+ { "province": 'MB', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 0.56, "CO2eq Emissions (g/m3)": 1.9 },
1696
+ { "province": 'NB', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 76.20, "CO2eq Emissions (g/m3)": 260.0 },
1697
+ { "province": 'NL', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 11.72, "CO2eq Emissions (g/m3)": 40.0 },
1698
+ { "province": 'NT', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 46.89, "CO2eq Emissions (g/m3)": 160.0 },
1699
+ { "province": 'NS', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 213.95, "CO2eq Emissions (g/m3)": 730.0 },
1700
+ { "province": 'NU', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 222.74, "CO2eq Emissions (g/m3)": 760.0 },
1701
+ { "province": 'ON', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 5.86, "CO2eq Emissions (g/m3)": 20.0 },
1702
+ { "province": 'PE', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 76.20, "CO2eq Emissions (g/m3)": 260.0 },
1703
+ { "province": 'QC', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 0.41, "CO2eq Emissions (g/m3)": 1.4 },
1704
+ { "province": 'SK', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 211.04, "CO2eq Emissions (g/m3)": 720.0 },
1705
+ { "province": 'YT', "fuel_type": 'Electricity', "CO2eq Emissions (kg/MBtu)": 16.41, "CO2eq Emissions (g/m3)": 140.0 }
1706
+ ]
1707
+ mbtu_to_gj = 1.05505585
1708
+ factor = ghg_data.detect { |item| (item[:province] == province) && (item[:fuel_type] == fuel_type) }
1709
+ raise "could not find ghg factor for province name #{province} and fuel_type #{fuel_type}" if factor.nil?
1710
+
1711
+ return factor[:"CO2eq Emissions (kg/MBtu)"] / mbtu_to_gj
1712
+ end
1713
+
1714
+ def bc_energy_step_code_performance_indicators
1715
+ # TEDI (Thermal Energy Demand Intensity) [kWh/(m2.year)]
1716
+ command = "SELECT Value
1717
+ FROM TabularDataWithStrings
1718
+ WHERE ReportName='EnergyMeters'
1719
+ AND ReportForString='Entire Facility'
1720
+ AND TableName='Annual and Peak Values - Other'
1721
+ AND RowName='Baseboard:EnergyTransfer'
1722
+ AND ColumnName='Annual Value'
1723
+ AND Units='GJ'"
1724
+ baseboard_energy_transfer_gj = @sqlite_file.get.execAndReturnFirstDouble(command)
1725
+ baseboard_energy_transfer_kwh = OpenStudio.convert(baseboard_energy_transfer_gj.to_f, 'GJ', 'kWh')
1726
+ command = "SELECT Value
1727
+ FROM TabularDataWithStrings
1728
+ WHERE ReportName='EnergyMeters'
1729
+ AND ReportForString='Entire Facility'
1730
+ AND TableName='Annual and Peak Values - Other'
1731
+ AND RowName='HeatingCoils:EnergyTransfer'
1732
+ AND ColumnName='Annual Value'
1733
+ AND Units='GJ'"
1734
+ heating_coils_energy_transfer_gj = @sqlite_file.get.execAndReturnFirstDouble(command)
1735
+ heating_coils_energy_transfer_kwh = OpenStudio.convert(heating_coils_energy_transfer_gj.to_f, 'GJ', 'kWh')
1736
+ tedi_kwh_per_m_sq = (baseboard_energy_transfer_kwh.to_f + heating_coils_energy_transfer_kwh.to_f) / @btap_data['bldg_conditioned_floor_area_m_sq']
1737
+ @btap_data.merge!('bc_step_code_tedi_kwh_per_m_sq' => tedi_kwh_per_m_sq)
1738
+
1739
+ # MEUI (Mechanical Energy Use Intensity) [kWh/(m2.year)]
1740
+ meui_gj_per_m_sq = @btap_data['energy_eui_heating_gj_per_m_sq'].to_f +
1741
+ @btap_data['energy_eui_cooling_gj_per_m_sq'].to_f +
1742
+ @btap_data['energy_eui_fans_gj_per_m_sq'].to_f +
1743
+ @btap_data['energy_eui_pumps_gj_per_m_sq'].to_f +
1744
+ @btap_data['energy_eui_water systems_gj_per_m_sq'].to_f
1745
+ meui_kwh_per_m_sq = OpenStudio.convert(meui_gj_per_m_sq, 'GJ', 'kWh').to_f
1746
+ @btap_data.merge!('bc_step_code_meui_kwh_per_m_sq' => meui_kwh_per_m_sq)
1747
+ end
1748
+
1749
+ # The below method calculates energy demands and peak loads calculations as per PHIUS and NECB; and compares them to see if NECB meets PHIUS' performance criteria.
1750
+ ### References:
1751
+ ### (1) PHIUS 2021 Passive Building Standard Standard-Setting Documentation. Available at https://www.phius.org/phius-certification-for-buildings-products/project-certification/phius-2021-emissions-down-scale-up
1752
+ ### (2) Wright, L. (2019). Setting the Heating/Cooling Performance Criteria for the PHIUS 2018 Passive Building Standard. In ASHRAE Topical Conference Proceedings, pp. 399-409
1753
+ def phius_performance_indicators(model)
1754
+ ### Envelope to Floor Area ratio (EnvFlr)
1755
+ ### Note: 'Floor Area' has been considered as iCFA (interior conditioned floor area) as per REF: Wright (2019)
1756
+ bldg_exterior_area_m_sq = @btap_data['bldg_exterior_area_m_sq']
1757
+ bldg_conditioned_floor_area_m_sq = @btap_data['bldg_conditioned_floor_area_m_sq']
1758
+ bldg_conditioned_floor_area_ft_sq = OpenStudio.convert(bldg_conditioned_floor_area_m_sq, 'm^2', 'ft^2').get
1759
+ envelope_to_floor_area_ratio = bldg_exterior_area_m_sq / bldg_conditioned_floor_area_m_sq
1760
+
1761
+ ### UnitDens: Unit density (1/ft2) (inverse of the floor area per unit) in PHIUS, 2021
1762
+ # Note: if commercial buildings, set the number of units to 1 and divide by the floor area
1763
+ # This is the list of building types considered as some sort of residential buildings when the whole building method is used
1764
+ building_type_names_necb_2011 = ['Dormitory', 'Hospital', 'Hotel', 'Motel', 'Multi-unit residential', 'Penitentiary']
1765
+ building_type_names_necb_2015 = ['Dormitory', 'Health care clinic', 'Hospital', 'Hotel/Motel', 'Long-term care - dwelling units', 'Long-term care - other', 'Multi-unit residential building', 'Penitentiary']
1766
+ building_type_names_necb_2017 = ['Dormitory', 'Health care clinic', 'Hospital', 'Hotel/Motel', 'Long-term care - dwelling units', 'Long-term care - other', 'Multi-unit residential building', 'Penitentiary']
1767
+ building_type_names_list = building_type_names_necb_2011 + building_type_names_necb_2015 + building_type_names_necb_2017
1768
+ building_type_names_list = building_type_names_list.uniq
1769
+ # This is the list of space types considered as some sort of residential spaces when the space type method is used
1770
+ space_type_names_necb_2011 = ['Dormitory - living quarters', 'Dwelling Unit(s)', 'Hotel/Motel - rooms', 'Hway lodging - rooms']
1771
+ space_type_names_necb_2015 = ['Guest room', 'Dormitory living quarters', 'Dwelling units general', 'Dwelling units long-term', 'Fire station sleeping quarters', 'Health care facility patient room', 'Health care facility recovery room']
1772
+ space_type_names_necb_2017 = ['Guest room', 'Dormitory living quarters', 'Dwelling units general', 'Dwelling units long-term', 'Fire station sleeping quarters', 'Health care facility patient room', 'Health care facility recovery room']
1773
+ space_type_names_list = space_type_names_necb_2011 + space_type_names_necb_2015 + space_type_names_necb_2017
1774
+ space_type_names_list = space_type_names_list.uniq
1775
+ sum_handle = 0.0
1776
+ number_of_dwelling_units = 0.0
1777
+ @btap_data['space_table'].each do |space_info|
1778
+ building_type_name = space_info['building_type'].sub! 'building', ''
1779
+ building_type_name = building_type_name.strip unless building_type_name.nil?
1780
+ space_type_name = space_info['space_type_name']
1781
+ if !space_type_name.include?('WholeBuilding')
1782
+ # puts "This_is_the_space_type_method"
1783
+ space_type_name = space_info['space_type_name'].sub! 'Space Function ', '' # This removes 'Space Function' from space type name
1784
+ if space_type_names_list.include?(space_type_name)
1785
+ number_of_dwelling_units += 1.0 * space_info['multiplier']
1786
+ sum_handle += OpenStudio.convert(space_info['floor_area_m2'], 'm^2', 'ft^2').get * space_info['multiplier']
1787
+ end
1788
+ elsif space_type_name.include?('WholeBuilding') && building_type_names_list.include?(building_type_name) && space_info['is_conditioned'] == 'Yes'
1789
+ # puts "This_is_the_whole_building_method"
1790
+ number_of_dwelling_units += 1.0 * space_info['multiplier']
1791
+ sum_handle += OpenStudio.convert(space_info['floor_area_m2'], 'm^2', 'ft^2').get * space_info['multiplier']
1792
+ end
1793
+ end
1794
+ # Calculate what percentage of conditioned floor area has space types of the 'space_type_names_list' list.
1795
+ # This percentage is used to determine if most of a building model is sort of dwelling type or not.
1796
+ # The threshold for this percentage has been set to 60% based on the below reference:
1797
+ # GSA (2012), Circulation: Defining and planning, U.S. General Services Administration, Available at Https://Www.Gsa.Gov/
1798
+ # The above reference says: 'As a general planning rule of thumb, Circulation Area comprises roughly 25 to 40% of the total Usable Area.'
1799
+ # Moreover, ~63% and ~41% of the SmallHotel and LargeHotel archetype, respectively, are guest rooms. So, the threshold has been chosen as 40%.
1800
+ percentage_dwelling = 100.0 * sum_handle / bldg_conditioned_floor_area_ft_sq
1801
+ # now, calculate UnitDens depending on whether a building model is sort of dwelling type or not
1802
+ if percentage_dwelling >= 40.0 && number_of_dwelling_units > 0.0
1803
+ unit_density_per_ft_sq = 1.0 / (sum_handle / number_of_dwelling_units)
1804
+ else # i.e. if commercial buildings, set the number of units to 1 and divide by the floor area
1805
+ unit_density_per_ft_sq = 1.0 / bldg_conditioned_floor_area_ft_sq
1806
+ end
1807
+
1808
+ ### Get weather file name
1809
+ weather_file = model.weatherFile.get.path.get.to_s
1810
+ weather_file = weather_file.split('/')[-1]
1811
+
1812
+ ### Cooling Degree Days, base 50degF
1813
+ cdd10_degree_c_days = BTAP::Environment::WeatherFile.new(weather_file).cdd10
1814
+ cdd50_degree_f_days = cdd10_degree_c_days * 9.0 / 5.0
1815
+
1816
+ ### Heating Degree Days, base 65degF (note that base temperature of 18degC has been considered)
1817
+ hdd18_degree_c_days = BTAP::Environment::WeatherFile.new(weather_file).hdd18
1818
+ hdd65_degree_f_days = hdd18_degree_c_days * 9.0 / 5.0
1819
+
1820
+ ### Dehumidification degree days
1821
+ ### ('Dehumidification degree-days, base 0.010' in REF: Wright (2019))
1822
+ dehumidification_degree_days = BTAP::Environment::WeatherFile.new(weather_file).calculate_humidity_ratio
1823
+
1824
+ ### annual global horizontal irradiance (GHI)
1825
+ annual_ghi_kwh_per_m_sq = BTAP::Environment::WeatherFile.new(weather_file).get_annual_ghi
1826
+
1827
+ ### THD-1 Temperature at the colder of the two heating design conditions in PHIUS, 2021
1828
+ ### ('Heating design temperature' in REF: Wright (2019))
1829
+ thd_degree_c = BTAP::Environment::WeatherFile.new(weather_file).heating_design_info[1]
1830
+ thd_degree_f = OpenStudio.convert(thd_degree_c, 'C', 'F').get
1831
+
1832
+ ### TCD Temperature at the cooling design condition in PHIUS, 2021
1833
+ ### ('Cooling design temperature' in REF: Wright (2019))
1834
+ tcd_degree_c = BTAP::Environment::WeatherFile.new(weather_file).cooling_design_info[2]
1835
+ tcd_degree_f = OpenStudio.convert(tcd_degree_c.to_f, 'C', 'F').get
1836
+
1837
+ ### IGHL (Irradiance, Global, at the heating design condition) (Btu/h.ft2) in PHIUS, 2021
1838
+ solar_irradiance_on_heating_design_day_w_per_m_sq = BTAP::Environment::WeatherFile.new(weather_file).get_ghi_on_heating_design_day
1839
+ solar_irradiance_on_heating_design_day_btu_per_hr_ft_sq = OpenStudio.convert(solar_irradiance_on_heating_design_day_w_per_m_sq.to_f, 'W/m^2', 'Btu/ft^2*h').get
1840
+
1841
+ ### IGCL (Irradiance, Global, at the cooling design condition) (Btu/h.ft2) in PHIUS, 2021
1842
+ solar_irradiance_on_cooling_design_day_w_per_m_sq = BTAP::Environment::WeatherFile.new(weather_file).get_ghi_on_cooling_design_day
1843
+ solar_irradiance_on_cooling_design_day_btu_per_hr_ft_sq = OpenStudio.convert(solar_irradiance_on_cooling_design_day_w_per_m_sq.to_f, 'W/m^2', 'Btu/ft^2*h').get
1844
+
1845
+ ### occupant density (persons per ft2 of floor area)
1846
+ sum_handle = 0.0
1847
+ @btap_data['space_type_table'].each do |space_info|
1848
+ unless space_info['occ_per_m_sq'].nil?
1849
+ sum_handle += space_info['floor_m_sq'] * space_info['occ_per_m_sq']
1850
+ end
1851
+ end
1852
+ occ_density_person_per_m_sq = sum_handle / bldg_conditioned_floor_area_m_sq
1853
+ occ_density_person_per_ft_sq = OpenStudio.convert(occ_density_person_per_m_sq, 'ft^2', 'm^2').get
1854
+
1855
+ ### marginal electricity price ($/kWh)
1856
+ ### ('Electricity price' in REF: Wright (2019))
1857
+ electricity_price_per_gj = @btap_data['cost_utility_neb_electricity_cost_per_m_sq'] / @btap_data['energy_eui_electricity_gj_per_m_sq']
1858
+ electricity_price_per_kwh = OpenStudio.convert(electricity_price_per_gj, 'kWh', 'GJ').get # note: this is not GJ to kWh since 1/GJ should be converted to 1/kWh.
1859
+
1860
+ ### Calculate annual heating and cooling energy demands based on PHIUS
1861
+ # REF: page 27 of PHIUS 2021 Passive Building Standard Standard-Setting Documentation. Available at https://www.phius.org/phius-certification-for-buildings-products/project-certification/phius-2021-emissions-down-scale-up
1862
+ annual_heating_demand_kbtu_per_ft_sq_phius = 3.2606827206 +
1863
+ 1.1634499236 * envelope_to_floor_area_ratio +
1864
+ 904.39163818 * unit_density_per_ft_sq +
1865
+ 0.000604853 * hdd65_degree_f_days +
1866
+ -0.001645777 * annual_ghi_kwh_per_m_sq +
1867
+ -11.87299596 * electricity_price_per_kwh +
1868
+ (envelope_to_floor_area_ratio - 1.766) * (envelope_to_floor_area_ratio - 1.766) * 0.8314860529 +
1869
+ (envelope_to_floor_area_ratio - 1.766) * (hdd65_degree_f_days - 5860.0833333) * 0.0002310823 +
1870
+ (hdd65_degree_f_days - 5860.0833333) * (hdd65_degree_f_days - 5860.0833333) * -5.736435e-8 +
1871
+ (hdd65_degree_f_days - 5860.0833333) * (annual_ghi_kwh_per_m_sq - 1451.0633333) * -3.260379e-7 +
1872
+ (envelope_to_floor_area_ratio - 1.766) * (electricity_price_per_kwh - -0.2029193333) * -3.851052937 +
1873
+ (hdd65_degree_f_days - 5860.0833333) * (electricity_price_per_kwh - -0.2029193333) * -0.001897043
1874
+ annual_heating_demand_kwh_per_m_sq_phius = OpenStudio.convert(annual_heating_demand_kbtu_per_ft_sq_phius, 'kBtu/ft^2', 'kWh/m^2').get
1875
+ @btap_data.merge!('phius_annual_heating_demand_kwh_per_m_sq' => annual_heating_demand_kwh_per_m_sq_phius)
1876
+
1877
+ # REF: page 28 of PHIUS 2021 Passive Building Standard Standard-Setting Documentation. Available at https://www.phius.org/phius-certification-for-buildings-products/project-certification/phius-2021-emissions-down-scale-up
1878
+ annual_cooling_demand_kbtu_per_ft_sq_phius = -6.510791255 +
1879
+ -0.749993351 * envelope_to_floor_area_ratio +
1880
+ 0.0004550801 * cdd50_degree_f_days +
1881
+ 0.004990109 * annual_ghi_kwh_per_m_sq +
1882
+ 7.9460878688 * dehumidification_degree_days +
1883
+ (envelope_to_floor_area_ratio - 1.766) * (envelope_to_floor_area_ratio - 1.766) * 1.6367059356 +
1884
+ (cdd50_degree_f_days - 4104.8333333) * (cdd50_degree_f_days - 4104.8333333) * 8.6952014e-8 +
1885
+ (envelope_to_floor_area_ratio - 1.766) * (annual_ghi_kwh_per_m_sq - 1451.0633333) * 0.001671947 +
1886
+ (cdd50_degree_f_days - 4104.8333333) * (annual_ghi_kwh_per_m_sq - 1451.0633333) * 0.0000013639 +
1887
+ (unit_density_per_ft_sq - 0.0008646735) * (dehumidification_degree_days - 0.3233057481) * 5547.7542211 +
1888
+ (dehumidification_degree_days - 0.3233057481) * (electricity_price_per_kwh - 0.2029193333) * -15.67511944 +
1889
+ 1624.6144639 * unit_density_per_ft_sq
1890
+ annual_cooling_demand_kwh_per_m_sq_phius = OpenStudio.convert(annual_cooling_demand_kbtu_per_ft_sq_phius, 'kBtu/ft^2', 'kWh/m^2').get
1891
+ @btap_data.merge!('phius_annual_cooling_demand_kwh_per_m_sq' => annual_cooling_demand_kwh_per_m_sq_phius)
1892
+
1893
+ ### Calculate peak heating and cooling loads based on PHIUS
1894
+ # REF: page 29 of PHIUS 2021 Passive Building Standard Standard-Setting Documentation. Available at https://www.phius.org/phius-certification-for-buildings-products/project-certification/phius-2021-emissions-down-scale-up
1895
+ peak_heating_load_btu_per_hr_ft_sq_phius = 4.6700403241 +
1896
+ 0.6774809481 * envelope_to_floor_area_ratio +
1897
+ 239.08369574 * occ_density_person_per_ft_sq +
1898
+ 596.681543 * unit_density_per_ft_sq +
1899
+ -0.000177742 * hdd65_degree_f_days +
1900
+ -0.076727655 * thd_degree_f +
1901
+ -0.03316804 * solar_irradiance_on_heating_design_day_btu_per_hr_ft_sq +
1902
+ -4.140193817 * electricity_price_per_kwh +
1903
+ (envelope_to_floor_area_ratio - 1.766) * (envelope_to_floor_area_ratio - 1.766) * 0.8449921713 +
1904
+ (hdd65_degree_f_days - 5860.0833333) * (hdd65_degree_f_days - 5860.0833333) * 2.8376386e-8 +
1905
+ (envelope_to_floor_area_ratio - 1.766) * (thd_degree_f - 14.7102) * -0.013821021 +
1906
+ (unit_density_per_ft_sq - 0.0008646735) * (thd_degree_f - 14.7102) * -20.10551451 +
1907
+ (hdd65_degree_f_days - 5860.0833333) * (thd_degree_f - 14.7102) * 5.1870203e-6 +
1908
+ (thd_degree_f - 14.7102) * (electricity_price_per_kwh - 0.2029193333) * 0.1264922802
1909
+ peak_heating_load_w_per_m_sq_phius = OpenStudio.convert(peak_heating_load_btu_per_hr_ft_sq_phius, 'Btu/ft^2*h', 'W/m^2').get
1910
+ @btap_data.merge!('phius_peak_heating_load_w_per_m_sq' => peak_heating_load_w_per_m_sq_phius)
1911
+
1912
+ # REF: page 30 of PHIUS 2021 Passive Building Standard Standard-Setting Documentation. Available at https://www.phius.org/phius-certification-for-buildings-products/project-certification/phius-2021-emissions-down-scale-up
1913
+ peak_cooling_load_btu_per_hr_ft_sq_phius = -7.289806442 +
1914
+ 98.245977611 * occ_density_person_per_ft_sq +
1915
+ 236.93351876 * unit_density_per_ft_sq +
1916
+ 0.0967328928 * tcd_degree_f +
1917
+ 0.010777725 * solar_irradiance_on_cooling_design_day_btu_per_hr_ft_sq +
1918
+ (cdd50_degree_f_days - 4104.8333333) * (cdd50_degree_f_days - 4104.8333333) * 1.7699655e-8 +
1919
+ (cdd50_degree_f_days - 4104.8333333) * (tcd_degree_f - 78.127) * 6.5268802e-6 +
1920
+ (tcd_degree_f - 78.127) * (envelope_to_floor_area_ratio - 1.766) * 0.0165401721 +
1921
+ (tcd_degree_f - 78.127) * (occ_density_person_per_ft_sq - 0.0027218) * 8.0465528305 +
1922
+ (cdd50_degree_f_days - 4104.8333333) * (envelope_to_floor_area_ratio - 1.766) * 0.0000322288 +
1923
+ (envelope_to_floor_area_ratio - 1.766) * (envelope_to_floor_area_ratio - 1.766) * 0.6579032913
1924
+ peak_cooling_load_w_per_m_sq_phius = OpenStudio.convert(peak_cooling_load_btu_per_hr_ft_sq_phius, 'Btu/ft^2*h', 'W/m^2').get
1925
+ @btap_data.merge!('phius_peak_cooling_load_w_per_m_sq' => peak_cooling_load_w_per_m_sq_phius)
1926
+
1927
+ ### Gather annual heating and cooling energy demands based on NECB
1928
+
1929
+ annual_heating_demand_kwh_per_m_sq_necb = OpenStudio.convert(@btap_data['energy_eui_heating_gj_per_m_sq'], 'GJ', 'kWh') unless @btap_data['energy_eui_heating_gj_per_m_sq'].nil?
1930
+ annual_cooling_demand_kwh_per_m_sq_necb = OpenStudio.convert(@btap_data['energy_eui_cooling_gj_per_m_sq'], 'GJ', 'kWh') unless @btap_data['energy_eui_cooling_gj_per_m_sq'].nil?
1931
+
1932
+ ### Gather peak heating and cooling loads based on NECB
1933
+ peak_heating_load_w_per_m_sq_necb = @btap_data['heating_peak_w_per_m_sq']
1934
+ peak_cooling_load_w_per_m_sq_necb = @btap_data['cooling_peak_w_per_m_sq']
1935
+ @btap_data.merge!('peak_heating_load_w_per_m_sq_necb' => peak_heating_load_w_per_m_sq_necb)
1936
+ @btap_data.merge!('peak_cooling_load_w_per_m_sq_necb' => peak_cooling_load_w_per_m_sq_necb)
1937
+
1938
+ ### Compare annual heating and cooling energy demands of NECB with PHIUS to see if NECB meets PHIUS
1939
+ if annual_heating_demand_kwh_per_m_sq_necb.to_f <= annual_heating_demand_kwh_per_m_sq_phius.to_f
1940
+ @btap_data.merge!('phius_necb_meet_heating_demand' => 'True')
1941
+ else
1942
+ @btap_data.merge!('phius_necb_meet_heating_demand' => 'False')
1943
+ end
1944
+ if annual_cooling_demand_kwh_per_m_sq_necb.to_f <= annual_cooling_demand_kwh_per_m_sq_phius.to_f
1945
+ @btap_data.merge!('phius_necb_meet_cooling_demand' => 'True')
1946
+ else
1947
+ @btap_data.merge!('phius_necb_meet_cooling_demand' => 'False')
1948
+ end
1949
+
1950
+ ### Compare peak heating and cooling loads of NECB with PHIUS to see if NECB meets PHIUS
1951
+ if peak_heating_load_w_per_m_sq_necb.to_f <= peak_heating_load_w_per_m_sq_phius.to_f
1952
+ @btap_data.merge!('phius_necb_meet_heating_peak_load' => 'True')
1953
+ else
1954
+ @btap_data.merge!('phius_necb_meet_heating_peak_load' => 'False')
1955
+ end
1956
+ if peak_cooling_load_w_per_m_sq_necb.to_f <= peak_cooling_load_w_per_m_sq_phius.to_f
1957
+ @btap_data.merge!('phius_necb_meet_cooling_peak_load' => 'True')
1958
+ else
1959
+ @btap_data.merge!('phius_necb_meet_cooling_peak_load' => 'False')
1960
+ end
1961
+ # def phius_metrics(model)
1962
+ end
1963
+ end