openstudio-standards 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (378) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +33 -0
  3. data/data/inventory/thermal_bridging.csv +90 -0
  4. data/data/standards/OpenStudio_Standards-deer-comstock.xlsx +0 -0
  5. data/data/standards/manage_OpenStudio_Standards.rb +1 -1
  6. data/data/standards/test_performance_expected_dd_results.csv +2014 -1891
  7. data/lib/openstudio-standards/btap/analysis.rb +8 -8
  8. data/lib/openstudio-standards/btap/bridging.rb +664 -645
  9. data/lib/openstudio-standards/btap/btap.model.rb +14 -14
  10. data/lib/openstudio-standards/btap/btap.rb +7 -7
  11. data/lib/openstudio-standards/btap/btap_result.rb +1 -1
  12. data/lib/openstudio-standards/btap/economics.rb +23 -23
  13. data/lib/openstudio-standards/btap/envelope.rb +8 -8
  14. data/lib/openstudio-standards/btap/equest.rb +1 -1
  15. data/lib/openstudio-standards/btap/geometry.rb +2 -2
  16. data/lib/openstudio-standards/btap/mpc.rb +7 -7
  17. data/lib/openstudio-standards/btap/schedules.rb +1 -1
  18. data/lib/openstudio-standards/btap/simmanager.rb +4 -4
  19. data/lib/openstudio-standards/btap/spaceloads.rb +26 -26
  20. data/lib/openstudio-standards/btap/utilities.rb +6 -6
  21. data/lib/openstudio-standards/btap/vintagizer.rb +1 -1
  22. data/lib/openstudio-standards/constructions/information.rb +83 -0
  23. data/lib/openstudio-standards/constructions/materials/modify.rb +72 -0
  24. data/lib/openstudio-standards/constructions/modify.rb +80 -0
  25. data/lib/openstudio-standards/create_typical/create_typical.rb +983 -0
  26. data/lib/openstudio-standards/create_typical/enumerations.rb +484 -0
  27. data/lib/openstudio-standards/create_typical/space_type_blend.rb +791 -0
  28. data/lib/openstudio-standards/create_typical/space_type_ratios.rb +494 -0
  29. data/lib/openstudio-standards/daylighting/space.rb +47 -0
  30. data/lib/openstudio-standards/geometry/create.rb +801 -0
  31. data/lib/openstudio-standards/geometry/create_bar.rb +2170 -0
  32. data/lib/openstudio-standards/geometry/information.rb +462 -0
  33. data/lib/openstudio-standards/geometry/modify.rb +48 -0
  34. data/lib/openstudio-standards/hvac/air_loop/information.rb +79 -0
  35. data/lib/openstudio-standards/hvac/cbecs_hvac.rb +616 -0
  36. data/lib/openstudio-standards/hvac/setpoint_managers/information.rb +91 -0
  37. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirTerminalSingleDuctVAVReheat.rb +1 -1
  38. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.AirTerminalSingleDuctVAVReheat.rb +1 -1
  39. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
  40. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Model.rb +1 -1
  41. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
  42. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +2 -2
  43. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.hvac_systems.rb +1 -1
  44. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
  45. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +4 -36
  46. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.hvac_systems.rb +1 -1
  47. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
  48. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +4 -36
  49. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +3 -3
  50. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb +1 -1
  51. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirTerminalSingleDuctVAVReheat.rb +1 -1
  52. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.elevators.rb +1 -1
  53. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirTerminalSingleDuctVAVReheat.rb +1 -1
  54. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.CoilHeatingGas.rb +1 -1
  55. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.elevators.rb +1 -1
  56. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
  57. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
  58. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +7 -7
  59. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Courthouse.rb +8 -8
  60. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.FullServiceRestaurant.rb +14 -14
  61. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.HighRiseApartment.rb +9 -9
  62. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Hospital.rb +16 -16
  63. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +7 -7
  64. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterHighITE.rb +8 -8
  65. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterLowITE.rb +8 -8
  66. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeHotel.rb +11 -11
  67. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOffice.rb +7 -7
  68. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOfficeDetailed.rb +9 -9
  69. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOffice.rb +8 -8
  70. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOfficeDetailed.rb +11 -11
  71. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MidriseApartment.rb +9 -9
  72. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Outpatient.rb +19 -19
  73. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.PrimarySchool.rb +10 -10
  74. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.QuickServiceRestaurant.rb +13 -13
  75. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStandalone.rb +6 -6
  76. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStripmall.rb +6 -6
  77. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SecondarySchool.rb +9 -9
  78. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterHighITE.rb +8 -8
  79. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterLowITE.rb +8 -8
  80. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallHotel.rb +8 -8
  81. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOffice.rb +8 -8
  82. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOfficeDetailed.rb +11 -11
  83. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperMarket.rb +10 -10
  84. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperTallBuilding.rb +19 -19
  85. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.TallBuilding.rb +18 -18
  86. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Warehouse.rb +6 -6
  87. data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +957 -957
  88. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirConditionerVariableRefrigerantFlow.rb +1 -1
  89. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirTerminalSingleDuctVAVReheat.rb +1 -1
  90. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWaterToAirHeatPumpEquationFit.rb +84 -16
  91. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingDXSingleSpeed.rb +1 -1
  92. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingGas.rb +1 -1
  93. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWaterToAirHeatPumpEquationFit.rb +61 -10
  94. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ControllerWaterCoil.rb +1 -1
  95. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoolingTower.rb +1 -1
  96. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +1 -1
  97. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanConstantVolume.rb +1 -1
  98. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanOnOff.rb +1 -1
  99. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanVariableVolume.rb +1 -1
  100. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanZoneExhaust.rb +1 -1
  101. data/lib/openstudio-standards/prototypes/common/objects/Prototype.HeatExchangerAirToAirSensibleAndLatent.rb +2 -2
  102. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.exterior_lights.rb +4 -4
  103. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.hvac.rb +4 -4
  104. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +43 -30
  105. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.swh.rb +1 -1
  106. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +18 -11
  107. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
  108. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +774 -117
  109. data/lib/openstudio-standards/prototypes/common/objects/Prototype.radiant_system_controls.rb +340 -481
  110. data/lib/openstudio-standards/prototypes/common/objects/Prototype.refrigeration.rb +3 -3
  111. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +3 -3
  112. data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +22 -22
  113. data/lib/openstudio-standards/prototypes/deer/deer.Model.rb +1 -1
  114. data/lib/openstudio-standards/qaqc/calibration.rb +131 -0
  115. data/lib/openstudio-standards/qaqc/create_results.rb +983 -0
  116. data/lib/openstudio-standards/qaqc/envelope.rb +399 -0
  117. data/lib/openstudio-standards/qaqc/eui.rb +213 -0
  118. data/lib/openstudio-standards/qaqc/hvac.rb +1943 -0
  119. data/lib/openstudio-standards/qaqc/internal_loads.rb +568 -0
  120. data/lib/openstudio-standards/qaqc/reporting.rb +141 -0
  121. data/lib/openstudio-standards/qaqc/schedules.rb +129 -0
  122. data/lib/openstudio-standards/qaqc/service_water_heating.rb +273 -0
  123. data/lib/openstudio-standards/qaqc/weather_files.rb +497 -0
  124. data/lib/openstudio-standards/qaqc/zone_conditions.rb +278 -0
  125. data/lib/openstudio-standards/schedules/create.rb +364 -0
  126. data/lib/openstudio-standards/schedules/information.rb +169 -0
  127. data/lib/openstudio-standards/schedules/modify.rb +445 -0
  128. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +110 -71
  129. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +3 -3
  130. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctVAVReheat.rb +4 -4
  131. data/lib/openstudio-standards/standards/Standards.BoilerHotWater.rb +2 -1
  132. data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +16 -10
  133. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +4 -4
  134. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXTwoSpeed.rb +1 -1
  135. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +1 -1
  136. data/lib/openstudio-standards/standards/Standards.CoilDX.rb +4 -4
  137. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXMultiSpeed.rb +1 -1
  138. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +5 -5
  139. data/lib/openstudio-standards/standards/Standards.CoilHeatingGas.rb +1 -1
  140. data/lib/openstudio-standards/standards/Standards.CoilHeatingGasMultiStage.rb +1 -1
  141. data/lib/openstudio-standards/standards/Standards.CoilHeatingWaterToAirHeatPumpEquationFit.rb +1 -1
  142. data/lib/openstudio-standards/standards/Standards.Construction.rb +17 -18
  143. data/lib/openstudio-standards/standards/Standards.CoolingTower.rb +6 -6
  144. data/lib/openstudio-standards/standards/Standards.CoolingTowerSingleSpeed.rb +1 -1
  145. data/lib/openstudio-standards/standards/Standards.CoolingTowerTwoSpeed.rb +1 -1
  146. data/lib/openstudio-standards/standards/Standards.CoolingTowerVariableSpeed.rb +1 -1
  147. data/lib/openstudio-standards/standards/Standards.Fan.rb +6 -12
  148. data/lib/openstudio-standards/standards/Standards.FanVariableVolume.rb +2 -2
  149. data/lib/openstudio-standards/standards/Standards.FluidCooler.rb +1 -1
  150. data/lib/openstudio-standards/standards/Standards.HeaderedPumpsVariableSpeed.rb +1 -1
  151. data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +3 -3
  152. data/lib/openstudio-standards/standards/Standards.Model.rb +411 -261
  153. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +2 -2
  154. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +94 -29
  155. data/lib/openstudio-standards/standards/Standards.Pump.rb +2 -2
  156. data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +2 -2
  157. data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +14 -14
  158. data/lib/openstudio-standards/standards/Standards.Space.rb +37 -30
  159. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +38 -29
  160. data/lib/openstudio-standards/standards/Standards.SubSurface.rb +7 -7
  161. data/lib/openstudio-standards/standards/Standards.Surface.rb +13 -13
  162. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +109 -66
  163. data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +11 -4
  164. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +6 -6
  165. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb +1 -1
  166. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PlantLoop.rb +1 -1
  167. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Space.rb +1 -1
  168. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.Space.rb +1 -1
  169. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirLoopHVAC.rb +4 -4
  170. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
  171. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Space.rb +4 -4
  172. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirLoopHVAC.rb +4 -4
  173. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
  174. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.CoolingTowerVariableSpeed.rb +1 -1
  175. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +5 -21
  176. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Space.rb +4 -4
  177. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.WaterHeaterMixed.rb +1 -1
  178. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.ZoneHVACComponent.rb +1 -1
  179. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirLoopHVAC.rb +36 -4
  180. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
  181. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.CoolingTowerVariableSpeed.rb +1 -1
  182. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Space.rb +4 -4
  183. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.ZoneHVACComponent.rb +1 -1
  184. 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
  185. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +53 -10
  186. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
  187. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerVariableSpeed.rb +1 -1
  188. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +6 -6
  189. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb +2 -2
  190. 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
  191. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.curves.json +211 -211
  192. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.economizers.json +14 -14
  193. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirLoopHVAC.rb +4 -4
  194. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.rb +1 -1
  195. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.PlantLoop.rb +1 -1
  196. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.economizers.json +14 -14
  197. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirLoopHVAC.rb +4 -4
  198. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.rb +1 -1
  199. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.PlantLoop.rb +1 -1
  200. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +6 -6
  201. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
  202. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.CoolingTowerVariableSpeed.rb +1 -1
  203. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.PlantLoop.rb +1 -1
  204. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.Space.rb +4 -4
  205. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirLoopHVAC.rb +6 -6
  206. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
  207. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.CoolingTowerVariableSpeed.rb +1 -1
  208. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.PlantLoop.rb +1 -1
  209. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.Space.rb +4 -4
  210. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +22 -28
  211. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +1 -1
  212. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +2 -2
  213. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +1 -74
  214. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +7 -59
  215. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +1 -1
  216. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +1 -1
  217. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +1 -1
  218. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +1 -1
  219. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +1 -21
  220. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.DesignSpecificationOutdoorAir.rb +101 -0
  221. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +1 -1
  222. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +1 -1
  223. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +1 -1
  224. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +1 -1
  225. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +643 -526
  226. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +8 -2
  227. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +17 -77
  228. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +74 -16
  229. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +96 -44
  230. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +6 -6
  231. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +18 -6
  232. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +1 -1
  233. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +328 -74
  234. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +0 -118
  235. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +2 -1
  236. 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
  237. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_outdoor_air.md +35 -0
  238. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +1 -1
  239. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData.rb +228 -0
  240. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_enums.rb +131 -0
  241. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -1
  242. data/lib/openstudio-standards/standards/cbes/cbes.AirLoopHVAC.rb +5 -5
  243. data/lib/openstudio-standards/standards/cbes/cbes.Model.rb +1 -1
  244. data/lib/openstudio-standards/standards/cbes/cbes.PlantLoop.rb +1 -1
  245. data/lib/openstudio-standards/standards/cbes/cbes.Space.rb +1 -1
  246. data/lib/openstudio-standards/standards/cbes/cbes_t24_2005/cbes_t24_2005.Space.rb +1 -1
  247. data/lib/openstudio-standards/standards/cbes/cbes_t24_2008/cbes_t24_2008.Space.rb +1 -1
  248. data/lib/openstudio-standards/standards/deer/deer.AirLoopHVAC.rb +109 -27
  249. data/lib/openstudio-standards/standards/deer/deer.Space.rb +1 -1
  250. data/lib/openstudio-standards/standards/deer/deer_1985/data/deer_1985.economizers.json +246 -4
  251. data/lib/openstudio-standards/standards/deer/deer_1996/data/deer_1996.economizers.json +246 -4
  252. data/lib/openstudio-standards/standards/deer/deer_2003/data/deer_2003.economizers.json +246 -4
  253. data/lib/openstudio-standards/standards/deer/deer_2003/deer_2003.ThermalZone.rb +18 -18
  254. data/lib/openstudio-standards/standards/deer/deer_2007/data/deer_2007.economizers.json +246 -4
  255. data/lib/openstudio-standards/standards/deer/deer_2007/deer_2007.ThermalZone.rb +18 -18
  256. data/lib/openstudio-standards/standards/deer/deer_2011/data/deer_2011.economizers.json +246 -4
  257. data/lib/openstudio-standards/standards/deer/deer_2011/deer_2011.ThermalZone.rb +18 -18
  258. data/lib/openstudio-standards/standards/deer/deer_2014/data/deer_2014.economizers.json +248 -6
  259. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.Space.rb +3 -3
  260. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.ThermalZone.rb +18 -18
  261. data/lib/openstudio-standards/standards/deer/deer_2015/data/deer_2015.economizers.json +248 -6
  262. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.Space.rb +3 -3
  263. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.ThermalZone.rb +18 -18
  264. data/lib/openstudio-standards/standards/deer/deer_2017/data/deer_2017.economizers.json +248 -6
  265. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.Space.rb +3 -3
  266. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.ThermalZone.rb +18 -18
  267. data/lib/openstudio-standards/standards/deer/deer_2020/data/deer_2020.economizers.json +248 -6
  268. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.AirLoopHVAC.rb +18 -5
  269. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.FanVariableVolume.rb +1 -1
  270. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.Space.rb +3 -3
  271. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.ThermalZone.rb +18 -18
  272. data/lib/openstudio-standards/standards/deer/deer_2025/data/deer_2025.economizers.json +248 -6
  273. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.AirLoopHVAC.rb +3 -3
  274. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.FanVariableVolume.rb +1 -1
  275. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.Space.rb +3 -3
  276. data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.economizers.json +248 -6
  277. data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.heat_pumps.json +2 -2
  278. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.AirLoopHVAC.rb +3 -3
  279. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.FanVariableVolume.rb +1 -1
  280. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.Space.rb +3 -3
  281. data/lib/openstudio-standards/standards/deer/deer_2035/data/deer_2035.economizers.json +248 -6
  282. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.AirLoopHVAC.rb +3 -3
  283. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.FanVariableVolume.rb +1 -1
  284. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.Space.rb +3 -3
  285. data/lib/openstudio-standards/standards/deer/deer_2040/data/deer_2040.economizers.json +248 -6
  286. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.AirLoopHVAC.rb +3 -3
  287. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.FanVariableVolume.rb +1 -1
  288. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.Space.rb +3 -3
  289. data/lib/openstudio-standards/standards/deer/deer_2045/data/deer_2045.economizers.json +260 -0
  290. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.AirLoopHVAC.rb +3 -3
  291. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.FanVariableVolume.rb +1 -1
  292. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.Space.rb +3 -3
  293. data/lib/openstudio-standards/standards/deer/deer_2050/data/deer_2050.economizers.json +248 -6
  294. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.AirLoopHVAC.rb +3 -3
  295. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.FanVariableVolume.rb +1 -1
  296. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.Space.rb +3 -3
  297. data/lib/openstudio-standards/standards/deer/deer_2055/data/deer_2055.economizers.json +248 -6
  298. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.AirLoopHVAC.rb +3 -3
  299. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.FanVariableVolume.rb +1 -1
  300. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.Space.rb +3 -3
  301. data/lib/openstudio-standards/standards/deer/deer_2060/data/deer_2060.economizers.json +248 -6
  302. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.AirLoopHVAC.rb +3 -3
  303. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.FanVariableVolume.rb +1 -1
  304. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.Space.rb +3 -3
  305. data/lib/openstudio-standards/standards/deer/deer_2065/data/deer_2065.economizers.json +248 -6
  306. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.AirLoopHVAC.rb +3 -3
  307. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.FanVariableVolume.rb +1 -1
  308. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.Space.rb +3 -3
  309. data/lib/openstudio-standards/standards/deer/deer_2070/data/deer_2070.economizers.json +248 -6
  310. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.AirLoopHVAC.rb +3 -3
  311. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.FanVariableVolume.rb +1 -1
  312. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.Space.rb +3 -3
  313. data/lib/openstudio-standards/standards/deer/deer_2075/data/deer_2075.economizers.json +248 -6
  314. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.AirLoopHVAC.rb +3 -3
  315. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.FanVariableVolume.rb +1 -1
  316. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.Space.rb +3 -3
  317. data/lib/openstudio-standards/standards/deer/deer_pre_1975/data/deer_pre_1975.economizers.json +246 -4
  318. data/lib/openstudio-standards/standards/necb/BTAP1980TO2010/data/space_types.json +447 -223
  319. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/building_envelope.rb +1 -1
  320. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/data/space_types.json +447 -223
  321. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_systems.rb +5 -2
  322. data/lib/openstudio-standards/standards/necb/ECMS/data/chiller_types.json +25 -0
  323. data/lib/openstudio-standards/standards/necb/ECMS/data/chillers.json +44 -0
  324. data/lib/openstudio-standards/standards/necb/ECMS/data/curves.json +225 -0
  325. data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +2 -2
  326. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +193 -73
  327. data/lib/openstudio-standards/standards/necb/ECMS/pv_ground.rb +1 -1
  328. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +10 -4
  329. data/lib/openstudio-standards/standards/necb/NECB2011/beps_compliance_path.rb +7 -7
  330. data/lib/openstudio-standards/standards/necb/NECB2011/building_envelope.rb +4 -5
  331. data/lib/openstudio-standards/standards/necb/NECB2011/data/chiller_types.json +32 -0
  332. data/lib/openstudio-standards/standards/necb/NECB2011/data/chillers.json +1 -1
  333. data/lib/openstudio-standards/standards/necb/NECB2011/data/constants.json +36 -0
  334. data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +7 -7
  335. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernEducation.osm +47587 -0
  336. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernHealthCare.osm +49764 -0
  337. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Warehouse.osm +283 -297
  338. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_type_unit_definitions.txt +2 -1
  339. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +447 -223
  340. data/lib/openstudio-standards/standards/necb/NECB2011/data/standards_data.rb +3 -3
  341. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_multi_speed.rb +1 -1
  342. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +49 -27
  343. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +400 -202
  344. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +4 -4
  345. data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +637 -318
  346. data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +18 -1
  347. data/lib/openstudio-standards/standards/necb/NECB2015/necb_2015.rb +3 -3
  348. data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +637 -318
  349. data/lib/openstudio-standards/standards/necb/NECB2017/hvac_systems.rb +1 -1
  350. data/lib/openstudio-standards/standards/necb/NECB2017/necb_2017.rb +3 -3
  351. data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +1 -1
  352. data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +615 -307
  353. data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +4 -4
  354. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +10 -5
  355. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +1 -1
  356. data/lib/openstudio-standards/utilities/assertion.rb +128 -0
  357. data/lib/openstudio-standards/utilities/logging.rb +2 -3
  358. data/lib/openstudio-standards/utilities/object_info.rb +39 -18
  359. data/lib/openstudio-standards/utilities/schedule_translator.rb +8 -6
  360. data/lib/openstudio-standards/utilities/simulation.rb +24 -11
  361. data/lib/openstudio-standards/utilities/sqlfile.rb +10 -5
  362. data/lib/openstudio-standards/version.rb +1 -1
  363. data/lib/openstudio-standards/weather/Weather.Model.rb +8 -9
  364. data/lib/openstudio-standards/weather/Weather.stat_file.rb +3 -3
  365. data/lib/openstudio-standards/weather/information.rb +35 -0
  366. data/lib/openstudio-standards.rb +69 -5
  367. metadata +54 -18
  368. data/License.txt +0 -65
  369. data/data/standards/OpenStudio_Standards-deer-ALL-comstock(space_types).xlsx +0 -0
  370. data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVAC.rb +0 -59
  371. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingWater.rb +0 -13
  372. data/lib/openstudio-standards/hvac_sizing/Siz.HVACComponent.rb +0 -36
  373. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +0 -898
  374. data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +0 -126
  375. data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +0 -356
  376. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.Model.rb +0 -35
  377. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +0 -110
  378. 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)