openstudio-standards 0.3.1.rc2 → 0.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (376) hide show
  1. checksums.yaml +4 -4
  2. data/data/inventory/thermal_bridging.csv +90 -0
  3. data/data/standards/OpenStudio_Standards-deer-comstock.xlsx +0 -0
  4. data/data/standards/manage_OpenStudio_Standards.rb +1 -1
  5. data/data/standards/test_performance_expected_dd_results.csv +2014 -1891
  6. data/lib/openstudio-standards/btap/analysis.rb +8 -8
  7. data/lib/openstudio-standards/btap/bridging.rb +665 -646
  8. data/lib/openstudio-standards/btap/btap.model.rb +14 -14
  9. data/lib/openstudio-standards/btap/btap.rb +7 -7
  10. data/lib/openstudio-standards/btap/btap_result.rb +1 -1
  11. data/lib/openstudio-standards/btap/economics.rb +23 -23
  12. data/lib/openstudio-standards/btap/envelope.rb +8 -8
  13. data/lib/openstudio-standards/btap/equest.rb +1 -1
  14. data/lib/openstudio-standards/btap/geometry.rb +2 -2
  15. data/lib/openstudio-standards/btap/mpc.rb +7 -7
  16. data/lib/openstudio-standards/btap/schedules.rb +1 -1
  17. data/lib/openstudio-standards/btap/simmanager.rb +4 -4
  18. data/lib/openstudio-standards/btap/spaceloads.rb +26 -26
  19. data/lib/openstudio-standards/btap/utilities.rb +6 -6
  20. data/lib/openstudio-standards/btap/vintagizer.rb +1 -1
  21. data/lib/openstudio-standards/constructions/information.rb +83 -0
  22. data/lib/openstudio-standards/constructions/materials/modify.rb +72 -0
  23. data/lib/openstudio-standards/constructions/modify.rb +80 -0
  24. data/lib/openstudio-standards/create_typical/create_typical.rb +983 -0
  25. data/lib/openstudio-standards/create_typical/enumerations.rb +484 -0
  26. data/lib/openstudio-standards/create_typical/space_type_blend.rb +791 -0
  27. data/lib/openstudio-standards/create_typical/space_type_ratios.rb +494 -0
  28. data/lib/openstudio-standards/daylighting/space.rb +47 -0
  29. data/lib/openstudio-standards/geometry/create.rb +801 -0
  30. data/lib/openstudio-standards/geometry/create_bar.rb +2171 -0
  31. data/lib/openstudio-standards/geometry/information.rb +462 -0
  32. data/lib/openstudio-standards/geometry/modify.rb +48 -0
  33. data/lib/openstudio-standards/hvac/air_loop/information.rb +79 -0
  34. data/lib/openstudio-standards/hvac/cbecs_hvac.rb +616 -0
  35. data/lib/openstudio-standards/hvac/setpoint_managers/information.rb +91 -0
  36. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirTerminalSingleDuctVAVReheat.rb +1 -1
  37. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.AirTerminalSingleDuctVAVReheat.rb +1 -1
  38. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
  39. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Model.rb +1 -1
  40. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
  41. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +2 -2
  42. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.hvac_systems.rb +1 -1
  43. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
  44. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +4 -36
  45. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.hvac_systems.rb +1 -1
  46. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
  47. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +4 -36
  48. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +3 -3
  49. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb +1 -1
  50. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirTerminalSingleDuctVAVReheat.rb +1 -1
  51. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.elevators.rb +1 -1
  52. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirTerminalSingleDuctVAVReheat.rb +1 -1
  53. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.CoilHeatingGas.rb +1 -1
  54. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.elevators.rb +1 -1
  55. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
  56. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
  57. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +7 -7
  58. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Courthouse.rb +8 -8
  59. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.FullServiceRestaurant.rb +14 -14
  60. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.HighRiseApartment.rb +9 -9
  61. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Hospital.rb +16 -16
  62. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +7 -7
  63. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterHighITE.rb +8 -8
  64. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterLowITE.rb +8 -8
  65. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeHotel.rb +11 -11
  66. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOffice.rb +7 -7
  67. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOfficeDetailed.rb +9 -9
  68. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOffice.rb +8 -8
  69. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOfficeDetailed.rb +11 -11
  70. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MidriseApartment.rb +9 -9
  71. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Outpatient.rb +19 -19
  72. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.PrimarySchool.rb +10 -10
  73. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.QuickServiceRestaurant.rb +13 -13
  74. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStandalone.rb +6 -6
  75. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStripmall.rb +6 -6
  76. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SecondarySchool.rb +9 -9
  77. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterHighITE.rb +8 -8
  78. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterLowITE.rb +8 -8
  79. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallHotel.rb +8 -8
  80. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOffice.rb +8 -8
  81. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOfficeDetailed.rb +11 -11
  82. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperMarket.rb +10 -10
  83. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperTallBuilding.rb +19 -19
  84. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.TallBuilding.rb +18 -18
  85. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Warehouse.rb +6 -6
  86. data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +957 -957
  87. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirConditionerVariableRefrigerantFlow.rb +1 -1
  88. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirTerminalSingleDuctVAVReheat.rb +1 -1
  89. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWaterToAirHeatPumpEquationFit.rb +84 -16
  90. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingDXSingleSpeed.rb +1 -1
  91. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingGas.rb +1 -1
  92. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWaterToAirHeatPumpEquationFit.rb +61 -10
  93. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ControllerWaterCoil.rb +1 -1
  94. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoolingTower.rb +1 -1
  95. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +1 -1
  96. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanConstantVolume.rb +1 -1
  97. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanOnOff.rb +1 -1
  98. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanVariableVolume.rb +1 -1
  99. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanZoneExhaust.rb +1 -1
  100. data/lib/openstudio-standards/prototypes/common/objects/Prototype.HeatExchangerAirToAirSensibleAndLatent.rb +2 -2
  101. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.exterior_lights.rb +4 -4
  102. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.hvac.rb +4 -4
  103. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +43 -30
  104. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.swh.rb +1 -1
  105. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +18 -11
  106. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
  107. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +774 -117
  108. data/lib/openstudio-standards/prototypes/common/objects/Prototype.radiant_system_controls.rb +340 -481
  109. data/lib/openstudio-standards/prototypes/common/objects/Prototype.refrigeration.rb +3 -3
  110. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +3 -3
  111. data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +22 -22
  112. data/lib/openstudio-standards/prototypes/deer/deer.Model.rb +1 -1
  113. data/lib/openstudio-standards/qaqc/calibration.rb +131 -0
  114. data/lib/openstudio-standards/qaqc/create_results.rb +983 -0
  115. data/lib/openstudio-standards/qaqc/envelope.rb +399 -0
  116. data/lib/openstudio-standards/qaqc/eui.rb +213 -0
  117. data/lib/openstudio-standards/qaqc/hvac.rb +1943 -0
  118. data/lib/openstudio-standards/qaqc/internal_loads.rb +568 -0
  119. data/lib/openstudio-standards/qaqc/reporting.rb +141 -0
  120. data/lib/openstudio-standards/qaqc/schedules.rb +129 -0
  121. data/lib/openstudio-standards/qaqc/service_water_heating.rb +273 -0
  122. data/lib/openstudio-standards/qaqc/weather_files.rb +497 -0
  123. data/lib/openstudio-standards/qaqc/zone_conditions.rb +278 -0
  124. data/lib/openstudio-standards/schedules/create.rb +364 -0
  125. data/lib/openstudio-standards/schedules/information.rb +169 -0
  126. data/lib/openstudio-standards/schedules/modify.rb +445 -0
  127. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +110 -71
  128. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +3 -3
  129. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctVAVReheat.rb +4 -4
  130. data/lib/openstudio-standards/standards/Standards.BoilerHotWater.rb +2 -1
  131. data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +16 -10
  132. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +4 -4
  133. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXTwoSpeed.rb +1 -1
  134. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +1 -1
  135. data/lib/openstudio-standards/standards/Standards.CoilDX.rb +4 -4
  136. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXMultiSpeed.rb +1 -1
  137. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +5 -5
  138. data/lib/openstudio-standards/standards/Standards.CoilHeatingGas.rb +1 -1
  139. data/lib/openstudio-standards/standards/Standards.CoilHeatingGasMultiStage.rb +1 -1
  140. data/lib/openstudio-standards/standards/Standards.CoilHeatingWaterToAirHeatPumpEquationFit.rb +1 -1
  141. data/lib/openstudio-standards/standards/Standards.Construction.rb +17 -18
  142. data/lib/openstudio-standards/standards/Standards.CoolingTower.rb +6 -6
  143. data/lib/openstudio-standards/standards/Standards.CoolingTowerSingleSpeed.rb +1 -1
  144. data/lib/openstudio-standards/standards/Standards.CoolingTowerTwoSpeed.rb +1 -1
  145. data/lib/openstudio-standards/standards/Standards.CoolingTowerVariableSpeed.rb +1 -1
  146. data/lib/openstudio-standards/standards/Standards.Fan.rb +6 -12
  147. data/lib/openstudio-standards/standards/Standards.FanVariableVolume.rb +2 -2
  148. data/lib/openstudio-standards/standards/Standards.FluidCooler.rb +1 -1
  149. data/lib/openstudio-standards/standards/Standards.HeaderedPumpsVariableSpeed.rb +1 -1
  150. data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +3 -3
  151. data/lib/openstudio-standards/standards/Standards.Model.rb +411 -261
  152. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +2 -2
  153. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +94 -29
  154. data/lib/openstudio-standards/standards/Standards.Pump.rb +2 -2
  155. data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +2 -2
  156. data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +14 -14
  157. data/lib/openstudio-standards/standards/Standards.Space.rb +37 -30
  158. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +38 -29
  159. data/lib/openstudio-standards/standards/Standards.SubSurface.rb +7 -7
  160. data/lib/openstudio-standards/standards/Standards.Surface.rb +13 -13
  161. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +109 -66
  162. data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +11 -4
  163. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +6 -6
  164. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb +1 -1
  165. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PlantLoop.rb +1 -1
  166. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Space.rb +1 -1
  167. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.Space.rb +1 -1
  168. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirLoopHVAC.rb +4 -4
  169. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
  170. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Space.rb +4 -4
  171. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirLoopHVAC.rb +4 -4
  172. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
  173. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.CoolingTowerVariableSpeed.rb +1 -1
  174. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +5 -21
  175. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Space.rb +4 -4
  176. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.WaterHeaterMixed.rb +1 -1
  177. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.ZoneHVACComponent.rb +1 -1
  178. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirLoopHVAC.rb +36 -4
  179. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
  180. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.CoolingTowerVariableSpeed.rb +1 -1
  181. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Space.rb +4 -4
  182. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.ZoneHVACComponent.rb +1 -1
  183. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/comstock_ashrae_90_1_2016.AirLoopHVAC.rb +26 -0
  184. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +53 -10
  185. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
  186. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerVariableSpeed.rb +1 -1
  187. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +6 -6
  188. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb +2 -2
  189. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/comstock_ashrae_90_1_2019.AirLoopHVAC.rb +26 -0
  190. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.curves.json +211 -211
  191. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.economizers.json +14 -14
  192. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirLoopHVAC.rb +4 -4
  193. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.rb +1 -1
  194. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.PlantLoop.rb +1 -1
  195. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.economizers.json +14 -14
  196. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirLoopHVAC.rb +4 -4
  197. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.rb +1 -1
  198. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.PlantLoop.rb +1 -1
  199. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +6 -6
  200. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
  201. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.CoolingTowerVariableSpeed.rb +1 -1
  202. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.PlantLoop.rb +1 -1
  203. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.Space.rb +4 -4
  204. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirLoopHVAC.rb +6 -6
  205. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
  206. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.CoolingTowerVariableSpeed.rb +1 -1
  207. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.PlantLoop.rb +1 -1
  208. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.Space.rb +4 -4
  209. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +22 -28
  210. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +1 -1
  211. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +2 -2
  212. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +1 -74
  213. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +7 -59
  214. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +1 -1
  215. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +1 -1
  216. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +1 -1
  217. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +1 -1
  218. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +1 -21
  219. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.DesignSpecificationOutdoorAir.rb +101 -0
  220. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +1 -1
  221. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +1 -1
  222. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +1 -1
  223. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +1 -1
  224. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +643 -526
  225. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +8 -2
  226. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +17 -77
  227. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +74 -16
  228. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +96 -44
  229. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +6 -6
  230. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +18 -6
  231. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +1 -1
  232. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +328 -74
  233. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +0 -118
  234. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +2 -1
  235. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_rejection.json +1 -1
  236. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_outdoor_air.md +35 -0
  237. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +1 -1
  238. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData.rb +228 -0
  239. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_enums.rb +131 -0
  240. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -1
  241. data/lib/openstudio-standards/standards/cbes/cbes.AirLoopHVAC.rb +5 -5
  242. data/lib/openstudio-standards/standards/cbes/cbes.Model.rb +1 -1
  243. data/lib/openstudio-standards/standards/cbes/cbes.PlantLoop.rb +1 -1
  244. data/lib/openstudio-standards/standards/cbes/cbes.Space.rb +1 -1
  245. data/lib/openstudio-standards/standards/cbes/cbes_t24_2005/cbes_t24_2005.Space.rb +1 -1
  246. data/lib/openstudio-standards/standards/cbes/cbes_t24_2008/cbes_t24_2008.Space.rb +1 -1
  247. data/lib/openstudio-standards/standards/deer/deer.AirLoopHVAC.rb +109 -27
  248. data/lib/openstudio-standards/standards/deer/deer.Space.rb +1 -1
  249. data/lib/openstudio-standards/standards/deer/deer_1985/data/deer_1985.economizers.json +246 -4
  250. data/lib/openstudio-standards/standards/deer/deer_1996/data/deer_1996.economizers.json +246 -4
  251. data/lib/openstudio-standards/standards/deer/deer_2003/data/deer_2003.economizers.json +246 -4
  252. data/lib/openstudio-standards/standards/deer/deer_2003/deer_2003.ThermalZone.rb +18 -18
  253. data/lib/openstudio-standards/standards/deer/deer_2007/data/deer_2007.economizers.json +246 -4
  254. data/lib/openstudio-standards/standards/deer/deer_2007/deer_2007.ThermalZone.rb +18 -18
  255. data/lib/openstudio-standards/standards/deer/deer_2011/data/deer_2011.economizers.json +246 -4
  256. data/lib/openstudio-standards/standards/deer/deer_2011/deer_2011.ThermalZone.rb +18 -18
  257. data/lib/openstudio-standards/standards/deer/deer_2014/data/deer_2014.economizers.json +248 -6
  258. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.Space.rb +3 -3
  259. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.ThermalZone.rb +18 -18
  260. data/lib/openstudio-standards/standards/deer/deer_2015/data/deer_2015.economizers.json +248 -6
  261. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.Space.rb +3 -3
  262. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.ThermalZone.rb +18 -18
  263. data/lib/openstudio-standards/standards/deer/deer_2017/data/deer_2017.economizers.json +248 -6
  264. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.Space.rb +3 -3
  265. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.ThermalZone.rb +18 -18
  266. data/lib/openstudio-standards/standards/deer/deer_2020/data/deer_2020.economizers.json +248 -6
  267. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.AirLoopHVAC.rb +18 -5
  268. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.FanVariableVolume.rb +1 -1
  269. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.Space.rb +3 -3
  270. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.ThermalZone.rb +18 -18
  271. data/lib/openstudio-standards/standards/deer/deer_2025/data/deer_2025.economizers.json +248 -6
  272. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.AirLoopHVAC.rb +3 -3
  273. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.FanVariableVolume.rb +1 -1
  274. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.Space.rb +3 -3
  275. data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.economizers.json +248 -6
  276. data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.heat_pumps.json +2 -2
  277. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.AirLoopHVAC.rb +3 -3
  278. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.FanVariableVolume.rb +1 -1
  279. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.Space.rb +3 -3
  280. data/lib/openstudio-standards/standards/deer/deer_2035/data/deer_2035.economizers.json +248 -6
  281. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.AirLoopHVAC.rb +3 -3
  282. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.FanVariableVolume.rb +1 -1
  283. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.Space.rb +3 -3
  284. data/lib/openstudio-standards/standards/deer/deer_2040/data/deer_2040.economizers.json +248 -6
  285. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.AirLoopHVAC.rb +3 -3
  286. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.FanVariableVolume.rb +1 -1
  287. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.Space.rb +3 -3
  288. data/lib/openstudio-standards/standards/deer/deer_2045/data/deer_2045.economizers.json +260 -0
  289. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.AirLoopHVAC.rb +3 -3
  290. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.FanVariableVolume.rb +1 -1
  291. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.Space.rb +3 -3
  292. data/lib/openstudio-standards/standards/deer/deer_2050/data/deer_2050.economizers.json +248 -6
  293. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.AirLoopHVAC.rb +3 -3
  294. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.FanVariableVolume.rb +1 -1
  295. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.Space.rb +3 -3
  296. data/lib/openstudio-standards/standards/deer/deer_2055/data/deer_2055.economizers.json +248 -6
  297. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.AirLoopHVAC.rb +3 -3
  298. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.FanVariableVolume.rb +1 -1
  299. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.Space.rb +3 -3
  300. data/lib/openstudio-standards/standards/deer/deer_2060/data/deer_2060.economizers.json +248 -6
  301. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.AirLoopHVAC.rb +3 -3
  302. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.FanVariableVolume.rb +1 -1
  303. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.Space.rb +3 -3
  304. data/lib/openstudio-standards/standards/deer/deer_2065/data/deer_2065.economizers.json +248 -6
  305. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.AirLoopHVAC.rb +3 -3
  306. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.FanVariableVolume.rb +1 -1
  307. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.Space.rb +3 -3
  308. data/lib/openstudio-standards/standards/deer/deer_2070/data/deer_2070.economizers.json +248 -6
  309. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.AirLoopHVAC.rb +3 -3
  310. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.FanVariableVolume.rb +1 -1
  311. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.Space.rb +3 -3
  312. data/lib/openstudio-standards/standards/deer/deer_2075/data/deer_2075.economizers.json +248 -6
  313. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.AirLoopHVAC.rb +3 -3
  314. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.FanVariableVolume.rb +1 -1
  315. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.Space.rb +3 -3
  316. data/lib/openstudio-standards/standards/deer/deer_pre_1975/data/deer_pre_1975.economizers.json +246 -4
  317. data/lib/openstudio-standards/standards/necb/BTAP1980TO2010/data/space_types.json +447 -223
  318. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/building_envelope.rb +1 -1
  319. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/data/space_types.json +447 -223
  320. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_systems.rb +5 -2
  321. data/lib/openstudio-standards/standards/necb/ECMS/data/chiller_types.json +25 -0
  322. data/lib/openstudio-standards/standards/necb/ECMS/data/chillers.json +44 -0
  323. data/lib/openstudio-standards/standards/necb/ECMS/data/curves.json +225 -0
  324. data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +2 -2
  325. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +193 -73
  326. data/lib/openstudio-standards/standards/necb/ECMS/pv_ground.rb +1 -1
  327. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +10 -4
  328. data/lib/openstudio-standards/standards/necb/NECB2011/beps_compliance_path.rb +7 -7
  329. data/lib/openstudio-standards/standards/necb/NECB2011/building_envelope.rb +4 -5
  330. data/lib/openstudio-standards/standards/necb/NECB2011/data/chiller_types.json +32 -0
  331. data/lib/openstudio-standards/standards/necb/NECB2011/data/chillers.json +1 -1
  332. data/lib/openstudio-standards/standards/necb/NECB2011/data/constants.json +36 -0
  333. data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +7 -7
  334. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernEducation.osm +47587 -0
  335. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernHealthCare.osm +49764 -0
  336. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Warehouse.osm +283 -297
  337. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_type_unit_definitions.txt +2 -1
  338. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +447 -223
  339. data/lib/openstudio-standards/standards/necb/NECB2011/data/standards_data.rb +3 -3
  340. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_multi_speed.rb +1 -1
  341. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +49 -27
  342. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +400 -202
  343. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +4 -4
  344. data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +637 -318
  345. data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +18 -1
  346. data/lib/openstudio-standards/standards/necb/NECB2015/necb_2015.rb +3 -3
  347. data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +637 -318
  348. data/lib/openstudio-standards/standards/necb/NECB2017/hvac_systems.rb +1 -1
  349. data/lib/openstudio-standards/standards/necb/NECB2017/necb_2017.rb +3 -3
  350. data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +1 -1
  351. data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +615 -307
  352. data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +4 -4
  353. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +10 -5
  354. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +1 -1
  355. data/lib/openstudio-standards/utilities/assertion.rb +128 -0
  356. data/lib/openstudio-standards/utilities/logging.rb +2 -3
  357. data/lib/openstudio-standards/utilities/object_info.rb +39 -18
  358. data/lib/openstudio-standards/utilities/schedule_translator.rb +8 -6
  359. data/lib/openstudio-standards/utilities/simulation.rb +24 -11
  360. data/lib/openstudio-standards/utilities/sqlfile.rb +10 -5
  361. data/lib/openstudio-standards/version.rb +1 -1
  362. data/lib/openstudio-standards/weather/Weather.Model.rb +8 -9
  363. data/lib/openstudio-standards/weather/Weather.stat_file.rb +3 -3
  364. data/lib/openstudio-standards/weather/information.rb +35 -0
  365. data/lib/openstudio-standards.rb +69 -5
  366. metadata +53 -17
  367. data/data/standards/OpenStudio_Standards-deer-ALL-comstock(space_types).xlsx +0 -0
  368. data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVAC.rb +0 -59
  369. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingWater.rb +0 -13
  370. data/lib/openstudio-standards/hvac_sizing/Siz.HVACComponent.rb +0 -36
  371. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +0 -898
  372. data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +0 -126
  373. data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +0 -356
  374. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.Model.rb +0 -35
  375. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +0 -110
  376. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTowerVariableSpeed.rb +0 -5
@@ -1,6 +1,9 @@
1
1
  # This class holds methods that apply NECB2011 rules.
2
2
  # @ref [References::NECB2011]
3
3
  class NECB2011 < Standard
4
+ require 'zip'
5
+ require 'open-uri'
6
+
4
7
  @template = new.class.name
5
8
  register_standard(@template)
6
9
  attr_reader :tbd
@@ -231,17 +234,19 @@ class NECB2011 < Standard
231
234
  output_meters: nil,
232
235
  airloop_economizer_type: nil,
233
236
  baseline_system_zones_map_option: nil,
234
- tbd_option: nil)
237
+ tbd_option: nil,
238
+ tbd_interpolate: false)
235
239
  model = load_building_type_from_library(building_type: building_type)
236
240
  return model_apply_standard(model: model,
237
241
  tbd_option: tbd_option,
242
+ tbd_interpolate: tbd_interpolate,
238
243
  epw_file: epw_file,
239
244
  sizing_run_dir: sizing_run_dir,
240
245
  primary_heating_fuel: primary_heating_fuel,
241
246
  dcv_type: dcv_type, # Four options: (1) 'NECB_Default', (2) 'No_DCV', (3) 'Occupancy_based_DCV' , (4) 'CO2_based_DCV'
242
247
  lights_type: lights_type, # Two options: (1) 'NECB_Default', (2) 'LED'
243
248
  lights_scale: lights_scale,
244
- daylighting_type: daylighting_type, # Two options: (1) 'NECB_Default', (2) 'add_daylighting_controls'
249
+ daylighting_type: daylighting_type, # Two options: (1) nil/none/false/'NECB_Default' (Option #1 puts daylighting sensors in the spaces as per NECB requirements; so some spaces may not have sensors), (2) 'add_daylighting_controls' (Option #2 puts daylighting sensors in all spaces regardless of NECB requirements)
245
250
  ecm_system_name: ecm_system_name,
246
251
  ecm_system_zones_map_option: ecm_system_zones_map_option, # (1) 'NECB_Default' (2) 'one_sys_per_floor' (3) 'one_sys_per_bldg'
247
252
  erv_package: erv_package,
@@ -306,6 +311,7 @@ class NECB2011 < Standard
306
311
  # code versions without modifying the build_protoype_model method or copying it wholesale for a few changes.
307
312
  def model_apply_standard(model:,
308
313
  tbd_option: nil,
314
+ tbd_interpolate: nil,
309
315
  epw_file:,
310
316
  sizing_run_dir: Dir.pwd,
311
317
  necb_reference_hp: false,
@@ -367,6 +373,11 @@ class NECB2011 < Standard
367
373
  fdwr_set = convert_arg_to_f(variable: fdwr_set, default: -1)
368
374
  srr_set = convert_arg_to_f(variable: srr_set, default: -1)
369
375
 
376
+ # Ensure the volume calculation in all spaces is done automatically
377
+ model.getSpaces.sort.each do |space|
378
+ space.autocalculateVolume
379
+ end
380
+
370
381
  apply_weather_data(model: model, epw_file: epw_file)
371
382
  apply_loads(model: model,
372
383
  lights_type: lights_type,
@@ -393,7 +404,12 @@ class NECB2011 < Standard
393
404
  apply_fdwr_srr_daylighting(model: model,
394
405
  fdwr_set: fdwr_set,
395
406
  srr_set: srr_set)
396
- apply_thermal_bridging(model: model, tbd_option: tbd_option)
407
+ apply_thermal_bridging(model: model,
408
+ tbd_option: tbd_option,
409
+ tbd_interpolate: tbd_interpolate,
410
+ wall_U: ext_wall_cond,
411
+ floor_U: ext_floor_cond,
412
+ roof_U: ext_roof_cond)
397
413
  apply_auto_zoning(model: model,
398
414
  sizing_run_dir: sizing_run_dir,
399
415
  lights_type: lights_type,
@@ -518,12 +534,12 @@ class NECB2011 < Standard
518
534
 
519
535
  # -------- Performace, Efficiencies, Controls and Sensors ------------
520
536
  #
521
- # Set code standard equipment charecteristics.
537
+ # Set code standard equipment characteristics.
522
538
  sql_db_vars_map = apply_standard_efficiencies(model: model,
523
539
  sizing_run_dir: sizing_run_dir,
524
540
  necb_reference_hp: self.fuel_type_set.necb_reference_hp)
525
541
  # Apply System
526
- ecm.apply_system_efficiencies_ecm(model: model, ecm_system_name: ecm_system_name)
542
+ ecm.apply_system_efficiencies_ecm(model: model, ecm_system_name: ecm_system_name, template_standard: self)
527
543
  # Apply ECM ERV charecteristics as required. Part 2 of above ECM.
528
544
  ecm.apply_erv_ecm_efficiency(model: model, erv_package: erv_package)
529
545
  # Apply DCV as required
@@ -537,7 +553,7 @@ class NECB2011 < Standard
537
553
  # Apply SHW Efficiency
538
554
  ecm.modify_shw_efficiency(model: model, shw_eff: shw_eff)
539
555
  # Apply daylight controls.
540
- model_add_daylighting_controls(model) if daylighting_type == 'add_daylighting_controls'
556
+ model_add_daylighting_controls(model: model, daylighting_type: daylighting_type)
541
557
  # Apply Chiller efficiency
542
558
  ecm.modify_chiller_efficiency(model: model, chiller_type: chiller_type)
543
559
  # Apply airloop economizer
@@ -551,7 +567,13 @@ class NECB2011 < Standard
551
567
  # apply unitary cop
552
568
  ecm.modify_unitary_cop(model: model, unitary_cop: unitary_cop, sizing_done: true, sql_db_vars_map: sql_db_vars_map)
553
569
  # set capacities of district heating and cooling equipment for ground-source heat pump ecm
554
- ecm.set_ghx_loop_district_cap(model) if (!model.getDistrictHeatings.empty? && !model.getDistrictCoolings.empty?)
570
+ district_heat = false
571
+ if model.version < OpenStudio::VersionString.new('3.7.0')
572
+ district_heat = !model.getDistrictHeatings.empty?
573
+ else
574
+ district_heat = !model.getDistrictHeatingWaters.empty?
575
+ end
576
+ ecm.set_ghx_loop_district_cap(model) if (district_heat && !model.getDistrictCoolings.empty?)
555
577
 
556
578
  # -------Pump sizing required by some vintages----------------
557
579
  # Apply Pump power as required.
@@ -578,6 +600,10 @@ class NECB2011 < Standard
578
600
  pv_ground_module_description: pv_ground_module_description)
579
601
  end
580
602
 
603
+ # Rename air loop and plant loop nodes to accommodate coming OpenStudio version
604
+ rename_air_loop_nodes(model)
605
+ rename_plant_loop_nodes(model)
606
+
581
607
  end
582
608
 
583
609
  def apply_loads(model:,
@@ -604,6 +630,14 @@ class NECB2011 < Standard
604
630
  end
605
631
 
606
632
  def apply_weather_data(model:, epw_file:)
633
+ # Create full path to weather file
634
+ weather_files = File.absolute_path(File.join(__FILE__, '..', '..', '..', '..', '..' , '..', "data/weather"))
635
+ weather_file = File.join(weather_files, epw_file)
636
+ # Check if the weather file exists. If it does continue as normal, otherwise try to dowload it from the
637
+ # canmet-energy/btap_weather repository
638
+ unless File.exist?(weather_file)
639
+ get_weather_file_from_repo(epw_file: epw_file)
640
+ end
607
641
  climate_zone = 'NECB HDD Method'
608
642
  # Fix EMS references. Temporary workaround for OS issue #2598
609
643
  model_temp_fix_ems_references(model)
@@ -901,43 +935,64 @@ class NECB2011 < Standard
901
935
  # @param model [OpenStudio::Model::Model] an OpenStudio model
902
936
  # @param tbd_option [String] BTAP/TBD option
903
937
  #
904
- # @return [Bool] true if successful, e.g. no errors, compliant if uprated
905
- def apply_thermal_bridging(model: nil, tbd_option: nil)
938
+ # @return [Boolean] true if successful, e.g. no errors, compliant if uprated
939
+
940
+ ##
941
+ # (Optionally) uprates, then derates, envelope surface constructions due to
942
+ # MAJOR thermal bridges (e.g. roof parapets, corners, fenestration
943
+ # perimeters). See lib/openstudio-standards/btap/bridging.rb, which relies on
944
+ # the Thermal Bridging & Derating (TBD) gem.
945
+ #
946
+ # @param model [OpenStudio::Model::Model] an OpenStudio model
947
+ # @param tbd_option [String] BTAP/TBD option
948
+ # @param tbd_interpolate [Boolean] true if TBD interpolates between costed Uo
949
+ # @param wall_U [Double] wall conductance in W/m2.K (nil by default)
950
+ # @param floor_U [Double] floor conductance in W/m2.K (nil by default)
951
+ # @param roof_U [Double] roof conductance in W/m2.K (nil by default)
952
+ #
953
+ # @return [Boolean] true if successful, e.g. no errors, compliant if uprated
954
+ def apply_thermal_bridging(model: nil,
955
+ tbd_option: 'none',
956
+ tbd_interpolate: false,
957
+ wall_U: nil,
958
+ floor_U: nil,
959
+ roof_U: nil)
906
960
  return false unless model.is_a?(OpenStudio::Model::Model)
907
961
  return false unless tbd_option.respond_to?(:to_s)
908
962
 
909
963
  tbd_option = tbd_option.to_s
910
964
  # 4x options:
911
- # - nil or 'none'(TBD is ignored)
965
+ # - 'none' (TBD is ignored)
912
966
  # - derate using 'bad' PSI factors (BTAP-costed)
913
967
  # - derate using 'good' PSI factors (BTAP-costed)
914
968
  # - 'uprate' (then derate), i.e. iterative process (BTAP-costed)
969
+ ok = tbd_option == 'bad' || tbd_option == 'good' || tbd_option == 'uprate'
970
+ return true if tbd_option == 'none'
971
+ return false unless ok
915
972
 
916
- # Do nothing if nil or none or NECB_Default.
917
- return true if tbd_option.nil? || tbd_option == 'none' || tbd_option =='NECB_Default'
918
- unless tbd_option == 'bad' || tbd_option == 'good' || tbd_option == 'uprate'
919
- puts("invalid input for thermal bridging. Must be good, bad, uprate or nil")
920
- return false
921
- end
973
+ argh = {} # BTAP/TBD arguments
974
+ ok = tbd_interpolate == true || tbd_interpolate == false
975
+ argh[:interpolate] = tbd_interpolate if ok
976
+ argh[:interpolate] = false unless ok
922
977
 
923
- argh = {} # BTAP/TBD arguments
924
- argh[:walls ] = { uo: nil }
925
- argh[:floors] = { uo: nil }
926
- argh[:roofs ] = { uo: nil }
978
+ argh[:walls ] = { uo: wall_U }
979
+ argh[:floors] = { uo: floor_U }
980
+ argh[:roofs ] = { uo: roof_U }
927
981
 
928
982
  if tbd_option == 'uprate'
929
- argh[:walls ][:ut] = nil
930
- argh[:floors ][:ut] = nil
931
- argh[:roofs ][:ut] = nil
983
+ argh[:walls ][:ut] = wall_U
984
+ argh[:floors ][:ut] = floor_U
985
+ argh[:roofs ][:ut] = roof_U
932
986
  elsif tbd_option == 'good'
933
987
  argh[:quality] = :good
934
988
  end # default == :bad
935
989
 
936
990
  @tbd = BTAP::Bridging.new(model, argh)
991
+
937
992
  true
938
993
  end
939
994
 
940
- # @param necb_ref_hp [Bool] if true, NECB reference model rules for heat pumps will be used.
995
+ # @param necb_reference_hp [Boolean] if true, NECB reference model rules for heat pumps will be used.
941
996
  def apply_standard_efficiencies(model:, sizing_run_dir:, dcv_type: 'NECB_Default', necb_reference_hp: false)
942
997
  raise('validation of model failed.') unless validate_initial_model(model)
943
998
 
@@ -972,7 +1027,7 @@ class NECB2011 < Standard
972
1027
  #
973
1028
  # @param min_occ_pct [Double] the fractional value below which
974
1029
  # the system will be considered unoccupied.
975
- # @return [Bool] true if successful, false if not
1030
+ # @return [Boolean] true if successful, false if not
976
1031
  def air_loop_hvac_enable_unoccupied_fan_shutoff(air_loop_hvac, min_occ_pct = 0.05)
977
1032
  # Set the system to night cycle
978
1033
  air_loop_hvac.setNightCycleControlType('CycleOnAny')
@@ -1154,7 +1209,7 @@ class NECB2011 < Standard
1154
1209
  return true
1155
1210
  end
1156
1211
 
1157
- # @return [Bool] returns true if successful, false if not
1212
+ # @return [Boolean] returns true if successful, false if not
1158
1213
  def set_occ_sensor_spacetypes(model, space_type_map)
1159
1214
  building_type = 'Space Function'
1160
1215
  space_type_map.each do |space_type_name, space_names|
@@ -1255,24 +1310,37 @@ class NECB2011 < Standard
1255
1310
  end
1256
1311
  end
1257
1312
 
1258
- ##### Ask user's inputs for daylighting controls illuminance setpoint and number of stepped control steps.
1259
- ##### Note that the minimum number of stepped control steps is two steps as per NECB2011.
1260
- def daylighting_controls_settings(illuminance_setpoint: 500.0,
1261
- number_of_stepped_control_steps: 2)
1262
- return illuminance_setpoint, number_of_stepped_control_steps
1263
- end
1313
+ def model_add_daylighting_controls(model:, daylighting_type:)
1264
1314
 
1265
- def model_add_daylighting_controls(model)
1315
+ return if daylighting_type == 'none'
1266
1316
  ##### Find spaces with exterior fenestration including fixed window, operable window, and skylight.
1267
1317
  daylight_spaces = []
1318
+ daylight_spaces_target_illuminance_setpoint_hash = {}
1268
1319
  model.getSpaces.sort.each do |space|
1269
1320
  space.surfaces.sort.each do |surface|
1270
1321
  surface.subSurfaces.sort.each do |subsurface|
1271
1322
  if subsurface.outsideBoundaryCondition == 'Outdoors' &&
1272
- (subsurface.subSurfaceType == 'FixedWindow' ||
1273
- subsurface.subSurfaceType == 'OperableWindow' ||
1274
- subsurface.subSurfaceType == 'Skylight')
1323
+ (subsurface.subSurfaceType == 'FixedWindow' ||
1324
+ subsurface.subSurfaceType == 'OperableWindow' ||
1325
+ subsurface.subSurfaceType == 'Skylight')
1275
1326
  daylight_spaces << space
1327
+ space_type = space.spaceType.get
1328
+ space_type_name = space.spaceType.get.name.to_s
1329
+ space_type_name = space_type_name.gsub('Space Function', '')
1330
+ # puts "space_type_name is #{space_type_name}"
1331
+
1332
+ # Gather minimum illuminance level as per NECB
1333
+ lux_spacetype_data = @standards_data['tables']['space_types']['table']
1334
+ standards_building_type = space_type.standardsBuildingType.is_initialized ? space_type.standardsBuildingType.get : nil
1335
+ standards_space_type = space_type.standardsSpaceType.is_initialized ? space_type.standardsSpaceType.get : nil
1336
+ lux_space_type_properties = lux_spacetype_data.detect { |s| (s['building_type'] == standards_building_type) && (s['space_type'] == standards_space_type) }
1337
+ if lux_space_type_properties.nil?
1338
+ raise("#{standards_building_type} for #{standards_space_type} was not found please verify the target_illuminance_setpoint database names match the space type names.")
1339
+ end
1340
+
1341
+ target_illuminance_setpoint = lux_space_type_properties['target_illuminance_setpoint'].to_f
1342
+ daylight_spaces_target_illuminance_setpoint_hash[space.name.to_s] = target_illuminance_setpoint
1343
+
1276
1344
  # subsurface.outsideBoundaryCondition == "Outdoors" && (subsurface.subSurfaceType == "FixedWindow" || "OperableWindow")
1277
1345
  end
1278
1346
  # surface.subSurfaces.each do |subsurface|
@@ -1284,188 +1352,193 @@ class NECB2011 < Standard
1284
1352
 
1285
1353
  ##### Remove duplicate spaces from the "daylight_spaces" array, as a daylighted space may have various fenestration types.
1286
1354
  daylight_spaces = daylight_spaces.uniq
1287
- # puts daylight_spaces
1288
-
1289
- ##### Create hashes for "Primary Sidelighted Areas", "Sidelighting Effective Aperture", "Daylighted Area Under Skylights",
1290
- ##### and "Skylight Effective Aperture" for the whole model.
1291
- ##### Each of these hashes will be used later in this function (i.e. model_add_daylighting_controls)
1292
- ##### to provide a dictionary of daylighted space names and the associated value (i.e. daylighted area or effective aperture).
1293
- primary_sidelighted_area_hash = {}
1294
- sidelighting_effective_aperture_hash = {}
1295
- daylighted_area_under_skylights_hash = {}
1296
- skylight_effective_aperture_hash = {}
1297
-
1298
- ##### Calculate "Primary Sidelighted Areas" AND "Sidelighting Effective Aperture" as per NECB2011. #TODO: consider removing overlapped sidelighted area
1299
- daylight_spaces.sort.each do |daylight_space|
1300
- # puts daylight_space.name.to_s
1301
- primary_sidelighted_area = 0.0
1302
- area_weighted_vt_handle = 0.0
1303
- area_weighted_vt = 0.0
1304
- window_area_sum = 0.0
1305
-
1306
- ##### Calculate floor area of the daylight_space and get floor vertices of the daylight_space (to be used for the calculation of daylight_space depth)
1307
- floor_surface = nil
1308
- floor_area = 0.0
1309
- floor_vertices = []
1310
- daylight_space.surfaces.sort.each do |surface|
1311
- if surface.surfaceType == 'Floor'
1312
- floor_surface = surface
1313
- floor_area += surface.netArea
1314
- floor_vertices << surface.vertices
1315
- end
1316
- end
1355
+ # puts "daylight_spaces are #{daylight_spaces}"
1317
1356
 
1318
- ##### Loop through the surfaces of each daylight_space to calculate primary_sidelighted_area and
1319
- ##### area-weighted visible transmittance and window_area_sum which are used to calculate sidelighting_effective_aperture
1320
- primary_sidelighted_area, area_weighted_vt_handle, window_area_sum =
1321
- get_parameters_sidelighting(daylight_space: daylight_space,
1322
- floor_surface: floor_surface,
1323
- floor_vertices: floor_vertices,
1324
- floor_area: floor_area,
1325
- primary_sidelighted_area: primary_sidelighted_area,
1326
- area_weighted_vt_handle: area_weighted_vt_handle,
1327
- window_area_sum: window_area_sum)
1328
-
1329
- primary_sidelighted_area_hash[daylight_space.name.to_s] = primary_sidelighted_area
1330
-
1331
- ##### Calculate area-weighted VT of glazing (this is used to calculate sidelighting effective aperture; see NECB2011: 4.2.2.10.).
1332
- area_weighted_vt = area_weighted_vt_handle / window_area_sum
1333
- sidelighting_effective_aperture_hash[daylight_space.name.to_s] = window_area_sum * area_weighted_vt / primary_sidelighted_area
1334
- # daylight_spaces.each do |daylight_space|
1335
- end
1357
+ if daylighting_type.nil? || daylighting_type == false || daylighting_type == 'none' || daylighting_type == 'NECB_Default' # puts daylighting sensors in the spaces as per NECB requirements; so some spaces may not have sensors
1336
1358
 
1337
- ##### Calculate "Daylighted Area Under Skylights" AND "Skylight Effective Aperture"
1338
- daylight_spaces.sort.each do |daylight_space|
1339
- # puts daylight_space.name.to_s
1340
- skylight_area = 0.0
1341
- skylight_area_weighted_vt_handle = 0.0
1342
- skylight_area_weighted_vt = 0.0
1343
- skylight_area_sum = 0.0
1344
- daylighted_under_skylight_area = 0.0
1345
-
1346
- ##### Loop through the surfaces of each daylight_space to calculate daylighted_area_under_skylights and skylight_effective_aperture for each daylight_space
1347
- daylighted_under_skylight_area, skylight_area_weighted_vt_handle, skylight_area_sum =
1348
- get_parameters_skylight(daylight_space: daylight_space,
1349
- skylight_area_weighted_vt_handle: skylight_area_weighted_vt_handle,
1350
- skylight_area_sum: skylight_area_sum,
1351
- daylighted_under_skylight_area: daylighted_under_skylight_area)
1352
-
1353
- daylighted_area_under_skylights_hash[daylight_space.name.to_s] = daylighted_under_skylight_area
1354
-
1355
- ##### Calculate skylight_effective_aperture as per NECB2011: 4.2.2.7.
1356
- ##### Note that it was assumed that the skylight is flush with the ceiling. Therefore, area-weighted average well factor (WF) was set to 0.9 in the below Equation.
1357
- skylight_area_weighted_vt = skylight_area_weighted_vt_handle / skylight_area_sum
1358
- skylight_effective_aperture_hash[daylight_space.name.to_s] = 0.85 * skylight_area_sum * skylight_area_weighted_vt * 0.9 / daylighted_under_skylight_area
1359
- # daylight_spaces.each do |daylight_space|
1360
- end
1361
- # puts primary_sidelighted_area_hash
1362
- # puts sidelighting_effective_aperture_hash
1363
- # puts daylighted_area_under_skylights_hash
1364
- # puts skylight_effective_aperture_hash
1359
+ ##### Create hashes for "Primary Sidelighted Areas", "Sidelighting Effective Aperture", "Daylighted Area Under Skylights",
1360
+ ##### and "Skylight Effective Aperture" for the whole model.
1361
+ ##### Each of these hashes will be used later in this function (i.e. model_add_daylighting_controls)
1362
+ ##### to provide a dictionary of daylighted space names and the associated value (i.e. daylighted area or effective aperture).
1363
+ primary_sidelighted_area_hash = {}
1364
+ sidelighting_effective_aperture_hash = {}
1365
+ daylighted_area_under_skylights_hash = {}
1366
+ skylight_effective_aperture_hash = {}
1365
1367
 
1366
- ##### Find office spaces >= 25m2 among daylight_spaces
1367
- offices_larger_25m2 = []
1368
- daylight_spaces.sort.each do |daylight_space|
1369
- ## The following steps are for in case an office has multiple floors at various heights
1370
- ## 1. Calculate number of floors of each daylight_space
1371
- ## 2. Find the lowest z among all floors of each daylight_space
1372
- ## 3. Find lowest floors of each daylight_space (these floors are at the same level)
1373
- ## 4. Calculate 'daylight_space_area' as sum of area of all the lowest floors of each daylight_space, and gather the vertices of all the lowest floors of each daylight_space
1374
-
1375
- ## 1. Calculate number of floors of daylight_space
1376
- floor_vertices = []
1377
- number_floor = 0
1378
- daylight_space.surfaces.sort.each do |surface|
1379
- if surface.surfaceType == 'Floor'
1380
- floor_vertices << surface.vertices
1381
- number_floor += 1
1368
+ ##### Calculate "Primary Sidelighted Areas" AND "Sidelighting Effective Aperture" as per NECB2011. # @todo consider removing overlapped sidelighted area
1369
+ daylight_spaces.sort.each do |daylight_space|
1370
+ primary_sidelighted_area = 0.0
1371
+ area_weighted_vt_handle = 0.0
1372
+ area_weighted_vt = 0.0
1373
+ window_area_sum = 0.0
1374
+
1375
+ ##### Calculate floor area of the daylight_space and get floor vertices of the daylight_space (to be used for the calculation of daylight_space depth)
1376
+ floor_surface = nil
1377
+ floor_area = 0.0
1378
+ floor_vertices = []
1379
+ daylight_space.surfaces.sort.each do |surface|
1380
+ if surface.surfaceType == 'Floor'
1381
+ floor_surface = surface
1382
+ floor_area += surface.netArea
1383
+ floor_vertices << surface.vertices
1384
+ end
1382
1385
  end
1386
+
1387
+ ##### Loop through the surfaces of each daylight_space to calculate primary_sidelighted_area and
1388
+ ##### area-weighted visible transmittance and window_area_sum which are used to calculate sidelighting_effective_aperture
1389
+ primary_sidelighted_area, area_weighted_vt_handle, window_area_sum =
1390
+ get_parameters_sidelighting(daylight_space: daylight_space,
1391
+ floor_surface: floor_surface,
1392
+ floor_vertices: floor_vertices,
1393
+ floor_area: floor_area,
1394
+ primary_sidelighted_area: primary_sidelighted_area,
1395
+ area_weighted_vt_handle: area_weighted_vt_handle,
1396
+ window_area_sum: window_area_sum)
1397
+
1398
+ primary_sidelighted_area_hash[daylight_space.name.to_s] = primary_sidelighted_area
1399
+
1400
+ ##### Calculate area-weighted VT of glazing (this is used to calculate sidelighting effective aperture; see NECB2011: 4.2.2.10.).
1401
+ area_weighted_vt = area_weighted_vt_handle / window_area_sum
1402
+ sidelighting_effective_aperture_hash[daylight_space.name.to_s] = window_area_sum * area_weighted_vt / primary_sidelighted_area
1403
+ # daylight_spaces.each do |daylight_space|
1383
1404
  end
1384
1405
 
1385
- ## 2. Loop through all floors of daylight_space, and find the lowest z among all floors of daylight_space
1386
- lowest_floor_z = []
1387
- highest_floor_z = []
1388
- for i in 0..number_floor - 1
1389
- if i == 0
1390
- lowest_floor_z = floor_vertices[i][0].z
1391
- highest_floor_z = floor_vertices[i][0].z
1392
- else
1393
- if lowest_floor_z > floor_vertices[i][0].z
1394
- lowest_floor_z = floor_vertices[i][0].z
1395
- else
1396
- lowest_floor_z = lowest_floor_z
1406
+ ##### Calculate "Daylighted Area Under Skylights" AND "Skylight Effective Aperture"
1407
+ daylight_spaces.sort.each do |daylight_space|
1408
+ # puts daylight_space.name.to_s
1409
+ skylight_area = 0.0
1410
+ skylight_area_weighted_vt_handle = 0.0
1411
+ skylight_area_weighted_vt = 0.0
1412
+ skylight_area_sum = 0.0
1413
+ daylighted_under_skylight_area = 0.0
1414
+
1415
+ ##### Loop through the surfaces of each daylight_space to calculate daylighted_area_under_skylights and skylight_effective_aperture for each daylight_space
1416
+ daylighted_under_skylight_area, skylight_area_weighted_vt_handle, skylight_area_sum =
1417
+ get_parameters_skylight(daylight_space: daylight_space,
1418
+ skylight_area_weighted_vt_handle: skylight_area_weighted_vt_handle,
1419
+ skylight_area_sum: skylight_area_sum,
1420
+ daylighted_under_skylight_area: daylighted_under_skylight_area)
1421
+
1422
+ daylighted_area_under_skylights_hash[daylight_space.name.to_s] = daylighted_under_skylight_area
1423
+
1424
+ ##### Calculate skylight_effective_aperture as per NECB2011: 4.2.2.7.
1425
+ ##### Note that it was assumed that the skylight is flush with the ceiling. Therefore, area-weighted average well factor (WF) was set to 0.9 in the below Equation.
1426
+ skylight_area_weighted_vt = skylight_area_weighted_vt_handle / skylight_area_sum
1427
+ skylight_effective_aperture_hash[daylight_space.name.to_s] = 0.85 * skylight_area_sum * skylight_area_weighted_vt * 0.9 / daylighted_under_skylight_area
1428
+ # daylight_spaces.each do |daylight_space|
1429
+ end
1430
+ # puts "primary_sidelighted_area_hash is #{primary_sidelighted_area_hash}"
1431
+ # puts sidelighting_effective_aperture_hash
1432
+ # puts daylighted_area_under_skylights_hash
1433
+ # puts skylight_effective_aperture_hash
1434
+
1435
+ ##### Find office spaces >= 25m2 among daylight_spaces
1436
+ offices_larger_25m2 = []
1437
+ daylight_spaces.sort.each do |daylight_space|
1438
+ ## The following steps are for in case an office has multiple floors at various heights
1439
+ ## 1. Calculate number of floors of each daylight_space
1440
+ ## 2. Find the lowest z among all floors of each daylight_space
1441
+ ## 3. Find lowest floors of each daylight_space (these floors are at the same level)
1442
+ ## 4. Calculate 'daylight_space_area' as sum of area of all the lowest floors of each daylight_space, and gather the vertices of all the lowest floors of each daylight_space
1443
+
1444
+ ## 1. Calculate number of floors of daylight_space
1445
+ floor_vertices = []
1446
+ number_floor = 0
1447
+ daylight_space.surfaces.sort.each do |surface|
1448
+ if surface.surfaceType == 'Floor'
1449
+ floor_vertices << surface.vertices
1450
+ number_floor += 1
1397
1451
  end
1398
- if highest_floor_z < floor_vertices[i][0].z
1452
+ end
1453
+
1454
+ ## 2. Loop through all floors of daylight_space, and find the lowest z among all floors of daylight_space
1455
+ lowest_floor_z = []
1456
+ highest_floor_z = []
1457
+ for i in 0..number_floor - 1
1458
+ if i == 0
1459
+ lowest_floor_z = floor_vertices[i][0].z
1399
1460
  highest_floor_z = floor_vertices[i][0].z
1400
1461
  else
1401
- highest_floor_z = highest_floor_z
1462
+ if lowest_floor_z > floor_vertices[i][0].z
1463
+ lowest_floor_z = floor_vertices[i][0].z
1464
+ else
1465
+ lowest_floor_z = lowest_floor_z
1466
+ end
1467
+ if highest_floor_z < floor_vertices[i][0].z
1468
+ highest_floor_z = floor_vertices[i][0].z
1469
+ else
1470
+ highest_floor_z = highest_floor_z
1471
+ end
1402
1472
  end
1403
1473
  end
1404
- end
1405
1474
 
1406
- ## 3 and 4. Loop through all floors of daylight_space, and calculate the sum of area of all the lowest floors of daylight_space,
1407
- ## and gather the vertices of all the lowest floors of daylight_space
1408
- daylight_space_area = 0
1409
- lowest_floors_vertices = []
1410
- floor_vertices = []
1411
- daylight_space.surfaces.sort.each do |surface|
1412
- if surface.surfaceType == 'Floor'
1413
- floor_vertices = surface.vertices
1414
- if floor_vertices[0].z == lowest_floor_z
1415
- lowest_floors_vertices << floor_vertices
1416
- daylight_space_area += surface.netArea
1475
+ ## 3 and 4. Loop through all floors of daylight_space, and calculate the sum of area of all the lowest floors of daylight_space,
1476
+ ## and gather the vertices of all the lowest floors of daylight_space
1477
+ daylight_space_area = 0
1478
+ lowest_floors_vertices = []
1479
+ floor_vertices = []
1480
+ daylight_space.surfaces.sort.each do |surface|
1481
+ if surface.surfaceType == 'Floor'
1482
+ floor_vertices = surface.vertices
1483
+ if floor_vertices[0].z == lowest_floor_z
1484
+ lowest_floors_vertices << floor_vertices
1485
+ daylight_space_area += surface.netArea
1486
+ end
1417
1487
  end
1418
1488
  end
1419
- end
1420
1489
 
1421
- if daylight_space.spaceType.get.standardsSpaceType.get.to_s == 'Office - enclosed' && daylight_space_area >= 25.0
1422
- offices_larger_25m2 << daylight_space.name.to_s
1490
+ if daylight_space.spaceType.get.standardsSpaceType.get.to_s == 'Office - enclosed' && daylight_space_area >= 25.0
1491
+ offices_larger_25m2 << daylight_space.name.to_s
1492
+ end
1423
1493
  end
1424
- end
1425
1494
 
1426
- ##### find daylight_spaces which do not need daylight sensor controls based on the primary_sidelighted_area as per NECB2011: 4.2.2.8.
1427
- ##### Note: Office spaces >= 25m2 are excluded (i.e. they should have daylighting controls even if their primary_sidelighted_area <= 100m2), as per NECB2011: 4.2.2.2.
1428
- daylight_spaces_exception = []
1429
- primary_sidelighted_area_hash.sort.each do |key_daylight_space_name, value_primary_sidelighted_area|
1430
- if value_primary_sidelighted_area <= 100.0 && [key_daylight_space_name].any? { |word| offices_larger_25m2.include?(word) } == false
1431
- daylight_spaces_exception << key_daylight_space_name
1495
+ ##### find daylight_spaces which do not need daylight sensor controls based on the primary_sidelighted_area as per NECB2011: 4.2.2.8.
1496
+ ##### Note: Office spaces >= 25m2 are excluded (i.e. they should have daylighting controls even if their primary_sidelighted_area <= 100m2), as per NECB2011: 4.2.2.2.
1497
+ daylight_spaces_exception = []
1498
+ primary_sidelighted_area_hash.sort.each do |key_daylight_space_name, value_primary_sidelighted_area|
1499
+ if value_primary_sidelighted_area <= 100.0 && [key_daylight_space_name].any? { |word| offices_larger_25m2.include?(word) } == false
1500
+ daylight_spaces_exception << key_daylight_space_name
1501
+ end
1432
1502
  end
1433
- end
1434
1503
 
1435
- ##### find daylight_spaces which do not need daylight sensor controls based on the sidelighting_effective_aperture as per NECB2011: 4.2.2.8.
1436
- ##### Note: Office spaces >= 25m2 are excluded (i.e. they should have daylighting controls even if their sidelighting_effective_aperture <= 10%), as per NECB2011: 4.2.2.2.
1437
- sidelighting_effective_aperture_hash.sort.each do |key_daylight_space_name, value_sidelighting_effective_aperture|
1438
- if value_sidelighting_effective_aperture <= 0.1 && [key_daylight_space_name].any? { |word| offices_larger_25m2.include?(word) } == false
1439
- daylight_spaces_exception << key_daylight_space_name
1504
+ ##### find daylight_spaces which do not need daylight sensor controls based on the sidelighting_effective_aperture as per NECB2011: 4.2.2.8.
1505
+ ##### Note: Office spaces >= 25m2 are excluded (i.e. they should have daylighting controls even if their sidelighting_effective_aperture <= 10%), as per NECB2011: 4.2.2.2.
1506
+ sidelighting_effective_aperture_hash.sort.each do |key_daylight_space_name, value_sidelighting_effective_aperture|
1507
+ if value_sidelighting_effective_aperture <= 0.1 && [key_daylight_space_name].any? { |word| offices_larger_25m2.include?(word) } == false
1508
+ daylight_spaces_exception << key_daylight_space_name
1509
+ end
1440
1510
  end
1441
- end
1442
1511
 
1443
- ##### find daylight_spaces which do not need daylight sensor controls based on the daylighted_area_under_skylights as per NECB2011: 4.2.2.4.
1444
- ##### Note: Office spaces >= 25m2 are excluded (i.e. they should have daylighting controls even if their daylighted_area_under_skylights <= 400m2), as per NECB2011: 4.2.2.2.
1445
- daylighted_area_under_skylights_hash.sort.each do |key_daylight_space_name, value_daylighted_area_under_skylights|
1446
- if value_daylighted_area_under_skylights <= 400.0 && [key_daylight_space_name].any? { |word| offices_larger_25m2.include?(word) } == false
1447
- daylight_spaces_exception << key_daylight_space_name
1512
+ ##### find daylight_spaces which do not need daylight sensor controls based on the daylighted_area_under_skylights as per NECB2011: 4.2.2.4.
1513
+ ##### Note: Office spaces >= 25m2 are excluded (i.e. they should have daylighting controls even if their daylighted_area_under_skylights <= 400m2), as per NECB2011: 4.2.2.2.
1514
+ daylighted_area_under_skylights_hash.sort.each do |key_daylight_space_name, value_daylighted_area_under_skylights|
1515
+ if value_daylighted_area_under_skylights <= 400.0 && [key_daylight_space_name].any? { |word| offices_larger_25m2.include?(word) } == false
1516
+ daylight_spaces_exception << key_daylight_space_name
1517
+ end
1448
1518
  end
1449
- end
1450
1519
 
1451
- ##### find daylight_spaces which do not need daylight sensor controls based on the skylight_effective_aperture criterion as per NECB2011: 4.2.2.4.
1452
- ##### Note: Office spaces >= 25m2 are excluded (i.e. they should have daylighting controls even if their skylight_effective_aperture <= 0.6%), as per NECB2011: 4.2.2.2.
1453
- skylight_effective_aperture_hash.sort.each do |key_daylight_space_name, value_skylight_effective_aperture|
1454
- if value_skylight_effective_aperture <= 0.006 && [key_daylight_space_name].any? { |word| offices_larger_25m2.include?(word) } == false
1455
- daylight_spaces_exception << key_daylight_space_name
1520
+ ##### find daylight_spaces which do not need daylight sensor controls based on the skylight_effective_aperture criterion as per NECB2011: 4.2.2.4.
1521
+ ##### Note: Office spaces >= 25m2 are excluded (i.e. they should have daylighting controls even if their skylight_effective_aperture <= 0.6%), as per NECB2011: 4.2.2.2.
1522
+ skylight_effective_aperture_hash.sort.each do |key_daylight_space_name, value_skylight_effective_aperture|
1523
+ if value_skylight_effective_aperture <= 0.006 && [key_daylight_space_name].any? { |word| offices_larger_25m2.include?(word) } == false
1524
+ daylight_spaces_exception << key_daylight_space_name
1525
+ end
1456
1526
  end
1457
- end
1458
- # puts daylight_spaces_exception
1527
+ # puts daylight_spaces_exception
1459
1528
 
1460
- ##### Loop through the daylight_spaces and exclude the daylight_spaces that do not meet the criteria (see above) as per NECB2011: 4.2.2.4. and 4.2.2.8.
1461
- daylight_spaces_exception.sort.each do |daylight_space_exception|
1462
- daylight_spaces.sort.each do |daylight_space|
1463
- if daylight_space.name.to_s == daylight_space_exception
1464
- daylight_spaces.delete(daylight_space)
1529
+ ##### Loop through the daylight_spaces and exclude the daylight_spaces that do not meet the criteria (see above) as per NECB2011: 4.2.2.4. and 4.2.2.8.
1530
+ daylight_spaces_exception.sort.each do |daylight_space_exception|
1531
+ daylight_spaces.sort.each do |daylight_space|
1532
+ if daylight_space.name.to_s == daylight_space_exception
1533
+ daylight_spaces.delete(daylight_space)
1534
+ end
1465
1535
  end
1466
1536
  end
1467
- end
1468
- # puts daylight_spaces
1537
+ # puts daylight_spaces
1538
+
1539
+ # elsif daylighting_type == 'add_daylighting_controls' # puts daylighting sensors in all spaces regardless of NECB requirements
1540
+
1541
+ end #if daylighting_type.nil? || daylighting_type == false || daylighting_type == 'none' || daylighting_type == 'NECB_Default'
1469
1542
 
1470
1543
  ##### Create one daylighting sensor and put it at the center of each daylight_space if the space area < 250m2;
1471
1544
  ##### otherwise, create two daylight sensors, divide the space into two parts and put each of the daylight sensors at the center of each part of the space.
@@ -1559,6 +1632,7 @@ class NECB2011 < Standard
1559
1632
 
1560
1633
  ##### Get the thermal zone of daylight_space (this is used later to assign daylighting sensor)
1561
1634
  zone = daylight_space.thermalZone
1635
+ # puts "zone name is #{zone}"
1562
1636
  if !zone.empty?
1563
1637
  zone = daylight_space.thermalZone.get
1564
1638
  ##### Get the floor of the daylight_space
@@ -1569,8 +1643,10 @@ class NECB2011 < Standard
1569
1643
  end
1570
1644
  end
1571
1645
 
1572
- ##### Get user's input for daylighting controls illuminance setpoint and number of stepped control steps
1573
- illuminance_setpoint, number_of_stepped_control_steps = daylighting_controls_settings(illuminance_setpoint: 500.0, number_of_stepped_control_steps: 2)
1646
+ ##### Set daylighting controls illuminance setpoint and number of stepped control steps
1647
+ number_of_stepped_control_steps = 2 ##### Note that the minimum number of stepped control steps is two steps as per NECB2011.
1648
+ illuminance_setpoint = daylight_spaces_target_illuminance_setpoint_hash.select {|key| key == daylight_space.name.to_s }
1649
+ illuminance_setpoint = illuminance_setpoint[daylight_space.name.to_s]
1574
1650
 
1575
1651
  ##### Create daylighting sensor control
1576
1652
  ##### NOTE: NECB2011 has some requirements on the number of sensors in spaces based on the area of the spaces.
@@ -1597,11 +1673,12 @@ class NECB2011 < Standard
1597
1673
  # if !zone.empty?
1598
1674
  end
1599
1675
  # daylight_spaces.each do |daylight_space|
1600
- end
1601
- end
1676
+ end # END if daylighting_controls_type.nil? || daylighting_controls_type == false || daylighting_controls_type == 'none' || daylighting_controls_type == 'NECB_Default'
1677
+
1678
+ end # END model_add_daylighting_controls(model:, daylighting_type:)
1602
1679
 
1603
1680
  ##### Define ScheduleTypeLimits for Any_Number_ppm
1604
- ##### TODO: (upon other BTAP tasks) This function can be added to btap/schedules.rb > module StandardScheduleTypeLimits
1681
+ ##### @todo (upon other BTAP tasks) This function can be added to btap/schedules.rb > module StandardScheduleTypeLimits
1605
1682
  def get_any_number_ppm(model)
1606
1683
  name = 'Any_Number_ppm'
1607
1684
  any_number_ppm_schedule_type_limits = model.getScheduleTypeLimitsByName(name)
@@ -1621,7 +1698,7 @@ class NECB2011 < Standard
1621
1698
  return if dcv_type == 'NECB_Defualt'
1622
1699
 
1623
1700
  if dcv_type == 'Occupancy_based_DCV' || dcv_type == 'CO2_based_DCV'
1624
- # TODO: IMPORTANT: (upon other BTAP tasks) Set a value for the "Outdoor Air Flow per Person" field of the "OS:DesignSpecification:OutdoorAir" object
1701
+ # @todo IMPORTANT: (upon other BTAP tasks) Set a value for the "Outdoor Air Flow per Person" field of the "OS:DesignSpecification:OutdoorAir" object
1625
1702
  # Note: The "Outdoor Air Flow per Person" field is required for occupancy-based DCV.
1626
1703
  # Note: The "Outdoor Air Flow per Person" values should be based on ASHRAE 62.1: Article 6.2.2.1.
1627
1704
  # Note: The "Outdoor Air Flow per Person" should be entered for "ventilation_per_person" in "lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json"
@@ -1758,17 +1835,17 @@ class NECB2011 < Standard
1758
1835
 
1759
1836
  # ##### Since Atrium's LPD for LED lighting depends on atrium's height, the height of the atrium (if applicable) should be found.
1760
1837
  standards_space_type = space_type.standardsSpaceType.is_initialized ? space_type.standardsSpaceType.get : nil
1761
- if standards_space_type.include? 'Atrium' # TODO: Note that since none of the archetypes has Atrium, this was tested for 'Dining'. #Atrium
1838
+ if standards_space_type.include? 'Atrium' # @todo Note that since none of the archetypes has Atrium, this was tested for 'Dining'. #Atrium
1762
1839
  puts "#{standards_space_type} - has atrium" # space_type.name.to_s
1763
1840
  # Get the max height for the spacetype.
1764
1841
  max_space_height_for_spacetype = get_max_space_height_for_space_type(space_type: space_type)
1765
- if max_space_height_for_spacetype < 12.0 # TODO: Note that since none of the archetypes has Atrium, this was tested for 'Dining' with the threshold of 5.0 m for space_height.
1766
- # TODO: Regarding the below equations, identify which version of ASHRAE 90.1 was used in NECB2015.
1842
+ if max_space_height_for_spacetype < 12.0 # @todo Note that since none of the archetypes has Atrium, this was tested for 'Dining' with the threshold of 5.0 m for space_height.
1843
+ # @todo Regarding the below equations, identify which version of ASHRAE 90.1 was used in NECB2015.
1767
1844
  atrium_lpd_eq_smaller_12_intercept = 0
1768
1845
  atrium_lpd_eq_smaller_12_slope = 1.06
1769
1846
  atrium_lpd_eq_larger_12_intercept = 4.3
1770
1847
  atrium_lpd_eq_larger_12_slope = 1.06
1771
- lighting_per_area_led_lighting_atrium = (atrium_lpd_eq_smaller_12_intercept + atrium_lpd_eq_smaller_12_slope * 12.0) * 0.092903 # W/ft2 TODO: Note that for NECB2011, a constant LPD is used for atrium based on NECB2015's equations. NECB2011's threshold for height is 13.0 m.
1848
+ lighting_per_area_led_lighting_atrium = (atrium_lpd_eq_smaller_12_intercept + atrium_lpd_eq_smaller_12_slope * 12.0) * 0.092903 # W/ft2 @todo Note that for NECB2011, a constant LPD is used for atrium based on NECB2015's equations. NECB2011's threshold for height is 13.0 m.
1772
1849
  elsif max_space_height_for_spacetype >= 12.0 && max_space_height_for_spacetype < 13.0
1773
1850
  lighting_per_area_led_lighting_atrium = (atrium_lpd_eq_larger_12_intercept + atrium_lpd_eq_larger_12_slope * 12.5) * 0.092903 # W/ft2
1774
1851
  else # i.e. space_height >= 13.0
@@ -1790,7 +1867,7 @@ class NECB2011 < Standard
1790
1867
  # Some loads are governed by the standard, others are typical values
1791
1868
  # pulled from sources such as the DOE Reference and DOE Prototype Buildings.
1792
1869
  #
1793
- # @return [Bool] returns true if successful, false if not
1870
+ # @return [Boolean] returns true if successful, false if not
1794
1871
  def model_add_loads(model, lights_type, lights_scale)
1795
1872
  OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Started applying space types (loads)')
1796
1873
 
@@ -2128,4 +2205,125 @@ class NECB2011 < Standard
2128
2205
  return model
2129
2206
  end
2130
2207
 
2208
+ # This method handles looking for the epw_file in the https://github.com/canmet-energy/btap_weather repository. It
2209
+ # checks for the epw_file in the historical data first. If it is not there then it looks in the future weather data.
2210
+ # If it is not there either, it throws an error.
2211
+ # epw_file (String): The name of the epw file. The different weather files all share the same name as the epw file,
2212
+ # only the extension changes.
2213
+ def get_weather_file_from_repo(epw_file:)
2214
+ # Get just the weather file name without the extension
2215
+ weather_loc = epw_file[0..-5]
2216
+ # Get the url of the file containing the historical weather data file names in the repository and the repository
2217
+ # folder containing the files
2218
+ historic_weather_files_loc = @standards_data['constants']['historic_weather_file_list']['value'].to_s
2219
+ historic_git_folder = @standards_data['constants']['historic_weather_folder_url']['value'].to_s
2220
+ # Get the files from the repository
2221
+ success_flag = download_and_save_file(weather_list_url: historic_weather_files_loc, weather_loc: weather_loc, git_folder: historic_git_folder)
2222
+ return if success_flag == true
2223
+ # If the file could not be found in the historical data look for it with the future weather data.
2224
+ puts "Could not find #{epw_file} in historical weather data files, looking in future weather data files."
2225
+ future_weather_files_loc = @standards_data['constants']['future_weather_file_list']['value'].to_s
2226
+ future_git_folder = @standards_data['constants']['future_weather_folder_url']['value'].to_s
2227
+ success_flag = download_and_save_file(weather_list_url: future_weather_files_loc, weather_loc: weather_loc, git_folder: future_git_folder)
2228
+ if success_flag == true
2229
+ # Rename the non-ASHRAE.ddy as '_non_ASHRAE.ddy' and save the '_ASHRAE.ddy' as the regular '.ddy' file. This is
2230
+ # because the ASHRAE .ddy file includes sizing information not included in the regular .ddy file for future
2231
+ # weather data files. Unfortunately, openstudio-standards just looks for the regular .ddy file for sizing
2232
+ # information which is why the switch is done.
2233
+ puts "Renaming #{weather_loc}.ddy as #{weather_loc}_orig.ddy and #{weather_loc}_ASHRAE.ddy as #{weather_loc}.ddy."
2234
+ puts "This is so that the design weather information in the #{weather_loc}_ASHRAE.ddy file is used."
2235
+ weather_dir = File.absolute_path(File.join(__FILE__, '..', '..', '..', '..', '..' , '..', "data/weather"))
2236
+ orig_ddy_name = File.join(weather_dir, (weather_loc + ".ddy"))
2237
+ ashrae_ddy_name = File.join(weather_dir, (weather_loc + "_ASHRAE.ddy"))
2238
+ rev_ddy_name = File.join(weather_dir, (weather_loc + "_orig.ddy"))
2239
+ FileUtils.cp(orig_ddy_name, rev_ddy_name)
2240
+ FileUtils.cp(ashrae_ddy_name, orig_ddy_name)
2241
+ return
2242
+ end
2243
+ raise("Could not locate the following file in the canmet/btap_weather repository: #{epw_file}. Please check the spelling of the file or visit https://github.com/canmet-energy/btap_weather to see if the file exists.")
2244
+ end
2245
+
2246
+ # This method actually looks for and downloads the zip file from the https://github.com/canmet-energy/btap_weather
2247
+ # repository. The repository contains json files containing the names of all of the weather data zip files of a given
2248
+ # type (either historic weather files or future weather files). This json is checked first to make sure that the file
2249
+ # is in the repository. If it is, the method downloads the zip file and extracts the data all to the
2250
+ # openstudio-standards weather file folder.
2251
+
2252
+ # Arguments:
2253
+ # weather_list_url (string): the web address of the json file containing the list of weather files on the repository
2254
+ # weather_loc (string): the name of the epw file we are looking for without the .epw extension
2255
+ # git_folder (string): the url of the folder containing the weather files. As of 2023-07-07 this this is either the
2256
+ # url of the historical weather data folder or the future weather data folder.
2257
+ def download_and_save_file(weather_list_url:, weather_loc:, git_folder:)
2258
+ status = false
2259
+ attempt = 1
2260
+ # Try to download the list of weather files 5 times, waiting 5 seconds between each attempt.
2261
+ until attempt > 5
2262
+ begin
2263
+ puts "Beginning attempt #{attempt} to download #{weather_list_url}"
2264
+ # Download the list of weather files on the repository
2265
+ URI.open(weather_list_url) do |web_data|
2266
+ # Convert the weather file list to an array
2267
+ if web_data.size <= 100
2268
+ raise("Could not read #{weather_list_url}!")
2269
+ end
2270
+ weather_files = (JSON.parse(web_data.read)).to_a
2271
+ # Check to see if the requested weather file is on the list
2272
+ zip_name = weather_files.find{ |weather_file| weather_file.match(weather_loc) }
2273
+ # If the weather file is on the list proceed, otherwise report that it could not be found
2274
+ unless zip_name.nil?
2275
+ # Found the weather file on the list
2276
+ status = true
2277
+ # Define the full url of the weather zip file we want to download
2278
+ save_file_url = git_folder + zip_name
2279
+ # Define the local location of where the weather zip file will be saved
2280
+ weather_dir = File.absolute_path(File.join(__FILE__, '..', '..', '..', '..', '..' , '..', "data/weather"))
2281
+ save_file = File.join(weather_dir, zip_name)
2282
+ attemptb = 1
2283
+ # Try to download the weather file up to 5 times, waiting 5 seconds between each attempt.
2284
+ until attemptb > 5
2285
+ begin
2286
+ puts "Beginning attempt #{attemptb} to download #{save_file_url}"
2287
+ # Download the weather zip file from the repository
2288
+ URI.open(save_file_url) do |file_url|
2289
+ if file_url.size <= 100
2290
+ raise("Could not read #{save_file_url}!")
2291
+ end
2292
+ # Save the zip file in the /data/weather folder
2293
+ File.open(save_file, 'wb') { |f| f.write(file_url.read) }
2294
+ puts "Downloaded #{save_file_url} to #{save_file}"
2295
+ # Extract the individual weother files from the zip file
2296
+ Zip::File.open(save_file) do |zip_file|
2297
+ puts "Expanding #{save_file}"
2298
+ # Cycle through each file in the zip file
2299
+ zip_file.each do |entry|
2300
+ # Define the location of where the file will be saved locally
2301
+ curr_save_file = File.join(weather_dir, entry.name.to_s)
2302
+ puts "Extracting #{entry.name} to #{curr_save_file}"
2303
+ # entry.extract # This was required before but now it isn't. I'm confused so am saving this comment to
2304
+ # remind me if there are ploblems later
2305
+ # Read the data from the file
2306
+ content = entry.get_input_stream.read
2307
+ # Save the data locally
2308
+ File.open(curr_save_file, 'wb') { |save_f| save_f.write(content) }
2309
+ end
2310
+ end
2311
+ end
2312
+ attemptb = 10
2313
+ rescue
2314
+ sleep(30)
2315
+ attemptb += 1
2316
+ end
2317
+ end
2318
+ end
2319
+ end
2320
+ attempt = 10
2321
+ rescue
2322
+ sleep(30)
2323
+ attempt += 1
2324
+ end
2325
+ end
2326
+ return status
2327
+ end
2328
+
2131
2329
  end