openstudio-standards 0.2.17.rc2 → 0.3.1.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (233) hide show
  1. checksums.yaml +4 -4
  2. data/data/geometry/ASHRAESuperMarket.json +29 -38
  3. data/data/standards/OpenStudio_Standards-deer-ALL-comstock(space_types).xlsx +0 -0
  4. data/data/standards/metadata_units_OpenStudio_Standards-deer-ALL-comstockspace_types.csv +172 -0
  5. data/data/standards/test_performance_expected_dd_results.csv +12 -12
  6. data/lib/openstudio-standards/btap/analysis.rb +389 -389
  7. data/lib/openstudio-standards/btap/bridging.rb +2099 -0
  8. data/lib/openstudio-standards/btap/btap.model.rb +717 -717
  9. data/lib/openstudio-standards/btap/btap.rb +33 -30
  10. data/lib/openstudio-standards/btap/economics.rb +1163 -1163
  11. data/lib/openstudio-standards/btap/envelope.rb +4 -4
  12. data/lib/openstudio-standards/btap/equest.rb +2524 -2524
  13. data/lib/openstudio-standards/btap/fileio.rb +9 -0
  14. data/lib/openstudio-standards/btap/measures.rb +1515 -1515
  15. data/lib/openstudio-standards/btap/mpc.rb +554 -554
  16. data/lib/openstudio-standards/btap/reporting.rb +287 -287
  17. data/lib/openstudio-standards/btap/simmanager.rb +759 -759
  18. data/lib/openstudio-standards/btap/spaceloads.rb +439 -439
  19. data/lib/openstudio-standards/btap/spacetypes.rb +113 -113
  20. data/lib/openstudio-standards/btap/utilities.rb +134 -134
  21. data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVAC.rb +8 -83
  22. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingWater.rb +3 -99
  23. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +81 -75
  24. data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +7 -306
  25. data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +70 -98
  26. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +41 -14
  27. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +40 -14
  28. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperMarket.rb +1 -23
  29. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.exterior_lights.rb +7 -7
  30. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +5 -1
  31. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +101 -4
  32. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +16 -1
  33. data/lib/openstudio-standards/prototypes/common/objects/Prototype.refrigeration.rb +5 -4
  34. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +24 -4
  35. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +18 -2
  36. data/lib/openstudio-standards/standards/Standards.BoilerHotWater.rb +18 -0
  37. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +13 -10
  38. data/lib/openstudio-standards/standards/Standards.CoilDX.rb +5 -3
  39. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +11 -8
  40. data/lib/openstudio-standards/standards/Standards.Construction.rb +1 -1
  41. data/lib/openstudio-standards/standards/Standards.Model.rb +68 -52
  42. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +2 -2
  43. data/lib/openstudio-standards/standards/Standards.Space.rb +16 -18
  44. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +1 -1
  45. data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +5 -5
  46. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.ref_cases.json +510 -0
  47. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.refrigeration_compressors.json +18 -0
  48. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.refrigeration_walkins.json +410 -0
  49. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.spc_typ.json +2 -2
  50. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.ref_cases.json +510 -0
  51. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.refrigeration_compressors.json +18 -0
  52. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.refrigeration_walkins.json +410 -0
  53. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.spc_typ.json +2 -2
  54. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.ref_cases.json +510 -0
  55. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.refrigeration_compressors.json +18 -0
  56. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.refrigeration_walkins.json +410 -0
  57. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.spc_typ.json +2 -2
  58. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.ref_cases.json +510 -0
  59. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.refrigeration_compressors.json +18 -0
  60. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.refrigeration_walkins.json +410 -0
  61. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.spc_typ.json +2 -2
  62. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.spc_typ.json +2 -2
  63. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.spc_typ.json +2 -2
  64. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.entryways.json +13 -2
  65. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.parking.json +11 -2
  66. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +9 -0
  67. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +2 -0
  68. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +4 -3
  69. data/lib/openstudio-standards/standards/deer/deer_1985/comstock_deer_1985/data/comstock_deer_1985.spc_typ.json +405 -405
  70. data/lib/openstudio-standards/standards/deer/deer_1996/comstock_deer_1996/data/comstock_deer_1996.spc_typ.json +405 -405
  71. data/lib/openstudio-standards/standards/deer/deer_2003/comstock_deer_2003/data/comstock_deer_2003.spc_typ.json +405 -405
  72. data/lib/openstudio-standards/standards/deer/deer_2003/deer_2003.ThermalZone.rb +21 -0
  73. data/lib/openstudio-standards/standards/deer/deer_2007/comstock_deer_2007/data/comstock_deer_2007.spc_typ.json +405 -405
  74. data/lib/openstudio-standards/standards/deer/deer_2007/deer_2007.ThermalZone.rb +21 -0
  75. data/lib/openstudio-standards/standards/deer/deer_2011/comstock_deer_2011/data/comstock_deer_2011.spc_typ.json +405 -405
  76. data/lib/openstudio-standards/standards/deer/deer_2011/deer_2011.ThermalZone.rb +21 -0
  77. data/lib/openstudio-standards/standards/deer/deer_2014/comstock_deer_2014/data/comstock_deer_2014.spc_typ.json +405 -405
  78. data/lib/openstudio-standards/standards/deer/deer_2014/deer_2014.ThermalZone.rb +21 -0
  79. data/lib/openstudio-standards/standards/deer/deer_2015/comstock_deer_2015/data/comstock_deer_2015.spc_typ.json +405 -405
  80. data/lib/openstudio-standards/standards/deer/deer_2015/deer_2015.ThermalZone.rb +21 -0
  81. data/lib/openstudio-standards/standards/deer/deer_2017/comstock_deer_2017/data/comstock_deer_2017.spc_typ.json +405 -405
  82. data/lib/openstudio-standards/standards/deer/deer_2017/deer_2017.ThermalZone.rb +21 -0
  83. data/lib/openstudio-standards/standards/deer/deer_2020/comstock_deer_2020/data/comstock_deer_2020.spc_typ.json +405 -405
  84. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.AirLoopHVAC.rb +8 -0
  85. data/lib/openstudio-standards/standards/deer/deer_2020/deer_2020.ThermalZone.rb +21 -0
  86. data/lib/openstudio-standards/standards/deer/deer_2025/comstock_deer_2025/data/comstock_deer_2025.spc_typ.json +405 -405
  87. data/lib/openstudio-standards/standards/deer/deer_2030/comstock_deer_2030/data/comstock_deer_2030.spc_typ.json +405 -405
  88. data/lib/openstudio-standards/standards/deer/deer_2035/comstock_deer_2035/data/comstock_deer_2035.spc_typ.json +405 -405
  89. data/lib/openstudio-standards/standards/deer/deer_2040/comstock_deer_2040/data/comstock_deer_2040.spc_typ.json +405 -405
  90. data/lib/openstudio-standards/standards/deer/deer_2045/comstock_deer_2045/data/comstock_deer_2045.spc_typ.json +405 -405
  91. data/lib/openstudio-standards/standards/deer/deer_2050/comstock_deer_2050/data/comstock_deer_2050.spc_typ.json +405 -405
  92. data/lib/openstudio-standards/standards/deer/deer_2055/comstock_deer_2055/data/comstock_deer_2055.spc_typ.json +405 -405
  93. data/lib/openstudio-standards/standards/deer/deer_2060/comstock_deer_2060/data/comstock_deer_2060.spc_typ.json +405 -405
  94. data/lib/openstudio-standards/standards/deer/deer_2065/comstock_deer_2065/data/comstock_deer_2065.spc_typ.json +405 -405
  95. data/lib/openstudio-standards/standards/deer/deer_2070/comstock_deer_2070/data/comstock_deer_2070.spc_typ.json +405 -405
  96. data/lib/openstudio-standards/standards/deer/deer_2075/comstock_deer_2075/data/comstock_deer_2075.spc_typ.json +405 -405
  97. data/lib/openstudio-standards/standards/deer/deer_pre_1975/comstock_deer_pre_1975/data/comstock_deer_pre_1975.spc_typ.json +405 -405
  98. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/btap_pre1980.rb +1 -1
  99. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_3_and_8_single_speed.rb +3 -1
  100. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_4.rb +3 -1
  101. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +2 -2
  102. data/lib/openstudio-standards/standards/necb/ECMS/data/curves.json +233 -0
  103. data/lib/openstudio-standards/standards/necb/ECMS/data/unitary_acs.json +180 -0
  104. data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +6 -1
  105. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +807 -258
  106. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +102 -66
  107. data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +85 -8
  108. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/HighriseApartment.osm +2483 -992
  109. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LowriseApartment.osm +4 -336
  110. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/MidriseApartment.osm +228 -231
  111. data/lib/openstudio-standards/standards/necb/NECB2011/data/heat_pumps_heating.json +12 -18
  112. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_type_unit_definitions.txt +76 -0
  113. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_multi_speed.rb +6 -1
  114. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_single_speed.rb +111 -24
  115. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_2_and_5.rb +1 -0
  116. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +3 -1
  117. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +64 -16
  118. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +61 -17
  119. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +128 -0
  120. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +252 -23
  121. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +316 -20
  122. data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +1 -1
  123. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +4 -6
  124. data/lib/openstudio-standards/standards/necb/NECB2011/system_fuels.rb +38 -0
  125. data/lib/openstudio-standards/standards/necb/NECB2015/data/heat_pumps_heating.json +16 -24
  126. data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +48 -25
  127. data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +3 -3
  128. data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +36 -19
  129. data/lib/openstudio-standards/standards/necb/NECB2020/data/furnaces.json +19 -4
  130. data/lib/openstudio-standards/standards/necb/NECB2020/data/heat_pumps.json +20 -40
  131. data/lib/openstudio-standards/standards/necb/NECB2020/data/heat_pumps_heating.json +74 -36
  132. data/lib/openstudio-standards/standards/necb/NECB2020/necb_2020.rb +0 -2
  133. data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +124 -57
  134. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +124 -2
  135. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +15 -2
  136. data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +1 -1
  137. data/lib/openstudio-standards/utilities/simulation.rb +1 -1
  138. data/lib/openstudio-standards/version.rb +1 -1
  139. data/lib/openstudio-standards/weather/Weather.Model.rb +5 -0
  140. data/lib/openstudio-standards/weather/Weather.stat_file.rb +33 -1
  141. data/lib/openstudio-standards.rb +1 -0
  142. metadata +14 -121
  143. data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
  144. data/data/weather/CAN_ON_Kingston.AP.718200_TMYx.2004-2018.ddy +0 -2342
  145. data/data/weather/CAN_ON_Kingston.AP.718200_TMYx.2004-2018.epw +0 -8768
  146. data/data/weather/CAN_ON_Kingston.AP.718200_TMYx.2004-2018.stat +0 -700
  147. data/data/weather/CAN_ON_Region.of.Waterloo.Intl.AP.713680_TMYx.2004-2018.ddy +0 -2342
  148. data/data/weather/CAN_ON_Region.of.Waterloo.Intl.AP.713680_TMYx.2004-2018.epw +0 -8768
  149. data/data/weather/CAN_ON_Region.of.Waterloo.Intl.AP.713680_TMYx.2004-2018.stat +0 -700
  150. data/data/weather/CAN_ON_Sarnia-Hadfield.AP.717040_TMYx.2004-2018.ddy +0 -2342
  151. data/data/weather/CAN_ON_Sarnia-Hadfield.AP.717040_TMYx.2004-2018.epw +0 -8768
  152. data/data/weather/CAN_ON_Sarnia-Hadfield.AP.717040_TMYx.2004-2018.stat +0 -700
  153. data/data/weather/CAN_QC_Gatineau.AP.716279_TMYx.2004-2018.ddy +0 -276
  154. data/data/weather/CAN_QC_Gatineau.AP.716279_TMYx.2004-2018.epw +0 -8768
  155. data/data/weather/CAN_QC_Gatineau.AP.716279_TMYx.2004-2018.stat +0 -611
  156. data/data/weather/CAN_QC_Granby.710367_TMYx.2004-2018.ddy +0 -276
  157. data/data/weather/CAN_QC_Granby.710367_TMYx.2004-2018.epw +0 -8768
  158. data/data/weather/CAN_QC_Granby.710367_TMYx.2004-2018.stat +0 -610
  159. data/data/weather/CAN_QC_Sherbrooke.AP.716100_TMYx.2004-2018.ddy +0 -2342
  160. data/data/weather/CAN_QC_Sherbrooke.AP.716100_TMYx.2004-2018.epw +0 -8768
  161. data/data/weather/CAN_QC_Sherbrooke.AP.716100_TMYx.2004-2018.stat +0 -700
  162. data/data/weather/CAN_QC_Trois.Rivieres.717240_TMYx.2004-2018.ddy +0 -2342
  163. data/data/weather/CAN_QC_Trois.Rivieres.717240_TMYx.2004-2018.epw +0 -8768
  164. data/data/weather/CAN_QC_Trois.Rivieres.717240_TMYx.2004-2018.stat +0 -700
  165. data/lib/openstudio-standards/hvac_sizing/Siz.AirConditionerVariableRefrigerantFlow.rb +0 -81
  166. data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVACUnitaryHeatCoolVAVChngByp.rb +0 -27
  167. data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVACUnitaryHeatPumpAirToAir.rb +0 -69
  168. data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed.rb +0 -178
  169. data/lib/openstudio-standards/hvac_sizing/Siz.AirLoopHVACUnitarySystem.rb +0 -27
  170. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctConstVolCooledBeam.rb +0 -27
  171. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctConstVolFourPipeInduction.rb +0 -27
  172. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctConstVolReheat.rb +0 -27
  173. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctParallelPIUReheat.rb +0 -67
  174. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctSeriesPIUReheat.rb +0 -27
  175. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctUncontrolled.rb +0 -30
  176. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctVAVHeatAndCoolNoReheat.rb +0 -27
  177. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctVAVHeatAndCoolReheat.rb +0 -27
  178. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctVAVNoReheat.rb +0 -68
  179. data/lib/openstudio-standards/hvac_sizing/Siz.AirTermSnglDuctVAVReheat.rb +0 -68
  180. data/lib/openstudio-standards/hvac_sizing/Siz.BoilerHotWater.rb +0 -42
  181. data/lib/openstudio-standards/hvac_sizing/Siz.BoilerSteam.rb +0 -27
  182. data/lib/openstudio-standards/hvac_sizing/Siz.ChillerElectricEIR.rb +0 -58
  183. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingDXMultiSpeed.rb +0 -171
  184. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingDXSingleSpeed.rb +0 -56
  185. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingDXTwoSpeed.rb +0 -89
  186. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingDXVariableRefrigerantFlow.rb +0 -50
  187. data/lib/openstudio-standards/hvac_sizing/Siz.CoilCoolingWaterToAirHeatPumpEquationFit.rb +0 -69
  188. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingDXMultiSpeed.rb +0 -120
  189. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingDXSingleSpeed.rb +0 -56
  190. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingDXVariableRefrigerantFlow.rb +0 -41
  191. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingDesuperheater.rb +0 -27
  192. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingElectric.rb +0 -30
  193. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingGas.rb +0 -30
  194. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingGasMultiStage.rb +0 -68
  195. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingWater.rb +0 -61
  196. data/lib/openstudio-standards/hvac_sizing/Siz.CoilHeatingWaterToAirHeatPumpEquationFit.rb +0 -57
  197. data/lib/openstudio-standards/hvac_sizing/Siz.CoilWaterHeatingDesuperheater.rb +0 -27
  198. data/lib/openstudio-standards/hvac_sizing/Siz.ControllerOutdoorAir.rb +0 -59
  199. data/lib/openstudio-standards/hvac_sizing/Siz.ControllerWaterCoil.rb +0 -49
  200. data/lib/openstudio-standards/hvac_sizing/Siz.CoolingTowerSingleSpeed.rb +0 -90
  201. data/lib/openstudio-standards/hvac_sizing/Siz.CoolingTowerTwoSpeed.rb +0 -83
  202. data/lib/openstudio-standards/hvac_sizing/Siz.CoolingTowerVariableSpeed.rb +0 -57
  203. data/lib/openstudio-standards/hvac_sizing/Siz.DistrictCooling.rb +0 -27
  204. data/lib/openstudio-standards/hvac_sizing/Siz.DistrictHeating.rb +0 -27
  205. data/lib/openstudio-standards/hvac_sizing/Siz.EvaporativeCoolerDirectResearchSpecial.rb +0 -27
  206. data/lib/openstudio-standards/hvac_sizing/Siz.EvaporativeCoolerIndirectResearchSpecial.rb +0 -27
  207. data/lib/openstudio-standards/hvac_sizing/Siz.EvaporativeFluidCoolerSingleSpeed.rb +0 -27
  208. data/lib/openstudio-standards/hvac_sizing/Siz.FanConstantVolume.rb +0 -29
  209. data/lib/openstudio-standards/hvac_sizing/Siz.FanOnOff.rb +0 -27
  210. data/lib/openstudio-standards/hvac_sizing/Siz.FanVariableVolume.rb +0 -29
  211. data/lib/openstudio-standards/hvac_sizing/Siz.HeaderedPumpsConstantSpeed.rb +0 -55
  212. data/lib/openstudio-standards/hvac_sizing/Siz.HeaderedPumpsVariableSpeed.rb +0 -55
  213. data/lib/openstudio-standards/hvac_sizing/Siz.HeatExchangerAirToAirSensibleAndLatent.rb +0 -38
  214. data/lib/openstudio-standards/hvac_sizing/Siz.HeatExchangerFluidToFluid.rb +0 -27
  215. data/lib/openstudio-standards/hvac_sizing/Siz.HumidifierSteamElectric.rb +0 -27
  216. data/lib/openstudio-standards/hvac_sizing/Siz.PlantLoop.rb +0 -42
  217. data/lib/openstudio-standards/hvac_sizing/Siz.PumpConstantSpeed.rb +0 -59
  218. data/lib/openstudio-standards/hvac_sizing/Siz.PumpVariableSpeed.rb +0 -59
  219. data/lib/openstudio-standards/hvac_sizing/Siz.SizingSystem.rb +0 -48
  220. data/lib/openstudio-standards/hvac_sizing/Siz.WaterHeaterMixed.rb +0 -16
  221. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACBaseboardConvectiveElectric.rb +0 -27
  222. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACBaseboardConvectiveWater.rb +0 -27
  223. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACFourPipeFanCoil.rb +0 -27
  224. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACHighTemperatureRadiant.rb +0 -27
  225. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACIdealLoadsAirSystem.rb +0 -27
  226. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACLowTempRadiantConstFlow.rb +0 -27
  227. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACLowTempRadiantVarFlow.rb +0 -27
  228. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACLowTemperatureRadiantElectric.rb +0 -27
  229. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACPackagedTerminalAirConditioner.rb +0 -88
  230. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACPackagedTerminalHeatPump.rb +0 -88
  231. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACTerminalUnitVariableRefrigerantFlow.rb +0 -104
  232. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACUnitHeater.rb +0 -27
  233. data/lib/openstudio-standards/hvac_sizing/Siz.ZoneHVACWaterToAirHeatPump.rb +0 -27
@@ -460,6 +460,36 @@ class ECMS
460
460
  updated_system_zones_map[sys_name] += zones
461
461
  end
462
462
  end
463
+
464
+ return updated_system_zones_map
465
+ end
466
+
467
+ # =============================================================================================================================
468
+ # The first 5 letters of the air loop name designate the system type (sys_abbr). This method updates the system type designation
469
+ # in the air loop name. At the same time the chosen air loop names are checked to avoid duplicate names from being used in the
470
+ # hash for system to zomes.
471
+ def update_system_zones_map_keys(system_zones_map,sys_abbr)
472
+ updated_system_zones_map = {}
473
+ system_zones_map.sort.each do |sname,zones|
474
+ updated_sys_name = "#{sys_abbr}#{sname[5..-1]}"
475
+ if !updated_system_zones_map.has_key? updated_sys_name
476
+ updated_system_zones_map[updated_sys_name] = zones
477
+ else
478
+ updated_sys_name_set = false
479
+ index = 1
480
+ while !updated_sys_name_set
481
+ updated_sys_name = "#{sys_abbr}#{sname[5..-1]}"
482
+ updated_sys_name.chop! if updated_sys_name.split.size > 1
483
+ updated_sys_name = updated_sys_name + index.to_s
484
+ if !updated_system_zones_map.has_key? updated_sys_name
485
+ updated_sys_name_set = true
486
+ updated_system_zones_map[updated_sys_name] = zones
487
+ end
488
+ index += 1
489
+ end
490
+ end
491
+ end
492
+
463
493
  return updated_system_zones_map
464
494
  end
465
495
 
@@ -467,7 +497,7 @@ class ECMS
467
497
  # Add equipment for ECM 'hs08_ccashp_vrf':
468
498
  # -Constant-volume DOAS with air-source heat pump for heating and cooling and electric backup
469
499
  # -Zonal terminal VRF units connected to an outdoor VRF condenser unit
470
- # -Zonal electric backup
500
+ # -Zonal electric or hot-water backup
471
501
  def add_ecm_hs08_ccashp_vrf(
472
502
  model:,
473
503
  system_zones_map:,
@@ -477,16 +507,18 @@ class ECMS
477
507
  standard:,
478
508
  air_sys_eqpt_type: 'ccashp')
479
509
 
510
+ # Create one hot-water loop for hot-water baseboards if primary heating fuel is gas
511
+ hw_loop = nil
512
+ hw_loop = add_hotwater_loop(model: model) if heating_fuel == 'NaturalGas'
513
+
480
514
  # Update system zones map if needed
481
- if ecm_system_zones_map_option != 'NECB_Default'
482
- system_zones_map = update_system_zones_map(model,system_zones_map,ecm_system_zones_map_option,'sys_1')
483
- else
484
- updated_system_zones_map = {}
485
- system_zones_map.each {|sname,zones| updated_system_zones_map["sys_1#{sname[5..-1]}"] = zones} # doas unit is an NECB sys_1
486
- system_zones_map = updated_system_zones_map
487
- end
515
+ system_zones_map = update_system_zones_map_keys(system_zones_map,'sys_1')
516
+ system_zones_map = update_system_zones_map(model,system_zones_map,ecm_system_zones_map_option,'sys_1') if ecm_system_zones_map_option != 'NECB_Default'
488
517
  # Add outdoor VRF unit
489
518
  outdoor_vrf_unit = add_outdoor_vrf_unit(model: model, ecm_name: 'hs08_ccashp_vrf')
519
+ eqpt_name = 'Mitsubishi_Hyper_Heating_VRF_Outdoor_Unit'
520
+ airconditioner_variablerefrigerantflow_cooling_apply_curves(outdoor_vrf_unit,eqpt_name)
521
+ airconditioner_variablerefrigerantflow_heating_apply_curves(outdoor_vrf_unit,eqpt_name)
490
522
  # Update system doas flags
491
523
  system_doas_flags = {}
492
524
  system_zones_map.keys.each { |sname| system_doas_flags[sname] = true }
@@ -504,7 +536,7 @@ class ECMS
504
536
  system_doas_flags: system_doas_flags)
505
537
  sys_supp_htg_eqpt_type = 'coil_electric'
506
538
  sys_supp_htg_eqpt_type = 'coil_gas' if updated_heating_fuel == 'NaturalGas'
507
- airloop, return_fan = add_air_system(model: model,
539
+ airloop,clg_dx_coil,htg_dx_coil,return_fan = add_air_system(model: model,
508
540
  zones: zones,
509
541
  sys_abbr: sys_info['sys_abbr'],
510
542
  sys_vent_type: sys_info['sys_vent_type'],
@@ -515,27 +547,17 @@ class ECMS
515
547
  sys_supp_fan_type: sys_info['sys_supp_fan_type'],
516
548
  sys_ret_fan_type: sys_info['sys_ret_fan_type'],
517
549
  sys_setpoint_mgr_type: sys_info['sys_setpoint_mgr_type'])
518
- # get and assign defrost curve
519
- dx_htg_coil = nil
520
- airloop.supplyComponents.sort.each do |comp|
521
- if comp.to_CoilHeatingDXSingleSpeed.is_initialized
522
- dx_htg_coil = comp.to_CoilHeatingDXSingleSpeed.get
523
- elsif comp.to_CoilHeatingDXVariableSpeed.is_initialized
524
- dx_htg_coil = comp.to_CoilHeatingDXVariableSpeed.get
525
- end
526
- end
527
- search_criteria = {}
550
+ # Appy performance curves
528
551
  if air_sys_eqpt_type == 'ccashp'
529
- search_criteria['name'] = 'Mitsubishi_Hyper_Heating_VRF_Outdoor_Unit RTU'
552
+ eqpt_name = 'Mitsubishi_Hyper_Heating_VRF_Outdoor_Unit RTU'
553
+ coil_cooling_dx_variable_speed_apply_curves(clg_dx_coil, eqpt_name)
554
+ coil_heating_dx_variable_speed_apply_curves(htg_dx_coil, eqpt_name)
530
555
  elsif air_sys_eqpt_type == 'ashp'
531
- search_criteria['name'] = 'NECB2015_ASHP'
532
- end
533
- props = model_find_object(standards_data['tables']['heat_pump_heating_ecm']['table'], search_criteria, 1.0)
534
- heat_defrost_eir_ft = model_add_curve(model, props['heat_defrost_eir_ft'])
535
- if heat_defrost_eir_ft
536
- dx_htg_coil.setDefrostEnergyInputRatioFunctionofTemperatureCurve(heat_defrost_eir_ft)
556
+ eqpt_name = 'NECB2015_ASHP'
557
+ coil_cooling_dx_single_speed_apply_curves(clg_dx_coil, eqpt_name)
558
+ coil_heating_dx_single_speed_apply_curves(htg_dx_coil, eqpt_name)
537
559
  else
538
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDX', "For #{dx_htg_coil.name}, cannot find heat_defrost_eir_ft curve, will not be set.")
560
+ raise("add_ecm_hs08_ccashp_vrf: The air system equipment type is neither an ashp nor a ccashp")
539
561
  end
540
562
  # add zone equipment and diffuser
541
563
  # add terminal VRF units
@@ -547,17 +569,22 @@ class ECMS
547
569
  zone_htg_eqpt_type: 'vrf',
548
570
  zone_supp_htg_eqpt_type: 'none',
549
571
  zone_clg_eqpt_type: 'vrf',
550
- zone_fan_type: 'On_Off')
551
- # add electric baseboards for backup
572
+ zone_fan_type: 'On_Off',
573
+ hw_loop: hw_loop)
574
+ # add electric or hot-water baseboards for backup; Type of baseboard follows the primary heating fuel used in the building model.
575
+ zone_htg_eqpt_type = 'baseboard_hotwater' if heating_fuel == 'NaturalGas'
576
+ zone_htg_eqpt_type = 'baseboard_electric' if heating_fuel == 'Electricity'
577
+
552
578
  add_zone_eqpt(model: model,
553
579
  airloop: airloop,
554
580
  zones: zones,
555
581
  outdoor_unit: nil,
556
582
  zone_diffuser_type: nil,
557
- zone_htg_eqpt_type: 'baseboard_electric',
583
+ zone_htg_eqpt_type: zone_htg_eqpt_type,
558
584
  zone_supp_htg_eqpt_type: 'none',
559
585
  zone_clg_eqpt_type: 'none',
560
- zone_fan_type: 'none')
586
+ zone_fan_type: 'none',
587
+ hw_loop: hw_loop)
561
588
  # Now we can find and apply maximum horizontal and vertical distances between outdoor vrf unit and zones with vrf terminal units
562
589
  max_hor_pipe_length, max_vert_pipe_length = get_max_vrf_pipe_lengths(model)
563
590
  outdoor_vrf_unit.setEquivalentPipingLengthusedforPipingCorrectionFactorinCoolingMode(max_hor_pipe_length)
@@ -567,7 +594,7 @@ class ECMS
567
594
  end
568
595
 
569
596
  # =============================================================================================================================
570
- # Apply efficiencies and performance curves for ECM 'hs08_ccashp_vrf'
597
+ # Apply efficiencies for ECM 'hs08_ccashp_vrf'
571
598
  def apply_efficiency_ecm_hs08_ccashp_vrf(model, air_sys_eqpt_type: 'ccashp')
572
599
  # Use same performance data as ECM 'hs09_ccashpsys' for air system
573
600
  if air_sys_eqpt_type == 'ccashp'
@@ -575,11 +602,13 @@ class ECMS
575
602
  elsif air_sys_eqpt_type == 'ashp'
576
603
  apply_efficiency_ecm_hs12_ashp_baseboard(model)
577
604
  end
578
- # Apply efficiency and curves for VRF units
605
+ # Apply efficiency for VRF units
579
606
  eqpt_name = 'Mitsubishi_Hyper_Heating_VRF_Outdoor_Unit'
607
+ search_criteria = {}
608
+ search_criteria['name'] = eqpt_name
580
609
  model.getAirConditionerVariableRefrigerantFlows.sort.each do |vrf_unit|
581
- airconditioner_variablerefrigerantflow_cooling_apply_efficiency_and_curves(vrf_unit, eqpt_name)
582
- airconditioner_variablerefrigerantflow_heating_apply_efficiency_and_curves(vrf_unit, eqpt_name)
610
+ airconditioner_variablerefrigerantflow_cooling_apply_cop(vrf_unit, search_criteria)
611
+ airconditioner_variablerefrigerantflow_heating_apply_cop(vrf_unit, search_criteria)
583
612
  end
584
613
  # Set fan size of VRF terminal units
585
614
  fan_power_per_flow_rate = 150.0 # based on Mitsubishi data: 100 low and 200 high (W-s/m3)
@@ -594,6 +623,7 @@ class ECMS
594
623
  fan_pr_rise = fan_power_per_flow_rate * (fan.fanEfficiency * fan.motorEfficiency)
595
624
  fan.setPressureRise(fan_pr_rise)
596
625
  end
626
+
597
627
  end
598
628
 
599
629
  # =============================================================================================================================
@@ -622,8 +652,8 @@ class ECMS
622
652
  airloop.sizingSystem.setAllOutdoorAirinCooling(true)
623
653
  airloop.sizingSystem.setAllOutdoorAirinHeating(true)
624
654
  airloop.sizingSystem.setTypeofLoadtoSizeOn('VentilationRequirement')
625
- airloop.sizingSystem.setCentralCoolingDesignSupplyAirTemperature(19.9)
626
- airloop.sizingSystem.setCentralHeatingDesignSupplyAirTemperature(20.0)
655
+ airloop.sizingSystem.setCentralCoolingDesignSupplyAirTemperature(13.0)
656
+ airloop.sizingSystem.setCentralHeatingDesignSupplyAirTemperature(22.0)
627
657
  when 'mixed'
628
658
  airloop.sizingSystem.setAllOutdoorAirinCooling(false)
629
659
  airloop.sizingSystem.setAllOutdoorAirinHeating(false)
@@ -637,7 +667,9 @@ class ECMS
637
667
 
638
668
  # =============================================================================================================================
639
669
  # create air system setpoint manager
640
- def create_air_sys_spm(model, setpoint_mgr_type, zones)
670
+ def create_air_sys_spm(model,
671
+ setpoint_mgr_type,
672
+ zones)
641
673
  spm = nil
642
674
  case setpoint_mgr_type.downcase
643
675
  when 'scheduled'
@@ -653,7 +685,7 @@ class ECMS
653
685
  when 'warmest'
654
686
  spm = OpenStudio::Model::SetpointManagerWarmest.new(model)
655
687
  spm.setMinimumSetpointTemperature(13.0)
656
- spm.setMaximumSetpointTemperature(43.0)
688
+ spm.setMaximumSetpointTemperature(22.0)
657
689
  end
658
690
 
659
691
  return spm
@@ -694,6 +726,9 @@ class ECMS
694
726
  clg_eqpt.addSpeed(clg_eqpt_speed1)
695
727
  clg_eqpt.setNominalSpeedLevel(1)
696
728
  clg_eqpt.setCrankcaseHeaterCapacity(1.0e-6)
729
+ when 'coil_chw'
730
+ clg_eqpt = OpenStudio::Model::CoilCoolingWater.new(model)
731
+ clg_eqpt.setName('CoilCoolingWater')
697
732
  when 'vrf'
698
733
  clg_eqpt = OpenStudio::Model::CoilCoolingDXVariableRefrigerantFlow.new(model)
699
734
  clg_eqpt.setName('CoilCoolingDXVariableRefrigerantFlow')
@@ -730,6 +765,9 @@ class ECMS
730
765
  htg_eqpt.setDefrostStrategy('ReverseCycle')
731
766
  htg_eqpt.setDefrostControl('OnDemand')
732
767
  htg_eqpt.setCrankcaseHeaterCapacity(1.0e-6)
768
+ when 'coil_hw'
769
+ htg_eqpt = OpenStudio::Model::CoilHeatingWater.new(model)
770
+ htg_eqpt.setName('CoilHeatingWater')
733
771
  end
734
772
 
735
773
  return htg_eqpt
@@ -737,19 +775,17 @@ class ECMS
737
775
 
738
776
  # =============================================================================================================================
739
777
  # add air system with all its components
740
- def add_air_system(
741
- model:,
742
- zones:,
743
- sys_abbr:,
744
- sys_vent_type:,
745
- sys_heat_rec_type:,
746
- sys_htg_eqpt_type:,
747
- sys_supp_htg_eqpt_type:,
748
- sys_clg_eqpt_type:,
749
- sys_supp_fan_type:,
750
- sys_ret_fan_type:,
751
- sys_setpoint_mgr_type:
752
- )
778
+ def add_air_system(model:,
779
+ zones:,
780
+ sys_abbr:,
781
+ sys_vent_type:,
782
+ sys_heat_rec_type:,
783
+ sys_htg_eqpt_type:,
784
+ sys_supp_htg_eqpt_type:,
785
+ sys_clg_eqpt_type:,
786
+ sys_supp_fan_type:,
787
+ sys_ret_fan_type:,
788
+ sys_setpoint_mgr_type:)
753
789
 
754
790
  # create all the needed components and the air loop
755
791
  airloop = create_airloop(model, sys_vent_type)
@@ -787,7 +823,7 @@ class ECMS
787
823
  sys_name_pars['sys_rf'] = 'cv' if sys_ret_fan_type == 'constant_volume'
788
824
  sys_name_pars['sys_rf'] = 'vv' if sys_ret_fan_type == 'variable_volume'
789
825
  assign_base_sys_name(airloop, sys_abbr: sys_abbr, sys_oa: sys_vent_type, sys_name_pars: sys_name_pars)
790
- return airloop, return_fan
826
+ return airloop, clg_eqpt, htg_eqpt, return_fan
791
827
  end
792
828
 
793
829
  # =============================================================================================================================
@@ -811,18 +847,27 @@ class ECMS
811
847
 
812
848
  # =============================================================================================================================
813
849
  # create zonal heating equipment
814
- def create_zone_htg_eqpt(model, zone_htg_eqpt_type)
850
+ def create_zone_htg_eqpt(model, zone_htg_eqpt_type, hw_loop)
815
851
  always_on = model.alwaysOnDiscreteSchedule
816
852
  always_off = model.alwaysOffDiscreteSchedule
817
853
  htg_eqpt = nil
818
854
  case zone_htg_eqpt_type.downcase
819
855
  when 'baseboard_electric'
820
856
  htg_eqpt = OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.new(model)
821
- htg_eqpt.setName('Zone HVAC Baseboard Convective Electric')
857
+ htg_eqpt.setName('ZoneHVACBaseboardConvectiveElectric')
858
+ when 'baseboard_hotwater'
859
+ htg_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model)
860
+ htg_coil.setName("CoilHeatingWaterBaseboard")
861
+ hw_loop.addDemandBranchForComponent(htg_coil)
862
+ htg_eqpt = OpenStudio::Model::ZoneHVACBaseboardConvectiveWater.new(model, model.alwaysOnDiscreteSchedule, htg_coil)
863
+ htg_eqpt.setName('ZoneHVACBaseboardConvectiveWater')
822
864
  when 'coil_electric', 'ptac_electric_off', 'unitheater_electric'
823
865
  htg_eqpt = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
824
866
  htg_eqpt.setName('CoilHeatingElectric')
825
867
  htg_eqpt.setAvailabilitySchedule(always_off) if zone_htg_eqpt_type == 'ptac_electric_off'
868
+ when 'fancoil_4pipe'
869
+ htg_eqpt = OpenStudio::Model::CoilHeatingWater.new(model)
870
+ htg_eqpt.setName('CoilHeatingWater_FanCoil')
826
871
  when 'pthp'
827
872
  htg_eqpt = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model)
828
873
  htg_eqpt.setName('CoilHeatingDXSingleSpeed_PTHP')
@@ -843,6 +888,9 @@ class ECMS
843
888
  always_on = model.alwaysOnDiscreteSchedule
844
889
  clg_eqpt = nil
845
890
  case zone_clg_eqpt_type.downcase
891
+ when 'fancoil_4pipe'
892
+ clg_eqpt = OpenStudio::Model::CoilCoolingWater.new(model)
893
+ clg_eqpt.setName('CoilCoolingWater_FanCoil')
846
894
  when 'ptac_electric_off', 'pthp'
847
895
  clg_eqpt = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model)
848
896
  clg_eqpt.setName('CoilCoolingDXSingleSpeed_PTHP') if zone_clg_eqpt_type.downcase == 'pthp'
@@ -858,20 +906,23 @@ class ECMS
858
906
 
859
907
  # =============================================================================================================================
860
908
  # create zpne container eqpt
861
- def create_zone_container_eqpt(
862
- model:,
863
- zone_cont_eqpt_type:,
864
- zone_htg_eqpt:,
865
- zone_supp_htg_eqpt:,
866
- zone_clg_eqpt:,
867
- zone_fan:,
868
- zone_vent_off: true
869
- )
909
+ def create_zone_container_eqpt(model:,
910
+ zone_cont_eqpt_type:,
911
+ zone_htg_eqpt:,
912
+ zone_supp_htg_eqpt:,
913
+ zone_clg_eqpt:,
914
+ zone_fan:,
915
+ zone_vent_off: true)
870
916
 
871
917
  always_on = model.alwaysOnDiscreteSchedule
872
918
  always_off = model.alwaysOffDiscreteSchedule
873
919
  zone_eqpt = nil
874
920
  case zone_cont_eqpt_type.downcase
921
+ when 'fancoil_4pipe'
922
+ zone_eqpt = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(model, always_on, zone_fan, zone_clg_eqpt, zone_htg_eqpt)
923
+ zone_eqpt.setName('ZoneHVACFourPipeFanCoil')
924
+ zone_eqpt.setSupplyAirFanOperatingModeSchedule(always_off)
925
+ zone_eqpt.setMaximumOutdoorAirFlowRate(1.0e-6)
875
926
  when 'ptac_electric_off'
876
927
  zone_eqpt = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(model, always_on, zone_fan, zone_htg_eqpt, zone_clg_eqpt)
877
928
  zone_eqpt.setName('ZoneHVACPackagedTerminalAirConditioner')
@@ -919,7 +970,8 @@ class ECMS
919
970
  zone_htg_eqpt_type:,
920
971
  zone_supp_htg_eqpt_type:,
921
972
  zone_clg_eqpt_type:,
922
- zone_fan_type:)
973
+ zone_fan_type:,
974
+ hw_loop: nil)
923
975
 
924
976
  always_on = model.alwaysOnDiscreteSchedule
925
977
  zones.sort.each do |zone|
@@ -934,13 +986,14 @@ class ECMS
934
986
  airloop.addBranchForZone(zone, diffuser.to_StraightComponent)
935
987
  end
936
988
  clg_eqpt = create_zone_clg_eqpt(model, zone_clg_eqpt_type)
937
- htg_eqpt = create_zone_htg_eqpt(model, zone_htg_eqpt_type)
938
- supp_htg_eqpt = create_zone_htg_eqpt(model, zone_supp_htg_eqpt_type)
989
+ htg_eqpt = create_zone_htg_eqpt(model, zone_htg_eqpt_type, hw_loop)
990
+ supp_htg_eqpt = create_zone_htg_eqpt(model, zone_supp_htg_eqpt_type, hw_loop)
939
991
  fan = create_air_sys_fan(model, zone_fan_type)
940
992
  # for container zonal equipment call method "create_zone_container_equipment"
941
993
  this_is_container_comp = false
942
994
  if (zone_htg_eqpt_type == 'pthp') || (zone_htg_eqpt_type == 'vrf') ||
943
- (zone_htg_eqpt_type.include? 'unitheater') || (zone_htg_eqpt_type.include? 'ptac')
995
+ (zone_htg_eqpt_type.include? 'unitheater') || (zone_htg_eqpt_type.include? 'ptac') ||
996
+ (zone_htg_eqpt_type.include? 'fancoil')
944
997
  this_is_container_comp = true
945
998
  zone_cont_eqpt = create_zone_container_eqpt(model: model,
946
999
  zone_cont_eqpt_type: zone_htg_eqpt_type,
@@ -958,11 +1011,159 @@ class ECMS
958
1011
  end
959
1012
  sys_name_zone_htg_eqpt_type = zone_htg_eqpt_type
960
1013
  sys_name_zone_htg_eqpt_type = 'b-e' if zone_htg_eqpt_type == 'baseboard_electric' || zone_htg_eqpt_type == 'ptac_electric_off'
1014
+ sys_name_zone_htg_eqpt_type = 'b-hw' if zone_htg_eqpt_type == 'baseboard_hotwater'
961
1015
  sys_name_zone_clg_eqpt_type = zone_clg_eqpt_type
962
1016
  sys_name_zone_clg_eqpt_type = 'ptac' if zone_clg_eqpt_type == 'ptac_electric_off'
963
1017
  update_sys_name(airloop, zone_htg: sys_name_zone_htg_eqpt_type, zone_clg: sys_name_zone_clg_eqpt_type) if zone_diffuser_type
964
1018
  end
965
1019
 
1020
+ # =============================================================================================================================
1021
+ # add plant loop pump
1022
+ def create_plantloop_pump(model, loop_pump_type)
1023
+
1024
+ pump = nil
1025
+ case loop_pump_type.downcase
1026
+ when "constant_speed"
1027
+ pump = OpenStudio::Model::PumpConstantSpeed.new(model)
1028
+ pump.setName("PumpConstantSpeed")
1029
+ when "variable_speed"
1030
+ pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1031
+ pump.setName("PumpVariableSpeed")
1032
+ end
1033
+
1034
+ return pump
1035
+ end
1036
+
1037
+ # =============================================================================================================================
1038
+ # add plant loop heating eqpt
1039
+ # created by: kamel.haddad@nrcan-rncan.gc.ca (August 2021)
1040
+ def create_plantloop_htg_eqpt(model, loop_htg_eqpt_type)
1041
+
1042
+ htg_eqpt = nil
1043
+ case loop_htg_eqpt_type.downcase
1044
+ when "district_heating"
1045
+ htg_eqpt = OpenStudio::Model::DistrictHeating.new(model)
1046
+ htg_eqpt.setName("DistrictHeating")
1047
+ when "heatpump_watertowater_equationfit"
1048
+ htg_eqpt = OpenStudio::Model::HeatPumpWaterToWaterEquationFitHeating.new(model)
1049
+ htg_eqpt.setName("HeatPumpWaterToWaterEquationFitHeating")
1050
+ end
1051
+
1052
+ return htg_eqpt
1053
+ end
1054
+
1055
+ # =============================================================================================================================
1056
+ # add plant loop cooling eqpt
1057
+ def create_plantloop_clg_eqpt(model, loop_clg_eqpt_type)
1058
+
1059
+ clg_eqpt = nil
1060
+ case loop_clg_eqpt_type.downcase
1061
+ when "chiller_electric_eir"
1062
+ clg_eqpt = OpenStudio::Model::ChillerElectricEIR.new(model)
1063
+ clg_eqpt.setName("ChillerElectricEIR")
1064
+ when "district_cooling"
1065
+ clg_eqpt = OpenStudio::Model::DistrictCooling.new(model)
1066
+ clg_eqpt.setName("DistrictCooling")
1067
+ when "heatpump_watertowater_equationfit"
1068
+ clg_eqpt = OpenStudio::Model::HeatPumpWaterToWaterEquationFitCooling.new(model)
1069
+ clg_eqpt.setName("HeatPumpWaterToWaterEquationFitCooling")
1070
+ end
1071
+
1072
+ return clg_eqpt
1073
+
1074
+ end
1075
+
1076
+ # =============================================================================================================================
1077
+ # add plant loop setpoint manager
1078
+ def create_plantloop_spm( model, loop_spm_type, loop_setpoint)
1079
+
1080
+ spm = nil
1081
+ case loop_spm_type.downcase
1082
+ when "scheduled"
1083
+ sch = OpenStudio::Model::ScheduleConstant.new(model)
1084
+ sch.setValue(loop_setpoint)
1085
+ spm = OpenStudio::Model::SetpointManagerScheduled.new(model,sch)
1086
+ spm.setName("SetpointManagerScheduled")
1087
+ when "followgroundtemperature"
1088
+ spm = OpenStudio::Model::SetpointManagerFollowGroundTemperature.new(model)
1089
+ spm.setReferenceGroundTemperatureObjectType("Site:GroundTemperature:Deep")
1090
+ spm.setMinimumSetpointTemperature(0.0)
1091
+ end
1092
+
1093
+ return spm
1094
+ end
1095
+
1096
+ # =============================================================================================================================
1097
+ # add plant loop heat rejection equipment
1098
+ def create_plantloop_heat_rej_eqpt(model, loop_heat_rej_eqpt_type)
1099
+
1100
+ heat_rej_eqpt = nil
1101
+ case loop_heat_rej_eqpt_type.downcase
1102
+ when "tower_single_speed"
1103
+ heat_rej_eqpt = OpenStudio::Model::CoolingTowerSingleSpeed.new(model)
1104
+ heat_rej_eqpt.setName("CoolingTowerSingleSpeed")
1105
+ when "vertical_ground_hx"
1106
+ heat_rej_eqpt = OpenStudio::Model::GroundHeatExchangerVertical.new(model)
1107
+ heat_rej_eqpt.setName("GroundHeatExchangerVertical")
1108
+ when "district_heating"
1109
+ heat_rej_eqpt = OpenStudio::Model::DistrictHeating.new(model)
1110
+ heat_rej_eqpt.setName("DistrictHeating")
1111
+ when "district_cooling"
1112
+ heat_rej_eqpt = OpenStudio::Model::DistrictCooling.new(model)
1113
+ heat_rej_eqpt.setName("DistrictCooling")
1114
+ end
1115
+
1116
+ return heat_rej_eqpt
1117
+ end
1118
+
1119
+ # =============================================================================================================================
1120
+ # add plant loop with all its components
1121
+ def add_plantloop(model:,
1122
+ loop_htg_eqpt_type:,
1123
+ loop_clg_eqpt_type:,
1124
+ loop_heat_rej_eqpt_type:,
1125
+ loop_pump_type:,
1126
+ loop_spm_type:,
1127
+ loop_setpoint:,
1128
+ loop_temp_diff:)
1129
+
1130
+ # create all the needed components and the plant loop
1131
+ plantloop = OpenStudio::Model::PlantLoop.new(model)
1132
+ spm = create_plantloop_spm(model, loop_spm_type, loop_setpoint)
1133
+ pump = create_plantloop_pump(model, loop_pump_type)
1134
+ htg_eqpt = create_plantloop_htg_eqpt(model, loop_htg_eqpt_type)
1135
+ clg_eqpt = create_plantloop_clg_eqpt(model, loop_clg_eqpt_type)
1136
+ heat_rej_eqpt = create_plantloop_heat_rej_eqpt(model, loop_heat_rej_eqpt_type)
1137
+ if heat_rej_eqpt.nil?
1138
+ if !htg_eqpt.nil?
1139
+ plantloop.sizingPlant.setLoopType('Heating')
1140
+ plantloop.setName("HW PlantLoop")
1141
+ eqpt = htg_eqpt
1142
+ elsif !clg_eqpt.nil?
1143
+ plantloop.sizingPlant.setLoopType('Cooling')
1144
+ plantloop.setName("CHW PlantLoop")
1145
+ eqpt = clg_eqpt
1146
+ end
1147
+ elsif !heat_rej_eqpt.nil?
1148
+ plantloop.sizingPlant.setLoopType('Condenser')
1149
+ plantloop.setName("Condenser PlantLoop")
1150
+ eqpt = heat_rej_eqpt
1151
+ end
1152
+ plantloop.sizingPlant.setDesignLoopExitTemperature(loop_setpoint) if loop_setpoint != 'none'
1153
+ plantloop.sizingPlant.setLoopDesignTemperatureDifference(loop_temp_diff) if loop_temp_diff != 'none'
1154
+ bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1155
+ supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
1156
+ supply_inlet_node = plantloop.supplyInletNode
1157
+ supply_outlet_node = plantloop.supplyOutletNode
1158
+ pump.addToNode(supply_inlet_node)
1159
+ plantloop.addSupplyBranchForComponent(eqpt)
1160
+ plantloop.addSupplyBranchForComponent(bypass_pipe)
1161
+ supply_outlet_pipe.addToNode(supply_outlet_node)
1162
+ spm.addToNode(supply_outlet_node) if loop_spm_type != 'none'
1163
+
1164
+ return plantloop,eqpt
1165
+ end
1166
+
966
1167
  # =============================================================================================================================
967
1168
  # Set assumptions for type of components for air system based on the number of zones served by the system and whether it's
968
1169
  # a mixed or doas.
@@ -1006,7 +1207,7 @@ class ECMS
1006
1207
  # -Constant-volume reheat system for single zone systems
1007
1208
  # -VAV system with reheat for non DOAS multi-zone systems
1008
1209
  # -Cold-climate air-source heat pump for heating and cooling with electric backup
1009
- # -Electric baseboards
1210
+ # -Electric or hot-water baseboards
1010
1211
  def add_ecm_hs09_ccashp_baseboard(model:,
1011
1212
  system_zones_map:, # hash of ailoop names as keys and array of zones as values
1012
1213
  system_doas_flags:, # hash of system names as keys and flag for DOAS as values
@@ -1014,6 +1215,10 @@ class ECMS
1014
1215
  heating_fuel:,
1015
1216
  standard:)
1016
1217
 
1218
+ # Create one hot-water loop for hot-water baseboards if primary heating fuel is gas
1219
+ hw_loop = nil
1220
+ hw_loop = add_hotwater_loop(model: model) if heating_fuel == 'NaturalGas'
1221
+
1017
1222
  # Set heating fuel
1018
1223
  updated_heating_fuel = heating_fuel
1019
1224
  if heating_fuel == 'DefaultFuel'
@@ -1030,7 +1235,7 @@ class ECMS
1030
1235
  zones: zones,
1031
1236
  system_doas_flags: system_doas_flags)
1032
1237
  # add airloop and its equipment
1033
- airloop, return_fan = add_air_system(
1238
+ airloop,clg_dx_coil,htg_dx_coil,return_fan = add_air_system(
1034
1239
  model: model,
1035
1240
  zones: zones,
1036
1241
  sys_abbr: sys_info['sys_abbr'],
@@ -1043,19 +1248,13 @@ class ECMS
1043
1248
  sys_ret_fan_type: sys_info['sys_ret_fan_type'],
1044
1249
  sys_setpoint_mgr_type: sys_info['sys_setpoint_mgr_type']
1045
1250
  )
1046
- htg_dx_coils = model.getCoilHeatingDXVariableSpeeds
1047
- search_criteria = {}
1048
- search_criteria['name'] = 'Mitsubishi_Hyper_Heating_VRF_Outdoor_Unit RTU',
1049
- props = model_find_object(standards_data['tables']['heat_pump_heating_ecm']['table'], search_criteria, 1.0)
1050
- heat_defrost_eir_ft = model_add_curve(model, props['heat_defrost_eir_ft'])
1051
- # This defrost curve has to be assigned here before sizing
1052
- if heat_defrost_eir_ft
1053
- htg_dx_coils.sort.each { |dxcoil| dxcoil.setDefrostEnergyInputRatioFunctionofTemperatureCurve(heat_defrost_eir_ft) }
1054
- else
1055
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXVariableSpeed', "For #{htg_dx_coils[0].name}, cannot find heat_defrost_eir_ft curve, will not be set.")
1056
- end
1251
+ # Appy performance curves
1252
+ eqpt_name = 'Mitsubishi_Hyper_Heating_VRF_Outdoor_Unit RTU'
1253
+ coil_cooling_dx_variable_speed_apply_curves(clg_dx_coil, eqpt_name)
1254
+ coil_heating_dx_variable_speed_apply_curves(htg_dx_coil, eqpt_name)
1057
1255
  # add zone equipment and diffuser
1058
- zone_htg_eqpt_type = 'baseboard_electric'
1256
+ zone_htg_eqpt_type = 'baseboard_hotwater' if heating_fuel == 'NaturalGas'
1257
+ zone_htg_eqpt_type = 'baseboard_electric' if heating_fuel == 'Electricity'
1059
1258
  zone_htg_eqpt_type = 'ptac_electric_off' if sys_info['sys_vent_type'] == 'doas'
1060
1259
  zone_clg_eqpt_type = 'none'
1061
1260
  zone_clg_eqpt_type = 'ptac_electric_off' if sys_info['sys_vent_type'] == 'doas'
@@ -1069,18 +1268,22 @@ class ECMS
1069
1268
  zone_htg_eqpt_type: zone_htg_eqpt_type,
1070
1269
  zone_supp_htg_eqpt_type: 'none',
1071
1270
  zone_clg_eqpt_type: zone_clg_eqpt_type,
1072
- zone_fan_type: zone_fan_type)
1073
- # for doas use baseboard electric as backup for PTAC units
1271
+ zone_fan_type: zone_fan_type,
1272
+ hw_loop: hw_loop)
1273
+ # for doas use baseboard electric or hotwater as backup for PTAC units
1274
+ zone_htg_eqpt_type = 'baseboard_hotwater' if heating_fuel == 'NaturalGas'
1275
+ zone_htg_eqpt_type = 'baseboard_electric' if heating_fuel == 'Electricity'
1074
1276
  if sys_info['sys_vent_type'] == 'doas'
1075
1277
  add_zone_eqpt(model: model,
1076
1278
  airloop: airloop,
1077
1279
  zones: zones,
1078
1280
  outdoor_unit: nil,
1079
1281
  zone_diffuser_type: nil,
1080
- zone_htg_eqpt_type: 'baseboard_electric',
1282
+ zone_htg_eqpt_type: zone_htg_eqpt_type,
1081
1283
  zone_supp_htg_eqpt_type: 'none',
1082
1284
  zone_clg_eqpt_type: 'none',
1083
- zone_fan_type: 'none')
1285
+ zone_fan_type: 'none',
1286
+ hw_loop: hw_loop)
1084
1287
  end
1085
1288
  return_fan.addToNode(airloop.returnAirNode.get) if return_fan
1086
1289
  systems << airloop
@@ -1090,7 +1293,7 @@ class ECMS
1090
1293
  end
1091
1294
 
1092
1295
  # =============================================================================================================================
1093
- # Apply efficiencies and performance curves for ECM "hs09_ccashp_baseboard"
1296
+ # Apply effiencies for ECM "hs09_ccashp_baseboard"
1094
1297
  def apply_efficiency_ecm_hs09_ccashp_baseboard(model)
1095
1298
  # fraction of electric backup heating coil capacity assigned to dx heating coil
1096
1299
  fr_backup_coil_cap_as_dx_coil_cap = 0.5
@@ -1166,10 +1369,11 @@ class ECMS
1166
1369
  if dx_cap < clg_dx_coil_cap then dx_cap = clg_dx_coil_cap end
1167
1370
  clg_dx_coil.setGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel(dx_cap)
1168
1371
  htg_dx_coil.setRatedHeatingCapacityAtSelectedNominalSpeedLevel(dx_cap)
1169
- # Assign performance curves and COPs
1170
- eqpt_name = 'Mitsubishi_Hyper_Heating_VRF_Outdoor_Unit RTU'
1171
- coil_cooling_dx_variable_speed_apply_efficiency_and_curves(clg_dx_coil, eqpt_name)
1172
- coil_heating_dx_variable_speed_apply_efficiency_and_curves(htg_dx_coil, eqpt_name)
1372
+ # Assign COPs
1373
+ search_criteria = {}
1374
+ search_criteria['name'] = 'Mitsubishi_Hyper_Heating_VRF_Outdoor_Unit RTU'
1375
+ coil_cooling_dx_variable_speed_apply_cop(clg_dx_coil, search_criteria, false)
1376
+ coil_heating_dx_variable_speed_apply_cop(htg_dx_coil, search_criteria, false)
1173
1377
  end
1174
1378
  end
1175
1379
  end
@@ -1184,6 +1388,7 @@ class ECMS
1184
1388
  ecm_system_zones_map_option:,
1185
1389
  standard:,
1186
1390
  heating_fuel:)
1391
+ hw_loop = nil
1187
1392
 
1188
1393
  # Set heating fuel
1189
1394
  updated_heating_fuel = heating_fuel
@@ -1196,13 +1401,8 @@ class ECMS
1196
1401
  sys_supp_htg_eqpt_type = 'coil_electric'
1197
1402
  sys_supp_htg_eqpt_type = 'coil_gas' if updated_heating_fuel == 'NaturalGas'
1198
1403
  # Update system zones map if needed
1199
- if ecm_system_zones_map_option != 'NECB_Default'
1200
- system_zones_map = update_system_zones_map(model,system_zones_map,ecm_system_zones_map_option,'sys_1')
1201
- else
1202
- updated_system_zones_map = {}
1203
- system_zones_map.each {|sname,zones| updated_system_zones_map["sys_1#{sname[5..-1]}"] = zones}
1204
- system_zones_map = updated_system_zones_map
1205
- end
1404
+ system_zones_map = update_system_zones_map_keys(system_zones_map,'sys_1')
1405
+ system_zones_map = update_system_zones_map(model,system_zones_map,ecm_system_zones_map_option,'sys_1') if ecm_system_zones_map_option != 'NECB_Default'
1206
1406
  # Update system doas flags
1207
1407
  system_doas_flags = {}
1208
1408
  system_zones_map.keys.each { |sname| system_doas_flags[sname] = true }
@@ -1212,7 +1412,7 @@ class ECMS
1212
1412
  sys_info = air_sys_comps_assumptions(sys_name: sys_name,
1213
1413
  zones: zones,
1214
1414
  system_doas_flags: system_doas_flags)
1215
- airloop, return_fan = add_air_system(model: model,
1415
+ airloop,clg_dx_coil,htg_dx_coil,return_fan = add_air_system(model: model,
1216
1416
  zones: zones,
1217
1417
  sys_abbr: sys_info['sys_abbr'],
1218
1418
  sys_vent_type: sys_info['sys_vent_type'],
@@ -1223,20 +1423,9 @@ class ECMS
1223
1423
  sys_supp_fan_type: sys_info['sys_supp_fan_type'],
1224
1424
  sys_ret_fan_type: sys_info['sys_ret_fan_type'],
1225
1425
  sys_setpoint_mgr_type: sys_info['sys_setpoint_mgr_type'])
1226
- # Get and assign defrost performance curve
1227
- search_criteria = {}
1228
- search_criteria['name'] = 'HS11_PTHP'
1229
- props = model_find_object(standards_data['tables']['heat_pump_heating_ecm']['table'], search_criteria, 1.0)
1230
- heat_defrost_eir_ft = model_add_curve(model, props['heat_defrost_eir_ft'])
1231
- if !heat_defrost_eir_ft
1232
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXConstantSpeed', 'Cannot find heat_defrost_eir_ft curve, will not be set.')
1233
- end
1234
- airloop.supplyComponents.each do |comp|
1235
- if comp.to_CoilHeatingDXSingleSpeed.is_initialized
1236
- htg_coil = comp.to_CoilHeatingDXSingleSpeed.get
1237
- htg_coil.setDefrostEnergyInputRatioFunctionofTemperatureCurve(heat_defrost_eir_ft)
1238
- end
1239
- end
1426
+ eqpt_name = 'HS11_PTHP'
1427
+ coil_cooling_dx_single_speed_apply_curves(clg_dx_coil,eqpt_name)
1428
+ coil_heating_dx_single_speed_apply_curves(htg_dx_coil,eqpt_name)
1240
1429
  # add zone equipment and diffuser
1241
1430
  zone_htg_eqpt_type = 'pthp'
1242
1431
  zone_clg_eqpt_type = 'pthp'
@@ -1250,13 +1439,18 @@ class ECMS
1250
1439
  zone_htg_eqpt_type: zone_htg_eqpt_type,
1251
1440
  zone_supp_htg_eqpt_type: zone_supp_htg_eqpt_type,
1252
1441
  zone_clg_eqpt_type: zone_clg_eqpt_type,
1253
- zone_fan_type: zone_fan_type)
1442
+ zone_fan_type: zone_fan_type,
1443
+ hw_loop: hw_loop)
1254
1444
  zones.each do |zone|
1255
1445
  zone.equipment.each do |comp|
1256
1446
  if comp.to_ZoneHVACPackagedTerminalHeatPump.is_initialized
1257
1447
  if comp.to_ZoneHVACPackagedTerminalHeatPump.get.heatingCoil.to_CoilHeatingDXSingleSpeed.is_initialized
1258
1448
  htg_coil = comp.to_ZoneHVACPackagedTerminalHeatPump.get.heatingCoil.to_CoilHeatingDXSingleSpeed.get
1259
- htg_coil.setDefrostEnergyInputRatioFunctionofTemperatureCurve(heat_defrost_eir_ft)
1449
+ coil_heating_dx_single_speed_apply_curves(htg_coil,eqpt_name)
1450
+ end
1451
+ if comp.to_ZoneHVACPackagedTerminalHeatPump.get.coolingCoil.to_CoilCoolingDXSingleSpeed.is_initialized
1452
+ clg_coil = comp.to_ZoneHVACPackagedTerminalHeatPump.get.coolingCoil.to_CoilCoolingDXSingleSpeed.get
1453
+ coil_cooling_dx_single_speed_apply_curves(clg_coil,eqpt_name)
1260
1454
  end
1261
1455
  end
1262
1456
  end
@@ -1319,9 +1513,11 @@ class ECMS
1319
1513
  if dx_cap < clg_dx_coil_cap then dx_cap = clg_dx_coil_cap end
1320
1514
  # clg_dx_coil.setRatedTotalCoolingCapacity(dx_cap)
1321
1515
  # htg_dx_coil.setRatedTotalHeatingCapacity(dx_cap)
1322
- # assign performance curves and COPs
1323
- coil_cooling_dx_single_speed_apply_efficiency_and_curves(clg_dx_coil, pthp_eqpt_name)
1324
- coil_heating_dx_single_speed_apply_efficiency_and_curves(htg_dx_coil, pthp_eqpt_name)
1516
+ # assign COPs
1517
+ search_criteria = {}
1518
+ search_criteria['name'] = pthp_eqpt_name
1519
+ coil_cooling_dx_single_speed_apply_cop(clg_dx_coil, search_criteria)
1520
+ coil_heating_dx_single_speed_apply_cop(htg_dx_coil, search_criteria)
1325
1521
  # Set fan power
1326
1522
  fan_power_per_flow_rate = 150.0 # based on Mitsubishi data: 100 low and 200 high (W-s/m3)
1327
1523
  fan_pr_rise = fan_power_per_flow_rate * (fan.fanEfficiency * fan.motorEfficiency)
@@ -1337,7 +1533,7 @@ class ECMS
1337
1533
  # -Constant-volume reheat system for single zone systems
1338
1534
  # -VAV system with reheat for non DOAS multi-zone systems
1339
1535
  # -Air-source heat pump for heating and cooling with electric backup
1340
- # -Electric baseboards
1536
+ # -Electric or hot-water baseboards
1341
1537
  def add_ecm_hs12_ashp_baseboard(model:,
1342
1538
  system_zones_map:,
1343
1539
  system_doas_flags:,
@@ -1345,6 +1541,10 @@ class ECMS
1345
1541
  standard:,
1346
1542
  heating_fuel:)
1347
1543
 
1544
+ # Create one hot-water loop for hot-water baseboards if primary heating fuel is gas
1545
+ hw_loop = nil
1546
+ hw_loop = add_hotwater_loop(model: model) if heating_fuel == 'NaturalGas'
1547
+
1348
1548
  # Set heating fuel
1349
1549
  updated_heating_fuel = heating_fuel
1350
1550
  if heating_fuel == 'DefaultFuel'
@@ -1361,7 +1561,7 @@ class ECMS
1361
1561
  zones: zones,
1362
1562
  system_doas_flags: system_doas_flags)
1363
1563
  # add air loop and its equipment
1364
- airloop, return_fan = add_air_system(model: model,
1564
+ airloop,clg_dx_coil,htg_dx_coil,return_fan = add_air_system(model: model,
1365
1565
  zones: zones,
1366
1566
  sys_abbr: sys_info['sys_abbr'],
1367
1567
  sys_vent_type: sys_info['sys_vent_type'],
@@ -1372,19 +1572,12 @@ class ECMS
1372
1572
  sys_supp_fan_type: sys_info['sys_supp_fan_type'],
1373
1573
  sys_ret_fan_type: sys_info['sys_ret_fan_type'],
1374
1574
  sys_setpoint_mgr_type: sys_info['sys_setpoint_mgr_type'])
1375
- # get and assign defrost curve
1376
- htg_dx_coils = model.getCoilHeatingDXSingleSpeeds
1377
- search_criteria = {}
1378
- search_criteria['name'] = 'NECB2015_ASHP'
1379
- props = model_find_object(standards_data['tables']['heat_pump_heating_ecm']['table'], search_criteria, 1.0)
1380
- heat_defrost_eir_ft = model_add_curve(model, props['heat_defrost_eir_ft'])
1381
- if heat_defrost_eir_ft
1382
- htg_dx_coils.sort.each { |dxcoil| dxcoil.setDefrostEnergyInputRatioFunctionofTemperatureCurve(heat_defrost_eir_ft) }
1383
- else
1384
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXSingleSpeed', "For #{htg_dx_coils[0].name}, cannot find heat_defrost_eir_ft curve, will not be set.")
1385
- end
1575
+ eqpt_name = 'NECB2015_ASHP'
1576
+ coil_cooling_dx_single_speed_apply_curves(clg_dx_coil,eqpt_name)
1577
+ coil_heating_dx_single_speed_apply_curves(htg_dx_coil,eqpt_name)
1386
1578
  # add zone equipment and diffuser
1387
- zone_htg_eqpt_type = 'baseboard_electric'
1579
+ zone_htg_eqpt_type = 'baseboard_hotwater' if heating_fuel == 'NaturalGas'
1580
+ zone_htg_eqpt_type = 'baseboard_electric' if heating_fuel == 'Electricity'
1388
1581
  zone_htg_eqpt_type = 'ptac_electric_off' if sys_info['sys_vent_type'] == 'doas'
1389
1582
  zone_clg_eqpt_type = 'none'
1390
1583
  zone_clg_eqpt_type = 'ptac_electric_off' if sys_info['sys_vent_type'] == 'doas'
@@ -1398,18 +1591,20 @@ class ECMS
1398
1591
  zone_htg_eqpt_type: zone_htg_eqpt_type,
1399
1592
  zone_supp_htg_eqpt_type: 'none',
1400
1593
  zone_clg_eqpt_type: zone_clg_eqpt_type,
1401
- zone_fan_type: zone_fan_type)
1402
- # for doas use baseboard electric as backup for PTAC units
1594
+ zone_fan_type: zone_fan_type,
1595
+ hw_loop: hw_loop)
1596
+ # for doas use baseboard electric or hotwater as backup for PTAC units
1403
1597
  if sys_info['sys_vent_type'] == 'doas'
1404
1598
  add_zone_eqpt(model: model,
1405
1599
  airloop: airloop,
1406
1600
  zones: zones,
1407
1601
  outdoor_unit: nil,
1408
1602
  zone_diffuser_type: nil,
1409
- zone_htg_eqpt_type: 'baseboard_electric',
1603
+ zone_htg_eqpt_type: zone_htg_eqpt_type,
1410
1604
  zone_supp_htg_eqpt_type: 'none',
1411
1605
  zone_clg_eqpt_type: 'none',
1412
- zone_fan_type: 'none')
1606
+ zone_fan_type: 'none',
1607
+ hw_loop: hw_loop)
1413
1608
  end
1414
1609
  return_fan.addToNode(airloop.returnAirNode.get) if return_fan
1415
1610
  systems << airloop
@@ -1479,9 +1674,11 @@ class ECMS
1479
1674
  if dx_cap < clg_dx_coil_cap then dx_cap = clg_dx_coil_cap end
1480
1675
  clg_dx_coil.setRatedTotalCoolingCapacity(dx_cap)
1481
1676
  htg_dx_coil.setRatedTotalHeatingCapacity(dx_cap)
1482
- # assign performance curves and COPs
1483
- coil_cooling_dx_single_speed_apply_efficiency_and_curves(clg_dx_coil, ashp_eqpt_name)
1484
- coil_heating_dx_single_speed_apply_efficiency_and_curves(htg_dx_coil, ashp_eqpt_name)
1677
+ # assign COPs
1678
+ search_criteria = {}
1679
+ search_criteria['name'] = ashp_eqpt_name
1680
+ coil_cooling_dx_single_speed_apply_cop(clg_dx_coil, search_criteria)
1681
+ coil_heating_dx_single_speed_apply_cop(htg_dx_coil, search_criteria)
1485
1682
  end
1486
1683
  end
1487
1684
  end
@@ -1515,8 +1712,315 @@ class ECMS
1515
1712
  end
1516
1713
 
1517
1714
  # =============================================================================================================================
1518
- # Applies the standard efficiency ratings and typical performance curves "CoilCoolingDXSingleSpeed" object.
1519
- def coil_cooling_dx_single_speed_apply_efficiency_and_curves(coil_cooling_dx_single_speed, eqpt_name)
1715
+ # Define object "SiteGroundTemperatureShallow" and use ground temperatures from weather file at 0.5 m depth
1716
+ def set_undisturbed_ground_surface_temp_objs(model)
1717
+ surface_ground_temp_obj = OpenStudio::Model::SiteGroundTemperatureShallow.new(model)
1718
+ wfile_path = model.getWeatherFile.path.get.to_s
1719
+ statsfile = EnergyPlus::StatFile.new(wfile_path.sub("epw","stat"))
1720
+ surface_ground_temp_obj.setJanuarySurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[0])
1721
+ surface_ground_temp_obj.setFebruarySurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[1])
1722
+ surface_ground_temp_obj.setMarchSurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[2])
1723
+ surface_ground_temp_obj.setAprilSurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[3])
1724
+ surface_ground_temp_obj.setMaySurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[4])
1725
+ surface_ground_temp_obj.setJuneSurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[5])
1726
+ surface_ground_temp_obj.setJulySurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[6])
1727
+ surface_ground_temp_obj.setAugustSurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[7])
1728
+ surface_ground_temp_obj.setSeptemberSurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[8])
1729
+ surface_ground_temp_obj.setOctoberSurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[9])
1730
+ surface_ground_temp_obj.setNovemberSurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[10])
1731
+ surface_ground_temp_obj.setDecemberSurfaceGroundTemperature(statsfile.monthly_undis_ground_temps_0p5m[11])
1732
+ end
1733
+
1734
+ # =============================================================================================================================
1735
+ # Define object "SiteGroundTemperatureDeep" and use ground temperatures from weather file at 4.0 m depth
1736
+ def set_undisturbed_ground_deep_temp_objs(model)
1737
+ surface_ground_temp_obj = OpenStudio::Model::SiteGroundTemperatureDeep.new(model)
1738
+ wfile_path = model.getWeatherFile.path.get.to_s
1739
+ statsfile = EnergyPlus::StatFile.new(wfile_path.sub("epw","stat"))
1740
+ surface_ground_temp_obj.setJanuaryDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[0])
1741
+ surface_ground_temp_obj.setFebruaryDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[1])
1742
+ surface_ground_temp_obj.setMarchDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[2])
1743
+ surface_ground_temp_obj.setAprilDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[3])
1744
+ surface_ground_temp_obj.setMayDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[4])
1745
+ surface_ground_temp_obj.setJuneDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[5])
1746
+ surface_ground_temp_obj.setJulyDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[6])
1747
+ surface_ground_temp_obj.setAugustDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[7])
1748
+ surface_ground_temp_obj.setSeptemberDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[8])
1749
+ surface_ground_temp_obj.setOctoberDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[9])
1750
+ surface_ground_temp_obj.setNovemberDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[10])
1751
+ surface_ground_temp_obj.setDecemberDeepGroundTemperature(statsfile.monthly_undis_ground_temps_4p0m[11])
1752
+ end
1753
+
1754
+ # =============================================================================================================================
1755
+ # Add equipment for ECM "hs14_cgshp_fancoils"
1756
+ # -Constant volume DOAS with hydronic htg and clg coils.
1757
+ # -Zonal terminal fan coil (4-pipe) connected to central ground-source heat pump.
1758
+ # -Plant has a heating loop with water-to-water heat pump with a backup boiler. It also has a water-cooled chiller with a
1759
+ # backup air-cooled chiller. Water-source heat pump and water-cooled chiller are connected to a ground-loop.
1760
+ def add_ecm_hs14_cgshp_fancoils(model:,
1761
+ system_zones_map:,
1762
+ system_doas_flags:,
1763
+ ecm_system_zones_map_option:,
1764
+ standard:,
1765
+ heating_fuel:)
1766
+
1767
+ updated_heating_fuel = heating_fuel
1768
+ if heating_fuel == 'DefaultFuel'
1769
+ epw = BTAP::Environment::WeatherFile.new(model.weatherFile.get.path.get)
1770
+ updated_heating_fuel = standard.standards_data['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.state_province_region)}['fueltype_set']
1771
+ end
1772
+ raise("Heating fuel for ECM 'HS11_ASHP_PTHP' is neither Electricity nor NaturalGas") if ((updated_heating_fuel != 'Electricity') && (updated_heating_fuel != 'NaturalGas'))
1773
+ # Set supplemental heaing for airloop
1774
+ sys_supp_htg_eqpt_type = 'coil_electric'
1775
+ sys_supp_htg_eqpt_type = 'coil_gas' if updated_heating_fuel == 'NaturalGas'
1776
+ # Update system zones map if needed
1777
+ system_zones_map = update_system_zones_map_keys(system_zones_map,'sys_1')
1778
+ system_zones_map = update_system_zones_map(model,system_zones_map,ecm_system_zones_map_option,'sys_1') if ecm_system_zones_map_option != 'NECB_Default'
1779
+ # Update system doas flags
1780
+ system_doas_flags = {}
1781
+ system_zones_map.keys.each { |sname| system_doas_flags[sname] = true }
1782
+ # use system zones map and generate new air system and zonal equipment
1783
+ systems = []
1784
+ system_zones_map.sort.each do |sys_name, zones|
1785
+ sys_info = air_sys_comps_assumptions(sys_name: sys_name,
1786
+ zones: zones,
1787
+ system_doas_flags: system_doas_flags)
1788
+ airloop,clg_coil,htg_coil,return_fan = add_air_system(model: model,
1789
+ zones: zones,
1790
+ sys_abbr: sys_info['sys_abbr'],
1791
+ sys_vent_type: sys_info['sys_vent_type'],
1792
+ sys_heat_rec_type: sys_info['sys_heat_rec_type'],
1793
+ sys_htg_eqpt_type: 'coil_hw',
1794
+ sys_supp_htg_eqpt_type: 'none',
1795
+ sys_clg_eqpt_type: 'coil_chw',
1796
+ sys_supp_fan_type: sys_info['sys_supp_fan_type'],
1797
+ sys_ret_fan_type: sys_info['sys_ret_fan_type'],
1798
+ sys_setpoint_mgr_type: 'warmest')
1799
+
1800
+ # add zone equipment and diffuser
1801
+ zone_htg_eqpt_type = 'fancoil_4pipe'
1802
+ zone_clg_eqpt_type = 'fancoil_4pipe'
1803
+ zone_supp_htg_eqpt_type = 'none'
1804
+ zone_fan_type = 'on_off'
1805
+ add_zone_eqpt(model: model,
1806
+ airloop: airloop,
1807
+ zones: zones,
1808
+ outdoor_unit: nil,
1809
+ zone_diffuser_type: sys_info['zone_diffuser_type'],
1810
+ zone_htg_eqpt_type: zone_htg_eqpt_type,
1811
+ zone_supp_htg_eqpt_type: zone_supp_htg_eqpt_type,
1812
+ zone_clg_eqpt_type: zone_clg_eqpt_type,
1813
+ zone_fan_type: zone_fan_type)
1814
+
1815
+ return_fan.addToNode(airloop.returnAirNode.get) if return_fan
1816
+ systems << airloop
1817
+ end
1818
+
1819
+ # add hot-water loop
1820
+ hw_loop,hw_loop_htg_eqpt = add_plantloop(model: model,
1821
+ loop_htg_eqpt_type: 'HeatPump_WaterToWater_EquationFit',
1822
+ loop_clg_eqpt_type: 'none',
1823
+ loop_heat_rej_eqpt_type: 'none',
1824
+ loop_pump_type: 'variable_speed',
1825
+ loop_spm_type: 'Scheduled',
1826
+ loop_setpoint: 50.0,
1827
+ loop_temp_diff: 5.0)
1828
+ model.getCoilHeatingWaters.each {|coil| hw_loop.addDemandBranchForComponent(coil)}
1829
+ hcapf_curve_name = "HEATPUMP_WATERTOWATER_HCAPF"
1830
+ hcapf_curve = model_add_curve(model, hcapf_curve_name)
1831
+ if hcapf_curve
1832
+ hw_loop_htg_eqpt.setHeatingCapacityCurve(hcapf_curve)
1833
+ else
1834
+ raise("Can not find curve hcapf for #{hw_loop_htg_eqpt.name}")
1835
+ end
1836
+ hpowerf_curve_name = "HEATPUMP_WATERTOWATER_HPOWERF"
1837
+ hpowerf_curve = model_add_curve(model, hpowerf_curve_name)
1838
+ if hpowerf_curve
1839
+ hw_loop_htg_eqpt.setHeatingCompressorPowerCurve(hpowerf_curve)
1840
+ else
1841
+ raise("Can not find curve hpowerf for #{hw_loop_htg_eqpt.name}")
1842
+ end
1843
+ boiler = OpenStudio::Model::BoilerHotWater.new(model)
1844
+ boiler.setFuelType(updated_heating_fuel)
1845
+ hw_loop_htg_eqpt_outlet_node = hw_loop_htg_eqpt.supplyOutletModelObject.get.to_Node.get
1846
+ boiler.addToNode(hw_loop_htg_eqpt_outlet_node)
1847
+
1848
+ # add chilled-water loop
1849
+ chw_loop,chw_loop_clg_eqpt = add_plantloop(model: model,
1850
+ loop_htg_eqpt_type: 'none',
1851
+ loop_clg_eqpt_type: 'chiller_electric_eir',
1852
+ loop_heat_rej_eqpt_type: 'none',
1853
+ loop_pump_type: 'variable_speed',
1854
+ loop_spm_type: 'Scheduled',
1855
+ loop_setpoint: 7.0,
1856
+ loop_temp_diff: 6.0)
1857
+
1858
+ chw_loop_clg_eqpt.setName('ChillerWaterCooled')
1859
+ chw_loop_clg_eqpt.setCondenserType("WaterCooled")
1860
+ model.getCoilCoolingWaters.each {|coil| chw_loop.addDemandBranchForComponent(coil)}
1861
+ sec_chiller = OpenStudio::Model::ChillerElectricEIR.new(model)
1862
+ chw_loop_clg_eqpt_outlet_node = chw_loop_clg_eqpt.supplyOutletModelObject.get.to_Node.get
1863
+ sec_chiller.addToNode(chw_loop_clg_eqpt_outlet_node)
1864
+ sec_chiller.setName('ChillerAirCooled')
1865
+
1866
+ # add ground HX loop with district heating and cooling plant to represent the ground HX
1867
+ heat_rej_loop,heat_rej_loop_eqpt = add_plantloop(model: model,
1868
+ loop_htg_eqpt_type: 'none',
1869
+ loop_clg_eqpt_type: 'none',
1870
+ loop_heat_rej_eqpt_type: 'District_Heating',
1871
+ loop_pump_type: 'variable_speed',
1872
+ loop_spm_type: 'none',
1873
+ loop_setpoint: 'none',
1874
+ loop_temp_diff: 10.0)
1875
+ heat_rej_loop_eqpt.setName('DistrictHeating GLHX')
1876
+ htg_eqpt_outlet_node = heat_rej_loop_eqpt.outletModelObject.get.to_Node.get
1877
+ clg_eqpt = create_plantloop_clg_eqpt(model, 'District_Cooling')
1878
+ clg_eqpt.setName('DistrictCooling GLHX')
1879
+ clg_eqpt.addToNode(htg_eqpt_outlet_node)
1880
+ htg_spm = create_plantloop_spm( model, 'Scheduled', 5.0)
1881
+ htg_spm.addToNode(htg_eqpt_outlet_node)
1882
+ clg_eqpt_outlet_node = clg_eqpt.outletModelObject.get.to_Node.get
1883
+ clg_spm = create_plantloop_spm( model, 'Scheduled', 25.0)
1884
+ clg_spm.addToNode(heat_rej_loop.supplyOutletNode)
1885
+ heat_rej_loop.setName("#{heat_rej_loop.name.to_s} GLHX")
1886
+ heat_rej_loop.addDemandBranchForComponent(hw_loop_htg_eqpt)
1887
+ heat_rej_loop.addDemandBranchForComponent(chw_loop_clg_eqpt)
1888
+
1889
+ # add output variables for district heating and cooling
1890
+ model.getOutputVariables.each {|ivar| ivar.remove}
1891
+ dist_htg_var = OpenStudio::Model::OutputVariable.new("District Heating Hot Water Rate",model)
1892
+ dist_htg_var.setReportingFrequency("hourly")
1893
+ dist_htg_var.setKeyValue("*")
1894
+ dist_clg_var = OpenStudio::Model::OutputVariable.new("District Cooling Chilled Water Rate",model)
1895
+ dist_clg_var.setReportingFrequency("hourly")
1896
+ dist_clg_var.setKeyValue("*")
1897
+
1898
+ return systems
1899
+ end
1900
+
1901
+ #=============================================================================================================================
1902
+ # Appy efficiencies for ECM "hs14_cgshp_fancoils"
1903
+ def apply_efficiency_ecm_hs14_cgshp_fancoils(model)
1904
+ heatpump_siz_f = 0.4 # sizing factor for water-source heat pump (heating mode)
1905
+ chiller_siz_f = 0.4 # sizing factor for water-cooled chiller
1906
+ # get water-source heat pump
1907
+ hw_loops = model.getPlantLoops.select {|loop| loop.sizingPlant.loopType.to_s.downcase == 'heating'}
1908
+ hw_heatpump_loop = nil
1909
+ hw_heatpump = nil
1910
+ hw_loops.each do |hw_loop|
1911
+ hw_heatpumps = hw_loop.supplyComponents.select {|comp| comp.to_HeatPumpWaterToWaterEquationFitHeating.is_initialized}
1912
+ if !hw_heatpumps.empty?
1913
+ hw_heatpump_loop = hw_loop
1914
+ hw_heatpump = hw_heatpumps[0].to_HeatPumpWaterToWaterEquationFitHeating.get
1915
+ break
1916
+ end
1917
+ end
1918
+ raise("apply_efficiency_ecm_hs14_cgshp_fancoils: no water-source heat pump found in heating loop #{hw_loops.name.to_s}") if hw_heatpump.nil?
1919
+ cw_loop = model.getPlantLoops.select {|loop| loop.sizingPlant.loopType.to_s.downcase == 'condenser'}[0]
1920
+ # condenser flow rate is set based on heating loop flow rate and cooling loop flow rate (adjusted for sizing factors)
1921
+ cw_loop_max_flow = 0.0
1922
+ if hw_heatpump_loop.autosizedMaximumLoopFlowRate.is_initialized
1923
+ cw_loop_max_flow += heatpump_siz_f*hw_heatpump_loop.autosizedMaximumLoopFlowRate.to_f
1924
+ elsif hw_heatpump_loop.maximumLoopFlowRate.is_initialized
1925
+ cw_loop_max_flow += heatpump_siz_f*hw_heatpump_loop.maximumLoopFlowRate.to_f
1926
+ else
1927
+ raise("apply_efficiency_ecm_hs14_cgshp_fancoils: heating loop #{hw_heatpump_loop.name.to_s} flow rate is not defined")
1928
+ end
1929
+ chw_loop = model.getPlantLoops.select {|loop| loop.sizingPlant.loopType.to_s.downcase == 'cooling'}[0]
1930
+ if chw_loop.autosizedMaximumLoopFlowRate.is_initialized
1931
+ cw_loop_max_flow += chiller_siz_f*chw_loop.autosizedMaximumLoopFlowRate.to_f
1932
+ elsif chw_loop.maximumLoopFlowRate.is_initialized
1933
+ cw_loop_max_flow += chiller_siz_f*chw_loop.maximumLoopFlowRate.to_f
1934
+ else
1935
+ raise("apply_efficiency_ecm_hs14_cgshp_fancoils: cooling loop #{chw_loop.name.to_s} is not defined")
1936
+ end
1937
+ cw_loop.setMaximumLoopFlowRate(cw_loop_max_flow)
1938
+ cw_loop_pump = cw_loop.supplyComponents.select {|comp| comp.to_PumpVariableSpeed.is_initialized}[0].to_PumpVariableSpeed.get
1939
+ cw_loop_pump.setRatedFlowRate(cw_loop_max_flow)
1940
+ # set heating capacity of water-source heat pump
1941
+ if hw_heatpump.autosizedRatedHeatingCapacity.is_initialized
1942
+ cap = hw_heatpump.autosizedRatedHeatingCapacity.to_f
1943
+ elsif hw_heatpump.ratedHeatingCapacity.is_initialized
1944
+ cap = hw_heatpump.ratedHeatingCapacity.to_f
1945
+ else
1946
+ raise("apply_efficiency_ecm_hs14_cgshp_fancoils: capacity of water-source heat pump #{hw_heatpump.name.to_s} is not defined")
1947
+ end
1948
+ hw_heatpump.setRatedHeatingCapacity(heatpump_siz_f*cap)
1949
+ # set cooling capacity of water-cooled chiller
1950
+ chillers = chw_loop.supplyComponents.select {|comp| comp.to_ChillerElectricEIR.is_initialized}
1951
+ chiller_water_cooled = nil
1952
+ chillers.each do |comp|
1953
+ chlr = comp.to_ChillerElectricEIR.get
1954
+ if chlr.name.to_s.include? 'ChillerWaterCooled'
1955
+ chiller_water_cooled = chlr
1956
+ break
1957
+ end
1958
+ end
1959
+ raise("apply_efficiency_ecm_hs14_cgshp_fancoils: no water-cooled chiller found in cooling loop #{chw_loop.name.to_s}") if chiller_water_cooled.nil?
1960
+ if chiller_water_cooled.autosizedReferenceCapacity.is_initialized
1961
+ cap = chiller_water_cooled.autosizedReferenceCapacity.to_f
1962
+ elsif chiller_water_cooled.referenceCapacity.is_initialized
1963
+ cap = chiller_water_cooled.referenceCapacity.to_f
1964
+ else
1965
+ raise("apply_efficiency_ecm_hs14_cgshp_fancoils: cooling capacity of chiller #{chiller_water_cooled.name.to_s} is not defined")
1966
+ end
1967
+ chiller_water_cooled.setReferenceCapacity(chiller_siz_f*cap)
1968
+ end
1969
+
1970
+ #=============================================================================================================================
1971
+ def set_ghx_loop_district_cap(model)
1972
+ # The autosized values for the district heating and cooling objects on a condenser loop are the sum of the peak heating and
1973
+ # cooling loads. Here the capacity of the district heating object of the condenser loop is set to the maximum district heating
1974
+ # rate on the winter design day. Similarily the capacity of the district cooling object of the condenser loop is set to the
1975
+ # maximum district cooling rate on the summer design day.
1976
+
1977
+ cw_loops = model.getPlantLoops.select{|loop| loop.sizingPlant.loopType.to_s.downcase == 'condenser'}
1978
+ ghx_loops = cw_loops.select {|loop| loop.name.to_s.downcase.include? 'glhx'}
1979
+ return if ghx_loops.empty?
1980
+ ghx_loop = ghx_loops[0]
1981
+ dist_htg_eqpts = ghx_loop.supplyComponents.select {|comp| comp.to_DistrictHeating.is_initialized}
1982
+ dist_htg_eqpt = dist_htg_eqpts[0].to_DistrictHeating.get if !dist_htg_eqpts.empty?
1983
+ dist_clg_eqpts = ghx_loop.supplyComponents.select {|comp| comp.to_DistrictCooling.is_initialized}
1984
+ dist_clg_eqpt = dist_clg_eqpts[0].to_DistrictCooling.get if !dist_clg_eqpts.empty?
1985
+ raise("set_cond_loop_district_cap: condenser loop doesn't have a district heating and district cooling objects") if dist_htg_eqpts.empty? || dist_clg_eqpts.empty?
1986
+ # District Heating
1987
+ sql_command = "SELECT ReportVariableDataDictionaryIndex FROM ReportVariableDataDictionary
1988
+ WHERE VariableName='District Heating Hot Water Rate'"
1989
+ dhtg_index = model.sqlFile.get.execAndReturnFirstString(sql_command).get
1990
+ raise("set_ghx_loop_district_cap: EnergyPlus sql results file has no data for district heating hot water rate") if dhtg_index.nil?
1991
+ sql_command = "SELECT Value FROM ReportVariableWithTime
1992
+ WHERE ReportDataDictionaryIndex=#{dhtg_index} AND DayType='WinterDesignDay'"
1993
+ dist_htg_w = model.sqlFile.get.execAndReturnVectorOfString(sql_command).get
1994
+ sql_command = "SELECT Value FROM ReportVariableWithTime
1995
+ WHERE ReportDataDictionaryIndex=#{dhtg_index} AND DayType='SummerDesignDay'"
1996
+ dist_htg_s = model.sqlFile.get.execAndReturnVectorOfString(sql_command).get
1997
+ # District Cooling
1998
+ sql_command = "SELECT ReportVariableDataDictionaryIndex FROM ReportVariableDataDictionary
1999
+ WHERE VariableName='District Cooling Chilled Water Rate'"
2000
+ dclg_index = model.sqlFile.get.execAndReturnFirstString(sql_command).get
2001
+ raise("set_ghx_loop_district_cap: EnergyPlus sql results file has no data for district cooling chilled water rate") if dclg_index.nil?
2002
+ sql_command = "SELECT Value FROM ReportVariableWithTime
2003
+ WHERE ReportDataDictionaryIndex=#{dclg_index} AND DayType='SummerDesignDay'"
2004
+ dist_clg_s = model.sqlFile.get.execAndReturnVectorOfString(sql_command).get
2005
+ sql_command = "SELECT Value FROM ReportVariableWithTime
2006
+ WHERE ReportDataDictionaryIndex=#{dclg_index} AND DayType='WinterDesignDay'"
2007
+ dist_clg_w = model.sqlFile.get.execAndReturnVectorOfString(sql_command).get
2008
+ # Assign peak heating and cooling loads to capacities of district objects
2009
+ max_htg_load = 0.0
2010
+ max_clg_load = 0.0
2011
+ for hour in 1..24
2012
+ htg_load = [dist_htg_w[hour-1].to_f-dist_clg_w[hour-1].to_f,0.0].max
2013
+ clg_load = [dist_clg_s[hour-1].to_f-dist_htg_s[hour-1].to_f,0.0].max
2014
+ max_htg_load = [max_htg_load,htg_load].max
2015
+ max_clg_load = [max_clg_load,clg_load].max
2016
+ end
2017
+ dist_htg_eqpt.setNominalCapacity(max_htg_load)
2018
+ dist_clg_eqpt.setNominalCapacity(max_clg_load)
2019
+ end
2020
+
2021
+ # =============================================================================================================================
2022
+ # Applies the performance curves "CoilCoolingDXSingleSpeed" object.
2023
+ def coil_cooling_dx_single_speed_apply_curves(coil_cooling_dx_single_speed, eqpt_name)
1520
2024
  successfully_set_all_properties = true
1521
2025
 
1522
2026
  search_criteria = {}
@@ -1524,6 +2028,7 @@ class ECMS
1524
2028
 
1525
2029
  # Get the capacity
1526
2030
  capacity_w = coil_cooling_dx_single_speed_find_capacity(coil_cooling_dx_single_speed)
2031
+ capacity_w = [1.0,capacity_w].max
1527
2032
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
1528
2033
 
1529
2034
  # Lookup efficiencies
@@ -1581,16 +2086,11 @@ class ECMS
1581
2086
  successfully_set_all_properties = false
1582
2087
  end
1583
2088
 
1584
- # Find the minimum COP and rename with efficiency rating
1585
- cop = coil_cooling_dx_single_speed_standard_minimum_cop(coil_cooling_dx_single_speed, search_criteria, false)
1586
-
1587
- # Set the efficiency values
1588
- coil_cooling_dx_single_speed.setRatedCOP(cop.to_f) unless cop.nil?
1589
2089
  end
1590
2090
 
1591
2091
  # =============================================================================================================================
1592
- # Applies the standard efficiency ratings and typical performance curves to "CoilHeatingSingleSpeed" object.
1593
- def coil_heating_dx_single_speed_apply_efficiency_and_curves(coil_heating_dx_single_speed, eqpt_name)
2092
+ # Applies the performance curves to "CoilHeatingSingleSpeed" object.
2093
+ def coil_heating_dx_single_speed_apply_curves(coil_heating_dx_single_speed, eqpt_name)
1594
2094
  successfully_set_all_properties = true
1595
2095
 
1596
2096
  # Get the search criteria
@@ -1599,6 +2099,7 @@ class ECMS
1599
2099
 
1600
2100
  # Get the capacity
1601
2101
  capacity_w = coil_heating_dx_single_speed_find_capacity(coil_heating_dx_single_speed)
2102
+ capacity_w = [1.0,capacity_w].max
1602
2103
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
1603
2104
  capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get
1604
2105
 
@@ -1655,32 +2156,37 @@ class ECMS
1655
2156
  OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXSingleSpeed', "For #{coil_heating_dx_single_speed.name}, cannot find heat_plf_fplr curve, will not be set.")
1656
2157
  successfully_set_all_properties = false
1657
2158
  end
2159
+
2160
+ # Make the HEAT-DEFROST-EIR-FT curve
2161
+ heat_defrost_eir_ft = model_add_curve(coil_heating_dx_single_speed.model, props['heat_defrost_eir_ft'])
2162
+ if heat_defrost_eir_ft
2163
+ coil_heating_dx_single_speed.setDefrostEnergyInputRatioFunctionofTemperatureCurve(heat_defrost_eir_ft)
2164
+ else
2165
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXSingleSpeed', "For #{coil_heating_dx_single_speed.name}, can not find heat_defrost_eir_ft curve, will not be set.")
2166
+ successfully_set_all_properties = false
2167
+ end
1658
2168
 
1659
- # Find the minimum COP and rename with efficiency rating
1660
- cop = coil_heating_dx_single_speed_standard_minimum_cop(coil_heating_dx_single_speed, search_criteria, false)
1661
-
1662
- # Set the efficiency values
1663
- coil_heating_dx_single_speed.setRatedCOP(cop.to_f) unless cop.nil?
1664
2169
  end
1665
2170
 
1666
2171
  # =============================================================================================================================
1667
- # Applies the standard efficiency ratings and typical performance curves "CoilCoolingDXVariableSpeed" object.
1668
- def coil_cooling_dx_variable_speed_apply_efficiency_and_curves(coil_cooling_dx_variable_speed, eqpt_name)
2172
+ # Applies the performance curves "CoilCoolingDXVariableSpeed" object.
2173
+ def coil_cooling_dx_variable_speed_apply_curves(coil_cooling_dx_variable_speed, eqpt_name)
1669
2174
  successfully_set_all_properties = true
1670
2175
 
1671
2176
  # Get the capacity
1672
2177
  capacity_w = coil_cooling_dx_variable_speed_find_capacity(coil_cooling_dx_variable_speed)
2178
+ capacity_w = [1.0,capacity_w].max
1673
2179
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
1674
2180
  capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get
1675
2181
 
1676
- # Lookup efficiencies depending on whether it is a unitary AC or a heat pump
2182
+ # Lookup performance curves
1677
2183
  search_criteria = {}
1678
2184
  search_criteria['name'] = eqpt_name
1679
2185
  ac_props = model_find_object(standards_data['tables']['heat_pump_cooling_ecm']['table'], search_criteria, capacity_btu_per_hr)
1680
2186
 
1681
2187
  # Check to make sure properties were found
1682
2188
  if ac_props.nil?
1683
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standard.CoilCoolingDXVariableSpeed', "For #{coil_cooling_dx_single_speed.name}, cannot find efficiency info using #{search_criteria}, cannot apply efficiency.")
2189
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standard.CoilCoolingDXVariableSpeed', "For #{coil_cooling_dx_variable_speed.name}, cannot find efficiency info using #{search_criteria}, cannot apply efficiency.")
1684
2190
  successfully_set_all_properties = false
1685
2191
  end
1686
2192
 
@@ -1729,16 +2235,11 @@ class ECMS
1729
2235
  successfully_set_all_properties = false
1730
2236
  end
1731
2237
 
1732
- # Find the minimum COP and rename with efficiency rating
1733
- cop = coil_cooling_dx_variable_speed_standard_minimum_cop(coil_cooling_dx_variable_speed, search_criteria, false)
1734
-
1735
- # Set the efficiency values
1736
- coil_cooling_dx_variable_speed.speeds.each { |speed| speed.setReferenceUnitGrossRatedCoolingCOP(cop.to_f) } unless cop.nil?
1737
2238
  end
1738
2239
 
1739
2240
  # =============================================================================================================================
1740
- # Applies the standard efficiency ratings and typical performance curves to "CoilHeatingVariableSpeed" object.
1741
- def coil_heating_dx_variable_speed_apply_efficiency_and_curves(coil_heating_dx_variable_speed, eqpt_name)
2241
+ # Applies performance curves to "CoilHeatingVariableSpeed" object.
2242
+ def coil_heating_dx_variable_speed_apply_curves(coil_heating_dx_variable_speed, eqpt_name)
1742
2243
  successfully_set_all_properties = true
1743
2244
 
1744
2245
  # Get the search criteria
@@ -1747,10 +2248,11 @@ class ECMS
1747
2248
 
1748
2249
  # Get the capacity
1749
2250
  capacity_w = coil_heating_dx_variable_speed_find_capacity(coil_heating_dx_variable_speed)
2251
+ capacity_w = [1.0,capacity_w].max
1750
2252
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
1751
2253
  capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get
1752
2254
 
1753
- # Lookup efficiencies
2255
+ # Lookup performance curves
1754
2256
  props = model_find_object(standards_data['tables']['heat_pump_heating_ecm']['table'], search_criteria, capacity_btu_per_hr)
1755
2257
 
1756
2258
  # Check to make sure properties were found
@@ -1804,27 +2306,31 @@ class ECMS
1804
2306
  successfully_set_all_properties = false
1805
2307
  end
1806
2308
 
1807
- # Find the minimum COP and rename with efficiency rating
1808
- cop = coil_heating_dx_variable_speed_standard_minimum_cop(coil_heating_dx_variable_speed, search_criteria, false)
2309
+ # Make the heat_defrost_eir_ft
2310
+ heat_defrost_eir_ft = model_add_curve(coil_heating_dx_variable_speed.model, props['heat_defrost_eir_ft'])
2311
+ if heat_defrost_eir_ft
2312
+ coil_heating_dx_variable_speed.setDefrostEnergyInputRatioFunctionofTemperatureCurve(heat_defrost_eir_ft)
2313
+ else
2314
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXVariableSpeed', "For #{coil_heating_dx_variable_speed.name}, cannot find heat_defrost_eir_ft curve, will not be set")
2315
+ successfully_set_all_properties = false
2316
+ end
1809
2317
 
1810
- # Set the efficiency values
1811
- coil_heating_dx_variable_speed.speeds.each { |speed| speed.setReferenceUnitGrossRatedHeatingCOP(cop.to_f) } unless cop.nil?
1812
2318
  end
1813
2319
 
1814
2320
  # =============================================================================================================================
1815
- # Applies the standard cooling efficiency ratings and typical performance curves to "AirConditionerVariableRefrigerantFlow" object.
1816
- def airconditioner_variablerefrigerantflow_cooling_apply_efficiency_and_curves(airconditioner_variablerefrigerantflow, eqpt_name)
2321
+ # Applies the cooling performance curves to "AirConditionerVariableRefrigerantFlow" object.
2322
+ def airconditioner_variablerefrigerantflow_cooling_apply_curves(airconditioner_variablerefrigerantflow, eqpt_name)
1817
2323
  successfully_set_all_properties = true
1818
2324
 
1819
2325
  search_criteria = {}
1820
2326
  search_criteria['name'] = eqpt_name
1821
-
1822
2327
  # Get the capacity
1823
2328
  capacity_w = airconditioner_variablerefrigerantflow_cooling_find_capacity(airconditioner_variablerefrigerantflow)
2329
+ capacity_w = [1.0,capacity_w].max
1824
2330
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
1825
2331
  capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get
1826
2332
 
1827
- # Lookup efficiencies
2333
+ # Lookup performance curves
1828
2334
  props = model_find_object(standards_data['tables']['heat_pump_cooling_ecm']['table'], search_criteria, capacity_btu_per_hr)
1829
2335
 
1830
2336
  # Check to make sure properties were found
@@ -1941,27 +2447,22 @@ class ECMS
1941
2447
  successfully_set_all_properties = false
1942
2448
  end
1943
2449
 
1944
- # Find the minimum COP
1945
- cop = airconditioner_variablerefrigerantflow_cooling_standard_minimum_cop(airconditioner_variablerefrigerantflow, search_criteria, false)
1946
-
1947
- # Set the efficiency values
1948
- airconditioner_variablerefrigerantflow.setRatedCoolingCOP(cop.to_f) unless cop.nil?
1949
2450
  end
1950
2451
 
1951
2452
  # =============================================================================================================================
1952
- # Applies the standard heating efficiency ratings and typical performance curves to "AirConditionerVariableRefrigerantFlow" object.
1953
- def airconditioner_variablerefrigerantflow_heating_apply_efficiency_and_curves(airconditioner_variablerefrigerantflow, eqpt_name)
2453
+ # Applies the heating performance curves to "AirConditionerVariableRefrigerantFlow" object.
2454
+ def airconditioner_variablerefrigerantflow_heating_apply_curves(airconditioner_variablerefrigerantflow, eqpt_name)
1954
2455
  successfully_set_all_properties = true
1955
2456
 
1956
2457
  search_criteria = {}
1957
2458
  search_criteria['name'] = eqpt_name
1958
-
1959
2459
  # Get the capacity
1960
2460
  capacity_w = airconditioner_variablerefrigerantflow_heating_find_capacity(airconditioner_variablerefrigerantflow)
2461
+ capacity_w = [1.0,capacity_w].max
1961
2462
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
1962
2463
  capacity_kbtu_per_hr = OpenStudio.convert(capacity_w, 'W', 'kBtu/hr').get
1963
2464
 
1964
- # Lookup efficiencies
2465
+ # Lookup performance curves
1965
2466
  props = model_find_object(standards_data['tables']['heat_pump_heating_ecm']['table'], search_criteria, capacity_btu_per_hr)
1966
2467
 
1967
2468
  # Check to make sure properties were found
@@ -2069,18 +2570,13 @@ class ECMS
2069
2570
  successfully_set_all_properties = false
2070
2571
  end
2071
2572
 
2072
- # Find the minimum COP and rename with efficiency rating
2073
- cop = airconditioner_variablerefrigerantflow_heating_standard_minimum_cop(airconditioner_variablerefrigerantflow, search_criteria, false)
2074
-
2075
- # Set the efficiency values
2076
- airconditioner_variablerefrigerantflow.setRatedHeatingCOP(cop.to_f) unless cop.nil?
2077
2573
  end
2078
2574
 
2079
2575
  # =============================================================================================================================
2080
- # Find minimum efficiency for "CoilCoolingDXSingleSpeed" object
2081
- def coil_cooling_dx_single_speed_standard_minimum_cop(coil_cooling_dx_single_speed,
2082
- search_criteria,
2083
- rename = false)
2576
+ # Find efficiency for "CoilCoolingDXSingleSpeed" object
2577
+ def coil_cooling_dx_single_speed_apply_cop(coil_cooling_dx_single_speed,
2578
+ search_criteria,
2579
+ rename = false)
2084
2580
 
2085
2581
  capacity_w = coil_cooling_dx_single_speed_find_capacity(coil_cooling_dx_single_speed)
2086
2582
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
@@ -2142,15 +2638,17 @@ class ECMS
2142
2638
  if rename
2143
2639
  coil_cooling_dx_single_speed.setName(new_comp_name)
2144
2640
  end
2641
+
2642
+ # Set COP
2643
+ coil_cooling_dx_single_speed.setRatedCOP(cop.to_f) unless cop.nil?
2145
2644
 
2146
- return cop
2147
2645
  end
2148
2646
 
2149
2647
  # =============================================================================================================================
2150
- # Find minimum efficiency for "CoilHeatingDXSingleSpeed" object
2151
- def coil_heating_dx_single_speed_standard_minimum_cop(coil_heating_dx_single_speed,
2152
- search_criteria,
2153
- rename = false)
2648
+ # Find efficiency for "CoilHeatingDXSingleSpeed" object
2649
+ def coil_heating_dx_single_speed_apply_cop(coil_heating_dx_single_speed,
2650
+ search_criteria,
2651
+ rename = false)
2154
2652
 
2155
2653
  capacity_w = coil_heating_dx_single_speed_find_capacity(coil_heating_dx_single_speed)
2156
2654
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
@@ -2205,14 +2703,16 @@ class ECMS
2205
2703
  coil_heating_dx_single_speed.setName(new_comp_name)
2206
2704
  end
2207
2705
 
2208
- return cop
2706
+ # Set COP
2707
+ coil_heating_dx_single_speed.setRatedCOP(cop.to_f) unless cop.nil?
2708
+
2209
2709
  end
2210
2710
 
2211
2711
  # =============================================================================================================================
2212
- # Find minimum efficiency for "CoilCoolingDXVariableSpeed" object
2213
- def coil_cooling_dx_variable_speed_standard_minimum_cop(coil_cooling_dx_variable_speed,
2214
- search_criteria,
2215
- rename = false)
2712
+ # Find efficiency for "CoilCoolingDXVariableSpeed" object
2713
+ def coil_cooling_dx_variable_speed_apply_cop(coil_cooling_dx_variable_speed,
2714
+ search_criteria,
2715
+ rename = false)
2216
2716
 
2217
2717
  capacity_w = coil_cooling_dx_variable_speed_find_capacity(coil_cooling_dx_variable_speed)
2218
2718
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
@@ -2275,14 +2775,16 @@ class ECMS
2275
2775
  coil_cooling_dx_variable_speed.setName(new_comp_name)
2276
2776
  end
2277
2777
 
2278
- return cop
2778
+ # Set COP values
2779
+ coil_cooling_dx_variable_speed.speeds.each { |speed| speed.setReferenceUnitGrossRatedCoolingCOP(cop.to_f) } unless cop.nil?
2780
+
2279
2781
  end
2280
2782
 
2281
2783
  # =============================================================================================================================
2282
- # Find minimum efficiency for "CoilHeatingDXVariableSpeed" object
2283
- def coil_heating_dx_variable_speed_standard_minimum_cop(coil_heating_dx_variable_speed,
2284
- search_criteria,
2285
- rename = false)
2784
+ # Find efficiency for "CoilHeatingDXVariableSpeed" object
2785
+ def coil_heating_dx_variable_speed_apply_cop(coil_heating_dx_variable_speed,
2786
+ search_criteria,
2787
+ rename = false)
2286
2788
 
2287
2789
  capacity_w = coil_heating_dx_variable_speed_find_capacity(coil_heating_dx_variable_speed)
2288
2790
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
@@ -2337,14 +2839,16 @@ class ECMS
2337
2839
  coil_heating_dx_variable_speed.setName(new_comp_name)
2338
2840
  end
2339
2841
 
2340
- return cop
2842
+ # Set COP values
2843
+ coil_heating_dx_variable_speed.speeds.each { |speed| speed.setReferenceUnitGrossRatedHeatingCOP(cop.to_f) } unless cop.nil?
2844
+
2341
2845
  end
2342
2846
 
2343
2847
  # =============================================================================================================================
2344
- # Find minimum cooling efficiency for "AirConditionerVariableRefrigerantFlow" object
2345
- def airconditioner_variablerefrigerantflow_cooling_standard_minimum_cop(airconditioner_variablerefrigerantflow,
2346
- search_criteria,
2347
- rename = false)
2848
+ # Find cooling efficiency for "AirConditionerVariableRefrigerantFlow" object
2849
+ def airconditioner_variablerefrigerantflow_cooling_apply_cop(airconditioner_variablerefrigerantflow,
2850
+ search_criteria,
2851
+ rename = false)
2348
2852
 
2349
2853
  capacity_w = airconditioner_variablerefrigerantflow_cooling_find_capacity(airconditioner_variablerefrigerantflow)
2350
2854
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
@@ -2399,14 +2903,16 @@ class ECMS
2399
2903
  airconditioner_variablerefrigerantflow.setName(new_comp_name)
2400
2904
  end
2401
2905
 
2402
- return cop
2906
+ # Set COP
2907
+ airconditioner_variablerefrigerantflow.setRatedCoolingCOP(cop.to_f) unless cop.nil?
2908
+
2403
2909
  end
2404
2910
 
2405
2911
  # =============================================================================================================================
2406
- # Find minimum heating efficiency for "AirConditionerVariableRefrigerantFlow" object
2407
- def airconditioner_variablerefrigerantflow_heating_standard_minimum_cop(airconditioner_variablerefrigerantflow,
2408
- search_criteria,
2409
- rename = false)
2912
+ # Find heating efficiency for "AirConditionerVariableRefrigerantFlow" object
2913
+ def airconditioner_variablerefrigerantflow_heating_apply_cop(airconditioner_variablerefrigerantflow,
2914
+ search_criteria,
2915
+ rename = false)
2410
2916
 
2411
2917
  capacity_w = airconditioner_variablerefrigerantflow_heating_find_capacity(airconditioner_variablerefrigerantflow)
2412
2918
  capacity_btu_per_hr = OpenStudio.convert(capacity_w, 'W', 'Btu/hr').get
@@ -2461,7 +2967,9 @@ class ECMS
2461
2967
  airconditioner_variablerefrigerantflow.setName(new_comp_name)
2462
2968
  end
2463
2969
 
2464
- return cop
2970
+ # Set COP
2971
+ airconditioner_variablerefrigerantflow.setRatedHeatingCOP(cop.to_f) unless cop.nil?
2972
+
2465
2973
  end
2466
2974
 
2467
2975
  # =============================================================================================================================
@@ -2613,7 +3121,7 @@ class ECMS
2613
3121
 
2614
3122
  component.setNormalizedBoilerEfficiencyCurve(part_load_curve)
2615
3123
  if component.isNominalCapacityAutosized
2616
- boiler_size_W = model.getAutosizedValue(component, 'Design Size Nominal Capacity', 'W').to_f
3124
+ boiler_size_W = component.autosizedNominalCapacity.get
2617
3125
  else
2618
3126
  boiler_size_W = component.nominalCapacity.to_f
2619
3127
  end
@@ -2813,10 +3321,11 @@ class ECMS
2813
3321
  # Method to update the cop and/or the performance curves of unitary dx coils. The method input 'unitary_cop' can either be a
2814
3322
  # string or a hash. When it's a string it's used to find a hash in the json table 'unitary_cop_ecm'. When it's a hash it holds
2815
3323
  # the parameters needed to update the cop and/or the performance curves of the unitary coil.
2816
- def modify_unitary_cop(model:, unitary_cop:, sql_db_vars_map:)
3324
+ def modify_unitary_cop(model:, unitary_cop:, sizing_done:, sql_db_vars_map:)
2817
3325
  return if unitary_cop.nil? || (unitary_cop.to_s == 'NECB_Default')
2818
3326
 
2819
- coils = model.getCoilCoolingDXSingleSpeeds + model.getCoilCoolingDXMultiSpeeds
3327
+ coils = model.getCoilCoolingDXSingleSpeeds.select {|coil| coil.name.to_s.include? '_dx'}
3328
+ coils += model.getCoilCoolingDXMultiSpeeds.select {|coil| coil.name.to_s.include? '_dx'}
2820
3329
  unitary_cop_copy = unitary_cop.dup
2821
3330
  coils.sort.each do |coil|
2822
3331
  coil_type = 'SingleSpeed'
@@ -2827,7 +3336,7 @@ class ECMS
2827
3336
  search_criteria = {}
2828
3337
  search_criteria['name'] = unitary_cop_copy
2829
3338
  coil_name = coil.name.to_s
2830
- if sql_db_vars_map.has_key? coil_name then coil.setName(sql_db_vars_map[coil_name]) end
3339
+ if (sql_db_vars_map.has_key? coil_name) && !sizing_done then coil.setName(sql_db_vars_map[coil_name]) end
2831
3340
  if coil_type == 'SingleSpeed'
2832
3341
  capacity_w = coil_cooling_dx_single_speed_find_capacity(coil)
2833
3342
  elsif coil_type == 'MultiSpeed'
@@ -2835,61 +3344,85 @@ class ECMS
2835
3344
  end
2836
3345
  coil.setName(coil_name)
2837
3346
  cop_package = model_find_object(@standards_data['tables']['unitary_cop_ecm'], search_criteria, capacity_w)
2838
- raise "Cannot not find #{unitary_cop_ecm} in the ECMS unitary_acs.json file. Please check that the name is correctly spelled in the ECMS class unitary_acs.json file and in the code calling (directly or through another method) the ECMS class modify_unitary_eff method." if cop_package.empty?
3347
+ raise "Cannot find #{unitary_cop_ecm} in the ECMS unitary_acs.json file. Please check that the name is correctly spelled in the ECMS class unitary_acs.json file and in the code calling (directly or through another method) the ECMS class modify_unitary_eff method." if cop_package.empty?
2839
3348
 
2840
3349
  ecm_name = unitary_cop_copy
2841
3350
  unitary_cop = {
2842
3351
  'name' => ecm_name,
3352
+ 'maximum_capacity' => cop_package['maximum_capacity'],
2843
3353
  'minimum_energy_efficiency_ratio' => cop_package['minimum_energy_efficiency_ratio'],
2844
3354
  'minimum_seasonal_energy_efficiency_ratio' => cop_package['minimum_seasonal_energy_efficiency_ratio'],
3355
+ 'minimum_coefficient_of_performance_cooling' => cop_package['minimum_coefficient_of_performance_cooling'],
3356
+ 'ref_flow_rate_m3_per_sec' => cop_package['ref_flow_rate_m3_per_sec'],
2845
3357
  'cool_cap_ft' => cop_package['cool_cap_ft'],
2846
3358
  'cool_cap_fflow' => cop_package['cool_cap_fflow'],
2847
3359
  'cool_eir_ft' => cop_package['cool_eir_ft'],
2848
3360
  'cool_eir_fflow' => cop_package['cool_eir_fflow'],
2849
- 'cool_plf_fplr' => cop_package['cool_eir_fplr']
3361
+ 'cool_plf_fplr' => cop_package['cool_plf_fplr']
2850
3362
  }
2851
3363
  end
2852
- next if unitary_cop['minimum_energy_efficiency_ratio'].nil? && unitary_cop['minimum_seasonal_energy_efficiency_ratio'].nil? && unitary_cop['cool_cap_ft'].nil? &&
2853
- unitary_cop['cool_cap_fflow'].nil? && unitary_cop['cool_eir_ft'].nil? && unitary_cop['cool_eir_fflow'].nil? && unitary_cop['cool_plf_fplr'].nil?
3364
+ next if unitary_cop['minimum_energy_efficiency_ratio'].nil? && unitary_cop['minimum_seasonal_energy_efficiency_ratio'].nil? &&
3365
+ unitary_cop['minimum_coefficient_of_performance_cooling'].nil? && unitary_cop['cool_cap_ft'].nil? && unitary_cop['cool_cap_fflow'].nil? &&
3366
+ unitary_cop['cool_eir_ft'].nil? && unitary_cop['cool_eir_fflow'].nil? && unitary_cop['cool_plf_fplr'].nil? && unitary_cop['ref_flow_rate_m3_per_sec'].nil?
2854
3367
 
2855
3368
  # If the dx coil is on an air loop then update its cop and the performance curves when these are specified in the ecm data
2856
3369
  if (coil_type == 'SingleSpeed' && coil.airLoopHVAC.is_initialized && (!coil.name.to_s.include? "_ASHP")) ||
2857
3370
  (coil_type == 'MultiSpeed' && coil.containingHVACComponent.get.airLoopHVAC.is_initialized)
2858
- cop = nil
2859
- if unitary_cop['minimum_energy_efficiency_ratio']
2860
- cop = eer_to_cop(unitary_cop['minimum_energy_efficiency_ratio'].to_f)
2861
- elsif unitary_cop['minimum_seasonal_energy_efficiency_ratio']
2862
- cop = seer_to_cop_cooling_with_fan(unitary_cop['minimum_seasonal_energy_efficiency_ratio'].to_f)
2863
- end
2864
- cool_cap_ft = nil
2865
- cool_cap_ft = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_cap_ft'] } if unitary_cop['cool_cap_ft']
2866
- cool_cap_fflow = nil
2867
- cool_cap_fflow = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_cap_fflow'] } if unitary_cop['cool_cap_fflow']
2868
- cool_eir_ft = nil
2869
- cool_eir_ft = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_eir_ft'] } if unitary_cop['cool_eir_ft']
2870
- cool_eir_fflow = nil
2871
- cool_eir_fflow = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_eir_fflow'] } if unitary_cop['cool_eir_fflow']
2872
- cool_plf_fplr = nil
2873
- cool_plf_fplr = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_plf_fplr'] } if unitary_cop['cool_plf_fplr']
2874
- if coil_type == 'SingleSpeed'
2875
- coil.setRatedCOP(cop) if cop
2876
- coil.setTotalCoolingCapacityFunctionOfTemperatureCurve(cool_cap_ft) if cool_cap_ft
2877
- coil.setTotalCoolingCapacityFunctionOfFlowFractionCurve(cool_cap_fflow) if cool_cap_fflow
2878
- coil.setEnergyInputRatioFunctionOfTemperatureCurve(cool_eir_ft) if cool_eir_ft
2879
- coil.setEnergyInputRatioFunctionOfFlowFractionCurve(cool_eir_fflow) if cool_eir_fflow
2880
- coil.setPartLoadFractionCorrelationCurve(cool_plf_fplr) if cool_plf_fplr
2881
- elsif coil_type == 'MultiSpeed'
2882
- coil.stages.sort.each do |stage|
2883
- stage.setGrossRatedCoolingCOP(cop) if cop
2884
- stage.setTotalCoolingCapacityFunctionofTemperatureCurve(cool_cap_ft) if cool_cap_ft
2885
- stage.setTotalCoolingCapacityFunctionofFlowFractionCurve(cool_cap_fflow) if cool_cap_fflow
2886
- stage.setEnergyInputRatioFunctionofTemperatureCurve(cool_eir_ft) if cool_eir_ft
2887
- stage.setEnergyInputRatioFunctionofFlowFractionCurve(cool_eir_fflow) if cool_eir_fflow
2888
- stage.setPartLoadFractionCorrelationCurve(cool_plf_fplr) if cool_plf_fplr
3371
+ # Set COP if sizing run is done
3372
+ if sizing_done
3373
+ cop = nil
3374
+ if unitary_cop['minimum_energy_efficiency_ratio']
3375
+ cop = eer_to_cop(unitary_cop['minimum_energy_efficiency_ratio'].to_f)
3376
+ elsif unitary_cop['minimum_seasonal_energy_efficiency_ratio']
3377
+ cop = seer_to_cop_cooling_with_fan(unitary_cop['minimum_seasonal_energy_efficiency_ratio'].to_f)
3378
+ elsif unitary_cop['minimum_coefficient_of_performance_cooling']
3379
+ cop = unitary_cop['minimum_coefficient_of_performance_cooling'].to_f
3380
+ end
3381
+ if coil_type == 'SingleSpeed'
3382
+ coil.setRatedCOP(cop) if cop
3383
+ elsif coil_type == 'MultiSpeed'
3384
+ coil.stages.sort.each do |stage|
3385
+ stage.setGrossRatedCoolingCOP(cop) if cop
3386
+ end
3387
+ end
3388
+ coil.setName('CoilCoolingDXSingleSpeed_dx-adv') if coil_type == 'SingleSpeed'
3389
+ coil.setName('CoilCoolingDXMultiSpeed_dx-adv') if coil_type == 'MultiSpeed'
3390
+ else
3391
+ # Set performance curves before sizing run
3392
+ cool_cap_ft = nil
3393
+ cool_cap_ft = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_cap_ft'] }[0] if unitary_cop['cool_cap_ft']
3394
+ cool_cap_ft = model_add_curve(model, unitary_cop['cool_cap_ft']) if cool_cap_ft
3395
+ cool_cap_fflow = nil
3396
+ cool_cap_fflow = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_cap_fflow'] }[0] if unitary_cop['cool_cap_fflow']
3397
+ cool_cap_fflow = model_add_curve(model, unitary_cop['cool_cap_fflow']) if cool_cap_fflow
3398
+ cool_eir_ft = nil
3399
+ cool_eir_ft = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_eir_ft'] }[0] if unitary_cop['cool_eir_ft']
3400
+ cool_eir_ft = model_add_curve(model, unitary_cop['cool_eir_ft']) if cool_eir_ft
3401
+ cool_eir_fflow = nil
3402
+ cool_eir_fflow = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_eir_fflow'] }[0] if unitary_cop['cool_eir_fflow']
3403
+ cool_eir_fflow = model_add_curve(model, unitary_cop['cool_eir_fflow']) if cool_eir_fflow
3404
+ cool_plf_fplr = nil
3405
+ cool_plf_fplr = @standards_data['curves'].select { |curve| curve['name'] == unitary_cop['cool_plf_fplr'] }[0] if unitary_cop['cool_plf_fplr']
3406
+ cool_plf_fplr = model_add_curve(model, unitary_cop['cool_plf_fplr']) if cool_plf_fplr
3407
+ rated_flow_rate = nil
3408
+ rated_flow_rate = unitary_cop['ref_flow_rate_m3_per_sec'] * (capacity_w / unitary_cop['maximum_capacity']) if unitary_cop['ref_flow_rate_m3_per_sec']
3409
+ if coil_type == 'SingleSpeed'
3410
+ coil.setTotalCoolingCapacityFunctionOfTemperatureCurve(cool_cap_ft) if cool_cap_ft
3411
+ coil.setTotalCoolingCapacityFunctionOfFlowFractionCurve(cool_cap_fflow) if cool_cap_fflow
3412
+ coil.setEnergyInputRatioFunctionOfTemperatureCurve(cool_eir_ft) if cool_eir_ft
3413
+ coil.setEnergyInputRatioFunctionOfFlowFractionCurve(cool_eir_fflow) if cool_eir_fflow
3414
+ coil.setPartLoadFractionCorrelationCurve(cool_plf_fplr) if cool_plf_fplr
3415
+ coil.setRatedAirFlowRate(rated_flow_rate) if rated_flow_rate
3416
+ elsif coil_type == 'MultiSpeed'
3417
+ coil.stages.sort.each do |stage|
3418
+ stage.setTotalCoolingCapacityFunctionofTemperatureCurve(cool_cap_ft) if cool_cap_ft
3419
+ stage.setTotalCoolingCapacityFunctionofFlowFractionCurve(cool_cap_fflow) if cool_cap_fflow
3420
+ stage.setEnergyInputRatioFunctionofTemperatureCurve(cool_eir_ft) if cool_eir_ft
3421
+ stage.setEnergyInputRatioFunctionofFlowFractionCurve(cool_eir_fflow) if cool_eir_fflow
3422
+ stage.setPartLoadFractionCorrelationCurve(cool_plf_fplr) if cool_plf_fplr
3423
+ end
2889
3424
  end
2890
3425
  end
2891
- coil.setName('CoilCoolingDXSingleSpeed_dx-adv') if cop && coil_type == 'SingleSpeed'
2892
- coil.setName('CoilCoolingDXMultiSpeed_dx-adv') if cop && coil_type == 'MultiSpeed'
2893
3426
  end
2894
3427
  end
2895
3428
  end
@@ -2965,6 +3498,7 @@ class ECMS
2965
3498
  model.getCoolingTowerSingleSpeeds.sort.each(&:autosizeFanPoweratDesignAirFlowRate)
2966
3499
  end
2967
3500
 
3501
+ # ========================================================================================================================
2968
3502
  def find_chiller_set(chiller_type:, ref_capacity_w:)
2969
3503
  if chiller_type.is_a?(String)
2970
3504
  ##### Find the chiller that has the required capacity
@@ -3083,4 +3617,19 @@ class ECMS
3083
3617
  end
3084
3618
  end
3085
3619
  end
3620
+ # ============================================================================================================================
3621
+ # Add one hot-water loop for hot-water baseboards if primary heating fuel is gas
3622
+ def add_hotwater_loop(model:)
3623
+ plant_loop_names = []
3624
+ model.getPlantLoops.sort.each do |plant_loop|
3625
+ plant_loop_names << plant_loop.name.to_s
3626
+ end
3627
+ unless plant_loop_names.include? 'Hot Water Loop'
3628
+ hw_loop = OpenStudio::Model::PlantLoop.new(model)
3629
+ setup_hw_loop_with_components(model, hw_loop, 'NaturalGas', model.alwaysOnDiscreteSchedule)
3630
+ end
3631
+ return hw_loop
3632
+ end
3633
+ # ============================================================================================================================
3634
+
3086
3635
  end