openstudio-standards 0.4.0 → 0.5.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +664 -645
  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 +52 -16
  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
@@ -24,7 +24,8 @@ class Standard
24
24
  # Creates a hot water loop with a boiler, district heating, or a water-to-water heat pump and adds it to the model.
25
25
  #
26
26
  # @param model [OpenStudio::Model::Model] OpenStudio model object
27
- # @param boiler_fuel_type [String] valid choices are Electricity, NaturalGas, Propane, PropaneGas, FuelOilNo1, FuelOilNo2, DistrictHeating, HeatPump
27
+ # @param boiler_fuel_type [String] valid choices are Electricity, NaturalGas, Propane, PropaneGas, FuelOilNo1, FuelOilNo2,
28
+ # DistrictHeating, DistrictHeatingWater, DistrictHeatingSteam, HeatPump
28
29
  # @param ambient_loop [OpenStudio::Model::PlantLoop] The condenser loop for the heat pump. Only used when boiler_fuel_type is HeatPump.
29
30
  # @param system_name [String] the name of the system, or nil in which case it will be defaulted
30
31
  # @param dsgn_sup_wtr_temp [Double] design supply water temperature in degrees Fahrenheit, default 180F
@@ -106,6 +107,15 @@ class Standard
106
107
  hw_pump.setPumpControlType('Intermittent')
107
108
  hw_pump.addToNode(hot_water_loop.supplyInletNode)
108
109
 
110
+ # switch statement to handle district heating name change
111
+ if model.version < OpenStudio::VersionString.new('3.7.0')
112
+ if boiler_fuel_type == 'DistrictHeatingWater' || boiler_fuel_type == 'DistrictHeatingSteam'
113
+ boiler_fuel_type = 'DistrictHeating'
114
+ end
115
+ else
116
+ boiler_fuel_type = 'DistrictHeatingWater' if boiler_fuel_type == 'DistrictHeating'
117
+ end
118
+
109
119
  # create boiler and add to loop
110
120
  case boiler_fuel_type
111
121
  # District Heating
@@ -114,8 +124,18 @@ class Standard
114
124
  district_heat.setName("#{hot_water_loop.name} District Heating")
115
125
  district_heat.autosizeNominalCapacity
116
126
  hot_water_loop.addSupplyBranchForComponent(district_heat)
117
- # Ambient Loop
127
+ when 'DistrictHeatingWater'
128
+ district_heat = OpenStudio::Model::DistrictHeatingWater.new(model)
129
+ district_heat.setName("#{hot_water_loop.name} District Heating")
130
+ district_heat.autosizeNominalCapacity
131
+ hot_water_loop.addSupplyBranchForComponent(district_heat)
132
+ when 'DistrictHeatingSteam'
133
+ district_heat = OpenStudio::Model::DistrictHeatingSteam.new(model)
134
+ district_heat.setName("#{hot_water_loop.name} District Heating")
135
+ district_heat.autosizeNominalCapacity
136
+ hot_water_loop.addSupplyBranchForComponent(district_heat)
118
137
  when 'HeatPump', 'AmbientLoop'
138
+ # Ambient Loop
119
139
  water_to_water_hp = OpenStudio::Model::HeatPumpWaterToWaterEquationFitHeating.new(model)
120
140
  water_to_water_hp.setName("#{hot_water_loop.name} Water to Water Heat Pump")
121
141
  hot_water_loop.addSupplyBranchForComponent(water_to_water_hp)
@@ -844,6 +864,15 @@ class Standard
844
864
  heating_equipment_stpt_manager.setHighSetpointSchedule(hp_high_temp_sch)
845
865
  heating_equipment_stpt_manager.setLowSetpointSchedule(hp_low_temp_sch)
846
866
 
867
+ # switch statement to handle district heating name change
868
+ if model.version < OpenStudio::VersionString.new('3.7.0')
869
+ if heating_fuel == 'DistrictHeatingWater' || heating_fuel == 'DistrictHeatingSteam'
870
+ heating_fuel = 'DistrictHeating'
871
+ end
872
+ else
873
+ heating_fuel = 'DistrictHeatingWater' if heating_fuel == 'DistrictHeating'
874
+ end
875
+
847
876
  # create heating equipment and add to the loop
848
877
  case heating_fuel
849
878
  when 'DistrictHeating'
@@ -852,6 +881,18 @@ class Standard
852
881
  heating_equipment.autosizeNominalCapacity
853
882
  heat_pump_water_loop.addSupplyBranchForComponent(heating_equipment)
854
883
  heating_equipment_stpt_manager.setName("#{heat_pump_water_loop.name} District Heating Scheduled Dual Setpoint")
884
+ when 'DistrictHeatingWater'
885
+ heating_equipment = OpenStudio::Model::DistrictHeatingWater.new(model)
886
+ heating_equipment.setName("#{heat_pump_water_loop.name} District Heating")
887
+ heating_equipment.autosizeNominalCapacity
888
+ heat_pump_water_loop.addSupplyBranchForComponent(heating_equipment)
889
+ heating_equipment_stpt_manager.setName("#{heat_pump_water_loop.name} District Heating Scheduled Dual Setpoint")
890
+ when 'DistrictHeatingSteam'
891
+ heating_equipment = OpenStudio::Model::DistrictHeatingSteam.new(model)
892
+ heating_equipment.setName("#{heat_pump_water_loop.name} District Heating")
893
+ heating_equipment.autosizeNominalCapacity
894
+ heat_pump_water_loop.addSupplyBranchForComponent(heating_equipment)
895
+ heating_equipment_stpt_manager.setName("#{heat_pump_water_loop.name} District Heating Scheduled Dual Setpoint")
855
896
  when 'AirSourceHeatPump', 'ASHP'
856
897
  heating_equipment = create_central_air_source_heat_pump(model, heat_pump_water_loop)
857
898
  heating_equipment_stpt_manager.setName("#{heat_pump_water_loop.name} ASHP Scheduled Dual Setpoint")
@@ -1056,7 +1097,11 @@ class Standard
1056
1097
  ambient_loop.addSupplyBranchForComponent(district_cooling)
1057
1098
 
1058
1099
  # heating
1059
- district_heating = OpenStudio::Model::DistrictHeating.new(model)
1100
+ if model.version < OpenStudio::VersionString.new('3.7.0')
1101
+ district_heating = OpenStudio::Model::DistrictHeating.new(model)
1102
+ else
1103
+ district_heating = OpenStudio::Model::DistrictHeatingWater.new(model)
1104
+ end
1060
1105
  district_heating.setNominalCapacity(1_000_000_000_000) # large number; no autosizing
1061
1106
  ambient_loop.addSupplyBranchForComponent(district_heating)
1062
1107
 
@@ -1084,6 +1129,123 @@ class Standard
1084
1129
  return ambient_loop
1085
1130
  end
1086
1131
 
1132
+ # Model a 2-pipe plant loop, where the loop is either in heating or cooling.
1133
+ # For sizing reasons, this method keeps separate hot water and chilled water loops,
1134
+ # and connects them together with a common inverse schedule.
1135
+ #
1136
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
1137
+ # @param hot_water_loop [OpenStudio::Model::PlantLoop] the hot water loop
1138
+ # @param chilled_water_loop [OpenStudio::Model::PlantLoop] the chilled water loop
1139
+ # @param control_strategy [String] Method to determine whether the loop is in heating or cooling mode
1140
+ # 'outdoor_air_lockout' - The system will be in heating below the lockout_temperature variable,
1141
+ # and cooling above the lockout_temperature. Requires the lockout_temperature variable.
1142
+ # 'zone_demand' - Heating or cooling determined by preponderance of zone demand.
1143
+ # Requires thermal_zones defined.
1144
+ # @param lockout_temperature [Double] lockout temperature in degrees Fahrenheit, default 65F.
1145
+ # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones
1146
+ # @return [OpenStudio::Model::ScheduleRuleset]
1147
+ def model_two_pipe_loop(model,
1148
+ hot_water_loop,
1149
+ chilled_water_loop,
1150
+ control_strategy: 'outdoor_air_lockout',
1151
+ lockout_temperature: 65.0,
1152
+ thermal_zones: [])
1153
+
1154
+ if control_strategy == 'outdoor_air_lockout'
1155
+ # get or create outdoor sensor node to be used in plant availability managers if needed
1156
+ outdoor_airnode = model.outdoorAirNode
1157
+
1158
+ # create availability managers based on outdoor temperature
1159
+ # create hot water plant availability manager
1160
+ hot_water_loop_lockout_manager = OpenStudio::Model::AvailabilityManagerHighTemperatureTurnOff.new(model)
1161
+ hot_water_loop_lockout_manager.setName("#{hot_water_loop.name} Lockout Manager")
1162
+ hot_water_loop_lockout_manager.setSensorNode(outdoor_airnode)
1163
+ hot_water_loop_lockout_manager.setTemperature(OpenStudio.convert(lockout_temperature, 'F', 'C').get)
1164
+
1165
+ # set availability manager to hot water plant
1166
+ hot_water_loop.addAvailabilityManager(hot_water_loop_lockout_manager)
1167
+
1168
+ # create chilled water plant availability manager
1169
+ chilled_water_loop_lockout_manager = OpenStudio::Model::AvailabilityManagerLowTemperatureTurnOff.new(model)
1170
+ chilled_water_loop_lockout_manager.setName("#{chilled_water_loop.name} Lockout Manager")
1171
+ chilled_water_loop_lockout_manager.setSensorNode(outdoor_airnode)
1172
+ chilled_water_loop_lockout_manager.setTemperature(OpenStudio.convert(lockout_temperature, 'F', 'C').get)
1173
+
1174
+ # set availability manager to hot water plant
1175
+ chilled_water_loop.addAvailabilityManager(chilled_water_loop_lockout_manager)
1176
+ else
1177
+ # create availability managers based on zone heating and cooling demand
1178
+ hot_water_loop_name = ems_friendly_name(hot_water_loop.name)
1179
+ chilled_water_loop_name = ems_friendly_name(chilled_water_loop.name)
1180
+
1181
+ # create hot water plant availability schedule managers and create an EMS acuator
1182
+ sch_hot_water_availability = model_add_constant_schedule_ruleset(model,
1183
+ 0,
1184
+ name = "#{hot_water_loop.name} Availability Schedule",
1185
+ sch_type_limit: 'OnOff')
1186
+
1187
+ hot_water_loop_manager = OpenStudio::Model::AvailabilityManagerScheduled.new(model)
1188
+ hot_water_loop_manager.setName("#{hot_water_loop.name} Availability Manager")
1189
+ hot_water_loop_manager.setSchedule(sch_hot_water_availability)
1190
+
1191
+ hot_water_plant_ctrl = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_hot_water_availability,
1192
+ 'Schedule:Year',
1193
+ 'Schedule Value')
1194
+ hot_water_plant_ctrl.setName("#{hot_water_loop_name}_availability_control")
1195
+
1196
+ # set availability manager to hot water plant
1197
+ hot_water_loop.addAvailabilityManager(hot_water_loop_manager)
1198
+
1199
+ # create chilled water plant availability schedule managers and create an EMS acuator
1200
+ sch_chilled_water_availability = model_add_constant_schedule_ruleset(model,
1201
+ 0,
1202
+ name = "#{chilled_water_loop.name} Availability Schedule",
1203
+ sch_type_limit: 'OnOff')
1204
+
1205
+ chilled_water_loop_manager = OpenStudio::Model::AvailabilityManagerScheduled.new(model)
1206
+ chilled_water_loop_manager.setName("#{chilled_water_loop.name} Availability Manager")
1207
+ chilled_water_loop_manager.setSchedule(sch_chilled_water_availability)
1208
+
1209
+ chilled_water_plant_ctrl = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_chilled_water_availability,
1210
+ 'Schedule:Year',
1211
+ 'Schedule Value')
1212
+ chilled_water_plant_ctrl.setName("#{chilled_water_loop_name}_availability_control")
1213
+
1214
+ # set availability manager to chilled water plant
1215
+ chilled_water_loop.addAvailabilityManager(chilled_water_loop_manager)
1216
+
1217
+ # check if zone heat and cool requests program exists, if not create it
1218
+ determine_zone_cooling_needs_prg = model.getEnergyManagementSystemProgramByName('Determine_Zone_Cooling_Needs')
1219
+ determine_zone_heating_needs_prg = model.getEnergyManagementSystemProgramByName('Determine_Zone_Heating_Needs')
1220
+ unless determine_zone_cooling_needs_prg.is_initialized && determine_zone_heating_needs_prg.is_initialized
1221
+ model_add_zone_heat_cool_request_count_program(model, thermal_zones)
1222
+ end
1223
+
1224
+ # create program to determine plant heating or cooling mode
1225
+ determine_plant_mode_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
1226
+ determine_plant_mode_prg.setName('Determine_Heating_Cooling_Plant_Mode')
1227
+ determine_plant_mode_prg_body = <<-EMS
1228
+ IF Zone_Heating_Ratio > 0.5,
1229
+ SET #{hot_water_loop_name}_availability_control = 1,
1230
+ SET #{chilled_water_loop_name}_availability_control = 0,
1231
+ ELSEIF Zone_Cooling_Ratio > 0.5,
1232
+ SET #{hot_water_loop_name}_availability_control = 0,
1233
+ SET #{chilled_water_loop_name}_availability_control = 1,
1234
+ ELSE,
1235
+ SET #{hot_water_loop_name}_availability_control = #{hot_water_loop_name}_availability_control,
1236
+ SET #{chilled_water_loop_name}_availability_control = #{chilled_water_loop_name}_availability_control,
1237
+ ENDIF
1238
+ EMS
1239
+ determine_plant_mode_prg.setBody(determine_plant_mode_prg_body)
1240
+
1241
+ # create EMS program manager objects
1242
+ programs_at_beginning_of_timestep = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
1243
+ programs_at_beginning_of_timestep.setName('Heating_Cooling_Demand_Based_Plant_Availability_At_Beginning_Of_Timestep')
1244
+ programs_at_beginning_of_timestep.setCallingPoint('BeginTimestepBeforePredictor')
1245
+ programs_at_beginning_of_timestep.addProgram(determine_plant_mode_prg)
1246
+ end
1247
+ end
1248
+
1087
1249
  # Creates a DOAS system with cold supply and terminal units for each zone.
1088
1250
  # This is the default DOAS system for DOE prototype buildings. Use model_add_doas for other DOAS systems.
1089
1251
  #
@@ -1097,7 +1259,7 @@ class Standard
1097
1259
  # @param min_frac_oa_sch [String] name of the minimum fraction of outdoor air schedule, default is always on
1098
1260
  # @param fan_maximum_flow_rate [Double] fan maximum flow rate in cfm, default is autosize
1099
1261
  # @param econo_ctrl_mthd [String] economizer control type, default is Fixed Dry Bulb
1100
- # @param energy_recovery [Bool] if true, an ERV will be added to the system
1262
+ # @param energy_recovery [Boolean] if true, an ERV will be added to the system
1101
1263
  # @param doas_control_strategy [String] DOAS control strategy
1102
1264
  # @param clg_dsgn_sup_air_temp [Double] design cooling supply air temperature in degrees Fahrenheit, default 65F
1103
1265
  # @param htg_dsgn_sup_air_temp [Double] design heating supply air temperature in degrees Fahrenheit, default 75F
@@ -1329,7 +1491,7 @@ class Standard
1329
1491
  # @param fan_maximum_flow_rate [Double] fan maximum flow rate in cfm, default is autosize
1330
1492
  # @param econo_ctrl_mthd [String] economizer control type, default is Fixed Dry Bulb
1331
1493
  # If enabled, the DOAS will be sized for twice the ventilation minimum to allow economizing
1332
- # @param include_exhaust_fan [Bool] if true, include an exhaust fan
1494
+ # @param include_exhaust_fan [Boolean] if true, include an exhaust fan
1333
1495
  # @param clg_dsgn_sup_air_temp [Double] design cooling supply air temperature in degrees Fahrenheit, default 65F
1334
1496
  # @param htg_dsgn_sup_air_temp [Double] design heating supply air temperature in degrees Fahrenheit, default 75F
1335
1497
  # @return [OpenStudio::Model::AirLoopHVAC] the resulting DOAS air loop
@@ -1622,7 +1784,7 @@ class Standard
1622
1784
  # @param system_name [String] the name of the system, or nil in which case it will be defaulted
1623
1785
  # @param return_plenum [OpenStudio::Model::ThermalZone] the zone to attach as the supply plenum, or nil, in which case no return plenum will be used
1624
1786
  # @param heating_type [String] main heating coil fuel type
1625
- # valid choices are NaturalGas, Gas, Electricity, HeatPump, DistrictHeating, or nil (defaults to NaturalGas)
1787
+ # valid choices are NaturalGas, Gas, Electricity, HeatPump, DistrictHeating, DistrictHeatingWater, DistrictHeatingSteam, or nil (defaults to NaturalGas)
1626
1788
  # @param reheat_type [String] valid options are NaturalGas, Gas, Electricity, Water, nil (no heat)
1627
1789
  # @param hot_water_loop [OpenStudio::Model::PlantLoop] hot water loop to connect heating and reheat coils to
1628
1790
  # @param chilled_water_loop [OpenStudio::Model::PlantLoop] chilled water loop to connect cooling coil to
@@ -1778,7 +1940,7 @@ class Standard
1778
1940
  else
1779
1941
  avail_mgr = nil
1780
1942
  end
1781
- else
1943
+ else
1782
1944
  avail_mgr = air_loop.availabilityManagers[0]
1783
1945
  end
1784
1946
 
@@ -1823,7 +1985,8 @@ class Standard
1823
1985
  else
1824
1986
  terminal.setZoneMinimumAirFlowInputMethod('Constant')
1825
1987
  end
1826
- terminal.setMaximumFlowFractionDuringReheat(0.5)
1988
+ # default to single maximum control logic
1989
+ terminal.setDamperHeatingAction('Normal')
1827
1990
  terminal.setMaximumReheatAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
1828
1991
  air_loop.multiAddBranchForZone(zone, terminal.to_HVACComponent.get)
1829
1992
  air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(terminal, thermal_zone_outdoor_airflow_rate_per_area(zone))
@@ -1858,12 +2021,6 @@ class Standard
1858
2021
  end
1859
2022
  end
1860
2023
 
1861
- # Design outdoor air calculation based on VRP if applicable (prototypes maintained by PNNL)
1862
- model_system_outdoor_air_sizing_vrp_method(air_loop)
1863
-
1864
- # set the damper action based on the template
1865
- air_loop_hvac_apply_vav_damper_action(air_loop)
1866
-
1867
2024
  return air_loop
1868
2025
  end
1869
2026
 
@@ -2012,9 +2169,10 @@ class Standard
2012
2169
  # @param chilled_water_loop [OpenStudio::Model::PlantLoop] chilled water loop to connect cooling coils to. If nil, will be DX cooling
2013
2170
  # @param heating_type [String] main heating coil fuel type
2014
2171
  # valid choices are NaturalGas, Electricity, Water, or nil (defaults to NaturalGas)
2015
- # @param electric_reheat [Bool] if true electric reheat coils, if false the reheat coils served by hot_water_loop
2172
+ # @param electric_reheat [Boolean] if true electric reheat coils, if false the reheat coils served by hot_water_loop
2016
2173
  # @param hvac_op_sch [String] name of the HVAC operation schedule or nil in which case will be defaulted to always on
2017
2174
  # @param oa_damper_sch [String] name of the oa damper schedule or nil in which case will be defaulted to always open
2175
+ # @param econo_ctrl_mthd [String] economizer control type
2018
2176
  # @return [OpenStudio::Model::AirLoopHVAC] the resulting packaged VAV air loop
2019
2177
  def model_add_pvav(model,
2020
2178
  thermal_zones,
@@ -2025,7 +2183,8 @@ class Standard
2025
2183
  heating_type: nil,
2026
2184
  electric_reheat: false,
2027
2185
  hvac_op_sch: nil,
2028
- oa_damper_sch: nil)
2186
+ oa_damper_sch: nil,
2187
+ econo_ctrl_mthd: nil)
2029
2188
  OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Adding Packaged VAV for #{thermal_zones.size} zones.")
2030
2189
 
2031
2190
  # create air handler
@@ -2118,18 +2277,25 @@ class Standard
2118
2277
  name: "#{air_loop.name} Clg Coil")
2119
2278
  end
2120
2279
 
2121
- # Outdoor air intake system
2280
+ # outdoor air intake system
2122
2281
  oa_intake_controller = OpenStudio::Model::ControllerOutdoorAir.new(model)
2282
+ oa_intake_controller.setName("#{air_loop.name} OA Controller")
2123
2283
  oa_intake_controller.setMinimumLimitType('FixedMinimum')
2124
2284
  oa_intake_controller.autosizeMinimumOutdoorAirFlowRate
2125
- oa_intake_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
2285
+ oa_intake_controller.resetMaximumFractionofOutdoorAirSchedule
2126
2286
  oa_intake_controller.resetEconomizerMinimumLimitDryBulbTemperature
2287
+ unless econo_ctrl_mthd.nil?
2288
+ oa_intake_controller.setEconomizerControlType(econo_ctrl_mthd)
2289
+ end
2290
+ unless oa_damper_sch.nil?
2291
+ oa_intake_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
2292
+ end
2293
+ controller_mv = oa_intake_controller.controllerMechanicalVentilation
2294
+ controller_mv.setName("#{air_loop.name} Mechanical Ventilation Controller")
2295
+ controller_mv.setSystemOutdoorAirMethod('ZoneSum')
2127
2296
  oa_intake = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_intake_controller)
2128
2297
  oa_intake.setName("#{air_loop.name} OA System")
2129
2298
  oa_intake.addToNode(air_loop.supplyInletNode)
2130
- controller_mv = oa_intake_controller.controllerMechanicalVentilation
2131
- controller_mv.setName("#{air_loop.name} Ventilation Controller")
2132
- controller_mv.setAvailabilitySchedule(oa_damper_sch)
2133
2299
 
2134
2300
  # set air loop availability controls and night cycle manager, after oa system added
2135
2301
  air_loop.setAvailabilitySchedule(hvac_op_sch)
@@ -2142,7 +2308,7 @@ class Standard
2142
2308
  else
2143
2309
  avail_mgr = nil
2144
2310
  end
2145
- else
2311
+ else
2146
2312
  avail_mgr = air_loop.availabilityManagers[0]
2147
2313
  end
2148
2314
 
@@ -2177,6 +2343,8 @@ class Standard
2177
2343
  else
2178
2344
  terminal.setZoneMinimumAirFlowInputMethod('Constant')
2179
2345
  end
2346
+ # default to single maximum control logic
2347
+ terminal.setDamperHeatingAction('Normal')
2180
2348
  terminal.setMaximumReheatAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
2181
2349
  air_loop.multiAddBranchForZone(zone, terminal.to_HVACComponent.get)
2182
2350
  air_terminal_single_duct_vav_reheat_apply_initial_prototype_damper_position(terminal, thermal_zone_outdoor_airflow_rate_per_area(zone))
@@ -2191,13 +2359,7 @@ class Standard
2191
2359
  sizing_zone.setZoneHeatingDesignSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
2192
2360
  end
2193
2361
 
2194
- # Design outdoor air calculation based on VRP if applicable (prototypes maintained by PNNL)
2195
- model_system_outdoor_air_sizing_vrp_method(air_loop)
2196
-
2197
- # set the damper action based on the template
2198
- air_loop_hvac_apply_vav_damper_action(air_loop)
2199
-
2200
- return true
2362
+ return air_loop
2201
2363
  end
2202
2364
 
2203
2365
  # Creates a packaged VAV system with parallel fan powered boxes and adds it to the model.
@@ -2502,7 +2664,7 @@ class Standard
2502
2664
  # Set the damper action based on the template.
2503
2665
  air_loop_hvac_apply_vav_damper_action(air_loop)
2504
2666
 
2505
- return true
2667
+ return air_loop
2506
2668
  end
2507
2669
 
2508
2670
  # Creates a PSZ-AC system for each zone and adds it to the model.
@@ -2722,9 +2884,15 @@ class Standard
2722
2884
  unitary_system.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40.0, 'F', 'C').get)
2723
2885
  unitary_system.setName("#{air_loop.name} Unitary HP")
2724
2886
  unitary_system.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
2725
- unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
2726
- unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
2727
- unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('SupplyAirFlowRate')
2887
+ if model.version < OpenStudio::VersionString.new('3.7.0')
2888
+ unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
2889
+ unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
2890
+ unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('SupplyAirFlowRate')
2891
+ else
2892
+ unitary_system.autosizeSupplyAirFlowRateDuringCoolingOperation
2893
+ unitary_system.autosizeSupplyAirFlowRateDuringHeatingOperation
2894
+ unitary_system.autosizeSupplyAirFlowRateWhenNoCoolingorHeatingisRequired
2895
+ end
2728
2896
  when 'Single Speed Heat Pump'
2729
2897
  unitary_system.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(OpenStudio.convert(40.0, 'F', 'C').get)
2730
2898
  unitary_system.setName("#{air_loop.name} Unitary HP")
@@ -2764,7 +2932,7 @@ class Standard
2764
2932
  else
2765
2933
  avail_mgr = nil
2766
2934
  end
2767
- else
2935
+ else
2768
2936
  avail_mgr = air_loop.availabilityManagers[0]
2769
2937
  end
2770
2938
 
@@ -2875,7 +3043,6 @@ class Standard
2875
3043
  when 'Water'
2876
3044
  htg_coil = create_coil_heating_water(model,
2877
3045
  hot_water_loop,
2878
- air_loop_node: air_loop.supplyOutletNode,
2879
3046
  name: "#{air_loop.name} Water Htg Coil")
2880
3047
  else
2881
3048
  # Zero-capacity, always-off electric heating coil
@@ -2934,13 +3101,23 @@ class Standard
2934
3101
  unitary_system.setControllingZoneorThermostatLocation(zone)
2935
3102
  unitary_system.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
2936
3103
  unitary_system.setFanPlacement('BlowThrough')
2937
- unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
2938
- unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
2939
- if minimum_volume_setpoint.nil?
2940
- unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('SupplyAirFlowRate')
3104
+ if model.version < OpenStudio::VersionString.new('3.7.0')
3105
+ unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
3106
+ unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
3107
+ if minimum_volume_setpoint.nil?
3108
+ unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('SupplyAirFlowRate')
3109
+ else
3110
+ unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('FractionOfAutosizedCoolingValue')
3111
+ unitary_system.setFractionofAutosizedDesignCoolingSupplyAirFlowRateWhenNoCoolingorHeatingisRequired(minimum_volume_setpoint)
3112
+ end
2941
3113
  else
2942
- unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('FractionOfAutosizedCoolingValue')
2943
- unitary_system.setFractionofAutosizedDesignCoolingSupplyAirFlowRateWhenNoCoolingorHeatingisRequired(minimum_volume_setpoint)
3114
+ unitary_system.autosizeSupplyAirFlowRateDuringCoolingOperation
3115
+ unitary_system.autosizeSupplyAirFlowRateDuringHeatingOperation
3116
+ if minimum_volume_setpoint.nil?
3117
+ unitary_system.autosizeSupplyAirFlowRateWhenNoCoolingorHeatingisRequired
3118
+ else
3119
+ unitary_system.setFractionofAutosizedDesignCoolingSupplyAirFlowRateWhenNoCoolingorHeatingisRequired(minimum_volume_setpoint)
3120
+ end
2944
3121
  end
2945
3122
  unitary_system.setSupplyAirFanOperatingModeSchedule(model.alwaysOnDiscreteSchedule)
2946
3123
  unitary_system.addToNode(air_loop.supplyInletNode)
@@ -2975,7 +3152,7 @@ class Standard
2975
3152
  # @param model [OpenStudio::Model::Model] OpenStudio model object
2976
3153
  # @param space [OpenStudio::Model::Space] which space to assign the data center loads to
2977
3154
  # @param dc_watts_per_area [Double] data center load, in W/m^2
2978
- # @return [Bool] returns true if successful, false if not
3155
+ # @return [Boolean] returns true if successful, false if not
2979
3156
  def model_add_data_center_load(model, space, dc_watts_per_area)
2980
3157
  # create data center load
2981
3158
  data_center_definition = OpenStudio::Model::ElectricEquipmentDefinition.new(model)
@@ -2999,7 +3176,7 @@ class Standard
2999
3176
  # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to connect to this system
3000
3177
  # @param hvac_op_sch [String] name of the HVAC operation schedule or nil in which case will be defaulted to always on
3001
3178
  # @param oa_damper_sch [String] name of the oa damper schedule or nil in which case will be defaulted to always open
3002
- # @param main_data_center [Bool] whether or not this is the main data center in the building.
3179
+ # @param main_data_center [Boolean] whether or not this is the main data center in the building.
3003
3180
  # @return [Array<OpenStudio::Model::AirLoopHVAC>] an array of the resulting air loops
3004
3181
  def model_add_data_center_hvac(model,
3005
3182
  thermal_zones,
@@ -3249,7 +3426,7 @@ class Standard
3249
3426
  fan.setAvailabilitySchedule(hvac_op_sch)
3250
3427
  else
3251
3428
  OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', "Fan type '#{fan_type}' not recognized, cannot add CRAC.")
3252
- return []
3429
+ return false
3253
3430
  end
3254
3431
 
3255
3432
  # create cooling coil
@@ -3369,7 +3546,7 @@ class Standard
3369
3546
  # Creates a CRAH system for larger size data center and adds it to the model.
3370
3547
  #
3371
3548
  # @param model [OpenStudio::Model::Model] OpenStudio model object
3372
- # @param chilled_water_loop [string]
3549
+ # @param chilled_water_loop [String
3373
3550
  # @param system_name [String] the name of the system, or nil in which case it will be defaulted
3374
3551
  # @param thermal_zones [String] zones to connect to this system
3375
3552
  # @param hvac_op_sch [String] name of the HVAC operation schedule
@@ -3806,7 +3983,7 @@ class Standard
3806
3983
  # @param heating_type [String] valid choices are NaturalGas, Electricity, Water, nil (no heat)
3807
3984
  # @param hot_water_loop [OpenStudio::Model::PlantLoop] hot water loop to connect heating coil to. Set to nil for heating types besides water
3808
3985
  # @param fan_type [String] valid choices are ConstantVolume, Cycling
3809
- # @param ventilation [Bool] If true, ventilation will be supplied through the unit. If false,
3986
+ # @param ventilation [Boolean] If true, ventilation will be supplied through the unit. If false,
3810
3987
  # no ventilation will be supplied through the unit, with the expectation that it will be provided by a DOAS or separate system.
3811
3988
  # @return [Array<OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner>] an array of the resulting PTACs
3812
3989
  def model_add_ptac(model,
@@ -3925,7 +4102,7 @@ class Standard
3925
4102
  # @param model [OpenStudio::Model::Model] OpenStudio model object
3926
4103
  # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to connect to this system
3927
4104
  # @param fan_type [String] valid choices are ConstantVolume, Cycling
3928
- # @param ventilation [Bool] If true, ventilation will be supplied through the unit. If false,
4105
+ # @param ventilation [Boolean] If true, ventilation will be supplied through the unit. If false,
3929
4106
  # no ventilation will be supplied through the unit, with the expectation that it will be provided by a DOAS or separate system.
3930
4107
  # @return [Array<OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner>] an array of the resulting PTACs.
3931
4108
  def model_add_pthp(model,
@@ -4013,7 +4190,7 @@ class Standard
4013
4190
  # @param hvac_op_sch [String] name of the HVAC operation schedule or nil in which case will be defaulted to always on
4014
4191
  # @param fan_control_type [String] valid choices are OnOff, ConstantVolume, VariableVolume
4015
4192
  # @param fan_pressure_rise [Double] fan pressure rise, inH2O
4016
- # @param heating_type [String] valid choices are NaturalGas, Gas, Electricity, Electric, DistrictHeating
4193
+ # @param heating_type [String] valid choices are NaturalGas, Gas, Electricity, Electric, DistrictHeating, DistrictHeatingWater, DistrictHeatingSteam
4017
4194
  # @param hot_water_loop [OpenStudio::Model::PlantLoop] hot water loop to connect to the heating coil
4018
4195
  # @param rated_inlet_water_temperature [Double] rated inlet water temperature in degrees Fahrenheit, default is 180F
4019
4196
  # @param rated_outlet_water_temperature [Double] rated outlet water temperature in degrees Fahrenheit, default is 160F
@@ -4075,7 +4252,7 @@ class Standard
4075
4252
  htg_coil = create_coil_heating_electric(model,
4076
4253
  name: "#{zone.name} UnitHeater Electric Htg Coil",
4077
4254
  schedule: hvac_op_sch)
4078
- elsif heating_type == 'DistrictHeating' && !hot_water_loop.nil?
4255
+ elsif heating_type.include?('DistrictHeating') && !hot_water_loop.nil?
4079
4256
  # control temperature for hot water loop
4080
4257
  if rated_inlet_water_temperature.nil?
4081
4258
  rated_inlet_water_temperature_c = OpenStudio.convert(180.0, 'F', 'C').get
@@ -4291,9 +4468,15 @@ class Standard
4291
4468
  unitary_system.setControllingZoneorThermostatLocation(zone)
4292
4469
  unitary_system.setMaximumSupplyAirTemperature(dsgn_temps['zn_htg_dsgn_sup_air_temp_c'])
4293
4470
  unitary_system.setFanPlacement('BlowThrough')
4294
- unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
4295
- unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
4296
- unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('SupplyAirFlowRate')
4471
+ if model.version < OpenStudio::VersionString.new('3.7.0')
4472
+ unitary_system.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
4473
+ unitary_system.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
4474
+ unitary_system.setSupplyAirFlowRateMethodWhenNoCoolingorHeatingisRequired('SupplyAirFlowRate')
4475
+ else
4476
+ unitary_system.autosizeSupplyAirFlowRateDuringCoolingOperation
4477
+ unitary_system.autosizeSupplyAirFlowRateDuringHeatingOperation
4478
+ unitary_system.autosizeSupplyAirFlowRateWhenNoCoolingorHeatingisRequired
4479
+ end
4297
4480
  unitary_system.setSupplyAirFanOperatingModeSchedule(model.alwaysOffDiscreteSchedule)
4298
4481
  unitary_system.addToNode(air_loop.supplyInletNode)
4299
4482
 
@@ -4376,7 +4559,7 @@ class Standard
4376
4559
  #
4377
4560
  # @param model [OpenStudio::Model::Model] OpenStudio model object
4378
4561
  # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to add fan coil units
4379
- # @param ventilation [Bool] If true, ventilation will be supplied through the unit. If false,
4562
+ # @param ventilation [Boolean] If true, ventilation will be supplied through the unit. If false,
4380
4563
  # no ventilation will be supplied through the unit, with the expectation that it will be provided by a DOAS or separate system.
4381
4564
  # @return [Array<OpenStudio::Model::ZoneHVACTerminalUnitVariableRefrigerantFlow>] array of vrf units.
4382
4565
  def model_add_vrf(model,
@@ -4436,7 +4619,7 @@ class Standard
4436
4619
  # @param chilled_water_loop [OpenStudio::Model::PlantLoop] the chilled water loop that serves the fan coils.
4437
4620
  # @param hot_water_loop [OpenStudio::Model::PlantLoop] the hot water loop that serves the fan coils.
4438
4621
  # If nil, a zero-capacity, electric heating coil set to Always-Off will be included in the unit.
4439
- # @param ventilation [Bool] If true, ventilation will be supplied through the unit. If false,
4622
+ # @param ventilation [Boolean] If true, ventilation will be supplied through the unit. If false,
4440
4623
  # no ventilation will be supplied through the unit, with the expectation that it will be provided by a DOAS or separate system.
4441
4624
  # @param capacity_control_method [String] Capacity control method for the fan coil. Options are ConstantFanVariableFlow,
4442
4625
  # CyclingFan, VariableFanVariableFlow, and VariableFanConstantFlow. If VariableFan, the fan will be VariableVolume.
@@ -4520,27 +4703,70 @@ class Standard
4520
4703
  # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to add radiant loops
4521
4704
  # @param hot_water_loop [OpenStudio::Model::PlantLoop] the hot water loop that serves the radiant loop.
4522
4705
  # @param chilled_water_loop [OpenStudio::Model::PlantLoop] the chilled water loop that serves the radiant loop.
4706
+ # @param two_pipe_system [Boolean] when set to true, it converts the default 4-pipe water plant HVAC system to a 2-pipe system.
4707
+ # @param two_pipe_control_strategy [String] Method to determine whether the loop is in heating or cooling mode
4708
+ # 'outdoor_air_lockout' - The system will be in heating below the two_pipe_lockout_temperature variable,
4709
+ # and cooling above the two_pipe_lockout_temperature. Requires the two_pipe_lockout_temperature variable.
4710
+ # 'zone_demand' - Create EMS code to determine heating or cooling mode based on zone heating or cooling load requests.
4711
+ # Requires thermal_zones defined.
4712
+ # @param two_pipe_lockout_temperature [Double] hot water plant lockout in degrees Fahrenheit, default 65F.
4713
+ # Hot water plant is unavailable when outdoor drybulb is above the specified threshold.
4714
+ # @param plant_supply_water_temperature_control [Bool] Set to true if the plant supply water temperature
4715
+ # is to be controlled else it is held constant, default to false.
4716
+ # @param plant_supply_water_temperature_control_strategy [String] Method to determine how to control the plant's supply water temperature.
4717
+ # 'outdoor_air' - Set the supply water temperature based on the outdoor air temperature.
4718
+ # 'zone_demand' - Set the supply water temperature based on the preponderance of zone demand.
4719
+ # Requires thermal_zone defined.
4720
+ # @param hwsp_at_oat_low [Double] hot water plant supply water temperature setpoint, in F, at the outdoor low temperature.
4721
+ # Requires
4722
+ # @param hw_oat_low [Double] outdoor drybulb air temperature, in F, for low setpoint for hot water plant.
4723
+ # @param hwsp_at_oat_high [Double] hot water plant supply water temperature setpoint, in F, at the outdoor high temperature.
4724
+ # @param hw_oat_high [Double] outdoor drybulb air temperature, in F, for high setpoint for hot water plant.
4725
+ # @param chwsp_at_oat_low [Double] chilled water plant supply water temperature setpoint, in F, at the outdoor low temperature.
4726
+ # @param chw_oat_low [Double] outdoor drybulb air temperature, in F, for low setpoint for chilled water plant.
4727
+ # @param chwsp_at_oat_high [Double] chilled water plant supply water temperature setpoint, in F, at the outdoor high temperature.
4728
+ # @param chw_oat_high [Double] outdoor drybulb air temperature, in F, for high setpoint for chilled water plant.
4523
4729
  # @param radiant_type [String] type of radiant system, floor or ceiling, to create in zone.
4524
- # @param include_carpet [Bool] boolean to include thin carpet tile over radiant slab, default to true
4730
+ # @param radiant_temperature_control_type [String] determines the controlled temperature for the radiant system
4731
+ # options are 'MeanAirTemperature', 'MeanRadiantTemperature', 'OperativeTemperature', 'OutdoorDryBulbTemperature',
4732
+ # 'OutdoorWetBulbTemperature', 'SurfaceFaceTemperature', 'SurfaceInteriorTemperature'
4733
+ # @param radiant_setpoint_control_type [String] determines the response of the radiant system at setpoint temperature
4734
+ # options are 'ZeroFlowPower', 'HalfFlowPower'
4735
+ # @param include_carpet [Boolean] boolean to include thin carpet tile over radiant slab, default to true
4525
4736
  # @param carpet_thickness_in [Double] thickness of carpet in inches
4737
+ # @param control_strategy [String] name of control strategy. Options are 'proportional_control', 'oa_based_control',
4738
+ # 'constant_control', and 'none'.
4739
+ # If control strategy is 'proportional_control', the method will apply the CBE radiant control sequences
4740
+ # detailed in Raftery et al. (2017), 'A new control strategy for high thermal mass radiant systems'.
4741
+ # If control strategy is 'oa_based_control', the method will apply native EnergyPlus objects/parameters
4742
+ # to vary slab setpoint based on outdoor weather.
4743
+ # If control strategy is 'constant_control', the method will apply native EnergyPlus objects/parameters to
4744
+ # maintain a constant slab setpoint.
4745
+ # Otherwise no control strategy will be applied and the radiant system will assume the EnergyPlus default controls.
4746
+ # @param use_zone_occupancy_for_control [Boolean] Set to true if radiant system is to use specific zone occupancy objects
4747
+ # for CBE control strategy. If false, then it will use values in model_occ_hr_start and model_occ_hr_end
4748
+ # for all radiant zones. default to true.
4749
+ # @param occupied_percentage_threshold [Double] the minimum fraction (0 to 1) that counts as occupied
4750
+ # if this parameter is set, the returned ScheduleRuleset will be 0 = unoccupied, 1 = occupied
4751
+ # otherwise the ScheduleRuleset will be the weighted fractional occupancy schedule.
4752
+ # Only used if use_zone_occupancy_for_control is set to true.
4526
4753
  # @param model_occ_hr_start [Double] (Optional) Only applies if control_strategy is 'proportional_control'.
4527
4754
  # Starting hour of building occupancy.
4528
4755
  # @param model_occ_hr_end [Double] (Optional) Only applies if control_strategy is 'proportional_control'.
4529
4756
  # Ending hour of building occupancy.
4530
- # @param control_strategy [String] name of control strategy. Options are 'proportional_control' and 'none'.
4531
- # If control strategy is 'proportional_control', the method will apply the CBE radiant control sequences
4532
- # detailed in Raftery et al. (2017), 'A new control strategy for high thermal mass radiant systems'.
4533
- # Otherwise no control strategy will be applied and the radiant system will assume the EnergyPlus default controls.
4534
4757
  # @param proportional_gain [Double] (Optional) Only applies if control_strategy is 'proportional_control'.
4535
4758
  # Proportional gain constant (recommended 0.3 or less).
4536
- # @param minimum_operation [Double] (Optional) Only applies if control_strategy is 'proportional_control'.
4537
- # Minimum number of hours of operation for radiant system before it shuts off.
4538
- # @param weekend_temperature_reset [Double] (Optional) Only applies if control_strategy is 'proportional_control'.
4539
- # Weekend temperature reset for slab temperature setpoint in degree Celsius.
4540
- # @param early_reset_out_arg [Double] (Optional) Only applies if control_strategy is 'proportional_control'.
4541
- # Time at which the weekend temperature reset is removed.
4542
4759
  # @param switch_over_time [Double] Time limitation for when the system can switch between heating and cooling
4543
- # @param radiant_lockout [Bool] True if system contains a radiant lockout
4760
+ # @param slab_sp_at_oat_low [Double] radiant slab temperature setpoint, in F, at the outdoor high temperature.
4761
+ # @param slab_oat_low [Double] outdoor drybulb air temperature, in F, for low radiant slab setpoint.
4762
+ # @param slab_sp_at_oat_high [Double] radiant slab temperature setpoint, in F, at the outdoor low temperature.
4763
+ # @param slab_oat_high [Double] outdoor drybulb air temperature, in F, for high radiant slab setpoint.
4764
+ # @param radiant_availability_type [String] a preset that determines the availability of the radiant system
4765
+ # options are 'all_day', 'precool', 'afternoon_shutoff', 'occupancy'
4766
+ # If preset is set to 'all_day' radiant system is available 24 hours a day, 'precool' primarily operates
4767
+ # radiant system during night-time hours, 'afternoon_shutoff' avoids operation during peak grid demand,
4768
+ # and 'occupancy' operates radiant system during building occupancy hours.
4769
+ # @param radiant_lockout [Boolean] True if system contains a radiant lockout. If true, it will overwrite radiant_availability_type.
4544
4770
  # @param radiant_lockout_start_time [double] decimal hour of when radiant lockout starts
4545
4771
  # Only used if radiant_lockout is true
4546
4772
  # @param radiant_lockout_end_time [double] decimal hour of when radiant lockout ends
@@ -4552,17 +4778,36 @@ class Standard
4552
4778
  thermal_zones,
4553
4779
  hot_water_loop,
4554
4780
  chilled_water_loop,
4781
+ two_pipe_system: false,
4782
+ two_pipe_control_strategy: 'outdoor_air_lockout',
4783
+ two_pipe_lockout_temperature: 65.0,
4784
+ plant_supply_water_temperature_control: false,
4785
+ plant_supply_water_temperature_control_strategy: 'outdoor_air',
4786
+ hwsp_at_oat_low: 120.0,
4787
+ hw_oat_low: 55.0,
4788
+ hwsp_at_oat_high: 80.0,
4789
+ hw_oat_high: 70.0,
4790
+ chwsp_at_oat_low: 70.0,
4791
+ chw_oat_low: 65.0,
4792
+ chwsp_at_oat_high: 55.0,
4793
+ chw_oat_high: 75.0,
4555
4794
  radiant_type: 'floor',
4795
+ radiant_temperature_control_type: 'SurfaceFaceTemperature',
4796
+ radiant_setpoint_control_type: 'ZeroFlowPower',
4556
4797
  include_carpet: true,
4557
4798
  carpet_thickness_in: 0.25,
4799
+ control_strategy: 'proportional_control',
4800
+ use_zone_occupancy_for_control: true,
4801
+ occupied_percentage_threshold: 0.10,
4558
4802
  model_occ_hr_start: 6.0,
4559
4803
  model_occ_hr_end: 18.0,
4560
- control_strategy: 'proportional_control',
4561
4804
  proportional_gain: 0.3,
4562
- minimum_operation: 1,
4563
- weekend_temperature_reset: 2,
4564
- early_reset_out_arg: 20,
4565
4805
  switch_over_time: 24.0,
4806
+ slab_sp_at_oat_low: 73,
4807
+ slab_oat_low: 65,
4808
+ slab_sp_at_oat_high: 68,
4809
+ slab_oat_high: 80,
4810
+ radiant_availability_type: 'precool',
4566
4811
  radiant_lockout: false,
4567
4812
  radiant_lockout_start_time: 12.0,
4568
4813
  radiant_lockout_end_time: 20.0)
@@ -4682,9 +4927,16 @@ class Standard
4682
4927
  radiant_interior_floor_slab_construction = OpenStudio::Model::ConstructionWithInternalSource.new(layers)
4683
4928
  radiant_interior_floor_slab_construction.setName('Radiant Interior Floor Slab Construction')
4684
4929
  radiant_interior_floor_slab_construction.setSourcePresentAfterLayerNumber(1)
4685
- radiant_interior_floor_slab_construction.setTemperatureCalculationRequestedAfterLayerNumber(2)
4930
+ radiant_interior_floor_slab_construction.setTemperatureCalculationRequestedAfterLayerNumber(1)
4686
4931
  radiant_interior_floor_slab_construction.setTubeSpacing(0.2286) # 9 inches
4687
4932
 
4933
+ # create reversed interior floor construction
4934
+ rev_radiant_interior_floor_slab_construction = OpenStudio::Model::ConstructionWithInternalSource.new(layers.reverse)
4935
+ rev_radiant_interior_floor_slab_construction.setName('Radiant Interior Floor Slab Construction - Reversed')
4936
+ rev_radiant_interior_floor_slab_construction.setSourcePresentAfterLayerNumber(layers.length - 1)
4937
+ rev_radiant_interior_floor_slab_construction.setTemperatureCalculationRequestedAfterLayerNumber(layers.length - 1)
4938
+ rev_radiant_interior_floor_slab_construction.setTubeSpacing(0.2286) # 9 inches
4939
+
4688
4940
  layers = []
4689
4941
  layers << mat_thin_carpet_tile if include_carpet
4690
4942
  layers << mat_concrete_3_5in
@@ -4693,9 +4945,16 @@ class Standard
4693
4945
  radiant_interior_ceiling_slab_construction.setName('Radiant Interior Ceiling Slab Construction')
4694
4946
  slab_src_loc = include_carpet ? 2 : 1
4695
4947
  radiant_interior_ceiling_slab_construction.setSourcePresentAfterLayerNumber(slab_src_loc)
4696
- radiant_interior_ceiling_slab_construction.setTemperatureCalculationRequestedAfterLayerNumber(slab_src_loc + 1)
4948
+ radiant_interior_ceiling_slab_construction.setTemperatureCalculationRequestedAfterLayerNumber(slab_src_loc)
4697
4949
  radiant_interior_ceiling_slab_construction.setTubeSpacing(0.2286) # 9 inches
4698
4950
 
4951
+ # create reversed interior ceiling construction
4952
+ rev_radiant_interior_ceiling_slab_construction = OpenStudio::Model::ConstructionWithInternalSource.new(layers.reverse)
4953
+ rev_radiant_interior_ceiling_slab_construction.setName('Radiant Interior Ceiling Slab Construction - Reversed')
4954
+ rev_radiant_interior_ceiling_slab_construction.setSourcePresentAfterLayerNumber(layers.length - slab_src_loc)
4955
+ rev_radiant_interior_ceiling_slab_construction.setTemperatureCalculationRequestedAfterLayerNumber(layers.length - slab_src_loc)
4956
+ rev_radiant_interior_ceiling_slab_construction.setTubeSpacing(0.2286) # 9 inches
4957
+
4699
4958
  layers = []
4700
4959
  layers << mat_refl_roof_membrane
4701
4960
  layers << mat_roof_insulation
@@ -4708,7 +4967,7 @@ class Standard
4708
4967
  radiant_ceiling_slab_construction.setTubeSpacing(0.2286) # 9 inches
4709
4968
 
4710
4969
  # adjust hot and chilled water loop temperatures and set new setpoint schedules
4711
- radiant_htg_dsgn_sup_wtr_temp_delt_r = 10
4970
+ radiant_htg_dsgn_sup_wtr_temp_delt_r = 10.0
4712
4971
  radiant_htg_dsgn_sup_wtr_temp_c = OpenStudio.convert(radiant_htg_dsgn_sup_wtr_temp_f, 'F', 'C').get
4713
4972
  radiant_htg_dsgn_sup_wtr_temp_delt_k = OpenStudio.convert(radiant_htg_dsgn_sup_wtr_temp_delt_r, 'R', 'K').get
4714
4973
  hot_water_loop.sizingPlant.setDesignLoopExitTemperature(radiant_htg_dsgn_sup_wtr_temp_c)
@@ -4756,29 +5015,89 @@ class Standard
4756
5015
  throttling_range_f = 4.0 # 2 degF on either side of control temperature
4757
5016
  throttling_range_c = OpenStudio.convert(throttling_range_f, 'F', 'C').get
4758
5017
 
4759
- # create availability schedule for radiant loop
4760
- if radiant_lockout
4761
- radiant_avail_sch = OpenStudio::Model::ScheduleRuleset.new(model)
4762
- radiant_avail_sch.setName('Radiant System Availability Schedule')
5018
+ # create preset availability schedule for radiant loop
5019
+ radiant_avail_sch = OpenStudio::Model::ScheduleRuleset.new(model)
5020
+ radiant_avail_sch.setName('Radiant System Availability Schedule')
5021
+
5022
+ unless radiant_lockout
5023
+ case radiant_availability_type.downcase
5024
+ when 'all_day'
5025
+ start_hour = 24
5026
+ start_minute = 0
5027
+ end_hour = 24
5028
+ end_minute = 0
5029
+ when 'afternoon_shutoff'
5030
+ start_hour = 15
5031
+ start_minute = 0
5032
+ end_hour = 22
5033
+ end_minute = 0
5034
+ when 'precool'
5035
+ start_hour = 10
5036
+ start_minute = 0
5037
+ end_hour = 22
5038
+ end_minute = 0
5039
+ when 'occupancy'
5040
+ start_hour = model_occ_hr_end.to_i
5041
+ start_minute = ((model_occ_hr_end % 1) * 60).to_i
5042
+ end_hour = model_occ_hr_start.to_i
5043
+ end_minute = ((model_occ_hr_start % 1) * 60).to_i
5044
+ else
5045
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.Model.Model', "Unsupported radiant availability preset '#{radiant_availability_type}'. Defaulting to all day operation.")
5046
+ start_hour = 24
5047
+ start_minute = 0
5048
+ end_hour = 24
5049
+ end_minute = 0
5050
+ end
5051
+ end
4763
5052
 
5053
+ # create custom availability schedule for radiant loop
5054
+ if radiant_lockout
4764
5055
  start_hour = radiant_lockout_start_time.to_i
4765
5056
  start_minute = ((radiant_lockout_start_time % 1) * 60).to_i
4766
5057
  end_hour = radiant_lockout_end_time.to_i
4767
5058
  end_minute = ((radiant_lockout_end_time % 1) * 60).to_i
5059
+ end
4768
5060
 
4769
- if radiant_lockout_end_time > radiant_lockout_start_time
4770
- radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, start_hour, start_minute, 0), 1.0)
4771
- radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, end_hour, end_minute, 0), 0.0)
4772
- radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1.0) if radiant_lockout_end_time < 24
4773
- elsif radiant_lockout_start_time > radiant_lockout_end_time
4774
- radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, end_hour, end_minute, 0), 0.0)
4775
- radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, start_hour, start_minute, 0), 1.0)
4776
- radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.0) if radiant_lockout_start_time < 24
4777
- else
4778
- radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1.0)
4779
- end
5061
+ # create availability schedules
5062
+ if end_hour > start_hour
5063
+ radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, start_hour, start_minute, 0), 1.0)
5064
+ radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, end_hour, end_minute, 0), 0.0)
5065
+ radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1.0) if end_hour < 24
5066
+ elsif start_hour > end_hour
5067
+ radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, end_hour, end_minute, 0), 0.0)
5068
+ radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, start_hour, start_minute, 0), 1.0)
5069
+ radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.0) if start_hour < 24
4780
5070
  else
4781
- radiant_avail_sch = model.alwaysOnDiscreteSchedule
5071
+ radiant_avail_sch.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1.0)
5072
+ end
5073
+
5074
+ # convert to a two-pipe system if required
5075
+ if two_pipe_system
5076
+ model_two_pipe_loop(model, hot_water_loop, chilled_water_loop,
5077
+ control_strategy: two_pipe_control_strategy,
5078
+ lockout_temperature: two_pipe_lockout_temperature,
5079
+ thermal_zones: thermal_zones)
5080
+ end
5081
+
5082
+ # add supply water temperature control if enabled
5083
+ if plant_supply_water_temperature_control
5084
+ # add supply water temperature for heating plant loop
5085
+ model_add_plant_supply_water_temperature_control(model, hot_water_loop,
5086
+ control_strategy: plant_supply_water_temperature_control_strategy,
5087
+ sp_at_oat_low: hwsp_at_oat_low,
5088
+ oat_low: hw_oat_low,
5089
+ sp_at_oat_high: hwsp_at_oat_high,
5090
+ oat_high: hw_oat_high,
5091
+ thermal_zones: thermal_zones)
5092
+
5093
+ # add supply water temperature for cooling plant loop
5094
+ model_add_plant_supply_water_temperature_control(model, chilled_water_loop,
5095
+ control_strategy: plant_supply_water_temperature_control_strategy,
5096
+ sp_at_oat_low: chwsp_at_oat_low,
5097
+ oat_low: chw_oat_low,
5098
+ sp_at_oat_high: chwsp_at_oat_high,
5099
+ oat_high: chw_oat_high,
5100
+ thermal_zones: thermal_zones)
4782
5101
  end
4783
5102
 
4784
5103
  # make a low temperature radiant loop for each zone
@@ -4824,6 +5143,10 @@ class Standard
4824
5143
  surface.setConstruction(radiant_exterior_slab_construction)
4825
5144
  else # interior floor
4826
5145
  surface.setConstruction(radiant_interior_floor_slab_construction)
5146
+
5147
+ # also assign construciton to adjacent surface
5148
+ adjacent_surface = surface.adjacentSurface.get
5149
+ adjacent_surface.setConstruction(rev_radiant_interior_floor_slab_construction)
4827
5150
  end
4828
5151
  end
4829
5152
  elsif radiant_type == 'ceiling'
@@ -4832,6 +5155,10 @@ class Standard
4832
5155
  surface.setConstruction(radiant_ceiling_slab_construction)
4833
5156
  else # interior ceiling
4834
5157
  surface.setConstruction(radiant_interior_ceiling_slab_construction)
5158
+
5159
+ # also assign construciton to adjacent surface
5160
+ adjacent_surface = surface.adjacentSurface.get
5161
+ adjacent_surface.setConstruction(rev_radiant_interior_ceiling_slab_construction)
4835
5162
  end
4836
5163
  end
4837
5164
  end
@@ -4854,8 +5181,11 @@ class Standard
4854
5181
  radiant_loop.setNumberofCircuits('CalculateFromCircuitLength')
4855
5182
  radiant_loop.setCircuitLength(106.7)
4856
5183
 
4857
- # radiant loop controls
4858
- radiant_loop.setTemperatureControlType('MeanAirTemperature')
5184
+ # radiant loop temperature controls
5185
+ radiant_loop.setTemperatureControlType(radiant_temperature_control_type)
5186
+
5187
+ # radiant loop setpoint temperature response
5188
+ radiant_loop.setSetpointControlType(radiant_setpoint_control_type)
4859
5189
  radiant_loop.addToThermalZone(zone)
4860
5190
  radiant_loops << radiant_loop
4861
5191
 
@@ -4863,19 +5193,41 @@ class Standard
4863
5193
  rename_plant_loop_nodes(model)
4864
5194
 
4865
5195
  # set radiant loop controls
4866
- if control_strategy == 'proportional_control'
5196
+ case control_strategy.downcase
5197
+ when 'proportional_control'
5198
+ # slab setpoint varies based on previous day zone conditions
4867
5199
  model_add_radiant_proportional_controls(model, zone, radiant_loop,
4868
- radiant_type: radiant_type,
5200
+ radiant_temperature_control_type: radiant_temperature_control_type,
5201
+ use_zone_occupancy_for_control: use_zone_occupancy_for_control,
5202
+ occupied_percentage_threshold: occupied_percentage_threshold,
4869
5203
  model_occ_hr_start: model_occ_hr_start,
4870
5204
  model_occ_hr_end: model_occ_hr_end,
4871
5205
  proportional_gain: proportional_gain,
4872
- minimum_operation: minimum_operation,
4873
- weekend_temperature_reset: weekend_temperature_reset,
4874
- early_reset_out_arg: early_reset_out_arg,
4875
5206
  switch_over_time: switch_over_time)
5207
+ when 'oa_based_control'
5208
+ # slab setpoint varies based on outdoor weather
5209
+ model_add_radiant_basic_controls(model, zone, radiant_loop,
5210
+ radiant_temperature_control_type: radiant_temperature_control_type,
5211
+ slab_setpoint_oa_control: true,
5212
+ switch_over_time: switch_over_time,
5213
+ slab_sp_at_oat_low: slab_sp_at_oat_low,
5214
+ slab_oat_low: slab_oat_low,
5215
+ slab_sp_at_oat_high: slab_sp_at_oat_high,
5216
+ slab_oat_high: slab_oat_high)
5217
+ when 'constant_control'
5218
+ # constant slab setpoint control
5219
+ model_add_radiant_basic_controls(model, zone, radiant_loop,
5220
+ radiant_temperature_control_type: radiant_temperature_control_type,
5221
+ slab_setpoint_oa_control: false,
5222
+ switch_over_time: switch_over_time,
5223
+ slab_sp_at_oat_low: slab_sp_at_oat_low,
5224
+ slab_oat_low: slab_oat_low,
5225
+ slab_sp_at_oat_high: slab_sp_at_oat_high,
5226
+ slab_oat_high: slab_oat_high)
5227
+ else
5228
+ # 'none'; use energyplus default controls
4876
5229
  end
4877
5230
  end
4878
-
4879
5231
  return radiant_loops
4880
5232
  end
4881
5233
 
@@ -4939,9 +5291,9 @@ class Standard
4939
5291
  #
4940
5292
  # @param model [OpenStudio::Model::Model] OpenStudio model object
4941
5293
  # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to add fan coil units to.
4942
- # @param heating [Bool] if true, the unit will include a NaturalGas heating coil
4943
- # @param cooling [Bool] if true, the unit will include a DX cooling coil
4944
- # @param ventilation [Bool] if true, the unit will include an OA intake
5294
+ # @param heating [Boolean] if true, the unit will include a NaturalGas heating coil
5295
+ # @param cooling [Boolean] if true, the unit will include a DX cooling coil
5296
+ # @param ventilation [Boolean] if true, the unit will include an OA intake
4945
5297
  # @return [Array<OpenStudio::Model::AirLoopHVAC>] and array of air loops representing the furnaces
4946
5298
  def model_add_furnace_central_ac(model,
4947
5299
  thermal_zones,
@@ -5070,9 +5422,9 @@ class Standard
5070
5422
  #
5071
5423
  # @param model [OpenStudio::Model::Model] OpenStudio model object
5072
5424
  # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to add fan coil units to.
5073
- # @param heating [Bool] if true, the unit will include a NaturalGas heating coil
5074
- # @param cooling [Bool] if true, the unit will include a DX cooling coil
5075
- # @param ventilation [Bool] if true, the unit will include an OA intake
5425
+ # @param heating [Boolean] if true, the unit will include a NaturalGas heating coil
5426
+ # @param cooling [Boolean] if true, the unit will include a DX cooling coil
5427
+ # @param ventilation [Boolean] if true, the unit will include an OA intake
5076
5428
  # @return [Array<OpenStudio::Model::AirLoopHVAC>] and array of air loops representing the heat pumps
5077
5429
  def model_add_central_air_source_heat_pump(model,
5078
5430
  thermal_zones,
@@ -5211,7 +5563,7 @@ class Standard
5211
5563
  # @param model [OpenStudio::Model::Model] OpenStudio model object
5212
5564
  # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones served by heat pumps
5213
5565
  # @param condenser_loop [OpenStudio::Model::PlantLoop] the condenser loop for the heat pumps #
5214
- # @param ventilation [Bool] if true, ventilation will be supplied through the unit.
5566
+ # @param ventilation [Boolean] if true, ventilation will be supplied through the unit.
5215
5567
  # If false, no ventilation will be supplied through the unit, with the expectation that it will be provided by a DOAS or separate system.
5216
5568
  # @return [Array<OpenStudio::Model::ZoneHVACWaterToAirHeatPump>] an array of heat pumps
5217
5569
  def model_add_water_source_hp(model,
@@ -5712,10 +6064,315 @@ class Standard
5712
6064
  return fan_type
5713
6065
  end
5714
6066
 
6067
+ # Adds supply water temperature control on specified plant water loops.
6068
+ #
6069
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
6070
+ # @param plant_water_loop [OpenStudio::Model::PlantLoop] plant water loop to add supply water temperature control.
6071
+ # @param control_strategy [String] Method to determine how to control the plant's supply water temperature (swt).
6072
+ # 'outdoor_air' - The plant's swt will be proportional to the outdoor air based on the next 4 parameters.
6073
+ # 'zone_demand' - The plant's swt will be determined by preponderance of zone demand.
6074
+ # Requires thermal_zone defined.
6075
+ # @param sp_at_oat_low [Double] supply water temperature setpoint, in F, at the outdoor low temperature.
6076
+ # @param oat_low [Double] outdoor drybulb air temperature, in F, for low setpoint.
6077
+ # @param sp_at_oat_high [Double] supply water temperature setpoint, in F, at the outdoor high temperature.
6078
+ # @param oat_high [Double] outdoor drybulb air temperature, in F, for high setpoint.
6079
+ # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones
6080
+ def model_add_plant_supply_water_temperature_control(model, plant_water_loop,
6081
+ control_strategy: 'outdoor_air',
6082
+ sp_at_oat_low: nil,
6083
+ oat_low: nil,
6084
+ sp_at_oat_high: nil,
6085
+ oat_high: nil,
6086
+ thermal_zones: [])
6087
+
6088
+ # check that all required temperature parameters are defined
6089
+ if sp_at_oat_low.nil? && oat_low.nil? && sp_at_oat_high.nil? && oat_high.nil?
6090
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', 'At least one of the required temperature parameter is nil.')
6091
+ end
6092
+
6093
+ # remove any existing setpoint manager on the plant water loop
6094
+ exisiting_setpoint_managers = plant_water_loop.loopTemperatureSetpointNode.setpointManagers
6095
+ exisiting_setpoint_managers.each(&:disconnect)
6096
+
6097
+ if control_strategy == 'outdoor_air'
6098
+ # create supply water temperature setpoint managers for plant based on outdoor temperature
6099
+ water_loop_setpoint_manager = OpenStudio::Model::SetpointManagerOutdoorAirReset.new(model)
6100
+ water_loop_setpoint_manager.setName("#{plant_water_loop.name.get} Supply Water Temperature Control")
6101
+ water_loop_setpoint_manager.setControlVariable('Temperature')
6102
+ water_loop_setpoint_manager.setSetpointatOutdoorLowTemperature(OpenStudio.convert(sp_at_oat_low, 'F', 'C').get)
6103
+ water_loop_setpoint_manager.setOutdoorLowTemperature(OpenStudio.convert(oat_low, 'F', 'C').get)
6104
+ water_loop_setpoint_manager.setSetpointatOutdoorHighTemperature(OpenStudio.convert(sp_at_oat_high, 'F', 'C').get)
6105
+ water_loop_setpoint_manager.setOutdoorHighTemperature(OpenStudio.convert(oat_high, 'F', 'C').get)
6106
+ water_loop_setpoint_manager.addToNode(plant_water_loop.loopTemperatureSetpointNode)
6107
+ else
6108
+ # create supply water temperature setpoint managers for plant based on zone heating and cooling demand
6109
+ # check if zone heat and cool requests program exists, if not create it
6110
+ determine_zone_cooling_needs_prg = model.getEnergyManagementSystemProgramByName('Determine_Zone_Cooling_Needs')
6111
+ determine_zone_heating_needs_prg = model.getEnergyManagementSystemProgramByName('Determine_Zone_Heating_Needs')
6112
+ unless determine_zone_cooling_needs_prg.is_initialized && determine_zone_heating_needs_prg.is_initialized
6113
+ model_add_zone_heat_cool_request_count_program(model, thermal_zones)
6114
+ end
6115
+
6116
+ plant_water_loop_name = ems_friendly_name(plant_water_loop.name)
6117
+
6118
+ if plant_water_loop.componentType.valueName == 'Heating'
6119
+ swt_upper_limit = sp_at_oat_low.nil? ? OpenStudio.convert(120, 'F', 'C').get : OpenStudio.convert(sp_at_oat_low, 'F', 'C').get
6120
+ swt_lower_limit = sp_at_oat_high.nil? ? OpenStudio.convert(80, 'F', 'C').get : OpenStudio.convert(sp_at_oat_high, 'F', 'C').get
6121
+ swt_init = OpenStudio.convert(100, 'F', 'C').get
6122
+ zone_demand_var = 'Zone_Heating_Ratio'
6123
+ swt_inc_condition_var = '> 0.70'
6124
+ swt_dec_condition_var = '< 0.30'
6125
+ else
6126
+ swt_upper_limit = sp_at_oat_low.nil? ? OpenStudio.convert(70, 'F', 'C').get : OpenStudio.convert(sp_at_oat_low, 'F', 'C').get
6127
+ swt_lower_limit = sp_at_oat_high.nil? ? OpenStudio.convert(55, 'F', 'C').get : OpenStudio.convert(sp_at_oat_high, 'F', 'C').get
6128
+ swt_init = OpenStudio.convert(62, 'F', 'C').get
6129
+ zone_demand_var = 'Zone_Cooling_Ratio'
6130
+ swt_inc_condition_var = '< 0.30'
6131
+ swt_dec_condition_var = '> 0.70'
6132
+ end
6133
+
6134
+ # plant loop supply water control actuator
6135
+ sch_plant_swt_ctrl = model_add_constant_schedule_ruleset(model,
6136
+ swt_init,
6137
+ name = "#{plant_water_loop_name}_Sch_Supply_Water_Temperature")
6138
+
6139
+ cmd_plant_water_ctrl = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_plant_swt_ctrl,
6140
+ 'Schedule:Year',
6141
+ 'Schedule Value')
6142
+ cmd_plant_water_ctrl.setName("#{plant_water_loop_name}_supply_water_ctrl")
6143
+
6144
+ # create plant loop setpoint manager
6145
+ water_loop_setpoint_manager = OpenStudio::Model::SetpointManagerScheduled.new(model,
6146
+ sch_plant_swt_ctrl)
6147
+ water_loop_setpoint_manager.setName("#{plant_water_loop.name.get} Supply Water Temperature Control")
6148
+ water_loop_setpoint_manager.setControlVariable('Temperature')
6149
+ water_loop_setpoint_manager.addToNode(plant_water_loop.loopTemperatureSetpointNode)
6150
+
6151
+ # add uninitialized variables into constant program
6152
+ set_constant_values_prg_body = <<-EMS
6153
+ SET #{plant_water_loop_name}_supply_water_ctrl = #{swt_init}
6154
+ EMS
6155
+
6156
+ set_constant_values_prg = model.getEnergyManagementSystemProgramByName('Set_Plant_Constant_Values')
6157
+ if set_constant_values_prg.is_initialized
6158
+ set_constant_values_prg = set_constant_values_prg.get
6159
+ set_constant_values_prg.addLine(set_constant_values_prg_body)
6160
+ else
6161
+ set_constant_values_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
6162
+ set_constant_values_prg.setName('Set_Plant_Constant_Values')
6163
+ set_constant_values_prg.setBody(set_constant_values_prg_body)
6164
+ end
6165
+
6166
+ # program for supply water temperature control in the plot
6167
+ determine_plant_swt_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
6168
+ determine_plant_swt_prg.setName("Determine_#{plant_water_loop_name}_Supply_Water_Temperature")
6169
+ determine_plant_swt_prg_body = <<-EMS
6170
+ SET SWT_Increase = 1,
6171
+ SET SWT_Decrease = 1,
6172
+ SET SWT_upper_limit = #{swt_upper_limit},
6173
+ SET SWT_lower_limit = #{swt_lower_limit},
6174
+ IF #{zone_demand_var} #{swt_inc_condition_var} && (@Mod CurrentTime 1) == 0,
6175
+ SET #{plant_water_loop_name}_supply_water_ctrl = #{plant_water_loop_name}_supply_water_ctrl + SWT_Increase,
6176
+ ELSEIF #{zone_demand_var} #{swt_dec_condition_var} && (@Mod CurrentTime 1) == 0,
6177
+ SET #{plant_water_loop_name}_supply_water_ctrl = #{plant_water_loop_name}_supply_water_ctrl - SWT_Decrease,
6178
+ ELSE,
6179
+ SET #{plant_water_loop_name}_supply_water_ctrl = #{plant_water_loop_name}_supply_water_ctrl,
6180
+ ENDIF,
6181
+ IF #{plant_water_loop_name}_supply_water_ctrl > SWT_upper_limit,
6182
+ SET #{plant_water_loop_name}_supply_water_ctrl = SWT_upper_limit
6183
+ ENDIF,
6184
+ IF #{plant_water_loop_name}_supply_water_ctrl < SWT_lower_limit,
6185
+ SET #{plant_water_loop_name}_supply_water_ctrl = SWT_lower_limit
6186
+ ENDIF
6187
+ EMS
6188
+ determine_plant_swt_prg.setBody(determine_plant_swt_prg_body)
6189
+
6190
+ # create EMS program manager objects
6191
+ programs_at_beginning_of_timestep = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
6192
+ programs_at_beginning_of_timestep.setName("#{plant_water_loop_name}_Demand_Based_Supply_Water_Temperature_At_Beginning_Of_Timestep")
6193
+ programs_at_beginning_of_timestep.setCallingPoint('BeginTimestepBeforePredictor')
6194
+ programs_at_beginning_of_timestep.addProgram(determine_plant_swt_prg)
6195
+
6196
+ initialize_constant_parameters = model.getEnergyManagementSystemProgramCallingManagerByName('Initialize_Constant_Parameters')
6197
+ if initialize_constant_parameters.is_initialized
6198
+ initialize_constant_parameters = initialize_constant_parameters.get
6199
+ # add program if it does not exist in manager
6200
+ existing_program_names = initialize_constant_parameters.programs.collect { |prg| prg.name.get.downcase }
6201
+ unless existing_program_names.include? set_constant_values_prg.name.get.downcase
6202
+ initialize_constant_parameters.addProgram(set_constant_values_prg)
6203
+ end
6204
+ else
6205
+ initialize_constant_parameters = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
6206
+ initialize_constant_parameters.setName('Initialize_Constant_Parameters')
6207
+ initialize_constant_parameters.setCallingPoint('BeginNewEnvironment')
6208
+ initialize_constant_parameters.addProgram(set_constant_values_prg)
6209
+ end
6210
+
6211
+ initialize_constant_parameters_after_warmup = model.getEnergyManagementSystemProgramCallingManagerByName('Initialize_Constant_Parameters_After_Warmup')
6212
+ if initialize_constant_parameters_after_warmup.is_initialized
6213
+ initialize_constant_parameters_after_warmup = initialize_constant_parameters_after_warmup.get
6214
+ # add program if it does not exist in manager
6215
+ existing_program_names = initialize_constant_parameters_after_warmup.programs.collect { |prg| prg.name.get.downcase }
6216
+ unless existing_program_names.include? set_constant_values_prg.name.get.downcase
6217
+ initialize_constant_parameters_after_warmup.addProgram(set_constant_values_prg)
6218
+ end
6219
+ else
6220
+ initialize_constant_parameters_after_warmup = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
6221
+ initialize_constant_parameters_after_warmup.setName('Initialize_Constant_Parameters_After_Warmup')
6222
+ initialize_constant_parameters_after_warmup.setCallingPoint('AfterNewEnvironmentWarmUpIsComplete')
6223
+ initialize_constant_parameters_after_warmup.addProgram(set_constant_values_prg)
6224
+ end
6225
+ end
6226
+ end
6227
+
6228
+ # Make EMS program that will compare 'measured' zone air temperatures to thermostats
6229
+ # setpoint to determine if zone needs cooling or heating. Program will output the total
6230
+ # zones needing heating and cooling and the their ratio using the total number of zones.
6231
+ #
6232
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
6233
+ # @param thermal_zones [Array<OpenStudio::Model::ThermalZone>] array of zones to dictate cooling or heating mode of water plant
6234
+ def model_add_zone_heat_cool_request_count_program(model, thermal_zones)
6235
+ # create container schedules to hold number of zones needing heating and cooling
6236
+ sch_zones_needing_heating = model_add_constant_schedule_ruleset(model,
6237
+ 0,
6238
+ name = 'Zones Needing Heating Count Schedule',
6239
+ sch_type_limit: 'Dimensionless')
6240
+
6241
+ zone_needing_heating_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_zones_needing_heating,
6242
+ 'Schedule:Year',
6243
+ 'Schedule Value')
6244
+ zone_needing_heating_actuator.setName('Zones_Needing_Heating')
6245
+
6246
+ sch_zones_needing_cooling = model_add_constant_schedule_ruleset(model,
6247
+ 0,
6248
+ name = 'Zones Needing Cooling Count Schedule',
6249
+ sch_type_limit: 'Dimensionless')
6250
+
6251
+ zone_needing_cooling_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_zones_needing_cooling,
6252
+ 'Schedule:Year',
6253
+ 'Schedule Value')
6254
+ zone_needing_cooling_actuator.setName('Zones_Needing_Cooling')
6255
+
6256
+ # create container schedules to hold ratio of zones needing heating and cooling
6257
+ sch_zones_needing_heating_ratio = model_add_constant_schedule_ruleset(model,
6258
+ 0,
6259
+ name = 'Zones Needing Heating Ratio Schedule',
6260
+ sch_type_limit: 'Dimensionless')
6261
+
6262
+ zone_needing_heating_ratio_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_zones_needing_heating_ratio,
6263
+ 'Schedule:Year',
6264
+ 'Schedule Value')
6265
+ zone_needing_heating_ratio_actuator.setName('Zone_Heating_Ratio')
6266
+
6267
+ sch_zones_needing_cooling_ratio = model_add_constant_schedule_ruleset(model,
6268
+ 0,
6269
+ name = 'Zones Needing Cooling Ratio Schedule',
6270
+ sch_type_limit: 'Dimensionless')
6271
+
6272
+ zone_needing_cooling_ratio_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_zones_needing_cooling_ratio,
6273
+ 'Schedule:Year',
6274
+ 'Schedule Value')
6275
+ zone_needing_cooling_ratio_actuator.setName('Zone_Cooling_Ratio')
6276
+
6277
+ #####
6278
+ # Create EMS program to check comfort exceedances
6279
+ ####
6280
+
6281
+ # initalize inner body for heating and cooling requests programs
6282
+ determine_zone_cooling_needs_prg_inner_body = ''
6283
+ determine_zone_heating_needs_prg_inner_body = ''
6284
+
6285
+ thermal_zones.each do |zone|
6286
+ # get existing 'sensors'
6287
+ exisiting_ems_sensors = model.getEnergyManagementSystemSensors
6288
+ exisiting_ems_sensors_names = exisiting_ems_sensors.collect { |sensor| sensor.name.get + '-' + sensor.outputVariableOrMeterName }
6289
+
6290
+ # Create zone air temperature 'sensor' for the zone.
6291
+ zone_name = ems_friendly_name(zone.name)
6292
+ zone_air_sensor_name = "#{zone_name}_ctrl_temperature"
6293
+
6294
+ unless exisiting_ems_sensors_names.include? zone_air_sensor_name + '-Zone Air Temperature'
6295
+ zone_ctrl_temperature = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Air Temperature')
6296
+ zone_ctrl_temperature.setName(zone_air_sensor_name)
6297
+ zone_ctrl_temperature.setKeyName(zone.name.get)
6298
+ end
6299
+
6300
+ # check for zone thermostats
6301
+ zone_thermostat = zone.thermostatSetpointDualSetpoint
6302
+ unless zone_thermostat.is_initialized
6303
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Model', "Zone #{zone.name} does not have thermostats.")
6304
+ return false
6305
+ end
6306
+
6307
+ zone_thermostat = zone.thermostatSetpointDualSetpoint.get
6308
+ zone_clg_thermostat = zone_thermostat.coolingSetpointTemperatureSchedule.get
6309
+ zone_htg_thermostat = zone_thermostat.heatingSetpointTemperatureSchedule.get
6310
+
6311
+ # create new sensor for zone thermostat if it does not exist already
6312
+ zone_clg_thermostat_sensor_name = "#{zone_name}_upper_comfort_limit"
6313
+ zone_htg_thermostat_sensor_name = "#{zone_name}_lower_comfort_limit"
6314
+
6315
+ unless exisiting_ems_sensors_names.include? zone_clg_thermostat_sensor_name + '-Schedule Value'
6316
+ # Upper comfort limit for the zone. Taken from existing thermostat schedules in the zone.
6317
+ zone_upper_comfort_limit = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
6318
+ zone_upper_comfort_limit.setName(zone_clg_thermostat_sensor_name)
6319
+ zone_upper_comfort_limit.setKeyName(zone_clg_thermostat.name.get)
6320
+ end
6321
+
6322
+ unless exisiting_ems_sensors_names.include? zone_htg_thermostat_sensor_name + '-Schedule Value'
6323
+ # Lower comfort limit for the zone. Taken from existing thermostat schedules in the zone.
6324
+ zone_lower_comfort_limit = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
6325
+ zone_lower_comfort_limit.setName(zone_htg_thermostat_sensor_name)
6326
+ zone_lower_comfort_limit.setKeyName(zone_htg_thermostat.name.get)
6327
+ end
6328
+
6329
+ # create program inner body for determining zone cooling needs
6330
+ if thermal_zones.include? zone
6331
+ determine_zone_cooling_needs_prg_inner_body += "IF #{zone_air_sensor_name} > #{zone_clg_thermostat_sensor_name},
6332
+ SET Zones_Needing_Cooling = Zones_Needing_Cooling + 1,
6333
+ ENDIF,\n"
6334
+ end
6335
+
6336
+ # create program inner body for determining zone cooling needs
6337
+ if thermal_zones.include? zone
6338
+ determine_zone_heating_needs_prg_inner_body += "IF #{zone_air_sensor_name} < #{zone_htg_thermostat_sensor_name},
6339
+ SET Zones_Needing_Heating = Zones_Needing_Heating + 1,
6340
+ ENDIF,\n"
6341
+ end
6342
+ end
6343
+
6344
+ # create program for determining zone cooling needs
6345
+ determine_zone_cooling_needs_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
6346
+ determine_zone_cooling_needs_prg.setName('Determine_Zone_Cooling_Needs')
6347
+ determine_zone_cooling_needs_prg_body =
6348
+ "SET Zones_Needing_Cooling = 0,
6349
+ #{determine_zone_cooling_needs_prg_inner_body}
6350
+ SET Total_Zones = #{thermal_zones.length},
6351
+ SET Zone_Cooling_Ratio = Zones_Needing_Cooling/Total_Zones"
6352
+ determine_zone_cooling_needs_prg.setBody(determine_zone_cooling_needs_prg_body)
6353
+
6354
+ # create program for determining zone heating needs
6355
+ determine_zone_heating_needs_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
6356
+ determine_zone_heating_needs_prg.setName('Determine_Zone_Heating_Needs')
6357
+ determine_zone_heating_needs_prg_body =
6358
+ "SET Zones_Needing_Heating = 0,
6359
+ #{determine_zone_heating_needs_prg_inner_body}
6360
+ SET Total_Zones = #{thermal_zones.length},
6361
+ SET Zone_Heating_Ratio = Zones_Needing_Heating/Total_Zones"
6362
+ determine_zone_heating_needs_prg.setBody(determine_zone_heating_needs_prg_body)
6363
+
6364
+ # create EMS program manager objects
6365
+ programs_at_beginning_of_timestep = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
6366
+ programs_at_beginning_of_timestep.setName('Heating_Cooling_Request_Programs_At_End_Of_Timestep')
6367
+ programs_at_beginning_of_timestep.setCallingPoint('EndOfZoneTimestepAfterZoneReporting')
6368
+ programs_at_beginning_of_timestep.addProgram(determine_zone_cooling_needs_prg)
6369
+ programs_at_beginning_of_timestep.addProgram(determine_zone_heating_needs_prg)
6370
+ end
6371
+
5715
6372
  # Adds a waterside economizer to the chilled water and condenser loop
5716
6373
  #
5717
6374
  # @param model [OpenStudio::Model::Model] OpenStudio model object
5718
- # @param integrated [Bool] when set to true, models an integrated waterside economizer
6375
+ # @param integrated [Boolean] when set to true, models an integrated waterside economizer
5719
6376
  # Integrated: in series with chillers, can run simultaneously with chillers
5720
6377
  # Non-Integrated: in parallel with chillers, chillers locked out during operation
5721
6378
  def model_add_waterside_economizer(model, chilled_water_loop, condenser_water_loop,
@@ -5864,7 +6521,7 @@ class Standard
5864
6521
  # Get the existing hot water loop in the model or add a new one if there isn't one already.
5865
6522
  #
5866
6523
  # @param model [OpenStudio::Model::Model] OpenStudio model object
5867
- # @param heat_fuel [String] the heating fuel. Valid choices are NaturalGas, Electricity, DistrictHeating
6524
+ # @param heat_fuel [String] the heating fuel. Valid choices are NaturalGas, Electricity, DistrictHeating, DistrictHeatingWater, DistrictHeatingSteam
5868
6525
  # @param hot_water_loop_type [String] Archetype for hot water loops
5869
6526
  # HighTemperature (180F supply) or LowTemperature (120F supply)
5870
6527
  def model_get_or_add_hot_water_loop(model, heat_fuel,
@@ -5936,7 +6593,7 @@ class Standard
5936
6593
  # Get the existing heat pump loop in the model or add a new one if there isn't one already.
5937
6594
  #
5938
6595
  # @param model [OpenStudio::Model::Model] OpenStudio model object
5939
- # @param heat_fuel [String] the heating fuel. Valid choices are NaturalGas, Electricity, DistrictHeating
6596
+ # @param heat_fuel [String] the heating fuel. Valid choices are NaturalGas, Electricity, DistrictHeating, DistrictHeatingWater, DistrictHeatingSteam
5940
6597
  # @param cool_fuel [String] the cooling fuel. Valid choices are Electricity and DistrictCooling.
5941
6598
  # @param heat_pump_loop_cooling_type [String] the type of cooling equipment if not DistrictCooling.
5942
6599
  # Valid options are:
@@ -5975,12 +6632,12 @@ class Standard
5975
6632
  # EvaporativeFluidCooler, EvaporativeFluidCoolerSingleSpeed, EvaporativeFluidCoolerTwoSpeed
5976
6633
  # @param air_loop_heating_type [String] type of heating coil serving main air loop, options are Gas, DX, or Water
5977
6634
  # @param air_loop_cooling_type [String] type of cooling coil serving main air loop, options are DX or Water
5978
- # @param zone_equipment_ventilation [Bool] toggle whether to include outdoor air ventilation on zone equipment
6635
+ # @param zone_equipment_ventilation [Boolean] toggle whether to include outdoor air ventilation on zone equipment
5979
6636
  # including as fan coil units, VRF terminals, or water source heat pumps.
5980
6637
  # @param fan_coil_capacity_control_method [String] Only applicable to Fan Coil system type.
5981
6638
  # Capacity control method for the fan coil. Options are ConstantFanVariableFlow, CyclingFan, VariableFanVariableFlow,
5982
6639
  # and VariableFanConstantFlow. If VariableFan, the fan will be VariableVolume.
5983
- # @return [Bool] returns true if successful, false if not
6640
+ # @return [Boolean] returns true if successful, false if not
5984
6641
  def model_add_hvac_system(model,
5985
6642
  system_type,
5986
6643
  main_heat_fuel,
@@ -6010,7 +6667,7 @@ class Standard
6010
6667
  case system_type
6011
6668
  when 'PTAC'
6012
6669
  case main_heat_fuel
6013
- when 'NaturalGas', 'DistrictHeating'
6670
+ when 'NaturalGas', 'DistrictHeating', 'DistrictHeatingWater', 'DistrictHeatingSteam'
6014
6671
  heating_type = 'Water'
6015
6672
  hot_water_loop = model_get_or_add_hot_water_loop(model, main_heat_fuel,
6016
6673
  hot_water_loop_type: hot_water_loop_type)
@@ -6052,7 +6709,7 @@ class Standard
6052
6709
  else
6053
6710
  hot_water_loop = nil
6054
6711
  end
6055
- when 'DistrictHeating'
6712
+ when 'DistrictHeating', 'DistrictHeatingWater', 'DistrictHeatingSteam'
6056
6713
  heating_type = 'Water'
6057
6714
  supplemental_heating_type = 'Electricity'
6058
6715
  hot_water_loop = model_get_or_add_hot_water_loop(model, main_heat_fuel,
@@ -6121,7 +6778,7 @@ class Standard
6121
6778
 
6122
6779
  when 'Fan Coil'
6123
6780
  case main_heat_fuel
6124
- when 'NaturalGas', 'DistrictHeating', 'Electricity'
6781
+ when 'NaturalGas', 'DistrictHeating', 'DistrictHeatingWater', 'DistrictHeatingSteam', 'Electricity'
6125
6782
  hot_water_loop = model_get_or_add_hot_water_loop(model, main_heat_fuel,
6126
6783
  hot_water_loop_type: hot_water_loop_type)
6127
6784
  when 'AirSourceHeatPump'
@@ -6148,7 +6805,7 @@ class Standard
6148
6805
 
6149
6806
  when 'Radiant Slab'
6150
6807
  case main_heat_fuel
6151
- when 'NaturalGas', 'DistrictHeating', 'Electricity'
6808
+ when 'NaturalGas', 'DistrictHeating', 'DistrictHeatingWater', 'DistrictHeatingSteam', 'Electricity'
6152
6809
  hot_water_loop = model_get_or_add_hot_water_loop(model, main_heat_fuel,
6153
6810
  hot_water_loop_type: hot_water_loop_type)
6154
6811
  when 'AirSourceHeatPump'
@@ -6173,7 +6830,7 @@ class Standard
6173
6830
 
6174
6831
  when 'Baseboards'
6175
6832
  case main_heat_fuel
6176
- when 'NaturalGas', 'DistrictHeating'
6833
+ when 'NaturalGas', 'DistrictHeating', 'DistrictHeatingWater', 'DistrictHeatingSteam'
6177
6834
  hot_water_loop = model_get_or_add_hot_water_loop(model, main_heat_fuel,
6178
6835
  hot_water_loop_type: hot_water_loop_type)
6179
6836
  when 'AirSourceHeatPump'
@@ -6251,7 +6908,7 @@ class Standard
6251
6908
 
6252
6909
  when 'VAV Reheat'
6253
6910
  case main_heat_fuel
6254
- when 'NaturalGas', 'Gas', 'HeatPump', 'DistrictHeating'
6911
+ when 'NaturalGas', 'Gas', 'HeatPump', 'DistrictHeating', 'DistrictHeatingWater', 'DistrictHeatingSteam'
6255
6912
  heating_type = main_heat_fuel
6256
6913
  hot_water_loop = model_get_or_add_hot_water_loop(model, main_heat_fuel,
6257
6914
  hot_water_loop_type: hot_water_loop_type)
@@ -6298,7 +6955,7 @@ class Standard
6298
6955
 
6299
6956
  when 'VAV No Reheat'
6300
6957
  case main_heat_fuel
6301
- when 'NaturalGas', 'Gas', 'HeatPump', 'DistrictHeating'
6958
+ when 'NaturalGas', 'Gas', 'HeatPump', 'DistrictHeating', 'DistrictHeatingWater', 'DistrictHeatingSteam'
6302
6959
  heating_type = main_heat_fuel
6303
6960
  hot_water_loop = model_get_or_add_hot_water_loop(model, main_heat_fuel,
6304
6961
  hot_water_loop_type: hot_water_loop_type)
@@ -6403,7 +7060,7 @@ class Standard
6403
7060
  fan_pressure_rise: 4.0)
6404
7061
 
6405
7062
  when 'Water Source Heat Pumps'
6406
- if main_heat_fuel == 'DistrictHeating' && cool_fuel == 'DistrictCooling'
7063
+ if main_heat_fuel.include?('DistrictHeating') && cool_fuel == 'DistrictCooling'
6407
7064
  condenser_loop = model_get_or_add_ambient_water_loop(model)
6408
7065
  elsif main_heat_fuel == 'AmbientLoop' && cool_fuel == 'AmbientLoop'
6409
7066
  condenser_loop = model_get_or_add_ambient_water_loop(model)