openstudio-standards 0.4.0 → 0.5.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. checksums.yaml +4 -4
  2. data/data/inventory/thermal_bridging.csv +90 -0
  3. data/data/standards/OpenStudio_Standards-deer-comstock.xlsx +0 -0
  4. data/data/standards/manage_OpenStudio_Standards.rb +1 -1
  5. data/data/standards/test_performance_expected_dd_results.csv +2014 -1891
  6. data/lib/openstudio-standards/btap/analysis.rb +8 -8
  7. data/lib/openstudio-standards/btap/bridging.rb +664 -645
  8. data/lib/openstudio-standards/btap/btap.model.rb +14 -14
  9. data/lib/openstudio-standards/btap/btap.rb +7 -7
  10. data/lib/openstudio-standards/btap/btap_result.rb +1 -1
  11. data/lib/openstudio-standards/btap/economics.rb +23 -23
  12. data/lib/openstudio-standards/btap/envelope.rb +8 -8
  13. data/lib/openstudio-standards/btap/equest.rb +1 -1
  14. data/lib/openstudio-standards/btap/geometry.rb +2 -2
  15. data/lib/openstudio-standards/btap/mpc.rb +7 -7
  16. data/lib/openstudio-standards/btap/schedules.rb +1 -1
  17. data/lib/openstudio-standards/btap/simmanager.rb +4 -4
  18. data/lib/openstudio-standards/btap/spaceloads.rb +26 -26
  19. data/lib/openstudio-standards/btap/utilities.rb +6 -6
  20. data/lib/openstudio-standards/btap/vintagizer.rb +1 -1
  21. data/lib/openstudio-standards/constructions/information.rb +83 -0
  22. data/lib/openstudio-standards/constructions/materials/modify.rb +72 -0
  23. data/lib/openstudio-standards/constructions/modify.rb +80 -0
  24. data/lib/openstudio-standards/create_typical/create_typical.rb +983 -0
  25. data/lib/openstudio-standards/create_typical/enumerations.rb +484 -0
  26. data/lib/openstudio-standards/create_typical/space_type_blend.rb +791 -0
  27. data/lib/openstudio-standards/create_typical/space_type_ratios.rb +494 -0
  28. data/lib/openstudio-standards/daylighting/space.rb +47 -0
  29. data/lib/openstudio-standards/geometry/create.rb +801 -0
  30. data/lib/openstudio-standards/geometry/create_bar.rb +2171 -0
  31. data/lib/openstudio-standards/geometry/information.rb +462 -0
  32. data/lib/openstudio-standards/geometry/modify.rb +48 -0
  33. data/lib/openstudio-standards/hvac/air_loop/information.rb +79 -0
  34. data/lib/openstudio-standards/hvac/cbecs_hvac.rb +616 -0
  35. data/lib/openstudio-standards/hvac/setpoint_managers/information.rb +91 -0
  36. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirTerminalSingleDuctVAVReheat.rb +1 -1
  37. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.AirTerminalSingleDuctVAVReheat.rb +1 -1
  38. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
  39. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Model.rb +1 -1
  40. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
  41. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +2 -2
  42. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.hvac_systems.rb +1 -1
  43. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
  44. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +4 -36
  45. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.hvac_systems.rb +1 -1
  46. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
  47. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +4 -36
  48. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +3 -3
  49. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb +1 -1
  50. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirTerminalSingleDuctVAVReheat.rb +1 -1
  51. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.elevators.rb +1 -1
  52. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirTerminalSingleDuctVAVReheat.rb +1 -1
  53. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.CoilHeatingGas.rb +1 -1
  54. data/lib/openstudio-standards/prototypes/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.elevators.rb +1 -1
  55. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
  56. data/lib/openstudio-standards/prototypes/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
  57. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +7 -7
  58. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Courthouse.rb +8 -8
  59. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.FullServiceRestaurant.rb +14 -14
  60. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.HighRiseApartment.rb +9 -9
  61. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Hospital.rb +16 -16
  62. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +7 -7
  63. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterHighITE.rb +8 -8
  64. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeDataCenterLowITE.rb +8 -8
  65. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeHotel.rb +11 -11
  66. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOffice.rb +7 -7
  67. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.LargeOfficeDetailed.rb +9 -9
  68. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOffice.rb +8 -8
  69. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MediumOfficeDetailed.rb +11 -11
  70. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.MidriseApartment.rb +9 -9
  71. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Outpatient.rb +19 -19
  72. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.PrimarySchool.rb +10 -10
  73. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.QuickServiceRestaurant.rb +13 -13
  74. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStandalone.rb +6 -6
  75. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.RetailStripmall.rb +6 -6
  76. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SecondarySchool.rb +9 -9
  77. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterHighITE.rb +8 -8
  78. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallDataCenterLowITE.rb +8 -8
  79. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallHotel.rb +8 -8
  80. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOffice.rb +8 -8
  81. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SmallOfficeDetailed.rb +11 -11
  82. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperMarket.rb +10 -10
  83. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperTallBuilding.rb +19 -19
  84. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.TallBuilding.rb +18 -18
  85. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Warehouse.rb +6 -6
  86. data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +957 -957
  87. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirConditionerVariableRefrigerantFlow.rb +1 -1
  88. data/lib/openstudio-standards/prototypes/common/objects/Prototype.AirTerminalSingleDuctVAVReheat.rb +1 -1
  89. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWaterToAirHeatPumpEquationFit.rb +84 -16
  90. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingDXSingleSpeed.rb +1 -1
  91. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingGas.rb +1 -1
  92. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWaterToAirHeatPumpEquationFit.rb +61 -10
  93. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ControllerWaterCoil.rb +1 -1
  94. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoolingTower.rb +1 -1
  95. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +1 -1
  96. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanConstantVolume.rb +1 -1
  97. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanOnOff.rb +1 -1
  98. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanVariableVolume.rb +1 -1
  99. data/lib/openstudio-standards/prototypes/common/objects/Prototype.FanZoneExhaust.rb +1 -1
  100. data/lib/openstudio-standards/prototypes/common/objects/Prototype.HeatExchangerAirToAirSensibleAndLatent.rb +2 -2
  101. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.exterior_lights.rb +4 -4
  102. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.hvac.rb +4 -4
  103. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +43 -30
  104. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.swh.rb +1 -1
  105. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +18 -11
  106. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
  107. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +774 -117
  108. data/lib/openstudio-standards/prototypes/common/objects/Prototype.radiant_system_controls.rb +340 -481
  109. data/lib/openstudio-standards/prototypes/common/objects/Prototype.refrigeration.rb +3 -3
  110. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +3 -3
  111. data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +22 -22
  112. data/lib/openstudio-standards/prototypes/deer/deer.Model.rb +1 -1
  113. data/lib/openstudio-standards/qaqc/calibration.rb +131 -0
  114. data/lib/openstudio-standards/qaqc/create_results.rb +983 -0
  115. data/lib/openstudio-standards/qaqc/envelope.rb +399 -0
  116. data/lib/openstudio-standards/qaqc/eui.rb +213 -0
  117. data/lib/openstudio-standards/qaqc/hvac.rb +1943 -0
  118. data/lib/openstudio-standards/qaqc/internal_loads.rb +568 -0
  119. data/lib/openstudio-standards/qaqc/reporting.rb +141 -0
  120. data/lib/openstudio-standards/qaqc/schedules.rb +129 -0
  121. data/lib/openstudio-standards/qaqc/service_water_heating.rb +273 -0
  122. data/lib/openstudio-standards/qaqc/weather_files.rb +497 -0
  123. data/lib/openstudio-standards/qaqc/zone_conditions.rb +278 -0
  124. data/lib/openstudio-standards/schedules/create.rb +364 -0
  125. data/lib/openstudio-standards/schedules/information.rb +169 -0
  126. data/lib/openstudio-standards/schedules/modify.rb +445 -0
  127. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +110 -71
  128. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +3 -3
  129. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctVAVReheat.rb +4 -4
  130. data/lib/openstudio-standards/standards/Standards.BoilerHotWater.rb +2 -1
  131. data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +16 -10
  132. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +4 -4
  133. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXTwoSpeed.rb +1 -1
  134. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +1 -1
  135. data/lib/openstudio-standards/standards/Standards.CoilDX.rb +4 -4
  136. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXMultiSpeed.rb +1 -1
  137. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +5 -5
  138. data/lib/openstudio-standards/standards/Standards.CoilHeatingGas.rb +1 -1
  139. data/lib/openstudio-standards/standards/Standards.CoilHeatingGasMultiStage.rb +1 -1
  140. data/lib/openstudio-standards/standards/Standards.CoilHeatingWaterToAirHeatPumpEquationFit.rb +1 -1
  141. data/lib/openstudio-standards/standards/Standards.Construction.rb +17 -18
  142. data/lib/openstudio-standards/standards/Standards.CoolingTower.rb +6 -6
  143. data/lib/openstudio-standards/standards/Standards.CoolingTowerSingleSpeed.rb +1 -1
  144. data/lib/openstudio-standards/standards/Standards.CoolingTowerTwoSpeed.rb +1 -1
  145. data/lib/openstudio-standards/standards/Standards.CoolingTowerVariableSpeed.rb +1 -1
  146. data/lib/openstudio-standards/standards/Standards.Fan.rb +6 -12
  147. data/lib/openstudio-standards/standards/Standards.FanVariableVolume.rb +2 -2
  148. data/lib/openstudio-standards/standards/Standards.FluidCooler.rb +1 -1
  149. data/lib/openstudio-standards/standards/Standards.HeaderedPumpsVariableSpeed.rb +1 -1
  150. data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +3 -3
  151. data/lib/openstudio-standards/standards/Standards.Model.rb +411 -261
  152. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +2 -2
  153. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +94 -29
  154. data/lib/openstudio-standards/standards/Standards.Pump.rb +2 -2
  155. data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +2 -2
  156. data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +14 -14
  157. data/lib/openstudio-standards/standards/Standards.Space.rb +37 -30
  158. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +38 -29
  159. data/lib/openstudio-standards/standards/Standards.SubSurface.rb +7 -7
  160. data/lib/openstudio-standards/standards/Standards.Surface.rb +13 -13
  161. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +109 -66
  162. data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +11 -4
  163. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +6 -6
  164. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.AirLoopHVAC.rb +1 -1
  165. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.PlantLoop.rb +1 -1
  166. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Space.rb +1 -1
  167. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/ashrae_90_1_2007.Space.rb +1 -1
  168. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirLoopHVAC.rb +4 -4
  169. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.AirTerminalSingleDuctVAVReheat.rb +1 -1
  170. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/ashrae_90_1_2010.Space.rb +4 -4
  171. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirLoopHVAC.rb +4 -4
  172. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.AirTerminalSingleDuctVAVReheat.rb +1 -1
  173. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.CoolingTowerVariableSpeed.rb +1 -1
  174. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Model.rb +5 -21
  175. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.Space.rb +4 -4
  176. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.WaterHeaterMixed.rb +1 -1
  177. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/ashrae_90_1_2013.ZoneHVACComponent.rb +1 -1
  178. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirLoopHVAC.rb +36 -4
  179. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.AirTerminalSingleDuctVAVReheat.rb +1 -1
  180. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.CoolingTowerVariableSpeed.rb +1 -1
  181. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Space.rb +4 -4
  182. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.ZoneHVACComponent.rb +1 -1
  183. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/comstock_ashrae_90_1_2016.AirLoopHVAC.rb +26 -0
  184. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +53 -10
  185. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirTerminalSingleDuctVAVReheat.rb +1 -1
  186. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.CoolingTowerVariableSpeed.rb +1 -1
  187. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Space.rb +6 -6
  188. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb +2 -2
  189. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/comstock_ashrae_90_1_2019.AirLoopHVAC.rb +26 -0
  190. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.curves.json +211 -211
  191. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.economizers.json +14 -14
  192. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirLoopHVAC.rb +4 -4
  193. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.Model.rb +1 -1
  194. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.PlantLoop.rb +1 -1
  195. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.economizers.json +14 -14
  196. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirLoopHVAC.rb +4 -4
  197. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.Model.rb +1 -1
  198. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.PlantLoop.rb +1 -1
  199. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +6 -6
  200. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirTerminalSingleDuctVAVReheat.rb +1 -1
  201. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.CoolingTowerVariableSpeed.rb +1 -1
  202. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.PlantLoop.rb +1 -1
  203. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.Space.rb +4 -4
  204. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirLoopHVAC.rb +6 -6
  205. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.AirTerminalSingleDuctVAVReheat.rb +1 -1
  206. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.CoolingTowerVariableSpeed.rb +1 -1
  207. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.PlantLoop.rb +1 -1
  208. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/ze_aedg_multifamily.Space.rb +4 -4
  209. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +22 -28
  210. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +1 -1
  211. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +2 -2
  212. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +1 -74
  213. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +7 -59
  214. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +1 -1
  215. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +1 -1
  216. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +1 -1
  217. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +1 -1
  218. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +1 -21
  219. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.DesignSpecificationOutdoorAir.rb +101 -0
  220. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +1 -1
  221. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +1 -1
  222. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +1 -1
  223. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +1 -1
  224. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +643 -526
  225. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +8 -2
  226. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +17 -77
  227. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +74 -16
  228. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +96 -44
  229. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +6 -6
  230. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +18 -6
  231. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +1 -1
  232. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +328 -74
  233. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +0 -118
  234. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +2 -1
  235. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_rejection.json +1 -1
  236. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_outdoor_air.md +35 -0
  237. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +1 -1
  238. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData.rb +228 -0
  239. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_enums.rb +131 -0
  240. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -1
  241. data/lib/openstudio-standards/standards/cbes/cbes.AirLoopHVAC.rb +5 -5
  242. data/lib/openstudio-standards/standards/cbes/cbes.Model.rb +1 -1
  243. data/lib/openstudio-standards/standards/cbes/cbes.PlantLoop.rb +1 -1
  244. data/lib/openstudio-standards/standards/cbes/cbes.Space.rb +1 -1
  245. data/lib/openstudio-standards/standards/cbes/cbes_t24_2005/cbes_t24_2005.Space.rb +1 -1
  246. data/lib/openstudio-standards/standards/cbes/cbes_t24_2008/cbes_t24_2008.Space.rb +1 -1
  247. data/lib/openstudio-standards/standards/deer/deer.AirLoopHVAC.rb +109 -27
  248. data/lib/openstudio-standards/standards/deer/deer.Space.rb +1 -1
  249. data/lib/openstudio-standards/standards/deer/deer_1985/data/deer_1985.economizers.json +246 -4
  250. data/lib/openstudio-standards/standards/deer/deer_1996/data/deer_1996.economizers.json +246 -4
  251. data/lib/openstudio-standards/standards/deer/deer_2003/data/deer_2003.economizers.json +246 -4
  252. data/lib/openstudio-standards/standards/deer/deer_2003/deer_2003.ThermalZone.rb +18 -18
  253. data/lib/openstudio-standards/standards/deer/deer_2007/data/deer_2007.economizers.json +246 -4
  254. data/lib/openstudio-standards/standards/deer/deer_2007/deer_2007.ThermalZone.rb +18 -18
  255. data/lib/openstudio-standards/standards/deer/deer_2011/data/deer_2011.economizers.json +246 -4
  256. data/lib/openstudio-standards/standards/deer/deer_2011/deer_2011.ThermalZone.rb +18 -18
  257. data/lib/openstudio-standards/standards/deer/deer_2014/data/deer_2014.economizers.json +248 -6
  258. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.Space.rb +3 -3
  259. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.ThermalZone.rb +18 -18
  260. data/lib/openstudio-standards/standards/deer/deer_2015/data/deer_2015.economizers.json +248 -6
  261. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.Space.rb +3 -3
  262. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.ThermalZone.rb +18 -18
  263. data/lib/openstudio-standards/standards/deer/deer_2017/data/deer_2017.economizers.json +248 -6
  264. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.Space.rb +3 -3
  265. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.ThermalZone.rb +18 -18
  266. data/lib/openstudio-standards/standards/deer/deer_2020/data/deer_2020.economizers.json +248 -6
  267. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.AirLoopHVAC.rb +18 -5
  268. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.FanVariableVolume.rb +1 -1
  269. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.Space.rb +3 -3
  270. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.ThermalZone.rb +18 -18
  271. data/lib/openstudio-standards/standards/deer/deer_2025/data/deer_2025.economizers.json +248 -6
  272. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.AirLoopHVAC.rb +3 -3
  273. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.FanVariableVolume.rb +1 -1
  274. data/lib/openstudio-standards/standards/deer/deer_2025/deer_2025.Space.rb +3 -3
  275. data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.economizers.json +248 -6
  276. data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.heat_pumps.json +2 -2
  277. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.AirLoopHVAC.rb +3 -3
  278. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.FanVariableVolume.rb +1 -1
  279. data/lib/openstudio-standards/standards/deer/deer_2030/deer_2030.Space.rb +3 -3
  280. data/lib/openstudio-standards/standards/deer/deer_2035/data/deer_2035.economizers.json +248 -6
  281. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.AirLoopHVAC.rb +3 -3
  282. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.FanVariableVolume.rb +1 -1
  283. data/lib/openstudio-standards/standards/deer/deer_2035/deer_2035.Space.rb +3 -3
  284. data/lib/openstudio-standards/standards/deer/deer_2040/data/deer_2040.economizers.json +248 -6
  285. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.AirLoopHVAC.rb +3 -3
  286. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.FanVariableVolume.rb +1 -1
  287. data/lib/openstudio-standards/standards/deer/deer_2040/deer_2040.Space.rb +3 -3
  288. data/lib/openstudio-standards/standards/deer/deer_2045/data/deer_2045.economizers.json +260 -0
  289. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.AirLoopHVAC.rb +3 -3
  290. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.FanVariableVolume.rb +1 -1
  291. data/lib/openstudio-standards/standards/deer/deer_2045/deer_2045.Space.rb +3 -3
  292. data/lib/openstudio-standards/standards/deer/deer_2050/data/deer_2050.economizers.json +248 -6
  293. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.AirLoopHVAC.rb +3 -3
  294. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.FanVariableVolume.rb +1 -1
  295. data/lib/openstudio-standards/standards/deer/deer_2050/deer_2050.Space.rb +3 -3
  296. data/lib/openstudio-standards/standards/deer/deer_2055/data/deer_2055.economizers.json +248 -6
  297. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.AirLoopHVAC.rb +3 -3
  298. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.FanVariableVolume.rb +1 -1
  299. data/lib/openstudio-standards/standards/deer/deer_2055/deer_2055.Space.rb +3 -3
  300. data/lib/openstudio-standards/standards/deer/deer_2060/data/deer_2060.economizers.json +248 -6
  301. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.AirLoopHVAC.rb +3 -3
  302. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.FanVariableVolume.rb +1 -1
  303. data/lib/openstudio-standards/standards/deer/deer_2060/deer_2060.Space.rb +3 -3
  304. data/lib/openstudio-standards/standards/deer/deer_2065/data/deer_2065.economizers.json +248 -6
  305. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.AirLoopHVAC.rb +3 -3
  306. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.FanVariableVolume.rb +1 -1
  307. data/lib/openstudio-standards/standards/deer/deer_2065/deer_2065.Space.rb +3 -3
  308. data/lib/openstudio-standards/standards/deer/deer_2070/data/deer_2070.economizers.json +248 -6
  309. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.AirLoopHVAC.rb +3 -3
  310. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.FanVariableVolume.rb +1 -1
  311. data/lib/openstudio-standards/standards/deer/deer_2070/deer_2070.Space.rb +3 -3
  312. data/lib/openstudio-standards/standards/deer/deer_2075/data/deer_2075.economizers.json +248 -6
  313. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.AirLoopHVAC.rb +3 -3
  314. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.FanVariableVolume.rb +1 -1
  315. data/lib/openstudio-standards/standards/deer/deer_2075/deer_2075.Space.rb +3 -3
  316. data/lib/openstudio-standards/standards/deer/deer_pre_1975/data/deer_pre_1975.economizers.json +246 -4
  317. data/lib/openstudio-standards/standards/necb/BTAP1980TO2010/data/space_types.json +447 -223
  318. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/building_envelope.rb +1 -1
  319. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/data/space_types.json +447 -223
  320. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_systems.rb +5 -2
  321. data/lib/openstudio-standards/standards/necb/ECMS/data/chiller_types.json +25 -0
  322. data/lib/openstudio-standards/standards/necb/ECMS/data/chillers.json +44 -0
  323. data/lib/openstudio-standards/standards/necb/ECMS/data/curves.json +225 -0
  324. data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +2 -2
  325. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +193 -73
  326. data/lib/openstudio-standards/standards/necb/ECMS/pv_ground.rb +1 -1
  327. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +10 -4
  328. data/lib/openstudio-standards/standards/necb/NECB2011/beps_compliance_path.rb +7 -7
  329. data/lib/openstudio-standards/standards/necb/NECB2011/building_envelope.rb +4 -5
  330. data/lib/openstudio-standards/standards/necb/NECB2011/data/chiller_types.json +32 -0
  331. data/lib/openstudio-standards/standards/necb/NECB2011/data/chillers.json +1 -1
  332. data/lib/openstudio-standards/standards/necb/NECB2011/data/constants.json +36 -0
  333. data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +7 -7
  334. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernEducation.osm +47587 -0
  335. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernHealthCare.osm +49764 -0
  336. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Warehouse.osm +283 -297
  337. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_type_unit_definitions.txt +2 -1
  338. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +447 -223
  339. data/lib/openstudio-standards/standards/necb/NECB2011/data/standards_data.rb +3 -3
  340. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_multi_speed.rb +1 -1
  341. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +49 -27
  342. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +400 -202
  343. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +4 -4
  344. data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +637 -318
  345. data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +18 -1
  346. data/lib/openstudio-standards/standards/necb/NECB2015/necb_2015.rb +3 -3
  347. data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +637 -318
  348. data/lib/openstudio-standards/standards/necb/NECB2017/hvac_systems.rb +1 -1
  349. data/lib/openstudio-standards/standards/necb/NECB2017/necb_2017.rb +3 -3
  350. data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +1 -1
  351. data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +615 -307
  352. data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +4 -4
  353. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +10 -5
  354. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +1 -1
  355. data/lib/openstudio-standards/utilities/assertion.rb +128 -0
  356. data/lib/openstudio-standards/utilities/logging.rb +2 -3
  357. data/lib/openstudio-standards/utilities/object_info.rb +39 -18
  358. data/lib/openstudio-standards/utilities/schedule_translator.rb +8 -6
  359. data/lib/openstudio-standards/utilities/simulation.rb +24 -11
  360. data/lib/openstudio-standards/utilities/sqlfile.rb +10 -5
  361. data/lib/openstudio-standards/version.rb +1 -1
  362. data/lib/openstudio-standards/weather/Weather.Model.rb +8 -9
  363. data/lib/openstudio-standards/weather/Weather.stat_file.rb +3 -3
  364. data/lib/openstudio-standards/weather/information.rb +35 -0
  365. data/lib/openstudio-standards.rb +69 -5
  366. metadata +52 -16
  367. data/data/standards/OpenStudio_Standards-deer-ALL-comstock(space_types).xlsx +0 -0
  368. data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVAC.rb +0 -59
  369. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingWater.rb +0 -13
  370. data/lib/openstudio-standards/hvac_sizing/Siz.HVACComponent.rb +0 -36
  371. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +0 -898
  372. data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +0 -126
  373. data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +0 -356
  374. data/lib/openstudio-standards/prototypes/ashrae_90_1/nrel_nze_ready_2017/nrel_zne_ready_2017.Model.rb +0 -35
  375. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +0 -110
  376. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTowerVariableSpeed.rb +0 -5
@@ -3,27 +3,29 @@ class Standard
3
3
  # @ref [References::CBERadiantSystems]
4
4
  # @param zone [OpenStudio::Model::ThermalZone>] zone to add radiant controls
5
5
  # @param radiant_loop [OpenStudio::Model::ZoneHVACLowTempRadiantVarFlow>] radiant loop in thermal zone
6
- # @param radiant_type [String] determines the surface of the radiant system for surface temperature output reporting
7
- # options are 'floor' and 'ceiling'
8
- # @param model_occ_hr_start [Double] Starting hour of building occupancy
9
- # @param model_occ_hr_end [Double] Ending hour of building occupancy
6
+ # @param radiant_temperature_control_type [String] determines the controlled temperature for the radiant system
7
+ # options are 'SurfaceFaceTemperature', 'SurfaceInteriorTemperature'
8
+ # @param use_zone_occupancy_for_control [Boolean] Set to true if radiant system is to use specific zone occupancy objects
9
+ # for CBE control strategy. If false, then it will use values in model_occ_hr_start and model_occ_hr_end
10
+ # for all radiant zones. default to true.
11
+ # @param occupied_percentage_threshold [Double] the minimum fraction (0 to 1) that counts as occupied
12
+ # if this parameter is set, the returned ScheduleRuleset will be 0 = unoccupied, 1 = occupied
13
+ # otherwise the ScheduleRuleset will be the weighted fractional occupancy schedule
14
+ # @param model_occ_hr_start [Double] Starting decimal hour of whole building occupancy
15
+ # @param model_occ_hr_end [Double] Ending decimal hour of whole building occupancy
10
16
  # @todo model_occ_hr_start and model_occ_hr_end from zone occupancy schedules
11
17
  # @param proportional_gain [Double] Proportional gain constant (recommended 0.3 or less).
12
- # @param minimum_operation [Double] Minimum number of hours of operation for radiant system before it shuts off.
13
- # @param weekend_temperature_reset [Double] Weekend temperature reset for slab temperature setpoint in degree Celsius.
14
- # @param early_reset_out_arg [Double] Time at which the weekend temperature reset is removed.
15
18
  # @param switch_over_time [Double] Time limitation for when the system can switch between heating and cooling
16
19
  def model_add_radiant_proportional_controls(model, zone, radiant_loop,
17
- radiant_type: 'floor',
20
+ radiant_temperature_control_type: 'SurfaceFaceTemperature',
21
+ use_zone_occupancy_for_control: true,
22
+ occupied_percentage_threshold: 0.10,
18
23
  model_occ_hr_start: 6.0,
19
24
  model_occ_hr_end: 18.0,
20
25
  proportional_gain: 0.3,
21
- minimum_operation: 1,
22
- weekend_temperature_reset: 2,
23
- early_reset_out_arg: 20,
24
26
  switch_over_time: 24.0)
25
27
 
26
- zone_name = zone.name.to_s.gsub(/[ +-.]/, '_')
28
+ zone_name = ems_friendly_name(zone.name)
27
29
  zone_timestep = model.getTimestep.numberOfTimestepsPerHour
28
30
 
29
31
  if model.version < OpenStudio::VersionString.new('3.1.1')
@@ -34,61 +36,56 @@ class Standard
34
36
  coil_heating_radiant = radiant_loop.heatingCoil.get.to_CoilHeatingLowTempRadiantVarFlow.get
35
37
  end
36
38
 
39
+ #####
40
+ # Define radiant system parameters
41
+ ####
42
+ # set radiant system temperature and setpoint control type
43
+ unless ['surfacefacetemperature', 'surfaceinteriortemperature'].include? radiant_temperature_control_type.downcase
44
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model',
45
+ "Control sequences not compatible with '#{radiant_temperature_control_type}' radiant system control. Defaulting to 'SurfaceFaceTemperature'.")
46
+ radiant_temperature_control_type = 'SurfaceFaceTemperature'
47
+ end
48
+
49
+ radiant_loop.setTemperatureControlType(radiant_temperature_control_type)
50
+
37
51
  #####
38
52
  # List of schedule objects used to hold calculation results
39
53
  ####
40
54
 
41
- # cold water control actuator
42
- # Command to turn ON/OFF the cold water through the radiant system. 0=ON and 100=OFF
43
- # Large temperatures are used to ensure that the radiant system valve will fully open and close
55
+ # get existing switchover time schedule or create one if needed
56
+ sch_radiant_switchover = model.getScheduleRulesetByName('Radiant System Switchover')
57
+ if sch_radiant_switchover.is_initialized
58
+ sch_radiant_switchover = sch_radiant_switchover.get
59
+ else
60
+ sch_radiant_switchover = model_add_constant_schedule_ruleset(model,
61
+ switch_over_time,
62
+ name = 'Radiant System Switchover',
63
+ sch_type_limit: 'Dimensionless')
64
+ end
65
+
66
+ # set radiant system switchover schedule
67
+ radiant_loop.setChangeoverDelayTimePeriodSchedule(sch_radiant_switchover.to_Schedule.get)
68
+
69
+ # Calculated active slab heating and cooling temperature setpoint.
70
+ # radiant system cooling control actuator
44
71
  sch_radiant_clgsetp = model_add_constant_schedule_ruleset(model,
45
- 0.0,
72
+ 26.0,
46
73
  name = "#{zone_name}_Sch_Radiant_ClgSetP")
47
74
  coil_cooling_radiant.setCoolingControlTemperatureSchedule(sch_radiant_clgsetp)
48
75
  cmd_cold_water_ctrl = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_radiant_clgsetp,
49
76
  'Schedule:Year',
50
77
  'Schedule Value')
51
- cmd_cold_water_ctrl.setName("#{zone_name}_CMD_COLD_WATER_CTRL")
78
+ cmd_cold_water_ctrl.setName("#{zone_name}_cmd_cold_water_ctrl")
52
79
 
53
- # hot water control actuator
54
- # Command to turn ON/OFF the hot water through the radiant system. 60=ON and -60=OFF.
55
- # Large temperatures are used to to ensure that the radiant system valve will fully open and close
80
+ # radiant system heating control actuator
56
81
  sch_radiant_htgsetp = model_add_constant_schedule_ruleset(model,
57
- -60.0,
82
+ 20.0,
58
83
  name = "#{zone_name}_Sch_Radiant_HtgSetP")
59
84
  coil_heating_radiant.setHeatingControlTemperatureSchedule(sch_radiant_htgsetp)
60
85
  cmd_hot_water_ctrl = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_radiant_htgsetp,
61
86
  'Schedule:Year',
62
87
  'Schedule Value')
63
- cmd_hot_water_ctrl.setName("#{zone_name}_CMD_HOT_WATER_CTRL")
64
-
65
- # set schedule type limits for hot water control
66
- hot_water_schedule_type_limits = model.getScheduleTypeLimitsByName('Radiant_Hot_water_Ctrl_Temperature_Limits')
67
- if hot_water_schedule_type_limits.is_initialized
68
- hot_water_schedule_type_limits = hot_water_schedule_type_limits.get
69
- else
70
- hot_water_schedule_type_limits = OpenStudio::Model::ScheduleTypeLimits.new(model)
71
- hot_water_schedule_type_limits.setName('Radiant_Hot_water_Ctrl_Temperature_Limits')
72
- hot_water_schedule_type_limits.setLowerLimitValue(-60.0)
73
- hot_water_schedule_type_limits.setUpperLimitValue(100.0)
74
- hot_water_schedule_type_limits.setNumericType('Continuous')
75
- hot_water_schedule_type_limits.setUnitType('Temperature')
76
- end
77
- sch_radiant_htgsetp.setScheduleTypeLimits(hot_water_schedule_type_limits)
78
-
79
- # Calculated active slab heating and cooling temperature setpoint. Default temperature is taken at the slab surface.
80
- sch_slab_sp = model_add_constant_schedule_ruleset(model,
81
- 21.0,
82
- name = "#{zone_name}_Sch_Slab_SP")
83
- cmd_slab_sp = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_slab_sp,
84
- 'Schedule:Year',
85
- 'Schedule Value')
86
- cmd_slab_sp.setName("#{zone_name}_CMD_SLAB_SP")
87
-
88
- # add output variable for slab setpoint temperature
89
- var = OpenStudio::Model::OutputVariable.new('Schedule Value', model)
90
- var.setKeyValue("#{zone_name}_Sch_Slab_SP")
91
- var.setReportingFrequency('Timestep')
88
+ cmd_hot_water_ctrl.setName("#{zone_name}_cmd_hot_water_ctrl")
92
89
 
93
90
  # Calculated cooling setpoint error. Calculated from upper comfort limit minus setpoint offset and 'measured' controlled zone temperature.
94
91
  sch_csp_error = model_add_constant_schedule_ruleset(model,
@@ -97,7 +94,7 @@ class Standard
97
94
  cmd_csp_error = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_csp_error,
98
95
  'Schedule:Year',
99
96
  'Schedule Value')
100
- cmd_csp_error.setName("#{zone_name}_CMD_CSP_ERROR")
97
+ cmd_csp_error.setName("#{zone_name}_cmd_csp_error")
101
98
 
102
99
  # Calculated heating setpoint error. Calculated from lower comfort limit plus setpoint offset and 'measured' controlled zone temperature.
103
100
  sch_hsp_error = model_add_constant_schedule_ruleset(model,
@@ -106,57 +103,12 @@ class Standard
106
103
  cmd_hsp_error = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_hsp_error,
107
104
  'Schedule:Year',
108
105
  'Schedule Value')
109
- cmd_hsp_error.setName("#{zone_name}_CMD_HSP_ERROR")
110
-
111
- # Averaged radiant slab controlled temperature. Averaged over the last 24 hours.
112
- sch_avg_ctrl_temp = model_add_constant_schedule_ruleset(model,
113
- 20.0,
114
- name = "#{zone_name}_Sch_Avg_Ctrl_Temp")
115
- cmd_ctrl_temp_running_mean = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_avg_ctrl_temp,
116
- 'Schedule:Year',
117
- 'Schedule Value')
118
- cmd_ctrl_temp_running_mean.setName("#{zone_name}_CMD_CTRL_TEMP_RUNNING_MEAN")
119
-
120
- # Averaged outdoor air temperature. Averaged over the last 24 hours.
121
- sch_oat_running_mean = model.getScheduleConstantByName('SCH_OAT_RUNNING_MEAN')
122
- if sch_oat_running_mean.is_initialized
123
- sch_oat_running_mean = sch_oat_running_mean.get
124
- else
125
- sch_oat_running_mean = model_add_constant_schedule_ruleset(model,
126
- 20.0,
127
- name = 'SCH_OAT_RUNNING_MEAN')
128
- end
129
-
130
- cmd_oat_running_mean = model.getEnergyManagementSystemActuatorByName('CMD_OAT_RUNNING_MEAN')
131
- if cmd_oat_running_mean.is_initialized
132
- cmd_oat_running_mean = cmd_oat_running_mean.get
133
- else
134
- cmd_oat_running_mean = OpenStudio::Model::EnergyManagementSystemActuator.new(sch_oat_running_mean,
135
- 'Schedule:Year',
136
- 'Schedule Value')
137
- cmd_oat_running_mean.setName('CMD_OAT_RUNNING_MEAN')
138
- end
106
+ cmd_hsp_error.setName("#{zone_name}_cmd_hsp_error")
139
107
 
140
108
  #####
141
109
  # List of global variables used in EMS scripts
142
110
  ####
143
111
 
144
- # Start of occupied time of zone. Valid from 1-24.
145
- occ_hr_start = model.getEnergyManagementSystemGlobalVariableByName('occ_hr_start')
146
- if occ_hr_start.is_initialized
147
- occ_hr_start = occ_hr_start.get
148
- else
149
- occ_hr_start = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'occ_hr_start')
150
- end
151
-
152
- # End of occupied time of zone. Valid from 1-24.
153
- occ_hr_end = model.getEnergyManagementSystemGlobalVariableByName('occ_hr_end')
154
- if occ_hr_end.is_initialized
155
- occ_hr_end = occ_hr_end.get
156
- else
157
- occ_hr_end = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'occ_hr_end')
158
- end
159
-
160
112
  # Proportional gain constant (recommended 0.3 or less).
161
113
  prp_k = model.getEnergyManagementSystemGlobalVariableByName('prp_k')
162
114
  if prp_k.is_initialized
@@ -165,55 +117,7 @@ class Standard
165
117
  prp_k = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'prp_k')
166
118
  end
167
119
 
168
- # mean outdoor dry-bulb air temperature
169
- mean_oat = model.getEnergyManagementSystemGlobalVariableByName('mean_oat')
170
- if mean_oat.is_initialized
171
- mean_oat = mean_oat.get
172
- else
173
- mean_oat = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'mean_oat')
174
- end
175
-
176
- # Is the day a weekend? 1=Weekend and 0=Not Weekend.
177
- weekend = model.getEnergyManagementSystemGlobalVariableByName('weekend')
178
- if weekend.is_initialized
179
- weekend = weekend.get
180
- else
181
- weekend = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'weekend')
182
- end
183
-
184
- # Is the building in unoccupied model? 1=Unoccupied and 0=Not Unoccupied.
185
- unoccupied = model.getEnergyManagementSystemGlobalVariableByName('unoccupied')
186
- if unoccupied.is_initialized
187
- unoccupied = unoccupied.get
188
- else
189
- unoccupied = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'unoccupied')
190
- end
191
-
192
- # Minimum number of hours of operation for radiant system before it shuts off.
193
- min_oper = model.getEnergyManagementSystemGlobalVariableByName('min_oper')
194
- if min_oper.is_initialized
195
- min_oper = min_oper.get
196
- else
197
- min_oper = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'min_oper')
198
- end
199
-
200
- # Weekend temperature reset for slab temperature setpoint in degree Celsius.
201
- wkend_temp_reset = model.getEnergyManagementSystemGlobalVariableByName('wkend_temp_reset')
202
- if wkend_temp_reset.is_initialized
203
- wkend_temp_reset = wkend_temp_reset.get
204
- else
205
- wkend_temp_reset = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'wkend_temp_reset')
206
- end
207
-
208
- # Time at which the weekend temperature reset is removed.
209
- early_reset_out = model.getEnergyManagementSystemGlobalVariableByName('early_reset_out')
210
- if early_reset_out.is_initialized
211
- early_reset_out = early_reset_out.get
212
- else
213
- early_reset_out = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'early_reset_out')
214
- end
215
-
216
- # Upper slab temperature setpoint limit
120
+ # Upper slab temperature setpoint limit (recommended no higher than 29C (84F))
217
121
  upper_slab_sp_lim = model.getEnergyManagementSystemGlobalVariableByName('upper_slab_sp_lim')
218
122
  if upper_slab_sp_lim.is_initialized
219
123
  upper_slab_sp_lim = upper_slab_sp_lim.get
@@ -221,7 +125,7 @@ class Standard
221
125
  upper_slab_sp_lim = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'upper_slab_sp_lim')
222
126
  end
223
127
 
224
- # Lower slab temperature setpoint limit
128
+ # Lower slab temperature setpoint limit (recommended no lower than 19C (66F))
225
129
  lower_slab_sp_lim = model.getEnergyManagementSystemGlobalVariableByName('lower_slab_sp_lim')
226
130
  if lower_slab_sp_lim.is_initialized
227
131
  lower_slab_sp_lim = lower_slab_sp_lim.get
@@ -229,7 +133,7 @@ class Standard
229
133
  lower_slab_sp_lim = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'lower_slab_sp_lim')
230
134
  end
231
135
 
232
- # Temperature offset used to modify.
136
+ # Temperature offset used as a safety factor for thermal control (recommend 0.5C (1F)).
233
137
  ctrl_temp_offset = model.getEnergyManagementSystemGlobalVariableByName('ctrl_temp_offset')
234
138
  if ctrl_temp_offset.is_initialized
235
139
  ctrl_temp_offset = ctrl_temp_offset.get
@@ -237,7 +141,17 @@ class Standard
237
141
  ctrl_temp_offset = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'ctrl_temp_offset')
238
142
  end
239
143
 
240
- # zone specific variables
144
+ # Hour where slab setpoint is to be changed
145
+ hour_of_slab_sp_change = model.getEnergyManagementSystemGlobalVariableByName('hour_of_slab_sp_change')
146
+ if hour_of_slab_sp_change.is_initialized
147
+ hour_of_slab_sp_change = hour_of_slab_sp_change.get
148
+ else
149
+ hour_of_slab_sp_change = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, 'hour_of_slab_sp_change')
150
+ end
151
+
152
+ #####
153
+ # List of zone specific variables used in EMS scripts
154
+ ####
241
155
 
242
156
  # Maximum 'measured' temperature in zone during occupied times. Default setup uses mean air temperature.
243
157
  # Other possible choices are operative and mean radiant temperature.
@@ -247,246 +161,189 @@ class Standard
247
161
  # Other possible choices are operative and mean radiant temperature.
248
162
  zone_min_ctrl_temp = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_min_ctrl_temp")
249
163
 
250
- # mean temperature of control surface
251
- zone_mean_ctrl = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_mean_ctrl")
252
-
253
- # Continuous operation where there is no active hydronic heating or cooling in thermal zone in hours.
254
- zone_cont_neutral_oper = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_cont_neutral_oper")
255
-
256
- # Zone mode of thermal zone. -1=Heating, 1=Cooling, and 0=Neutral.
257
- zone_zone_mode = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_zone_mode")
258
-
259
- # Amount of hours that building needs to be in neutral mode in order to switch over from heating to cooling or from cooling to heating.
260
- zone_switch_over_time = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_switch_over_time")
261
-
262
- # Continuous operation when radiant system is active in hours.
263
- zone_cont_rad_oper = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_cont_rad_oper")
264
-
265
- # Total time the radiant system was in cooling mode in the last 24 hours.
266
- # Calculated at one timestep before the end of occupied time.
267
- zone_daily_cool_sum = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_daily_cool_sum")
268
-
269
- # Total time the radiant system was in heating mode in the last 24 hours.
270
- # Calculated at one timestep before the end of occupied time.
271
- zone_daily_heat_sum = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_daily_heat_sum")
272
-
273
- # Total time the radiant system was in cooling mode for the previous day.
274
- zone_daily_cool_sum_one = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_daily_cool_sum_one")
275
-
276
- # Total time the radiant system was in heating mode for the previous day.
277
- zone_daily_heat_sum_one = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{zone_name}_daily_heat_sum_one")
278
-
279
164
  #####
280
165
  # List of 'sensors' used in the EMS programs
281
166
  ####
282
167
 
283
- # Outdoor air temperature.
284
- oat = model.getEnergyManagementSystemSensorByName('OAT')
285
- if oat.is_initialized
286
- oat = oat.get
287
- else
288
- oat = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Site Outdoor Air Drybulb Temperature')
289
- oat.setName('OAT')
290
- oat.setKeyName('Environment')
291
- end
292
-
293
- # Number of timesteps to average control temperature. (Currently unused)
294
- # avg_window_n = model.getEnergyManagementSystemSensorByName('avg_window_n')
295
- # if avg_window_n.is_initialized
296
- # avg_window_n = avg_window_n.get
297
- # else
298
- # avg_window_n = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
299
- # avg_window_n.setName('avg_window_n')
300
- # avg_window_n.setKeyName('Sch_Slab_Ctrl_Avg_Window_N')
301
- # end
302
-
303
168
  # Controlled zone temperature for the zone.
304
169
  zone_ctrl_temperature = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Air Temperature')
305
- zone_ctrl_temperature.setName("#{zone_name}_Ctrl_Temperature")
170
+ zone_ctrl_temperature.setName("#{zone_name}_ctrl_temperature")
306
171
  zone_ctrl_temperature.setKeyName(zone.name.get)
307
172
 
308
- # Active surface slab temperature. # Use largest surface in zone.
309
- surface_type = radiant_type == 'floor' ? 'Floor' : 'RoofCeiling'
310
- surfaces = []
311
- zone.spaces.each do |space|
312
- space.surfaces.each do |surface|
313
- surfaces << surface if surface.surfaceType == surface_type
314
- end
173
+ # check for zone thermostat and replace heat/cool schedules for radiant system control
174
+ # if there is no zone thermostat, then create one
175
+ zone_thermostat = zone.thermostatSetpointDualSetpoint
176
+
177
+ if zone_thermostat.is_initialized
178
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Replacing thermostat schedules in zone #{zone.name} for radiant system control.")
179
+ zone_thermostat = zone.thermostatSetpointDualSetpoint.get
180
+ else
181
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.Model.Model', "Zone #{zone.name} does not have a thermostat. Creating a thermostat for radiant system control.")
182
+ zone_thermostat = OpenStudio::Model::ThermostatSetpointDualSetpoint.new(model)
183
+ zone_thermostat.setName("#{zone_name}_Thermostat_DualSetpoint")
315
184
  end
316
- if surfaces.empty?
317
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', "Zone #{zone.name} does not have floor surfaces; cannot add radiant system.")
318
- return false
185
+
186
+ # create new heating and cooling schedules to be used with all radiant systems
187
+ zone_htg_thermostat = model.getScheduleRulesetByName('Radiant System Heating Setpoint')
188
+ if zone_htg_thermostat.is_initialized
189
+ zone_htg_thermostat = zone_htg_thermostat.get
190
+ else
191
+ zone_htg_thermostat = model_add_constant_schedule_ruleset(model,
192
+ 20.0,
193
+ name = 'Radiant System Heating Setpoint',
194
+ sch_type_limit: 'Temperature')
319
195
  end
320
- zone_floor = surfaces.max_by(&:grossArea)
321
- zone_srf_temp = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Surface Inside Face Temperature')
322
- zone_srf_temp.setName("#{zone_name}_Srf_Temp")
323
- zone_srf_temp.setKeyName(zone_floor.name.get)
324
196
 
325
- # check for zone thermostats
326
- zone_thermostat = zone.thermostatSetpointDualSetpoint
327
- unless zone_thermostat.is_initialized
328
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model', "Zone #{zone.name} does not have thermostats.")
329
- return false
197
+ zone_clg_thermostat = model.getScheduleRulesetByName('Radiant System Cooling Setpoint')
198
+ if zone_clg_thermostat.is_initialized
199
+ zone_clg_thermostat = zone_clg_thermostat.get
200
+ else
201
+ zone_clg_thermostat = model_add_constant_schedule_ruleset(model,
202
+ 26.0,
203
+ name = 'Radiant System Cooling Setpoint',
204
+ sch_type_limit: 'Temperature')
330
205
  end
331
- zone_thermostat = zone.thermostatSetpointDualSetpoint.get
332
- zone_clg_thermostat = zone_thermostat.coolingSetpointTemperatureSchedule.get
333
- zone_htg_thermostat = zone_thermostat.heatingSetpointTemperatureSchedule.get
206
+
207
+ # implement new heating and cooling schedules
208
+ zone_thermostat.setHeatingSetpointTemperatureSchedule(zone_htg_thermostat)
209
+ zone_thermostat.setCoolingSetpointTemperatureSchedule(zone_clg_thermostat)
334
210
 
335
211
  # Upper comfort limit for the zone. Taken from existing thermostat schedules in the zone.
336
212
  zone_upper_comfort_limit = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
337
- zone_upper_comfort_limit.setName("#{zone_name}_Upper_Comfort_Limit")
213
+ zone_upper_comfort_limit.setName("#{zone_name}_upper_comfort_limit")
338
214
  zone_upper_comfort_limit.setKeyName(zone_clg_thermostat.name.get)
339
215
 
340
216
  # Lower comfort limit for the zone. Taken from existing thermostat schedules in the zone.
341
217
  zone_lower_comfort_limit = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
342
- zone_lower_comfort_limit.setName("#{zone_name}_Lower_Comfort_Limit")
218
+ zone_lower_comfort_limit.setName("#{zone_name}_lower_comfort_limit")
343
219
  zone_lower_comfort_limit.setKeyName(zone_htg_thermostat.name.get)
344
220
 
345
221
  # Radiant system water flow rate used to determine if there is active hydronic cooling in the radiant system.
346
222
  zone_rad_cool_operation = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'System Node Mass Flow Rate')
347
- zone_rad_cool_operation.setName("#{zone_name}_Rad_Cool_Operation")
223
+ zone_rad_cool_operation.setName("#{zone_name}_rad_cool_operation")
348
224
  zone_rad_cool_operation.setKeyName(coil_cooling_radiant.to_StraightComponent.get.inletModelObject.get.name.get)
349
225
 
350
226
  # Radiant system water flow rate used to determine if there is active hydronic heating in the radiant system.
351
227
  zone_rad_heat_operation = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'System Node Mass Flow Rate')
352
- zone_rad_heat_operation.setName("#{zone_name}_Rad_Heat_Operation")
228
+ zone_rad_heat_operation.setName("#{zone_name}_rad_heat_operation")
353
229
  zone_rad_heat_operation.setKeyName(coil_heating_radiant.to_StraightComponent.get.inletModelObject.get.name.get)
354
230
 
355
- # Last 24 hours trend for the outdoor air temperature.
356
- oat_trend = model.getEnergyManagementSystemTrendVariableByName('OAT_Trend')
357
- if oat_trend.is_initialized
358
- oat_trend = oat_trend.get
359
- else
360
- oat_trend = OpenStudio::Model::EnergyManagementSystemTrendVariable.new(model, oat)
361
- oat_trend.setName('OAT_Trend')
362
- oat_trend.setNumberOfTimestepsToBeLogged(zone_timestep * 24)
363
- end
231
+ # Radiant system switchover delay time period schedule
232
+ # used to determine if there is active hydronic cooling/heating in the radiant system.
233
+ zone_rad_switch_over = model.getEnergyManagementSystemSensorByName('radiant_switch_over_time')
364
234
 
365
- # Last 24 hours trend for active slab surface temperature.
366
- zone_srf_temp_trend = OpenStudio::Model::EnergyManagementSystemTrendVariable.new(model, zone_srf_temp)
367
- zone_srf_temp_trend.setName("#{zone_name}_Srf_Temp_Trend")
368
- zone_srf_temp_trend.setNumberOfTimestepsToBeLogged(zone_timestep * 24)
235
+ unless zone_rad_switch_over.is_initialized
236
+ zone_rad_switch_over = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
237
+ zone_rad_switch_over.setName('radiant_switch_over_time')
238
+ zone_rad_switch_over.setKeyName(sch_radiant_switchover.name.get)
239
+ end
369
240
 
370
241
  # Last 24 hours trend for radiant system in cooling mode.
371
242
  zone_rad_cool_operation_trend = OpenStudio::Model::EnergyManagementSystemTrendVariable.new(model, zone_rad_cool_operation)
372
- zone_rad_cool_operation_trend.setName("#{zone_name}_Rad_Cool_Operation_Trend")
373
- zone_rad_cool_operation_trend.setNumberOfTimestepsToBeLogged(zone_timestep * 24)
243
+ zone_rad_cool_operation_trend.setName("#{zone_name}_rad_cool_operation_trend")
244
+ zone_rad_cool_operation_trend.setNumberOfTimestepsToBeLogged(zone_timestep * 48)
374
245
 
375
246
  # Last 24 hours trend for radiant system in heating mode.
376
247
  zone_rad_heat_operation_trend = OpenStudio::Model::EnergyManagementSystemTrendVariable.new(model, zone_rad_heat_operation)
377
- zone_rad_heat_operation_trend.setName("#{zone_name}_Rad_Heat_Operation_Trend")
378
- zone_rad_heat_operation_trend.setNumberOfTimestepsToBeLogged(zone_timestep * 24)
248
+ zone_rad_heat_operation_trend.setName("#{zone_name}_rad_heat_operation_trend")
249
+ zone_rad_heat_operation_trend.setNumberOfTimestepsToBeLogged(zone_timestep * 48)
250
+
251
+ # use zone occupancy objects for radiant system control if selected
252
+ if use_zone_occupancy_for_control
253
+
254
+ # get annual occupancy schedule for zone
255
+ occ_schedule_ruleset = thermal_zone_get_occupancy_schedule(zone,
256
+ sch_name: "#{zone.name} Radiant System Occupied Schedule",
257
+ occupied_percentage_threshold: occupied_percentage_threshold)
258
+ else
259
+
260
+ occ_schedule_ruleset = model.getScheduleRulesetByName('Whole Building Radiant System Occupied Schedule')
261
+ if occ_schedule_ruleset.is_initialized
262
+ occ_schedule_ruleset = occ_schedule_ruleset.get
263
+ else
264
+ # create occupancy schedules
265
+ occ_schedule_ruleset = OpenStudio::Model::ScheduleRuleset.new(model)
266
+ occ_schedule_ruleset.setName('Whole Building Radiant System Occupied Schedule')
267
+
268
+ start_hour = model_occ_hr_end.to_i
269
+ start_minute = ((model_occ_hr_end % 1) * 60).to_i
270
+ end_hour = model_occ_hr_start.to_i
271
+ end_minute = ((model_occ_hr_start % 1) * 60).to_i
272
+
273
+ if end_hour > start_hour
274
+ occ_schedule_ruleset.defaultDaySchedule.addValue(OpenStudio::Time.new(0, start_hour, start_minute, 0), 1.0)
275
+ occ_schedule_ruleset.defaultDaySchedule.addValue(OpenStudio::Time.new(0, end_hour, end_minute, 0), 0.0)
276
+ occ_schedule_ruleset.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1.0) if end_hour < 24
277
+ elsif start_hour > end_hour
278
+ occ_schedule_ruleset.defaultDaySchedule.addValue(OpenStudio::Time.new(0, end_hour, end_minute, 0), 0.0)
279
+ occ_schedule_ruleset.defaultDaySchedule.addValue(OpenStudio::Time.new(0, start_hour, start_minute, 0), 1.0)
280
+ occ_schedule_ruleset.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 0.0) if start_hour < 24
281
+ else
282
+ occ_schedule_ruleset.defaultDaySchedule.addValue(OpenStudio::Time.new(0, 24, 0, 0), 1.0)
283
+ end
284
+ end
285
+ end
286
+
287
+ # create ems sensor for zone occupied status
288
+ zone_occupied_status = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
289
+ zone_occupied_status.setName("#{zone_name}_occupied_status")
290
+ zone_occupied_status.setKeyName(occ_schedule_ruleset.name.get)
291
+
292
+ # Last 24 hours trend for zone occupied status
293
+ zone_occupied_status_trend = OpenStudio::Model::EnergyManagementSystemTrendVariable.new(model, zone_occupied_status)
294
+ zone_occupied_status_trend.setName("#{zone_name}_occupied_status_trend")
295
+ zone_occupied_status_trend.setNumberOfTimestepsToBeLogged(zone_timestep * 48)
379
296
 
380
297
  #####
381
298
  # List of EMS programs to implement the proportional control for the radiant system.
382
299
  ####
383
300
 
384
301
  # Initialize global constant values used in EMS programs.
385
- set_constant_values_prg = model.getEnergyManagementSystemTrendVariableByName('Set_Constant_Values')
386
- unless set_constant_values_prg.is_initialized
302
+ set_constant_values_prg_body = <<-EMS
303
+ SET prp_k = #{proportional_gain},
304
+ SET ctrl_temp_offset = 0.5,
305
+ SET upper_slab_sp_lim = 29,
306
+ SET lower_slab_sp_lim = 19,
307
+ SET hour_of_slab_sp_change = 18
308
+ EMS
309
+
310
+ set_constant_values_prg = model.getEnergyManagementSystemProgramByName('Set_Constant_Values')
311
+ if set_constant_values_prg.is_initialized
312
+ set_constant_values_prg = set_constant_values_prg.get
313
+ else
387
314
  set_constant_values_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
388
315
  set_constant_values_prg.setName('Set_Constant_Values')
389
- set_constant_values_prg_body = <<-EMS
390
- SET occ_hr_start = #{model_occ_hr_start},
391
- SET occ_hr_end = #{model_occ_hr_end},
392
- SET prp_k = #{proportional_gain},
393
- SET min_oper = #{minimum_operation},
394
- SET ctrl_temp_offset = 0.5,
395
- SET wkend_temp_reset = #{weekend_temperature_reset},
396
- SET early_reset_out = #{early_reset_out_arg},
397
- SET upper_slab_sp_lim = 29,
398
- SET lower_slab_sp_lim = 19
399
- EMS
400
316
  set_constant_values_prg.setBody(set_constant_values_prg_body)
401
317
  end
402
318
 
403
- # Determine if it is a weekend or not a weekend schedule for the building.
404
- determine_weekend_prg = model.getEnergyManagementSystemTrendVariableByName('Determine_Weekend')
405
- unless determine_weekend_prg.is_initialized
406
- determine_weekend_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
407
- determine_weekend_prg.setName('Determine_Weekend')
408
- determine_weekend_prg_body = <<-EMS
409
- IF (DayOfWeek == 1) || (DayOfWeek == 7),
410
- SET weekend = 1,
411
- ELSEIF (DayOfWeek == 2) && (CurrentTime < occ_hr_start),
412
- SET weekend = 1,
413
- ELSEIF (DayOfWeek == 6) && (CurrentTime > occ_hr_end),
414
- SET weekend = 1,
415
- ELSE,
416
- SET weekend = 0,
417
- ENDIF
418
- EMS
419
- determine_weekend_prg.setBody(determine_weekend_prg_body)
420
- end
421
-
422
- # Determine if building is in unoccupied mode or not in unoccupied mode.
423
- determine_unoccupied_prg = model.getEnergyManagementSystemTrendVariableByName('Determine_Unoccupied')
424
- unless determine_unoccupied_prg.is_initialized
425
- determine_unoccupied_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
426
- determine_unoccupied_prg.setName('Determine_Unoccupied')
427
- determine_unoccupied_prg_body = <<-EMS
428
- IF (DayOfWeek == 1) || (DayOfWeek == 7),
429
- SET unoccupied = 0,
430
- ELSEIF (CurrentTime > occ_hr_end) || (CurrentTime < occ_hr_start),
431
- IF (DayOfWeek == 2) && (CurrentTime < occ_hr_start),
432
- SET unoccupied = 0,
433
- ELSEIF (DayOfWeek == 6) && (CurrentTime > occ_hr_end),
434
- SET unoccupied = 0,
435
- ELSE,
436
- SET unoccupied = 1,
437
- ENDIF,
438
- ELSE,
439
- SET unoccupied = 0,
440
- ENDIF
441
- EMS
442
- determine_unoccupied_prg.setBody(determine_unoccupied_prg_body)
443
- end
444
-
445
319
  # Initialize zone specific constant values used in EMS programs.
446
- set_constant_zone_values_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
447
- set_constant_zone_values_prg.setName("#{zone_name}_Set_Constant_Values")
448
320
  set_constant_zone_values_prg_body = <<-EMS
449
- SET #{zone_name}_max_ctrl_temp = #{zone_name}_Lower_Comfort_Limit,
450
- SET #{zone_name}_min_ctrl_temp = #{zone_name}_Upper_Comfort_Limit,
451
- SET #{zone_name}_cont_neutral_oper = 0,
452
- SET #{zone_name}_zone_mode = 0,
453
- SET #{zone_name}_switch_over_time = #{switch_over_time},
454
- SET #{zone_name}_CMD_CSP_ERROR = 0,
455
- SET #{zone_name}_CMD_HSP_ERROR = 0,
456
- SET #{zone_name}_CMD_SLAB_SP = #{zone_name}_Lower_Comfort_Limit,
457
- SET #{zone_name}_cont_rad_oper = 0,
458
- SET #{zone_name}_daily_cool_sum = 0,
459
- SET #{zone_name}_daily_heat_sum = 0,
460
- SET #{zone_name}_daily_cool_sum_one = 0,
461
- SET #{zone_name}_daily_heat_sum_one = 0
321
+ SET #{zone_name}_max_ctrl_temp = #{zone_name}_lower_comfort_limit,
322
+ SET #{zone_name}_min_ctrl_temp = #{zone_name}_upper_comfort_limit,
323
+ SET #{zone_name}_cmd_csp_error = 0,
324
+ SET #{zone_name}_cmd_hsp_error = 0,
325
+ SET #{zone_name}_cmd_cold_water_ctrl = #{zone_name}_upper_comfort_limit,
326
+ SET #{zone_name}_cmd_hot_water_ctrl = #{zone_name}_lower_comfort_limit
462
327
  EMS
463
- set_constant_zone_values_prg.setBody(set_constant_zone_values_prg_body)
464
328
 
465
- # Calculate temperature averages.
466
- calculate_trends_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
467
- calculate_trends_prg.setName("#{zone_name}_Calculate_Trends")
468
- calculate_trends_prg_body = <<-EMS
469
- SET mean_oat = @TrendAverage OAT_Trend 24/ZoneTimeStep,
470
- SET #{zone_name}_mean_ctrl = @TrendAverage #{zone_name}_Srf_Temp_Trend 24/ZoneTimeStep,
471
- SET CMD_OAT_RUNNING_MEAN = mean_oat + 0,
472
- SET #{zone_name}_CMD_CTRL_TEMP_RUNNING_MEAN = #{zone_name}_mean_ctrl + 0
473
- EMS
474
- calculate_trends_prg.setBody(calculate_trends_prg_body)
329
+ set_constant_zone_values_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
330
+ set_constant_zone_values_prg.setName("#{zone_name}_Set_Constant_Values")
331
+ set_constant_zone_values_prg.setBody(set_constant_zone_values_prg_body)
475
332
 
476
333
  # Calculate maximum and minimum 'measured' controlled temperature in the zone
477
334
  calculate_minmax_ctrl_temp_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
478
335
  calculate_minmax_ctrl_temp_prg.setName("#{zone_name}_Calculate_Extremes_In_Zone")
479
336
  calculate_minmax_ctrl_temp_prg_body = <<-EMS
480
- IF ((CurrentTime >= occ_hr_start) && (CurrentTime <= occ_hr_end)),
481
- IF #{zone_name}_Ctrl_Temperature > #{zone_name}_max_ctrl_temp,
482
- SET #{zone_name}_max_ctrl_temp = #{zone_name}_Ctrl_Temperature,
337
+ IF (#{zone_name}_occupied_status == 1),
338
+ IF #{zone_name}_ctrl_temperature > #{zone_name}_max_ctrl_temp,
339
+ SET #{zone_name}_max_ctrl_temp = #{zone_name}_ctrl_temperature,
483
340
  ENDIF,
484
- IF #{zone_name}_Ctrl_Temperature < #{zone_name}_min_ctrl_temp,
485
- SET #{zone_name}_min_ctrl_temp = #{zone_name}_Ctrl_Temperature,
341
+ IF #{zone_name}_ctrl_temperature < #{zone_name}_min_ctrl_temp,
342
+ SET #{zone_name}_min_ctrl_temp = #{zone_name}_ctrl_temperature,
486
343
  ENDIF,
487
344
  ELSE,
488
- SET #{zone_name}_max_ctrl_temp = #{zone_name}_Lower_Comfort_Limit,
489
- SET #{zone_name}_min_ctrl_temp = #{zone_name}_Upper_Comfort_Limit,
345
+ SET #{zone_name}_max_ctrl_temp = #{zone_name}_lower_comfort_limit,
346
+ SET #{zone_name}_min_ctrl_temp = #{zone_name}_upper_comfort_limit,
490
347
  ENDIF
491
348
  EMS
492
349
  calculate_minmax_ctrl_temp_prg.setBody(calculate_minmax_ctrl_temp_prg_body)
@@ -495,148 +352,48 @@ class Standard
495
352
  calculate_errors_from_comfort_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
496
353
  calculate_errors_from_comfort_prg.setName("#{zone_name}_Calculate_Errors_From_Comfort")
497
354
  calculate_errors_from_comfort_prg_body = <<-EMS
498
- IF (CurrentTime >= (occ_hr_end - ZoneTimeStep)) && (CurrentTime <= (occ_hr_end)),
499
- SET #{zone_name}_CMD_CSP_ERROR = (#{zone_name}_Upper_Comfort_Limit - ctrl_temp_offset) - #{zone_name}_max_ctrl_temp,
500
- SET #{zone_name}_CMD_HSP_ERROR = (#{zone_name}_Lower_Comfort_Limit + ctrl_temp_offset) - #{zone_name}_min_ctrl_temp,
355
+ IF (CurrentTime == (hour_of_slab_sp_change - ZoneTimeStep)),
356
+ SET #{zone_name}_cmd_csp_error = (#{zone_name}_upper_comfort_limit - ctrl_temp_offset) - #{zone_name}_max_ctrl_temp,
357
+ SET #{zone_name}_cmd_hsp_error = (#{zone_name}_lower_comfort_limit + ctrl_temp_offset) - #{zone_name}_min_ctrl_temp,
501
358
  ENDIF
502
359
  EMS
503
360
  calculate_errors_from_comfort_prg.setBody(calculate_errors_from_comfort_prg_body)
504
361
 
505
- # Calculate time when there is no active hydronic heating or cooling.
506
- calculate_neutral_time_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
507
- calculate_neutral_time_prg.setName("#{zone_name}_Calculate_Neutral_Time")
508
- calculate_neutral_time_prg_body = <<-EMS
509
- IF (#{zone_name}_Rad_Cool_Operation > 0) || (#{zone_name}_Rad_Heat_Operation > 0),
510
- SET #{zone_name}_cont_neutral_oper = 0,
511
- ELSE,
512
- SET #{zone_name}_cont_neutral_oper = #{zone_name}_cont_neutral_oper + ZoneTimeStep,
513
- ENDIF
514
- EMS
515
- calculate_neutral_time_prg.setBody(calculate_neutral_time_prg_body)
516
-
517
- # Calculate time when there is active hydronic heating or cooling in thermal zone.
518
- calculate_continuous_radiant_operation_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
519
- calculate_continuous_radiant_operation_prg.setName("#{zone_name}_Calculate_Continuous_Radiant_Operation")
520
- calculate_continuous_radiant_operation_prg_body = <<-EMS
521
- IF (#{zone_name}_Rad_Cool_Operation > 0) || (#{zone_name}_Rad_Heat_Operation > 0),
522
- SET #{zone_name}_cont_rad_oper = #{zone_name}_cont_rad_oper + ZoneTimeStep,
523
- ELSE,
524
- SET #{zone_name}_cont_rad_oper = 0,
525
- ENDIF
526
- EMS
527
- calculate_continuous_radiant_operation_prg.setBody(calculate_continuous_radiant_operation_prg_body)
528
-
529
- # Determine if the zone is in cooling, heating, or neutral mode.
530
- determine_zone_mode_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
531
- determine_zone_mode_prg.setName("#{zone_name}_Determine_Zone_Mode")
532
- determine_zone_mode_prg_body = <<-EMS
533
- SET #{zone_name}_cont_cool_oper = @TrendSum #{zone_name}_Rad_Cool_Operation_Trend 24/ZoneTimeStep,
534
- SET #{zone_name}_cont_heat_oper = @TrendSum #{zone_name}_Rad_Heat_Operation_Trend 24/ZoneTimeStep,
535
- IF (#{zone_name}_zone_mode <> 0) && (#{zone_name}_cont_neutral_oper > #{zone_name}_switch_over_time),
536
- SET #{zone_name}_zone_mode = 0,
537
- ELSEIF (#{zone_name}_cont_cool_oper > 0) && (#{zone_name}_zone_mode == 0),
538
- SET #{zone_name}_zone_mode = 1,
539
- ELSEIF (#{zone_name}_cont_heat_oper > 0) && (#{zone_name}_zone_mode == 0),
540
- SET #{zone_name}_zone_mode = -1,
541
- ELSE,
542
- SET #{zone_name}_zone_mode = #{zone_name}_zone_mode,
543
- ENDIF
544
- EMS
545
- determine_zone_mode_prg.setBody(determine_zone_mode_prg_body)
546
-
547
- # Calculate the cumulative time for active hydronic cooling and heating.
548
- calculate_cumulative_sum_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
549
- calculate_cumulative_sum_prg.setName("#{zone_name}_Calculate_Cumulative_Sum")
550
- calculate_cumulative_sum_prg_body = <<-EMS
551
- IF (CurrentTime == (occ_hr_end - ZoneTimeStep)),
552
- SET #{zone_name}_daily_cool_sum_one = #{zone_name}_daily_cool_sum,
553
- SET #{zone_name}_daily_heat_sum_one = #{zone_name}_daily_heat_sum,
554
- SET #{zone_name}_daily_cool_sum = @TrendSum #{zone_name}_Rad_Cool_Operation_Trend 24/ZoneTimeStep,
555
- SET #{zone_name}_daily_heat_sum = @TrendSum #{zone_name}_Rad_Heat_Operation_Trend 24/ZoneTimeStep,
556
- ENDIF
557
- EMS
558
- calculate_cumulative_sum_prg.setBody(calculate_cumulative_sum_prg_body)
559
-
560
362
  # Calculate the new active slab temperature setpoint for heating and cooling
561
363
  calculate_slab_ctrl_setpoint_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
562
364
  calculate_slab_ctrl_setpoint_prg.setName("#{zone_name}_Calculate_Slab_Ctrl_Setpoint")
563
365
  calculate_slab_ctrl_setpoint_prg_body = <<-EMS
564
- IF (#{zone_name}_zone_mode >= 0),
565
- SET #{zone_name}_cont_cool_oper = @TrendSum #{zone_name}_Rad_Cool_Operation_Trend 24/ZoneTimeStep,
566
- IF (#{zone_name}_cont_cool_oper > 0) && (CurrentTime == occ_hr_end),
567
- SET #{zone_name}_CMD_SLAB_SP = #{zone_name}_CMD_SLAB_SP + (#{zone_name}_CMD_CSP_ERROR*prp_k),
568
- ENDIF,
569
- ELSEIF (#{zone_name}_zone_mode <= 0),
570
- SET #{zone_name}_cont_heat_oper = @TrendSum #{zone_name}_Rad_Heat_Operation_Trend 24/ZoneTimeStep,
571
- IF (#{zone_name}_cont_heat_oper > 0) && (CurrentTime == occ_hr_end),
572
- SET #{zone_name}_CMD_SLAB_SP = #{zone_name}_CMD_SLAB_SP + (#{zone_name}_CMD_HSP_ERROR*prp_k),
573
- ENDIF,
366
+ SET #{zone_name}_cont_cool_oper = @TrendSum #{zone_name}_rad_cool_operation_trend radiant_switch_over_time/ZoneTimeStep,
367
+ SET #{zone_name}_cont_heat_oper = @TrendSum #{zone_name}_rad_heat_operation_trend radiant_switch_over_time/ZoneTimeStep,
368
+ SET #{zone_name}_occupied_hours = @TrendSum #{zone_name}_occupied_status_trend 24/ZoneTimeStep,
369
+ IF (#{zone_name}_cont_cool_oper > 0) && (#{zone_name}_occupied_hours > 0) && (CurrentTime == hour_of_slab_sp_change),
370
+ SET #{zone_name}_cmd_hot_water_ctrl = #{zone_name}_cmd_hot_water_ctrl + (#{zone_name}_cmd_csp_error*prp_k),
371
+ ELSEIF (#{zone_name}_cont_heat_oper > 0) && (#{zone_name}_occupied_hours > 0) && (CurrentTime == hour_of_slab_sp_change),
372
+ SET #{zone_name}_cmd_hot_water_ctrl = #{zone_name}_cmd_hot_water_ctrl + (#{zone_name}_cmd_hsp_error*prp_k),
373
+ ELSE,
374
+ SET #{zone_name}_cmd_hot_water_ctrl = #{zone_name}_cmd_hot_water_ctrl,
574
375
  ENDIF,
575
- IF (#{zone_name}_CMD_SLAB_SP < lower_slab_sp_lim),
576
- SET #{zone_name}_CMD_SLAB_SP = lower_slab_sp_lim,
577
- ELSEIF (#{zone_name}_CMD_SLAB_SP > upper_slab_sp_lim),
578
- SET #{zone_name}_CMD_SLAB_SP = upper_slab_sp_lim,
376
+ IF (#{zone_name}_cmd_hot_water_ctrl < lower_slab_sp_lim),
377
+ SET #{zone_name}_cmd_hot_water_ctrl = lower_slab_sp_lim,
378
+ ELSEIF (#{zone_name}_cmd_hot_water_ctrl > upper_slab_sp_lim),
379
+ SET #{zone_name}_cmd_hot_water_ctrl = upper_slab_sp_lim,
579
380
  ENDIF,
381
+ SET #{zone_name}_cmd_cold_water_ctrl = #{zone_name}_cmd_hot_water_ctrl + 0.01
580
382
  EMS
581
383
  calculate_slab_ctrl_setpoint_prg.setBody(calculate_slab_ctrl_setpoint_prg_body)
582
384
 
583
- # Apply a weekend setback at the start of a weekend and remove the reset at the defined time.
584
- implement_setback_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
585
- implement_setback_prg.setName("#{zone_name}_Implement_setback")
586
- implement_setback_prg_body = <<-EMS
587
- IF early_reset_out > occ_hr_start,
588
- SET turn_on_day = 1,
589
- SET turn_on_hour = 24 - (early_reset_out - occ_hr_start),
590
- ELSE,
591
- SET turn_on_day = 2,
592
- SET turn_on_hour = occ_hr_start - early_reset_out,
593
- ENDIF,
594
- IF (CurrentTime == occ_hr_end) && (DayOfWeek == 6),
595
- SET #{zone_name}_CMD_SLAB_SP = #{zone_name}_CMD_SLAB_SP,
596
- ELSEIF (CurrentTime == turn_on_hour) && (DayOfWeek == turn_on_day),
597
- SET #{zone_name}_CMD_SLAB_SP = #{zone_name}_CMD_SLAB_SP,
598
- ENDIF
599
- EMS
600
- implement_setback_prg.setBody(implement_setback_prg_body)
601
-
602
- # Get design day size
603
- num_design_days = model.getDesignDays.size
604
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.Model.Model', "EMS code for radiant system operation depends on the number of design days being fixed. The model has #{num_design_days}. Do not change design days now that the model has EMS code dependent on them. ")
605
-
606
- # Turn radiant system ON/OFF for cooling or heating based on calculated setpoints and building mode.
607
- determine_radiant_operation_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
608
- determine_radiant_operation_prg.setName("#{zone_name}_Determine_Radiant_Operation")
609
- determine_radiant_operation_prg_body = <<-EMS
610
- IF (CurrentEnvironment) <= #{num_design_days} ! Operation during design days
611
- SET #{zone_name}_CMD_COLD_WATER_CTRL = 0,
612
- SET #{zone_name}_CMD_HOT_WATER_CTRL = -60,
613
- ELSE, ! Operation during annual simulation
614
- IF (#{zone_name}_zone_mode >= 0) && (#{zone_name}_Srf_Temp > #{zone_name}_CMD_SLAB_SP),
615
- SET #{zone_name}_CMD_COLD_WATER_CTRL = 0,
616
- SET #{zone_name}_CMD_HOT_WATER_CTRL = -60,
617
- ELSEIF (#{zone_name}_zone_mode >= 0) && (#{zone_name}_Srf_Temp < #{zone_name}_CMD_SLAB_SP) && (min_oper > #{zone_name}_cont_rad_oper) && (#{zone_name}_cont_rad_oper <> 0),
618
- SET #{zone_name}_CMD_COLD_WATER_CTRL = 0,
619
- SET #{zone_name}_CMD_HOT_WATER_CTRL = -60,
620
- ELSEIF (#{zone_name}_zone_mode <= 0) && (#{zone_name}_Srf_Temp < #{zone_name}_CMD_SLAB_SP),
621
- SET #{zone_name}_CMD_COLD_WATER_CTRL = 100,
622
- SET #{zone_name}_CMD_HOT_WATER_CTRL = 60,
623
- ELSEIF (#{zone_name}_zone_mode <= 0) && (#{zone_name}_Srf_Temp > #{zone_name}_CMD_SLAB_SP) && (min_oper > #{zone_name}_cont_rad_oper) && (#{zone_name}_cont_rad_oper <> 0),
624
- SET #{zone_name}_CMD_COLD_WATER_CTRL = 100,
625
- SET #{zone_name}_CMD_HOT_WATER_CTRL = 60,
626
- ELSE,
627
- SET #{zone_name}_CMD_COLD_WATER_CTRL = 60,
628
- SET #{zone_name}_CMD_HOT_WATER_CTRL = -60,
629
- ENDIF,
630
- ENDIF
631
- EMS
632
- determine_radiant_operation_prg.setBody(determine_radiant_operation_prg_body)
633
-
634
385
  #####
635
386
  # List of EMS program manager objects
636
387
  ####
637
- initialize_constant_parameters = model.getEnergyManagementSystemProgramCallingManagerByName('Set_Constant_Values')
388
+
389
+ initialize_constant_parameters = model.getEnergyManagementSystemProgramCallingManagerByName('Initialize_Constant_Parameters')
638
390
  if initialize_constant_parameters.is_initialized
639
391
  initialize_constant_parameters = initialize_constant_parameters.get
392
+ # add program if it does not exist in manager
393
+ existing_program_names = initialize_constant_parameters.programs.collect { |prg| prg.name.get.downcase }
394
+ unless existing_program_names.include? set_constant_values_prg.name.get.downcase
395
+ initialize_constant_parameters.addProgram(set_constant_values_prg)
396
+ end
640
397
  else
641
398
  initialize_constant_parameters = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
642
399
  initialize_constant_parameters.setName('Initialize_Constant_Parameters')
@@ -644,13 +401,18 @@ class Standard
644
401
  initialize_constant_parameters.addProgram(set_constant_values_prg)
645
402
  end
646
403
 
647
- initialize_constant_parameters_after_warmup = model.getEnergyManagementSystemProgramCallingManagerByName('Set_Constant_Values')
404
+ initialize_constant_parameters_after_warmup = model.getEnergyManagementSystemProgramCallingManagerByName('Initialize_Constant_Parameters_After_Warmup')
648
405
  if initialize_constant_parameters_after_warmup.is_initialized
649
406
  initialize_constant_parameters_after_warmup = initialize_constant_parameters_after_warmup.get
407
+ # add program if it does not exist in manager
408
+ existing_program_names = initialize_constant_parameters_after_warmup.programs.collect { |prg| prg.name.get.downcase }
409
+ unless existing_program_names.include? set_constant_values_prg.name.get.downcase
410
+ initialize_constant_parameters_after_warmup.addProgram(set_constant_values_prg)
411
+ end
650
412
  else
651
413
  initialize_constant_parameters_after_warmup = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
652
414
  initialize_constant_parameters_after_warmup.setName('Initialize_Constant_Parameters_After_Warmup')
653
- initialize_constant_parameters_after_warmup.setCallingPoint('BeginNewEnvironment')
415
+ initialize_constant_parameters_after_warmup.setCallingPoint('AfterNewEnvironmentWarmUpIsComplete')
654
416
  initialize_constant_parameters_after_warmup.addProgram(set_constant_values_prg)
655
417
  end
656
418
 
@@ -661,7 +423,7 @@ class Standard
661
423
 
662
424
  zone_initialize_constant_parameters_after_warmup = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
663
425
  zone_initialize_constant_parameters_after_warmup.setName("#{zone_name}_Initialize_Constant_Parameters_After_Warmup")
664
- zone_initialize_constant_parameters_after_warmup.setCallingPoint('BeginNewEnvironment')
426
+ zone_initialize_constant_parameters_after_warmup.setCallingPoint('AfterNewEnvironmentWarmUpIsComplete')
665
427
  zone_initialize_constant_parameters_after_warmup.addProgram(set_constant_zone_values_prg)
666
428
 
667
429
  average_building_temperature = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
@@ -669,42 +431,139 @@ class Standard
669
431
  average_building_temperature.setCallingPoint('EndOfZoneTimestepAfterZoneReporting')
670
432
  average_building_temperature.addProgram(calculate_minmax_ctrl_temp_prg)
671
433
  average_building_temperature.addProgram(calculate_errors_from_comfort_prg)
672
- average_building_temperature.addProgram(calculate_neutral_time_prg)
673
- average_building_temperature.addProgram(determine_zone_mode_prg)
674
- average_building_temperature.addProgram(calculate_trends_prg)
675
- average_building_temperature.addProgram(calculate_continuous_radiant_operation_prg)
676
- average_building_temperature.addProgram(calculate_cumulative_sum_prg)
677
434
 
678
435
  programs_at_beginning_of_timestep = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
679
436
  programs_at_beginning_of_timestep.setName("#{zone_name}_Programs_At_Beginning_Of_Timestep")
680
437
  programs_at_beginning_of_timestep.setCallingPoint('BeginTimestepBeforePredictor')
681
- programs_at_beginning_of_timestep.addProgram(determine_weekend_prg)
682
- programs_at_beginning_of_timestep.addProgram(determine_unoccupied_prg)
683
- programs_at_beginning_of_timestep.addProgram(determine_zone_mode_prg)
684
- programs_at_beginning_of_timestep.addProgram(implement_setback_prg)
685
438
  programs_at_beginning_of_timestep.addProgram(calculate_slab_ctrl_setpoint_prg)
686
- programs_at_beginning_of_timestep.addProgram(determine_radiant_operation_prg)
687
439
 
688
440
  #####
689
441
  # List of variables for output.
690
442
  ####
443
+
691
444
  zone_max_ctrl_temp_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_max_ctrl_temp)
692
445
  zone_max_ctrl_temp_output.setName("#{zone_name} Maximum occupied temperature in zone")
693
446
  zone_min_ctrl_temp_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_min_ctrl_temp)
694
447
  zone_min_ctrl_temp_output.setName("#{zone_name} Minimum occupied temperature in zone")
695
- zone_zone_mode_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_zone_mode)
696
- zone_zone_mode_output.setName("#{zone_name} Zone Mode of Operation")
697
- zone_cont_neutral_oper_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_cont_neutral_oper)
698
- zone_cont_neutral_oper_output.setName("#{zone_name} Number of Hours in Neutral Operation")
699
- zone_cont_rad_oper_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_cont_rad_oper)
700
- zone_cont_rad_oper_output.setName("#{zone_name} Number of Hours in Continuous Operation")
701
- zone_daily_cool_sum_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_daily_cool_sum)
702
- zone_daily_cool_sum_output.setName("#{zone_name} Daily Building Cool Operation")
703
- zone_daily_heat_sum_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_daily_heat_sum)
704
- zone_daily_heat_sum_output.setName("#{zone_name} Daily Building Heat Operation")
705
- zone_daily_cool_sum_one_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_daily_cool_sum_one)
706
- zone_daily_cool_sum_one_output.setName("#{zone_name} Daily Building Cool Operation One")
707
- zone_daily_heat_sum_one_output = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, zone_daily_heat_sum_one)
708
- zone_daily_heat_sum_one_output.setName("#{zone_name} Daily Building Heat Operation One")
448
+ end
449
+
450
+ # Native EnergyPlus objects implement a control for a single thermal zone with a radiant system.
451
+ # @param zone [OpenStudio::Model::ThermalZone>] zone to add radiant controls
452
+ # @param radiant_loop [OpenStudio::Model::ZoneHVACLowTempRadiantVarFlow>] radiant loop in thermal zone
453
+ # @param radiant_temperature_control_type [String] determines the controlled temperature for the radiant system
454
+ # options are 'SurfaceFaceTemperature', 'SurfaceInteriorTemperature'
455
+ # @param slab_setpoint_oa_control [Bool] True if slab setpoint is to be varied based on outdoor air temperature
456
+ # @param switch_over_time [Double] Time limitation for when the system can switch between heating and cooling
457
+ # @param slab_sp_at_oat_low [Double] radiant slab temperature setpoint, in F, at the outdoor high temperature.
458
+ # @param slab_oat_low [Double] outdoor drybulb air temperature, in F, for low radiant slab setpoint.
459
+ # @param slab_sp_at_oat_high [Double] radiant slab temperature setpoint, in F, at the outdoor low temperature.
460
+ # @param slab_oat_high [Double] outdoor drybulb air temperature, in F, for high radiant slab setpoint.
461
+ def model_add_radiant_basic_controls(model, zone, radiant_loop,
462
+ radiant_temperature_control_type: 'SurfaceFaceTemperature',
463
+ slab_setpoint_oa_control: false,
464
+ switch_over_time: 24.0,
465
+ slab_sp_at_oat_low: 73,
466
+ slab_oat_low: 65,
467
+ slab_sp_at_oat_high: 68,
468
+ slab_oat_high: 80)
469
+
470
+ zone_name = zone.name.to_s.gsub(/[ +-.]/, '_')
471
+
472
+ if model.version < OpenStudio::VersionString.new('3.1.1')
473
+ coil_cooling_radiant = radiant_loop.coolingCoil.to_CoilCoolingLowTempRadiantVarFlow.get
474
+ coil_heating_radiant = radiant_loop.heatingCoil.to_CoilHeatingLowTempRadiantVarFlow.get
475
+ else
476
+ coil_cooling_radiant = radiant_loop.coolingCoil.get.to_CoilCoolingLowTempRadiantVarFlow.get
477
+ coil_heating_radiant = radiant_loop.heatingCoil.get.to_CoilHeatingLowTempRadiantVarFlow.get
478
+ end
479
+
480
+ #####
481
+ # Define radiant system parameters
482
+ ####
483
+ # set radiant system temperature and setpoint control type
484
+ unless ['surfacefacetemperature', 'surfaceinteriortemperature'].include? radiant_temperature_control_type.downcase
485
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model',
486
+ "Control sequences not compatible with '#{radiant_temperature_control_type}' radiant system control. Defaulting to 'SurfaceFaceTemperature'.")
487
+ radiant_temperature_control_type = 'SurfaceFaceTemperature'
488
+ end
489
+
490
+ radiant_loop.setTemperatureControlType(radiant_temperature_control_type)
491
+
492
+ # get existing switchover time schedule or create one if needed
493
+ sch_radiant_switchover = model.getScheduleRulesetByName('Radiant System Switchover')
494
+ if sch_radiant_switchover.is_initialized
495
+ sch_radiant_switchover = sch_radiant_switchover.get
496
+ else
497
+ sch_radiant_switchover = model_add_constant_schedule_ruleset(model,
498
+ switch_over_time,
499
+ name = 'Radiant System Switchover',
500
+ sch_type_limit: 'Dimensionless')
501
+ end
502
+
503
+ # set radiant system switchover schedule
504
+ radiant_loop.setChangeoverDelayTimePeriodSchedule(sch_radiant_switchover.to_Schedule.get)
505
+
506
+ if slab_setpoint_oa_control
507
+ # get weather file from model
508
+ weather_file = model.getWeatherFile
509
+ if weather_file.initialized
510
+ # get annual outdoor dry bulb temperature
511
+ annual_oat = weather_file.file.get.data.collect { |dat| dat.dryBulbTemperature.get }
512
+
513
+ # calculate a nhrs rolling average from annual outdoor dry bulb temperature
514
+ nhrs = 24
515
+ last_nhrs_oat_in_year = annual_oat.last(nhrs - 1)
516
+ combined_oat = last_nhrs_oat_in_year + annual_oat
517
+ oat_rolling_average = combined_oat.each_cons(nhrs).map { |e| e.reduce(&:+).fdiv(nhrs).round(2) }
518
+
519
+ # use rolling average to calculate slab setpoint temperature
520
+
521
+ # convert temperature from IP to SI units
522
+ slab_sp_at_oat_low_si = OpenStudio.convert(slab_sp_at_oat_low, 'F', 'C').get
523
+ slab_oat_low_si = OpenStudio.convert(slab_oat_low, 'F', 'C').get
524
+ slab_sp_at_oat_high_si = OpenStudio.convert(slab_sp_at_oat_high, 'F', 'C').get
525
+ slab_oat_high_si = OpenStudio.convert(slab_oat_high, 'F', 'C').get
526
+
527
+ # calculate relationship between slab setpoint and slope
528
+ slope_num = slab_sp_at_oat_high_si - slab_sp_at_oat_low_si
529
+ slope_den = slab_oat_high_si - slab_oat_low_si
530
+ sp_and_oat_slope = slope_num.fdiv(slope_den).round(4)
531
+
532
+ slab_setpoint = oat_rolling_average.map { |e| (slab_sp_at_oat_low_si + ((e - slab_oat_low_si) * sp_and_oat_slope)).round(1) }
533
+
534
+ # input upper limits on slab setpoint
535
+ slab_sp_upper_limit = [slab_sp_at_oat_high_si, slab_sp_at_oat_low_si].max
536
+ slab_sp_lower_limit = [slab_sp_at_oat_high_si, slab_sp_at_oat_low_si].min
537
+ slab_setpoint.map! { |e| e > slab_sp_upper_limit ? slab_sp_upper_limit.round(1) : e }
538
+
539
+ # input lower limits on slab setpoint
540
+ slab_setpoint.map! { |e| e < slab_sp_lower_limit ? slab_sp_lower_limit.round(1) : e }
541
+
542
+ # create ruleset for slab setpoint
543
+ sch_type_limits_obj = model_add_schedule_type_limits(model, standard_sch_type_limit: 'Temperature')
544
+ sch_radiant_slab_setp = make_ruleset_sched_from_8760(model, slab_setpoint,
545
+ 'Sch_Radiant_SlabSetP_Based_On_Rolling_Mean_OAT',
546
+ sch_type_limits_obj)
547
+
548
+ coil_heating_radiant.setHeatingControlTemperatureSchedule(sch_radiant_slab_setp)
549
+ coil_cooling_radiant.setCoolingControlTemperatureSchedule(sch_radiant_slab_setp)
550
+ else
551
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.Model.Model',
552
+ 'Model does not have a weather file associated with it. Define to implement slab setpoint based on outdoor weather.')
553
+ end
554
+ else
555
+ # radiant system cooling control setpoint
556
+ slab_setpoint = 22
557
+ sch_radiant_clgsetp = model_add_constant_schedule_ruleset(model,
558
+ slab_setpoint + 0.1,
559
+ name = "#{zone_name}_Sch_Radiant_ClgSetP")
560
+ coil_cooling_radiant.setCoolingControlTemperatureSchedule(sch_radiant_clgsetp)
561
+
562
+ # radiant system heating control setpoint
563
+ sch_radiant_htgsetp = model_add_constant_schedule_ruleset(model,
564
+ slab_setpoint,
565
+ name = "#{zone_name}_Sch_Radiant_HtgSetP")
566
+ coil_heating_radiant.setHeatingControlTemperatureSchedule(sch_radiant_htgsetp)
567
+ end
709
568
  end
710
569
  end